First pass. Grief. Works with cons cells for tree structure.

This commit is contained in:
Elf M. Sternberg 2015-04-03 20:30:02 -07:00
parent ac2b89fa5a
commit 6558843e9b
9 changed files with 65 additions and 57 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ npm-debug.log
node_modules/* node_modules/*
lib/lisp_parser.js lib/lisp_parser.js
tmp/ tmp/
test/

View File

@ -2,4 +2,4 @@ lisp = require '../lib/lisp'
fs = require 'fs' fs = require 'fs'
{inspect} = require 'util' {inspect} = require 'util'
console.log inspect((lisp.run process.argv[2]), true, null, false) console.log lisp.run process.argv[2]

View File

@ -1,16 +1,17 @@
lookup = require './lookup' lookup = require './lookup'
{car, cdr} = require './lists'
lispeval = (element, scope) -> lispeval = (element, scope) ->
switch element.type switch element.type
when 'boolean' then element.value == '#t'
when 'number' then parseInt(element.value, 10) when 'number' then parseInt(element.value, 10)
when 'symbol' when 'symbol'
lookup(scope, element.value) lookup(scope, element.value)
when 'list' when 'list'
proc = lispeval(element.value[0], scope) proc = lispeval((car element.value), scope)
args = element.value.slice(1) args = (cdr element.value)
proc args, scope proc args, scope
else throw new Error ("Unrecognized type in parse: #{element.type}")
else throw new Error ("Unrecognized type in parse")
module.exports = lispeval module.exports = lispeval

View File

@ -1,20 +1,23 @@
lispeval = require './eval' lispeval = require './eval'
{cons} = require './lists' {cons, nil, nilp, car, cdr, listToVector} = require './lists'
module.exports = module.exports =
create_expression_evaluator: (defining_scope, params, body) -> create_vm_expression_evaluator: (defining_scope, params, body) ->
if body instanceof Function (cells, scope) ->
(cells, scope) -> args = listToVector(cells).map (i) -> lispeval i, scope
args = cells.map (i) -> lispeval i, scope body.apply null, args
body.apply null, args
else create_lisp_expression_evaluator: (defining_scope, params, body) ->
(cells, scope) -> (cells, scope) ->
args = cells.map (i) -> lispeval i, scope new_scope = (cmap = (cells, params, nscope) ->
new_scope = {} return nscope if (nilp cells) or (nilp params)
params.forEach (name, i) -> new_scope[name] = args[i] nscope[(car params)] = lispeval (car cells), scope
inner = cons(new_scope, defining_scope) cmap((cdr cells), (cdr params), nscope))(cells, params, {})
body.map((i) -> lispeval i, inner).pop() 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) -> create_special_form_evaluator: (defining_scope, params, body) ->
(cells, scope) -> body(cells, scope) (cells, scope) -> body(cells, scope)

View File

@ -1,12 +1,17 @@
fs = require 'fs' fs = require 'fs'
{parse} = require './lisp_parser' {readForms} = require './reader'
lisp = require './parser' lispeval = require './eval'
{scope} = require './scope' scope = require './scope'
{inspect} = require 'util' {car, cdr, nilp} = require './lists'
module.exports = module.exports =
run: (pathname) -> run: (pathname) ->
text = fs.readFileSync(pathname, 'utf8') text = fs.readFileSync(pathname, 'utf8')
ast = parse(text) root = scope
return lisp(ast, scope) ast = readForms(text)
(nval = (body, memo) ->
return memo if nilp body
nval((cdr body), lispeval((car body), root)))(ast.value)

View File

@ -1,8 +0,0 @@
lispeval = require './eval'
lisp = (ast, scope) ->
ast.map((e) -> lispeval(e, scope)).pop()
module.exports = lisp

View File

@ -31,8 +31,11 @@ skipWS = (inStream) ->
while inStream.peek() in WHITESPACE then inStream.next() while inStream.peek() in WHITESPACE then inStream.next()
# (type, value, line, column) -> (node {type, value, line, column)} # (type, value, line, column) -> (node {type, value, line, column)}
makeObj = (type, value, line, column) -> makeObj = (type, value, line, column) ->
cons type, (cons value, (cons line, (cons column))) 'type': type
'value': value
'line': line
'column': column
# msg -> (IO -> Node => Error) # msg -> (IO -> Node => Error)
handleError = (message) -> handleError = (message) ->

View File

@ -1,28 +1,32 @@
parser = require './parser'
lispeval = require './eval' lispeval = require './eval'
{cons, car, cdr, nilp} = require './lists' {cons, car, cdr, nilp, nil} = require './lists'
{create_expression_evaluator, create_special_form_evaluator} = require './fn' {create_lisp_expression_evaluator, create_vm_expression_evaluator, create_special_form_evaluator} = require './fn'
lookup = require './lookup'
scope = cons scope = cons
'+': create_expression_evaluator scope, [], (a, b) -> a + b '+': create_vm_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_expression_evaluator scope, [], (a, b) -> a * b '*': create_vm_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_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 = (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) -> 'lambda': create_special_form_evaluator scope, [], (nodes, scope) ->
params = list[0].value.map (n) -> return n.value param_nodes = (car nodes).value
create_expression_evaluator(scope, params, list.slice(1)) 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) -> 'if': create_special_form_evaluator scope, [], (nodes, scope) ->
lispeval(list[if lispeval(list[0], scope) then 1 else 2], scope) if lispeval((car nodes), scope)
lispeval((car cdr nodes), scope)
else
lispeval((car cdr cdr nodes), scope)
module.exports = scope
module.exports =
lookup: lookup
scope: scope

View File

@ -1 +0,0 @@
true