在 Ocaml 中生成 C 代码
Generating C code in Ocaml
我正在尝试在 OCaml 中创建一个代码生成 DSL,但是我找不到很多关于代码生成的例子。我只想看看如何在 OCaml 中创建代码值。
例如,如果我有这样的类型:
let equation =
Add of int * int
| Sub of int * int
| Mul of int * int
| Div of int * int;;
我想要这样的函数:
let write_code = function
| Add (x, y) -> // INSERT CODE "x + y" here
等...这看起来如何?
我看过这个例子 http://okmij.org/ftp/meta-programming/tutorial/power.ml 但是字符 .< >。当我尝试编译时导致语法错误。
生成的代码不需要编译或执行,而是保存到.c文件中供以后使用。
我只想了解这个简单示例的基本结构,以便将其应用于更复杂的问题。
你可以这样做:
type equation =
| Const of int
| Var of string
| Add of equation * equation
| Mul of equation * equation ;;
let rec c_string_of_equation = function
| Const i -> string_of_int i
| Var x -> x
| Add (e1, e2) ->
"(" ^ c_string_of_equation e1 ^ ") + (" ^ c_string_of_equation e2 ^ ")"
| Mul (e1, e2) ->
"(" ^ c_string_of_equation e1 ^ ") * (" ^ c_string_of_equation e2 ^ ")"
;;
在这里你生成一个字符串,然后你可以在你想要的地方写那个字符串。
我稍微更改了你的表达式类型,使其更通用。
结果字符串将包含太多括号,但这并不重要,因为生成的代码不是针对人类而是针对编译器。
你可以使用 buffer :
如模块中所写:
This module implements buffers that automatically expand as necessary. It provides accumulative concatenation of strings in quasi-linear time (instead of quadratic time when strings are concatenated pairwise).
例如,你可以这样写:
let equation =
| Add of int * int
| Sub of int * int
| Mul of int * int
| Div of int * int;;
let co = open_out filename
let buff = Buffer.create 11235
let write_code = function
| Add (x, y) -> Buffer.add_string buff (Printf.sprintf "%d + %d" x y)
| ... -> ...
let write c =
write_code c;
Buffer.output_buffer co buff
有
# Buffer.create;;
- : int -> Buffer.t = <fun>
# Buffer.add_string;;
- : Buffer.t -> string -> unit = <fun>
# Buffer.output_buffer;;
- : out_channel -> Buffer.t -> unit = <fun>
注意Buffer.add_string
把字符串写在缓冲区的末尾;-)
我正在尝试在 OCaml 中创建一个代码生成 DSL,但是我找不到很多关于代码生成的例子。我只想看看如何在 OCaml 中创建代码值。
例如,如果我有这样的类型:
let equation =
Add of int * int
| Sub of int * int
| Mul of int * int
| Div of int * int;;
我想要这样的函数:
let write_code = function
| Add (x, y) -> // INSERT CODE "x + y" here
等...这看起来如何?
我看过这个例子 http://okmij.org/ftp/meta-programming/tutorial/power.ml 但是字符 .< >。当我尝试编译时导致语法错误。
生成的代码不需要编译或执行,而是保存到.c文件中供以后使用。
我只想了解这个简单示例的基本结构,以便将其应用于更复杂的问题。
你可以这样做:
type equation =
| Const of int
| Var of string
| Add of equation * equation
| Mul of equation * equation ;;
let rec c_string_of_equation = function
| Const i -> string_of_int i
| Var x -> x
| Add (e1, e2) ->
"(" ^ c_string_of_equation e1 ^ ") + (" ^ c_string_of_equation e2 ^ ")"
| Mul (e1, e2) ->
"(" ^ c_string_of_equation e1 ^ ") * (" ^ c_string_of_equation e2 ^ ")"
;;
在这里你生成一个字符串,然后你可以在你想要的地方写那个字符串。
我稍微更改了你的表达式类型,使其更通用。
结果字符串将包含太多括号,但这并不重要,因为生成的代码不是针对人类而是针对编译器。
你可以使用 buffer :
如模块中所写:
This module implements buffers that automatically expand as necessary. It provides accumulative concatenation of strings in quasi-linear time (instead of quadratic time when strings are concatenated pairwise).
例如,你可以这样写:
let equation =
| Add of int * int
| Sub of int * int
| Mul of int * int
| Div of int * int;;
let co = open_out filename
let buff = Buffer.create 11235
let write_code = function
| Add (x, y) -> Buffer.add_string buff (Printf.sprintf "%d + %d" x y)
| ... -> ...
let write c =
write_code c;
Buffer.output_buffer co buff
有
# Buffer.create;;
- : int -> Buffer.t = <fun>
# Buffer.add_string;;
- : Buffer.t -> string -> unit = <fun>
# Buffer.output_buffer;;
- : out_channel -> Buffer.t -> unit = <fun>
注意Buffer.add_string
把字符串写在缓冲区的末尾;-)