eval + basic stdlib

This commit is contained in:
Loic Nageleisen 2014-01-26 18:56:03 +01:00
parent 5bb94d2dda
commit b6560c6484
5 changed files with 115 additions and 17 deletions

16
repl.py
View file

@ -1,5 +1,4 @@
import wasp import wasp
import wasp.parser
import readline import readline
@ -29,21 +28,20 @@ if __name__ == "__main__":
# http://stackoverflow.com/questions/5637124 # http://stackoverflow.com/questions/5637124
#readline.set_completer(complete) #readline.set_completer(complete)
context = wasp.Context()
for line in Reader(">> ", banner="WASP %s" % wasp.VERSION): for line in Reader(">> ", banner="WASP %s" % wasp.VERSION):
if line == "" or line is None: if line == "" or line is None:
continue continue
try: try:
ptree = wasp.parser.parse(line) ast = context['read'](line)
except ValueError, e: except wasp.lib.ReadError, e:
print "Parse error:", e.message print "Parse error:", e.message
continue continue
print " ^ %s" % ptree
try: try:
ast = ptree.ast() print context['eval'](ast, context)
except ValueError, e: except wasp.SymbolError, e:
print "AST error:", e.message print "Undefined symbol:", e.message
continue continue
print "%r" % ast
#ast.eval()

View file

@ -40,6 +40,12 @@ class TestParser(TestCase):
self.assertRaises(ValueError, parser.parse("(42")) self.assertRaises(ValueError, parser.parse("(42"))
class TestAST(TestCase):
def test_lists_in_list(self):
ptree = parser.parse("(+ (* 4 5) (* 3 2))")
repr(ptree.ast())
if __name__ == '__main__': if __name__ == '__main__':
import unittest import unittest
unittest.main() unittest.main()

View file

@ -1 +1,31 @@
from __future__ import print_function
import wasp.lib as lib
VERSION = '0.0.1' VERSION = '0.0.1'
class SymbolError(Exception):
pass
class Context(object):
symbols = {
'+': lib.plus,
'-': lib.minus,
'*': lib.multiply,
'/': lib.div,
'read': lib.read,
'eval': lib.eval,
'print': lib.print,
'apply': lib.apply,
'quote': lib.quote,
}
def __getitem__(self, symbol):
try:
return self.symbols[symbol]
except KeyError:
raise SymbolError(symbol)

View file

@ -7,8 +7,8 @@ class List(Node):
self.car = car self.car = car
self.cdr = cdr self.cdr = cdr
def eval(self): def eval(self, context):
pass return context['apply'](self.car, self.cdr, context)
def __repr__(self): def __repr__(self):
return "<List %r %r>" % (self.car, self.cdr) return "<List %r %r>" % (self.car, self.cdr)
@ -26,7 +26,7 @@ class Number(Atom):
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
def eval(self): def eval(self, context):
return self.value return self.value
def __repr__(self): def __repr__(self):
@ -45,8 +45,8 @@ class Symbol(Atom):
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
def eval(self): def eval(self, context):
return self.value return context[self.value]
def __repr__(self): def __repr__(self):
return "<Symbol %s>" % self.value return "<Symbol %s>" % self.value
@ -56,7 +56,7 @@ class String(Atom):
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
def eval(self): def eval(self, context):
return self.value return self.value
def __repr__(self): def __repr__(self):
@ -67,8 +67,8 @@ class Quote(Node):
def __init__(self, sexpr): def __init__(self, sexpr):
self.sexpr = sexpr self.sexpr = sexpr
def eval(self): def eval(self, context):
return self.sexpr.eval() return context['quote'](self.sexpr)
def __repr__(self): def __repr__(self):
return "<Quote %r>" % self.sexpr return "<Quote %r>" % self.sexpr

64
wasp/lib.py Normal file
View file

@ -0,0 +1,64 @@
from __future__ import print_function
import wasp.parser
py_print = print
py_eval = eval
class ReadError(Exception):
pass
def plus(a, b):
return a + b
def minus(a, b):
return a - b
def multiply(a, b):
return a * b
def div(a, b):
return a / b
def read(string):
try:
ptree = wasp.parser.parse(string)
except ValueError, e:
raise ReadError(e.message)
py_print(" ^ %s" % ptree)
try:
ast = ptree.ast()
except ValueError, e:
raise ReadError(e.message)
py_print("%r" % ast)
return ast
def eval(ast, context):
# eval value unless list
# eval args unless lazy
# eval call
return ast.eval(context)
def apply(a, b, context):
# move to eval
args = [arg.eval(context) for arg in b]
return a.eval(context)(*args)
def quote(a):
return a
def print(string):
py_print(string)