Skip to content

Commit b5f98c6

Browse files
committed
Syntactic sugar for strings
1 parent 44676e0 commit b5f98c6

File tree

5 files changed

+108
-0
lines changed

5 files changed

+108
-0
lines changed

compiler/bin-wasmoo_util/tests/cram.t

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,35 @@ Wrong type
144144
File "-", line 1, characters 14-16:
145145
Expected a boolean but this is a string.
146146
[1]
147+
148+
Bad strings
149+
150+
$ echo '(@string)' | wasmoo_util pp
151+
File "-", line 1, characters 8-9:
152+
Expecting an id or a string.
153+
[1]
154+
155+
$ echo '(@string a "b")' | wasmoo_util pp
156+
File "-", line 1, characters 9-10:
157+
Expecting an id
158+
[1]
159+
160+
$ echo '(@string $a b)' | wasmoo_util pp
161+
File "-", line 1, characters 12-13:
162+
Expecting a string
163+
[1]
164+
165+
$ echo '(@string $bad "\u{1F600}")' | wasmoo_util pp
166+
File "-", line 1, characters 14-25:
167+
Unicode escape sequences are not supported.
168+
[1]
169+
170+
$ echo '(@string a)' | wasmoo_util pp
171+
File "-", line 1, characters 9-10:
172+
Expecting a string
173+
[1]
174+
175+
$ echo '(@string a b c)' | wasmoo_util pp
176+
File "-", line 1, characters 13-14:
177+
Expecting a closing parenthesis.
178+
[1]

compiler/bin-wasmoo_util/tests/tests.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,10 @@
6565
(4 1 1) < (4 2 0)
6666
(4 1 1) < (5 0 1)
6767

68+
69+
;; strings
70+
(global $s (ref eq) (array.new_fixed $string 4 (i32.const 97) (i32.const 98) (i32.const 99) (i32.const 100)))
71+
(array.new_fixed $string 4 (i32.const 97) (i32.const 98) (i32.const 99) (i32.const 100))
72+
(array.new_fixed $string 4 (i32.const 92) (i32.const 39) (i32.const 40) (i32.const 10))
73+
(array.new_fixed $string 4 (i32.const 97) (i32.const 98) (i32.const 99) (i32.const 100))
74+
(array.new_fixed $string 4 (i32.const 97) (i32.const 98) (i32.const 99) (i32.const 100))

compiler/bin-wasmoo_util/tests/tests.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,10 @@
6565
(@if (< (4 1 1) (4 2 0)) (@then (4 1 1) < (4 2 0)))
6666
(@if (< (4 1 1) (5 0 1)) (@then (4 1 1) < (5 0 1)))
6767
(@if (< (4 1 1) (3 2 1)) (@then (4 1 1) < (3 2 1)))
68+
69+
;; strings
70+
(@string $s "abcd")
71+
(@string "abcd")
72+
(@string "\\\'\28\n")
73+
(@if (and) (@then (@string "abcd")))
74+
(@if (or) (@then) (@else (@string "abcd")))

compiler/lib-wasm/wat_preprocess.ml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,20 @@ let parse_string loc s =
237237
, Printf.sprintf "Unicode escape sequences are not supported.\n" ))
238238
| Some s -> s
239239

240+
let is_string s = String.length s > 0 && Char.equal s.[0] '"'
241+
240242
let is_keyword s =
241243
let lexbuf = Sedlexing.Utf8.from_string s in
242244
match%sedlex lexbuf with
243245
| keyword, eof -> true
244246
| _ -> false
245247

248+
let is_id s =
249+
let lexbuf = Sedlexing.Utf8.from_string s in
250+
match%sedlex lexbuf with
251+
| id, eof -> true
252+
| _ -> false
253+
246254
(****)
247255

248256
module StringMap = Map.Make (String)
@@ -370,6 +378,14 @@ let skip st (pos' : pos) =
370378
Buffer.add_string st.buf (String.make (max 0 cols) ' ');
371379
st.pos <- pos'
372380

381+
let insert st s =
382+
Buffer.add_string st.buf s;
383+
let n = String.length s in
384+
st.pos <-
385+
{ loc = { st.pos.loc with pos_cnum = st.pos.loc.pos_cnum + n }
386+
; byte_loc = st.pos.byte_loc - 1
387+
}
388+
373389
let pred_position { loc; byte_loc } =
374390
{ loc = { loc with pos_cnum = loc.pos_cnum - 1 }; byte_loc = byte_loc - 1 }
375391

@@ -456,6 +472,50 @@ and rewrite st elt =
456472
( position_of_loc loc
457473
, Printf.sprintf "Unexpected %s clause. Maybe you forgot a parenthesis.\n" nm
458474
))
475+
| { desc =
476+
List
477+
[ { desc = Atom "@string"; _ }
478+
; { desc = Atom name; loc = loc_name }
479+
; { desc = Atom value; loc = loc_value }
480+
]
481+
; loc = pos, pos'
482+
} ->
483+
if not (is_id name) then raise (Error (position_of_loc loc_name, "Expecting an id"));
484+
if not (is_string value)
485+
then raise (Error (position_of_loc loc_value, "Expecting a string"));
486+
let s = parse_string loc_value value in
487+
write st pos;
488+
insert
489+
st
490+
(Format.asprintf
491+
"(global %s (ref eq) (array.new_fixed $string %d%a))"
492+
name
493+
(String.length s)
494+
(fun f s ->
495+
String.iter ~f:(fun c -> Format.fprintf f " (i32.const %d)" (Char.code c)) s)
496+
s);
497+
skip st pos'
498+
| { desc = List [ { desc = Atom "@string"; _ }; { desc = Atom value; loc = loc_value } ]
499+
; loc = pos, pos'
500+
} ->
501+
if not (is_string value)
502+
then raise (Error (position_of_loc loc_value, "Expecting a string"));
503+
let s = parse_string loc_value value in
504+
write st pos;
505+
insert
506+
st
507+
(Format.asprintf
508+
"(array.new_fixed $string %d%a)"
509+
(String.length s)
510+
(fun f s ->
511+
String.iter ~f:(fun c -> Format.fprintf f " (i32.const %d)" (Char.code c)) s)
512+
s);
513+
skip st pos'
514+
| { desc = List [ { desc = Atom "@string"; loc = _, pos } ]; loc = _, pos' } ->
515+
raise (Error ((pos.loc, pos'.loc), Printf.sprintf "Expecting an id or a string.\n"))
516+
| { desc = List ({ desc = Atom "@string"; _ } :: _ :: _ :: { loc; _ } :: _); _ } ->
517+
raise
518+
(Error (position_of_loc loc, Printf.sprintf "Expecting a closing parenthesis.\n"))
459519
| { desc = List l; _ } -> rewrite_list st l
460520
| _ -> ()
461521

manual/wasm_runtime.wiki

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ To form conditional expressions, the following operators are available:
6060
- comparisons: {{{=}}}, {{{>}}}, {{{>=}}}, {{{<}}}, {{{<=}}}, {{{<>}}};
6161
- boolean operators: {{{and}}}, {{{or}}}, {{{not}}}
6262

63+
It also provides some syntactic sugar to write strings. The expression{{{(@string "ab")}}} is expanded into {{{(array.new_fixed $string 2 (i32.const 97) (i32.const 98))}}}. The statement {{{(@string $s "ab")}}} is an abbreviatiation for {{{(global $s (ref eq) (@string "ab"))}}}.
64+
6365
== Implementing primitives ==
6466

6567
You define a primitive by exporting a Wasm function with parameters and return value of type {{{(ref eq)}}}.

0 commit comments

Comments
 (0)