1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 01:57:09 +03:00

RPython: step2 basics.

This commit is contained in:
Joel Martin 2015-06-03 23:01:16 -05:00
parent f0cd131844
commit 2dd89a96de
3 changed files with 117 additions and 9 deletions

View File

@ -3,7 +3,7 @@ RPYTHON = rpython
#PYTHONPATH = /home/joelm/scratch/pypy/rpython
#export PYTHONPATH
STEPS: step0_repl step1_read_print
STEPS: step0_repl step1_read_print step2_eval
all: $(STEPS)
@ -11,6 +11,7 @@ all: $(STEPS)
$(RPYTHON) --output=$@ $<
step1_read_print: mal_types.py reader.py printer.py
step2_eval: mal_types.py reader.py printer.py
clean:
rm -f $(STEPS) *.pyc

View File

@ -142,7 +142,12 @@ def _keywordu(strn):
def _keyword_Q(exp):
return _string_Q(exp) and exp.value[0] == u"\u029e"
### Functions
# Functions
class MalFunc(MalType):
def __init__(self, fn):
self.fn = fn
def apply(self, args):
return self.fn(args)
##def _function(Eval, Env, ast, env, params):
## def fn(*args):
## return Eval(ast, Env(env, params, args))
@ -150,7 +155,9 @@ def _keyword_Q(exp):
## fn.__ast__ = ast
## fn.__gen_env__ = lambda args: Env(env, params, args)
## return fn
##def _function_Q(f): return type(f) == type(function_Q)
def _function_Q(exp):
assert isinstance(exp, MalType)
return exp.__class__ is MalFunc
# lists
class MalList(MalType):
@ -159,12 +166,8 @@ class MalList(MalType):
self.values = vals
def append(self, val):
self.values.append(val)
## def __len__(self):
## return len(self.values)
## def __getitem__(self, i):
## if type(i) == slice: return List(list.__getitem__(self, i))
## elif i >= len(self): return None
## else: return list.__getitem__(self, i)
def __len__(self):
return len(self.values)
## def __add__(self, rhs): return List(list.__add__(self, rhs))
## def __getitem__(self, i):

104
rpython/step2_eval.py Normal file
View File

@ -0,0 +1,104 @@
#import sys, traceback
import mal_readline
import mal_types as types
from mal_types import (MalSym, MalInt, MalStr, _keywordu,
MalList, _list, MalFunc)
import reader, printer
# read
def READ(str):
return reader.read_str(str)
# eval
def eval_ast(ast, env):
if types._symbol_Q(ast):
assert isinstance(ast, MalSym)
if ast.value in env:
return env[ast.value]
else:
raise Exception(u"'" + ast.value + u"' not found")
elif types._list_Q(ast):
res = []
for a in ast.values:
res.append(EVAL(a, env))
return MalList(res)
## elif types._vector_Q(ast):
## return types._vector(*map(lambda a: EVAL(a, env), ast))
## elif types._hash_map_Q(ast):
## keyvals = []
## for k in ast.keys():
## keyvals.append(EVAL(k, env))
## keyvals.append(EVAL(ast[k], env))
## return types._hash_map(*keyvals)
else:
return ast # primitive value, return unchanged
def EVAL(ast, env):
#print("EVAL %s" % printer._pr_str(ast))
if not types._list_Q(ast):
return eval_ast(ast, env)
# apply list
el = eval_ast(ast, env)
f = el.values[0]
if isinstance(f, MalFunc):
return f.apply(el.values[1:])
else:
raise Exception("%s is not callable" % f)
# print
def PRINT(exp):
return printer._pr_str(exp)
# repl
repl_env = {}
def REP(str, env):
return PRINT(EVAL(READ(str), env))
def plus(args):
a, b = args[0], args[1]
assert isinstance(a, MalInt)
assert isinstance(b, MalInt)
return MalInt(a.value+b.value)
def minus(args):
a, b = args[0], args[1]
assert isinstance(a, MalInt)
assert isinstance(b, MalInt)
return MalInt(a.value-b.value)
def multiply(args):
a, b = args[0], args[1]
assert isinstance(a, MalInt)
assert isinstance(b, MalInt)
return MalInt(a.value*b.value)
def divide(args):
a, b = args[0], args[1]
assert isinstance(a, MalInt)
assert isinstance(b, MalInt)
return MalInt(int(a.value/b.value))
repl_env[u'+'] = MalFunc(plus)
repl_env[u'-'] = MalFunc(minus)
repl_env[u'*'] = MalFunc(multiply)
repl_env[u'/'] = MalFunc(divide)
def entry_point(argv):
#mal_readline.init()
while True:
try:
line = mal_readline.readline("user> ")
if line == "": continue
print(REP(line, repl_env))
except EOFError as e:
break
except Exception as e:
print(e)
#print("".join(traceback.format_exception(*sys.exc_info())))
return 0
# _____ Define and setup target ___
def target(*args):
return entry_point
# Just run entry_point if not RPython compilation
import sys
if not sys.argv[0].endswith('rpython'):
entry_point(sys.argv)