Beispiel #1
0
def func_rest(arg):
    if isinstance(arg, parser.NilSymbol):
        return parser.LispList([])
    if (isinstance(arg, parser.LispList)
            or isinstance(arg, parser.LispVector)):
        return parser.LispList(arg.values[1:])
    raise ArgumentError("should be list or vector")
Beispiel #2
0
def quasiquote(ast):
    #print ("quasiquote with", printer.pr_str(ast, True))
    if not is_pair(ast):
        #print("step i: ast is not pair", ast)
        return parser.LispList([parser.StrSymbol('quote'), ast])
    if (isinstance(ast.values[0], parser.StrSymbol)
            and ast.values[0].val == 'unquote'):
        #print("step ii : found 'unquote'")
        return ast.values[1]
    if is_pair(ast.values[0]):
        zz = ast.values[0].values[0]
        #print ("zz", zz)
        #print ("t(zz)", type(zz))
        if isinstance(zz, parser.StrSymbol) and zz.val == 'splice-unquote':
            #print("step iii : found 'splice-unquote'")
            return parser.LispList([
                parser.StrSymbol('concat'), ast.values[0].values[1],
                quasiquote(parser.LispList(ast.values[1:]))
            ])
    #print("step iv : else")
    return parser.LispList([
        parser.StrSymbol('cons'),
        quasiquote(ast.values[0]),
        quasiquote(parser.LispList(ast.values[1:]))
    ])
Beispiel #3
0
def func_seq(arg):
    if (isinstance(arg, parser.NilSymbol)):
        return parser.NilSymbol()
    if (isinstance(arg, parser.LispList)
            or isinstance(arg, parser.LispVector)):
        if len(arg.values) == 0:
            return parser.NilSymbol()
        return parser.LispList(arg.values)
    if isinstance(arg, parser.LispString):
        if len(arg.str) == 0:
            return parser.NilSymbol()
        return parser.LispList([parser.LispString(x) for x in list(arg.str)])
Beispiel #4
0
def eval_ast(ast, env):
    if isinstance(ast, parser.StrSymbol):
        v = ast.val
        return env.get(v)

    elif isinstance(ast, parser.LispList):
        return parser.LispList([EVAL(x, env) for x in ast.values])
    else:
        return ast
Beispiel #5
0
def func_conj(*args):
    first = args[0]
    first_values = list(first.values)
    #print(type(first))
    #print(type(first.values))
    rest = list(args[1:])
    #print(type(rest))
    if isinstance(first, parser.LispList):
        rest.reverse()
        return parser.LispList(rest + first_values)
    if isinstance(first, parser.LispVector):
        return parser.LispVector(first_values + rest)
    return parser.NilSymbol()
Beispiel #6
0
def func_map(fn, argList):
    """takes a function and a list (or vector) and evaluates the function
    against every element of the list (or vector) one at a time and
    returns the results as a list."""

    retvals = []

    for arg in argList.values:
        if isinstance(fn, parser.FuncClosure):
            r = fn.call([arg])
        else:
            r = fn(arg)
        retvals.append(r)
    return parser.LispList(retvals)
Beispiel #7
0
def eval_ast(ast, env):
    if isinstance(ast, parser.StrSymbol):
        v = ast.val
        return env.get(v)
        
    elif isinstance(ast, parser.LispList):
        return parser.LispList([EVAL(x, env) for x in ast.values])
    elif isinstance(ast, parser.LispVector):
        return parser.LispVector([EVAL(x, env) for x in ast.values])
    elif isinstance(ast, parser.LispHashMap):
        keyvals = []
        for k in ast.keys():
            keyvals.append(EVAL(k, env))
            keyvals.append(EVAL(ast.lookup(k), env))
        return parser.LispHashMap(keyvals)
    else:
        return ast
Beispiel #8
0
def read_form(readerInst):
    """this function will peek at the first token in the Reader object
    and switch on the first character of that token.  If the character
    is a left paren then read_list is called with the Reader object.
    Otherwise, read_atom is called with the Reader Ojbect.  The return
    value from read_form is a MAL data type. You can likely just
    return a plain list of MAL types.
    """

    tok = readerInst.peek()

    if tok is '(':
        return parser.LispList(read_list(readerInst, ')'))
    elif tok is '[':
        return parser.LispVector(read_list(readerInst, ']'))
    elif tok is '{':
        return parser.LispHashMap(read_list(readerInst, '}'))
    elif tok is '@':
        atSign = readerInst.next()
        nextForm = read_form(readerInst)
        return parser.LispList([parser.StrSymbol('deref'), nextForm])
    elif tok is "'":
        readerInst.next()
        nextForm = read_form(readerInst)
        return parser.LispList([parser.StrSymbol('quote'), nextForm])
    elif tok is "`":
        readerInst.next()
        nextForm = read_form(readerInst)
        return parser.LispList([parser.StrSymbol('quasiquote'), nextForm])
    elif tok is "~":
        readerInst.next()
        nextForm = read_form(readerInst)
        return parser.LispList([parser.StrSymbol('unquote'), nextForm])
    elif tok == "~@":
        readerInst.next()
        nextForm = read_form(readerInst)
        return parser.LispList([parser.StrSymbol('splice-unquote'), nextForm])
    elif tok == "^":
        readerInst.next()
        nf = read_form(readerInst)
        nnf = read_form(readerInst)
        return parser.LispList([parser.StrSymbol('with-meta'), nnf, nf])
    else:
        return read_atom(readerInst)
Beispiel #9
0

def mainloop():
    while True:
        s = input("user> ")
        try:
            print (rep(s))
        except ValueError as e:
            print(e)
        except IndexError as e:
            print(e)
        except parser.MalException as me:
            print(me)
            print(printer.pr_str(me.mal_obj, True))
        
if __name__ == "__main__":
    if len(sys.argv) == 1:
        mainloop()
    else:
        #print ("processing command line:", sys.argv)
        fn = sys.argv[1]
        #print ("processing file:", fn)        
        #print ("extra args:", sys.argv[2:])
        argStrings = [parser.LispString(x) for x in sys.argv[2:]]
        listObj = parser.LispList(argStrings)
        repl_env.set('*ARGV*', listObj)
        
        rep('(load-file "{0}")'.format(fn))
        #print("Done")
        
Beispiel #10
0
def func_list(*args):
    return parser.LispList(args)
Beispiel #11
0
def func_vals(arg):
    vals = []
    for k in arg.keys():
        vals.append(arg.lookup(k))
    return parser.LispList(vals)
Beispiel #12
0
def func_keys(arg):
    return parser.LispList(list(arg.keys()))
Beispiel #13
0
def func_concat(*args):
    outvals = []
    for a in args:
        outvals += a.values
    return parser.LispList(outvals)
Beispiel #14
0
def EVAL(ast, env):
    while True:
        #print ("evaluating", ast)
        if not isinstance(ast, parser.LispList):
            return eval_ast(ast, env)
        if len(ast.values) == 0:
            return ast

        op = ast.values[0]
        #print ("op", op)
        if isinstance(op, parser.StrSymbol) and op.val == 'def!':
            """call the set method of the current environment (second parameter of
            EVAL called env) using the unevaluated first parameter (second
            list element) as the symbol key and the evaluated second
            parameter as the value."""
            val = EVAL(ast.values[2], env)
            env.set(ast.values[1].val, val)
            return val
        elif isinstance(op, parser.StrSymbol) and op.val == 'let*':
            newenv = environment.Environment(env)
            for i in range(0, len(ast.values[1]), 2):
                name = ast.values[1][i].val
                val = EVAL(ast.values[1][i + 1], newenv)
                newenv.set(name, val)
            env = newenv
            ast = ast.values[2]
            continue
        elif isinstance(op, parser.StrSymbol) and op.val == 'do':
            ret = None
            for t in ast.values[1:-1]:
                #print ("evaluating",t)
                ret = EVAL(t, env)
                #print ("got ret")
                #print ("env:", env)
            ast = ast.values[-1]
            continue
        elif isinstance(op, parser.StrSymbol) and op.val == 'if':
            #print ("evaluating if")
            test = EVAL(ast.values[1], env)
            #print ("test:", test)
            if not (isinstance(test, parser.NilSymbol)
                    or isinstance(test, parser.FalseSymbol)):
                # true eval
                #print ("test was true, evaluating", ast.values[2])
                ast = ast.values[2]
                continue
            elif len(ast.values) > 3:
                #print ("test was false, evaluating else", ast.values[3])
                #else
                ast = ast.values[3]
                continue
            else:
                #print ("test was false, returning Nil")
                return parser.NilSymbol()
        elif isinstance(op, parser.StrSymbol) and op.val == 'fn*':
            newenv = environment.Environment(env, [], [])
            params = [x.val for x in ast.values[1].values]
            body = ast.values[2]
            #print ("making func", params, body)
            funcClosure = parser.FuncClosure(newenv, params, body)
            return funcClosure

        else:
            ast_list = eval_ast(ast, env)

            if isinstance(ast_list.values[0], parser.FuncClosure):
                func = ast_list.values[0]
                newenv = environment.Environment(func.env, [], [])

                for i in range(len(func.params)):
                    p = func.params[i]
                    if p == '&':
                        nextP = func.params[i + 1]
                        val = parser.LispList(ast_list.values[i + 1:])
                        newenv.set(nextP, val)
                        break
                    val = ast_list.values[1 + i]
                    newenv.set(p, val)

                ast = func.body
                env = newenv
                continue

            #print ("about to call", ast_list.values[0])

            return ast_list.values[0](*ast_list.values[1:])