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:
parent
f0cd131844
commit
2dd89a96de
@ -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
|
||||
|
@ -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
104
rpython/step2_eval.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user