Пример #1
0
def read_atom(readerInst):
    """ this function will look at the contents of the token and return the appropriate scalar (simple/single) data type value. Initially, you can just implement numbers(integers) and symbols. This will allow you to proceed through the next couple of steps before you will need to implement the other fundamental MAL types: nil, true, false, and string. The remaining MAL types: keyword, vector, hash-map, and atom do not need to be implemented until step 9 (but can be implemented at any point between this step and that). BTW, symbol types are just objects that contain a single string name value."""

    if not readerInst.has_token():
        raise SyntaxError('reached EOF')

    malItem = readerInst.next()

    try:
        intNum = int(malItem)
        return parser.IntSymbol(intNum)
    except ValueError:
        #print ("malItem:", malItem)
        #print ("len:", len(malItem))
        if ((len(malItem) > 1) and (malItem[0] == '"')
                and (malItem[-1] == '"')):
            s = printer.unescape(malItem[1:-1])
            #print ("making lisp string:", s)
            #for i,c in enumerate(s):
            #    print (i, c)
            return parser.LispString(s)

        if ((len(malItem) > 1) and (malItem[0] == ':')):
            s = malItem[1:]
            return parser.LispKeyword(s)
        if malItem == 'nil':
            return parser.NilSymbol()
        elif malItem == 'true':
            return parser.TrueSymbol()
        elif malItem == 'false':
            return parser.FalseSymbol()
        else:
            return parser.StrSymbol(malItem)
Пример #2
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)])
Пример #3
0
def func_readline(arg):
    prompt = printer.pr_str(arg, False)

    try:
        if sys.version_info[0] >= 3:
            #print(prompt, end='', flush=True)
            in_str = input(prompt)
        else:
            in_str = raw_input(prompt)
        return parser.LispString(in_str)
    except EOFError:
        return parser.NilSymbol()
Пример #4
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

        ast = macro_expand(ast, env)
        if not isinstance(ast, parser.LispList):
            return eval_ast(ast, env)
        
        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
        if isinstance(op, parser.StrSymbol) and op.val == 'defmacro!':
            val = EVAL(ast.values[2], env)
            val.setMacro(True)
            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].values), 2):
                name = ast.values[1].values[i].val
                val = EVAL(ast.values[1].values[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, EVAL)
            return funcClosure
        elif isinstance(op, parser.StrSymbol) and op.val == 'quote':
            return ast.values[1]
        elif isinstance(op, parser.StrSymbol) and op.val == 'quasiquote':
            ast = quasiquote(ast.values[1])
            continue
        elif isinstance(op, parser.StrSymbol) and op.val == 'macroexpand':
            return macro_expand(ast.values[1], env)
        elif isinstance(op, parser.StrSymbol) and op.val == 'try*':
            catchop = ast.values[2].values[0]
            if isinstance(catchop, parser.StrSymbol) and catchop.val == 'catch*':
                try:
                    return EVAL(ast.values[1], env)
                except parser.MalException as me:
                    ex_label = ast.values[2].values[1].val
                    newenv = environment.Environment(env, [ex_label], [me.mal_obj])
                    return EVAL(ast.values[2].values[2], newenv)
                    
                except Exception as e:
                    ex_label = ast.values[2].values[1].val
                    ex_str = parser.LispString(str(e))
                    newenv = environment.Environment(env, [ex_label], [ex_str])
                    return EVAL(ast.values[2].values[2], newenv)
            else:
                return EVAL(ast.values[1], env)
        else:
            ast_list = eval_ast(ast, env)
            
            if isinstance(ast_list.values[0], parser.FuncClosure):
                func = ast_list.values[0]

                ast = func.body
                env = func.prepareEnv(ast_list.values[1:])
                continue
    
            #print ("about to call", ast_list.values[0])
            
            return ast_list.values[0](*ast_list.values[1:])
Пример #5
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")
        
Пример #6
0
def func_python_eval(arg):
    s = printer.pr_str(arg, False)
    val = str(eval(s))
    return parser.LispString(val)
Пример #7
0
def func_slurp(arg):
    if not isinstance(arg, parser.LispString):
        raise ArgumentError("should be a string")
    fn = arg.str
    with open(fn) as fileObj:
        return parser.LispString(fileObj.read())
Пример #8
0
def func_str(*args):
    strings = [printer.pr_str(a, False) for a in args]
    joined = "".join(strings)
    return parser.LispString(joined)