예제 #1
0
파일: builtins.py 프로젝트: jstepien/psota
 def invoke(self, args, *_):
     acc = ""
     for w_arg in args:
         if isinstance(w_arg, space.W_String):
             acc += w_arg.val
         else:
             acc += w_arg.to_str()
     return space.wrap(acc)
예제 #2
0
파일: eval.py 프로젝트: emidln/psota
def invoke(ip, env, code, r1, stack, sp, ctx):
    ip += 1
    sp = jit.promote(sp)
    argc = jit.promote(get_op(code, ip))
    assert argc >= 0
    fn = jit.promote(r1)
    if isinstance(fn, space.W_Fun):
        arg_ids_len = const_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():
                new_sp = sp - (argc - arg_ids_len)
                assert new_sp >= 0
                rest_args = [space.w_nil for _ in range(argc - arg_ids_len)]
                for i in range(new_sp, sp):
                    rest_args[i - new_sp] = stack[jit.promote(i)]
                sp = new_sp
                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)
            sp -= arg_ids_len
            idx = 0
            for arg_id in fn.arg_ids:
                new_env.set(arg_id, stack[jit.promote(idx + sp)])
                idx += 1
            return eval(ctx, new_env, fn.code)
        finally:
            new_env.mark_free()
    else:
        new_sp = sp - argc
        assert new_sp >= 0
        args = [space.w_nil for _ in range(argc)]
        for i in range(new_sp, sp):
            args[i - new_sp] = stack[i]
        ret = fn.invoke(args, ctx)
        if ret is None:
            ret = space.w_nil
        return ret
예제 #3
0
파일: eval.py 프로젝트: emidln/psota
def invoke_fn(w_fn, args_w, ctx):
    w_fn = space.cast(w_fn, space.W_Fun)
    argc = len(args_w)
    arg_ids_len = len(w_fn.arg_ids)
    rest_args = space.w_empty_list
    if argc > arg_ids_len and w_fn.got_rest_args():
        rest_args = [args_w.pop() for _ in range(argc - arg_ids_len)]
        rest_args.reverse()
        rest_args = space.wrap(rest_args)
    args = [args_w.pop() for _ in range(arg_ids_len)]
    idx = 0
    env = Env([], w_fn.env)
    for arg_id in reversed(w_fn.arg_ids):
        env.set(arg_id, args[idx])
        idx += 1
    if w_fn.got_rest_args():
        env.set(w_fn.rest_args_id, rest_args)
    return eval(ctx, env, w_fn.code)
예제 #4
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
예제 #5
0
파일: parser.py 프로젝트: emidln/psota
def lambda_expr(sexpr):
    return wrap([W_Sym('#'), sexpr])
예제 #6
0
파일: parser.py 프로젝트: emidln/psota
def unquote(sexpr):
    return wrap([W_Sym('~'), sexpr])
예제 #7
0
파일: parser.py 프로젝트: emidln/psota
def quasiquote(sexpr):
    return wrap([W_Sym('qquote'), sexpr])
예제 #8
0
파일: eval.py 프로젝트: emidln/psota
def eval(ctx, env, code):
    ip = 0
    stack = empty_stack
    sp = 0
    r1 = space.w_nil
    while ip < const_len(code):
        jitdriver.jit_merge_point(
                ip=ip,
                sp=sp,
                stack=stack,
                ctx=ctx,
                env=env,
                code=code,
                r1=r1,
                )
        assert r1 is not None
        assert sp >= 0
        op = get_op(code, ip)
        if op == ops.IF:
            ip += 1
            if not space.is_true(r1):
                ip += get_op(code, ip)
        elif op == ops.SYM:
            ip += 1
            r1 = lookup(env, ctx, get_op(code, ip))
        elif op == ops.KEYWORD:
            ip += 1
            r1 = space.W_Keyword(ctx.st().get_sym(get_op(code, ip)))
        elif op == ops.STRING:
            ip += 1
            r1 = space.W_String(ctx.st().get_sym(get_op(code, ip)))
        elif op == ops.INT:
            ip += 1
            r1 = space.W_Int(get_op(code, ip))
        elif op == ops.PUSH_ENV:
            ip += 1
            env = Env([(get_op(code, ip), r1)], env)
        elif op == ops.POP_ENV:
            env = env.parent
        elif op == ops.QUOTE:
            ip += 1
            r1 = space.W_Sym(ctx.st().get_sym(get_op(code, ip)))
        elif op == ops.RELJMP:
            ip += get_op(code, ip + 1) + 1
        elif op == ops.FN:
            ip += 1
            r1 = ctx.st().get_fn(get_op(code, ip)).with_env(env)
        elif op == ops.PUSH:
            if stack is empty_stack:
                stack = [None for _ in range(stack_size)]
            stack[jit.promote(sp)] = r1
            sp += 1
        elif op == ops.DEF:
            ip += 1
            ctx.bindings().set(get_op(code, ip), r1)
        elif op == ops.RECUR:
            ip += 1
            argc = jit.promote(get_op(code, ip))
            sp -= argc
            idx = argc - 1
            while idx >= 0:
                ip += 1
                env.set(get_op(code, ip), stack[jit.promote(idx + sp)])
                idx -= 1
            ip = -1
        elif op == ops.INVOKE:
            r1 = invoke(ip, env, code, r1, stack, sp, ctx)
            ip += 1
            sp -= get_op(code, ip)
        elif op == ops.APPLY:
            r1 = apply(ip, env, code, r1, stack, sp, ctx)
            ip += 1
            sp -= 2
        elif op == ops.TRY:
            try:
                assert isinstance(r1, space.W_Fun)
                r1 = eval(ctx, env, r1.code)
                ip += code[ip + 1]
            except space.SpaceException as ex:
                if stack is empty_stack:
                    stack = [None for _ in range(stack_size)]
                stack[jit.promote(sp)] = space.wrap(ex.reason())
                sp += 1
                ip += 1
        elif op == ops.CHAR:
            ip += 1
            r1 = space.W_Char(get_op(code, ip))
        else:
            raise Exception("Unknown code: %s, ip %s, code %s" %
                    (str(op), ip, str(code)))
        ip += 1
    assert sp == 0
    return r1
예제 #9
0
파일: builtins.py 프로젝트: jstepien/psota
 def invoke(self, args, *_):
     return space.wrap(args)
예제 #10
0
파일: builtins.py 프로젝트: jstepien/psota
 def invoke(self, args, *_):
     a = space.cast(args[0], space.W_Int)
     b = space.cast(args[1], space.W_Int)
     return space.wrap(a.val < b.val)
예제 #11
0
파일: builtins.py 프로젝트: jstepien/psota
 def invoke(self, *_):
     return space.wrap(str(stdin.get().readline()))
예제 #12
0
파일: builtins.py 프로젝트: jstepien/psota
 def f(self, args, *_):
     arg = args[0]
     return space.wrap(isinstance(arg, type))