2016-03-10 35 views
0

我试图在OCaml中创建一个生成DSL的代码,但是我找不到代码生成的代码。我只想看看如何在OCaml中创建代码值。在Ocaml中生成C代码

例如,如果我有一类这样的:

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文件供以后使用。

我只想看看这个简单例子的基本结构,所以我可以将它应用于一个更复杂的问题。

+1

如果需要的结束的字符串生成C代码并保存,只需生成字符串,并将它们保存到C文件。 '| Add(x,y) - > Printf.sprintf“(%s +%s)”(write_code x)(write_code y)'。 – antron

+2

'。 <' and '>。用于MetaOCaml。你需要使用它来代替香草OCaml。但我想这不是你真正想要的。 – camlspotter

回答

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

在这里,您生成一个字符串之后,你可以写,你想要的字符串。

我改变了你的表情类型有点更一般。

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

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写在缓冲区;-)