Skip to content

Commit

Permalink
Add support for WebAssembly target (#4)
Browse files Browse the repository at this point in the history
[This pull request against
MLton](MLton/mlton#550) enables compiling to
WebAssembly, so that twelf can be run from, e.g. inside a web browser.

A demo can be seen at:
https://jcreedcmu.github.io/twelf-wasm/

Test plan:
- ensure that the make target `twelf-server-mlton` still produces a
twelf-server binary
- ensure that the make target `wasi` produces
`bin/twelf.wasm`, when an appropriate version of `mlton` is installed.
Detailed instructions for building follow. Comments on the above pull
request have more details pertaining to build and install of GMP.

Checked out
https://github.com/agoode/mlton/tree/wasm2
at commit
MLton/mlton@d2b9e5d
put into
`$BUILD/dev-mlton`

and then did the following:

```
MLTON=$BUILD/mlton-wasm2-INSTALL

cd $BUILD/dev-mlton
make clean
make CC=$WASISDK/bin/clang \
     AR=$WASISDK/bin/ar \
     RANLIB=$WASISDK/bin/ranlib \
     TARGET_OS=wasi \
     TARGET_ARCH=wasm32 \
     TARGET=wasm32-unknown-wasi \
     WITH_GMP_DIR=$BUILD/gmp-wasi-INSTALL \
     PREFIX=$MLTON \
     dirs runtime install-runtime

cd $BUILD/dev-mlton
make clean
make all
make PREFIX=$MLTON install

cd $BUILD/twelf
mlton=$BUILD/mlton-wasm2-INSTALL/bin/mlton make wasi
```

Co-authored-by: Jason Reed <[email protected]>
  • Loading branch information
jcreedcmu and Jason Reed authored Feb 29, 2024
1 parent 7b3f3db commit d357dbe
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 5 deletions.
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
polyml = poly
smlnj = sml
oldnj = sml
mlton = mlton -default-ann 'nonexhaustiveMatch ignore'
mlton ?= mlton -default-ann 'nonexhaustiveMatch ignore'
make = make

twelfdir = `pwd`
Expand Down Expand Up @@ -55,6 +55,14 @@ twelf-server-mlton:
fi; \
$(mlton) -output bin/$(twelfserver) build/$${cmfileid}

.PHONY: twelf-lib-mlton-wasi
twelf-lib-mlton-wasi:
$(mlton) -target wasm32-unknown-wasi \
-format libexecutable \
-output bin/twelf.wasm \
-default-ann 'allowFFI true' \
build/twelf-lib-mlton-wasi.mlb

.PHONY: twelf-server-smlnj
twelf-server-smlnj:
$(smlnj) < build/twelf-server-smlnj.sml ;
Expand Down Expand Up @@ -82,6 +90,8 @@ smlnj : twelf-server-announce buildid twelf-server-smlnj twelf-emacs

mlton : twelf-server-announce buildid twelf-server-mlton twelf-emacs

wasi : twelf-server-announce buildid twelf-lib-mlton-wasi

.PHONY: twelf-regression check
twelf-regression: buildid
$(mlton) -output bin/twelf-regression TEST/mlton-regression.mlb
Expand Down
3 changes: 0 additions & 3 deletions build/twelf-core-mlton.mlb
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,3 @@ $(SML_LIB)/basis/sml-nj.mlb
../src/frontend/unknownexn.fun
../src/frontend/unknownexn-smlnj.sml
../src/frontend/frontend.sml
../src/server/sigint.sig
../src/server/sigint-mlton.sml
../src/server/server.sml
3 changes: 3 additions & 0 deletions build/twelf-lib-mlton-wasi.mlb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

twelf-core-mlton.mlb
twelf-wasi.sml
4 changes: 3 additions & 1 deletion build/twelf-server-mlton.mlb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

twelf-core-mlton.mlb
../src/server/sigint.sig
../src/server/sigint-mlton.sml
../src/server/server.sml
twelf-server-mlton.sml

37 changes: 37 additions & 0 deletions build/twelf-wasi.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
(*
*
* This file makes twelf into a library that can be called directly from WASI Preview 1,
* which specifies an API by which WebAssembly programs can interact with the outside world.
* It is somewhat like POSIX.
*
* https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md
*
* It provides two entry points:
*
* allocate : int -> CharArray.array
* expects to be called with the length of the twelf source string
* we want to evaluate, so that the sml side can allocate a buffer.
* The caller is then expected to write the twelf source into the
* buffer returned.
*
* execute : unit -> unit
* has the side effect of loading the string found in the allocated
* buffer, which will result in various print statements. The caller
* is expected to implement the WASI fd_write endpoint so that they
* can see the output so printed.
*)

val bref: CharArray.array option ref = ref NONE

val e = _export "allocate": (int -> CharArray.array) -> unit;
val _ = e (fn size =>
let
val b = CharArray.tabulate (size, fn _ => Char.chr 0)
in
bref := SOME b; b
end)

val e = _export "execute": (unit -> unit) -> unit;
val _ = e (fn () => (case !bref of
NONE => print "No input buffer allocated"
| SOME b => (Twelf.loadString (CharArray.vector b); ())))
10 changes: 10 additions & 0 deletions src/server/sigint-noop.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
structure SigINT :> SIGINT =
struct

fun interruptLoop (loop:unit -> unit) =
let
in
loop ()
end

end;

0 comments on commit d357dbe

Please sign in to comment.