Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
309f722712 | ||
|
|
31cc2b1720 | ||
|
|
3cdae9eab4 | ||
|
|
c6036ffbb4 | ||
|
|
6ebe92e7cd | ||
|
|
0f9ba3c51e | ||
|
|
10bd6b733a | ||
|
|
d1588bd917 | ||
|
|
c495fc064a | ||
|
|
ac39175767 | ||
|
|
31c610db34 | ||
|
|
1ec3d35282 | ||
|
|
9f37d10e4f | ||
|
|
ba5dc401d9 | ||
|
|
bc599df65f | ||
|
|
f26ac50d4e | ||
|
|
3196d8db84 | ||
|
|
75e6c963c7 | ||
|
|
25f1f008bd | ||
|
|
276c2c1249 | ||
|
|
03797d573b | ||
|
|
0df7280236 | ||
|
|
a09c00badd | ||
|
|
e7c0ae9161 | ||
|
|
5ccb3f3e1a | ||
|
|
9cb169f9b8 | ||
|
|
c0a44c89b4 | ||
|
|
49292d5d01 | ||
|
|
679cc076ad | ||
|
|
8048573cd8 | ||
|
|
bbb5d6e99f | ||
|
|
1f40120740 | ||
|
|
196dd0d1b3 | ||
|
|
009a154a6e | ||
|
|
21b9f0e69d | ||
|
|
87baed9efc | ||
|
|
796b967686 | ||
|
|
99d9e460fc | ||
|
|
c9eb8f6f85 | ||
|
|
030b36cd98 | ||
|
|
bf2fc08ec4 | ||
|
|
950d123760 | ||
|
|
8a20c4f4aa | ||
|
|
d4c1385225 | ||
|
|
2ceefdb3df | ||
|
|
7c0642655f | ||
|
|
bf5595f185 | ||
|
|
bbcc924b34 | ||
|
|
73063d2b2c | ||
|
|
4beeb7c4cd | ||
|
|
c340ede84f | ||
|
|
66386cda64 | ||
|
|
b234a52d4b | ||
|
|
6ff01a8607 | ||
|
|
5200932944 | ||
|
|
f9ed1274d9 | ||
|
|
6c29f3779a | ||
|
|
5a173a7a3b | ||
|
|
b329a42b71 | ||
|
|
25ba8c03b8 | ||
|
|
fc8cf263aa | ||
|
|
c5f9bf1850 | ||
|
|
94b1a5fb45 | ||
|
|
ca1b53f3d1 | ||
|
|
eb51f4fff7 | ||
|
|
8bdbfafb9c | ||
|
|
6949ff7fdf | ||
|
|
a73b3ed89b | ||
|
|
1c13de4153 | ||
|
|
d91e059a84 | ||
|
|
c4bcf38374 | ||
|
|
745277ed1a | ||
|
|
c3c4866fa8 | ||
|
|
80164acb96 | ||
|
|
1c7322614c | ||
|
|
81a136fcf2 | ||
|
|
be1d7566f4 | ||
|
|
fab29f6fce | ||
|
|
7ab98341b9 | ||
|
|
2f471ae4b1 | ||
|
|
57defed077 | ||
|
|
0ba49ed85c | ||
|
|
33fb0f831c | ||
|
|
8120e21eae | ||
|
|
6774c08efb | ||
|
|
530a6934ba | ||
|
|
e2e287079c | ||
|
|
a97a0ad7bb | ||
|
|
9334373f96 | ||
|
|
aa5b45ec76 | ||
|
|
85d34883a6 | ||
|
|
f09a63f11c | ||
|
|
2dffdf112c |
+16
-2
@@ -1,5 +1,19 @@
|
||||
((haskell-cabal-mode
|
||||
((haskell-mode
|
||||
. ((eval
|
||||
. (progn (add-to-list 'haskell-font-lock-quasi-quote-modes
|
||||
'("cps" . scheme-mode))
|
||||
(add-to-list 'haskell-font-lock-quasi-quote-modes
|
||||
'("scm" . scheme-mode))))))
|
||||
(haskell-cabal-mode
|
||||
. ((eval
|
||||
. (progn (defun apply-cabal-fmt-h ()
|
||||
(haskell-mode-buffer-apply-command "cabal-fmt"))
|
||||
(add-hook 'before-save-hook #'apply-cabal-fmt-h nil t))))))
|
||||
(add-hook 'before-save-hook #'apply-cabal-fmt-h nil t)))))
|
||||
(scheme-mode
|
||||
. ((eval . (dolist (s '(kappa κ prim))
|
||||
(put s 'scheme-indent-function 1)))))
|
||||
(nil
|
||||
. ((eval
|
||||
. (progn (defun display-ansi ()
|
||||
(interactive)
|
||||
(ansi-color-apply-on-region (point-min) (point-max))))))))
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
use flake
|
||||
watch_file gyehoek.cabal cabal.project
|
||||
PATH_add $(dirname $(cabal list-bin gyehoek))
|
||||
|
||||
+2
-1
@@ -8,4 +8,5 @@ dist-newstyle
|
||||
*.tix
|
||||
.direnv
|
||||
result
|
||||
play/
|
||||
play/
|
||||
trace.html
|
||||
@@ -1,3 +1,3 @@
|
||||
# gyehoek-hs (계획)
|
||||
# 계획
|
||||
|
||||
a (wip) toy compiler for a Scheme-like language. currently targetting [QBE](https://c9x.me/compile/). nabbing from GHC and GNU Guile.
|
||||
a WIP compiler for R⁷RS Scheme targeting WebAssembly.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
packages: *.cabal
|
||||
tests: True
|
||||
-- required for doctest-parallel
|
||||
write-ghc-environment-files: always
|
||||
|
||||
-- https://github.com/martijnbastiaan/doctest-parallel/pull/66
|
||||
allow-older: Cabal:process
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
#+title: ABI
|
||||
|
||||
largely based on the Guile Hoot's [[https://codeberg.org/spritely/hoot/src/branch/main/design/ABI.md][ABI]].
|
||||
|
||||
* calling convention
|
||||
|
||||
** non-tail calls
|
||||
|
||||
- set the global variable ~$current-closure~ to the callee's closure.
|
||||
- load arguments into globals ~$arg0~, ~$arg1~, ~$arg2~, …
|
||||
- push return continuation onto ~$cont-stack~
|
||||
|
||||
* scratchpad
|
||||
|
||||
#+begin_src scheme
|
||||
;; Scheme source
|
||||
(define (silly f g h x)
|
||||
(f (h x) (g x)))
|
||||
|
||||
|
||||
;; continuation-passing style
|
||||
(define (silly f g h x ktail)
|
||||
(h x (κ (x0)
|
||||
(g x (κ (x1)
|
||||
(f x0 x1 ktail))))))
|
||||
|
||||
;; with explicit stacks
|
||||
(define (silly)
|
||||
(define f (pop!))
|
||||
(define g (pop!))
|
||||
(define h (pop!))
|
||||
(define x (pop!))
|
||||
(define ktail (pop-cont!))
|
||||
(push-cont! (κ (x0)
|
||||
(define x* (pop!))
|
||||
(define g* (pop!))
|
||||
(push-cont! (κ (x1)
|
||||
(define f* (pop!))
|
||||
(define x0* (pop!))
|
||||
(push-cont! ktail)
|
||||
(push! x0*)
|
||||
(push! x1)
|
||||
(call! f)))
|
||||
(push! x*)
|
||||
(call! g)))
|
||||
(push! x)
|
||||
(call! h))
|
||||
#+end_src
|
||||
|
||||
** fac
|
||||
|
||||
*** Scheme source
|
||||
|
||||
#+begin_src scheme
|
||||
(define fac
|
||||
(λ (n)
|
||||
(if (zero? n)
|
||||
1
|
||||
(* n (fac (- n 1))))))
|
||||
|
||||
(fac 3)
|
||||
#+end_src
|
||||
|
||||
*** CPS
|
||||
|
||||
#+begin_src scheme
|
||||
(define fac
|
||||
(λ (n ktail)
|
||||
(zero? n (κ (x0)
|
||||
(if x0
|
||||
1
|
||||
(- n 1
|
||||
(κ (x1)
|
||||
(fac x1
|
||||
(κ (x2)
|
||||
(* n x2 ktail))))))))))
|
||||
|
||||
(fac 3 halt)
|
||||
|
||||
#+end_src
|
||||
|
||||
*** tailified
|
||||
|
||||
#+begin_src scheme
|
||||
(define (fac-k1)
|
||||
(define n (pop!))
|
||||
(define x2 (pop!))
|
||||
(define x3 (* n x2))
|
||||
(define ktail (pop-cont!))
|
||||
(push! x3)
|
||||
(call! ktail))
|
||||
|
||||
(define (fac-k0)
|
||||
(define x0 (pop!))
|
||||
(define n (pop!))
|
||||
(if x0
|
||||
(begin (define ktail (pop-cont!))
|
||||
(push! 1)
|
||||
(call! ktail))
|
||||
(begin (define x1 (- n 1))
|
||||
(push! x1)
|
||||
(push-cont! fac-k1)
|
||||
(call! fac))))
|
||||
|
||||
(define (fac)
|
||||
(define n (pop!))
|
||||
(push! n)
|
||||
(push-cont! fac-k0)
|
||||
(push! n)
|
||||
(call! zero?))
|
||||
|
||||
(push! 3)
|
||||
(push-cont! halt)
|
||||
(call! fac)
|
||||
#+end_src
|
||||
|
||||
evaluation of ~(fac 0)~:
|
||||
|
||||
#+begin_src scheme
|
||||
(push! 0) ; [] []
|
||||
(push-cont! halt) ; [0] []
|
||||
(call! fac) ; [0] [halt]
|
||||
(define n (pop!)) ; [0] [halt]
|
||||
(push! n) ; [] [halt]
|
||||
(push-cont! fac-k0) ; [0] [halt]
|
||||
(push! n) ; [0] [halt fac-k0]
|
||||
(call! zero?) ; [0 0] [halt fac-k0]
|
||||
#<internals of zero?> ; [0 0] [halt fac-k0]
|
||||
(define x0 (pop!)) ; [0 #t] [halt]
|
||||
(define n (pop!)) ; [0] [halt]
|
||||
(define ktail (pop-cont!)) ; [] [halt]
|
||||
(push! 1) ; [] []
|
||||
(call! ktail) ; [1] []
|
||||
#+end_src
|
||||
|
||||
evaluation of ~(fac 3)~
|
||||
|
||||
#+begin_src scheme
|
||||
(push! 3) ; [] []
|
||||
(push-cont! halt) ; [3] []
|
||||
(call! fac) ; [3] [halt]
|
||||
|
||||
(define n (pop!)) ; [3] [halt]
|
||||
(push! n) ; [] [halt]
|
||||
(push-cont! fac-k0) ; [3] [halt]
|
||||
(push! n) ; [3] [halt fac-k0]
|
||||
(call! zero?) ; [3 3] [halt fac-k0]
|
||||
#<internals of zero?> ; [3 3] [halt fac-k0]
|
||||
(define x0 (pop!)) ; [3 #f] [halt]
|
||||
(define n (pop!)) ; [3] [halt]
|
||||
(define x1 (- n 1)) ; [] [halt]
|
||||
(push! n) ; [] [halt]
|
||||
(push! x1) ; [3] [halt]
|
||||
(push-cont! fac-k1) ; [3 2] [halt]
|
||||
(call! fac) ; [3 2] [halt fac-k1]
|
||||
|
||||
(define n (pop!)) ; [3 2] [halt fac-k1]
|
||||
(push! n) ; [3 ] [halt fac-k1]
|
||||
(push-cont! fac-k0) ; [3 2] [halt fac-k1]
|
||||
(push! n) ; [3 2] [halt fac-k1 fac-k0]
|
||||
(call! zero?) ; [3 2 2] [halt fac-k1 fac-k0]
|
||||
#<internals of zero?> ; [3 2 2] [halt fac-k1 fac-k0]
|
||||
(define x0 (pop!)) ; [3 2 #f] [halt fac-k1]
|
||||
(define n (pop!)) ; [3 2] [halt fac-k1]
|
||||
(define x1 (- n 1)) ; [3] [halt fac-k1]
|
||||
(push! n) ; [3] [halt fac-k1]
|
||||
(push! x1) ; [3 2] [halt fac-k1]
|
||||
(push-cont! fac-k1) ; [3 2 1] [halt fac-k1]
|
||||
(call! fac) ; [3 2 1] [halt fac-k1 fac-k1]
|
||||
|
||||
(define n (pop!)) ; [3 2 1] [halt fac-k1 fac-k1]
|
||||
(push! n) ; [3 2] [halt fac-k1 fac-k1]
|
||||
(push-cont! fac-k0) ; [3 2 1] [halt fac-k1 fac-k1]
|
||||
(push! n) ; [3 2 1] [halt fac-k1 fac-k1 fac-k0]
|
||||
(call! zero?) ; [3 2 1 1] [halt fac-k1 fac-k1 fac-k0]
|
||||
#<internals of zero?> ; [3 2 1 1] [halt fac-k1 fac-k1 fac-k0]
|
||||
(define x0 (pop!)) ; [3 2 1 #f] [halt fac-k1 fac-k1]
|
||||
(define n (pop!)) ; [3 2 1] [halt fac-k1 fac-k1]
|
||||
(define x1 (- n 1)) ; [3 2] [halt fac-k1 fac-k1]
|
||||
(push! n) ; [3 2] [halt fac-k1]
|
||||
(push! x1) ; [3 2 1] [halt fac-k1 fac-k1]
|
||||
(push-cont! fac-k1) ; [3 2 1 0] [halt fac-k1 fac-k1]
|
||||
(call! fac) ; [3 2 1 0] [halt fac-k1 fac-k1 fac-k1]
|
||||
|
||||
(define n (pop!)) ; [3 2 1 0] [halt fac-k1 fac-k1 fac-k1]
|
||||
(push! n) ; [3 2 1] [halt fac-k1 fac-k1 fac-k1]
|
||||
(push-cont! fac-k0) ; [3 2 1 0] [halt fac-k1 fac-k1 fac-k1]
|
||||
(push! n) ; [3 2 1 0] [halt fac-k1 fac-k1 fac-k1 fac-k0]
|
||||
(call! zero?) ; [3 2 1 0 0] [halt fac-k1 fac-k1 fac-k1 fac-k0]
|
||||
#<internals of zero?> ; [3 2 1 0 0] [halt fac-k1 fac-k1 fac-k1 fac-k0]
|
||||
(define x0 (pop!)) ; [3 2 1 0 #t] [halt fac-k1 fac-k1 fac-k1]
|
||||
(define n (pop!)) ; [3 2 1 0] [halt fac-k1 fac-k1 fac-k1]
|
||||
(define ktail (pop-cont!)) ; [3 2 1] [halt fac-k1 fac-k1 fac-k1]
|
||||
(push! 1) ; [3 2 1 1] [halt fac-k1 fac-k1]
|
||||
(call! ktail) ; [3 2 1 1] [halt fac-k1 fac-k1]
|
||||
|
||||
(define n (pop!)) ; [3 2 1 1] [halt fac-k1 fac-k1]
|
||||
(define x2 (pop!)) ; [3 2 1] [halt fac-k1 fac-k1]
|
||||
(define x3 (* n x2)) ; [3 2] [halt fac-k1 fac-k1]
|
||||
(define ktail (pop-cont!)) ; [3 2] [halt fac-k1 fac-k1]
|
||||
(push! x3) ; [3 2] [halt fac-k1]
|
||||
(call! ktail) ; [3 2 1] [halt fac-k1]
|
||||
|
||||
(define n (pop!)) ; [3 2 1] [halt fac-k1]
|
||||
(define x2 (pop!)) ; [3 2] [halt fac-k1]
|
||||
(define x3 (* n x2)) ; [3] [halt fac-k1]
|
||||
(define ktail (pop-cont!)) ; [3] [halt fac-k1]
|
||||
(push! x3) ; [3] [halt]
|
||||
(call! ktail) ; [3 2] [halt]
|
||||
|
||||
(define n (pop!)) ; [3 2] [halt]
|
||||
(define x2 (pop!)) ; [3] [halt]
|
||||
(define x3 (* n x2)) ; [] [halt]
|
||||
(define ktail (pop-cont!)) ; [] [halt]
|
||||
(push! x3) ; [] []
|
||||
(call! ktail) ; [6] []
|
||||
;; => (halt 6)
|
||||
#+end_src
|
||||
@@ -0,0 +1,165 @@
|
||||
#+title: closure-conversion
|
||||
|
||||
the closure-conversion phase makes closed-over variables explicit by addition of the primitive ~make-closure~, taking a code pointer (in the CPS language, bare lambda) and the environment.
|
||||
|
||||
nice testable properties of closure-converted code:
|
||||
- code pointers only appear in function position
|
||||
- no function has free variables
|
||||
|
||||
multiple ~env-ref~ calls could probably be replaced with a primitive that loads the entire environment at once, returning multiple variables.
|
||||
|
||||
* scratchpad
|
||||
|
||||
** example
|
||||
|
||||
#+caption: scheme source
|
||||
#+begin_src scheme
|
||||
(letrec ((curried-add (λ (n)
|
||||
(λ (m)
|
||||
(+ n m)))))
|
||||
((curried-add 3) 4))
|
||||
#+end_src
|
||||
|
||||
#+caption: cps
|
||||
#+begin_src scheme
|
||||
(letrec ((curried-add
|
||||
(λ (n ktail0)
|
||||
(letrec ((curried-add-in
|
||||
(λ (m ktail1)
|
||||
(prim (+ n m)
|
||||
(κ (x0) (continue ktail1 x0))))))
|
||||
(continue ktail0 curried-add-in)))))
|
||||
(letrec ((k0 (κ (adder) (adder 4 halt))))
|
||||
(curried-add 3 k0)))
|
||||
#+end_src
|
||||
|
||||
#+caption: closure-converted
|
||||
#+begin_src scheme
|
||||
(letrec ((curried-add
|
||||
(λ (n ktail0)
|
||||
(letrec ((curried-add-in-code
|
||||
(λ (env m ktail1)
|
||||
(prim (env-ref 0 env)
|
||||
(κ (n)
|
||||
(prim (+ n m)
|
||||
(κ (x0) (continue ktail1 x0))))))))
|
||||
(prim (make-closure curried-add-in-code n)
|
||||
(κ (curried-add-in)
|
||||
(continue ktail0 curried-add-in)))))))
|
||||
(letrec ((k0 (κ (adder-closure)
|
||||
(prim (closure-code adder-closure)
|
||||
(κ (adder)
|
||||
(adder adder-closure 4 halt))))))
|
||||
(curried-add 3 k0)))
|
||||
#+end_src
|
||||
|
||||
** wasm
|
||||
|
||||
#+begin_src scheme
|
||||
(letrec ((make-adder
|
||||
(lambda (n)
|
||||
(lambda (x)
|
||||
(+ n x)))))
|
||||
((make-adder 3) 2))
|
||||
#+end_src
|
||||
|
||||
#+begin_src scheme
|
||||
(define add-code
|
||||
(lambda (n env)
|
||||
(+ n (env-ref env 'x))))
|
||||
|
||||
(define make-adder-code
|
||||
(lambda (n)
|
||||
(make-closure add-code ('x n))))
|
||||
|
||||
(define make-adder (make-closure make-adder-code))
|
||||
|
||||
(apply-closure (apply-closure make-addder 3) 2)
|
||||
#+end_src
|
||||
|
||||
#+begin_src wat
|
||||
(module
|
||||
(type $heap-object (sub (struct (field $hash (mut i32)))))
|
||||
(type $closure (sub $heap-object
|
||||
(struct (field $hash (mut i32))
|
||||
(field $code (ref $cont-type)))))
|
||||
(type $closure1 (sub $closure
|
||||
(struct (field $hash (mut i32))
|
||||
(field $code (ref $cont-type))
|
||||
(field $env0 (ref eq)))))
|
||||
(global $arg0 (mut (ref null eq)) (ref.null eq))
|
||||
(global $arg1 (mut (ref null eq)) (ref.null eq))
|
||||
(global $arg2 (mut (ref null eq)) (ref.null eq))
|
||||
(global $arg3 (mut (ref null eq)) (ref.null eq))
|
||||
(global $arg4 (mut (ref null eq)) (ref.null eq))
|
||||
(global $arg5 (mut (ref null eq)) (ref.null eq))
|
||||
;; ⋮
|
||||
;; (global $argn (mut (ref null eq)) (ref.null eq))
|
||||
|
||||
(global $current-closure (mut (ref null $closure)) (ref.null $closure))
|
||||
|
||||
(func $add-code (param $nargs i32)
|
||||
(local $n (ref eq))
|
||||
(local $x (ref eq))
|
||||
(local.set $n (global.get $arg0))
|
||||
(local.set $x (struct.get $closure1
|
||||
(global.get $current-closure)
|
||||
$env0))
|
||||
(return (i32.add $n $x)))
|
||||
|
||||
(func $make-adder-code (param $nargs i32)
|
||||
(local $n (ref eq))
|
||||
(local.set $n (global.get $arg0))
|
||||
(return (struct.new $closure1
|
||||
0
|
||||
$add-code)))
|
||||
|
||||
(func $main
|
||||
(local.set $make-adder
|
||||
(struct.new $closure
|
||||
0
|
||||
$make-adder-code))
|
||||
(global.set $current-closure $make-adder)
|
||||
(global.set $arg0 (i32.const 3))
|
||||
(local.set $f (call (struct.get $closure
|
||||
$make-adder
|
||||
$code)
|
||||
1))
|
||||
(global.set $current-closure $f)
|
||||
(global.set $arg0 (i32.const 2))
|
||||
(return (call (struct.get $closure
|
||||
$f
|
||||
$code)
|
||||
1))))
|
||||
#+end_src
|
||||
|
||||
** example
|
||||
|
||||
#+begin_src scheme
|
||||
(λ (n m ktail)
|
||||
(letrec ((f (λ (x ktail-0) (+ x n ktail-0)))
|
||||
(g (λ (y ktail-1) (+ y g ktail-1))))
|
||||
(prim (cons f g) ktail)))
|
||||
#+end_src
|
||||
|
||||
#+begin_src scheme
|
||||
(λ (n m ktail)
|
||||
(letrec ((f-code (λ (x ktail-0)
|
||||
(prim (env-get 2)
|
||||
(κ (n)
|
||||
(+ x n ktail-0)))))
|
||||
(g-code (λ (y ktail-1)
|
||||
(prim (env-get 3)
|
||||
(κ (m)
|
||||
(+ y m ktail-1))))))
|
||||
(letrec ((with-closure-code
|
||||
(κ (f g)
|
||||
(prim (get-env 0)
|
||||
(κ (ktail)
|
||||
(prim cons f g ktail))))))
|
||||
(prim (make-shared-closure (with-closure-code)
|
||||
ktail)
|
||||
(κ (with-closure)
|
||||
(prim (make-shared-closure (f-code g-code) n m)
|
||||
with-closure))))))
|
||||
#+end_src
|
||||
@@ -15,3 +15,9 @@ XXXX XXXX XXXX XXXX XXXX XXXX XXXX XX00
|
||||
zero indicates a 30-bit fixnum /
|
||||
in the upper bits
|
||||
#+end_example
|
||||
|
||||
| type/value | low bits |
|
||||
|------------+----------|
|
||||
| small int | 0 |
|
||||
| ~false~ | 01 |
|
||||
| ~true~ | 11 |
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#+title: Gyehoek Scheme
|
||||
|
||||
#+begin_center
|
||||
(this document is written in present tense as if the project is complete, but Gyehoek is a work-in-progress.)
|
||||
#+end_center
|
||||
|
||||
Gyehoek is an R⁷RS-compliant Scheme compiler targeting WebAssembly 3.0, relying principally on the recently standardised garbage collector and tail call proposals. the Gyehoek compiler is implemented in Haskell, and the Gyehoek runtime is a Rust program providing primitive routines and WebAssembly execution via the Wasmtime library.
|
||||
|
||||
primitives are implemented as native Rust functions made available to the guest by Wasmtime. in the future, it would be ideal to provide the primitives as a WASI interface to help decouple ourselves from a specific Wasm runtime, but it is not a priority.
|
||||
|
||||
Gyehoek allows separate compilation, ~eval~, first-class continuations, and so on.
|
||||
|
||||
* pipeline
|
||||
|
||||
a Scheme program's journey through Gyehoek is as follows:
|
||||
1. read (source code → Scheme data)
|
||||
2. parse (Scheme data → AST)
|
||||
3. expand(?) (AST → AST)
|
||||
4. contify (AST → CPS)
|
||||
5. close (CPS → CPS)
|
||||
6. lower (CPS → Wasm)
|
||||
|
||||
** read
|
||||
|
||||
in the read phase, Gyehoek's reader serialises textual source code into a sequence of tokens, which are then parsed into S-expressions. this phase is completely agnostic towards any interpretation of the data — it's just data, not code (yet). this distinction between reading and parsing is made so that the reader can easily be shared amongst many parsers, allowing convenient definition of human-readable representations for all sorts of compiler internals. Gyehoek's intermediate languages and WebAssembly text format are of particular interest.
|
||||
|
||||
the reader may be configured to extend R⁷RS's syntax with a special "antiquotation" notation, used internally in the compiler to elegantly interpolate and splice S-expression literals via Haskell's quasiquotation.
|
||||
#+begin_src haskell
|
||||
let meta = 123 :: Int
|
||||
in [sx|(a b c #{meta} d)|] -- ⇒ (a b c 123 d)
|
||||
|
||||
let metas = ["c","d"] :: List Text
|
||||
in [sx|(a b ##{metas} e f)|] -- ⇒ (a b "c" "d" e f)
|
||||
#+end_src
|
||||
|
||||
Gyehoek's lexer and parser are generated by Alex and Happy, respectively.
|
||||
|
||||
unless otherwise noted, the term "parse" will be used in reference to the phase taking S-expressions to ASTs, while "read" refers to the combined Alex/Happy process. if the tokenisation process (Alex) must be distinguished from the "parse" process (Happy), the former is called "lexical analysis" and the latter "syntactic analysis."
|
||||
|
||||
** parse
|
||||
|
||||
- use invertible-grammar library
|
||||
|
||||
** expand
|
||||
|
||||
** contify
|
||||
|
||||
- procedures are distinguished from continuations, and procedure applications are distinguished from continuation jumps.
|
||||
- all continuations and lambda will be named i think. the exception is continuations for primitive calls.
|
||||
|
||||
** close
|
||||
|
||||
** lower
|
||||
@@ -0,0 +1,9 @@
|
||||
#+title: on libraries
|
||||
|
||||
R⁷RS leaves it unspecified how exactly libraries correspond to files:
|
||||
|
||||
#+begin_quote
|
||||
Programs and libraries are typically stored in files, although in some implementations they can be entered interactively into a running Scheme system. Other paradigms are possible. Implementations which store libraries in files should document the mapping from the name of a library to its location in the file system.
|
||||
#+end_quote
|
||||
|
||||
thus the implementation of ~define-library~ is open to much interpretation. we could possibly define libraries as first-class objects, or deal with them statically. the former case is appealing to me, as it could massively simplify interactive use.
|
||||
@@ -0,0 +1,100 @@
|
||||
* rationale?
|
||||
|
||||
previously, the VM's stack was used for storing local variables across blocks; a Scheme procedure was split into several low-level routines (one for the procedure itself and one for each continuation), and the stack was used as a communication channel for these separate routines. in contrast, registers were local to each routine. this aligns with Wasm's model of functions pretty well, with Wasm /locals/ acting as the VM's /registers/, and a global mutable stack serving as fallback.
|
||||
|
||||
this worked quite well until it became time to implement ~call/cc~.
|
||||
|
||||
we are considering making the following alterations to the VM:
|
||||
- explicitly segment the stack into frames.
|
||||
- passing procedures and return addresses on the stack.
|
||||
- new instructions:
|
||||
+ ~(tail-call /n/)~
|
||||
+ ~(call /n/)~
|
||||
+ ~(load /r/ /n/)~
|
||||
+ ~(return /n/)~
|
||||
|
||||
* scratchpad
|
||||
|
||||
#+begin_src scheme
|
||||
(letrec ((fac (λ (n)
|
||||
(if (zero? n)
|
||||
1
|
||||
(* n (fac (- n 1)))))))
|
||||
(fac 3))
|
||||
#+end_src
|
||||
|
||||
#+begin_src scheme
|
||||
(λ (ktail0)
|
||||
(letrec ((fac
|
||||
(λ (n ktail1)
|
||||
(zero?
|
||||
n
|
||||
(κ (x0)
|
||||
(if x0
|
||||
(continue ktail1 1)
|
||||
(- n 1
|
||||
(κ (x1)
|
||||
(fac x1
|
||||
(κ (x2)
|
||||
(* n x2 ktail1)))))))))))
|
||||
(fac 3)))
|
||||
#+end_src
|
||||
|
||||
#+begin_example
|
||||
n ktail1
|
||||
| |
|
||||
| | x0
|
||||
| | |
|
||||
| | ^
|
||||
| |
|
||||
| | x1
|
||||
| | |
|
||||
| | ^
|
||||
| |
|
||||
| | x2
|
||||
| | |
|
||||
^ ^ ^
|
||||
#+end_example
|
||||
|
||||
#+begin_src scheme
|
||||
(define $fac-c0
|
||||
(pop! %x0 0) ; [ x0 $fac-c0 n $fac ktail1 ]
|
||||
(if %x0 ; [ $fac-c0 n $fac ktail1 ]
|
||||
;; every variable but `ktail1' is dead so we pop them all.
|
||||
;; this probably means that `if' should take two continuations
|
||||
;; rather than two blocks.
|
||||
(then (push! 1) ; [ $fac-c0 n $fac ktail1 ]
|
||||
(return 1)) ; [ 1 $fac-c0 n $fac ktail1 ]
|
||||
(else (load %n 1) ; [ $fac-c0 n $fac ktail1 ]
|
||||
(prim %x1 (- %n 1)) ; [ $fac-c0 n $fac ktail1 ]
|
||||
(push! $fac-c1) ; [ $fac-c0 n $fac ktail1 ]
|
||||
(push! $fac) ; [ $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
(push! %x1) ; [ $fac $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
(call 1) ; [ x1 $fac $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
)))
|
||||
|
||||
(define $fac-c1
|
||||
(pop! %x2) ; [ x2 $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
(load %n 3) ; [ $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
(prim %x3 (* %n %x2))
|
||||
(push! %x3) ; [ $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
(return 1) ; [ x3 $fac-c1 $fac-c0 n $fac ktail1 ]
|
||||
)
|
||||
|
||||
(define $fac
|
||||
(load %ktail1 2) ; [ n $fac ktail1 ]
|
||||
(load %n 0) ; [ n $fac ktail1 ]
|
||||
(push! $fac-c0) ; [ n $fac ktail1 ]
|
||||
(push! $zero?) ; [ $fac-c0 n $fac ktail1 ]
|
||||
(push! %n) ; [ $zero? $fac-c0 n $fac ktail1 ]
|
||||
(call 1) ; [ n $zero? $fac-c0 n $fac ktail1 ]
|
||||
)
|
||||
|
||||
(define $start
|
||||
(push! $fac) ; [ $start ktail0 ]
|
||||
(push! 3) ; [ $fac $start ktail0 ]
|
||||
(tail-call 1) ; [ 3 $fac $start ktail0 ]
|
||||
;; ↑ `tail-call' knows how to dispose of the caller's stack frame.
|
||||
)
|
||||
#+end_src
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#+title: assorted notes on compilation
|
||||
|
||||
* letrec
|
||||
|
||||
consider:
|
||||
|
||||
#+begin_src scheme
|
||||
(letrec ((even? (lambda (n)
|
||||
(if (zero? n)
|
||||
#t
|
||||
(odd? (- n 1)))))
|
||||
(odd? (lambda (n)
|
||||
(if (zero? n)
|
||||
#f
|
||||
(even? (- n 1))))))
|
||||
(even? 12))
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
: #t
|
||||
|
||||
since ~letrec~ is a primitive construct in the CPS language, the translation of mutually recursive functions is straightforward:
|
||||
|
||||
#+begin_src scheme
|
||||
(define (-& x y k) (k (- x y)))
|
||||
(define (zero?& x k) (k (zero? x)))
|
||||
(define (halt x) x)
|
||||
|
||||
(letrec ((even? (lambda (n ktail)
|
||||
(zero?& n
|
||||
(lambda (x1)
|
||||
(if x1
|
||||
#t
|
||||
(-& n 1
|
||||
(lambda (x2)
|
||||
(odd? x2 ktail))))))))
|
||||
(odd? (lambda (n ktail)
|
||||
(zero?& n
|
||||
(lambda (x1)
|
||||
(if x1
|
||||
#f
|
||||
(-& n 1
|
||||
(lambda (x2)
|
||||
(even? x2 ktail)))))))))
|
||||
(even? 12 halt))
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
: #t
|
||||
|
||||
however, Scheme permits ~letrec~-expressions with non-lambda right-hand sides, while the CPS language permits only kappa and lambda forms. thus, the handling of these forms is less trivial.
|
||||
|
||||
for now we'll just reject any ~letrec~ forms with non-lambda right-hand sides, lol. they aren't very important.
|
||||
Generated
+16
@@ -66,6 +66,21 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1784248371,
|
||||
"narHash": "sha256-0l0Y4D4wbZhp1Oi6h8OpbLtIm/4FN88oCf54MK2ZgiM=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "f7d151ec0bf52cf9662e2f59d7bea28588c2f070",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@@ -587,6 +602,7 @@
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"crane": "crane",
|
||||
"haskellNix": "haskellNix",
|
||||
"nixpkgs": [
|
||||
"haskellNix",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
url = "git+https://git.deertopia.net/msyds/sydpkgs";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
crane.url = "github:ipetkov/crane";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, sydpkgs, haskellNix, ... }@inputs:
|
||||
@@ -16,46 +17,52 @@
|
||||
"x86_64-darwin" "x86_64-linux"
|
||||
];
|
||||
|
||||
|
||||
overlays = [
|
||||
haskellNix.overlay
|
||||
(final: prev: {
|
||||
gyehoek-wasmtime-wrapper = final.callPackage ./wasmtime.nix {};
|
||||
})
|
||||
(final: prev: {
|
||||
gyehoek-wasm-runtime = final.callPackage ./wasm-runtime {
|
||||
crane-lib = inputs.crane.mkLib final;
|
||||
};
|
||||
gyehoek = final.haskell-nix.project' {
|
||||
src = ./.;
|
||||
compiler-nix-name = "ghc912";
|
||||
configureArgs = "-f-doctest";
|
||||
modules = [({ pkgs, lib, ...}: {
|
||||
packages.gyehoek.components.tests.test.preCheck =
|
||||
let
|
||||
bin = [
|
||||
pkgs.gyehoek-wasmtime-wrapper
|
||||
pkgs.git
|
||||
pkgs.git # tasty uses git diff
|
||||
];
|
||||
in ''
|
||||
# Wasmtime requires a cache in $HOME. This is less
|
||||
# painful than reconfiguring the cache location.
|
||||
export HOME=$(mktemp -d)
|
||||
export GYEHOEK_WASM_RUNTIME=${
|
||||
lib.getExe final.gyehoek-wasm-runtime
|
||||
}
|
||||
export PATH=${lib.makeBinPath bin}:$PATH
|
||||
'';
|
||||
})];
|
||||
shell = {
|
||||
withHoogle = true;
|
||||
inputsFrom = [];
|
||||
inputsFrom = [
|
||||
final.gyehoek-wasm-runtime
|
||||
];
|
||||
tools = {
|
||||
cabal = {};
|
||||
haskell-language-server = {};
|
||||
};
|
||||
buildInputs = with final; [
|
||||
haskellPackages.cabal-fmt
|
||||
self.packages.${final.stdenv.hostPlatform.system}.shake
|
||||
final.wabt
|
||||
final.nodejs
|
||||
final.wasm-tools
|
||||
final.wac-cli
|
||||
final.guile
|
||||
final.gyehoek-wasmtime-wrapper
|
||||
wabt
|
||||
nodejs
|
||||
wasm-tools
|
||||
wac-cli
|
||||
guile
|
||||
rust-analyzer
|
||||
wasmtime
|
||||
# bashInteractive is necessary to work around an
|
||||
# optparse-applicative issue
|
||||
#
|
||||
# https://github.com/pcapriotti/optparse-applicative/pull/408
|
||||
bashInteractive
|
||||
];
|
||||
};
|
||||
};
|
||||
@@ -87,7 +94,7 @@
|
||||
hf.packages.${system} // lib.fix (packages: {
|
||||
gyehoek = hf.packages.${system}."gyehoek:exe:gyehoek";
|
||||
default = packages.gyehoek;
|
||||
shake = pkgs.callPackage ./shake-wrapper.nix {};
|
||||
inherit (pkgs) gyehoek-wasm-runtime;
|
||||
}));
|
||||
|
||||
devShells = each-system
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
ret > ExitSuccess
|
||||
out > 22
|
||||
out >
|
||||
err > warning: using `--invoke` with a function that returns values is experimental and may break in the future
|
||||
err >
|
||||
@@ -1,47 +0,0 @@
|
||||
(module
|
||||
(type $heap-object (sub (struct (field (mut i32)))))
|
||||
(func
|
||||
(param)
|
||||
(result (ref eq))
|
||||
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
|
||||
(i32.const 3)
|
||||
(i32.const 2)
|
||||
i32.shl
|
||||
ref.i31
|
||||
(ref.cast (ref i31))
|
||||
i31.get_s
|
||||
(i32.const 4)
|
||||
(i32.const 2)
|
||||
i32.shl
|
||||
ref.i31
|
||||
(ref.cast (ref i31))
|
||||
i31.get_s
|
||||
i32.mul
|
||||
ref.i31
|
||||
(local.set 0)
|
||||
(i32.const 2)
|
||||
(i32.const 2)
|
||||
i32.shl
|
||||
ref.i31
|
||||
(ref.cast (ref i31))
|
||||
i31.get_s
|
||||
(i32.const 5)
|
||||
(i32.const 2)
|
||||
i32.shl
|
||||
ref.i31
|
||||
(ref.cast (ref i31))
|
||||
i31.get_s
|
||||
i32.mul
|
||||
ref.i31
|
||||
(local.set 1)
|
||||
(local.get 0)
|
||||
(ref.cast (ref i31))
|
||||
i31.get_s
|
||||
(local.get 1)
|
||||
(ref.cast (ref i31))
|
||||
i31.get_s
|
||||
i32.add
|
||||
ref.i31
|
||||
(local.set 2)
|
||||
(local.get 2))
|
||||
(export "main" (func 0)))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 9
|
||||
@@ -0,0 +1,4 @@
|
||||
(let ((make-adder (lambda (x)
|
||||
(lambda (y)
|
||||
(+ x y)))))
|
||||
((make-adder 4) 5))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 17
|
||||
@@ -0,0 +1,5 @@
|
||||
;; apply `f' to `x' twice.
|
||||
((λ (f x)
|
||||
(f (f x)))
|
||||
(λ (x) (+ x 4))
|
||||
9)
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 10
|
||||
@@ -0,0 +1,5 @@
|
||||
((λ (f g x)
|
||||
(f (g x)))
|
||||
(λ (x) (+ x 4))
|
||||
(λ (x) (* x 2))
|
||||
3)
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 22
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 456
|
||||
@@ -0,0 +1 @@
|
||||
(begin 123 456) ; => 456
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 123
|
||||
@@ -0,0 +1 @@
|
||||
(call/cc (λ (cc) (cc 123)))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 1234
|
||||
@@ -0,0 +1 @@
|
||||
(call/cc (λ (_) 1234))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #t
|
||||
@@ -0,0 +1,12 @@
|
||||
(letrec ((iter (λ (n f)
|
||||
(if (zero? n)
|
||||
#f
|
||||
(begin (f n)
|
||||
(iter (- n 1) f))))))
|
||||
(call/cc
|
||||
(λ (k)
|
||||
(iter 10 (λ (n)
|
||||
;; i don't feel like implementing (= n 5) right now lmfao
|
||||
(if (zero? (- n 5))
|
||||
(k #t)
|
||||
#f))))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #t
|
||||
@@ -0,0 +1,4 @@
|
||||
(call/cc
|
||||
(λ (k)
|
||||
(begin (k #t)
|
||||
#f)))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #t
|
||||
@@ -0,0 +1,5 @@
|
||||
;; confer ../callcc-early-exit-4
|
||||
(letrec ((app (λ (f x)
|
||||
(begin (f x)
|
||||
#f))))
|
||||
(call/cc (λ (k) (app k #t))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #t
|
||||
@@ -0,0 +1,5 @@
|
||||
;; confer ../callcc-early-exit-3
|
||||
(letrec ((app (λ (f x)
|
||||
(begin (f x)
|
||||
#f))))
|
||||
(call/cc (λ (k) (app (λ (x) (k x)) #t))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #t
|
||||
@@ -0,0 +1,4 @@
|
||||
(call/cc
|
||||
(λ (k)
|
||||
(begin ((λ () (k #t)))
|
||||
#f)))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 12
|
||||
@@ -0,0 +1,4 @@
|
||||
(* 2 (call/cc
|
||||
(λ (k)
|
||||
(begin (k 6)
|
||||
3))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 456
|
||||
@@ -0,0 +1,5 @@
|
||||
(call/cc
|
||||
(λ (k1)
|
||||
(call/cc
|
||||
(λ (k2)
|
||||
(k1 456)))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 456
|
||||
@@ -0,0 +1,5 @@
|
||||
(call/cc
|
||||
(λ (k1)
|
||||
(call/cc
|
||||
(λ (k2)
|
||||
(k2 456)))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 155
|
||||
@@ -0,0 +1,10 @@
|
||||
(letrec ((factorial (λ (n)
|
||||
(if (zero? n)
|
||||
1
|
||||
(* n (factorial (- n 1)))))))
|
||||
(letrec ((sum-of-factorials
|
||||
(λ (n)
|
||||
(if (zero? n)
|
||||
0
|
||||
(+ (factorial n) (sum-of-factorials (- n 1)))))))
|
||||
(+ 2 (sum-of-factorials 5))))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > (6 . 7)
|
||||
@@ -0,0 +1 @@
|
||||
(cons 6 7)
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > (456 . 123)
|
||||
@@ -0,0 +1,2 @@
|
||||
(let ((p (cons 123 456)))
|
||||
(cons (cdr p) (car p)))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 2432902008176640000
|
||||
@@ -0,0 +1,5 @@
|
||||
(letrec ((fac (λ (n)
|
||||
(if (zero? n)
|
||||
1
|
||||
(* n (fac (- n 1)))))))
|
||||
(fac 20))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #f
|
||||
@@ -0,0 +1 @@
|
||||
#f
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 128
|
||||
@@ -0,0 +1,3 @@
|
||||
(((λ (f) f)
|
||||
(λ (x) (* x 4)))
|
||||
32)
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 555
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 777
|
||||
@@ -0,0 +1 @@
|
||||
(if 123 777 555)
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 777
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #<procedure>
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 16
|
||||
@@ -0,0 +1,2 @@
|
||||
(let ((square (λ (x) (* x x))))
|
||||
(square 4))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 16
|
||||
@@ -0,0 +1,2 @@
|
||||
(letrec ((square (λ (x) (* x x))))
|
||||
(square 4))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 123
|
||||
@@ -0,0 +1 @@
|
||||
123
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > (0 . (1 . (4 . (9 . (16 . ())))))
|
||||
@@ -0,0 +1,7 @@
|
||||
(letrec ((my-map (λ (f l)
|
||||
(if (pair? l)
|
||||
(cons (f (car l))
|
||||
(my-map f (cdr l)))
|
||||
(list)))))
|
||||
(my-map (λ (x) (* x x))
|
||||
(list 0 1 2 3 4)))
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > 25
|
||||
@@ -0,0 +1,2 @@
|
||||
ret > ExitSuccess
|
||||
out > #t
|
||||
@@ -0,0 +1 @@
|
||||
#t
|
||||
@@ -1,5 +0,0 @@
|
||||
ret > ExitSuccess
|
||||
out > 555
|
||||
out >
|
||||
err > warning: using `--invoke` with a function that returns values is experimental and may break in the future
|
||||
err >
|
||||
@@ -1,13 +0,0 @@
|
||||
(module
|
||||
(type (sub (struct (field (mut i32)))))
|
||||
(func
|
||||
(param)
|
||||
(result (ref eq))
|
||||
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
|
||||
(i32.const 0)
|
||||
ref.i31
|
||||
(if
|
||||
(result i32)
|
||||
(then (i32.const 777) ref.i31)
|
||||
(else (i32.const 555) ref.i31)))
|
||||
(export "main" (func 0)))
|
||||
@@ -1,5 +0,0 @@
|
||||
ret > ExitSuccess
|
||||
out > 777
|
||||
out >
|
||||
err > warning: using `--invoke` with a function that returns values is experimental and may break in the future
|
||||
err >
|
||||
@@ -1,13 +0,0 @@
|
||||
(module
|
||||
(type (sub (struct (field (mut i32)))))
|
||||
(func
|
||||
(param)
|
||||
(result (ref eq))
|
||||
(local (ref eq) (ref eq) (ref eq) (ref eq) (ref eq))
|
||||
(i32.const 1)
|
||||
ref.i31
|
||||
(if
|
||||
(result i32)
|
||||
(then (i32.const 777) ref.i31)
|
||||
(else (i32.const 555) ref.i31)))
|
||||
(export "main" (func 0)))
|
||||
@@ -0,0 +1,4 @@
|
||||
[0;31m([0m[0;95;1;3mbegin[0m
|
||||
[0m책을[0m
|
||||
[0m더[0m
|
||||
[0m먹으세요~![0m[0;31m)[0m
|
||||
@@ -0,0 +1,4 @@
|
||||
[0;31m([0m[0;95;1;3mbegin[0m
|
||||
[0m책을[0m
|
||||
[0m더[0m
|
||||
[0m먹으세요~![0m[0;31m)[0m
|
||||
@@ -0,0 +1,5 @@
|
||||
[0;31m([0m[0;95;1;3mlambda[0m
|
||||
[0;33m([0m[0m어간[0m
|
||||
[0m어미[0m[0;33m)[0m
|
||||
[0;33m([0m[0mdisplay[0m
|
||||
[0m꾸깃[0m[0;33m)[0m[0;31m)[0m
|
||||
@@ -0,0 +1,2 @@
|
||||
[0;31m([0m[0;95;1;3mlambda[0m [0;33m([0m[0m어간[0m [0m어미[0m[0;33m)[0m
|
||||
[0;33m([0m[0mdisplay[0m [0m꾸깃[0m[0;33m)[0m[0;31m)[0m
|
||||
@@ -0,0 +1 @@
|
||||
[0;31m([0m[0;31m)[0m
|
||||
@@ -0,0 +1 @@
|
||||
[0;31m([0m[0;33m([0m[0;32m([0m[0;34m([0m[0;35m([0m[0;35m)[0m[0;34m)[0m[0;32m)[0m[0;33m)[0m[0;31m)[0m
|
||||
@@ -0,0 +1,4 @@
|
||||
[0;31m([0m[0m가[0m
|
||||
[0m나[0m
|
||||
[0m다[0m
|
||||
[0m라[0m[0;31m)[0m
|
||||
@@ -0,0 +1 @@
|
||||
[0;31m([0m[0m가[0m [0m나[0m [0m다[0m [0m라[0m[0;31m)[0m
|
||||
@@ -0,0 +1,41 @@
|
||||
[ MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/bool/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 1
|
||||
}
|
||||
)
|
||||
} :< SimpleF ( SimpleBoolean True )
|
||||
, MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/bool/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 4
|
||||
}
|
||||
)
|
||||
} :< SimpleF ( SimpleBoolean True )
|
||||
, MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/bool/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 10
|
||||
}
|
||||
)
|
||||
} :< SimpleF ( SimpleBoolean False )
|
||||
, MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/bool/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 13
|
||||
}
|
||||
)
|
||||
} :< SimpleF ( SimpleBoolean False )
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
#t #true #f #false
|
||||
@@ -0,0 +1,4 @@
|
||||
#;(a datum comment can
|
||||
span multiple lines)
|
||||
|
||||
(but it ends here)
|
||||
@@ -0,0 +1,36 @@
|
||||
[ MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/decimal/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 1
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleNumber 45.0 )
|
||||
, MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/decimal/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 4
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleNumber 5667.0 )
|
||||
, MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/decimal/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 10
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleNumber
|
||||
( -123.0 )
|
||||
)
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
45 +5667 -123
|
||||
@@ -0,0 +1,5 @@
|
||||
[ Fix
|
||||
( SimpleF
|
||||
( Symbol "aaaa bc" )
|
||||
)
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
|aaaa bc|
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,62 @@
|
||||
[ MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/list-dot-flat/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 1
|
||||
}
|
||||
)
|
||||
} :< CompoundF
|
||||
( DotListF
|
||||
(
|
||||
( MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/list-dot-flat/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 2
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleSymbol "가" )
|
||||
) :|
|
||||
[ MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/list-dot-flat/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 5
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleSymbol "나" )
|
||||
, MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/list-dot-flat/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 8
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleSymbol "다" )
|
||||
]
|
||||
)
|
||||
( MkAnn
|
||||
{ syntax = SynNone
|
||||
, position = Just
|
||||
( SourcePos
|
||||
{ sourceName = "golden/read/list-dot-flat/source.scm"
|
||||
, sourceLine = Pos 1
|
||||
, sourceColumn = Pos 13
|
||||
}
|
||||
)
|
||||
} :< SimpleF
|
||||
( SimpleSymbol "라" )
|
||||
)
|
||||
)
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user