[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 01/99: Temp commit
From: |
Christopher Allan Webber |
Subject: |
[Guile-commits] 01/99: Temp commit |
Date: |
Sun, 10 Oct 2021 21:50:39 -0400 (EDT) |
cwebber pushed a commit to branch compile-to-js-merge
in repository guile.
commit ce1cc2706c62e2e497a44d88465ae31e1f289aa4
Author: Ian Price <ianprice90@googlemail.com>
AuthorDate: Fri Jun 5 22:46:44 2015 +0100
Temp commit
---
module/Makefile.am | 11 ++
module/language/cps/compile-js.scm | 125 +++++++++++++++
module/language/cps/spec.scm | 4 +-
module/language/javascript.scm | 190 +++++++++++++++++++++++
module/language/javascript/spec.scm | 13 ++
module/language/js-il.scm | 223 +++++++++++++++++++++++++++
module/language/js-il/compile-javascript.scm | 104 +++++++++++++
module/language/js-il/runtime.js | 191 +++++++++++++++++++++++
module/language/js-il/spec.scm | 12 ++
9 files changed, 872 insertions(+), 1 deletion(-)
diff --git a/module/Makefile.am b/module/Makefile.am
index 88b84a1..584039b 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -76,6 +76,8 @@ SOURCES = \
$(ECMASCRIPT_LANG_SOURCES) \
$(ELISP_LANG_SOURCES) \
$(BRAINFUCK_LANG_SOURCES) \
+ $(JS_IL_LANG_SOURCES) \
+ $(JS_LANG_SOURCES) \
$(LIB_SOURCES) \
$(WEB_SOURCES)
@@ -204,6 +206,15 @@ BRAINFUCK_LANG_SOURCES = \
language/brainfuck/compile-tree-il.scm \
language/brainfuck/spec.scm
+JS_IL_LANG_SOURCES = \
+ language/js-il.scm \
+ language/js-il/compile-javascript.scm \
+ language/js-il/spec.scm
+
+JS_LANG_SOURCES = \
+ language/javascript.scm \
+ language/js-il/spec.scm
+
SCRIPTS_SOURCES = \
scripts/compile.scm \
scripts/disassemble.scm \
diff --git a/module/language/cps/compile-js.scm
b/module/language/cps/compile-js.scm
new file mode 100644
index 0000000..ed75db0
--- /dev/null
+++ b/module/language/cps/compile-js.scm
@@ -0,0 +1,125 @@
+(define-module (language cps compile-js)
+ #:use-module ((guile) #:select ((values . mv:values))) ;; FIXME:
+ #:use-module (language cps)
+ #:use-module (language js-il)
+ #:use-module (ice-9 match)
+ #:export (compile-js))
+
+(define optimize (@@ (language cps compile-bytecode) optimize))
+(define convert-closures (@@ (language cps compile-bytecode) convert-closures))
+(define reify-primitives (@@ (language cps compile-bytecode) reify-primitives))
+(define renumber (@@ (language cps compile-bytecode) renumber))
+
+(define (compile-js exp env opts)
+ ;; See comment in `optimize' about the use of set!.
+ (set! exp (optimize exp opts))
+ (set! exp (convert-closures exp))
+ ;; first-order optimization should go here
+ (set! exp (reify-primitives exp))
+ (set! exp (renumber exp))
+ ;; (values exp env env)
+ (match exp
+ (($ $program funs)
+ ;; TODO: I should special case the compilation for the initial fun,
+ ;; as this is the entry point for the program, and shouldn't get a
+ ;; "self" argument, for now, I add "undefined" as the first
+ ;; argument in the call to it.
+ ;; see compile-exp in (language js-il compile-javascript)
+ (mv:values (make-program (compile-fun (car funs))
+ (map compile-fun (cdr funs)))
+ env
+ env)))
+ )
+
+(define (compile-fun fun)
+ ;; meta
+ (match fun
+ (($ $cont k ($ $kfun src meta self ($ $cont tail ($ $ktail)) clause))
+ (make-var k (compile-clause clause self tail)))
+ (_
+ `(fun:todo: ,fun))))
+
+(define (compile-clause clause self tail)
+ (match clause
+ (($ $cont k ($ $kclause ($ $arity req opt rest kw allow-other-keys?)
+ body alternate))
+ ;; add function argument prelude
+ (unless (null? opt)
+ (not-supported "optional arguments are not supported" clause))
+ (when rest
+ (not-supported "rest arguments are not supported" clause))
+ (unless (or (null? kw) allow-other-keys?)
+ (not-supported "keyword arguments are not supported" clause))
+ (when alternate
+ (not-supported "alternate continuations are not supported" clause))
+ (make-function self ;; didn't think this js pattern would come in handy
+ (cons tail req)
+ (match body
+ (($ $cont k ($ $kargs () () exp))
+ (compile-term exp))
+ (($ $cont k _)
+ (make-local (list (compile-cont body))
+ (make-jscall k req))))))
+ (_
+ `(clause:todo: ,clause))))
+
+(define (not-supported msg clause)
+ (error 'not-supported msg clause))
+
+(define (compile-term term)
+ (match term
+ (($ $letk conts body)
+ (make-local (map compile-cont conts) (compile-term body)))
+ (($ $continue k src exp)
+ (compile-exp exp k))))
+
+(define (compile-cont cont)
+ (match cont
+ (($ $cont k ($ $kargs names syms body))
+ ;; use the name part?
+ (make-var k (make-function syms (compile-term body))))
+ (($ $cont k ($ $kreceive ($ $arity (arg) _ (? symbol? rest) _ _) k2))
+ ;; still not 100% on passing values as args vs a values object.
+ ;; using the former means I can merge make-jscall and make-continue
+ (make-var k (make-function (list arg rest) (make-jscall k2 (list arg
rest)))))
+ (($ $cont k ($ $kreceive ($ $arity (arg) _ #f _ _) k2))
+ (make-var k (make-function (list arg) (make-jscall k2 (list arg)))))
+ (_
+ `(cont:todo: ,cont))
+ ))
+
+(define (compile-exp exp k)
+ (match exp
+ (($ $branch kt exp)
+ (compile-test exp kt k))
+ (($ $primcall 'return (arg))
+ (make-continue k (make-id arg)))
+ (($ $call name args)
+ (make-call name (cons k args)))
+ (($ $callk label proc args)
+ ;; eh?
+ ;; (pk 'callk label proc args k)
+ (make-jscall label (cons k args)))
+ (_
+ (make-continue k (compile-exp* exp)))))
+
+(define (compile-exp* exp)
+ (match exp
+ (($ $const val)
+ (make-const val))
+ (($ $primcall name args)
+ (make-primcall name args))
+ (($ $closure label nfree)
+ (make-closure label nfree))
+ (($ $values values)
+ (make-values values))
+ (_
+ `(exp:todo: ,exp))))
+
+(define (compile-test exp kt kf)
+ ;; TODO: find out if the expression is always simple enough that I
+ ;; don't need to create a new continuation (which will require extra
+ ;; arguments being passed through)
+ (make-branch (compile-exp* exp)
+ (make-continue kt (make-values '()))
+ (make-continue kf (make-values '()))))
diff --git a/module/language/cps/spec.scm b/module/language/cps/spec.scm
index f1255af..ec73528 100644
--- a/module/language/cps/spec.scm
+++ b/module/language/cps/spec.scm
@@ -22,6 +22,7 @@
#:use-module (system base language)
#:use-module (language cps)
#:use-module (language cps compile-bytecode)
+ #:use-module (language cps compile-js)
#:export (cps))
(define* (write-cps exp #:optional (port (current-output-port)))
@@ -32,6 +33,7 @@
#:reader (lambda (port env) (read port))
#:printer write-cps
#:parser parse-cps
- #:compilers `((bytecode . ,compile-bytecode))
+ #:compilers `((bytecode . ,compile-bytecode)
+ (js-il . ,compile-js))
#:for-humans? #f
)
diff --git a/module/language/javascript.scm b/module/language/javascript.scm
new file mode 100644
index 0000000..0a0b20e
--- /dev/null
+++ b/module/language/javascript.scm
@@ -0,0 +1,190 @@
+;; Only has enough of the ecmascript language for compilation from cps
+(define-module (language javascript)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-9 gnu)
+ #:export (
+ make-const const
+ make-function function
+ make-return return
+ make-call call
+ make-block block
+ make-new new
+ make-id id
+ make-refine refine
+ make-conditional conditional
+ make-var var
+
+ print-statement))
+
+;; Copied from (language cps)
+;; Should put in a srfi 99 module
+(define-syntax define-record-type*
+ (lambda (x)
+ (define (id-append ctx . syms)
+ (datum->syntax ctx (apply symbol-append (map syntax->datum syms))))
+ (syntax-case x ()
+ ((_ name field ...)
+ (and (identifier? #'name) (and-map identifier? #'(field ...)))
+ (with-syntax ((cons (id-append #'name #'make- #'name))
+ (pred (id-append #'name #'name #'?))
+ ((getter ...) (map (lambda (f)
+ (id-append f #'name #'- f))
+ #'(field ...))))
+ #'(define-record-type name
+ (cons field ...)
+ pred
+ (field getter)
+ ...))))))
+
+;; TODO: add type predicates to fields so I can only construct valid
+;; objects
+(define-syntax-rule (define-js-type name field ...)
+ (begin
+ (define-record-type* name field ...)
+ (set-record-type-printer! name print-js)))
+
+(define (print-js exp port)
+ (format port "#<js ~S>" (unparse-js exp)))
+
+(define-js-type const c)
+(define-js-type function args body)
+(define-js-type return exp)
+(define-js-type call function args)
+(define-js-type block statements)
+(define-js-type new expr)
+(define-js-type id name)
+(define-js-type refine id field)
+(define-js-type conditional test then else)
+(define-js-type var id exp)
+
+(define (unparse-js exp)
+ (match exp
+ (($ const c)
+ `(const ,c))
+ (($ function args body)
+ `(function ,args ,@(map unparse-js body)))
+ (($ return exp)
+ `(return ,(unparse-js exp)))
+ (($ call function args)
+ `(call ,(unparse-js function) ,@(map unparse-js args)))
+ (($ block statements)
+ `(block ,@(map unparse-js statements)))
+ (($ new expr)
+ `(new ,(unparse-js expr)))
+ (($ id name)
+ `(id ,name))
+ (($ refine id field)
+ `(refine ,(unparse-js id) ,(unparse-js field)))
+ (($ conditional test then else)
+ `(if ,(unparse-js test)
+ (block ,@(map unparse-js then))
+ (block ,@(map unparse-js else))))
+ (($ var id exp)
+ `(var ,id ,(unparse-js exp)))))
+
+(define (print-exp exp port)
+ (match exp
+
+ (($ const c)
+ (print-const c port))
+
+ (($ id name)
+ (print-id name port))
+
+ (($ call (and ($ function _ _) fun) args)
+ (format port "(")
+ (print-exp fun port)
+ (format port ")(")
+ (print-separated args print-exp "," port)
+ (format port ")"))
+
+ (($ call fun args)
+ (print-exp fun port)
+ (format port "(")
+ (print-separated args print-exp "," port)
+ (format port ")"))
+
+
+ (($ refine expr field)
+ (print-exp expr port)
+ (format port "[")
+ (print-exp field port)
+ (format port "]"))
+
+ (($ function params body)
+ (format port "function (")
+ (print-separated params print-id "," port)
+ (format port ")")
+ (print-block body port))
+
+ (($ block stmts)
+ (print-block stmts port))
+
+ (($ new expr)
+ (format port "new ")
+ (print-exp expr port))))
+
+(define (print-statement stmt port)
+ (match stmt
+ (($ var id exp)
+ (format port "var ")
+ (print-id id port)
+ (format port " = ")
+ (print-exp exp port)
+ (format port ";"))
+
+ (($ conditional test then else)
+ (format port "if (")
+ (print-exp test port)
+ (format port ") {")
+ (print-block then port)
+ (format port "} else {")
+ (print-block else port)
+ (format port "}"))
+
+ (($ return expr)
+ (format port "return ")
+ (print-exp expr port)
+ (format port ";"))
+
+ (expr
+ (print-exp expr port)
+ (format port ";"))))
+
+(define (print-id id port)
+ (display id port))
+
+(define (print-block stmts port)
+ (format port "{")
+ (print-statements stmts port)
+ (format port "}"))
+
+(define (print-statements stmts port)
+ (for-each (lambda (stmt)
+ (print-statement stmt port))
+ stmts))
+
+(define (print-const c port)
+ (cond ((string? c)
+ (write c port))
+ ((number? c)
+ (write c port))
+ (else
+ (throw 'unprintable-const c))))
+
+(define (print-separated args printer separator port)
+ (unless (null? args)
+ (let ((first (car args))
+ (rest (cdr args)))
+ (printer first port)
+ (for-each (lambda (x)
+ (display separator port)
+ (printer x port))
+ rest))))
+
+(define (print-terminated args printer terminator port)
+ (for-each (lambda (x)
+ (printer x port)
+ (display terminator port))
+ args))
diff --git a/module/language/javascript/spec.scm
b/module/language/javascript/spec.scm
new file mode 100644
index 0000000..f04341f
--- /dev/null
+++ b/module/language/javascript/spec.scm
@@ -0,0 +1,13 @@
+;; in future, this should be merged with ecmacript
+
+(define-module (language javascript spec)
+ #:use-module (system base language)
+ #:use-module (language javascript)
+ #:export (javascript))
+
+(define-language javascript
+ #:title "Javascript"
+ #:reader #f
+ #:printer print-statement
+ #:for-humans? #f
+ )
diff --git a/module/language/js-il.scm b/module/language/js-il.scm
new file mode 100644
index 0000000..b62c3ba
--- /dev/null
+++ b/module/language/js-il.scm
@@ -0,0 +1,223 @@
+(define-module (language js-il)
+ #:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-9 gnu)
+ #:use-module (ice-9 match)
+ #:export (make-program program
+ (make-function* . make-function) function
+ make-local local
+ make-var var
+ make-continue continue ; differ from conts
+ make-const const
+ make-primcall primcall
+ make-call call
+ make-jscall jscall
+ make-closure closure
+ make-branch branch
+ make-values values
+ ; print-js
+ make-return return
+ make-id id
+ ))
+
+;; Copied from (language cps)
+;; Should put in a srfi 99 module
+(define-syntax define-record-type*
+ (lambda (x)
+ (define (id-append ctx . syms)
+ (datum->syntax ctx (apply symbol-append (map syntax->datum syms))))
+ (syntax-case x ()
+ ((_ name field ...)
+ (and (identifier? #'name) (and-map identifier? #'(field ...)))
+ (with-syntax ((cons (id-append #'name #'make- #'name))
+ (pred (id-append #'name #'name #'?))
+ ((getter ...) (map (lambda (f)
+ (id-append f #'name #'- f))
+ #'(field ...))))
+ #'(define-record-type name
+ (cons field ...)
+ pred
+ (field getter)
+ ...))))))
+
+;; TODO: add type predicates to fields so I can only construct valid
+;; objects
+(define-syntax-rule (define-js-type name field ...)
+ (begin
+ (define-record-type* name field ...)
+ (set-record-type-printer! name print-js)))
+
+(define (print-js exp port)
+ (format port "#<js-il ~S>" (unparse-js exp)))
+
+(define-js-type program entry body)
+(define-js-type function name params body)
+
+(define make-function*
+ (case-lambda
+ ((name params body)
+ (make-function name params body))
+ ((params body)
+ (make-function #f params body))))
+
+(define-js-type local bindings body) ; local scope
+(define-js-type var id exp)
+(define-js-type continue cont exp)
+(define-js-type const value)
+(define-js-type primcall name args)
+(define-js-type call name args)
+(define-js-type jscall name args) ;; TODO: shouldn't need this hack
+(define-js-type closure label num-free)
+(define-js-type values vals)
+(define-js-type branch test consequence alternate)
+(define-js-type id name)
+(define-js-type return val)
+
+(define (unparse-js exp)
+ (match exp
+ (($ program entry body)
+ `(program ,(unparse-js entry) . ,(map unparse-js body)))
+ (($ function name params body)
+ `(function ,name ,params ,(unparse-js body)))
+ (($ local bindings body)
+ `(local ,(map unparse-js bindings) ,(unparse-js body)))
+ (($ var id exp)
+ `(var ,id ,(unparse-js exp)))
+ (($ continue k exp)
+ `(continue ,k ,(unparse-js exp)))
+ (($ branch test then else)
+ `(if ,(unparse-js test) ,(unparse-js then) ,(unparse-js else)))
+ ;; values
+ (($ const c)
+ `(const ,c))
+ (($ primcall name args)
+ `(primcall ,name , args))
+ (($ call name args)
+ `(call ,name , args))
+ (($ jscall name args)
+ `(jscall ,name , args))
+ (($ closure label nfree)
+ `(closure ,label ,nfree))
+ (($ values vals)
+ `(values . ,vals))
+ (($ return val)
+ `(return . ,(unparse-js val)))
+ (($ id name)
+ `(id . ,name))
+ (_
+ ;(error "unexpected js" exp)
+ (pk 'unexpected exp)
+ exp)))
+#|
+(define (print-js exp port)
+ ;; could be much nicer with foof's fmt
+ (match exp
+ (($ program (and entry ($ var name _)) body)
+ ;; TODO: I should probably put call to entry in js-il
+ (format port "(function(){\n")
+ (print-js entry port) (display ";\n" port)
+ (print-terminated body print-js ";\n" port)
+ ;; call to entry point
+ (format port "return ~a(scheme.initial_cont);" (lookup-cont name))
+ (format port "})();\n"))
+ (($ function #f params body)
+ (format port "function(")
+ (print-separated params print-var "," port)
+ (format port "){\n")
+ (print-js body port)(display ";" port)
+ (format port "}"))
+ ;; TODO: clean this code up
+ (($ function name params body)
+ (format port "function (~a," (lookup-cont name))
+ (print-separated params print-var "," port)
+ (format port "){\n")
+ (print-js body port)(display ";" port)
+ (format port "}"))
+ (($ local bindings body)
+ (display "{" port)
+ (print-terminated bindings print-js ";\n" port)
+ (print-js body port)
+ (display ";\n")
+ (display "}" port))
+ (($ var id exp)
+ (format port "var ~a = " (lookup-cont id))
+ (print-js exp port))
+ (($ continue k exp)
+ (format port "return ~a(" (lookup-cont k))
+ (print-js exp port)
+ (display ")" port))
+ (($ branch test then else)
+ (display "if (scheme.is_true(" port)
+ (print-js test port)
+ (display ")) {\n" port)
+ (print-js then port)
+ (display ";} else {\n" port)
+ (print-js else port)
+ (display ";}" port))
+ ;; values
+ (($ const c)
+ (print-const c port))
+ (($ primcall name args)
+ (format port "scheme.primitives[\"~s\"](" name)
+ (print-separated args print-var "," port)
+ (format port ")"))
+ (($ call name args)
+ ;; TODO: need to also add closure env
+ (format port "return ~a.fun(~a," (lookup-cont name) (lookup-cont name))
+ (print-separated args print-var "," port)
+ (format port ")"))
+ (($ jscall name args)
+ (format port "return ~a(" (lookup-cont name))
+ (print-separated args print-var "," port)
+ (format port ")"))
+ (($ closure label nfree)
+ (format port "new scheme.Closure(~a,~a)" (lookup-cont label) nfree))
+ (($ values vals)
+ (display "new scheme.Values(" port)
+ (print-separated vals print-var "," port)
+ (display ")" port))
+ ;; (($ return val)
+ ;; (display "return " port)
+ ;; (print-js val port))
+ (($ id name)
+ (print-var name port))
+ (_
+ (error "print: unexpected js" exp))))
+
+(define (print-var var port)
+ (if (number? var)
+ (display (lookup-cont var) port)
+ (display var port)))
+
+(define (lookup-cont k)
+ (format #f "kont_~s" k))
+
+(define (print-separated args printer separator port)
+ (unless (null? args)
+ (let ((first (car args))
+ (rest (cdr args)))
+ (printer first port)
+ (for-each (lambda (x)
+ (display separator port)
+ (printer x port))
+ rest))))
+
+(define (print-terminated args printer terminator port)
+ (for-each (lambda (x)
+ (printer x port)
+ (display terminator port))
+ args))
+
+(define (print-const c port)
+ (cond ((number? c) (display c port))
+ ((eqv? c #t) (display "scheme.TRUE" port))
+ ((eqv? c #f) (display "scheme.FALSE" port))
+ ((eqv? c '()) (display "scheme.EMPTY" port))
+ ((unspecified? c) (display "scheme.UNSPECIFIED" port))
+ ((symbol? c) (format port "new scheme.Symbol(\"~s\")" c))
+ ((list? c)
+ (display "scheme.list(" port)
+ (print-separated c print-const "," port)
+ (display ")" port))
+ (else
+ (throw 'not-implemented))))
+|#
diff --git a/module/language/js-il/compile-javascript.scm
b/module/language/js-il/compile-javascript.scm
new file mode 100644
index 0000000..21b6fc9
--- /dev/null
+++ b/module/language/js-il/compile-javascript.scm
@@ -0,0 +1,104 @@
+(define-module (language js-il compile-javascript)
+ #:use-module (ice-9 match)
+ #:use-module ((language js-il) #:renamer (symbol-prefix-proc 'il:))
+ #:use-module (language javascript)
+ #:export (compile-javascript))
+
+(define (compile-javascript exp env opts)
+ (values (compile-exp exp) env env))
+
+(define *scheme* (make-id "scheme"))
+
+(define (name->id name)
+ (make-id (rename name)))
+
+(define (rename name)
+ (format #f "kont_~a" name))
+
+(define (compile-exp exp)
+ ;; TODO: handle ids for js
+ (match exp
+ (($ il:program (and entry ($ il:var name _)) body)
+ (let ((entry-call
+ (make-return
+ (make-call (name->id name)
+ (list
+ (make-id "undefined")
+ (make-refine *scheme* (make-const
"initial_cont")))))))
+ (make-call (make-function '() (append (map compile-exp body)
+ (list (compile-exp entry)
entry-call)))
+ '())))
+
+ (($ il:function #f params body)
+ (make-function (map rename params) (list (compile-exp body))))
+
+ (($ il:function name params body)
+ ;; TODO: split il:function into closure (with self) and cont types
+ (make-function (map rename (cons name params)) (list (compile-exp body))))
+
+ (($ il:local bindings body)
+ (make-block (append (map compile-exp bindings) (list (compile-exp
body)))))
+
+ (($ il:var id exp)
+ (make-var (rename id) (compile-exp exp)))
+
+ (($ il:continue k exp)
+ (make-return (make-call (name->id k) (list (compile-exp exp)))))
+
+ (($ il:branch test then else)
+ (make-conditional (make-call (make-refine *scheme* (make-const "is_true"))
+ (list (compile-exp test)))
+ (list (compile-exp then))
+ (list (compile-exp else))))
+
+ (($ il:const c)
+ (compile-const c))
+
+ (($ il:primcall name args)
+ (make-call (make-refine (make-refine *scheme* (make-const "primitives"))
+ (make-const (symbol->string name)))
+ (map name->id args)))
+
+ (($ il:call name args)
+ (make-return
+ (make-call (make-refine (name->id name) (make-const "fun"))
+ (map name->id (cons name args)))))
+
+ (($ il:jscall name args)
+ (make-return (make-call (name->id name) (map name->id args))))
+
+ (($ il:closure label nfree)
+ (make-new
+ (make-call (make-refine *scheme* (make-const "Closure"))
+ (list (name->id label) (make-const nfree)))))
+
+ (($ il:values vals)
+ (make-new
+ (make-call (make-refine *scheme* (make-const "Values"))
+ (map name->id vals))))
+
+ (($ il:id name)
+ (name->id name))))
+
+(define (compile-const c)
+ (cond ((number? c)
+ (make-const c))
+ ((eqv? c #t)
+ (make-refine *scheme* (make-const "TRUE")))
+ ((eqv? c #f)
+ (make-refine *scheme* (make-const "FALSE")))
+ ((eqv? c '())
+ (make-refine *scheme* (make-const "EMPTY")))
+ ((unspecified? c)
+ (make-refine *scheme* (make-const "UNSPECIFIED")))
+ ((symbol? c)
+ (make-new
+ (make-call
+ (make-refine *scheme* (make-const "Symbol"))
+ (list (make-const (symbol->string c))))))
+ ((list? c)
+ (make-call
+ (make-refine *scheme* (make-const "list"))
+ (map compile-const c)))
+ (else
+ (throw 'uncompilable-const c))))
diff --git a/module/language/js-il/runtime.js b/module/language/js-il/runtime.js
new file mode 100644
index 0000000..823ba97
--- /dev/null
+++ b/module/language/js-il/runtime.js
@@ -0,0 +1,191 @@
+var scheme = {
+ obarray : {},
+ primitives : {},
+ env : {},
+ cache: [],
+ builtins: [],
+ // TODO: placeholders
+ FALSE : false,
+ TRUE : true,
+ NIL : false,
+ EMPTY : [],
+ UNSPECIFIED : []
+};
+
+function not_implemented_yet() {
+ throw "not implemented yet";
+};
+
+// Numbers
+scheme.primitives.add = function (x, y) {
+ return x + y;
+};
+
+scheme.primitives.add1 = function (x) {
+ return x + 1;
+};
+
+scheme.primitives.sub = function (x, y) {
+ return x - y;
+};
+
+scheme.primitives.sub1 = function (x) {
+ return x - 1;
+};
+
+scheme.primitives.mul = function (x, y) {
+ return x * y;
+};
+
+scheme.primitives.div = function (x, y) {
+ return x / y;
+};
+
+scheme.primitives["="] = function (x, y) {
+ return x == y;
+};
+
+scheme.primitives["<"] = function (x, y) {
+ return x < y;
+};
+
+scheme.primitives.quo = not_implemented_yet;
+scheme.primitives.rem = not_implemented_yet;
+scheme.primitives.mod = not_implemented_yet;
+
+// Boxes
+scheme.Box = function (x) {
+ this.x = x;
+ return this;
+};
+
+scheme.primitives["box-ref"] = function (box) {
+ return box.x;
+};
+
+scheme.primitives["box-set!"] = function (box, val) {
+ box.x = val;
+};
+
+// Lists
+scheme.Pair = function (car, cdr) {
+ this.car = car;
+ this.cdr = cdr;
+ return this;
+};
+
+scheme.primitives.cons = function (car, cdr) {
+ return new scheme.Pair(car,cdr);
+};
+
+scheme.primitives.car = function (obj) {
+ return obj.car;
+};
+
+scheme.primitives.cdr = function (obj) {
+ return obj.cdr;
+};
+
+scheme.list = function () {
+ var l = scheme.EMPTY;
+ for (var i = arguments.length - 1; i >= 0; i--){
+ l = scheme.primitives.cons(arguments[i],l);
+ };
+ return l;
+};
+
+scheme.primitives["null?"] = function(obj) {
+ return scheme.EMPTY == obj;
+};
+
+// Symbols
+scheme.Symbol = function(s) {
+ if (scheme.obarray[s]) {
+ return scheme.obarray[s];
+ } else {
+ this.name = s;
+ scheme.obarray[s] = this;
+ return this;
+ };
+};
+
+// Vectors
+
+// Bytevectors
+
+// Booleans
+
+// Chars
+
+// Strings
+
+// Closures
+scheme.Closure = function(f, size) {
+ this.fun = f;
+ this.freevars = new Array(size);
+ return this;
+};
+
+scheme.primitives["free-set!"] = function (closure, idx, obj) {
+ closure.freevars[idx] = obj;
+};
+
+scheme.primitives["free-ref"] = function (closure, idx) {
+ return closure.freevars[idx];
+};
+
+scheme.primitives["builtin-ref"] = function (idx) {
+ return scheme.builtins[idx];
+};
+
+// Modules
+scheme.primitives["define!"] = function(sym, obj) {
+ scheme.env[sym.name] = new scheme.Box(obj);
+};
+
+scheme.primitives["cache-current-module!"] = function (module, scope) {
+ scheme.cache[scope] = module;
+};
+
+scheme.primitives["cached-toplevel-box"] = function (scope, sym, is_bound) {
+ return scheme.cache[scope][sym.name];
+};
+
+scheme.primitives["current-module"] = function () {
+ return scheme.env;
+};
+
+scheme.primitives["resolve"] = function (sym, is_bound) {
+ return scheme.env[sym.name];
+};
+
+// values
+scheme.Values = function () {
+ this.values = arguments;
+ return this;
+};
+
+// bleh
+scheme.initial_cont = function (x) { return x; };
+scheme.primitives.return = function (x) { return x; };
+scheme.is_true = function (obj) {
+ return !(obj == scheme.FALSE || obj == scheme.NIL);
+};
+
+var callcc = function (k,vals) {
+ var closure = vals.values[0];
+ var f = function (k2, val) {
+ // TODO: multivalue continuations
+ return k(val);
+ };
+ return closure.fun(k, new scheme.Closure(f, 0));
+};
+scheme.builtins[4] = new scheme.Closure(callcc, 0);
+// #define FOR_EACH_VM_BUILTIN(M) \
+// M(apply, APPLY, 2, 0, 1) \
+// M(values, VALUES, 0, 0, 1) \
+// M(abort_to_prompt, ABORT_TO_PROMPT, 1, 0, 1) \
+// M(call_with_values, CALL_WITH_VALUES, 2, 0, 0) \
+// M(call_with_current_continuation, CALL_WITH_CURRENT_CONTINUATION, 1, 0, 0)
+
+// ---
diff --git a/module/language/js-il/spec.scm b/module/language/js-il/spec.scm
new file mode 100644
index 0000000..81ca5da
--- /dev/null
+++ b/module/language/js-il/spec.scm
@@ -0,0 +1,12 @@
+(define-module (language js-il spec)
+ #:use-module (system base language)
+ ; #:use-module (language js-il)
+ #:use-module (language js-il compile-javascript)
+ #:export (js-il))
+
+(define-language js-il
+ #:title "Javascript Intermediate Language"
+ #:reader #f
+ #:compilers `((javascript . ,compile-javascript))
+ #:printer #f ; print-js
+ #:for-humans? #f)
- [Guile-commits] branch compile-to-js-merge created (now 6f112d5), Christopher Allan Webber, 2021/10/10
- [Guile-commits] 02/99: Replace values object with values passed as continuation arguments, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 01/99: Temp commit,
Christopher Allan Webber <=
- [Guile-commits] 09/99: get rid of unused match case, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 03/99: Remove jscall type, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 04/99: fix makefile, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 05/99: separate js-il functions into actual functions and those for continuations, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 06/99: Get rid of comments and dead branches, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 07/99: Simple inlining of immediate calls, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 08/99: conditional->branch, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 10/99: fix makefile, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 11/99: Compile rest args, Christopher Allan Webber, 2021/10/10
- [Guile-commits] 16/99: Remove superfluous space, Christopher Allan Webber, 2021/10/10