#+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