Skip to content

Commit 740abc2

Browse files
authored
[interpreter] Support quoted module definitions in .wast (#475)
Also converts all existing .fail. tests to uses of quotation.
1 parent 6d6648b commit 740abc2

77 files changed

Lines changed: 1070 additions & 680 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎interpreter/Makefile‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
# Configuration
1111

1212
NAME = wasm
13-
UNOPT = $(NAME)
14-
OPT = $(NAME).opt
13+
UNOPT = $(NAME).debug
14+
OPT = $(NAME)
1515
LIB = $(NAME)
1616
ZIP = $(NAME).zip
1717
JSLIB = wast.js

‎interpreter/host/js.ml‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -310,12 +310,13 @@ let of_literal lit =
310310
| Values.F32 z -> of_float (F32.to_float z)
311311
| Values.F64 z -> of_float (F64.to_float z)
312312

313-
let of_definition def =
314-
let bs =
315-
match def.it with
316-
| Textual m -> Encode.encode m
317-
| Encoded (_, bs) -> bs
318-
in of_bytes bs
313+
let rec of_definition def =
314+
match def.it with
315+
| Textual m -> of_bytes (Encode.encode m)
316+
| Encoded (_, bs) -> of_bytes bs
317+
| Quoted (_, s) ->
318+
try of_definition (Parse.string_to_module s) with Parse.Syntax _ ->
319+
of_bytes "<malformed quote>"
319320

320321
let of_wrapper mods x_opt name wrap_action wrap_assertion at =
321322
let x = of_var_opt mods x_opt in
@@ -382,11 +383,12 @@ let of_command mods cmd =
382383
":" ^ string_of_int cmd.at.left.line ^ "\n" ^
383384
match cmd.it with
384385
| Module (x_opt, def) ->
385-
let m =
386+
let rec unquote def =
386387
match def.it with
387388
| Textual m -> m
388389
| Encoded (_, bs) -> Decode.decode "binary" bs
389-
in bind mods x_opt m;
390+
| Quoted (_, s) -> unquote (Parse.string_to_module s)
391+
in bind mods x_opt (unquote def);
390392
"let " ^ current_var mods ^ " = instance(" ^ of_definition def ^ ");\n" ^
391393
(if x_opt = None then "" else
392394
"let " ^ of_var_opt mods x_opt ^ " = " ^ current_var mods ^ ";\n")

‎interpreter/host/run.ml‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,16 @@ let lookup_registry module_name item_name _t =
281281

282282
(* Running *)
283283

284-
let run_definition def =
284+
let rec run_definition def =
285285
match def.it with
286286
| Textual m -> m
287287
| Encoded (name, bs) ->
288288
trace "Decoding...";
289289
Decode.decode name bs
290+
| Quoted (_, s) ->
291+
trace "Parsing quote...";
292+
let def' = Parse.string_to_module s in
293+
run_definition def'
290294

291295
let run_action act =
292296
match act.it with
@@ -332,7 +336,8 @@ let run_assertion ass =
332336
trace "Asserting malformed...";
333337
(match ignore (run_definition def) with
334338
| exception Decode.Code (_, msg) -> assert_message ass.at "decoding" msg re
335-
| _ -> Assert.error ass.at "expected decoding error"
339+
| exception Parse.Syntax (_, msg) -> assert_message ass.at "parsing" msg re
340+
| _ -> Assert.error ass.at "expected decoding/parsing error"
336341
)
337342

338343
| AssertInvalid (def, re) ->

‎interpreter/text/arrange.ml‎

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,17 @@ let nat n = I32.to_string_u (I32.of_int_u n)
1212
let nat32 = I32.to_string_u
1313

1414
let add_hex_char buf c = Printf.bprintf buf "\\%02x" (Char.code c)
15-
let add_char buf c =
16-
if c < '\x20' || c >= '\x7f' then
17-
add_hex_char buf c
18-
else begin
19-
if c = '\"' || c = '\\' then Buffer.add_char buf '\\';
20-
Buffer.add_char buf c
21-
end
22-
let add_unicode_char buf uc =
23-
if uc < 0x20 || uc >= 0x7f then
24-
Printf.bprintf buf "\\u{%02x}" uc
25-
else
26-
add_char buf (Char.chr uc)
15+
let add_char buf = function
16+
| '\n' -> Buffer.add_string buf "\\n"
17+
| '\t' -> Buffer.add_string buf "\\t"
18+
| '\"' -> Buffer.add_string buf "\\\""
19+
| '\\' -> Buffer.add_string buf "\\\\"
20+
| c when '\x20' <= c && c < '\x7f' -> Buffer.add_char buf c
21+
| c -> add_hex_char buf c
22+
let add_unicode_char buf = function
23+
| (0x09 | 0x0a) as uc -> add_char buf (Char.chr uc)
24+
| uc when 0x20 <= uc && uc < 0x7f -> add_char buf (Char.chr uc)
25+
| uc -> Printf.bprintf buf "\\u{%02x}" uc
2726

2827
let string_with iter add_char s =
2928
let buf = Buffer.create 256 in
@@ -49,6 +48,10 @@ let break_bytes s =
4948
let ss = Lib.String.breakup s 16 in
5049
list (atom bytes) ss
5150

51+
let break_string s =
52+
let ss, s' = Lib.List.split_last (Lib.String.split s '\n') in
53+
list (atom string) (List.map (fun s -> s ^ "\n") ss @ [s'])
54+
5255

5356
(* Types *)
5457

@@ -369,7 +372,10 @@ let module_with_var_opt x_opt m =
369372
)
370373

371374
let binary_module_with_var_opt x_opt bs =
372-
Node ("module" ^ var_opt x_opt, break_bytes bs)
375+
Node ("module" ^ var_opt x_opt ^ " binary", break_bytes bs)
376+
377+
let quoted_module_with_var_opt x_opt s =
378+
Node ("module" ^ var_opt x_opt ^ " quote", break_string s)
373379

374380
let module_ = module_with_var_opt None
375381

@@ -384,19 +390,26 @@ let literal lit =
384390
| Values.F64 z -> Node ("f64.const " ^ F64.to_string z, [])
385391

386392
let definition mode x_opt def =
387-
match mode, def.it with
388-
| `Textual, _ | `Original, Textual _ ->
389-
let m =
390-
match def.it with
391-
| Textual m -> m
392-
| Encoded (_, bs) -> Decode.decode "" bs
393-
in module_with_var_opt x_opt m
394-
| `Binary, _ | `Original, Encoded _ ->
395-
let bs =
396-
match def.it with
397-
| Textual m -> Encode.encode m
398-
| Encoded (_, bs) -> bs
399-
in binary_module_with_var_opt x_opt bs
393+
try
394+
match mode, def.it with
395+
| `Textual, _ | `Original, Textual _ ->
396+
let rec unquote def =
397+
match def.it with
398+
| Textual m -> m
399+
| Encoded (_, bs) -> Decode.decode "" bs
400+
| Quoted (_, s) -> unquote (Parse.string_to_module s)
401+
in module_with_var_opt x_opt (unquote def)
402+
| `Binary, _ | `Original, Encoded _ ->
403+
let rec unquote bs =
404+
match def.it with
405+
| Textual m -> Encode.encode m
406+
| Encoded (_, bs) -> bs
407+
| Quoted (_, s) -> unquote (Parse.string_to_module s)
408+
in binary_module_with_var_opt x_opt (unquote def)
409+
| `Original, Quoted (_, s) ->
410+
quoted_module_with_var_opt x_opt s
411+
with Parse.Syntax _ ->
412+
quoted_module_with_var_opt x_opt "<invalid module>"
400413

401414
let access x_opt n =
402415
String.concat " " [var_opt x_opt; name n]

‎interpreter/text/lexer.mll‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@ rule token = parse
322322
| "result" { RESULT }
323323
| "local" { LOCAL }
324324
| "global" { GLOBAL }
325-
| "module" { MODULE }
326325
| "table" { TABLE }
327326
| "memory" { MEMORY }
328327
| "elem" { ELEM }
@@ -331,6 +330,10 @@ rule token = parse
331330
| "import" { IMPORT }
332331
| "export" { EXPORT }
333332

333+
| "module" { MODULE }
334+
| "binary" { BIN }
335+
| "quote" { QUOTE }
336+
334337
| "script" { SCRIPT }
335338
| "register" { REGISTER }
336339
| "invoke" { INVOKE }

‎interpreter/text/parser.mly‎

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,11 @@ let inline_type_explicit (c : context) x ty at =
160160
%token CALL CALL_INDIRECT RETURN
161161
%token GET_LOCAL SET_LOCAL TEE_LOCAL GET_GLOBAL SET_GLOBAL
162162
%token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT
163-
%token CONST UNARY BINARY COMPARE CONVERT
163+
%token CONST UNARY BINARY TEST COMPARE CONVERT
164164
%token UNREACHABLE CURRENT_MEMORY GROW_MEMORY
165165
%token FUNC START TYPE PARAM RESULT LOCAL GLOBAL
166-
%token MODULE TABLE ELEM MEMORY DATA OFFSET IMPORT EXPORT TABLE
166+
%token TABLE ELEM MEMORY DATA OFFSET IMPORT EXPORT TABLE
167+
%token MODULE BIN QUOTE
167168
%token SCRIPT REGISTER INVOKE GET
168169
%token ASSERT_MALFORMED ASSERT_INVALID ASSERT_SOFT_INVALID ASSERT_UNLINKABLE
169170
%token ASSERT_RETURN ASSERT_RETURN_CANONICAL_NAN ASSERT_RETURN_ARITHMETIC_NAN ASSERT_TRAP ASSERT_EXHAUSTION
@@ -655,11 +656,13 @@ module_fields1 :
655656
{ fun c -> let m = $2 c in
656657
{m with exports = $1 c :: m.exports} }
657658
659+
module_var_opt :
660+
| /* empty */ { None }
661+
| VAR { Some ($1 @@ at ()) } /* Sugar */
662+
658663
module_ :
659-
| LPAR MODULE script_var_opt module_fields RPAR
664+
| LPAR MODULE module_var_opt module_fields RPAR
660665
{ $3, Textual ($4 (empty_context ()) @@ at ()) @@ at () }
661-
| LPAR MODULE script_var_opt STRING string_list RPAR
662-
{ $3, Encoded ("binary", $4 ^ $5) @@ at() }
663666
664667
inline_module : /* Sugar */
665668
| module_fields { Textual ($1 (empty_context ()) @@ at ()) @@ at () }
@@ -674,20 +677,27 @@ script_var_opt :
674677
| /* empty */ { None }
675678
| VAR { Some ($1 @@ at ()) } /* Sugar */
676679
680+
script_module :
681+
| module_ { $1 }
682+
| LPAR MODULE module_var_opt BIN string_list RPAR
683+
{ $3, Encoded ("binary", $5) @@ at() }
684+
| LPAR MODULE module_var_opt QUOTE string_list RPAR
685+
{ $3, Quoted ("quote", $5) @@ at() }
686+
677687
action :
678-
| LPAR INVOKE script_var_opt name const_list RPAR
688+
| LPAR INVOKE module_var_opt name const_list RPAR
679689
{ Invoke ($3, $4, $5) @@ at () }
680-
| LPAR GET script_var_opt name RPAR
690+
| LPAR GET module_var_opt name RPAR
681691
{ Get ($3, $4) @@ at() }
682692
683693
assertion :
684-
| LPAR ASSERT_MALFORMED module_ STRING RPAR
694+
| LPAR ASSERT_MALFORMED script_module STRING RPAR
685695
{ AssertMalformed (snd $3, $4) @@ at () }
686-
| LPAR ASSERT_INVALID module_ STRING RPAR
696+
| LPAR ASSERT_INVALID script_module STRING RPAR
687697
{ AssertInvalid (snd $3, $4) @@ at () }
688-
| LPAR ASSERT_UNLINKABLE module_ STRING RPAR
698+
| LPAR ASSERT_UNLINKABLE script_module STRING RPAR
689699
{ AssertUnlinkable (snd $3, $4) @@ at () }
690-
| LPAR ASSERT_TRAP module_ STRING RPAR
700+
| LPAR ASSERT_TRAP script_module STRING RPAR
691701
{ AssertUninstantiable (snd $3, $4) @@ at () }
692702
| LPAR ASSERT_RETURN action const_list RPAR { AssertReturn ($3, $4) @@ at () }
693703
| LPAR ASSERT_RETURN_CANONICAL_NAN action RPAR { AssertReturnCanonicalNaN $3 @@ at () }
@@ -698,8 +708,8 @@ assertion :
698708
cmd :
699709
| action { Action $1 @@ at () }
700710
| assertion { Assertion $1 @@ at () }
701-
| module_ { Module (fst $1, snd $1) @@ at () }
702-
| LPAR REGISTER name script_var_opt RPAR { Register ($3, $4) @@ at () }
711+
| script_module { Module (fst $1, snd $1) @@ at () }
712+
| LPAR REGISTER name module_var_opt RPAR { Register ($3, $4) @@ at () }
703713
| meta { Meta $1 @@ at () }
704714
705715
cmd_list :

‎interpreter/text/script.ml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type definition = definition' Source.phrase
44
and definition' =
55
| Textual of Ast.module_
66
| Encoded of string * string
7+
| Quoted of string * string
78

89
type action = action' Source.phrase
910
and action' =

‎interpreter/util/lib.ml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ struct
2828
for i = String.length s - 1 downto 0 do cs := s.[i] :: !cs done;
2929
!cs
3030

31+
let split s c =
32+
let len = String.length s in
33+
let rec loop i =
34+
if i > len then [] else
35+
let j = try String.index_from s i c with Not_found -> len in
36+
String.sub s i (j - i) :: loop (j + 1)
37+
in loop 0
38+
3139
let breakup s n =
3240
let rec loop i =
3341
let len = min n (String.length s - i) in

‎interpreter/util/lib.mli‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,6 @@ module String :
6666
sig
6767
val implode : char list -> string
6868
val explode : string -> char list
69+
val split : string -> char -> string list
6970
val breakup : string -> int -> string list
7071
end

‎test/core/address-offset-range.fail.wast‎

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)