Skip to content
This repository was archived by the owner on Aug 31, 2023. It is now read-only.

Commit 4753632

Browse files
authored
[interpreter] Implement func.bind (#17)
Plus some minor fixes and more tests.
1 parent 9b80f54 commit 4753632

File tree

21 files changed

+845
-56
lines changed

21 files changed

+845
-56
lines changed

interpreter/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ instr:
216216
op:
217217
unreachable
218218
nop
219+
drop
220+
select
219221
br <var>
220222
br_if <var>
221223
br_table <var>+
@@ -225,8 +227,7 @@ op:
225227
call_indirect <var>? <func_type>
226228
call_ref
227229
return_call_ref
228-
drop
229-
select
230+
func.bind <func_type>
230231
local.get <var>
231232
local.set <var>
232233
local.tee <var>

interpreter/binary/decode.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,15 +279,16 @@ let rec instr s =
279279

280280
| 0x14 -> call_ref
281281
| 0x15 -> return_call_ref
282+
| 0x16 -> func_bind (at var s)
282283

283-
| 0x16 ->
284+
| 0x17 ->
284285
let bt = stack_type s in
285286
let locs = locals s in
286287
let es = instr_block s in
287288
end_ s;
288289
let_ bt locs es
289290

290-
| 0x17 | 0x18 | 0x19 as b -> illegal s pos b
291+
| 0x18 | 0x19 as b -> illegal s pos b
291292

292293
| 0x1a -> drop
293294
| 0x1b -> select None

interpreter/binary/encode.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ let encode m =
172172
if es2 <> [] then op 0x05;
173173
list instr es2; end_ ()
174174
| Let (bt, locs, es) ->
175-
op 0x16; stack_type bt; locals locs; list instr es; end_ ()
175+
op 0x17; stack_type bt; locals locs; list instr es; end_ ()
176176

177177
| Br x -> op 0x0c; var x
178178
| BrIf x -> op 0x0d; var x
@@ -183,6 +183,7 @@ let encode m =
183183
| CallRef -> op 0x14
184184
| CallIndirect (x, y) -> op 0x11; var y; var x
185185
| ReturnCallRef -> op 0x15
186+
| FuncBind x -> op 0x16; var x
186187

187188
| Drop -> op 0x1a
188189
| Select None -> op 0x1b

interpreter/exec/eval.ml

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,29 @@ let rec step (c : config) : config =
218218
else
219219
vs, [Trapping "indirect call type mismatch" @@ e.at]
220220

221+
| ReturnCallRef, Ref NullRef :: vs ->
222+
vs, [Trapping "null function reference" @@ e.at]
223+
221224
| ReturnCallRef, vs ->
222225
(match (step {c with code = (vs, [Plain CallRef @@ e.at])}).code with
223226
| vs', [{it = Invoke a; at}] -> vs', [ReturningInvoke (vs', a) @@ at]
224227
| vs', [{it = Trapping s; at}] -> vs', [Trapping s @@ at]
225228
| _ -> assert false
226229
)
227230

231+
| FuncBind x, Ref NullRef :: vs ->
232+
vs, [Trapping "null function reference" @@ e.at]
233+
234+
| FuncBind x, Ref (FuncRef f) :: vs ->
235+
let FuncType (ins, out) = Func.type_of f in
236+
let FuncType (ins', out') = func_type frame.inst x in
237+
let args, vs' =
238+
try split (List.length ins - List.length ins') vs e.at
239+
with Failure _ -> Crash.error e.at "type mismatch at function bind"
240+
in
241+
let f' = Func.alloc_closure f args in
242+
Ref (FuncRef f') :: vs', []
243+
228244
| Drop, v :: vs' ->
229245
vs', []
230246

@@ -553,23 +569,27 @@ let rec step (c : config) : config =
553569
let c' = step {frame = frame'; code = code'; budget = c.budget - 1} in
554570
vs, [Frame (n, inst, c'.code) @@ e.at]
555571

556-
| Invoke func, vs when c.budget = 0 ->
572+
| Invoke f, vs when c.budget = 0 ->
557573
Exhaustion.error e.at "call stack exhausted"
558574

559-
| Invoke func, vs ->
560-
let FuncType (ins, out) = Func.type_of func in
575+
| Invoke f, vs ->
576+
let FuncType (ins, out) = Func.type_of f in
561577
let args, vs' = split (List.length ins) vs e.at in
562-
(match func with
563-
| Func.AstFunc (t, inst', f) ->
564-
let ts = List.map Source.it f.it.locals in
565-
let locals' = List.map (fun t -> t @@ f.at) ins @ f.it.locals in
578+
(match f with
579+
| Func.AstFunc (ft, inst', func) ->
580+
let {locals; body; _} = func.it in
581+
let ts = List.map Source.it locals in
582+
let locals' = List.map (fun t -> t @@ func.at) ins @ locals in
566583
let vs0 = List.rev args @ List.map default_value ts in
567-
let es0 = [Plain (Let (out, locals', f.it.body)) @@ f.at] in
584+
let es0 = [Plain (Let (out, locals', body)) @@ func.at] in
568585
vs', [Frame (List.length out, !inst', (List.rev vs0, es0)) @@ e.at]
569586

570-
| Func.HostFunc (t, f) ->
571-
try List.rev (f (List.rev args)) @ vs', []
572-
with Crash (_, msg) -> Crash.error e.at msg
587+
| Func.HostFunc (_ft, f) ->
588+
(try List.rev (f (List.rev args)) @ vs', []
589+
with Crash (_, msg) -> Crash.error e.at msg)
590+
591+
| Func.ClosureFunc (f', args') ->
592+
args @ args' @ vs', [Invoke f' @@ e.at]
573593
)
574594
in {c with code = vs', es' @ List.tl es}
575595

@@ -588,8 +608,13 @@ let rec eval (c : config) : value stack =
588608

589609
(* Functions & Constants *)
590610

611+
let rec at_func = function
612+
| Func.AstFunc (_, _, f) -> f.at
613+
| Func.HostFunc _ -> no_region
614+
| Func.ClosureFunc (func, _) -> at_func func
615+
591616
let invoke (func : func_inst) (vs : value list) : value list =
592-
let at = match func with Func.AstFunc (_, _, f) -> f.at | _ -> no_region in
617+
let at = at_func func in
593618
let FuncType (ins, out) = Func.type_of func in
594619
if List.length vs <> List.length ins then
595620
Crash.error at "wrong number of arguments";

interpreter/runtime/func.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ type 'inst t = 'inst func
55
and 'inst func =
66
| AstFunc of func_type * 'inst * Ast.func
77
| HostFunc of func_type * (value list -> value list)
8+
| ClosureFunc of 'inst func * value list
89

910
let alloc ft inst f = AstFunc (ft, inst, f)
1011
let alloc_host ft f = HostFunc (ft, f)
12+
let alloc_closure func vs = ClosureFunc (func, vs)
1113

12-
let type_of = function
14+
let rec type_of = function
1315
| AstFunc (ft, _, _) -> ft
1416
| HostFunc (ft, _) -> ft
17+
| ClosureFunc (f, vs) ->
18+
let FuncType (ins, out) = type_of f in
19+
FuncType (Lib.List.drop (List.length vs) ins, out)

interpreter/runtime/func.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ type 'inst t = 'inst func
55
and 'inst func =
66
| AstFunc of func_type * 'inst * Ast.func
77
| HostFunc of func_type * (value list -> value list)
8+
| ClosureFunc of 'inst func * value list
89

910
val alloc : func_type -> 'inst -> Ast.func -> 'inst func
1011
val alloc_host : func_type -> (value list -> value list) -> 'inst func
12+
val alloc_closure : 'inst func -> value list -> 'inst func
1113
val type_of : 'inst func -> func_type

interpreter/runtime/instance.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ let () =
3939
let x =
4040
match func with
4141
| Func.AstFunc (_, _, f) -> f.Source.it.Ast.ftype.Source.it
42-
| Func.HostFunc _ -> 0l (* HACK! *)
42+
| _ -> 0l (* HACK! *)
4343
in
4444
DefRefType (NonNullable, x)
4545
| r -> type_of_ref' r

interpreter/syntax/ast.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ and instr' =
8888
| CallRef (* call function through reference *)
8989
| CallIndirect of idx * idx (* call function through table *)
9090
| ReturnCallRef (* tail call through reference *)
91+
| FuncBind of idx (* closure creation *)
9192
| LocalGet of idx (* read local idxiable *)
9293
| LocalSet of idx (* write local idxiable *)
9394
| LocalTee of idx (* write local idxiable and keep value *)

interpreter/syntax/free.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ let rec instr (e : instr) =
101101
| Return | CallRef | ReturnCallRef -> empty
102102
| Call x -> funcs (idx x)
103103
| CallIndirect (x, y) -> tables (idx x) ++ types (idx y)
104+
| FuncBind x -> types (idx x)
104105
| LocalGet x | LocalSet x | LocalTee x -> locals (idx x)
105106
| GlobalGet x | GlobalSet x -> globals (idx x)
106107
| TableGet x | TableSet x | TableSize x | TableGrow x | TableFill x ->

interpreter/syntax/operators.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ let call x = Call x
3434
let call_ref = CallRef
3535
let call_indirect x y = CallIndirect (x, y)
3636
let return_call_ref = ReturnCallRef
37+
let func_bind x = FuncBind x
3738

3839
let local_get x = LocalGet x
3940
let local_set x = LocalSet x

0 commit comments

Comments
 (0)