@@ -188,6 +188,13 @@ function assert_return(action, ...expected) {
188
188
| }
189
189
190
190
191
+ (* Errors & Tracing *)
192
+
193
+ module Error = Error. Make ()
194
+
195
+ exception Error = Error. Error
196
+
197
+
191
198
(* Context *)
192
199
193
200
module NameMap = Map. Make (struct type t = Ast. name let compare = compare end )
@@ -217,12 +224,26 @@ let bind (mods : modules) x_opt m =
217
224
let lookup (mods : modules ) x_opt name at =
218
225
let exports =
219
226
try Map. find (of_var_opt mods x_opt) mods.env with Not_found ->
220
- raise ( Eval. Crash (at,
221
- if x_opt = None then " no module defined within script"
222
- else " unknown module " ^ of_var_opt mods x_opt ^ " within script" ) )
227
+ Error. error at
228
+ ( if x_opt = None then " no module defined within script"
229
+ else " unknown module " ^ of_var_opt mods x_opt ^ " within script" )
223
230
in try NameMap. find name exports with Not_found ->
224
- raise (Eval. Crash (at, " unknown export \" " ^
225
- string_of_name name ^ " \" within module" ))
231
+ Error. error at (" unknown export \" " ^
232
+ string_of_name name ^ " \" within module" )
233
+
234
+ let lookup_func (mods : modules ) x_opt name at =
235
+ match lookup mods x_opt name at with
236
+ | ExternFuncType ft -> ft
237
+ | _ ->
238
+ Error. error at (" export \" " ^
239
+ string_of_name name ^ " \" is not a function" )
240
+
241
+ let lookup_global (mods : modules ) x_opt name at =
242
+ match lookup mods x_opt name at with
243
+ | ExternGlobalType gt -> gt
244
+ | _ ->
245
+ Error. error at (" export \" " ^
246
+ string_of_name name ^ " \" is not a global" )
226
247
227
248
228
249
(* Wrappers *)
@@ -259,21 +280,34 @@ let abs_mask_of = function
259
280
| I32Type | F32Type -> Values. I32 Int32. max_int
260
281
| I64Type | F64Type -> Values. I64 Int64. max_int
261
282
262
- let value v =
263
- match v.it with
264
- | Values. Num n -> [Const (n @@ v.at) @@ v.at]
265
- | Values. Vec s -> [VecConst (s @@ v.at) @@ v.at]
266
- | Values. Ref (Values. NullRef t ) -> [RefNull t @@ v.at]
283
+ (*
284
+ let literal lit =
285
+ match lit.it with
286
+ | Values.Num n -> [Const (n @@ lit.at) @@ lit.at]
287
+ | Values.Vec s -> [VecConst (s @@ lit.at) @@ lit.at]
288
+ | Values.Ref (Values.NullRef t) -> [RefNull t @@ lit.at]
267
289
| Values.Ref (ExternRef n) ->
268
- [Const (Values. I32 n @@ v.at) @@ v.at; Call (externref_idx @@ v.at) @@ v.at]
290
+ [ Const (Values.I32 n @@ lit.at) @@ lit.at;
291
+ Call (externref_idx @@ lit.at) @@ lit.at;
292
+ ]
269
293
| Values.Ref _ -> assert false
270
-
271
- let invoke ft vs at =
272
- [ft @@ at], FuncImport (subject_type_idx @@ at) @@ at,
273
- List. concat (List. map value vs) @ [Call (subject_idx @@ at) @@ at]
294
+ *)
274
295
275
296
let get t at =
276
- [] , GlobalImport t @@ at, [GlobalGet (subject_idx @@ at) @@ at]
297
+ [] , GlobalImport t @@ at, [] , [GlobalGet (subject_idx @@ at) @@ at]
298
+
299
+ let invoke ft at =
300
+ let FuncType (ts, _) = ft in
301
+ [ft @@ at], FuncImport (subject_type_idx @@ at) @@ at,
302
+ List. mapi (fun i t ->
303
+ { module_name = Utf8. decode " arg" ;
304
+ item_name = Utf8. decode (string_of_int i);
305
+ idesc = GlobalImport (GlobalType (t, Immutable )) @@ at;
306
+ } @@ at
307
+ ) ts,
308
+ List. concat
309
+ (Lib.List32. mapi (fun i _ -> [GlobalGet (i @@ at) @@ at]) ts) @
310
+ [Call (subject_idx @@ at) @@ at]
277
311
278
312
let run ts at =
279
313
[] , []
@@ -378,7 +412,7 @@ let assert_return ress ts at =
378
412
in [] , List. flatten (List. rev_map test ress)
379
413
380
414
let wrap item_name wrap_action wrap_assertion at =
381
- let itypes, idesc, action = wrap_action at in
415
+ let itypes, idesc, iargs, action = wrap_action at in
382
416
let locals, assertion = wrap_assertion at in
383
417
let types =
384
418
(FuncType ([] , [] ) @@ at) ::
@@ -400,7 +434,8 @@ let wrap item_name wrap_action wrap_assertion at =
400
434
{module_name = Utf8. decode " spectest" ; item_name = Utf8. decode " eq_externref" ;
401
435
idesc = FuncImport (4l @@ at) @@ at} @@ at;
402
436
{module_name = Utf8. decode " spectest" ; item_name = Utf8. decode " eq_funcref" ;
403
- idesc = FuncImport (5l @@ at) @@ at} @@ at ]
437
+ idesc = FuncImport (5l @@ at) @@ at} @@ at;
438
+ ] @ iargs
404
439
in
405
440
let item =
406
441
List. fold_left
@@ -429,10 +464,10 @@ let is_js_value_type = function
429
464
| RefType t -> true
430
465
431
466
let is_js_global_type = function
432
- | GlobalType (t , mut ) -> is_js_value_type t && mut = Immutable
467
+ | GlobalType (t , mut ) -> is_js_value_type t
433
468
434
469
let is_js_func_type = function
435
- | FuncType (ins , out ) -> List. for_all is_js_value_type (ins @ out )
470
+ | FuncType (ts1 , ts2 ) -> List. for_all is_js_value_type (ts1 @ ts2 )
436
471
437
472
438
473
(* Script conversion *)
@@ -473,14 +508,19 @@ let of_num n =
473
508
let open Values in
474
509
match n with
475
510
| I32 i -> I32. to_string_s i
476
- | I64 i -> " int64( \" " ^ I64. to_string_s i ^ " \" ) "
511
+ | I64 i -> I64. to_string_s i ^ " n "
477
512
| F32 z -> of_float (F32. to_float z)
478
513
| F64 z -> of_float (F64. to_float z)
479
514
480
515
let of_vec v =
481
- let open Values in
482
- match v with
483
- | V128 v -> " v128(\" " ^ V128. to_string v ^ " \" )"
516
+ let at = Source. no_region in
517
+ let gtype = GlobalType (VecType (Values. type_of_vec v), Immutable ) in
518
+ let ginit = [VecConst (v @@ at) @@ at] @@ at in
519
+ let globals = [{gtype; ginit} @@ at] in
520
+ let edesc = GlobalExport (0l @@ at) @@ at in
521
+ let exports = [{name = Utf8. decode " v128" ; edesc} @@ at] in
522
+ let bs = Encode. encode ({empty_module with globals; exports} @@ at) in
523
+ " instance(" ^ of_bytes bs ^ " ).exports.v128"
484
524
485
525
let of_ref r =
486
526
let open Values in
@@ -489,9 +529,9 @@ let of_ref r =
489
529
| ExternRef n -> " externref(" ^ Int32. to_string n ^ " )"
490
530
| _ -> assert false
491
531
492
- let of_value v =
532
+ let of_literal lit =
493
533
let open Values in
494
- match v .it with
534
+ match lit .it with
495
535
| Num n -> of_num n
496
536
| Vec v -> of_vec v
497
537
| Ref r -> of_ref r
@@ -529,43 +569,52 @@ let rec of_definition def =
529
569
try of_definition (Parse. string_to_module s) with Parse. Syntax _ ->
530
570
of_bytes " <malformed quote>"
531
571
532
- let of_wrapper mods x_opt name wrap_action wrap_assertion at =
572
+ let of_arg_import i opd =
573
+ " arg" ^ string_of_int i ^ " : " ^ opd
574
+
575
+ let of_wrapper mods x_opt name wrap_action opds wrap_assertion at =
533
576
let x = of_var_opt mods x_opt in
534
577
let bs = wrap name wrap_action wrap_assertion at in
535
- " call(instance(" ^ of_bytes bs ^ " , " ^
536
- " exports(" ^ x ^ " )), " ^ " \" run\" , [])"
578
+ let exs = if opds = [] then " exports(" ^ x ^ " )" else
579
+ " {...exports(" ^ x ^ " ), " ^
580
+ " args: [" ^ String. concat " , " (List. mapi of_arg_import opds) ^ " ]}"
581
+ in " call(instance(" ^ of_bytes bs ^ " , " ^ exs ^ " ), \" run\" , [])"
537
582
538
- let of_action mods act =
583
+ let rec of_action mods act =
539
584
match act.it with
540
- | Invoke (x_opt , name , vs ) ->
585
+ | Invoke (x_opt , name , args ) ->
541
586
" call(" ^ of_var_opt mods x_opt ^ " , " ^ of_name name ^ " , " ^
542
- " [" ^ String. concat " , " (List. map of_value vs) ^ " ])" ,
543
- (match lookup mods x_opt name act.at with
544
- | ExternFuncType ft when not (is_js_func_type ft) ->
545
- let FuncType (_, out) = ft in
546
- Some (of_wrapper mods x_opt name (invoke ft vs), out)
547
- | _ -> None
548
- )
587
+ " [" ^ String. concat " , " (List. map (of_arg mods) args) ^ " ].flat())" ,
588
+ let FuncType (_, ts2) as ft = lookup_func mods x_opt name act.at in
589
+ if is_js_func_type ft then None else
590
+ let opds = List. map (of_arg mods) args in
591
+ Some (of_wrapper mods x_opt name (invoke ft) opds, ts2)
549
592
| Get (x_opt , name ) ->
550
593
" get(" ^ of_var_opt mods x_opt ^ " , " ^ of_name name ^ " )" ,
551
- (match lookup mods x_opt name act.at with
552
- | ExternGlobalType gt when not (is_js_global_type gt) ->
553
- let GlobalType (t, _) = gt in
554
- Some (of_wrapper mods x_opt name (get gt), [t])
555
- | _ -> None
556
- )
594
+ let GlobalType (t, _) as gt = lookup_global mods x_opt name act.at in
595
+ if is_js_global_type gt then None else
596
+ Some (of_wrapper mods x_opt name (get gt) [] , [t])
597
+
598
+ and of_arg mods arg =
599
+ match arg.it with
600
+ | LiteralArg lit -> of_literal lit
601
+ | ActionArg act ->
602
+ let act_js, act_wrapper_opt = of_action mods act in
603
+ match act_wrapper_opt with
604
+ | None -> act_js
605
+ | Some (act_wrapper , ts ) -> act_wrapper (run ts) act.at
557
606
558
607
let of_assertion' mods act name args wrapper_opt =
559
608
let act_js, act_wrapper_opt = of_action mods act in
560
609
let js = name ^ " (() => " ^ act_js ^ String. concat " , " (" " :: args) ^ " )" in
561
610
match act_wrapper_opt with
562
611
| None -> js ^ " ;"
563
- | Some (act_wrapper , out ) ->
612
+ | Some (act_wrapper , ts ) ->
564
613
let run_name, wrapper =
565
614
match wrapper_opt with
566
615
| None -> name, run
567
616
| Some wrapper -> " run" , wrapper
568
- in run_name ^ " (() => " ^ act_wrapper (wrapper out ) act.at ^ " ); // " ^ js
617
+ in run_name ^ " (() => " ^ act_wrapper (wrapper ts ) act.at ^ " ); // " ^ js
569
618
570
619
let of_assertion mods ass =
571
620
match ass.it with
0 commit comments