Exemplo n.º 1
0
def first(x):
    # print('x.data', x.data)
    if isinstance(x, mal_types.MalNil):
        return mal_types.MalNil()
    elif isinstance(x, mal_types.list_types) and len(x) == 0:
        return mal_types.MalNil()
    return x[0]
Exemplo n.º 2
0
def EVAL(ast, env):
    while True:
        if not isinstance(ast, mal_types.list_types):
            return eval_ast(ast, env)
        elif not ast:
            return ast
        elif isinstance(ast, mal_types.list_types):
            if len(ast) == 0:
                return ast
            if isinstance(ast[0], mal_types.MalSymbol):
                if ast[0].data == 'def!':
                    value = EVAL(ast[2], env)
                    env.set(ast[1].data, value)
                    return value

                elif ast[0].data == 'let*':
                    let_env = Env(outer=env)
                    for k, v in zip(ast[1][::2], ast[1][1::2]):
                        let_env.set(k, EVAL(v, let_env))
                    ast, env = ast[2], let_env
                    continue

                elif ast[0].data == 'do':
                    ast = eval_ast(ast[1:], env)[-1]
                    return ast

                elif ast[0].data == 'if':
                    if EVAL(ast[1], env):
                        ast = ast[2]
                        continue
                    else:
                        if len(ast) == 4:
                            ast = ast[3]
                            continue
                        return mal_types.MalNil()

                elif ast[0].data == 'fn*':

                    def fn(*exprs):
                        new_env = Env(outer=env, binds=ast[1], exprs=exprs)
                        return EVAL(ast[2], new_env)

                    return mal_types.MalFn(ast=ast[2],
                                           params=ast[1],
                                           env=env,
                                           fn=fn)

            # apply
            evaluated_ast = eval_ast(ast, env)
            if callable(evaluated_ast[0]):
                f, args = evaluated_ast[0], evaluated_ast[1:]
                if isinstance(f, mal_types.MalFn):
                    ast = f.ast
                    env = Env(outer=f.env, binds=f.params, exprs=args)
                    # print(f)
                    continue
                else:
                    return f(*args)
            return evaluated_ast
        return mal_types.MalNil()
Exemplo n.º 3
0
def read_atom(reader):
    token = reader.peek()
    try:
        val = int(token)
        return mal_types.MalNumber(val)
    except ValueError:
        pass
    if token in _quote_mapping:
        reader.next()
        return mal_types.MalList(
            [mal_types.MalSymbol(_quote_mapping[token]),
             read_form(reader)])
    elif token == '^':
        reader.next()
        meta_data = read_form(reader)
        reader.next()
        lst = read_form(reader)
        return mal_types.MalList(
            [mal_types.MalSymbol("with-meta"), lst, meta_data])
    elif token.startswith('"') and token.endswith('"'):
        return mal_types.MalString(
            bytes(token[1:-1], "utf-8").decode("unicode_escape"))
    elif token.startswith(":"):
        return mal_types.MalKeyword(token)
    elif token in ('true', 'false'):
        if token == 'true':
            return mal_types.MalBool(True)
        return mal_types.MalBool(False)
    elif token == 'nil':
        return mal_types.MalNil()
    return mal_types.MalSymbol(token)  # symbol?
Exemplo n.º 4
0
def EVAL(ast, env):
    # print('EVAL', ast)
    if not isinstance(ast, mal_types.list_types):
        return eval_ast(ast, env)
    elif not ast:
        return ast
    elif isinstance(ast, mal_types.list_types):
        if len(ast) == 0:
            return ast
        if isinstance(ast[0], mal_types.MalSymbol):
            if ast[0].data == 'def!':
                value = EVAL(ast[2], env)
                env.set(ast[1].data, value)
                return value

            elif ast[0].data == 'let*':
                let_env = Env(outer=env)
                for k, v in zip(ast[1][::2], ast[1][1::2]):
                    let_env.set(k, EVAL(v, let_env))
                return EVAL(ast[2], let_env)

            elif ast[0].data == 'do':
                return eval_ast(ast[1:], env)[-1]  # fixme

            elif ast[0].data == 'if':
                if EVAL(ast[1], env):
                    return EVAL(ast[2], env)
                else:
                    if len(ast) == 4:
                        return EVAL(ast[3], env)
                    return mal_types.MalNil()

            elif ast[0].data == 'fn*':

                def closure(*exprs):
                    new_env = Env(outer=env, binds=ast[1], exprs=exprs)
                    # print(new_env.data)
                    # print(ast[2])
                    return EVAL(ast[2], new_env)

                return closure
        evaluated_ast = eval_ast(ast, env)
        if callable(evaluated_ast[0]):
            return evaluated_ast[0](*evaluated_ast[1:])  # apply
        return evaluated_ast
    return mal_types.MalNil()
Exemplo n.º 5
0
def seq(x):
    if not x.data:
        return mal_types.MalNil()
    elif isinstance(x, mal_types.MalList):
        return x
    elif isinstance(x, mal_types.MalVector):
        return mal_types.MalList(x.data)
    elif isinstance(x, mal_types.MalString):
        return mal_types.MalList([mal_types.MalString(i) for i in x.data])
Exemplo n.º 6
0
def prn(*args):
    print(" ".join([pr_str(i, print_readably=True) for i in args]))
    return mal_types.MalNil()
Exemplo n.º 7
0
def meta(x):
    return getattr(x, 'metadata', mal_types.MalNil())
Exemplo n.º 8
0
def readline(string):
    try:
        return mal_types.MalString(input(string))
    except EOFError:
        return mal_types.MalNil()
Exemplo n.º 9
0
def get(x, key):
    if isinstance(x, mal_types.MalHashMap):
        return x.get(key)
    return mal_types.MalNil()
Exemplo n.º 10
0
def EVAL(ast, env):
    while True:
        # print('INLOOP', ast)
        if not isinstance(ast, mal_types.list_types):
            return eval_ast(ast, env)
        elif not ast:
            return ast
        elif isinstance(ast, mal_types.list_types):
            if len(ast) == 0:
                return ast
            ast = macroexpand(ast, env)
            if not isinstance(ast, mal_types.list_types):
                return eval_ast(ast, env)
            if isinstance(ast[0], mal_types.MalSymbol):
                if ast[0].data == 'macroexpand':
                    return macroexpand(ast[1], env)

                if ast[0].data == 'def!':
                    value = EVAL(ast[2], env)
                    env.set(ast[1].data, value)
                    return value

                elif ast[0].data == 'defmacro!':
                    value = EVAL(ast[2], env)
                    value.is_macro = True
                    env.set(ast[1].data, value)
                    return value

                elif ast[0].data == 'let*':
                    let_env = Env(outer=env)
                    for k, v in zip(ast[1][::2], ast[1][1::2]):
                        new_value = EVAL(v, let_env)
                        let_env.set(k, new_value)
                    # print('let_env', k, new_value)
                    ast, env = ast[2], let_env
                    continue

                elif ast[0].data == 'do':
                    return eval_ast(ast[1:], env)[-1]

                elif ast[0].data == 'if':
                    if EVAL(ast[1], env):
                        ast = ast[2]
                        continue
                    else:
                        if len(ast) == 4:
                            ast = ast[3]
                            continue
                        return mal_types.MalNil()

                elif ast[0].data == 'fn*':

                    def fn(*exprs):
                        new_env = Env(outer=env, binds=ast[1], exprs=exprs)
                        return EVAL(ast[2], new_env)

                    return mal_types.MalFn(ast=ast[2],
                                           params=ast[1],
                                           env=env,
                                           fn=fn)

                elif ast[0].data == 'quote':
                    return ast[1]

                elif ast[0].data == 'quasiquote':
                    ast = quasiquote(ast[1])
                    continue

                elif ast[0].data == 'try*':
                    try:
                        return EVAL(ast[1], env)
                    except mal_types.MalException as e:
                        new_env = Env(outer=env)
                        new_env.set(ast[2][1], e)
                        return EVAL(ast[2][2], new_env)
            # apply
            evaluated_ast = eval_ast(ast, env)
            if callable(evaluated_ast[0]):
                #print("function", ast)
                f, args = evaluated_ast[0], evaluated_ast[1:]
                # print('f', f)
                # print('args', args)
                if isinstance(f, mal_types.MalFn):
                    ast = f.ast
                    env = Env(outer=f.env, binds=f.params, exprs=args)
                    continue
                else:
                    # print('********************f', f)
                    # print('********************args', args)
                    # print('@result', type(x), x)
                    return f(*args)
            return evaluated_ast
        return mal_types.MalNil()