add standard library / initial environment
This commit is contained in:
parent
ffbe99061f
commit
88fff1c119
|
@ -5,7 +5,7 @@ let () =
|
|||
Logs.set_level (Some Logs.Debug);
|
||||
|
||||
try
|
||||
let ast = parse "obj pos { val x = 3 val y = 4 } val result = pos.x" in
|
||||
let ast = parse "val output = min(4, min(2, 7))" in
|
||||
let prog = compile ast in
|
||||
let ret = run prog in
|
||||
Fmt.pr "{\"program\":%a,\"output\":%a}" Code.pp_program prog Value.pp ret
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Ast = Spice_syntax.Ast
|
||||
module Code = Spice_runtime.Code
|
||||
module Value = Spice_runtime.Value
|
||||
module Interp = Spice_runtime.Interp
|
||||
module Env = Map.Make (String)
|
||||
|
||||
type binding = {
|
||||
|
@ -142,7 +143,11 @@ let compile modl =
|
|||
| Some ret -> ret
|
||||
in
|
||||
|
||||
let env = Env.empty in
|
||||
emit_mov 0 (compile_obj env 0 modl.Ast.items);
|
||||
let stdlib_env =
|
||||
List.to_seq Interp.stdlib
|
||||
|> Seq.mapi (fun i (name, _) -> name, { self = 0; elem = Value.Method i })
|
||||
|> Env.of_seq
|
||||
in
|
||||
emit_mov 0 (compile_obj stdlib_env 1 modl.Ast.items);
|
||||
emit RET;
|
||||
Code.make_program ep
|
||||
|
|
|
@ -75,14 +75,6 @@ type frame = {
|
|||
mutable pc : Code.ins list;
|
||||
}
|
||||
|
||||
let make_frame prog =
|
||||
{
|
||||
regs = Array.make (Code.frame_size prog) Value.Nil;
|
||||
pc = Code.instructions Code.(prog.entrypoint);
|
||||
}
|
||||
|
||||
let return_value fr = fr.regs.(0)
|
||||
|
||||
let eval fr = function
|
||||
| Code.Cst_nil -> Value.Nil
|
||||
| Code.Cst_true -> Value.True
|
||||
|
@ -116,15 +108,63 @@ and call mthd self args =
|
|||
match mthd with
|
||||
| Code.Method pr ->
|
||||
if args <> [] then failwith "Interp.call: TODO: method arguments";
|
||||
run_program pr
|
||||
run pr self
|
||||
| _ -> Value.call mthd self args
|
||||
|
||||
and run fr =
|
||||
match fr.pc with
|
||||
| [] -> return_value fr
|
||||
| is :: rest ->
|
||||
fr.pc <- rest;
|
||||
exec fr is;
|
||||
run fr
|
||||
and run prog self =
|
||||
let frame_size = 1 in
|
||||
let frame_size = max frame_size (Code.frame_size prog) in
|
||||
let fr =
|
||||
let regs = Array.make frame_size Value.Nil in
|
||||
let pc = Code.instructions prog.entrypoint in
|
||||
{ regs; pc }
|
||||
in
|
||||
let rec run_loop () =
|
||||
match fr.pc with
|
||||
| [] -> ()
|
||||
| ins :: rest ->
|
||||
fr.pc <- rest;
|
||||
exec fr ins;
|
||||
run_loop ()
|
||||
in
|
||||
fr.regs.(0) <- self;
|
||||
run_loop ();
|
||||
fr.regs.(0)
|
||||
|
||||
and run_program pr = run (make_frame pr)
|
||||
let stdlib =
|
||||
let println vs =
|
||||
let pp ppf vs =
|
||||
List.iteri
|
||||
(fun i v ->
|
||||
if i > 0 then Fmt.pf ppf " ";
|
||||
Value.pp ppf v)
|
||||
vs
|
||||
in
|
||||
Fmt.pr "%a\n" pp vs;
|
||||
Value.Nil
|
||||
in
|
||||
let min = function
|
||||
| [] -> runtime_error "zero arguments to min()"
|
||||
| [ v ] -> v
|
||||
| v :: vs ->
|
||||
List.fold_left
|
||||
(fun v1 v2 ->
|
||||
match Op.lst v1 v2 with
|
||||
| Value.True -> v1
|
||||
| _ -> v2)
|
||||
v
|
||||
vs
|
||||
in
|
||||
let max = function
|
||||
| [] -> runtime_error "zero arguments to max()"
|
||||
| [ v ] -> v
|
||||
| v :: vs ->
|
||||
List.fold_left
|
||||
(fun v1 v2 ->
|
||||
match Op.grt v1 v2 with
|
||||
| Value.True -> v1
|
||||
| _ -> v2)
|
||||
v
|
||||
vs
|
||||
in
|
||||
[ "println", println; "min", min; "max", max ]
|
||||
|
|
|
@ -63,9 +63,17 @@ and pp_obj ppf vtable slots =
|
|||
vtable.elems;
|
||||
Fmt.pf ppf "}"
|
||||
|
||||
type mthd += Native_function of (t -> t list -> t)
|
||||
type mthd += Native_function of (t list -> t)
|
||||
|
||||
let call mthd self args =
|
||||
let call mthd _self args =
|
||||
match mthd with
|
||||
| Native_function f -> f self args
|
||||
| Native_function f -> f args
|
||||
| _ -> raise Not_found
|
||||
|
||||
let native_lib fns =
|
||||
let elems = Hashtbl.create (List.length fns * 4) in
|
||||
List.iteri (fun i (name, _) -> Hashtbl.add elems name (Method i)) fns;
|
||||
let mthds = List.map (fun (_, f) -> Native_function f) fns in
|
||||
let mthds = Array.of_list mthds in
|
||||
let vtable = { n_slots = 0; elems; mthds } in
|
||||
Obj (vtable, [||])
|
||||
|
|
|
@ -15,5 +15,8 @@ let parse input =
|
|||
let compile ast = Spice_compile.Bcc.compile ast
|
||||
|
||||
let run prog =
|
||||
try Spice_runtime.Interp.run_program prog
|
||||
try
|
||||
let open Spice_runtime in
|
||||
let stdlib = Value.native_lib Interp.stdlib in
|
||||
Interp.run prog stdlib
|
||||
with Spice_runtime.Interp.Runtime_error msg -> failf "runtime error: %s" msg
|
||||
|
|
Loading…
Reference in New Issue