First pass. Grief. Works with cons cells for tree structure.
This commit is contained in:
parent
ac2b89fa5a
commit
6558843e9b
|
@ -6,3 +6,4 @@ npm-debug.log
|
|||
node_modules/*
|
||||
lib/lisp_parser.js
|
||||
tmp/
|
||||
test/
|
||||
|
|
2
bin/lisp
2
bin/lisp
|
@ -2,4 +2,4 @@ lisp = require '../lib/lisp'
|
|||
fs = require 'fs'
|
||||
{inspect} = require 'util'
|
||||
|
||||
console.log inspect((lisp.run process.argv[2]), true, null, false)
|
||||
console.log lisp.run process.argv[2]
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
lookup = require './lookup'
|
||||
{car, cdr} = require './lists'
|
||||
|
||||
lispeval = (element, scope) ->
|
||||
|
||||
switch element.type
|
||||
when 'boolean' then element.value == '#t'
|
||||
when 'number' then parseInt(element.value, 10)
|
||||
when 'symbol'
|
||||
lookup(scope, element.value)
|
||||
when 'list'
|
||||
proc = lispeval(element.value[0], scope)
|
||||
args = element.value.slice(1)
|
||||
proc = lispeval((car element.value), scope)
|
||||
args = (cdr element.value)
|
||||
proc args, scope
|
||||
|
||||
else throw new Error ("Unrecognized type in parse")
|
||||
else throw new Error ("Unrecognized type in parse: #{element.type}")
|
||||
|
||||
module.exports = lispeval
|
||||
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
lispeval = require './eval'
|
||||
{cons} = require './lists'
|
||||
{cons, nil, nilp, car, cdr, listToVector} = require './lists'
|
||||
|
||||
module.exports =
|
||||
create_expression_evaluator: (defining_scope, params, body) ->
|
||||
if body instanceof Function
|
||||
(cells, scope) ->
|
||||
args = cells.map (i) -> lispeval i, scope
|
||||
body.apply null, args
|
||||
else
|
||||
(cells, scope) ->
|
||||
args = cells.map (i) -> lispeval i, scope
|
||||
new_scope = {}
|
||||
params.forEach (name, i) -> new_scope[name] = args[i]
|
||||
inner = cons(new_scope, defining_scope)
|
||||
body.map((i) -> lispeval i, inner).pop()
|
||||
|
||||
create_vm_expression_evaluator: (defining_scope, params, body) ->
|
||||
(cells, scope) ->
|
||||
args = listToVector(cells).map (i) -> lispeval i, scope
|
||||
body.apply null, args
|
||||
|
||||
create_lisp_expression_evaluator: (defining_scope, params, body) ->
|
||||
(cells, scope) ->
|
||||
new_scope = (cmap = (cells, params, nscope) ->
|
||||
return nscope if (nilp cells) or (nilp params)
|
||||
nscope[(car params)] = lispeval (car cells), scope
|
||||
cmap((cdr cells), (cdr params), nscope))(cells, params, {})
|
||||
inner = cons(new_scope, defining_scope)
|
||||
(nval = (body, memo) ->
|
||||
return memo if nilp body
|
||||
nval((cdr body), lispeval((car body), inner)))(body)
|
||||
|
||||
create_special_form_evaluator: (defining_scope, params, body) ->
|
||||
(cells, scope) -> body(cells, scope)
|
||||
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
fs = require 'fs'
|
||||
{parse} = require './lisp_parser'
|
||||
lisp = require './parser'
|
||||
{scope} = require './scope'
|
||||
{inspect} = require 'util'
|
||||
{readForms} = require './reader'
|
||||
lispeval = require './eval'
|
||||
scope = require './scope'
|
||||
{car, cdr, nilp} = require './lists'
|
||||
|
||||
module.exports =
|
||||
run: (pathname) ->
|
||||
text = fs.readFileSync(pathname, 'utf8')
|
||||
ast = parse(text)
|
||||
return lisp(ast, scope)
|
||||
root = scope
|
||||
ast = readForms(text)
|
||||
(nval = (body, memo) ->
|
||||
return memo if nilp body
|
||||
nval((cdr body), lispeval((car body), root)))(ast.value)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
lispeval = require './eval'
|
||||
|
||||
lisp = (ast, scope) ->
|
||||
ast.map((e) -> lispeval(e, scope)).pop()
|
||||
|
||||
module.exports = lisp
|
||||
|
||||
|
|
@ -31,8 +31,11 @@ skipWS = (inStream) ->
|
|||
while inStream.peek() in WHITESPACE then inStream.next()
|
||||
|
||||
# (type, value, line, column) -> (node {type, value, line, column)}
|
||||
makeObj = (type, value, line, column) ->
|
||||
cons type, (cons value, (cons line, (cons column)))
|
||||
makeObj = (type, value, line, column) ->
|
||||
'type': type
|
||||
'value': value
|
||||
'line': line
|
||||
'column': column
|
||||
|
||||
# msg -> (IO -> Node => Error)
|
||||
handleError = (message) ->
|
||||
|
|
|
@ -1,28 +1,32 @@
|
|||
parser = require './parser'
|
||||
lispeval = require './eval'
|
||||
{cons, car, cdr, nilp} = require './lists'
|
||||
{create_expression_evaluator, create_special_form_evaluator} = require './fn'
|
||||
lookup = require './lookup'
|
||||
{cons, car, cdr, nilp, nil} = require './lists'
|
||||
{create_lisp_expression_evaluator, create_vm_expression_evaluator, create_special_form_evaluator} = require './fn'
|
||||
|
||||
scope = cons
|
||||
'+': create_expression_evaluator scope, [], (a, b) -> a + b
|
||||
'-': create_expression_evaluator scope, [], (a, b) -> a - b
|
||||
'*': create_expression_evaluator scope, [], (a, b) -> a * b
|
||||
'/': create_expression_evaluator scope, [], (a, b) -> a / b
|
||||
'==': create_expression_evaluator scope, [], (a, b) -> a == b
|
||||
'+': create_vm_expression_evaluator scope, [], (a, b) -> a + b
|
||||
'-': create_vm_expression_evaluator scope, [], (a, b) -> a - b
|
||||
'*': create_vm_expression_evaluator scope, [], (a, b) -> a * b
|
||||
'/': create_vm_expression_evaluator scope, [], (a, b) -> a / b
|
||||
'==': create_vm_expression_evaluator scope, [], (a, b) -> a == b
|
||||
'#t': true
|
||||
'#f': false
|
||||
|
||||
'define': create_special_form_evaluator scope, [], (list, scope) ->
|
||||
'define': create_special_form_evaluator scope, [], (nodes, scope) ->
|
||||
current = (car scope)
|
||||
current[list[0].value] = lispeval(list[1], scope)
|
||||
current[(car nodes).value] = lispeval((car cdr nodes), scope)
|
||||
|
||||
'lambda': create_special_form_evaluator scope, [], (list, scope) ->
|
||||
params = list[0].value.map (n) -> return n.value
|
||||
create_expression_evaluator(scope, params, list.slice(1))
|
||||
'lambda': create_special_form_evaluator scope, [], (nodes, scope) ->
|
||||
param_nodes = (car nodes).value
|
||||
reducer = (l) ->
|
||||
if (nilp l) then nil else cons((car l).value, reducer(cdr l))
|
||||
param_names = reducer(param_nodes)
|
||||
|
||||
create_lisp_expression_evaluator(scope, param_names, (cdr nodes))
|
||||
|
||||
'if': create_special_form_evaluator scope, [], (list, scope) ->
|
||||
lispeval(list[if lispeval(list[0], scope) then 1 else 2], scope)
|
||||
'if': create_special_form_evaluator scope, [], (nodes, scope) ->
|
||||
if lispeval((car nodes), scope)
|
||||
lispeval((car cdr nodes), scope)
|
||||
else
|
||||
lispeval((car cdr cdr nodes), scope)
|
||||
|
||||
|
||||
module.exports =
|
||||
lookup: lookup
|
||||
scope: scope
|
||||
module.exports = scope
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
true
|
Loading…
Reference in New Issue