Skip to content

Commit a8539bb

Browse files
committed
Initial commit
1 parent 0b2bda0 commit a8539bb

15 files changed

+798
-0
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Logs
2+
*.log
3+
4+
# Dependency directories
5+
node_modules/

package.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "wasm-run",
3+
"version": "0.1.0",
4+
"description": "Run arbitrary WASM/WASI files",
5+
"author": "Volodymyr Shymanskyy",
6+
"main": "wasm-run.js",
7+
"license": "MIT",
8+
"scripts": {
9+
"test": "echo \"Error: no test specified\" && exit 1"
10+
},
11+
"bin": {
12+
"wasm-run": "wasm-run.js"
13+
},
14+
"dependencies": {
15+
"binaryen": "^101.0.0",
16+
"chalk": "^4.1.1",
17+
"restructure": "^0.5.4",
18+
"yargs": "^16.2.0"
19+
}
20+
}

test/fib32.wasm

62 Bytes
Binary file not shown.

test/fib32.wat

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
(module
2+
(export "fib" (func $fib)) ;; fib exported function
3+
(func $fib (param $n i32) (result i32)
4+
(if
5+
(i32.lt_u
6+
(get_local $n)
7+
(i32.const 2)
8+
)
9+
(return
10+
(get_local $n)
11+
)
12+
)
13+
(return
14+
(i32.add
15+
(call $fib
16+
(i32.sub
17+
(get_local $n)
18+
(i32.const 2)
19+
)
20+
)
21+
(call $fib
22+
(i32.sub
23+
(get_local $n)
24+
(i32.const 1)
25+
)
26+
)
27+
)
28+
)
29+
)
30+
)

test/fib64.wasm

62 Bytes
Binary file not shown.

test/mal/core.mal

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
(def! _macro? (fn* [x]
2+
(if (map? x)
3+
(contains? x :__MAL_MACRO__)
4+
false)))
5+
6+
(def! core_ns
7+
[['= =]
8+
['throw throw]
9+
['nil? nil?]
10+
['true? true?]
11+
['false? false?]
12+
['number? number?]
13+
['string? string?]
14+
['symbol symbol]
15+
['symbol? symbol?]
16+
['keyword keyword]
17+
['keyword? keyword?]
18+
['fn? fn?]
19+
['macro? _macro?]
20+
21+
['pr-str pr-str]
22+
['str str]
23+
['prn prn]
24+
['println println]
25+
['readline readline]
26+
['read-string read-string]
27+
['slurp slurp]
28+
['< <]
29+
['<= <=]
30+
['> >]
31+
['>= >=]
32+
['+ +]
33+
['- -]
34+
['* *]
35+
['/ /]
36+
['time-ms time-ms]
37+
38+
['list list]
39+
['list? list?]
40+
['vector vector]
41+
['vector? vector?]
42+
['hash-map hash-map]
43+
['map? map?]
44+
['assoc assoc]
45+
['dissoc dissoc]
46+
['get get]
47+
['contains? contains?]
48+
['keys keys]
49+
['vals vals]
50+
51+
['sequential? sequential?]
52+
['cons cons]
53+
['concat concat]
54+
['vec vec]
55+
['nth nth]
56+
['first first]
57+
['rest rest]
58+
['empty? empty?]
59+
['count count]
60+
['apply apply]
61+
['map map]
62+
63+
['conj conj]
64+
['seq seq]
65+
66+
['with-meta with-meta]
67+
['meta meta]
68+
['atom atom]
69+
['atom? atom?]
70+
['deref deref]
71+
['reset! reset!]
72+
['swap! swap!]])

test/mal/env.mal

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
(def! bind-env (fn* [env b e]
2+
(if (empty? b)
3+
env
4+
(let* [b0 (first b)]
5+
(if (= '& b0)
6+
(assoc env (str (nth b 1)) e)
7+
(bind-env (assoc env (str b0) (first e)) (rest b) (rest e)))))))
8+
9+
(def! new-env (fn* [& args]
10+
(if (<= (count args) 1)
11+
(atom {:outer (first args)})
12+
(atom (apply bind-env {:outer (first args)} (rest args))))))
13+
14+
(def! env-find (fn* [env k]
15+
(env-find-str env (str k))))
16+
17+
(def! env-find-str (fn* [env ks]
18+
(if env
19+
(let* [data @env]
20+
(if (contains? data ks)
21+
env
22+
(env-find-str (get data :outer) ks))))))
23+
24+
(def! env-get (fn* [env k]
25+
(let* [ks (str k)
26+
e (env-find-str env ks)]
27+
(if e
28+
(get @e ks)
29+
(throw (str "'" ks "' not found"))))))
30+
31+
(def! env-set (fn* [env k v]
32+
(do
33+
(swap! env assoc (str k) v)
34+
v)))

test/mal/mal-fib.mal

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
;; Compute a Fibonacci number with two recursions.
2+
(def! fib
3+
(fn* [n] ; non-negative number
4+
(if (<= n 1)
5+
n
6+
(+ (fib (- n 1)) (fib (- n 2))))))
7+
8+
(println (fib (read-string (first *ARGV*))))

test/mal/mal.mal

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
(load-file "./env.mal")
2+
(load-file "./core.mal")
3+
4+
;; read
5+
(def! READ read-string)
6+
7+
8+
;; eval
9+
10+
(def! qq-loop (fn* [elt acc]
11+
(if (if (list? elt) (= (first elt) 'splice-unquote)) ; 2nd 'if' means 'and'
12+
(list 'concat (nth elt 1) acc)
13+
(list 'cons (QUASIQUOTE elt) acc))))
14+
(def! qq-foldr (fn* [xs]
15+
(if (empty? xs)
16+
(list)
17+
(qq-loop (first xs) (qq-foldr (rest xs))))))
18+
(def! QUASIQUOTE (fn* [ast]
19+
(cond
20+
(vector? ast) (list 'vec (qq-foldr ast))
21+
(map? ast) (list 'quote ast)
22+
(symbol? ast) (list 'quote ast)
23+
(not (list? ast)) ast
24+
(= (first ast) 'unquote) (nth ast 1)
25+
"else" (qq-foldr ast))))
26+
27+
(def! MACROEXPAND (fn* [ast env]
28+
(let* [a0 (if (list? ast) (first ast))
29+
e (if (symbol? a0) (env-find env a0))
30+
m (if e (env-get e a0))]
31+
(if (_macro? m)
32+
(MACROEXPAND (apply (get m :__MAL_MACRO__) (rest ast)) env)
33+
ast))))
34+
35+
(def! eval-ast (fn* [ast env]
36+
;; (do (prn "eval-ast" ast "/" (keys env)) )
37+
(cond
38+
(symbol? ast) (env-get env ast)
39+
40+
(list? ast) (map (fn* [exp] (EVAL exp env)) ast)
41+
42+
(vector? ast) (vec (map (fn* [exp] (EVAL exp env)) ast))
43+
44+
(map? ast) (apply hash-map
45+
(apply concat
46+
(map (fn* [k] [k (EVAL (get ast k) env)])
47+
(keys ast))))
48+
49+
"else" ast)))
50+
51+
(def! LET (fn* [env binds form]
52+
(if (empty? binds)
53+
(EVAL form env)
54+
(do
55+
(env-set env (first binds) (EVAL (nth binds 1) env))
56+
(LET env (rest (rest binds)) form)))))
57+
58+
(def! EVAL (fn* [ast env]
59+
;; (do (prn "EVAL" ast "/" (keys @env)) )
60+
(let* [ast (MACROEXPAND ast env)]
61+
(if (not (list? ast))
62+
(eval-ast ast env)
63+
64+
;; apply list
65+
(let* [a0 (first ast)]
66+
(cond
67+
(empty? ast)
68+
ast
69+
70+
(= 'def! a0)
71+
(env-set env (nth ast 1) (EVAL (nth ast 2) env))
72+
73+
(= 'let* a0)
74+
(LET (new-env env) (nth ast 1) (nth ast 2))
75+
76+
(= 'quote a0)
77+
(nth ast 1)
78+
79+
(= 'quasiquoteexpand a0)
80+
(QUASIQUOTE (nth ast 1))
81+
82+
(= 'quasiquote a0)
83+
(EVAL (QUASIQUOTE (nth ast 1)) env)
84+
85+
(= 'defmacro! a0)
86+
(env-set env (nth ast 1) (hash-map :__MAL_MACRO__
87+
(EVAL (nth ast 2) env)))
88+
89+
(= 'macroexpand a0)
90+
(MACROEXPAND (nth ast 1) env)
91+
92+
(= 'try* a0)
93+
(if (< (count ast) 3)
94+
(EVAL (nth ast 1) env)
95+
(try*
96+
(EVAL (nth ast 1) env)
97+
(catch* exc
98+
(let* [a2 (nth ast 2)]
99+
(EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc]))))))
100+
101+
(= 'do a0)
102+
(let* [el (eval-ast (rest ast) env)]
103+
(nth el (- (count el) 1)))
104+
105+
(= 'if a0)
106+
(if (EVAL (nth ast 1) env)
107+
(EVAL (nth ast 2) env)
108+
(if (> (count ast) 3)
109+
(EVAL (nth ast 3) env)))
110+
111+
(= 'fn* a0)
112+
(fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args)))
113+
114+
"else"
115+
(let* [el (eval-ast ast env)]
116+
(apply (first el) (rest el)))))))))
117+
118+
119+
;; print
120+
(def! PRINT pr-str)
121+
122+
;; repl
123+
(def! repl-env (new-env))
124+
(def! rep (fn* [strng]
125+
(PRINT (EVAL (READ strng) repl-env))))
126+
127+
;; core.mal: defined directly using mal
128+
(map (fn* [data] (apply env-set repl-env data)) core_ns)
129+
(env-set repl-env 'eval (fn* [ast] (EVAL ast repl-env)))
130+
(env-set repl-env '*ARGV* (rest *ARGV*))
131+
132+
;; core.mal: defined using the new language itself
133+
(rep (str "(def! *host-language* \"" *host-language* "-mal\")"))
134+
(rep "(def! not (fn* [a] (if a false true)))")
135+
(rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))")
136+
(rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))")
137+
138+
;; repl loop
139+
(def! repl-loop (fn* [line]
140+
(if line
141+
(do
142+
(if (not (= "" line))
143+
(try*
144+
(println (rep line))
145+
(catch* exc
146+
(println "Uncaught exception:" exc))))
147+
(repl-loop (readline "mal-user> "))))))
148+
149+
;; main
150+
(if (empty? *ARGV*)
151+
(repl-loop "(println (str \"Mal [\" *host-language* \"]\"))")
152+
(rep (str "(load-file \"" (first *ARGV*) "\")")))

test/mal/mal.wasm

14.6 KB
Binary file not shown.

test/swap.wasm

236 Bytes
Binary file not shown.

test/swap.wat

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
(module
2+
(type $t0 (func (param i32 i32) (result i32 i32)))
3+
(type $t1 (func (param i64 i64) (result i64 i64)))
4+
(type $t2 (func (param f32 f32) (result f32 f32)))
5+
(type $t3 (func (param f64 f64) (result f64 f64)))
6+
(func $swap_i32 (export "swap_i32") (type $t0) (param $p0 i32) (param $p1 i32) (result i32 i32)
7+
(local.get $p1)
8+
(local.get $p0))
9+
(func $swap_i64 (export "swap_i64") (type $t1) (param $p0 i64) (param $p1 i64) (result i64 i64)
10+
(local.get $p1)
11+
(local.get $p0))
12+
(func $swap_f32 (export "swap_f32") (type $t2) (param $p0 f32) (param $p1 f32) (result f32 f32)
13+
(local.get $p1)
14+
(local.get $p0))
15+
(func $swap_f64 (export "swap_f64") (type $t3) (param $p0 f64) (param $p1 f64) (result f64 f64)
16+
(local.get $p1)
17+
(local.get $p0))
18+
)
56.2 KB
Binary file not shown.

test/wasi/test-wasi-unstable.wasm

44.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)