module ocaml imports libstrategolib signatures/- util signature/TYPE analysis /* Note will use bottomup-para to traverse the full AST so that we have access to the original expression (and can get the Statix-associated type when we need to). This means that every one of our local rules must take a pair of an original term and a term with every child replaced by its generated code. */ rules ml: (_, TopLevel(x)) -> $[(* fostr preamble *) type stream = { getS: string -> stream; emitS: unit -> string } let rec stdio = { getS = (fun s -> print_string s; stdio); emitS = (fun () -> (read_line ()) ^ "\n"); };; (* End of preamble *) [x]] ml: (_, Stream()) -> $[stdio] ml: (_, Int(x)) -> x ml: (_, LitString(x)) -> $[{|[x]|}] ml: (_, EscString(x)) -> x ml: (_, Sum(x, y)) -> $[[x] + [y]] ml: (_, Concat(x, y)) -> $[[x] ^ [y]] ml: (Gets(_,yn), Gets(x, y)) -> $[([x]).getS ([(yn,y)])] ml: (To(xn,_), To(x, y)) -> $[let _fto = ([x]) in (ignore (([y]).getS ([(xn,"_fto")])); _fto)] ml: (_, Emits(s)) -> $[[s].emitS ()] ml: (_, Terminate(x)) -> x ml: (_, Sequence(l)) -> l ml_seq: [x] -> x ml_seq: [x | xs ] -> $[ignore ([x]); [xs]] /* One drawback of using paramorphism is we have to handle lists explicitly: */ ml: (_, []) -> [] ml: (_, [x | xs]) -> [x | xs] /* Another drawback of using paramorphism is at the very leaves we have to undouble the tuple: */ ml: (x, x) -> x where x ml_str: (node, code) -> $[[node]([code])] strategies ml_string_cast = get-type; (?INT() < !"string_of_int" + !"") ocaml = bottomup-para(try(ml)) // Interface ocaml code generation with editor services and file system to-ocaml: (selected, _, _, path, project-path) -> (filename, result) with filename := path ; result := selected