def read_form(reader): tok = reader.peek() val = None if not tok: val = mtypes.MslNil() elif tok[0] == ';': reader.next() val = None elif tok == '\'': reader.next() return mtypes.MslList([ mtypes.MslSymbol('quote'), read_form(reader) ]) elif tok == '`': reader.next() return mtypes.MslList([ mtypes.MslSymbol('quasiquote'), read_form(reader) ]) elif tok == '~': reader.next() return mtypes.MslList([ mtypes.MslSymbol('unquote'), read_form(reader) ]) elif tok == '~@': reader.next() return mtypes.MslList([ mtypes.MslSymbol('slice-unquote'), read_form(reader) ]) elif tok == '@': reader.next() return mtypes.MslList([ mtypes.MslSymbol('deref'), read_form(reader) ]) elif tok == ')': raise Exception("Unexpected ')' reading form") elif tok == '(': val = read_list(reader) elif tok == ']': raise Exception("Unexpected ']'") elif tok == '[': val = read_vector(reader) elif tok == '}': raise Exception("Unexpected '}'") elif tok == '{': val = read_hashmap(reader) else: val = read_atom(reader) return val
def c_cons(x, seq): print('params', x, seq) lst1 = mtypes.MslList([x]) lst2 = mtypes.MslList([seq]) print('lst1', lst1) print('lst2', lst2) res = lst1.values + lst2.values print('res', res) return mtypes.MslList(res)
def quasiquote(ast, qflag=False): print("qquote", ast) if not is_pair(ast): if isinstance(ast, mtypes.MslList): if len(ast) > 0: return ast[0] else: return ast else: if isinstance(ast, mtypes.MslSymbol): return mtypes.MslList([ mtypes.MslSymbol("quote"), ast ]) else: return ast elif ast[0] == mtypes.MslSymbol('unquote'): return ast[1] elif is_pair(ast[0]) and ast[0][0] == mtypes.MslSymbol('splice-unquote'): if len(ast[1:]) > 0: lst = [ mtypes.MslSymbol("concat"), ast[0][1], ] lst.append(quasiquote(ast[1:])) return mtypes.MslList(lst) else: lst = [ ast[0][1], ] return mtypes.MslList(lst) else: if len(ast[1:]) > 0: lst = [ mtypes.MslSymbol("cons"), quasiquote(ast[0]), ] lst.append(quasiquote(ast[1:], True)) return mtypes.MslList(lst) else: lst = [ quasiquote(ast[0], True), ] return mtypes.MslList(lst)
def eval_ast(ast, env): if not hasattr(ast, 'type'): merror.error("eval_ast: Error evaluating AST(%s) %s" % (type(ast), repr(ast))) if ast.type == 'symbol': return env.get(ast.symval) elif ast.type == 'list': res = [] for e in ast.values: evaled = msl_eval(e, env) res.append(evaled) return mtypes.MslList(res) elif ast.type == 'vec': res = [] for e in ast.values: evaled = msl_eval(e, env) res.append(evaled) return mtypes.MslVector(res) elif ast.type == 'hashmap': newhm = mtypes.MslHashmap([]) for k in ast.hm: newhm.hm[k] = msl_eval(ast.hm[k], env) return newhm else: return ast
def c_cons(x, y): print(x, y) newlist = mtypes.MslList([]) newlist.append(x) if isinstance(y, mtypes.MslList): #newlist.values.extend(y.values) newlist.extend(y) else: newlist.append(y) return newlist
def c_concat(*args): final_lst = mtypes.MslList([]) for lst in args: final_lst.values.extend(lst) return final_lst
def make_list(*args): return mtypes.MslList(args)
def msl_eval(ast, env): while True: # print('ast', repr(ast)) if hasattr(ast, 'type'): if ast.type == 'list': if len(ast) == 0: return ast else: funcname = ast.values[0] if hasattr(funcname, 'type'): if funcname.type == 'symbol': funcname = funcname.symval if funcname == 'def!': a1, a2 = ast.values[1], ast.values[2] res = msl_eval(a2, env) return env.set(a1.symval, res) elif funcname == "let*": a1, a2 = ast.values[1], ast.values[2] let_env = menv.Enviroment(env) for i in range(0, len(a1), 2): let_env.set(a1.values[i].symval, msl_eval(a1.values[i+1], let_env)) env = let_env ast = a2 continue elif funcname == 'exit' or funcname == 'quit': a1 = ast.values[1] if not isinstance(a1, mtypes.MslNumber): raise RuntimeError('A number is required') sys.exit(a1.num) elif funcname == 'do': vals = mtypes.MslList(ast.values[1:-1]) eval_ast(vals, env) ast = ast[-1] continue elif funcname == 'if': a1, a2 = ast.values[1], ast.values[2] cond = msl_eval(a1, env) if (cond == None) or (not cond): if len(ast.values) > 3: ast = ast.values[3] continue else: ast = None continue else: ast = a2 continue elif funcname == 'fn*': a1, a2 = ast.values[1], ast.values[2] return mtypes.MslFunction(msl_eval, menv.Enviroment, a2, env, a1) elif funcname == 'quote': return ast.values[1] elif funcname == 'quasiquote': ast = quasiquote(ast[1], False) continue else: d = eval_ast(ast, env) f = d[0] if hasattr(f, '__ast__'): ast = f.__ast__ env = f.__gen__env(d.values[1:]) continue else: if callable(f): return f(*d.values[1:]) # my beautiful hack elif isinstance(ast, mtypes.MslPList): possible_fname = ast[0] print('pfname', possible_fname) ''' TODO: msl> `(1 2 (3 4)) pfname List([Symbol('cons'), Number(3), P_List([Number(4)])]) pfname Number(4) (1 2 3 4) should give (1 2 (3 4)) ''' if isinstance(possible_fname, mtypes.MslList): if isinstance(possible_fname[0], mtypes.MslSymbol): if env.find(possible_fname[0].symval): '''print("got func %s in plist" % possible_fname[0].symval) print("fargs %r" % possible_fname[1:])''' d = eval_ast(possible_fname, env) f = d[0] # ast = mtypes.MslList(ast.values) return f(*d.values[1:]) else: return eval_ast(ast, env) else: return eval_ast(ast, env) return ast