Compare commits
69
Commits
6ffdf3f7e0
...
superfuck
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
No files matched your search
+16
-4
@@ -1,7 +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
|
. ((eval
|
||||||
. (progn (defun apply-cabal-fmt-h ()
|
. (progn (defun apply-cabal-fmt-h ()
|
||||||
(haskell-mode-buffer-apply-command "cabal-fmt"))
|
(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)))))
|
||||||
(add-to-list 'haskell-font-lock-quasi-quote-modes
|
(scheme-mode
|
||||||
'("cps" . 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
|
use flake
|
||||||
|
watch_file gyehoek.cabal cabal.project
|
||||||
|
PATH_add $(dirname $(cabal list-bin gyehoek))
|
||||||
+2
-1
@@ -8,4 +8,5 @@ dist-newstyle
|
|||||||
*.tix
|
*.tix
|
||||||
.direnv
|
.direnv
|
||||||
result
|
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
|
packages: *.cabal
|
||||||
tests: True
|
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
|
source-repository-package
|
||||||
type: git
|
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
|
||||||
@@ -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,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.
|
||||||
@@ -20,13 +20,13 @@
|
|||||||
overlays = [
|
overlays = [
|
||||||
haskellNix.overlay
|
haskellNix.overlay
|
||||||
(final: prev: {
|
(final: prev: {
|
||||||
shake-wrapper = final.callPackage ./shake-wrapper.nix {};
|
gyehoek-wasm-runtime = final.callPackage ./wasm-runtime {
|
||||||
gyehoek-runtime = final.callPackage ./runtime {
|
|
||||||
crane-lib = inputs.crane.mkLib final;
|
crane-lib = inputs.crane.mkLib final;
|
||||||
};
|
};
|
||||||
gyehoek = final.haskell-nix.project' {
|
gyehoek = final.haskell-nix.project' {
|
||||||
src = ./.;
|
src = ./.;
|
||||||
compiler-nix-name = "ghc912";
|
compiler-nix-name = "ghc912";
|
||||||
|
configureArgs = "-f-doctest";
|
||||||
modules = [({ pkgs, lib, ...}: {
|
modules = [({ pkgs, lib, ...}: {
|
||||||
packages.gyehoek.components.tests.test.preCheck =
|
packages.gyehoek.components.tests.test.preCheck =
|
||||||
let
|
let
|
||||||
@@ -34,14 +34,16 @@
|
|||||||
pkgs.git # tasty uses git diff
|
pkgs.git # tasty uses git diff
|
||||||
];
|
];
|
||||||
in ''
|
in ''
|
||||||
export GYEHOEK_RUNTIME=${lib.getExe final.gyehoek-runtime}
|
export GYEHOEK_WASM_RUNTIME=${
|
||||||
|
lib.getExe final.gyehoek-wasm-runtime
|
||||||
|
}
|
||||||
export PATH=${lib.makeBinPath bin}:$PATH
|
export PATH=${lib.makeBinPath bin}:$PATH
|
||||||
'';
|
'';
|
||||||
})];
|
})];
|
||||||
shell = {
|
shell = {
|
||||||
withHoogle = true;
|
withHoogle = true;
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
final.gyehoek-runtime
|
final.gyehoek-wasm-runtime
|
||||||
];
|
];
|
||||||
tools = {
|
tools = {
|
||||||
cabal = {};
|
cabal = {};
|
||||||
@@ -49,7 +51,6 @@
|
|||||||
};
|
};
|
||||||
buildInputs = with final; [
|
buildInputs = with final; [
|
||||||
haskellPackages.cabal-fmt
|
haskellPackages.cabal-fmt
|
||||||
shake-wrapper
|
|
||||||
wabt
|
wabt
|
||||||
nodejs
|
nodejs
|
||||||
wasm-tools
|
wasm-tools
|
||||||
@@ -57,6 +58,11 @@
|
|||||||
guile
|
guile
|
||||||
rust-analyzer
|
rust-analyzer
|
||||||
wasmtime
|
wasmtime
|
||||||
|
# bashInteractive is necessary to work around an
|
||||||
|
# optparse-applicative issue
|
||||||
|
#
|
||||||
|
# https://github.com/pcapriotti/optparse-applicative/pull/408
|
||||||
|
bashInteractive
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -88,7 +94,7 @@
|
|||||||
hf.packages.${system} // lib.fix (packages: {
|
hf.packages.${system} // lib.fix (packages: {
|
||||||
gyehoek = hf.packages.${system}."gyehoek:exe:gyehoek";
|
gyehoek = hf.packages.${system}."gyehoek:exe:gyehoek";
|
||||||
default = packages.gyehoek;
|
default = packages.gyehoek;
|
||||||
inherit (pkgs) gyehoek-runtime shake-wrapper;
|
inherit (pkgs) gyehoek-wasm-runtime;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
devShells = each-system
|
devShells = each-system
|
||||||
|
|||||||
@@ -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
|
||||||
File renamed without changes.
@@ -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)
|
||||||
File renamed without changes.
File renamed without changes.
@@ -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))
|
||||||
File renamed without changes.
@@ -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 @@
|
|||||||
|
(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))
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,3 @@
|
|||||||
|
(((λ (f) f)
|
||||||
|
(λ (x) (* x 4)))
|
||||||
|
32)
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,2 @@
|
|||||||
|
ret > ExitSuccess
|
||||||
|
out > #t
|
||||||
File renamed without changes.
@@ -1 +0,0 @@
|
|||||||
(((λ (f) f) (λ (x) (* x 4))) 32)
|
|
||||||
@@ -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 @@
|
|||||||
|
[]
|
||||||
Whitespace-only changes.
@@ -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 "라" )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
(가 나 다 . 라)
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< CompoundF
|
||||||
|
( ListF Ordinary
|
||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 2
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "가" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 5
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "나" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 8
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "다" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 11
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "라" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 14
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleNumber 1.0 )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 16
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleNumber 2.0 )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list-flat/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 18
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleNumber 3.0 )
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
(가 나 다 라 1 2 3)
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< CompoundF
|
||||||
|
( DotListF
|
||||||
|
(
|
||||||
|
( MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 2
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "a" )
|
||||||
|
) :|
|
||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 4
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "b" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 6
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< CompoundF
|
||||||
|
( ListF Ordinary
|
||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 7
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "c" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 9
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "d" )
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
( MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 14
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< CompoundF
|
||||||
|
( ListF Ordinary
|
||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 15
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "가" )
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 18
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< CompoundF
|
||||||
|
( DotListF
|
||||||
|
(
|
||||||
|
( MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 19
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "나" )
|
||||||
|
) :| []
|
||||||
|
)
|
||||||
|
( MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 24
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "다" )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
, MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/list/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 28
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleSymbol "라" )
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
(a b (c d) . (가 (나 . 다) 라))
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-expression/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< MetaF "aHaskellVariable + abc * 2"
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#{aHaskellVariable + abc * 2}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
##{case 123 of { 123 -> blah
|
||||||
|
; xyz -> flah }}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-splice-expression/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< MetaSpliceF "takeWhile (\x -> even x) aHaskellList"
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
##{takeWhile (\x -> even x) aHaskellList}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-splice-variable/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< MetaSpliceF "aHaskellList"
|
||||||
|
]
|
||||||
Loaded 100 of 173 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user