Пример #1
0
def _mal(d):
    if isinstance(d, bool) and d == True:
        return _MalData("TRUE")
    elif isinstance(d, bool) and d == False:
        return _MalData("FALSE")
    elif isinstance(d, int):
        return _MalData("INT", d)
Пример #2
0
def EVAL(ast, env):
    while True:

        if ast.type != "LIST":
            return eval_ast(ast, env)

        if len(ast.val) == 0:
            return ast

        ast0 = ast.val[0]

        # def!
        if ast0.val == "def!":
            key = ast.val[1].val
            v = EVAL(ast.val[2], env)
            env.set(key, v)
            return v
        # let*
        elif ast0.val == "let*":
            a1, a2 = ast.val[1], ast.val[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
        # do
        elif ast0.val == "do":
            eval_ast(_MalData("LIST", ast.val[1:-1]), env)
            ast = ast.val[-1]
        # if
        elif ast0.val == "if":
            b = EVAL(ast.val[1], env)
            if b.type != "NIL" and b.type != "FALSE":
                ast = ast.val[2]
            else:
                if len(ast.val) <= 3: ast = None
                ast = ast.val[3]
        # fn*
        elif ast0.val == "fn*":
            params = [p.val for p in ast.val[1].val]
            expr_ast = ast.val[2]

            def fn(*args):
                pass
                #new_env = Env(env, params, args)
                #return EVAL(expr_ast, new_env)
            fn.__ast__ = expr_ast
            fn.__gen_env__ = lambda args: Env(env, params, args)

            return _MalData("FUNCTION", fn)
        # apply
        else:
            new_ast = eval_ast(ast, env)
            l = new_ast.val
            f, args = l[0].val, l[1:]
            if hasattr(f, '__ast__'):
                ast = f.__ast__
                env = f.__gen_env__(args)
            else:
                return f(*args)
Пример #3
0
def EVAL(ast, env):
    if ast.type != "LIST":
        return eval_ast(ast, env)
    elif len(ast.val) == 0:
        return ast

    ast0 = ast.val[0]

    # def!
    if ast0.val == "def!":
        key = ast.val[1].val
        v = EVAL(ast.val[2], env)
        env.set(key, v)
        return v
    # let*
    elif ast0.val == "let*":
        let_env = Env(env)
        bidings = ast.val[1]

        for a, b in zip(bidings.val[0::2], bidings.val[1::2]):
            key = a.val
            v = EVAL(b, let_env)
            let_env.set(key, v)

        return EVAL(ast.val[2], let_env)
    # do
    elif ast0.val == "do":
        new_ast = eval_ast(_MalData("LIST", ast.val[1:]), env)
        return new_ast.val[-1]
    # if
    elif ast0.val == "if":
        b = EVAL(ast.val[1], env)
        if b.type != "NIL" and b.type != "FALSE":
            return EVAL(ast.val[2], env)
        else:
            if len(ast.val) <= 3: return _MalData("NIL")
            return EVAL(ast.val[3], env)
    # fn*
    elif ast0.val == "fn*":
        params = [p.val for p in ast.val[1].val]
        expr_ast = ast.val[2]

        def fn(*args):
            new_env = Env(env, params, args)
            return EVAL(expr_ast, new_env)
        return _MalData("FUNCTION", fn)

    # apply
    else:
        new_ast = eval_ast(ast, env)
        l = new_ast.val
        f, args = l[0].val, l[1:]
        return f(*args)
Пример #4
0
def println(*args):
    ret = []
    for ast in args:
        ret.append(printer.pr_str(ast, False))
    txt = " ".join(ret)
    print(txt)
    return _MalData("NIL")
Пример #5
0
def EVAL(ast, env):
    if ast.type == "LIST":
        l = ast.val
        if len(l) == 0:
            return ast
        else:
            ast0 = ast.val[0]

            if ast0.type == "SYMBOL" and ast0.val == "def!":
                key = ast.val[1].val
                v = EVAL(ast.val[2], env)
                env.set(key, v)
                return v
            elif ast0.type == "SYMBOL" and ast0.val == "let*":
                let_env = Env(env)
                bidings = ast.val[1]
                assert bidings.type == "LIST"

                for a, b in zip(bidings.val[0::2], bidings.val[1::2]):
                    key = a.val
                    v = EVAL(b, let_env)
                    let_env.set(key, v)

                return EVAL(ast.val[2], let_env)
            else:
                new_ast = eval_ast(ast, env)
                l = new_ast.val
                f, args = l[0], l[1:]
                res = f(*[x.val for x in args])  # apply
                return _MalData("INT", res)

    else:
        return eval_ast(ast, env)
Пример #6
0
    def __init__(self, outer=None, binds=None, exprs=None):
        self.data = {}
        self.outer = outer

        if binds:
            for i in range(len(binds)):
                if binds[i] == "&":
                    self.data[binds[i + 1]] = _MalData("LIST", exprs[i:])
                    break
                else:
                    self.data[binds[i]] = exprs[i]
Пример #7
0
def eval_ast(ast, env):
    if ast.type == "SYMBOL":
        key = ast.val
        if env.find(key) is None:
            raise Exception('no key for env:', key)
        f = env.get(key)
        return f
    elif ast.type == "LIST":
        data = tuple([EVAL(x, env) for x in ast.val])
        return _MalData("LIST", data)
    else:
        return ast
Пример #8
0
def eval_ast(ast, env):
    if ast.type == "SYMBOL":
        key = ast.val
        if not key in env:
            raise Exception('no key for env:', key)
        f = env[key]
        print('fff', f)
        return f
    elif ast.type == "LIST":
        data = tuple([EVAL(x, env) for x in ast.val])
        return _MalData("LIST", data)
    else:
        return ast
Пример #9
0
def quasiquote(ast):

    if not is_pair(ast):
        _v = (_MalData("SYMBOLE", "quote"), ast)
        return _MalData("LIST", _v)
    elif ast.val[0].val == 'unquote':
        return ast.val[1]
    elif is_pair(ast.val[0]) and ast.val[0].val[0].val == 'splice-unquote':
        _v = (_MalData("SYMBOL", "concat"), ast.val[0].val[1],
              quasiquote(_MalData("LIST", ast.val[1:])))
        return _MalData("LIST", _v)
    else:
        _v = (_MalData("SYMBOL", "cons"), quasiquote(ast.val[0]),
              quasiquote(_MalData("LIST", ast.val[1:])))
        return _MalData("LIST", _v)
Пример #10
0
def EVAL(ast, env):

    if ast.type != "LIST": return eval_ast(ast, env)
    elif len(ast.val) == 0: return ast

    type0 = ast.val[0].type

    if type0 == "def!":
        pass
    else:
        new_ast = eval_ast(ast, env)
        l = new_ast.val
        f, args = l[0], l[1:]
        res = f(*[x.val for x in args])  # apply
        return _MalData("INT", res)
Пример #11
0
def _atom(atom):
    return _MalData("ATOM", atom)
Пример #12
0
def first(lst):
    if lst.val == None or len(lst.val) == 0 or lst.val[0].type == "NIL":
        return _MalData("NIL")
    return lst.val[0]
Пример #13
0
def _list(*args):
    return _MalData("LIST", args)
Пример #14
0
def _is_atom(atom):
    if atom.type == "ATOM":
        return _MalData("TRUE")
    return _MalData("FALSE")
Пример #15
0
def _slurp(node):

    path = node.val
    with open(path) as f:
        s = f.read()
    return _MalData("STRING", s)
Пример #16
0
def _concat(*args):
    ret = []
    for a in args:
        for _a in a.val:
            ret.append(_a)
    return _MalData("LIST", tuple(ret))
Пример #17
0
def is_nil(arg):
    if arg.type == "NIL": return _MalData("TRUE")
Пример #18
0
def rest(lst):
    if lst.val is None:
        return _MalData("LIST", ())

    return _MalData("LIST", lst.val[1:])
Пример #19
0
def EVAL(ast, env):
    while True:

        if ast.type != "LIST":
            return eval_ast(ast, env)

        ast = macroexpand(ast, env)
        if ast.type != "LIST":
            return eval_ast(ast, env)

        if len(ast.val) == 0:
            return ast
        ast0 = ast.val[0]

        # def!
        if ast0.val == "def!":
            key = ast.val[1].val
            v = EVAL(ast.val[2], env)
            env.set(key, v)
            return v

        # macro
        elif ast0.val == "defmacro!":
            key = ast.val[1].val
            new_ast = ast.val[2]
            v = EVAL(new_ast, env)
            v.is_macro = True
            env.set(key, v)
            return v
        elif ast0.val == "macroexpand":
            return macroexpand(ast.val[1], env)

        elif ast0.val == "try*":
            if len(ast.val) < 3:
                return EVAL(ast[1], env)

            a1, a2 = ast.val[1], ast.val[2]
            if a2.val[0].val == "catch*":
                err = None
                try:
                    return EVAL(a1, env)
                except MalException as exc:
                    err = exc.object
                except Exception as exc:
                    #msg = "'" + exc.args[1] + "'" + " not found"
                    err = _MalData("STRING", exc.args[0])

                catch_env = Env(env, [a2.val[1].val], [err])
                return EVAL(a2.val[2], catch_env)
            else:
                return EVAL(a1, env)
        # let*
        elif ast0.val == "let*":
            a1, a2 = ast.val[1], ast.val[2]
            let_env = Env(env)

            for i in range(0, len(a1.val), 2):
                let_env.set(a1.val[i].val, EVAL(a1.val[i + 1], let_env))
            ast = a2
            env = let_env
        # do
        elif ast0.val == "do":
            eval_ast(_MalData("LIST", ast.val[1:-1]), env)
            ast = ast.val[-1]
        # if
        elif ast0.val == "if":
            b = EVAL(ast.val[1], env)
            if b.type != "NIL" and b.type != "FALSE":
                ast = ast.val[2]
            else:
                if len(ast.val) <= 3: ast = None
                ast = ast.val[3]
        # fn*
        elif ast0.val == "fn*":
            params = [p.val for p in ast.val[1].val]
            expr_ast = ast.val[2]

            def fn(*args):
                new_env = Env(env, params, args)
                return EVAL(expr_ast, new_env)

            fn.__ast__ = expr_ast
            fn.__gen_env__ = lambda args: Env(env, params, args)
            return _MalData("FUNCTION", fn)

        # quote
        elif ast0.val == "quote":
            return ast.val[1]
        elif ast0.val == "quasiquote":
            ast = quasiquote(ast.val[1])
        # apply
        else:
            new_ast = eval_ast(ast, env)
            l = new_ast.val
            f, args = l[0].val, l[1:]
            if hasattr(f, '__ast__'):
                ast = f.__ast__
                env = f.__gen_env__(args)
            else:
                return f(*args)
Пример #20
0
def is_symbol(arg):
    if arg.type == "SYMBOL": return _MalData("TRUE")
Пример #21
0
def is_false(arg):
    if arg.type == "FALSE": return _MalData("TRUE")
Пример #22
0
def is_true(arg):
    if arg.type == "TRUE": return _MalData("TRUE")
Пример #23
0
    repl_env.set(key, val)

repl_env.set('eval', core._F(lambda ast: EVAL(ast, repl_env)))

rep("(def! not (fn* (a) (if a false true)))", out_print=False)
rep("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))",
    out_print=False)
#macro
rep("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))",
    out_print=False)
rep("(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))",
    out_print=False)

if __name__ == '__main__':
    _args = sys.argv[2:]
    repl_env.set('*ARGV*', _MalData('LIST', list(_args)))

    #rep("(def! not (fn* (a) (if a false true)))")
    if len(sys.argv) >= 2:
        path = sys.argv[1]
        rep('(load-file "' + path + '")')
        sys.exit(0)

    while True:
        try:
            x = input('user> ')
            rep(x, repl_env)

        except Exception as e:
            print("".join(traceback.format_exception(*sys.exc_info())))
        except KeyboardInterrupt:
Пример #24
0
def _str(*args):
    ret = []
    for ast in args:
        ret.append(printer.pr_str(ast, False))
    return _MalData("STRING", "".join(ret))
Пример #25
0
def _P(f):
    def g(*args):
        return _mal(f(*[x.val for x in args]))

    return _MalData("FUNCTION", g)
Пример #26
0
def mapf(f, lst):
    ret = map(f.val, lst.val)
    return _MalData("LIST", ret)
Пример #27
0
def _F(f):
    return _MalData("FUNCTION", f)
Пример #28
0
def _cons(a1, a2):
    new_list = (a1, ) + a2.val
    return _MalData("LIST", new_list)