Skip to content

Instantly share code, notes, and snippets.

@robotlolita
Last active July 17, 2017 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robotlolita/1966465 to your computer and use it in GitHub Desktop.
Save robotlolita/1966465 to your computer and use it in GitHub Desktop.
Really naïve and small subset of Lisp
ometa NaiveLispParser {
fromTo :x :y = seq(x) (~seq(y) char*) seq(y),
space = ^space | fromTo(';', '\n'),
symbol = '+' | '=' | '-' | '_' | '*' | '%' | '!' | '/' | '^' | '>' | '<',
idChars = symbol | letterOrDigit,
nil = spaces "nil" -> #nil,
id = spaces idChars+:id -> [#id, id.join('')],
num = spaces digit+:d -> [#num, Number(d.join(''))],
funcall = "(" expr:hd (spaces expr)*:tl ")" -> [hd, tl],
expr = funcall | num | id
}
ometa NaiveLispCompiler {
eval = #nil
| [#num :a] -> a
| [#id :a] -> { 'self.env["' + a + '"]' }
| [eval:hd [eval:tl0 eval:tl1]] -> { '(' + hd + ')(' + tl0 + ', ' + tl1 + ')' }
}
ometa NaiveLispInterpreter {
eval = #nil
| [#num :a] -> a
| [#id :a] -> self.env[a]
| [eval:hd [eval:tl0 eval:tl1]] -> hd(tl0, tl1)
}
NaiveLispInterpreter.initialize = function() {
this.env = { "+": function(a,b){ return a + b }
, "-": function(a,b){ return a - b }
, "*": function(a,b){ return a * b }
, "/": function(a,b){ return a / b }
, "%": function(a,b){ return a % b }
}
}
NaiveLispCompiler.initialize = NaiveLispInterpreter.initialize
evaluate = function(sexp){ return NaiveLispInterpreter.match(NaiveLispParser.matchAll(sexp, 'expr'), 'eval') }
evaluate('(+ 3 (/ 4 2))')
// ==> 5
compile = function(sexp) { return NaiveLispCompiler.match(NaiveLispParser.matchAll(sexp, 'expr'), 'eval') }
compile('(+ 3 (/ 4 2))')
// ==> "(self['+'](3, self['/'](4, 2))"
// ^ Lisp -> JavaScript
eval("var self = { '+'(a, b) { return a + b }, '/'(a, b) { return a / b } }; " + compile('(+ 3 (/ 4 2))'));
// ==> 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment