diff --git a/bin/main.ml b/bin/main.ml index 2b7b7d8..d772212 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -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 diff --git a/lib/compile/bcc.ml b/lib/compile/bcc.ml index 67c6d72..1d4cff0 100644 --- a/lib/compile/bcc.ml +++ b/lib/compile/bcc.ml @@ -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