2021-03-01 20:40:35 +00:00
|
|
|
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 *)
|
2021-03-13 05:49:34 +00:00
|
|
|
type stream = { getS: string -> stream; emitS: unit -> string }
|
2021-03-01 20:40:35 +00:00
|
|
|
let rec stdio = {
|
2021-03-13 05:49:34 +00:00
|
|
|
getS = (fun s -> print_string s; stdio);
|
|
|
|
emitS = (fun () -> (read_line ()) ^ "\n");
|
2021-03-01 20:40:35 +00:00
|
|
|
};;
|
|
|
|
(* End of preamble *)
|
|
|
|
|
|
|
|
[x]]
|
|
|
|
|
|
|
|
ml: (_, Stream()) -> $[stdio]
|
|
|
|
ml: (_, Int(x)) -> x
|
|
|
|
ml: (_, LitString(x)) -> $[{|[<un-single-quote>x]|}]
|
|
|
|
ml: (_, EscString(x)) -> x
|
2021-03-13 05:49:34 +00:00
|
|
|
ml: (_, Sum(x, y)) -> $[[x] + [y]]
|
|
|
|
ml: (_, Concat(x, y)) -> $[[x] ^ [y]]
|
|
|
|
|
2021-03-01 20:40:35 +00:00
|
|
|
ml: (Gets(_,yn), Gets(x, y))
|
|
|
|
-> $[([x]).getS ([<ml_str>(yn,y)])]
|
|
|
|
ml: (To(xn,_), To(x, y))
|
|
|
|
-> $[let _fto = ([x]) in (ignore (([y]).getS ([<ml_str>(xn,"_fto")])); _fto)]
|
2021-03-13 05:49:34 +00:00
|
|
|
ml: (_, Emits(s)) -> $[[s].emitS ()]
|
|
|
|
|
2021-03-01 20:40:35 +00:00
|
|
|
ml: (_, Terminate(x)) -> x
|
|
|
|
ml: (_, Sequence(l)) -> <ml_seq>l
|
|
|
|
|
|
|
|
ml_seq: [x] -> x
|
|
|
|
ml_seq: [x | xs ] -> $[ignore ([x]);
|
|
|
|
[<ml_seq>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 <is-string>x
|
|
|
|
|
|
|
|
ml_str: (node, code) -> $[[<ml_string_cast>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 := <guarantee-extension(|"ml")> path
|
|
|
|
; result := <ocaml> selected
|