Ejemplo n.º 1
0
def EVAL(expr: types.LispType, env: Environment) -> types.LispType:
    while True:
        if not types.is_list(expr):
            return eval_ast(expr, env)

        if len(expr) == 0:
            return expr

        if types.is_list(expr):
            if expr[0] == 'def!':
                ele1, ele2 = expr[1], expr[2]
                value = env.set(types.Symbol(ele1), EVAL(ele2, env))
                return value
            elif expr[0] == 'let*':
                new_env = Environment(env)
                ele1 = expr[1]

                keys = ele1[::2]
                values = ele1[1::2]

                for k, v in zip(keys, values):
                    new_env.set(types.Symbol(k), EVAL(v, new_env))

                env = new_env
                expr = expr[2]
                continue
            elif expr[0] == 'do':
                for e in expr[1:-1]:
                    EVAL(e, env)
                expr = expr[-1]
                continue
            elif expr[0] == 'if':
                cond = EVAL(expr[1], env)
                if cond:
                    expr = expr[2]
                elif not cond and len(expr) == 4:
                    expr = expr[3]
                else:
                    expr = None
                continue
            elif expr[0] == 'fn*':
                closure = types.Closure(
                    expr[1], expr[2], env, EVAL
                )
                return closure
            else:
                fun, *args = eval_ast(expr, env)
                return fun(*args)
Ejemplo n.º 2
0
def read_form(reader: Reader) -> types.LispType:
    token = reader.peek()

    if token == '(':
        return read_list(reader)
    elif token == '[':
        return read_list(reader, stop=']', seq=types.make_vector)
    elif token == '{':
        return read_list(reader, stop='}', seq=types.make_hash_map)
    elif token == '\'':
        reader.next()
        return types.make_list([types.Symbol('quote'), read_form(reader)])
    elif token == '`':
        reader.next()
        return types.make_list([types.Symbol('quasiquote'), read_form(reader)])
    elif token == '~':
        reader.next()
        return types.make_list([types.Symbol('unquote'), read_form(reader)])
    elif token == '~@':
        reader.next()
        return types.make_list(
            [types.Symbol('splice-unquote'),
             read_form(reader)])
    elif token == '@':
        reader.next()
        return types.make_list([types.Symbol('deref'), read_form(reader)])
    elif token == '^':
        reader.next()
        meta = read_form(reader)
        return types.make_list(
            [types.Symbol('with-meta'),
             read_form(reader), meta])
    else:
        return read_atom(reader)
Ejemplo n.º 3
0
def read_atom(reader: Reader) -> types.LispType:
    token = reader.next()
    if re.match(r'^[-+]?\d+$', token):
        return int(token)
    elif re.match(r'^"(?:[\\].|[^\\"])*"$', token):
        return escape(token[1:-1])
    elif token[0] == '"':
        raise types.LispException('unbalanced \'"\'')
    elif token[0] == ':':
        return types.KeyWord(token[1:])
    elif token == 'nil':
        return None
    elif token == 'true':
        return True
    elif token == 'false':
        return False
    else:
        return types.Symbol(token)
Ejemplo n.º 4
0
                continue
            elif expr[0] == 'fn*':
                closure = types.Closure(
                    expr[1], expr[2], env, EVAL
                )
                return closure
            else:
                fun, *args = eval_ast(expr, env)
                return fun(*args)


def PRINT(expr: types.LispType) -> str:
    return printer.print_string(expr)


def REP(expr: str) -> str:
    return PRINT(EVAL(READ(expr), repl_env))


repl_env.set(types.Symbol('eval'), lambda a: EVAL(a, repl_env))
repl_env.set(types.Symbol('*ARGV*'), types.List(sys.argv[1:]))
REP("(def! not (fn* (a) (if a false true)))")
REP('(def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) "\nnil)")))))')
#REP('(def! a (slurp "../tests/incA.mal"))')

if __name__ == '__main__':
    while True:
        try:
            print(REP(input('user> ')))
        except Exception as exception:
            print(exception)
Ejemplo n.º 5
0

def cons(item, lst):
    return types.List([item] + lst)


def concat(*lsts):
    n_lst = []
    for lst in lsts:
        n_lst.extend(lst)

    return types.List(n_lst)


repl_env = types.Environment(None)
repl_env.set(types.Symbol('+'), lambda a, b: a + b)
repl_env.set(types.Symbol('-'), lambda a, b: a - b)
repl_env.set(types.Symbol('*'), lambda a, b: a * b)
repl_env.set(types.Symbol('/'), lambda a, b: a // b)
repl_env.set(types.Symbol('list'), lambda *a: types.List(a))
repl_env.set(types.Symbol('vector'), lambda *a: types.Vector(a))
repl_env.set(types.Symbol('list?'), types.is_list)
repl_env.set(types.Symbol('vector?'), types.is_vector)
repl_env.set(types.Symbol('empty?'), lambda a: len(a) == 0)
repl_env.set(types.Symbol('count'), lambda a: len(a))
repl_env.set(types.Symbol('='), lambda a, b: a == b)
repl_env.set(types.Symbol('>'), lambda a, b: a > b)
repl_env.set(types.Symbol('>='), lambda a, b: a >= b)
repl_env.set(types.Symbol('<'), lambda a, b: a < b)
repl_env.set(types.Symbol('<='), lambda a, b: a <= b)
repl_env.set(types.Symbol('pr-str'), pr_str)