def compile_namedlet(self, exp, env, cont, istail=False): """Compile a named let form. At runtime a new frame will be created and the closure will be defined in such frame and applied to the arguments listed in the bindings. """ def got_define(define_code): nonlocal compiled_define_code compiled_define_code = define_code apply_form = cons(proc_name, from_python_list(vall)) return bounce(self.compile_call, apply_form, newenv, got_apply, istail=istail) def got_apply(apply_code): code = [ (inst_extenv,), ] + compiled_define_code + \ apply_code + [ (inst_killenv,), ] return bounce(cont, code) proc_name = cadr(exp) varl = let_vars(caddr(exp)) vall = let_vals(caddr(exp)) lambda_form = lib_append( lib_list( tsym('lambda'), from_python_list(varl)), cdddr(exp)) define_form = lib_list(tsym('define'), proc_name, lambda_form) newenv = Frame([proc_name], outer=env) compiled_define_code = None return bounce(self.compile_define, define_form, newenv, got_define)
def got_test(test_code): nonlocal compiled_test_code compiled_test_code = test_code if cadar(clauses) is tsym('=>'): # current clause is in arrow form (foo => proc) proc = caddar(clauses) return bounce(self.dispatch_exp, proc, env, got_proc, istail=istail) # normal cond clause ((foo x) (bar)) seq = cdar(clauses) defs = define_dumb(seq, env) return bounce(self.compile_sequence, seq, defs, env, got_action, istail=istail)
def compile_define(self, exp, env, cont, istail=False): def got_val(val_code): if var not in env.binds: env.binds.append(var) code = val_code + [ (inst_bindvar, env.get_lexaddr(var)), ] return bounce(cont, code) var, val = cadr(exp), cddr(exp) if lib_issymbol(var): return bounce(self.dispatch_exp, car(val), env, got_val) lambda_form = lib_append(lib_list(tsym('lambda'), cdr(var)), val) var = car(var) return bounce(self.compile_lambda, lambda_form, env, got_val)
def parse_lexeme_datum(self, tokens, cont): token = tokens[0] token_type = token[1] if token_type == TOKEN_TYPE_BOOLEAN: self.consume(tokens, TOKEN_TYPE_BOOLEAN) if token[0] == '#t': return bounce(cont, True) else: return bounce(cont, False) elif token_type == TOKEN_TYPE_STRING: self.consume(tokens, TOKEN_TYPE_STRING) return bounce(cont, token[0][1:-1]) elif token_type == TOKEN_TYPE_SYMBOL: self.consume(tokens, TOKEN_TYPE_SYMBOL) return bounce(cont, tsym(token[0])) elif token_type == TOKEN_TYPE_INTEGER: self.consume(tokens, TOKEN_TYPE_INTEGER) return bounce(cont, int(token[0])) elif token_type == TOKEN_TYPE_FLOAT: self.consume(tokens, TOKEN_TYPE_FLOAT) return bounce(cont, float(token[0])) elif token_type == TOKEN_TYPE_FRACTION: self.consume(tokens, TOKEN_TYPE_FRACTION) numer, denom = token[0].split('/') return bounce(cont, float(numer) / float(denom)) elif token_type == TOKEN_TYPE_COMPLEX: self.consume(tokens, TOKEN_TYPE_COMPLEX) return bounce(cont, complex(token[0].replace('i', 'j'))) else: raise SchemeError(token, 'is not a lexeme datum')
def testLexemeParsing(self): """Test parsing lexemes. """ self.tokenizer.tokenize_piece("aaa" + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], tsym("aaa")) self.tokenizer.tokenize_piece("#t" + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], True) self.tokenizer.tokenize_piece('"helloworld"' + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], "helloworld") self.tokenizer.tokenize_piece('123' + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], 123) self.tokenizer.tokenize_piece('-4/6' + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], -2.0/3.0) self.tokenizer.tokenize_piece('.0' + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], 0.0) self.tokenizer.tokenize_piece('+i' + "\n") obj = self.parser.parse(self.tokenizer.get_tokens()) self.assertEqual(len(obj), 1) self.assertEqual(obj[0], 1j)
def got_action(action_code): nonlocal code if test is tsym('else'): code += action_code + [ label_after, ] return bounce(cont, resolve_label(code)) elif lib_isnull(cdr(clauses)): code += compiled_test_code + [ (inst_jf, label_after), ] + action_code + [ label_after, ] return bounce(cont, resolve_label(code)) else: label_next = label() code += compiled_test_code + [ (inst_jf, label_next), ] + action_code + [ (inst_j, label_after), label_next, ] return bounce(self.compile_clauses, cdr(clauses), code, label_after, env, cont, istail=istail)
def make_quote(word): return bounce(cont, lib_list(tsym('quote'), word))
def compile_clauses(self, clauses, code, label_after, env, cont, istail=False): """Compile clauses of a cond form. Decide if each clause is a normal clause or an arrow clause. If the clause is a normal one, the last expression in the action part of the chosen clause will be in tail position if the whole cond is in tail position; if the clause is an arrow clause, the call will be a tail call. """ def got_test(test_code): nonlocal compiled_test_code compiled_test_code = test_code if cadar(clauses) is tsym('=>'): # current clause is in arrow form (foo => proc) proc = caddar(clauses) return bounce(self.dispatch_exp, proc, env, got_proc, istail=istail) # normal cond clause ((foo x) (bar)) seq = cdar(clauses) defs = define_dumb(seq, env) return bounce(self.compile_sequence, seq, defs, env, got_action, istail=istail) def got_proc(proc_code): nonlocal code if lib_isnull(cdr(clauses)): if istail: code += compiled_test_code + [ (inst_jf, label_after), (inst_clrargs,), (inst_addarg,), ] + proc_code + [ (inst_tailcall,), label_after, ] else: code += compiled_test_code + [ (inst_jf, label_after), (inst_pushr, VM.REG_ARGS), (inst_clrargs,), (inst_addarg,), ] + proc_code + [ (inst_call,), (inst_pop, VM.REG_ARGS), label_after, ] return bounce(cont, resolve_label(code)) else: label_next = label() code += compiled_test_code + [ (inst_jf, label_next), (inst_pushr, VM.REG_ARGS), (inst_clrargs,), (inst_addarg,), ] + proc_code + [ (inst_call,), (inst_pop, VM.REG_ARGS), (inst_j, label_after), label_next, ] return bounce(self.compile_clauses, cdr(clauses), code, label_after, env, cont, istail=istail) def got_action(action_code): nonlocal code if test is tsym('else'): code += action_code + [ label_after, ] return bounce(cont, resolve_label(code)) elif lib_isnull(cdr(clauses)): code += compiled_test_code + [ (inst_jf, label_after), ] + action_code + [ label_after, ] return bounce(cont, resolve_label(code)) else: label_next = label() code += compiled_test_code + [ (inst_jf, label_next), ] + action_code + [ (inst_j, label_after), label_next, ] return bounce(self.compile_clauses, cdr(clauses), code, label_after, env, cont, istail=istail) compiled_test_code = None test = caar(clauses) if test is tsym('else'): defs = define_dumb(cdar(clauses), env) return bounce(self.compile_sequence, cdar(clauses), defs, env, got_action, istail=istail) return bounce(self.dispatch_exp, test, env, got_test)
from closure import Closure from tsymbol import tsym from scmlib import * from prim import * def init_compiletime_env(): return Frame(list(top_bindings.keys())) def init_runtime_env(): return Frame(list(top_bindings.values())) top_bindings = { tsym("+"): Closure((0, -1), prim_add, None, isprim=True), tsym("-"): Closure((1, -1), prim_sub, None, isprim=True), tsym("*"): Closure((0, -1), prim_mul, None, isprim=True), tsym("/"): Closure((1, -1), prim_div, None, isprim=True), tsym("="): Closure((2, -1), prim_eq, None, isprim=True), tsym(">"): Closure((2, -1), prim_gt, None, isprim=True), tsym("<"): Closure((2, -1), prim_lt, None, isprim=True), tsym(">="): Closure((2, -1), prim_ge, None, isprim=True), tsym("<="): Closure((2, -1), prim_le, None, isprim=True), tsym("or"): Closure((0, -1), prim_or, None, isprim=True), tsym("and"): Closure((0, -1), prim_and, None, isprim=True), tsym("not"): Closure((1, 1), prim_not, None, isprim=True), tsym("max"): Closure((1, -1), prim_max, None, isprim=True), tsym("min"): Closure((1, -1), prim_min, None, isprim=True), tsym("abs"): Closure((1, 1), prim_abs, None, isprim=True), tsym("gcd"): Closure((2, 2), prim_gcd, None, isprim=True),
def testSexpParsing(self): """Test parsing S-expressions. """ cases = [("x", tsym("x")), \ ("(x)", from_python_list([tsym("x")])), \ ("(x y)", from_python_list([tsym("x"), tsym("y")])), \ ("(x (y))", from_python_list([tsym("x"), [tsym("y")]])), \ ("(x . y)", cons(tsym("x"), tsym("y"))), \ ("(x y . z)", cons(tsym("x"), cons(tsym("y"), tsym("z")))), \ ("(x (y . z) w)", cons(tsym("x"), cons(cons(tsym("y"), tsym("z")), cons(tsym("w"), NIL))))] for case in cases: sexp = self.parser.parse(self.tokenizer.tokenize(case[0] + '\n'))[0] self.assertEqual(sexp, case[1])