示例#1
0
def try_block(ctx, list_w):
    _, w_body, w_catch, w_finally = list_w
    fn_code = fn(ctx, unwrap(w_body))
    if w_catch is w_nil:
        catch_code = []
    else:
        catch_code = fn(ctx, unwrap(w_catch)) + [ops.INVOKE, 1]
    finally_id = fn(ctx, unwrap(w_finally))[1] if w_finally is not w_nil else -1
    return fn_code + [ops.TRY, finally_id, 1 + len(catch_code)] + catch_code
示例#2
0
def emit_quasiquoted_list(ctx, w_val, recur):
    list_w = unwrap(w_val)
    if is_unquote(list_w):
        code = emit(ctx, list_w[1])
        return code
    else:
        code = []
        list = unwrap(w_val)
        for w_elem in list:
            code += recur(ctx, w_elem) + [ops.PUSH]
        return code + [ops.SYM, ctx.st().add_sym("list"), ops.INVOKE, len(list)]
示例#3
0
def mkfn(ctx, w_args, body_w):
    args = []
    rest_args_id = -1
    arg_vec_w = unwrap(cast(w_args, W_Seq))
    idx = 0
    st = ctx.st()
    while idx < len(arg_vec_w):
        w_arg = cast(arg_vec_w[idx], W_Sym)
        if w_arg.val == '&':
            assert idx == len(arg_vec_w) - 2
            w_last = cast(arg_vec_w[idx + 1], W_Sym)
            rest_args_id = st.add_sym(w_last.val)
            break
        else:
            args.append(w_arg.val)
        idx += 1
    ids = []
    for arg in args:
        id = st.add_sym(arg)
        ids.append(id)
    if len(ids) > 0 or rest_args_id >= 0:
        recur_bindings = (ids, rest_args_id)
    else:
        recur_bindings = empty_recur_bindings
    code = []
    for w_elem in body_w:
        code += emit(ctx, w_elem, recur_bindings)
    return st.add_fn(W_Fun(code, ids, rest_args_id))
示例#4
0
 def invoke(self, args, ctx):
     form = args[0]
     if not isinstance(form, space.W_List):
         return form
     head = form.first()
     if not isinstance(head, space.W_Sym):
         return form
     st = ctx.st()
     val = head.val
     if not st.has_macro(val):
         return form
     macro_fn = st.get_fn(st.get_macro(val))
     return eval.invoke_fn(macro_fn, space.unwrap(form.rest()), ctx)
示例#5
0
文件: eval.py 项目: emidln/psota
def apply(ip, env, code, r1, stack, sp, ctx):
    ip += 1
    assert code[ip] == 2
    new_sp = sp - 2
    assert new_sp >= 0
    (fn, w_args) = stack[new_sp : sp]
    sp = new_sp
    args = space.unwrap(w_args)
    argc = len(args)
    if isinstance(fn, space.W_Fun):
        arg_ids_len = len(fn.arg_ids)
        if fn.env.on_stack:
            new_env = Env([], fn.env)
        else:
            new_env = fn.env
        try:
            new_env.mark_used()
            if (argc < arg_ids_len or
                    (argc > arg_ids_len and not fn.got_rest_args())):
                raise space.ArityException(argc, arg_ids_len)
            if argc > arg_ids_len and fn.got_rest_args():
                rest_args = [args.pop() for _ in range(argc - arg_ids_len)]
                rest_args.reverse()
                new_env.set(fn.rest_args_id, space.wrap(rest_args))
            elif fn.got_rest_args():
                new_env.set(fn.rest_args_id, space.w_empty_list)
            idx = 0
            for arg_id in fn.arg_ids:
                new_env.set(arg_id, args[idx])
                idx += 1
            return eval(ctx, new_env, fn.code)
        finally:
            new_env.mark_free()
    else:
        ret = fn.invoke(args, ctx)
        if ret is None:
            ret = space.w_nil
        return ret
示例#6
0
def emit_list(ctx, node, recur_bindings):
    st = ctx.st()
    list_w = unwrap(node)
    if len(list_w) == 0:
        return [ops.SYM, st.add_sym("list"), ops.INVOKE, 0]
    w_head = list_w[0]
    args_w = list_w[1:]
    if isinstance(w_head, W_Sym):
        head = w_head.val
        if head == "if":
            cond_code = emit(ctx, list_w[1])
            true_code = emit(ctx, list_w[2], recur_bindings)
            false_code = emit(ctx, list_w[3], recur_bindings)
            jmp_code = [ops.RELJMP, len(false_code)]
            code = (cond_code + [ops.IF, len(true_code) + len(jmp_code)] +
                    true_code + jmp_code + false_code)
            return code
        elif head == "let*":
            sym = cast(list_w[1], W_Sym)
            binding_code = emit(ctx, list_w[2])
            id = st.add_sym(sym.val)
            inner_code = emit(ctx, list_w[3], recur_bindings)
            code = binding_code + [ops.PUSH_ENV, id] + inner_code + [ops.POP_ENV]
            return code
        elif head == "do":
            body_code = []
            for step in list_w[1:]:
                body_code += emit(ctx, step, recur_bindings)
            return body_code
        elif head == "quote":
            return emit_quote(ctx, list_w[1])
        elif head == "qquote*":
            return emit_quasiquote(ctx, list_w[1])
        elif head == "fn*":
            return fn(ctx, list_w)
        elif head == "defmacro*":
            return defmacro(ctx, list_w)
        elif head == "def*":
            var_sym = cast(list_w[1], W_Sym)
            id = st.add_sym(var_sym.val)
            val_code = emit(ctx, list_w[2])
            return val_code + [ops.DEF, id]
        elif head == "try*":
            return try_block(ctx, list_w)
        elif head == "recur":
            args = list_w[1:]
            args_code = []
            (ids, rest_id) = recur_bindings
            if len(args) < len(ids):
                msg = "Invalid number of recur arguments: %s given, %s expected"
                raise CompilationException(msg % (len(args), len(ids)))
            for arg in args:
                c = emit(ctx, arg)
                args_code += c + [ops.PUSH]
            if recur_bindings == no_recur_bindings:
                raise CompilationException("Not a recur point :o")
            bindings_ids = [x for x in reversed(ids)] + \
                    [rest_id if rest_id >= 0 else -1]
            return args_code + [ops.RECUR, len(args)] + bindings_ids
        elif st.has_macro(head):
            return expand_macro(ctx, st.get_macro(head), list_w[1:], recur_bindings)
        elif head == "apply":
            args_code = []
            for arg in args_w:
                c = emit(ctx, arg)
                args_code += c + [ops.PUSH]
            return args_code + [ops.APPLY, len(args_w)]
    args_code = []
    for arg in args_w:
        c = emit(ctx, arg)
        args_code += c + [ops.PUSH]
    fn_code = emit(ctx, w_head)
    return args_code + fn_code + [ops.INVOKE, len(args_w)]
示例#7
0
def emit_quoted_list(ctx, w_val, recur):
    code = []
    list = unwrap(w_val)
    for w_elem in list:
        code += recur(ctx, w_elem) + [ops.PUSH]
    return code + [ops.SYM, ctx.st().add_sym("list"), ops.INVOKE, len(list)]
示例#8
0
文件: compiler.py 项目: emidln/psota
def try_block(ctx, list_w):
    _, w_body, w_catch = list_w
    fn_code = fn(ctx, unwrap(w_body))
    catch_code = fn(ctx, unwrap(w_catch))
    return fn_code + [ops.TRY, 3 + len(catch_code)] + catch_code + [ops.INVOKE, 1]