def EVAL(ast, env): while True: #print("EVAL %s" % printer._pr_str(ast)) if not types._list_Q(ast): return eval_ast(ast, env) # apply list ast = macroexpand(ast, env) if not types._list_Q(ast): return eval_ast(ast, env) if len(ast) == 0: return ast a0 = ast[0] if "def!" == a0: a1, a2 = ast[1], ast[2] res = EVAL(a2, env) return env.set(a1, res) elif "let*" == a0: a1, a2 = ast[1], ast[2] let_env = Env(env) for i in range(0, len(a1), 2): let_env.set(a1[i], EVAL(a1[i+1], let_env)) ast = a2 env = let_env # Continue loop (TCO) elif "quote" == a0: return ast[1] elif "quasiquote" == a0: ast = quasiquote(ast[1]); # Continue loop (TCO) elif 'defmacro!' == a0: func = types._clone(EVAL(ast[2], env)) func._ismacro_ = True return env.set(ast[1], func) elif 'macroexpand' == a0: return macroexpand(ast[1], env) elif "do" == a0: eval_ast(ast[1:-1], env) ast = ast[-1] # Continue loop (TCO) elif "if" == a0: a1, a2 = ast[1], ast[2] cond = EVAL(a1, env) if cond is None or cond is False: if len(ast) > 3: ast = ast[3] else: ast = None else: ast = a2 # Continue loop (TCO) elif "fn*" == a0: a1, a2 = ast[1], ast[2] return types._function(EVAL, Env, a2, env, a1) else: el = eval_ast(ast, env) f = el[0] if hasattr(f, '__ast__'): ast = f.__ast__ env = f.__gen_env__(el[1:]) else: return f(*el[1:])
def with_meta(args): obj, meta = args[0], args[1] if isinstance(obj, MalMeta): new_obj = types._clone(obj) new_obj.meta = meta return new_obj else: throw_str("with-meta not supported on type")
def EVAL(ast, env): while True: dbgeval = env.get_or_nil('DEBUG-EVAL') if dbgeval is not None and dbgeval is not False: print('EVAL: ' + printer._pr_str(ast)) if types._symbol_Q(ast): return env.get(ast) elif types._vector_Q(ast): return types._vector(*map(lambda a: EVAL(a, env), ast)) elif types._hash_map_Q(ast): return types.Hash_Map((k, EVAL(v, env)) for k, v in ast.items()) elif not types._list_Q(ast): return ast # primitive value, return unchanged else: # apply list if len(ast) == 0: return ast a0 = ast[0] if "def!" == a0: a1, a2 = ast[1], ast[2] res = EVAL(a2, env) return env.set(a1, res) elif "let*" == a0: a1, a2 = ast[1], ast[2] let_env = Env(env) for i in range(0, len(a1), 2): let_env.set(a1[i], EVAL(a1[i + 1], let_env)) ast = a2 env = let_env # Continue loop (TCO) elif "quote" == a0: return ast[1] elif "quasiquote" == a0: ast = quasiquote(ast[1]) # Continue loop (TCO) elif 'defmacro!' == a0: func = types._clone(EVAL(ast[2], env)) func._ismacro_ = True return env.set(ast[1], func) elif "do" == a0: for i in range(1, len(ast) - 1): EVAL(ast[i], env) ast = ast[-1] # Continue loop (TCO) elif "if" == a0: a1, a2 = ast[1], ast[2] cond = EVAL(a1, env) if cond is None or cond is False: if len(ast) > 3: ast = ast[3] else: ast = None else: ast = a2 # Continue loop (TCO) elif "fn*" == a0: a1, a2 = ast[1], ast[2] return types._function(EVAL, Env, a2, env, a1) else: f = EVAL(a0, env) args = ast[1:] if hasattr(f, '_ismacro_'): ast = f(*args) continue # TCO if hasattr(f, '__ast__'): ast = f.__ast__ env = f.__gen_env__(types.List(EVAL(a, env) for a in args)) else: return f(*(EVAL(a, env) for a in args))
def EVAL(ast, env): while True: #print("EVAL %s" % printer._pr_str(ast)) if not types._list_Q(ast): return eval_ast(ast, env) # apply list ast = macroexpand(ast, env) if not types._list_Q(ast): return eval_ast(ast, env) if len(ast) == 0: return ast a0 = ast[0] if "def!" == a0: a1, a2 = ast[1], ast[2] res = EVAL(a2, env) return env.set(a1, res) elif "let*" == a0: a1, a2 = ast[1], ast[2] let_env = Env(env) for i in range(0, len(a1), 2): let_env.set(a1[i], EVAL(a1[i + 1], let_env)) ast = a2 env = let_env # Continue loop (TCO) elif "quote" == a0: return ast[1] elif "quasiquote" == a0: ast = quasiquote(ast[1]) # Continue loop (TCO) elif 'defmacro!' == a0: func = types._clone(EVAL(ast[2], env)) func._ismacro_ = True return env.set(ast[1], func) elif 'macroexpand' == a0: return macroexpand(ast[1], env) elif "py!*" == a0: exec(compile(ast[1], '', 'single'), globals()) return None elif "py*" == a0: return types.py_to_mal(eval(ast[1])) elif "." == a0: el = eval_ast(ast[2:], env) f = eval(ast[1]) return f(*el) elif "try*" == a0: if len(ast) < 3: return EVAL(ast[1], env) a1, a2 = ast[1], ast[2] if a2[0] == "catch*": err = None try: return EVAL(a1, env) except types.MalException as exc: err = exc.object except Exception as exc: err = exc.args[0] catch_env = Env(env, [a2[1]], [err]) return EVAL(a2[2], catch_env) else: return EVAL(a1, env) elif "do" == a0: eval_ast(ast[1:-1], env) ast = ast[-1] # Continue loop (TCO) elif "if" == a0: a1, a2 = ast[1], ast[2] cond = EVAL(a1, env) if cond is None or cond is False: if len(ast) > 3: ast = ast[3] else: ast = None else: ast = a2 # Continue loop (TCO) elif "fn*" == a0: a1, a2 = ast[1], ast[2] return types._function(EVAL, Env, a2, env, a1) else: el = eval_ast(ast, env) f = el[0] if hasattr(f, '__ast__'): ast = f.__ast__ env = f.__gen_env__(el[1:]) else: return f(*el[1:])
def with_meta(obj, meta): new_obj = types._clone(obj) new_obj.__meta__ = meta return new_obj
def EVAL(ast, env): while True: dbgeval = env.get_or_nil('DEBUG-EVAL') if dbgeval is not None and dbgeval is not False: print('EVAL: ' + printer._pr_str(ast)) if types._symbol_Q(ast): return env.get(ast) elif types._vector_Q(ast): return types._vector(*map(lambda a: EVAL(a, env), ast)) elif types._hash_map_Q(ast): return types.Hash_Map((k, EVAL(v, env)) for k, v in ast.items()) elif not types._list_Q(ast): return ast # primitive value, return unchanged else: # apply list if len(ast) == 0: return ast a0 = ast[0] if "def!" == a0: a1, a2 = ast[1], ast[2] res = EVAL(a2, env) return env.set(a1, res) elif "let*" == a0: a1, a2 = ast[1], ast[2] let_env = Env(env) for i in range(0, len(a1), 2): let_env.set(a1[i], EVAL(a1[i+1], let_env)) ast = a2 env = let_env # Continue loop (TCO) elif "quote" == a0: return ast[1] elif "quasiquote" == a0: ast = quasiquote(ast[1]); # Continue loop (TCO) elif 'defmacro!' == a0: func = types._clone(EVAL(ast[2], env)) func._ismacro_ = True return env.set(ast[1], func) elif "py!*" == a0: exec(compile(ast[1], '', 'single'), globals()) return None elif "py*" == a0: return types.py_to_mal(eval(ast[1])) elif "." == a0: el = (EVAL(ast[i], env) for i in range(2, len(ast))) f = eval(ast[1]) return f(*el) elif "try*" == a0: if len(ast) < 3: return EVAL(ast[1], env) a1, a2 = ast[1], ast[2] if a2[0] == "catch*": err = None try: return EVAL(a1, env) except types.MalException as exc: err = exc.object except Exception as exc: err = exc.args[0] catch_env = Env(env, [a2[1]], [err]) return EVAL(a2[2], catch_env) else: return EVAL(a1, env); elif "do" == a0: for i in range(1, len(ast)-1): EVAL(ast[i], env) ast = ast[-1] # Continue loop (TCO) elif "if" == a0: a1, a2 = ast[1], ast[2] cond = EVAL(a1, env) if cond is None or cond is False: if len(ast) > 3: ast = ast[3] else: ast = None else: ast = a2 # Continue loop (TCO) elif "fn*" == a0: a1, a2 = ast[1], ast[2] return types._function(EVAL, Env, a2, env, a1) else: f = EVAL(a0, env) args = ast[1:] if hasattr(f, '_ismacro_'): ast = f(*args) continue # TCO if hasattr(f, '__ast__'): ast = f.__ast__ env = f.__gen_env__(types.List(EVAL(a, env) for a in args)) else: return f(*(EVAL(a, env) for a in args))