def parse_unary(node): if node["type"] != "UNARY": return parse_val_expr(node) prefix_ops = [Unary[v] for v in node["prefix"]] prefix_ops.reverse() p_flag, obj = parse_val_expr(node["obj"]) suffix_ops = list(map(parse_suffix_op, node["suffix"])) def _unary_helper(env, v): for sf in suffix_ops: v = sf(env)(v) for pf in prefix_ops: v = pf(v) return v def _unary(env): v = obj(env) return _unary_helper(env, v) def _unary_partial(env): def warpper(v): return _unary_helper(env, v) return warpper if p_flag == "PARTIAL": return ("PARTIAL", exception_warp(_unary_partial, node["msg"])) for op in node["suffix"]: if op["type"] == "PARTIAL": return ("PARTIAL", exception_warp(_unary, node["msg"])) return ("UNARY", exception_warp(_unary, node["msg"]))
def parse_val_expr(node): t_type = node["type"] if t_type == 'VAR': return parse_var(node) elif t_type == 'LIST': atom = parse_list(node["val"]) elif t_type == 'TUPLE': atom = parse_tuple(node) elif t_type == 'DICT': atom = parse_dict(node) elif t_type in ("BOOL", 'NUM', 'STRING', "NONE"): atom = lambda env: node["val"] elif t_type == 'SYSCALL': atom = parse_syscall(node) elif t_type == 'SYSFUNC': atom = parse_sysfunc(node) elif t_type == 'LAMBDA': atom = parse_lambda(node) elif t_type == 'CASE_LAMBDA': atom = parse_case_lambda(node) elif t_type == 'PARN': atom = parse_parn(node) else: Error("val_expr: " + t_type) return ("VAL", exception_warp(atom, node["msg"]))
def parse_binary_expr(node): g_flag_vals = list(map(parse_unary, node["val"])) g_ops = list(map(parse_bi_oper, node["op"])) g_vals = [] partial_idx = -1 for i in range(len(g_flag_vals)): g_vals.append(g_flag_vals[i][1]) if g_flag_vals[i][0] == "PARTIAL": syntax_cond_assert( partial_idx < 0, "partial binary expression can only have one unknown arg") partial_idx = i def ori_warpper(env): vals, ops = copy.copy(g_vals), copy.copy(g_ops) return compute_expr(env, vals, ops) def partial_warpper(env): def warpper(v): vals, ops = copy.copy(g_vals), copy.copy(g_ops) vals[partial_idx] = lambda env: g_vals[partial_idx](env)(v) return compute_expr(env, vals, ops) return warpper func = ori_warpper if partial_idx < 0 else partial_warpper return exception_warp(func, node["msg"])
def parse_dict(node): keys = parse_list(node["key"]) vals = parse_list(node["val"]) def _dict(env): return dict(zip(keys(env), vals(env))) return exception_warp(_dict, node["msg"])
def parse_elevator_bin(node): g_vals = list(map(parse_simple_expr, node["val"])) g_ops = list(map(parse_bi_oper, node["op"])) def ori_warpper(env): vals, ops = copy.copy(g_vals), copy.copy(g_ops) return compute_expr(env, vals, ops) return exception_warp(ori_warpper, node["msg"])
def parse_pipe(node): g_exprs = list(map(parse_simple_expr, node["exprs"])) g_ops = list(map(parse_bi_oper, node["pipes"])) def _eval_pipe(env): exprs, ops = copy.copy(g_exprs), copy.copy(g_ops) return compute_expr(env, exprs, ops) return exception_warp(_eval_pipe, node["msg"])
def parse_sh(node): cmd = parse_pipe_or_expr(node["cmd"]) def _sh(env): cmd_val = cmd(env) syntax_cond_assert( type(cmd_val) == str, "Value Error: sh handles a string") return osCall(cmd_val) return exception_warp(_sh, node["msg"])
def parse_del(node): names = node["vars"] def _del(env): for name in names: t = env.find(name) if t is None: Error("undefind variable %s" % name) del t[name] return exception_warp(_del, node["msg"])
def parse_cd(node): cmd = parse_pipe_or_expr(node["cmd"]) def _cd(env): cmd_val = cmd(env) syntax_cond_assert( type(cmd_val) in [str, int], "Value Error: cd accept a string or int") return cd(cmd_val) return exception_warp(_cd, node["msg"])
def parse_in(node): v = parse_pipe_or_expr(node["val"]) var = node["var"][0] if len(node["var"]) == 1 else node["var"] def _in(env): for ele in v(env): yield [(var, ele)] def _p_in(env): for ele in v(env): yield lst_combine(var, ele) func = _p_in if type(var) == list else _in return exception_warp(func, node["msg"])
def parse_list_comp(node): interval = lambda env: 1 if 1 != node["interval"]: interval = parse_pipe_or_expr(node["interval"]) beg = parse_pipe_or_expr(node["beg"]) end = parse_pipe_or_expr(node["end"]) def _list_range(env): beg_v = beg(env) end_v = end(env) interval_v = interval(env) return range(beg_v, end_v, interval_v) return exception_warp(_list_range, node["msg"])
def parse_elevator_unary(node): prefix_ops = [Unary[v] for v in node["prefix"]] obj = parse_simple_expr(node["obj"]) def _unary_helper(env, v): for pf in prefix_ops: v = pf(v) return v def _unary(env): v = obj(env) return _unary_helper(env, v) return exception_warp(_unary, node["msg"])
def parse_lambda(node): arg_var_list = node["args"] body_f = parse_block_or_expr(node["body"]) def _lambda(env): def proc(*arg_val_list): syntax_cond_assert(len(arg_var_list) == len(arg_val_list), \ "unmatched arguments, need %d actually %d"%(len(arg_var_list), len(arg_val_list))) new_env = Env(arg_var_list, arg_val_list, outer=env) val = body_f(new_env) del new_env return val return proc return exception_warp(_lambda, node["msg"])
def parse_tuple(node): val = parse_list(node["val"]) return exception_warp(lambda env: tuple(val(env)), node["msg"])