Skip to content

Commit

Permalink
Make macros persist in REPL
Browse files Browse the repository at this point in the history
This introduces a stateful version of the compiler, which holds on to
the compilation environment and can be given further code to compile
with respect to that environment.  This is great for the REPL, because
it means macros will be stored in the environment and persist for the
session.

It even works with transform macros given on the command line.

Closes anko#17.
  • Loading branch information
anko committed Sep 26, 2015
1 parent a528e52 commit a7bc9c6
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 12 deletions.
7 changes: 6 additions & 1 deletion src/cli.ls
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ else

# Interactive stdin: start repl
else

# Create a stateful instance of the compiler that holds on to a root macro
# environment. This lets typed-in macros persist for the session.
stateful-compiler = esl.stateful compiler-opts

# see https://nodejs.org/api/repl.html
repl = require \repl
vm = require \vm
Expand All @@ -86,6 +91,6 @@ else
# NOTE: will fail on older nodejs due to paren wrapping logic; see
# SO http://stackoverflow.com/questions/19182057/node-js-repl-funny-behavior-with-custom-eval-function
# GH https://github.com/nodejs/node-v0.x-archive/commit/9ef9a9dee54a464a46739b14e8a348bec673c5a5
esl cmd, compiler-opts
stateful-compiler cmd
|> vm.run-in-this-context
|> callback null, _
2 changes: 1 addition & 1 deletion src/env.ls
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# compilation. Environment objects most importantly store the macro table of a
# compilation scope.

{ concat-map, unfoldr, map, reverse, fold } = require \prelude-ls
{ keys, concat-map, unfoldr, map, reverse, fold } = require \prelude-ls
es-generate = require \escodegen .generate _

# Recursively search a macro table and its parents for a macro with a given
Expand Down
19 changes: 17 additions & 2 deletions src/index.ls
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ string-to-ast = require \./parse
ast-to-estree = require \./translate
estree-to-js = (require \escodegen).generate _

module.exports = (input, options={}) ->
root-macro-table = require \./built-in-macros
environment = require \./env

compile = (root-env, input, options={}) ->

input .= to-string!

Expand All @@ -11,5 +14,17 @@ module.exports = (input, options={}) ->

"(#input\n)" # Implicit list of everything (trailing \n terminates comments)
|> string-to-ast
|> ast-to-estree _, transform-macros : options.transform-macros
|> ast-to-estree root-env, _, transform-macros : options.transform-macros
|> estree-to-js


make-stateful-compiler = (options={}) ->
root-env = environment root-macro-table
return compile root-env, _, options

compile-once = (input, options={}) ->
root-env = environment root-macro-table
return compile root-env, input, options

module.exports = compile-once
..stateful = make-stateful-compiler
12 changes: 4 additions & 8 deletions src/translate.ls
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
# Turns an internal AST form into an estree object with reference to the given
# root environment. Throws error unless the resulting estree AST is valid.

{ concat-map } = require \prelude-ls
root-macro-table = require \./built-in-macros
statementify = require \./es-statementify
environment = require \./env
{ list } = require \./ast

{ create-transform-macro } = require \./import-macro

{ errors } = require \esvalid

module.exports = (ast, options) ->
module.exports = (root-env, ast, options={}) ->

transform-macros = (options.transform-macros || []) .map (func) ->
isolated-env = environment root-macro-table
create-transform-macro isolated-env, func

# Create an extra node on the "linked list" of macro tables so multiple runs
# of the compiler have somewhere to put any new macro definitions, without
# changing the underlying root macro table. This guards multiple compiler
# invocations from accidentally influencing each other.
root-env = environment root-macro-table

statements = ast.content

transform-macros .for-each (macro) ->
Expand Down

0 comments on commit a7bc9c6

Please sign in to comment.