在Ocaml中生成C代码

时间:2016-03-10 22:06:19

标签: ocaml code-generation dsl

我正在尝试在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文件供以后使用。

我只想看看这个简单示例的基本结构,以便将其应用于更复杂的问题。

2 个答案:

答案 0 :(得分:2)

你可以这样做:

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 ^ ")"
;;

在这里,您可以生成一个字符串,之后您可以将该字符串写入所需的位置。

我改变了你的表达类型,使其更加通用。

结果字符串将包含太多括号,但无关紧要,因为生成的代码不是针对人类而是针对编译器。

答案 1 :(得分:0)

您可以使用buffer

正如它在模块中所写:

  

此模块实现了根据需要自动扩展的缓冲区。它在准线性时间内提供字符串的累积串联(而不是字符串成对连接时的二次时间)。

例如,您可以写:

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将字符串写在缓冲区的末尾; - )