def eval_call(func, args): code = func[0] argnames = func[1] fenv = func[2] assert len(argnames) == len(args), "Wrong number of arguments : " + str(argnames) for i in range(len(argnames)): fenv = add_to_env(fenv, argnames[i], args[i]) return eval_expr(fenv, code)
def eval_main(env, code, args): for expr in code: if expr[0] == PARSED_CALL and expr[1][0][1] in ["let", "letrec"] and len(expr[1]) == 3: env = make_binding(env, expr[1][1], expr[1][2], expr[1][0][1] == "letrec") elif expr[0] == PARSED_CALL and expr[1][0][1] in ["let*", "letrec*"] and len(expr[1]) == 2: env = make_bindings(env, expr[1][1], expr[1][0][1] == "letrec*") else: print(show(eval_expr(env, expr))) env = add_to_env(env, "args ", make_string(args)) print(show(eval_expr(env, (PARSED_CALL, [(PARSED_IDENT, "main"), (PARSED_IDENT, "args ")]))))
def bind(env, bind_def, value): if bind_def[0] == PARSED_IDENT: if bind_def[1] == "[]": assert value[0] in [TYPE_NIL, TYPE_UNKNOWN, TYPE_ERROR] return env elif bind_def[1] == "_": return env else: return add_to_env(env, bind_def[1], value) elif is_call_to(bind_def, "cons"): return bind(bind(env, bind_def[1][1], tagged_head(value)), bind_def[1][2], tagged_tail(value))
def make_bindings(env, bds, is_recursive=False): assert bds[0] == PARSED_CALL bds = bds[1] assert all(bd[0] == PARSED_CALL and len(bd[1]) == 2 for bd in bds) bind_defs = tuple(bd[1][0] for bd in bds) bind_values = tuple(bd[1][1] for bd in bds) if is_recursive: assert all(binding_is_func(bind_def) for bind_def in bind_defs) if not is_recursive: newenv = env for bind_def, bind_value in zip(bind_defs, bind_values): if not binding_is_func(bind_def): newenv = bind(newenv, bind_def, eval_expr(env, bind_value)) else: newenv = add_to_env(newenv, bind_def[1][0][1], make_func(env, bind_def[1], bind_value)) return newenv names = [bind_def[1][0][1] for bind_def in bind_defs] frecs = tuple(make_rec(env, names, bind_def, bind_value) for bind_def, bind_value in zip(bind_defs, bind_values)) for i in range(len(names)): env = add_to_env(env, names[i], (TYPE_FIXPOINT, frecs, frecs[i], names[i])) return env
def make_binding(env, bind_def, bind_value, is_recursive=False): if is_recursive: assert binding_is_func(bind_def), "Incorrect recursive binding" if bind_def[0] == PARSED_IDENT: return bind(env, bind_def, eval_expr(env, bind_value)) elif is_call_to(bind_def, "cons"): return bind(env, bind_def, eval_expr(env, bind_value)) elif bind_def[0] == PARSED_CALL: if is_recursive: name = bind_def[1][0][1] frec = make_rec(env, [name], bind_def, bind_value) return add_to_env(env, name, (TYPE_FIXPOINT, (frec,), frec, name)) return make_func_in_env(env, bind_def[1], bind_value) else: raise Exception("Incorrect binding")
def make_func_in_env(env, func_def, func_code): return add_to_env(env, func_def[0][1], make_func(env, func_def, func_code))