Skip to content

Commit

Permalink
Merge pull request #80 from ngzhian/merge-upstream
Browse files Browse the repository at this point in the history
Merge upstream
  • Loading branch information
ngzhian authored Aug 4, 2022
2 parents c2e53ec + 1438c0e commit d4f766c
Show file tree
Hide file tree
Showing 18 changed files with 87 additions and 141 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ jobs:
- run: opam install --yes ocamlbuild.0.14.0
- run: cd interpreter && opam exec make all

ref-interpreter-js-library:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup OCaml
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: 4.12.x
- 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
- run: cd interpreter && opam exec make wast.js

build-js-api-spec:
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion document/core/intro/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ This language is structured around the following concepts.
**Tables**
A *table* is an array of opaque values of a particular *element type*.
It allows programs to select such values indirectly through a dynamic index operand.
Currently, the only available element type is an untyped function reference.
Currently, the only available element type is an untyped function reference or a reference to an external host value.
Thereby, a program can call functions indirectly through a dynamic index into a table.
For example, this allows emulating function pointers by way of table indices.

Expand Down
2 changes: 1 addition & 1 deletion document/core/syntax/instructions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ Occasionally, it is convenient to group operators together according to the foll
Vector Instructions
~~~~~~~~~~~~~~~~~~~

Vector instructions (also known as *SIMD* instructions, single data multiple value) provide basic operations over :ref:`values <syntax-value>` of :ref:`vector type <syntax-vectype>`.
Vector instructions (also known as *SIMD* instructions, single instruction multiple data) provide basic operations over :ref:`values <syntax-value>` of :ref:`vector type <syntax-vectype>`.

.. math::
\begin{array}{llcl}
Expand Down
2 changes: 1 addition & 1 deletion document/core/syntax/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ The |MSTART| component of a module declares the :ref:`function index <syntax-fun
.. note::
The start function is intended for initializing the state of a module.
The module and its exports are not accessible before this initialization has completed.
The module and its exports are not accessible externally before this initialization has completed.


.. index:: ! export, name, index, function index, table index, memory index, global index, function, table, memory, global, instantiation
Expand Down
2 changes: 1 addition & 1 deletion document/core/valid/instructions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ Table Instructions
\frac{
C.\CTABLES[x] = \limits_1~t
\qquad
C.\CTABLES[x] = \limits_2~t
C.\CTABLES[y] = \limits_2~t
}{
C \vdashinstr \TABLECOPY~x~y : [\I32~\I32~\I32] \to []
}
Expand Down
3 changes: 1 addition & 2 deletions document/core/valid/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Import Subtyping

When :ref:`instantiating <exec-module>` a module,
:ref:`external values <syntax-externval>` must be provided whose :ref:`types <valid-externval>` are *matched* against the respective :ref:`external types <syntax-externtype>` classifying each import.
In some cases, this allows for a simple form of subtyping, as defined here.
In some cases, this allows for a simple form of subtyping (written ":math:`\matchesexterntype`" formally), as defined here.


.. index:: limits
Expand Down Expand Up @@ -279,7 +279,6 @@ Limits
\vdashlimitsmatch \{ \LMIN~n_1, \LMAX~m_1 \} \matcheslimits \{ \LMIN~n_2, \LMAX~m_2 \}
}
.. _match-externtype:

.. index:: function type
Expand Down
24 changes: 13 additions & 11 deletions interpreter/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# package manager to build. However, Opam package management is available
# optionally through the check/install/uninstall targets.
#
# The $(JSLIB) target requires node.js and BuckleScript.
# The $(JSLIB).js target requires Js_of_ocaml (using ocamlfind).
#
# See README.me for instructions.

Expand All @@ -14,14 +14,15 @@ UNOPT = $(NAME).debug
OPT = $(NAME)
LIB = $(NAME)
ZIP = $(NAME).zip
JSLIB = wast.js
JSLIB = wast
WINMAKE = winmake.bat

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


Expand All @@ -35,7 +36,7 @@ opt: $(OPT)
unopt: $(UNOPT)
libopt: _build/$(LIB).cmx _build/$(LIB).cmxa
libunopt: _build/$(LIB).cmo _build/$(LIB).cma
jslib: $(JSLIB)
jslib: $(JSLIB).js
all: unopt opt libunopt libopt test
land: $(WINMAKE) all
zip: $(ZIP)
Expand Down Expand Up @@ -108,14 +109,15 @@ _build/$(LIB).cmxa: $(FILES) $(LIB).mllib _tags Makefile
# Building JavaScript library
.PHONY: $(JSLIB)
$(JSLIB): $(UNOPT)
mkdir -p _build/jslib/src
cp meta/jslib/* _build/jslib
cp $(DIRS:%=_build/%/*.ml*) meta/jslib/*.ml _build/jslib/src
rm _build/jslib/src/*.ml[^i]
(cd _build/jslib; ./build.sh ../../$@)
JSLIB_DIR = meta/jslib
JSLIB_FLAGS = -I $(JSLIB_DIR) -use-ocamlfind -pkg js_of_ocaml -pkg js_of_ocaml-ppx
.INTERMEDIATE: $(JSLIB).byte
$(JSLIB).byte: $(JSLIB_DIR)/$(JSLIB).ml
$(OCBA) $(JSLIB_FLAGS) $@
$(JSLIB).js: $(JSLIB).byte
$(JSO) $<
# Building Windows build file
Expand Down Expand Up @@ -181,7 +183,7 @@ $(ZIP): $(WINMAKE)
git archive --format=zip --prefix=$(NAME)/ -o $@ HEAD
clean:
rm -rf _build/jslib $(LIB).mlpack _tags
rm -rf _build/jslib $(LIB).mlpack _tags $(JSLIB).js
$(OCB) -clean
Expand Down
23 changes: 20 additions & 3 deletions interpreter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ The Makefile also provides a target to compile (parts of) the interpreter into a
```
make wast.js
```
Building this target requires node.js and BuckleScript.
Building this target requires `js_of_ocaml`, which can be installed with OPAM:
```
opam install js_of_ocaml js_of_ocaml-ppx
```


## Synopsis
Expand Down Expand Up @@ -139,7 +142,7 @@ WebAssemblyText.encode(source)
```
which turns a module in S-expression syntax into a WebAssembly binary, and
```
WebAssemblyText.decode(binary, width = 80)
WebAssemblyText.decode(binary, width)
```
which pretty-prints a binary back into a canonicalised S-expression string.

Expand All @@ -151,7 +154,7 @@ let binary = WebAssemblyText.encode(source)
(new WebAssembly.Instance(new WebAssembly.Module(binary))).exports.f(3, 4)
// => 7
WebAssemblyText.decode(binary)
WebAssemblyText.decode(binary, 80)
// =>
// (module
// (type $0 (func (param i32 i32) (result i32)))
Expand All @@ -160,6 +163,20 @@ WebAssemblyText.decode(binary)
// )
```

Depending on how you load the library, the object may be accessed in different ways. For example, using `require` in node.js:

```
let wast = require("./wast.js");
let binary = wast.WebAssemblyText.encode("(module)");
```

Or using `load` from a JavaScript shell:

```
load("./wast.js");
let binary = WebAssemblyText.encode("(module)");
```


## S-Expression Syntax

Expand Down
5 changes: 2 additions & 3 deletions interpreter/dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
(name wasm)
; The 'main' module shall not be part of the library, as it would start the
; Wasm REPL every time in all the dependencies.
; We also need to exclude the 'wasm' module as it overlaps with the library
; name.
; We exclude the 'wast' module as it is only used for the JS build.
; 'smallint' is a separate test module.
(modules :standard \ main wasm smallint))
(modules :standard \ main smallint wast))

(executable
(name main)
Expand Down
3 changes: 2 additions & 1 deletion interpreter/exec/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ type config =
}

let frame inst locals = {inst; locals}
let config inst vs es = {frame = frame inst []; code = vs, es; budget = 300}
let config inst vs es =
{frame = frame inst []; code = vs, es; budget = !Flags.budget}

let plain e = Plain e.it @@ e.at

Expand Down
1 change: 1 addition & 0 deletions interpreter/main/flags.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ let print_sig = ref false
let dry = ref false
let width = ref 80
let harness = ref true
let budget = ref 256
6 changes: 4 additions & 2 deletions interpreter/main/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ let argspec = Arg.align
" read script from file";
"-o", Arg.String (fun file -> add_arg ("(output " ^ quote file ^ ")")),
" write module to file";
"-b", Arg.Int (fun n -> Flags.budget := n),
" configure call depth budget (default is " ^ string_of_int !Flags.budget ^ ")";
"-w", Arg.Int (fun n -> Flags.width := n),
" configure output width (default is 80)";
" configure output width (default is " ^ string_of_int !Flags.width ^ ")";
"-s", Arg.Set Flags.print_sig, " show module signatures";
"-u", Arg.Set Flags.unchecked, " unchecked, do not perform validation";
"-h", Arg.Clear Flags.harness, " exclude harness for JS conversion";
"-j", Arg.Clear Flags.harness, " exclude harness for JS conversion";
"-d", Arg.Set Flags.dry, " dry, do not run program";
"-t", Arg.Set Flags.trace, " trace execution";
"-v", Arg.Unit banner, " show version"
Expand Down
6 changes: 0 additions & 6 deletions interpreter/meta/jslib/bsconfig.json

This file was deleted.

97 changes: 0 additions & 97 deletions interpreter/meta/jslib/build.sh

This file was deleted.

9 changes: 0 additions & 9 deletions interpreter/meta/jslib/wasm.ml

This file was deleted.

26 changes: 26 additions & 0 deletions interpreter/meta/jslib/wast.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
(* Implements a wrapper library that allows the use of the reference
* interpreter's encode/decode functionality in JavaScript.
*)
open Js_of_ocaml

let _ =
Js.export "WebAssemblyText"
(object%js (_self)

method encode (s : Js.js_string Js.t) : (Typed_array.arrayBuffer Js.t) =
let def = Parse.string_to_module (Js.to_string s) in
let bs =
match def.Source.it with
| Script.Textual m -> (Encode.encode m)
| Script.Encoded (_, bs) -> bs
| Script.Quoted (_, _) -> failwith "Unsupported" in
let buf = new%js Typed_array.arrayBuffer (String.length bs) in
let u8arr = new%js Typed_array.uint8Array_fromBuffer buf in
String.iteri (fun i c -> Typed_array.set u8arr i (int_of_char c)) bs; buf

method decode (buf : Typed_array.arrayBuffer Js.t) width : (Js.js_string Js.t) =
let s = Typed_array.String.of_uint8Array (new%js Typed_array.uint8Array_fromBuffer buf) in
let m = Decode.decode "(decode)" s in
Js.string (Sexpr.to_string width (Arrange.module_ m))

end)
2 changes: 1 addition & 1 deletion test/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def ensure_wasm_executable(path_to_wasm):
def convert_one_wast_file(inputs):
wast_file, js_file = inputs
print('Compiling {} to JS...'.format(wast_file))
return run(WASM_EXEC, wast_file, '-h', '-o', js_file)
return run(WASM_EXEC, wast_file, '-j', '-o', js_file)

def convert_wast_to_js(out_js_dir):
"""Compile all the wast files to JS and store the results in the JS dir."""
Expand Down
Loading

0 comments on commit d4f766c

Please sign in to comment.