| 1 |
open Ident
|
| 2 |
open Lambda
|
| 3 |
|
| 4 |
type env = {
|
| 5 |
vars: var_loc Env.t;
|
| 6 |
stack_size: int
|
| 7 |
}
|
| 8 |
|
| 9 |
let empty = { vars = Env.empty; stack_size = 0 }
|
| 10 |
|
| 11 |
let find x env =
|
| 12 |
try Env.find x env.vars
|
| 13 |
with Not_found ->
|
| 14 |
failwith ("Compile: cannot find " ^ (Ident.to_string x))
|
| 15 |
|
| 16 |
let rec compile env tail e = compile_aux env tail e.Typed.exp_descr
|
| 17 |
and compile_aux env tail = function
|
| 18 |
| Typed.Forget (e,_) -> compile env tail e
|
| 19 |
| Typed.Var x -> Var (find x env)
|
| 20 |
| Typed.Apply (e1,e2) -> Apply (tail, compile env false e1, compile env tail e2)
|
| 21 |
| Typed.Abstraction a -> compile_abstr env a
|
| 22 |
| Typed.Cst c -> Const c
|
| 23 |
| Typed.Pair (e1,e2) -> Pair(compile env false e1, compile env tail e2)
|
| 24 |
| Typed.Xml (e1, { Typed.exp_descr = Typed.Pair (e2,e3) }) ->
|
| 25 |
Xml (compile env false e1, compile env false e2, compile env tail e3)
|
| 26 |
| Typed.Xml (_,_) -> assert false
|
| 27 |
| Typed.RecordLitt r -> Record (LabelMap.map (compile env false) r)
|
| 28 |
| Typed.String (i,j,s,q) -> String (i,j,s,compile env tail q)
|
| 29 |
| Typed.Match (e,brs) -> Match (compile env false e, compile_branches env tail brs)
|
| 30 |
| Typed.Map (e,brs) -> Map (compile env false e, compile_branches env false brs)
|
| 31 |
| Typed.Transform (e,brs) -> Transform
|
| 32 |
(compile env false e, compile_branches env false brs)
|
| 33 |
| Typed.Xtrans (e,brs) -> Xtrans (compile env false e, compile_branches env false brs)
|
| 34 |
| Typed.Validate (e,sch,t) -> Validate (compile env tail e, sch, t)
|
| 35 |
| Typed.RemoveField (e,l) -> RemoveField (compile env tail e,l)
|
| 36 |
| Typed.Dot (e,l) -> Dot (compile env tail e, l)
|
| 37 |
| Typed.Try (e,brs) -> Try (compile env false e, compile_branches env tail brs)
|
| 38 |
| Typed.UnaryOp (op,e) -> UnaryOp (op, compile env tail e)
|
| 39 |
| Typed.BinaryOp (op,e1,e2) -> BinaryOp (op, compile env false e1, compile env tail e2)
|
| 40 |
| Typed.Ref (e,t) -> Ref (compile env tail e, t)
|
| 41 |
|
| 42 |
and compile_abstr env a =
|
| 43 |
let fun_env =
|
| 44 |
match a.Typed.fun_name with
|
| 45 |
| Some x -> Env.add x (Env 0) Env.empty
|
| 46 |
| None -> Env.empty in
|
| 47 |
|
| 48 |
let (slots,nb_slots,fun_env) =
|
| 49 |
List.fold_left
|
| 50 |
(fun (slots,nb_slots,fun_env) x ->
|
| 51 |
match find x env with
|
| 52 |
| (Stack _ | Env _) as p ->
|
| 53 |
p::slots,
|
| 54 |
succ nb_slots,
|
| 55 |
Env.add x (Env nb_slots) fun_env;
|
| 56 |
| Global _ as p ->
|
| 57 |
slots,
|
| 58 |
nb_slots,
|
| 59 |
Env.add x p fun_env
|
| 60 |
| Dummy -> assert false
|
| 61 |
)
|
| 62 |
([Dummy],1,fun_env) (IdSet.get a.Typed.fun_fv) in
|
| 63 |
|
| 64 |
|
| 65 |
let slots = Array.of_list (List.rev slots) in
|
| 66 |
let env = { vars = fun_env; stack_size = 0 } in
|
| 67 |
let body = compile_branches env true a.Typed.fun_body in
|
| 68 |
Abstraction (slots, a.Typed.fun_iface, body)
|
| 69 |
|
| 70 |
and compile_branches env tail (brs : Typed.branches) =
|
| 71 |
{
|
| 72 |
brs = List.map (compile_branch env tail) brs.Typed.br_branches;
|
| 73 |
brs_tail = tail;
|
| 74 |
brs_accept_chars = not (Types.Char.is_empty brs.Typed.br_accept);
|
| 75 |
brs_input = brs.Typed.br_typ;
|
| 76 |
brs_compiled = None
|
| 77 |
}
|
| 78 |
|
| 79 |
and compile_branch env tail br =
|
| 80 |
let env =
|
| 81 |
List.fold_left
|
| 82 |
(fun env x ->
|
| 83 |
{ vars = Env.add x (Stack env.stack_size) env.vars;
|
| 84 |
stack_size = env.stack_size + 1 }
|
| 85 |
|
| 86 |
) env (Patterns.fv_list br.Typed.br_pat) in
|
| 87 |
(br.Typed.br_pat, compile env tail br.Typed.br_body)
|
| 88 |
|
| 89 |
|
| 90 |
let enter_global env x =
|
| 91 |
{ vars = Env.add x (Global env.stack_size) env.vars;
|
| 92 |
stack_size = env.stack_size + 1 }
|
| 93 |
|
| 94 |
let enter_globals = List.fold_left enter_global
|
| 95 |
|
| 96 |
let compile_eval env e = Eval (compile env false e)
|
| 97 |
|
| 98 |
let compile_let_decl env decl =
|
| 99 |
let pat = decl.Typed.let_pat in
|
| 100 |
let code = Let_decl (pat, compile env false (decl.Typed.let_body)) in
|
| 101 |
let env = enter_globals env (Patterns.fv_list pat) in
|
| 102 |
(env, code)
|
| 103 |
|
| 104 |
|
| 105 |
let compile_rec_funs env funs =
|
| 106 |
let fun_name = function
|
| 107 |
| { Typed.exp_descr=Typed.Abstraction{Typed.fun_name = Some x}} -> x
|
| 108 |
| _ -> assert false in
|
| 109 |
let fun_a = function
|
| 110 |
| { Typed.exp_descr=Typed.Abstraction a } -> a
|
| 111 |
| _ -> assert false in
|
| 112 |
let names = List.map fun_name funs in
|
| 113 |
let env = enter_globals env names in
|
| 114 |
let exprs = List.map (compile_abstr env) (List.map fun_a funs) in
|
| 115 |
(env, Let_funs exprs)
|
| 116 |
|
| 117 |
|
| 118 |
(****************************************)
|
| 119 |
|
| 120 |
open Location
|
| 121 |
|
| 122 |
let eval (tenv,cenv,codes) e =
|
| 123 |
let (e,_) = Typer.type_expr tenv e in
|
| 124 |
let code = compile_eval cenv e in
|
| 125 |
(tenv,cenv,code :: codes)
|
| 126 |
|
| 127 |
let let_decl (tenv,cenv,codes) p e =
|
| 128 |
let (tenv,decl,_) = Typer.type_let_decl tenv p e in
|
| 129 |
let (cenv,code) = compile_let_decl cenv decl in
|
| 130 |
(tenv,cenv,code :: codes)
|
| 131 |
|
| 132 |
let let_funs (tenv,cenv,codes) funs =
|
| 133 |
let (tenv,funs,_) = Typer.type_let_funs tenv funs in
|
| 134 |
let (cenv,code) = compile_rec_funs cenv funs in
|
| 135 |
(tenv,cenv,code :: codes)
|
| 136 |
|
| 137 |
let type_defs (tenv,cenv,codes) typs =
|
| 138 |
let tenv = Typer.enter_types (Typer.type_defs tenv typs) tenv in
|
| 139 |
(tenv,cenv,codes)
|
| 140 |
|
| 141 |
let namespace (tenv,cenv,codes) pr ns =
|
| 142 |
let tenv = Typer.enter_ns pr ns tenv in
|
| 143 |
(tenv,cenv,codes)
|
| 144 |
|
| 145 |
let rec collect_funs accu = function
|
| 146 |
| { descr = Ast.FunDecl e } :: rest -> collect_funs (e::accu) rest
|
| 147 |
| rest -> (accu,rest)
|
| 148 |
|
| 149 |
let rec collect_types accu = function
|
| 150 |
| { descr = Ast.TypeDecl (x,t) } :: rest ->
|
| 151 |
collect_types ((x,t) :: accu) rest
|
| 152 |
| rest -> (accu,rest)
|
| 153 |
|
| 154 |
let rec phrases accu phs = match phs with
|
| 155 |
| { descr = Ast.FunDecl _ } :: _ ->
|
| 156 |
let (funs,rest) = collect_funs [] phs in
|
| 157 |
phrases (let_funs accu funs) rest
|
| 158 |
| { descr = Ast.TypeDecl (_,_) } :: _ ->
|
| 159 |
let (typs,rest) = collect_types [] phs in
|
| 160 |
phrases (type_defs accu typs) rest
|
| 161 |
| { descr = Ast.SchemaDecl (name, schema) } :: rest ->
|
| 162 |
Typer.register_schema name schema;
|
| 163 |
phrases accu rest
|
| 164 |
| { descr = Ast.Namespace (pr,ns) } :: rest ->
|
| 165 |
phrases (namespace accu pr ns) rest
|
| 166 |
| { descr = Ast.EvalStatement e } :: rest ->
|
| 167 |
phrases (eval accu e) rest
|
| 168 |
| { descr = Ast.LetDecl (p,e) } :: rest ->
|
| 169 |
phrases (let_decl accu p e) rest
|
| 170 |
| { descr = Ast.Debug l } :: rest ->
|
| 171 |
phrases accu rest
|
| 172 |
| { descr = Ast.Directive _ } :: rest ->
|
| 173 |
phrases accu rest
|
| 174 |
| [] -> accu
|
| 175 |
|
| 176 |
let comp_unit tenv cenv phs =
|
| 177 |
let (tenv,cenv,codes) = phrases (tenv,cenv,[]) phs in
|
| 178 |
(tenv,cenv,List.rev codes)
|