Skip to content
David Vázquez Púa edited this page Aug 9, 2016 · 6 revisions

Debugging the compiler

Load jscl.lisp into your Lisp implementation and switch to the new jscl package. You will want to bootstrap the project most of the time:

JSCL> (bootstrap)

as this will fill the global environment with all the macros that you would expect. The compiler is implemented in compiler/compiler.lisp.

There are a few entry points you may want to invoke. But you have to invoke all of them in the body of the with-compilation-environment macro, which set some dynamic variables that are needed. The entry-points are:

  • compile-toplevel, which takes a toplevel Lisp expression and return the output Javascript code. For example
(with-compilation-environment
   (compile-toplevel 'x))

=>

var l1=internals.intern('X');
internals.symbolValue(l1);
  • convert, that is the main recursive function that is called to compile every subform. It will macro-expand a form and dispatch according to the type of form it is. The result of convert is S-Expression representing Javascript syntax. This is a good function to trace:
(with-compilation-environment
  (compile-toplevel 'x))
;  0: (CONVERT X NIL)
;    1: (CONVERT (SYMBOL-VALUE 'X))
;      2: (CONVERT 'X)
;      2: CONVERT returned #:|l1|
;    1: CONVERT returned (CALL-INTERNAL |symbolValue| #:|l1|)
;  0: CONVERT returned (CALL-INTERNAL |symbolValue| #:|l1|)
"var l1=internals.intern('X');
internals.symbolValue(l1);
"
  • process-toplevel, however, more convenient to call interactively. It will collect also some additional code that some forms emit and will return the resulting JS syntax:
(with-compilation-environment
  (process-toplevel 'x))
; =>
; (PROGN
;   (VAR (#:|l1| (CALL-INTERNAL |intern| "X")))
;   (CALL-INTERNAL |symbolValue| #:|l1|))

The JS syntax can be converted to string with the js function, defined into compiler/codegen.js.

Clone this wiki locally