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)
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)])
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()
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:])
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")
def func_python_eval(arg): s = printer.pr_str(arg, False) val = str(eval(s)) return parser.LispString(val)
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())
def func_str(*args): strings = [printer.pr_str(a, False) for a in args] joined = "".join(strings) return parser.LispString(joined)