forked from glen/fostr
62 lines
1.8 KiB
Plaintext
62 lines
1.8 KiB
Plaintext
|
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 }
|
||
|
let rec stdio = {
|
||
|
getS = (fun s -> print_string s; stdio)
|
||
|
};;
|
||
|
(* End of preamble *)
|
||
|
|
||
|
[x]]
|
||
|
|
||
|
ml: (_, Stream()) -> $[stdio]
|
||
|
ml: (_, Int(x)) -> x
|
||
|
ml: (_, LitString(x)) -> $[{|[<un-single-quote>x]|}]
|
||
|
ml: (_, EscString(x)) -> x
|
||
|
ml: (_, Sum(x,y)) -> $[[x] + [y]]
|
||
|
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)]
|
||
|
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
|