def eval(self, exp, env): condition = exp.getCdr().getCar() if condition.eval(env) == BoolLit.getInstance(True): return exp.getCdr().getCdr().getCar().eval(env) elif not (exp.getCdr().getCdr().getCdr() == Nil.getInstance()): return exp.getCdr().getCdr().getCdr().getCar().eval(env) else: return StrLit("else expression not found")
def setEnv(cls, e): cls.env = e #TODO: Cleanup builtins = [ "b+", "b-", "b/", "b*", "b=", "b<", "number?", "null?", "procedure?", "pair?", "cons", "car", "cdr", "set-car!", "set-cdr!", "eq?", "interaction-environment", "load", "read", "write", "display", "eval", "apply", "newline" ] for i in builtins: cls.env.define(Ident(i), Cons(BuiltIn(StrLit(i)), Nil.getInstance()))
def eval(self, exp, env): key = exp.getCdr().getCar() val = exp.getCdr().getCdr().getCar() # if defining a variable if key.isSymbol(): env.define(key, val) # if defining a function else: func = Closure( Cons(exp.getCdr().getCar().getCdr(), exp.getCdr().getCdr()), env) env.define(key.getCar(), func) return StrLit("no values returned")
def populateEnv(cls, env, ini_file): builtIns = [ 'symbol?', 'number?', 'b+', 'b-', 'b*', 'b/', 'b=', 'b<', 'car', 'cdr', 'cons', 'set-car!', 'set-cdr!', 'null?', 'pair?', 'eq?', 'procedure?', 'read', 'write', 'display', 'newline', 'eval', 'apply', 'interaction-environment', 'load' ] for name in builtIns: id = Ident(name) env.define(id, BuiltIn(id)) if os.path.exists(ini_file): #sys.stdout.write('path exists') path = env.lookup(Ident('load')) path.apply(Cons(StrLit(ini_file), Nil.getInstance()))
def populateEnv(env, file): # Array of builtIn names builtIns = [ 'read', 'newline', 'interaction-environment', 'load', 'car', 'cdr', 'number?', 'symbol?', 'null?', 'pair?', 'procedure?', 'write', 'display', 'eq?', 'cons', 'set-car!', 'set-cdr!', 'eval', 'apply', 'b+', 'b-', 'b*', 'b/', 'b=', 'b<' ] # for each name in the builtIns array, define it in the environment for name in builtIns: node = Ident(name) env.define(node, BuiltIn(node)) # as long as the file exists, load file into the environment using the load built-in function if os.path.exists(file): load = env.lookup(Ident('load')) load.apply(Cons(StrLit(file), Nil.getInstance()))
def buildStrLit(self,s): return StrLit(s)
def apply(self, args): argLength = self.util.length(args) name = self.symbol.strVal if name == "b+": #Binary Addition if argLength is not 2: return self.invalidArgCount() if not args.getCar().isNumber() or not args.getCdr().getCar( ).isNumber(): return self.invalidArgType() sum = args.getCar().intVal + args.getCdr().getCar().intVal return IntLit(sum) elif name == "b-": #Binary Subtraction if argLength is not 2: return self.invalidArgCount() if not args.getCar().isNumber() or not args.getCdr().getCar( ).isNumber(): return self.invalidArgType() diff = args.getCar().intVal - args.getCdr().getCar().intVal return IntLit(diff) elif name == "b*": #Binary Multiplication if argLength is not 2: return self.invalidArgCount() if not args.getCar().isNumber() or not args.getCdr().getCar( ).isNumber(): return self.invalidArgType() return IntLit(args.getCar().intVal * args.getCdr().getCar().intVal) elif name == "b/": #Binary Division if argLength is not 2: return self.invalidArgCount() if not args.getCar().isNumber() or not args.getCdr().getCar( ).isNumber(): return self.invalidArgType() return IntLit(args[0].intVal / args.getCdr().getCar().intVal) elif name == "number?": #Check if is a number if argLength is not 1: return self.invalidArgCount() if args.getCar().isNumber(): return BoolLit.getInstance(True) return BoolLit.getInstance(False) elif name == "b=": if argLength is not 2: return self.invalidArgCount() if not args.getCar().isNumber() or not args.getCdr().getCar( ).isNumber(): return self.invalidArgType() return BoolLit.getInstance(True) if args.getCar( ).intVal == args.getCdr().getCar().intVal else BoolLit.getInstance( False) elif name == "b<": if argLength is not 2: return self.invalidArgCount() if not args.getCar().isNumber() or not args.getCdr().getCar( ).isNumber(): return self.invalidArgType() return BoolLit.getInstance(True) if args.getCar( ).intVal < args.getCdr().getCar().intVal else BoolLit.getInstance( False) elif name == "null?": if argLength is not 1: return self.invalidArgCount() if args.getCar().isNull(): return BoolLit.getInstance(True) return BoolLit.getInstance(False) elif name == "procedure?": if argLength is not 1: return self.invalidArgCount() if args.getCar().isProcedure(): return BoolLit.getInstance(True) return BoolLit.getInstance(False) elif name == "pair?": if argLength is not 1: return self.invalidArgCount() return BoolLit.getInstance( True) if args.getCar().isPair() else BoolLit.getInstance(False) elif name == "cons": if argLength is not 2: return self.invalidArgCount() return Cons(args.getCar(), args.getCdr().getCar()) elif name == "car": if argLength is not 1: return self.invalidArgCount() if not args.getCar().isPair(): return self.invalidArgType() return args.getCar().getCar() elif name == "cdr": if argLength is not 1: return self.invalidArgCount() if not args.getCar().isPair(): return self.invalidArgType() return args.getCar().getCdr() elif name == "set-car!": if argLength is not 2: return self.invalidArgCount() if not args.getCar().isPair(): return self.invalidArgType() args.getCar().setCar(args.getCdr().getCar()) return Nil.getInstance() elif name == "set-cdr!": if argLength is not 2: return self.invalidArgCount() if not args.getCar().isPair(): return self.invalidArgType() args.getCar().setCdr(args.getCdr().getCar()) return Nil.getInstance() elif name == "eq?": if args.getCar().isSymbol() and args.getCdr().getCar().isSymbol(): arg1_name = args.getCar().getName() arg2_name = args.getCdr().getCar().getName() return BoolLit.getInstance(arg1_name == arg2_name) return BoolLit.getInstance(args.getCar() == args.getCdr().getCar()) #load elif name == "load": if not args.getCar().isString(): return self.invalidArgType() filename = args.getCar().strVal try: scanner = Scanner(open(filename)) builder = TreeBuilder() parser = Parser(scanner, builder) root = parser.parseExp() while root != None: root.eval(BuiltIn.env) root = parser.parseExp() except IOError: self._error("could not find file " + filename) return Nil.getInstance() # or Unspecific.getInstance() #read, calls parser and returns a parse tree elif name == "read": scanner = Scanner(sys.stdin) builder = TreeBuilder() parser = Parser(scanner, builder) #return parse tree here if parser != None: return parser.parseExp() return Ident('End of Parse Tree') #write, calls pretty printer elif name == "write": if argLength is not 1: return self.invalidArgCount() args.getCar().print(-1) return Nil.getInstance() #display, calls pretty printer elif name == "display": if argLength is not 1: return self.invalidArgCount() StrLit.include_quote = 0 args.getCar().print(-1) StrLit.include_quote = 1 return Nil.getInstance() #eval, calls python eval function elif name == 'eval': if argLength is not 2: return self.invalidArgCount() if args.getCdr().getCar().isEnvironment(): return args.getCar().eval(args.getCdr().getCar()) return self.invalidArgType() #apply, calls python apply function elif name == "apply": if argLength is not 2: return self.invalidArgCount() return args.getCar().apply(args.getCdr().getCar()) #interaction-environment, returns a pointer to interpreter's global environment elif name == "interaction-environment": return BuiltIn.env #newline without optional port argument elif name == "newline": sys.stdout.write('\n') sys.stdout.flush() return Nil.getInstance() return StrLit("Error: BuiltIn.apply not yet implemented for " + self.symbol)
def apply(self, args): if args == None: return None symbolName = self.symbol.getName() arg1 = args.getCar() if arg1 == None or arg1.isNull(): arg1 = Nil() arg2 = args.getCdr() if arg2 == None or arg2.isNull(): arg2 = Nil() if symbolName == '+': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return IntLit(x + y) else: print('bad argument for +') return StrLit("") elif symbolName == '-': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return IntLit(x - y) else: print('bad argument for -') return StrLit("") elif symbolName == '*': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return IntLit(x * y) else: print('bad argument for *') return StrLit("") elif symbolName == '/': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return IntLit(x / y) else: print('bad argument for /') return StrLit("") elif symbolName == '=': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return BoolLit(x == y) else: print('bad argument for =') elif symbolName == '<': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return BoolLit(x < y) else: print('bad argument for <') elif symbolName == '>': if arg1.isNumber() and arg2.isNumber(): x = arg1.getIntVal() y = arg2.getIntVal() return BoolLit(x > y) else: print('bad argument for >') elif symbolName == 'car': if arg1.isNull(): return arg1 return arg1.getCar() elif symbolName == 'cdr': if arg1.isNull(): return arg1 return arg1.getCdr() elif symbolName == 'cons': return Cons(arg1, arg2) elif symbolName == 'set-car!': arg1.setCar(arg2) return arg1 elif symbolName == 'set-cdr!': arg1.setCdr(arg2) return arg1 elif symbolName == 'symbol?': return BoolLit(arg1.isSymbol()) elif symbolName == 'number?': return BoolLit(arg1.isNumber()) elif symbolName == 'null?': return BoolLit(arg1.isNull()) elif symbolName == 'pair?': return BoolLit(arg1.isPair()) elif symbolName == 'eq?': if (arg1.isBool() and arg2.isBool()) or (arg1.isNumber() and arg2.isNumber()) or ( arg1.isString() and arg2.isString()): return BoolLit(arg1 == arg2) elif arg1.isSymbol() and arg2.isSymbol(): return BoolLit(arg1.getName() == arg2.getName()) elif arg1.isNull() and arg2.isNull(): return BoolLit(True) elif arg1.isPair() and arg2.isPair(): frontArgs = Cons(arg1.getCar(), Cons(arg2.getCar(), Nil)) backArgs = Cons(arg1.getCdr(), Cons(arg2.getCdr(), Nil)) return BoolLit(apply(frontArgs) and apply(backArgs)) return BoolLit(false) elif symbolName == 'procedure?': return BoolLit(arg1.isProcedure) elif symbolName == 'display': return arg1 elif symbolName == 'newline': return StrLit("", false) elif symbolName == 'exit' or symbolName == 'quit': exit() elif symbolName == 'write': arg1.print(0) elif symbolName == 'eval': return arg1 elif symbolName == 'apply': return arg1.apply(arg2) elif symbolName == 'read': parser = Parser() return parser.parseExp() elif symbolName == 'interaction-environment': self.env.print(0) else: arg1.print(0) return Nil() return StrLit('>')
def eval(self, exp, env): return StrLit("eval for this special has not been defined")
def apply(self, args): ## The easiest way to implement BuiltIn.apply is as an ## if-then-else chain testing for the different names of ## the built-in functions. E.g., here's how load could ## be implemented: # if name == "load": # if not arg1.isString(): # self._error("wrong type of argument") # return Nil.getInstance() # filename = arg1.getStrVal() # try: # scanner = Scanner(open(filename)) # builder = TreeBuilder() # parser = Parser(scanner, builder) # root = parser.parseExp() # while root != None: # root.eval(BuiltIn.env) # root = parser.parseExp() # except IOError: # self._error("could not find file " + filename) # return Nil.getInstance() # or Unspecific.getInstance() # this may or may not work # get args (arg 1 is the car, arg 2 is the car of the cdr) if args == None: return Nil.getInstance() name = self.symbol.getName() car = args.getCar() if car.isNull(): car = Nil.getInstance() cdr = args.getCdr() # if there is no arg 2, just set it to nil if cdr.isNull(): cdr = Nil.getInstance() # otherwise arg2 is the car of the cdr else: cdr = cdr.getCar() if name == "b+": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return IntLit(x + y) else: return StrLit("Invalid arguments for b+") elif name == "b-": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return IntLit(x - y) else: return StrLit("Invalid arguments for b-") elif name == "b*": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return IntLit(x * y) else: return StrLit("Invalid arguments for b*") elif name == "b/": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return IntLit(x / y) else: return StrLit("Invalid arguments for b/") elif name == "b=": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return BoolLit.getInstance(x == y) else: return StrLit("Invalid arguments for b=") elif name == "b<": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return BoolLit.getInstance(x < y) else: return StrLit("Invalid arguments for b<") elif name == "b>": if car.isNumber() and cdr.isNumber(): x = car.intVal y = cdr.intVal return BoolLit.getInstance(x > y) else: return StrLit("Invalid arguments for b>") elif name == "car": if car.isPair(): return car.getCar() return StrLit("Wrong number of arguements") elif name == "cdr": if car.isPair(): return car.getCdr() return StrLit("Wrong number of arguements") elif name == "cons": if cdr.isPair(): return Cons(car, cdr) return StrLit("Wrong number of arguements") elif name == "set-car!": #does this work?? car.setCar(cdr) return car elif name == "set-cdr!": #does this work?? car.setCdr(cdr) return car elif name == "symbol?": return BoolLit.getInstance(car.isSymbol()) elif name == "number?": return BoolLit.getInstance(car.isNumber()) elif name == "null?": return BoolLit.getInstance(car == Nil.getInstance()) elif name == "pair?": return BoolLit.getInstance(car.isPair()) elif name == "eq?": #come back to this if car.isBool() and cdr.isBool(): return BoolLit.getInstance(car.boolVal == cdr.boolVal) elif car.isNumber() and cdr.isNumber(): return BoolLit.getInstance(car.intVal == cdr.intVal) elif car.isSymbol() and cdr.isSymbol(): return BoolLit(car.getName().equals(cdr.getName())) elif car == Nil.getInstance(): return BoolLit.getInstance(True) elif (car.isPair() and cdr.isPair()): opener = Cons(car.getCar(), Cons(cdr.getCar(), Nil.getInstance())) closer = Cons(car.getCdr(), Cons(cdr.getCdr(), Nil.getInstance())) return BoolLit(apply(opener).boolVal and apply(closer).boolVal) elif name == "procedure?": return BoolLit.getInstance(car.isProcedure()) elif name == "display": return car elif name == "newline": #come back to this StrLit("") elif name == "read": parser = Parser(Scanner(sys.stdin)) #com back to this return parser.parseExp() elif name == "write": #come back to this car.print(0) return StrLit("") elif name == "eval": #come back return car elif name == "apply": #come back return car.apply(cdr) elif name == "interaction-development": #come back interaction_environment.print(0) elif name == "load": #come back if not car.isString(): self._error("wrong type of argument") return Nil.getInstance() filename = arg1.getStrVal() try: scanner = Scanner(open(filename)) builder = TreeBuilder() parser = Parser(scanner, builder) root = parser.parseExp() while root != None: root.eval(BuiltIn.env) root = parser.parseExp() except IOError: self._error("could not find file " + filename) return Nil.getInstance() # or Unspecific.getInstance() else: car.print(0) return Nil.getInstance() return StrLit(">")
def eval(self, exp, env): key = exp.getCdr().getCar() val = exp.getCdr().getCdr().getCar() if key.isSymbol(): env.assign(key,val) return StrLit("no values returned")