def def_(args, scopes): if len(args) != 2: raise TypeError("def takes two arguments") atom = args.first() rhs = args.second() if type(atom) is not Atom: raise TypeError("First argument to def must be atom") scopes[-1][atom.name()] = evaluate(rhs, scopes)
def evaluate(x, scopes): if type(x) in (int, float): return x elif type(x) is Atom: val = find_in_scopechain(scopes, x.name()) if not val: raise UnknownVariable("Unknown variable: %s" % x.name()) else: return val elif type(x) is Keyword: return x elif type(x) is Vector: return apply(Vector, [evaluate(el, scopes) for el in x]) elif type(x) is Map: return Map(dict([(evaluate(k, scopes), evaluate(v, scopes)) for k, v in x.items()])) elif type(x) is List: contents = x return eval_list(contents, scopes) return x
def eval_list(contents, scopes): if contents.empty(): return List() # () first = contents.first() rest = contents.rest() if type(first) is Map: if not rest.rest().empty(): raise TypeError("Map lookup takes one argument") return evaluate(first, scopes)[evaluate(rest.first(), scopes)] elif type(first) is Atom: name = first.name() if name in BUILTIN_FUNCTIONS: func = BUILTIN_FUNCTIONS[name] return func(rest, scopes) else: val = find_in_scopechain(scopes, name) if not val: raise UnknownVariable("Function %s is unknown" % name) if callable(val): args = map((lambda obj: evaluate(obj, scopes)), rest) return val(*args) else: raise TypeError("%s is not callable" % name)
def main(): global_scope = GlobalScope() scopechain = [global_scope] while True: try: txt = raw_input("pyclojure> ") if re.search('^\s*$', txt): continue else: print(tostring(evaluate( parser.parse(txt, lexer=lexer), scopechain))) except EOFError: break except KeyboardInterrupt: print # Give user a newline after Cntrl-C for readability break except Exception, e: print e
def evalparse(x): return evaluate(parse(x), scopechain)