Skip to content

Commit 7e13ccb

Browse files
committed
Preprocessor: syntactic sugar for ASCII characters
1 parent 3a92c44 commit 7e13ccb

File tree

10 files changed

+191
-158
lines changed

10 files changed

+191
-158
lines changed

compiler/lib-wasm/wat_preprocess.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,24 @@ and rewrite st elt =
533533
| { desc = List ({ desc = Atom "@string"; _ } :: _ :: _ :: { loc; _ } :: _); _ } ->
534534
raise
535535
(Error (position_of_loc loc, Printf.sprintf "Expecting a closing parenthesis.\n"))
536+
| { desc = List [ { desc = Atom "@char"; _ }; { desc = Atom value; loc = loc_value } ]
537+
; loc = pos, pos'
538+
} ->
539+
if
540+
(not (is_string value))
541+
||
542+
let s = parse_string loc_value value in
543+
String.length s <> 1 || Char.code s.[0] > 127
544+
then raise (Error (position_of_loc loc_value, "Expecting an ASCII character"));
545+
let s = parse_string loc_value value in
546+
write st pos;
547+
insert st (Format.asprintf "(i32.const %d)" (Char.code s.[0]));
548+
skip st pos'
549+
| { desc = List [ { desc = Atom "@char"; loc = _, pos } ]; loc = _, pos' } ->
550+
raise (Error ((pos.loc, pos'.loc), Printf.sprintf "Expecting a string.\n"))
551+
| { desc = List ({ desc = Atom "@char"; _ } :: _ :: _ :: { loc; _ } :: _); _ } ->
552+
raise
553+
(Error (position_of_loc loc, Printf.sprintf "Expecting a closing parenthesis.\n"))
536554
| { desc =
537555
List
538556
({ desc = Atom "func"; loc = _, pos }

compiler/tests-wasm_of_ocaml/preprocess/cram.t

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,28 @@ Bad strings
184184
File "-", line 1, characters 13-14:
185185
Expecting a closing parenthesis.
186186
[1]
187+
188+
Bad characters
189+
190+
$ echo '(@char "")' | wasm_of_ocaml pp
191+
File "-", line 1, characters 7-9:
192+
Expecting an ASCII character
193+
[1]
194+
195+
196+
$ echo '(@char "aa")' | wasm_of_ocaml pp
197+
File "-", line 1, characters 7-11:
198+
Expecting an ASCII character
199+
[1]
200+
201+
202+
$ echo '(@char "é")' | wasm_of_ocaml pp
203+
File "-", line 1, characters 7-10:
204+
Expecting an ASCII character
205+
[1]
206+
207+
208+
$ echo '(@char "\80")' | wasm_of_ocaml pp
209+
File "-", line 1, characters 7-12:
210+
Expecting an ASCII character
211+
[1]

compiler/tests-wasm_of_ocaml/preprocess/tests.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,8 @@
7272
(array.new_fixed $bytes 4 (i32.const 92) (i32.const 39) (i32.const 40) (i32.const 10))
7373
(array.new_fixed $bytes 4 (i32.const 97) (i32.const 98) (i32.const 99) (i32.const 100))
7474
(array.new_fixed $bytes 4 (i32.const 97) (i32.const 98) (i32.const 99) (i32.const 100))
75+
76+
;; chars
77+
(array.new_fixed $bytes 1 (i32.const 48))
78+
(array.new_fixed $bytes 1 (i32.const 10))
79+

compiler/tests-wasm_of_ocaml/preprocess/tests.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,8 @@
7272
(@string "\\\'\28\n")
7373
(@if (and) (@then (@string "abcd")))
7474
(@if (or) (@then) (@else (@string "abcd")))
75+
76+
;; chars
77+
(@string "0")
78+
(@string "\n")
79+

manual/wasm_runtime.wiki

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ 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 $bytes 2 (i32.const 97) (i32.const 98))}}}. The statement {{{(@string $s "ab")}}} is an abbreviation for {{{(global $s (ref eq) (@string "ab"))}}}.
63+
It also provides some syntactic sugar for strings and ASCII characters. The expression {{{(@string "ab")}}} is expanded into {{{(array.new_fixed $bytes 2 (i32.const 97) (i32.const 98))}}}. The statement {{{(@string $s "ab")}}} is an abbreviation for {{{(global $s (ref eq) (@string "ab"))}}}. The expression {{{(@char "a")}}} is expanded to {{{(i32.const 92)}}}.
6464

6565
To provide a better debugging experience, the function export name is used to name functions with no explicit id: {{{(func (export "foo") ...)}}}} is expanded into {{{(func $foo (export "foo") ...)}}}}.
6666

runtime/wasm/float.wat

Lines changed: 64 additions & 71 deletions
Large diffs are not rendered by default.

runtime/wasm/int64.wat

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
(if (i32.lt_s (local.get $i) (local.get $len))
157157
(then
158158
(local.set $c (array.get_u $bytes (local.get $s) (local.get $i)))
159-
(br_if $loop (i32.eq (local.get $c) (i32.const 95))) ;; '_'
159+
(br_if $loop (i32.eq (local.get $c) (@char "_")))
160160
(local.set $d (call $parse_digit (local.get $c)))
161161
(if (i32.ge_u (local.get $d) (local.get $base))
162162
(then (call $caml_failwith (local.get $errmsg))))
@@ -221,14 +221,12 @@
221221
(loop $write
222222
(local.set $i (i32.sub (local.get $i) (i32.const 1)))
223223
(array.set $bytes (local.get $s) (local.get $i)
224-
(i32.add (i32.const 48)
224+
(i32.add (@char "0")
225225
(i32.wrap_i64 (i64.rem_u (local.get $d) (i64.const 10)))))
226226
(local.set $d (i64.div_u (local.get $d) (i64.const 10)))
227227
(br_if $write (i64.ne (local.get $d) (i64.const 0))))
228228
(if (local.get $negative)
229-
(then
230-
(array.set $bytes (local.get $s) (i32.const 0)
231-
(i32.const 45)))) ;; '-'
229+
(then (array.set $bytes (local.get $s) (i32.const 0) (@char "-"))))
232230
(local.get $s))
233231

234232
(type $chars (array i8))
@@ -249,7 +247,7 @@
249247
(if (i32.eq (array.len (local.get $s)) (i32.const 2))
250248
(then
251249
(if (i32.eq (array.get_u $bytes (local.get $s) (i32.const 1))
252-
(i32.const 100)) ;; 'd'
250+
(@char "d"))
253251
(then (return_call $format_int64_default (local.get $d))))))
254252
(local.set $format (call $parse_int_format (local.get $s)))
255253
(local.set $sign_style (tuple.extract 5 0 (local.get $format)))
@@ -296,28 +294,26 @@
296294
(br_if $write (i64.ne (local.get $d) (i64.const 0))))
297295
(if (local.get $negative)
298296
(then
299-
(array.set $bytes (local.get $s) (i32.const 0)
300-
(i32.const 45))) ;; '-'
297+
(array.set $bytes (local.get $s) (i32.const 0) (@char "-")))
301298
(else
302299
(if (local.get $sign_style)
303300
(then
304301
(if (i32.eq (local.get $sign_style) (i32.const 1))
305302
(then
306303
(array.set $bytes (local.get $s) (i32.const 0)
307-
(i32.const 43))) ;; '+'
304+
(@char "+")))
308305
(else
309306
(array.set $bytes (local.get $s) (i32.const 0)
310-
(i32.const 32)))))))) ;; ' '
307+
(@char " "))))))))
311308
(if (local.get $alternate)
312309
(then
313310
(if (local.get $i)
314311
(then
315-
(array.set $bytes (local.get $s) (i32.const 0)
316-
(i32.const 48)) ;; '0'
312+
(array.set $bytes (local.get $s) (i32.const 0) (@char "0"))
317313
(if (i64.eq (local.get $base) (i64.const 16))
318314
(then
319315
(array.set $bytes (local.get $s) (i32.const 1)
320-
(select (i32.const 88) (i32.const 120) ;; 'X' 'x'
316+
(select (@char "X") (@char "x")
321317
(local.get $uppercase)))))))))
322318
(local.get $s))
323319

runtime/wasm/ints.wat

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040
(if (i32.ne (local.get $len) (i32.const 0))
4141
(then
4242
(local.set $c (array.get_u $bytes (local.get $s) (i32.const 0)))
43-
(if (i32.eq (local.get $c) (i32.const 45))
43+
(if (i32.eq (local.get $c) (@char "-"))
4444
(then
4545
(local.set $sign (i32.const -1))
4646
(local.set $i (i32.const 1)))
47-
(else (if (i32.eq (local.get $c) (i32.const 43))
47+
(else (if (i32.eq (local.get $c) (@char "+"))
4848
(then (local.set $i (i32.const 1))))))))
4949
(if (i32.lt_s (i32.add (local.get $i) (i32.const 1)) (local.get $len))
5050
(then (if (i32.eq (array.get_u $bytes (local.get $s) (local.get $i))
@@ -53,26 +53,26 @@
5353
(local.set $c
5454
(array.get_u $bytes (local.get $s)
5555
(i32.add (local.get $i) (i32.const 1))))
56-
(if (i32.or (i32.eq (local.get $c) (i32.const 88))
57-
(i32.eq (local.get $c) (i32.const 120)))
56+
(if (i32.or (i32.eq (local.get $c) (@char "X"))
57+
(i32.eq (local.get $c) (@char "x")))
5858
(then
5959
(local.set $base (i32.const 16))
6060
(local.set $signedness (i32.const 0))
6161
(local.set $i (i32.add (local.get $i) (i32.const 2))))
62-
(else (if (i32.or (i32.eq (local.get $c) (i32.const 79))
63-
(i32.eq (local.get $c) (i32.const 111)))
62+
(else (if (i32.or (i32.eq (local.get $c) (@char "O"))
63+
(i32.eq (local.get $c) (@char "o")))
6464
(then
6565
(local.set $base (i32.const 8))
6666
(local.set $signedness (i32.const 0))
6767
(local.set $i (i32.add (local.get $i) (i32.const 2))))
68-
(else (if (i32.or (i32.eq (local.get $c) (i32.const 66))
69-
(i32.eq (local.get $c) (i32.const 98)))
68+
(else (if (i32.or (i32.eq (local.get $c) (@char "B"))
69+
(i32.eq (local.get $c) (@char "b")))
7070
(then
7171
(local.set $base (i32.const 2))
7272
(local.set $signedness (i32.const 0))
7373
(local.set $i (i32.add (local.get $i) (i32.const 2))))
74-
(else (if (i32.or (i32.eq (local.get $c) (i32.const 85))
75-
(i32.eq (local.get $c) (i32.const 117)))
74+
(else (if (i32.or (i32.eq (local.get $c) (@char "U"))
75+
(i32.eq (local.get $c) (@char "u")))
7676
(then
7777
(local.set $signedness (i32.const 0))
7878
(local.set $i (i32.add (local.get $i)
@@ -82,14 +82,14 @@
8282
(local.get $base)))
8383

8484
(func $parse_digit (export "parse_digit") (param $c i32) (result i32)
85-
(if (i32.and (i32.ge_u (local.get $c) (i32.const 48))
86-
(i32.le_u (local.get $c) (i32.const 57)))
87-
(then (return (i32.sub (local.get $c) (i32.const 48)))))
88-
(if (i32.and (i32.ge_u (local.get $c) (i32.const 65))
89-
(i32.le_u (local.get $c) (i32.const 90)))
85+
(if (i32.and (i32.ge_u (local.get $c) (@char "0"))
86+
(i32.le_u (local.get $c) (@char "9")))
87+
(then (return (i32.sub (local.get $c) (@char "0")))))
88+
(if (i32.and (i32.ge_u (local.get $c) (@char "A"))
89+
(i32.le_u (local.get $c) (@char "Z")))
9090
(then (return (i32.sub (local.get $c) (i32.const 55)))))
91-
(if (i32.and (i32.ge_u (local.get $c) (i32.const 97))
92-
(i32.le_u (local.get $c) (i32.const 122)))
91+
(if (i32.and (i32.ge_u (local.get $c) (@char "a"))
92+
(i32.le_u (local.get $c) (@char "z")))
9393
(then (return (i32.sub (local.get $c) (i32.const 87)))))
9494
(return (i32.const -1)))
9595

@@ -123,7 +123,7 @@
123123
(if (i32.lt_s (local.get $i) (local.get $len))
124124
(then
125125
(local.set $c (array.get_u $bytes (local.get $s) (local.get $i)))
126-
(br_if $loop (i32.eq (local.get $c) (i32.const 95))) ;; '_'
126+
(br_if $loop (i32.eq (local.get $c) (@char "_")))
127127
(local.set $d (call $parse_digit (local.get $c)))
128128
(if (i32.ge_u (local.get $d) (local.get $base))
129129
(then (call $caml_failwith (local.get $errmsg))))
@@ -178,17 +178,17 @@
178178

179179
(global $lowercase_hex_table (export "lowercase_hex_table") (ref $chars)
180180
(array.new_fixed $chars 16
181-
(i32.const 48) (i32.const 49) (i32.const 50) (i32.const 51)
182-
(i32.const 52) (i32.const 53) (i32.const 54) (i32.const 55)
183-
(i32.const 56) (i32.const 57) (i32.const 97) (i32.const 98)
184-
(i32.const 99) (i32.const 100) (i32.const 101) (i32.const 102)))
181+
(@char "0") (@char "1") (@char "2") (@char "3")
182+
(@char "4") (@char "5") (@char "6") (@char "7")
183+
(@char "8") (@char "9") (@char "a") (@char "b")
184+
(@char "c") (@char "d") (@char "e") (@char "f")))
185185

186186
(global $uppercase_hex_table (export "uppercase_hex_table") (ref $chars)
187187
(array.new_fixed $chars 16
188-
(i32.const 48) (i32.const 49) (i32.const 50) (i32.const 51)
189-
(i32.const 52) (i32.const 53) (i32.const 54) (i32.const 55)
190-
(i32.const 56) (i32.const 57) (i32.const 65) (i32.const 66)
191-
(i32.const 67) (i32.const 68) (i32.const 69) (i32.const 70)))
188+
(@char "0") (@char "1") (@char "2") (@char "3")
189+
(@char "4") (@char "5") (@char "6") (@char "7")
190+
(@char "8") (@char "9") (@char "A") (@char "B")
191+
(@char "C") (@char "D") (@char "E") (@char "F")))
192192

193193
(func $format_int_default (param $d i32) (result (ref eq))
194194
(local $s (ref $bytes))
@@ -207,14 +207,12 @@
207207
(loop $write
208208
(local.set $i (i32.sub (local.get $i) (i32.const 1)))
209209
(array.set $bytes (local.get $s) (local.get $i)
210-
(i32.add (i32.const 48)
210+
(i32.add (@char "0")
211211
(i32.rem_u (local.get $d) (i32.const 10))))
212212
(local.set $d (i32.div_u (local.get $d) (i32.const 10)))
213213
(br_if $write (local.get $d)))
214214
(if (local.get $negative)
215-
(then
216-
(array.set $bytes (local.get $s) (i32.const 0)
217-
(i32.const 45)))) ;; '-'
215+
(then (array.set $bytes (local.get $s) (i32.const 0) (@char "-"))))
218216
(local.get $s))
219217

220218
(@string $format_error "format_int: bad format")
@@ -231,48 +229,48 @@
231229
(br_if $bad_format (i32.lt_u (local.get $len) (i32.const 2)))
232230
(br_if $bad_format
233231
(i32.ne (array.get_u $bytes (local.get $s) (i32.const 0))
234-
(i32.const 37))) ;; '%'
232+
(@char "%")))
235233
(local.set $c (array.get_u $bytes (local.get $s) (i32.const 1)))
236-
(if (i32.eq (local.get $c) (i32.const 43)) ;; '+'
234+
(if (i32.eq (local.get $c) (@char "+"))
237235
(then
238236
(local.set $sign_style (i32.const 1))
239237
(local.set $i (i32.add (local.get $i) (i32.const 1)))))
240-
(if (i32.eq (local.get $c) (i32.const 32)) ;; ' '
238+
(if (i32.eq (local.get $c) (@char " "))
241239
(then
242240
(local.set $sign_style (i32.const 2))
243241
(local.set $i (i32.add (local.get $i) (i32.const 1)))))
244-
(if (i32.eq (local.get $c) (i32.const 35)) ;; '#'
242+
(if (i32.eq (local.get $c) (@char "#"))
245243
(then
246244
(local.set $alternate (i32.const 1))
247245
(local.set $i (i32.add (local.get $i) (i32.const 1)))))
248246
(br_if $bad_format (i32.eq (local.get $i) (local.get $len)))
249247
(local.set $c (array.get_u $bytes (local.get $s) (local.get $i)))
250-
(if (i32.or (i32.or (i32.eq (local.get $c) (i32.const 76)) ;; 'L'
251-
(i32.eq (local.get $c) (i32.const 108))) ;; 'l'
252-
(i32.eq (local.get $c) (i32.const 110))) ;; 'n'
248+
(if (i32.or (i32.or (i32.eq (local.get $c) (@char "L"))
249+
(i32.eq (local.get $c) (@char "l")))
250+
(i32.eq (local.get $c) (@char "n")))
253251
(then
254252
(local.set $i (i32.add (local.get $i) (i32.const 1)))
255253
(br_if $bad_format (i32.eq (local.get $i) (local.get $len)))
256254
(local.set $c
257255
(array.get_u $bytes (local.get $s) (local.get $i)))))
258256
(br_if $bad_format
259257
(i32.ne (i32.add (local.get $i) (i32.const 1)) (local.get $len)))
260-
(if (i32.or (i32.eq (local.get $c) (i32.const 100)) ;; 'd'
261-
(i32.eq (local.get $c) (i32.const 105))) ;; 'i'
258+
(if (i32.or (i32.eq (local.get $c) (@char "d"))
259+
(i32.eq (local.get $c) (@char "i")))
262260
(then
263261
(local.set $base (i32.const 10))
264262
(local.set $signed (i32.const 1)))
265-
(else (if (i32.eq (local.get $c) (i32.const 117)) ;; 'u'
263+
(else (if (i32.eq (local.get $c) (@char "u"))
266264
(then
267265
(local.set $base (i32.const 10)))
268-
(else (if (i32.eq (local.get $c) (i32.const 120)) ;; 'x'
266+
(else (if (i32.eq (local.get $c) (@char "x"))
269267
(then
270268
(local.set $base (i32.const 16)))
271-
(else (if (i32.eq (local.get $c) (i32.const 88)) ;; 'X'
269+
(else (if (i32.eq (local.get $c) (@char "X"))
272270
(then
273271
(local.set $base (i32.const 16))
274272
(local.set $uppercase (i32.const 1)))
275-
(else (if (i32.eq (local.get $c) (i32.const 111)) ;; 'o'
273+
(else (if (i32.eq (local.get $c) (@char "o"))
276274
(then
277275
(local.set $base (i32.const 8)))
278276
(else
@@ -300,7 +298,7 @@
300298
(if (i32.eq (array.len (local.get $s)) (i32.const 2))
301299
(then
302300
(if (i32.eq (array.get_u $bytes (local.get $s) (i32.const 1))
303-
(i32.const 100)) ;; 'd'
301+
(@char "d"))
304302
(then (return_call $format_int_default (local.get $d))))))
305303
(local.set $format (call $parse_int_format (local.get $s)))
306304
(local.set $sign_style (tuple.extract 5 0 (local.get $format)))
@@ -353,28 +351,26 @@
353351
(br_if $write (local.get $d)))
354352
(if (local.get $negative)
355353
(then
356-
(array.set $bytes (local.get $s) (i32.const 0)
357-
(i32.const 45))) ;; '-'
354+
(array.set $bytes (local.get $s) (i32.const 0) (@char "-")))
358355
(else
359356
(if (local.get $sign_style)
360357
(then
361358
(if (i32.eq (local.get $sign_style) (i32.const 1))
362359
(then
363360
(array.set $bytes (local.get $s) (i32.const 0)
364-
(i32.const 43))) ;; '+'
361+
(@char "+")))
365362
(else
366363
(array.set $bytes (local.get $s) (i32.const 0)
367-
(i32.const 32)))))))) ;; ' '
364+
(@char " "))))))))
368365
(if (local.get $alternate)
369366
(then
370367
(if (local.get $i)
371368
(then
372-
(array.set $bytes (local.get $s) (i32.const 0)
373-
(i32.const 48)) ;; '0'
369+
(array.set $bytes (local.get $s) (i32.const 0) (@char "0"))
374370
(if (i32.eq (local.get $base) (i32.const 16))
375371
(then
376372
(array.set $bytes (local.get $s) (i32.const 1)
377-
(select (i32.const 88) (i32.const 120) ;; 'X' 'x'
373+
(select (@char "X") (@char "x")
378374
(local.get $uppercase)))))))))
379375
(local.get $s))
380376
)

0 commit comments

Comments
 (0)