Recap - Lexing & Parsing
print( x + 2 );
becomes:
("call",
("symbol", "print"),
[
("operation",
"+",
("symbol", "x"),
("number", "2")
)
]
)
Evaluation is finding values
Scope
x = "World!";
myfn = {
x = "Hello, ";
print( x );
};
myfn();
print( x );
Scope
x = "World!";
myfn = {
x = "Hello, ";
print( x );
};
myfn();
print( x );
Hello,
World!
Scope
outerfn = {
x = 12;
innerfn = {
print(x);
};
innerfn;
};
thing = outerfn();
thing();
Scope
outerfn = {
x = 12;
innerfn = {
print(x);
};
innerfn;
};
thing = outerfn();
thing();
12
Environments
class Env:
# ...
def get(self, name):
if name in self.items:
return self.items[name]
elif self.parent is not None:
return self.parent.get(name)
else:
return None
Environments
class Env:
# ...
def set(self, name, value):
self.items[name] = value
Cell's evaluator
def eval_expr(expr, env):
typ = expr[0]
if typ == "number": ...
elif typ == "string": ...
elif typ == "none": ...
elif typ == "operation": ...
elif typ == "symbol": ...
elif typ == "assignment": ...
elif typ == "call": ...
elif typ == "function": ...
else: ...
Cell's evaluator
def eval_expr(expr, env):
...
if typ == "number":
return ("number", float(expr[1]))
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "string":
return ("string", expr[1])
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "none":
return ("none",)
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "operation":
return _operation(expr, env)
Cell's evaluator
def _operation(expr, env):
arg1 = eval_expr(expr[2], env)
arg2 = eval_expr(expr[3], env)
if expr[1] == "+":
return ("number", arg1[1] + arg2[1])
elif expr[1] == "-":
return ("number", arg1[1] - arg2[1])
# ...
else:
raise Exception("Unknown operation: " + expr[1])
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "symbol":
name = expr[1]
ret = env.get(name)
if ret is None:
raise Exception("Unknown symbol '%s'." % name)
else:
return ret
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "assignment":
var_name = expr[1][1]
val = eval_expr(expr[2], env)
env.set(var_name, val)
return val
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "call":
return _function_call(expr, env)
Cell's evaluator
def _function_call(expr, env):
fn = eval_expr(expr[1], env)
args = list((eval_expr(a, env) for a in expr[2]))
if fn[0] == "function": ...
elif fn[0] == "native": ...
else: ...
Cell's evaluator
args = list((eval_expr(a, env) for a in expr[2]))
...
if fn[0] == "function":
params = fn[1]
fail_if_wrong_number_of_args(expr[1], params, args)
body = fn[2]
fn_env = fn[3]
new_env = Env(fn_env)
for p, a in zip(params, args):
new_env.set(p[1], a)
return eval_list(body, new_env)
Cell's evaluator
args = list((eval_expr(a, env) for a in expr[2]))
...
if fn[0] == "function": ...
elif fn[0] == "native":
py_fn = fn[1]
params = inspect.getargspec(py_fn).args
fail_if_wrong_number_of_args(expr[1], params[1:], args)
return fn[1](env, *args)
Cell's evaluator
args = list((eval_expr(a, env) for a in expr[2]))
...
if fn[0] == "function": ...
elif fn[0] == "native":
else:
raise Exception( "Not a function: %s" % str(fn))
Cell's evaluator
def eval_expr(expr, env):
...
elif typ == "function":
return ("function", expr[1], expr[2], Env(env))
Cell's evaluator
def eval_expr(expr, env):
...
else:
raise Exception("Unknown expression type: " + str(expr))
End result: value + side effects