Skip to content

Commit

Permalink
Allow macros to return estree objects
Browse files Browse the repository at this point in the history
This change allows macros to return arbitrary [estree][1] objects as an
alternative to returning arrays and objects as usual.

This means you can now write macros that support estree features that
eslisp doesn't yet (e.g. ES6 arrow functions), as long as [escodegen][2]
supports them.  You can even use crazy experimental estree extensions
(e.g.  Facebook's [JSX][3], or anko#11; ES7 async/await), as long as your
macro can do the appropriate transformation to the core eslisp standard
that escodegen understands before returning.

[1]: https://github.com/estree/estree
[2]: https://github.com/estools/escodegen
[3]: https://github.com/facebook/jsx
  • Loading branch information
anko committed Oct 28, 2015
1 parent ed5bed7 commit bd7ecff
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/import-macro.ls
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ to-compiler-form = (ast) ->
# Objects are expected to represent atoms
| \Object =>
if ast.atom then atom ("" + ast.atom), macro-location-string
else throw Error "Macro returned object without `atom` property, or atom property set to empty string (got #{JSON.stringify ast})"
else
ast # assume the returned object is in estree form

# Strings become strings as you'd expect
| \String => string ast, macro-location-string
Expand Down Expand Up @@ -82,6 +83,7 @@ macro-env = (env) ->
# Create the functions to be exposed for use in a macro's body based on the
# given compilation environment

compile : -> it |> to-compiler-form |> env.compile
evaluate : ->
it |> to-compiler-form |> env.compile |> env.compile-to-js |> eval
multi : (...args) -> multiple-statements args
Expand Down
42 changes: 42 additions & 0 deletions test.ls
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,48 @@ test "macro return intermediates may be invalid if fixed by later macro" ->
'''
..`@equals` "x;"

test "macro can return estree object" ->
esl '''
(macro identifier (lambda ()
(return (object "type" "Identifier"
"name" "x"))))
(identifier)
'''
..`@equals` "x;"

test "macro can multi-return estree objects" ->
esl '''
(macro identifiers (lambda ()
(return ((. this multi)
(object "type" "Identifier"
"name" "x")
(object "type" "Identifier"
"name" "y")))))
(identifiers)
'''
..`@equals` "x;\ny;"

test "macro can multi-return estree objects as well as arrays" ->
esl '''
(macro identifiers (lambda ()
(return ((. this multi)
(object "type" "Identifier"
"name" "x")
'x))))
(identifiers)
'''
..`@equals` "x;\nx;"

test "macro can compile and return parameter as estree" ->
esl '''
(macro that (lambda (x)
(return ((. this compile) x))))
(that 3)
(that "hi")
(that (c))
'''
..`@equals` "3;\n'hi';\nc();"

test "multiple invocations of the compiler are separate" ->
esl "(macro what (lambda () (return 'hi)))"
esl "(what)"
Expand Down

0 comments on commit bd7ecff

Please sign in to comment.