JSCL
A Lisp-to-Javascript compiler bootstrapped from Common Lisp
@PuercoPop
Algunas Características
- Necesita de un 'run-time'
- Corre en Node y en el Navegador
- Un FFI para llamar código escrito en JS
- Viene con un REPL para Node y el Navegador
(defvar *source*
'(("boot" :target)
("compat" :host)
("setf" :target)
("utils" :both)
("defstruct" :both)
("lambda-list" :both)
("numbers" :target)
("char" :target)
("list" :target)
("array" :target)
("string" :target)
("sequence" :target)
("stream" :target)
("hash-table" :target)
("print" :target)
("misc" :target)
("ffi" :target)
("symbol" :target)
("package" :target)
("read" :both)
("conditions" :both)
("backquote" :both)
("compiler"
("codegen" :both)
("compiler" :both))
("documentation" :target)
("toplevel" :target)))
Boostraping
;; Tests
(compile-application (append (directory "tests.lisp")
(directory "tests/*.lisp")
(directory "tests-report.lisp"))
(merge-pathnames "tests.js" *base-directory*))
;; Web REPL
(compile-application (list #P"repl-web/repl.lisp")
(merge-pathnames "repl-web.js" *base-directory*))
;; Node REPL
(compile-application (list #P"repl-node/repl.lisp")
(merge-pathnames "repl-node.js" *base-directory*))
Compilando tu código
(defun compile-application (files output)
(with-compilation-environment
(with-open-file (out output :direction :output :if-exists :supersede)
(format out "(function(jscl){~%")
(format out "'use strict';~%")
(format out "(function(values, internals){~%")
(dolist (input files)
(!compile-file input out))
(format out "})(jscl.internals.pv, jscl.internals);~%")
(format out "})( typeof require !== 'undefined'? require('./jscl'): window.jscl )~%"))))
Compilando tu código
FFI: Call to JS
-
#j:<function>
-
(oget <obj> &rest keys)
-
js-vref
-
js-vset
-
new
Llamar a una función de JS
(defmacro async (&body body)
`(#j:setTimeout (lambda () ,@body)))
Acceder a una propiedad de un objecto de JS
;; Retrieve a property
(defun length (array)
(oget array "length"))
;; Set a property
(setf (oget my-array 2) "foo")
Crear objectos JS
(let ((obj (new)))
(setf (oget obj "a") 1) obj)
;; Retrieve a variable
(%js-vref "window")
;; Set a variable
(%js-vset "eval_in_lisp"
(lambda (form) (eval (read-from-string form))))
Acceder a variables de JS
Compilador
Tradicionalmente
Lexer -> Parser -> AST -> AST -> Codegen
Lisp
Read -> Macroexpansion -> Compile
compiler.lisp: Rescribiendo S-expressions
define-raw-builtin
define-builtin
codegen.lisp: S-expressions a Javscript
literales
operadores
special forms?
Projectos Similares
JSCL
By puercopop
JSCL
- 725