mirror of
https://github.com/lloeki/wasp.git
synced 2025-12-06 10:44:39 +01:00
eval + basic stdlib
This commit is contained in:
parent
5bb94d2dda
commit
b6560c6484
5 changed files with 115 additions and 17 deletions
16
repl.py
16
repl.py
|
|
@ -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()
|
|
||||||
|
|
|
||||||
6
test.py
6
test.py
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
16
wasp/ast.py
16
wasp/ast.py
|
|
@ -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
64
wasp/lib.py
Normal 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)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue