Skip to content

Commit 40dca73

Browse files
authored
[interpreter] Build wast.js with Js_of_ocaml (#1507)
1 parent 8159541 commit 40dca73

File tree

8 files changed

+72
-129
lines changed

8 files changed

+72
-129
lines changed

.github/workflows/main.yml

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ jobs:
2121
- run: opam install --yes ocamlbuild.0.14.0
2222
- run: cd interpreter && opam exec make all
2323

24+
ref-interpreter-js-library:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v2
28+
- name: Setup OCaml
29+
uses: ocaml/setup-ocaml@v2
30+
with:
31+
ocaml-compiler: 4.12.x
32+
- run: opam install --yes ocamlbuild.0.14.0 ocamlfind.1.9.5 js_of_ocaml.4.0.0 js_of_ocaml-ppx.4.0.0
33+
- run: cd interpreter && opam exec make wast.js
34+
2435
build-js-api-spec:
2536
runs-on: ubuntu-latest
2637
steps:

interpreter/Makefile

+13-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# package manager to build. However, Opam package management is available
33
# optionally through the check/install/uninstall targets.
44
#
5-
# The $(JSLIB) target requires node.js and BuckleScript.
5+
# The $(JSLIB).js target requires Js_of_ocaml (using ocamlfind).
66
#
77
# See README.me for instructions.
88

@@ -14,14 +14,15 @@ UNOPT = $(NAME).debug
1414
OPT = $(NAME)
1515
LIB = $(NAME)
1616
ZIP = $(NAME).zip
17-
JSLIB = wast.js
17+
JSLIB = wast
1818
WINMAKE = winmake.bat
1919

2020
DIRS = util syntax binary text valid runtime exec script host main tests
2121
LIBS = bigarray
2222
FLAGS = -lexflags -ml -cflags '-w +a-4-27-42-44-45-70 -warn-error +a-3'
2323
OCBA = ocamlbuild $(FLAGS) $(DIRS:%=-I %)
2424
OCB = $(OCBA) $(LIBS:%=-libs %)
25+
JSO = js_of_ocaml -q --opt 3
2526
JS = # set to JS shell command to run JS tests
2627

2728

@@ -35,7 +36,7 @@ opt: $(OPT)
3536
unopt: $(UNOPT)
3637
libopt: _build/$(LIB).cmx _build/$(LIB).cmxa
3738
libunopt: _build/$(LIB).cmo _build/$(LIB).cma
38-
jslib: $(JSLIB)
39+
jslib: $(JSLIB).js
3940
all: unopt opt libunopt libopt test
4041
land: $(WINMAKE) all
4142
zip: $(ZIP)
@@ -108,14 +109,15 @@ _build/$(LIB).cmxa: $(FILES) $(LIB).mllib _tags Makefile
108109
109110
# Building JavaScript library
110111
111-
.PHONY: $(JSLIB)
112-
$(JSLIB): $(UNOPT)
113-
mkdir -p _build/jslib/src
114-
cp meta/jslib/* _build/jslib
115-
cp $(DIRS:%=_build/%/*.ml*) meta/jslib/*.ml _build/jslib/src
116-
rm _build/jslib/src/*.ml[^i]
117-
(cd _build/jslib; ./build.sh ../../$@)
112+
JSLIB_DIR = meta/jslib
113+
JSLIB_FLAGS = -I $(JSLIB_DIR) -use-ocamlfind -pkg js_of_ocaml -pkg js_of_ocaml-ppx
118114
115+
.INTERMEDIATE: $(JSLIB).byte
116+
$(JSLIB).byte: $(JSLIB_DIR)/$(JSLIB).ml
117+
$(OCBA) $(JSLIB_FLAGS) $@
118+
119+
$(JSLIB).js: $(JSLIB).byte
120+
$(JSO) $<
119121
120122
# Building Windows build file
121123
@@ -181,7 +183,7 @@ $(ZIP): $(WINMAKE)
181183
git archive --format=zip --prefix=$(NAME)/ -o $@ HEAD
182184
183185
clean:
184-
rm -rf _build/jslib $(LIB).mlpack _tags
186+
rm -rf _build/jslib $(LIB).mlpack _tags $(JSLIB).js
185187
$(OCB) -clean
186188
187189

interpreter/README.md

+20-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ The Makefile also provides a target to compile (parts of) the interpreter into a
6565
```
6666
make wast.js
6767
```
68-
Building this target requires node.js and BuckleScript.
68+
Building this target requires `js_of_ocaml`, which can be installed with OPAM:
69+
```
70+
opam install js_of_ocaml js_of_ocaml-ppx
71+
```
6972

7073

7174
## Synopsis
@@ -139,7 +142,7 @@ WebAssemblyText.encode(source)
139142
```
140143
which turns a module in S-expression syntax into a WebAssembly binary, and
141144
```
142-
WebAssemblyText.decode(binary, width = 80)
145+
WebAssemblyText.decode(binary, width)
143146
```
144147
which pretty-prints a binary back into a canonicalised S-expression string.
145148

@@ -151,7 +154,7 @@ let binary = WebAssemblyText.encode(source)
151154
(new WebAssembly.Instance(new WebAssembly.Module(binary))).exports.f(3, 4)
152155
// => 7
153156
154-
WebAssemblyText.decode(binary)
157+
WebAssemblyText.decode(binary, 80)
155158
// =>
156159
// (module
157160
// (type $0 (func (param i32 i32) (result i32)))
@@ -160,6 +163,20 @@ WebAssemblyText.decode(binary)
160163
// )
161164
```
162165

166+
Depending on how you load the library, the object may be accessed in different ways. For example, using `require` in node.js:
167+
168+
```
169+
let wast = require("./wast.js");
170+
let binary = wast.WebAssemblyText.encode("(module)");
171+
```
172+
173+
Or using `load` from a JavaScript shell:
174+
175+
```
176+
load("./wast.js");
177+
let binary = WebAssemblyText.encode("(module)");
178+
```
179+
163180

164181
## S-Expression Syntax
165182

interpreter/dune

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
(name wasm)
55
; The 'main' module shall not be part of the library, as it would start the
66
; Wasm REPL every time in all the dependencies.
7-
; We also need to exclude the 'wasm' module as it overlaps with the library
8-
; name.
7+
; We exclude the 'wast' module as it is only used for the JS build.
98
; 'smallint' is a separate test module.
10-
(modules :standard \ main wasm smallint))
9+
(modules :standard \ main smallint wast))
1110

1211
(executable
1312
(name main)

interpreter/meta/jslib/bsconfig.json

-6
This file was deleted.

interpreter/meta/jslib/build.sh

-97
This file was deleted.

interpreter/meta/jslib/wasm.ml

-9
This file was deleted.

interpreter/meta/jslib/wast.ml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
(* Implements a wrapper library that allows the use of the reference
2+
* interpreter's encode/decode functionality in JavaScript.
3+
*)
4+
open Js_of_ocaml
5+
6+
let _ =
7+
Js.export "WebAssemblyText"
8+
(object%js (_self)
9+
10+
method encode (s : Js.js_string Js.t) : (Typed_array.arrayBuffer Js.t) =
11+
let def = Parse.string_to_module (Js.to_string s) in
12+
let bs =
13+
match def.Source.it with
14+
| Script.Textual m -> (Encode.encode m)
15+
| Script.Encoded (_, bs) -> bs
16+
| Script.Quoted (_, _) -> failwith "Unsupported" in
17+
let buf = new%js Typed_array.arrayBuffer (String.length bs) in
18+
let u8arr = new%js Typed_array.uint8Array_fromBuffer buf in
19+
String.iteri (fun i c -> Typed_array.set u8arr i (int_of_char c)) bs; buf
20+
21+
method decode (buf : Typed_array.arrayBuffer Js.t) width : (Js.js_string Js.t) =
22+
let s = Typed_array.String.of_uint8Array (new%js Typed_array.uint8Array_fromBuffer buf) in
23+
let m = Decode.decode "(decode)" s in
24+
Js.string (Sexpr.to_string width (Arrange.module_ m))
25+
26+
end)

0 commit comments

Comments
 (0)