compile scope expressions

This commit is contained in:
tali 2023-11-30 13:52:05 -05:00
parent c089d893c6
commit fd3b356699
2 changed files with 29 additions and 18 deletions

View File

@ -5,7 +5,7 @@ let () =
Logs.set_level (Some Logs.Debug);
try
let ast = parse "val x = 3 val y = 5 val output = 2 * (if(9 < 8) x else 1 + y)" in
let ast = parse "val z = 5 val output = 1 + (({ val x = 3 val y = 4 x * y }) + z)" in
let prog = compile ast in
let ret = run prog in
Fmt.pr "{\"program\":%a,\"output\":%a}" Code.pp_program prog Value.pp ret

View File

@ -72,8 +72,9 @@ let compile modl =
bb := jp;
Reg tmp
| Ast.Obj body -> compile_obj env body
| Ast.Scope body -> compile_scope env body
| _ -> failwith "Bcc.compile_exp: TODO"
and compile_obj env items =
and compile_block env items =
let self = !sp in
(* construct new env and vtable *)
@ -92,7 +93,7 @@ let compile modl =
in
let vtable = Value.{ elems; n_slots } in
(* emit constructor / field inits *)
(* emit constructor, compile val fields, and get result of final expression *)
emit (CON (self, vtable));
let emit_set name rhs =
let slot = (Env.find name env).slot in
@ -100,23 +101,33 @@ let compile modl =
emit_mov (self + 1) (Code.cst_of_int slot);
emit (SET (self, self + 1))
in
List.iter
(function
| Ast.Item_fun (_, _, _) -> failwith "Bcc: unsupported: methods"
| Ast.Item_exp e ->
sp := self + 1;
ignore (compile_exp env e)
| Ast.Item_obj (name, body) ->
sp := self + 2;
emit_set name (compile_obj env body)
| Ast.Item_val (name, rhs) ->
sp := self + 2;
emit_set name (compile_exp env rhs))
items;
(* reset sp and return self *)
let final_exp =
List.fold_left
(fun _ -> function
| Ast.Item_fun (_, _, _) -> failwith "Bcc: unsupported: methods"
| Ast.Item_exp e ->
sp := self + 1;
Some (compile_exp env e)
| Ast.Item_obj (name, body) ->
sp := self + 2;
emit_set name (compile_obj env body);
None
| Ast.Item_val (name, rhs) ->
sp := self + 2;
emit_set name (compile_exp env rhs);
None)
None
items
in
self, final_exp
and compile_obj env items =
let self, _ = compile_block env items in
sp := self + 1;
Code.Reg self
and compile_scope env items =
match compile_block env items with
| _, None -> failwith "block must end with an expression"
| _, Some ret -> ret
in
let env = Env.empty in