|
include import "./compile.ml"
|
|
open import "prelude.ml"
|
|
open import "lua/io.ml"
|
|
|
|
let resolve_addr = function
|
|
| Combinator n -> n ^ "_combinator"
|
|
| Arg i -> "stack[sp - " ^ show (i + 1) ^ "][3]"
|
|
|
|
let gm2lua = function
|
|
| Push addr -> " stack[sp + 1] = " ^ resolve_addr addr ^ "; sp = sp + 1"
|
|
| Pop n -> " sp = sp - " ^ show n
|
|
| Update n -> " stack[sp - " ^ show (n + 1) ^ "] = { I, stack[sp] }; sp = sp - 1"
|
|
| Mkap -> " stack[sp - 1] = { A, stack[sp - 1], stack[sp] }; sp = sp - 1"
|
|
| Unwind -> " return unwind()"
|
|
|
|
let compute_local_set xs =
|
|
let rec go i (s : S.t string) = function
|
|
| Cons ((name, _, _), xs) ->
|
|
if i >= 100 then
|
|
s
|
|
else
|
|
go (i + 2) (S.insert name (S.insert (name ^ "_combinator") s)) xs
|
|
| Nil -> s
|
|
go 1 S.empty xs
|
|
|
|
let sc2lua (name, arity, body) =
|
|
let body =
|
|
body
|
|
|> foldl (fun x s -> x ^ gm2lua s ^ ";\n") (name ^ " = function()\n")
|
|
|> (^ "end")
|
|
let dec =
|
|
name ^ "_combinator = { F, " ^ name ^ ", " ^ show arity ^ ", " ^ show name ^ " };"
|
|
body ^ "\n" ^ dec
|
|
|
|
let preamble =
|
|
let f = open_for_reading "preamble.lua"
|
|
let x = read_all f
|
|
close_file f
|
|
match x with
|
|
| Some s -> s
|
|
| None -> error "no preamble.lua"
|
|
|
|
let assm_program decs =
|
|
match decs with
|
|
| [] -> error "empty program"
|
|
| _ ->
|
|
let Cons (local1, locals) =
|
|
compute_local_set decs |> S.members
|
|
let local_decs =
|
|
foldl (fun x v -> x ^ ", " ^ v) ("local " ^ local1) locals
|
|
let body = foldl (fun x s -> x ^ sc2lua s ^ "\n") "" decs
|
|
preamble ^ local_decs ^ "\n" ^ body ^ "stack[sp] = { A, main_combinator, 0 }; unwind()"
|