Example #1
0
def A_closure_holds_updateable_values():
    def dumb_set(env, sym, val):
        env.parent.parent.parent.set(sym[1], val)

    def dumb_if_equal(env, val1, val2, then_fn, else_fn):
        if val1 == val2:
            ret = then_fn
        else:
            ret = else_fn
        return eval_expr(("call", ret, []), env)
    env = Env()
    env.set("dumb_set", ("native", dumb_set))
    env.set("dumb_if_equal", ("native", dumb_if_equal))
    assert_that(
        evald(
            """
            counter = {
                x = 0;
                {:(meth)
                    dumb_if_equal(meth, "get",
                        {x;},
                        {dumb_set("x", x + 1);}
                    );
                }
            }();
            counter("inc");
            counter("inc");
            counter("get");
            """,
            env
        ),
        equals(("number", 2))
    )
Example #2
0
def A_native_function_can_edit_the_environment():
    def mx3(env):
        env.set("x", ("number", 3))

    env = Env()
    env.set("make_x_three", ("native", mx3))
    assert_that(evald("x=1;make_x_three();x;", env), equals(("number", 3)))
Example #3
0
def Native_function_gets_called():
    def native_fn(env, x, y):
        return ("number", x[1] + y[1])

    env = Env()
    env.set("native_fn", ("native", native_fn))
    assert_that(evald("native_fn( 2, 8 );", env), equals(("number", 10)))
Example #4
0
def A_native_function_can_edit_the_environment():
    def mx3(env):
        env.set("x", ("number", 3))
    env = Env()
    env.set("make_x_three", ("native", mx3))
    assert_that(
        evald("x=1;make_x_three();x;", env),
        equals(("number", 3))
    )
Example #5
0
def eval_expr(expr, env):
    typ = expr[0]
    if typ == "number":
        return ("number", float(expr[1]))
    elif typ == "string":
        return ("string", expr[1])
    elif typ == "none":
        return ("none", )
    elif typ == "operation":
        return _operation(expr, env)
    elif typ == "symbol":
        name = expr[1]
        ret = env.get(name)
        if ret is None:
            raise Exception("Unknown symbol '%s'." % name)
        else:
            return ret
    elif typ == "assignment":
        var_name = expr[1][1]
        if var_name in env.items:
            raise Exception("Not allowed to re-assign symbol '%s'." % var_name)
        val = eval_expr(expr[2], env)
        env.set(var_name, val)
        return val
    elif typ == "call":
        return _function_call(expr, env)
    elif typ == "function":
        return ("function", expr[1], expr[2], Env(env))
    else:
        raise Exception("Unknown expression type: " + str(expr))
Example #6
0
def compile_(output, filename):
    env = Env()
    with open(output, "w") as outfile:
        outfile.write(
            compile_list(parse(lex(pycell.library.as_text(env))), env))
        with open(filename, encoding="ascii") as infile:
            outfile.write(
                compile_list(parse(lex(chars_in_file(infile))), env))
Example #7
0
def Wrong_number_of_arguments_to_a_native_function_is_an_error():
    def native_fn0(env):
        return ("number", 12)

    def native_fn3(env, x, y, z):
        return ("number", 12)

    env = Env()
    env.set("native_fn0", ("native", native_fn0))
    env.set("native_fn3", ("native", native_fn3))
    assert_prog_fails(
        "native_fn0(3);",
        "1 arguments passed to function ('symbol', 'native_fn0'), but it requires 0 arguments.",
        env)
    assert_prog_fails(
        "native_fn3(3, 2);",
        "2 arguments passed to function ('symbol', 'native_fn3'), but it requires 3 arguments.",
        env)
Example #8
0
def Wrong_number_of_arguments_to_a_native_function_is_an_error():
    def native_fn0(env):
        return ("number", 12)

    def native_fn3(env, x, y, z):
        return ("number", 12)
    env = Env()
    env.set("native_fn0", ("native", native_fn0))
    env.set("native_fn3", ("native", native_fn3))
    assert_prog_fails(
        "native_fn0(3);",
        "1 arguments passed to function ('symbol', 'native_fn0'), but it requires 0 arguments.",
        env
    )
    assert_prog_fails(
        "native_fn3(3, 2);",
        "2 arguments passed to function ('symbol', 'native_fn3'), but it requires 3 arguments.",
        env
    )
Example #9
0
def _function_call(expr, env):
    fn = eval_expr(expr[1], env)
    args = list((eval_expr(a, env) for a in expr[2]))
    if fn[0] == "function":
        params = fn[1]
        fail_if_wrong_number_of_args(expr[1], params, args)
        body = fn[2]
        fn_env = fn[3]
        new_env = Env(fn_env)
        for p, a in zip(params, args):
            new_env.set(p[1], a)
        return eval_list(body, new_env)
    elif fn[0] == "native":
        py_fn = fn[1]
        params = inspect.getargspec(py_fn).args
        fail_if_wrong_number_of_args(expr[1], params[1:], args)
        return fn[1](env, *args)
    else:
        raise Exception(
            "Attempted to call something that is not a function: %s" % str(fn))
Example #10
0
def A_closure_holds_updateable_values():
    def dumb_set(env, sym, val):
        env.parent.parent.parent.set(sym[1], val)

    def dumb_if_equal(env, val1, val2, then_fn, else_fn):
        if val1 == val2:
            ret = then_fn
        else:
            ret = else_fn
        return eval_expr(("call", ret, []), env)

    env = Env()
    env.set("dumb_set", ("native", dumb_set))
    env.set("dumb_if_equal", ("native", dumb_if_equal))
    assert_that(
        evald(
            """
            counter = {
                x = 0;
                {:(meth)
                    dumb_if_equal(meth, "get",
                        {x;},
                        {dumb_set("x", x + 1);}
                    );
                }
            }();
            counter("inc");
            counter("inc");
            counter("get");
            """, env), equals(("number", 2)))
Example #11
0
def _function_call(expr, env):
    fn = eval_expr(expr[1], env)
    args = list((eval_expr(a, env) for a in expr[2]))
    if fn[0] == "function":
        params = fn[1]
        fail_if_wrong_number_of_args(expr[1], params, args)
        body = fn[2]
        fn_env = fn[3]
        new_env = Env(fn_env)
        for p, a in zip(params, args):
            new_env.set(p[1], a)
        return eval_list(body, new_env)
    elif fn[0] == "native":
        py_fn = fn[1]
        params = inspect.getargspec(py_fn).args
        fail_if_wrong_number_of_args(expr[1], params[1:], args)
        return fn[1](env, *args)
    else:
        raise Exception(
            "Attempted to call something that is not a function: %s" %
            str(fn)
        )
Example #12
0
def repl(stdin, stdout, stderr):
    env = Env(parent=None, stdin=stdin, stdout=stdout, stderr=stderr)
    pycell.library.import_(env)
    while True:
        try:
            p = Prompt(stdout)
            for value in eval_iter(
                    parse(lex(p.handle_chars(chars_in_file(stdin)))), env):
                p.value(value)
            break
        except Exception as e:
            stderr.write(str(e))
            stderr.write("\n")
    stdout.write("\n")
    stdout.flush()
Example #13
0
def runned(inp):
    with StringIO() as stdin, StringIO() as stdout:
        env = Env(stdin=stdin, stdout=stdout, stderr=stdout)
        pycell.library.import_(env)
        return eval_list(parse(lex(inp)), env)
Example #14
0
def evald(inp, stdout=None):
    env = Env(stdout=stdout)
    pycell.library.import_(env)
    return eval_list(parse(lex(inp)), env)
Example #15
0
def None_evaluates_to_None():
    assert_that(eval_expr(("none", ), Env()), equals(("none", )))
Example #16
0
def run(filename, stdin, stdout, stderr):
    env = Env(stdin=stdin, stdout=stdout, stderr=stdout)
    pycell.library.import_(env)
    with open(filename, encoding="ascii") as f:
        eval_list(parse(lex(chars_in_file(f))), env)
Example #17
0
def Native_function_gets_called():
    def native_fn(env, x, y):
        return ("number", x[1] + y[1])
    env = Env()
    env.set("native_fn", ("native", native_fn))
    assert_that(evald("native_fn( 2, 8 );", env), equals(("number", 10)))
Example #18
0
def compiled(inp, env=None):
    if env is None:
        env = Env()
    return compile_list(parse(lex(inp)), env)
Example #19
0
def evald(inp, env=None):
    if env is None:
        env = Env()
    return eval_list(parse(lex(inp)), env)