简体   繁体   中英

Generating C code in Ocaml

I'm trying to create a code generating DSL in OCaml, however I can't find many examples on what the code generation looks like. I would just like to see how to create code values in OCaml.

For example if I had a type like this:

let equation =
    Add of int * int
    | Sub of int * int
    | Mul of int * int
    | Div of int * int;;

and I want a function like this:

let write_code = function
    | Add (x, y) -> // INSERT CODE "x + y" here

etc... how would this look?

I have looked at this example http://okmij.org/ftp/meta-programming/tutorial/power.ml but the characters .< >. are causing syntax errors when I try to compile.

The code generated will not need to be compiled or executed, but saved to a .c file for later use.

I would just like to see the basic structure for this simple example so I can apply it to a more complicated problem.

You can do like that :

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

Here you produce a string and after that you can write that string where you want.

I changed your expression type a bit to be more general.

The result string will contain too much parentheses, but it does not matter because the generated code is not targeted to humans but to a compiler.

You could use a buffer :

As it's written in the module :

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 ).

For example, you can write :

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

With

# Buffer.create;;
- : int -> Buffer.t = <fun>
# Buffer.add_string;;
- : Buffer.t -> string -> unit = <fun>
# Buffer.output_buffer;;
- : out_channel -> Buffer.t -> unit = <fun>

Notice that Buffer.add_string write the string at the end of the buffer ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM