public override Node eval(Node t, Environment e) { if(t.getCdr() is Closure) return e.lookup(t.getCar()).apply(t.getCdr()); else { Node args = t.getCdr(); Node param; if (args.getCar().isSymbol()) param = new Cons(e.lookup((Node)args.GetCar()), Nil.getInstance()); else param = new Cons((Node)args.GetCar(), Nil.getInstance()); Node currentNode = param; args = args.getCdr(); while (args != Nil.getInstance()) { if (args.getCar().isSymbol()) currentNode.setCdr(new Cons(e.lookup(args.getCar()), Nil.getInstance())); else currentNode.setCdr(new Cons(args.getCar(), Nil.getInstance())); currentNode = currentNode.getCdr(); args = args.getCdr(); } return e.lookup(t.getCar()).apply(param); } }
public override Node eval(Node exp, Environment env) { int length = Util.expLength(exp); if (length < 3) { Console.Error.WriteLine("Error: invalid expression"); return Nil.getInstance(); } Node second = exp.getCdr().getCar(); Node name, value; if (length == 3 && second.isSymbol()) { name = second; value = exp.getCdr().getCdr().getCar().eval(env); env.define(name, value); return null; } if (!second.isPair()) { Console.Error.WriteLine("Error: invalid expression"); return Nil.getInstance(); } name = second.getCar(); Node lambda = exp.getCdr(); lambda.setCar(second.getCdr()); lambda = new Cons(new Ident("lambda"), lambda); value = lambda.eval(env); env.define(name, value); return null; }
public Node evalLetBody(Node t, Environment env) { if(t == Nil.getInstance()) //This isn't correct. What do? { Node l = new Cons(new Nil(), new Nil()); //tree with pair of () return l; } else { Node restBody = t.getCdr(); Node variable = t.getCar().getCar(); Node value = t.getCar().getCdr().getCar(); if(variable.isSymbol()) //was value earlier, should be variable? { env.define(variable,value.eval(env)); return evalLetBody(restBody, env); } else if(!variable.isPair()) //if it is a cons node. ??? { Console.Write("Error in Let->evalLetBody, variable is not valid"); return new Nil(); } else if(variable.isNull()) { return new Nil(); } else { return variable.eval(env); } } }
// TODO: The method apply() should be defined in class Node // to report an error. It should be overridden only in classes // BuiltIn and Closure. public override Node apply(Node args) { Environment funcEnvironment = new Environment(env); Node param = fun.getCdr().getCar(); while (param != Nil.getInstance() && args != Nil.getInstance()) { funcEnvironment.define(param.getCar(), args.getCar()); param = param.getCdr(); args = args.getCdr(); } Node body = new Cons(new Ident("begin"), fun.getCdr().getCdr()); return body.eval(funcEnvironment); }
public override Node eval(Environment env, Node args) { // Evaluate the list Node evaluated = new Cons(args.getCar().eval(env), args.getCdr().eval(env)); // If the car is a closure, apply it if (evaluated.getCar().isProcedure()) { return(evaluated.getCar().apply(evaluated.getCdr())); } else { return(evaluated); } }
public override Node apply(Node args) { Environment funcEnv = new Environment(env); Node temp = fun.getCdr().getCar(); while (temp != Nil.getInstance()) { funcEnv.define(temp.getCar(), args.getCar()); temp = temp.getCdr(); args = args.getCdr(); } Node body = new Cons(new Ident("begin"), fun.getCdr().getCdr()); return(body.eval(funcEnv)); }
public void assign(Node id, Node val) { // search for id in id_value_pair in frame heirarchy Node result_lookup = lookup(id); // if nothing found, report error. if (result_lookup == null) { Console.Error.WriteLine("Exception in assigning: variable with that name does not exist"); } else { result_lookup = new Cons(val, Nil.getInstance()); } }
public override Node eval(Node t, Environment env) { Node variable = t.getCdr().getCar(); if(variable.isPair()) { //variable is of the form (decl params...), ex: (foo x y) Node declaration = variable.getCar(); Node parameters = variable.getCdr(); Cons lambda = new Cons(new Ident("lambda"),new Cons(parameters,t.getCdr().getCdr().getCar())); env.define(declaration,new Closure(lambda, env)); } else { env.define(variable, t.getCdr().getCdr().getCar().eval(env)); } return new StringLit("definition recorded"); }
public override Node eval(Node t, Environment env) { Node car1 = t.getCdr().getCar(); Node car2 = t.getCdr().getCdr().getCar(); if (car1.isSymbol()) { // if first arg is not a list, define variable env.define(car1, car2); } else { // if first arg is list, define function and function body Cons funcbody = new Cons(car1.getCdr(), t.getCdr().getCdr()); Node closureFun = new Cons(new Ident("lambda"), funcbody).eval(env); env.define(car1.getCar(), closureFun); } return(Void.getInstance()); }
public override Node eval(Node exp, Environment env) { int numArgs = 0; Node expCdr = exp.getCdr(); while (!expCdr.isNull()) { numArgs++; expCdr = expCdr.getCdr(); } if (numArgs < 2) { Console.Error.WriteLine("Error: invalid expression"); return(Nil.getInstance()); } Node arg1 = exp.getCdr().getCar(); if (numArgs == 2 && arg1.isSymbol()) { Node val = exp.getCdr().getCdr().getCar(); env.define(arg1, val.eval(env)); return(new StringLit("; no values returned", false)); } if (arg1.isPair()) { Node fName = arg1.getCar(); Node fArgs = arg1.getCdr(); Node fBody = exp.getCdr().getCdr(); bool validArgs = verifyArgs(fArgs); if (fName.isSymbol() && validArgs) { Node node = new Cons(new Ident("lambda"), new Cons(fArgs, fBody)); env.define(fName, node.eval(env)); return(new StringLit("; no values returned", false)); } Console.Error.WriteLine("Error: ill-formed definition"); return(Nil.getInstance()); } Console.Error.WriteLine("Error: invalid expression"); return(Nil.getInstance()); }
public override Node eval(Environment env, Node args) { Node expr1 = args.getCar(); if (args.getCdr().isNull() == true) { return(new StringLit("Error: Only 1 argument passed to 'define.'")); } else if (args.getCdr().getCdr().isNull() == false) { return(new StringLit("Error: Too many arguments passed to 'define.'")); } // Is this defining a function? else if (expr1.isPair() == true) { if (expr1.getCar().isSymbol() == true) { // Construct the lambda expression Node formalsAndBody = new Cons(expr1.getCdr(), args.getCdr()); Node lambdaExpr = new Cons(new Ident("lambda"), formalsAndBody); // define.apply() return(env.define(expr1.getCar(), lambdaExpr.eval(env))); } else { return(new StringLit("Error: First argument to 'define' must be a <variable>")); } } else { if (expr1.isSymbol() == true) { // define.apply() return(env.define(expr1, args.getCdr().getCar().eval(env))); } else { return(new StringLit("Error: First argument to 'define' must be a <variable>")); } } }
public Node evalRest(Node t, Environment env) { Node c; if(t == null) { c = new Cons(new Nil(), new Nil()); } else { Node car = t.getCar(); Node cdr = t.getCdr(); if(car.isSymbol()) { car = env.lookup(car); } c = new Cons(car.eval(env), evalRest(cdr, env)); return c; } return c; }
public override Node eval(Node t, Environment env) { // if cdr is null, define call has no arguments (error state) if (t.getCdr() == Nil.getInstance()) { Console.Error.WriteLine("Special form 'Define' evaluated with no arguments"); return(Nil.getInstance()); } // to evaluate an expression of the form '(eval x e)', // evaluate e, store its value as e1, then look up x in the current scope. // if a binding for x exists, set the value to e1 // otherwise, add (x e1) as the first element of the first association // lists into env. t = t.getCdr(); // determine if the form is '(eval x e)' if (t.getCar().isSymbol()) { // evaluate e, then store into e1 Node e1 = t.getCdr().eval(env); env.define(t.getCar(), e1); } // if the expression is of the form '(define (x p1 ... pn) b1 ... bm)', // construct the lambda expression // (lambda(p1...pn) b1...bm) // then proceed as for the definition // (define x(lambda(p1...pn) b1...bm)) if (t.getCar().isPair()) { Node arg1 = t.getCar().getCar(); Cons arg2 = new Cons(new Ident("lambda"), new Cons(t.getCdr().getCar(), t.getCdr().getCar().getCdr())); env.define(arg1, arg2); } return(null); }
public void define(Node id, Node val) { // it should be noted that when parsing the written structure // print elements,... if there is a left parenthesis in front // in front of variable name, ... we are dealing with a function definition. // // and the variable name ought to be considered an identifier. // function example : where root cons node is given by: identifier // a . // a equals : (define (xoo x) (+ x x)) // to get expression for lambda out of any function defintion... // node funcLambda = (cons 'lambda (cons (cdr (car (cdr a))) (cdr (cdr a)))) // xoo can be looked up by querying: (car (car (cdr a))) // we only want to define this in the frontmost frame at hand. Node result_lookup = find(id, frame.get_root_of_frame()); if (result_lookup == null) { Cons node_being_added = new Cons(id, new Cons(val, Nil.getInstance())); // put new definition in front of frame ( association list structure ) frame.set_root_car_node(node_being_added); } else // if preexisting... // update node for value (, in innermost scope). { result_lookup = new Cons(val, Nil.getInstance()); } }
// to evaluate expressions of the regular form '(f a1 ... an)', // i.e. function calls that don't fit under another Special // subclass, recursively evaluate f, a1, ... an, calling the // results f', a1', ... an', then call apply with f' as the // first argument, and (a1', ... an') as the second argument. public override Node eval(Node t, Environment env) { // get f' from t to use for apply call later. Node fPrime = t.getCar().eval(env); // create node for holding list (a1' ... an') Node aPrime = Nil.getInstance(); // get cdr of regular (a1 ... an) t = t.getCdr(); // recursively evaluate a1 ... a(n-1) while (t.getCdr() != Nil.getInstance()) { aPrime = new Cons(aPrime, t.getCar().eval(env)); t = t.getCdr(); } // evaluate an, add to list, and return a' aPrime = new Cons(aPrime, t.getCar().eval(env)); return(fPrime.apply(aPrime)); }
public Node define(Node id, Node val) { Node oldVal = find(id, frame); if (oldVal != null) { // id exists in environment, update the value oldVal.setCar(val); return(new StringLit("no values returned.")); } else { // Add the new frame to the environment (front of the association list) Node newFrame = new Cons(new Cons(id, new Cons(val, null)), null); // New variable for clarity newFrame.setCdr(frame); frame = newFrame; return(new StringLit("no values returned.")); } }
public override Node eval(Node t, Environment env) { Node iden = t.getCdr().getCar(); Node val = t.getCdr().getCdr().getCar(); if (iden.isSymbol()) { env.define(iden, val); } else { Closure close = new Closure(new Cons(t.getCdr().getCar().getCdr(), t.getCdr().getCdr()), env); env.define(iden.getCar(), close); } if (iden.isPair()) { Node func = iden.getCar(); Cons list = new Cons(new Ident("lambda"), new Cons(val, t.getCdr().getCar().getCdr())); env.define(func, list); } return(new StringLit("Values are null (Define)")); }
public Node evalRegList(Node t, Environment env) { if (t == null || t.isNull()) { Node list = new Cons(Nil.getInstance(), Nil.getInstance()); return(list); } else { Node arg = t.getCar(); Node rest = t.getCdr(); if (arg.isSymbol()) { arg = env.lookup(arg); } if (arg == null || arg.isNull()) { return(Nil.getInstance()); } Node list = new Cons(arg.eval(env), evalRegList(rest, env)); return(list); } }
// sets first as function, args as function arguments, and performs apply() on first public override Node eval(Node t, Environment env) { Node first = t.getCar(); Node args = t.getCdr(); if (!(args is Nil)) { if (t.getCdr().getCar().isSymbol()) { args = getArgs(t.getCdr(), env); } if (t.getCdr().getCar().isPair() && !t.getCdr().getCar().getCar().isNumber()) { args = new Cons(t.getCdr().getCar().eval(env), Nil.getInstance()); } if (env.lookup(first).isProcedure()) { first = env.lookup(first); Node temp = first.apply(args); return(temp); } else { Console.WriteLine("Error: Procedure not specified."); } } else { if (env.lookup(first).isProcedure()) { first = env.lookup(first); Node temp = first.apply(Nil.getInstance()); return(temp); } } return(Void.getInstance()); }
// also now need to ensure that all arguments in regular expression // get their values looked up if they are symbols // implementation // Note : sometimes env1 will not conform, or be pertinent to what is written relation to c# loops and scheme code public override Node eval(Node node1, Environment env1) { if (node1 == null || node1.getCar() == null) { Console.WriteLine("Error: the expression is not initialized to values: null list and car"); return(Nil.getInstance()); } // for any regular defined function enclosed in parentheses, // the first element is supposed to be a function to be evaluated. // this variable will hold the final function head term we get. Node firstElem_car = node1.getCar(); // step one : if Car is a pair, evaluate it and store resulting ident, ... which ought to be // another function once evaluated... if (node1.getCar().isPair()) { // build new environment for this to be computed for. Environment envExtend = new Environment(env1); firstElem_car = node1.getCar().eval(envExtend); //report error if not a builtin/ or /closure if (firstElem_car == null || !firstElem_car.isProcedure()) { Console.WriteLine("Error: regular expression needs a function builtin/closure for first term!, __ + returning null instead."); return(Nil.getInstance()); } } else if (node1.getCar().isSymbol()) { // start loop to get closure from obstructing intermediate symbolic expression. bool first_element_is_not_closure = true; firstElem_car = node1.getCar(); while (first_element_is_not_closure) { firstElem_car = env1.lookup(firstElem_car); //report error if not a builtin/ or /closure if (firstElem_car == null) { Console.WriteLine("Error: regular expression needs a function builtin/closure for first term!, __ + returning null instead."); return(Nil.getInstance()); } else if (firstElem_car.isProcedure()) { first_element_is_not_closure = false; } } } // this would be improper end for cons regular expression. if (node1.getCdr() == null) { Console.WriteLine("error: one of regular expressions elements is null."); return(Nil.getInstance()); } // special builtIn eval case. BuiltIn givenId = null; if (firstElem_car.isBuiltIn()) { givenId = (BuiltIn)firstElem_car; // check if built in is eval // note carefully: if symbol == null, null pointer will happen. if (givenId.getSymbol().getName().Equals("eval")) { // build new environment for this to be computed for. Environment envExtend = new Environment(env1); // check for null values now so null pointer doesnt get encountered if (node1.getCdr().getCar() == null || node1.getCdr().getCdr() == null || node1.getCdr().getCdr().getCar() == null) { Console.WriteLine("Error: lacking one of the following for eval : expression or environment."); return(Nil.getInstance()); } // side maneuver. _ work out the environment first... bool environment_taken = false; Node env_symbol_to_lookup = node1.getCdr().getCdr().getCar(); Node environment_found = null; // check if symbol needs to be evaluated if (env_symbol_to_lookup.isSymbol()) { if (env1.lookup(env_symbol_to_lookup) != null) { environment_found = env1.lookup(env_symbol_to_lookup); } else { Console.WriteLine("Error: environment symbol was not found."); return(Nil.getInstance()); } } // check if expression needs to be evaluated else if (env_symbol_to_lookup.isPair()) { environment_found = env_symbol_to_lookup.eval(envExtend); } if (environment_found != null && environment_found.isEnvironment()) { environment_taken = true; } else { Console.WriteLine("Error: evaluation op_ did not find a fitting environment."); return(Nil.getInstance()); } // working on expression now Node args_to_eval = null; Node localTerms_data = node1.getCdr().getCar(); // check if second argument is code // and then evaluate if it needs more processing // for eval to implement as code if (localTerms_data.isPair() && environment_taken) { if (localTerms_data.getCar() != null && localTerms_data.getCar().isSymbol() && localTerms_data.getCar().getName().Equals("quote")) { Node args_of_Quote = localTerms_data.eval(envExtend); if (args_of_Quote != null) { // copy evaluated quote expression args_to_eval = args_of_Quote; } } else if (localTerms_data.getCar() != null && localTerms_data.getCar().isSymbol() && localTerms_data.getCar().getName().Equals("lambda")) { Node args_of_Lambda = localTerms_data.eval(envExtend); if (args_of_Lambda != null) { // copy evaluated lambda expression args_to_eval = args_of_Lambda; } } else { // this needs fine tuning for more special cases..\\ //("may have more cases... ") //?? args_to_eval = localTerms_data; } } else if (localTerms_data.isSymbol() && environment_taken) { Node node_symbol_expression = env1.lookup(localTerms_data); if (node_symbol_expression != null) { // copy evaluated symbol and then the environment args_to_eval = node_symbol_expression; } else { Console.WriteLine("Error: first expression argument symbol not found."); return(Nil.getInstance()); } } // return the built in eval of args and environment given if (args_to_eval != null) { Environment environment_copy_found = (Environment)environment_found; if (args_to_eval.isPair()) { return(args_to_eval.eval(environment_copy_found)); } else { return(args_to_eval.eval(environment_copy_found)); } } else { Console.WriteLine("Error: expression arg was null."); return(Nil.getInstance()); } } // note: looking at special eq? case // check if built in is eq? only look at case of (eq? 'exp 'exp) // note carefully: if symbol == null, null pointer will happen. if (givenId.getSymbol().getName().Equals("eq?") && node1.getCdr().getCar() != null && node1.getCdr().getCdr() != null && node1.getCdr().getCdr().getCar() != null && node1.getCdr().getCdr().getCdr() != null && node1.getCdr().getCdr().getCdr().isNull() && node1.getCdr().getCar().isPair() && node1.getCdr().getCdr().getCar().isPair() ) { // first we must check if the arguments to (eq? ... )are in fact quote arguments. Cons argument1 = (Cons)node1.getCdr().getCar(); Cons argument2 = (Cons)node1.getCdr().getCdr().getCar(); if (argument1.getForm_ofCons() is Tree.Quote && argument2.getForm_ofCons() is Tree.Quote) { String first_argument_printed = ""; String second_argument_printed = ""; // redirect output to evaulate if print of Pair nodes is same var originalConsoleOut = Console.Out; // preserve the original stream using (var writer = new StringWriter()) { Console.SetOut(writer); argument1.print(0); writer.Flush(); var myString = writer.ToString(); first_argument_printed = myString.TrimEnd('\n'); } using (var writer1 = new StringWriter()) { Console.SetOut(writer1); argument2.print(0); writer1.Flush(); var myString_2 = writer1.ToString(); second_argument_printed = myString_2.TrimEnd('\n'); } Console.SetOut(originalConsoleOut); // restore Console.Out if (first_argument_printed.Equals(second_argument_printed)) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } } // security check for eof-object? builtIn test... if (givenId != null && givenId.getSymbol().getName().Equals("eof-object?")) { if (node1.getCdr().isNull() || !node1.getCdr().isPair()) { Console.WriteLine("Error: no argument for eof-object? test. the BuiltIn function eof-object? requires one argument to test."); return(Nil.getInstance()); } } } // other cases builtin or closure... Node args_given = node1.getCdr(); bool hasArguments = true; // test if there are arguments to this form function if (args_given.isNull()) { hasArguments = false; } if (hasArguments) { if (args_given.getCdr() == null || args_given.getCar() == null) { Console.WriteLine("Error: one of passed arguments in function expression is null."); return(Nil.getInstance()); } // need to evaluate args (each car separately)... and then return what is resulting list of elements... // build new environment on hand _ for each car to be computed at times. Environment envExtend1 = new Environment(env1); // this will hold the list of evaluated arguments cumulatively. Cons evaluated_argsList__in_progress; // this will hold a latest fringe of for extending fringe items. Cons fringe_cons = null; bool hasMoreDescendents = !args_given.getCdr().isNull(); if (hasMoreDescendents) { // start this off as unassigned. Cons added_fringe_con = null; // this will hold the list of evaluated arguments cumulatively. // Cons evaluated_argsList__in_progress; // check if eval is not null Node evalItem1 = args_given.getCar().eval(envExtend1); if (evalItem1 != null) { evaluated_argsList__in_progress = new Cons(evalItem1, added_fringe_con); } else { // first a detour... // // check for special case of eof-object? builtIn test if (givenId != null && givenId.getSymbol().getName().Equals("eof-object?")) { Console.WriteLine("Error: too many args for function eof-object? test. "); return(Nil.getInstance()); } // normal case where regular expression argument evaluated to null is to throw an error else { Console.WriteLine("Error: one of the args items in regular function was null. "); return(Nil.getInstance()); } } // under the alias of fringe_cons... // we will continue this reference down to assess the next fringe branch fringe_cons = evaluated_argsList__in_progress; } // dealt with the sole generation here. // no more fringes left. else { // check if eval is not null Node evalItem1 = args_given.getCar().eval(envExtend1); if (evalItem1 != null) { // first a detour... // // check for special case of eof-object? builtIn test is false if (givenId != null && givenId.getSymbol().getName().Equals("eof-object?")) { return(BoolLit.getInstance(false)); } // normal case where regular expression argument evaluated to null is to throw an error else { evaluated_argsList__in_progress = new Cons(evalItem1, Nil.getInstance()); } } else { // first a detour... // // check for special case of eof-object? builtIn test is true if (givenId != null && givenId.getSymbol().getName().Equals("eof-object?")) { return(BoolLit.getInstance(true)); } // normal case where regular expression argument evaluated to null is to throw an error else { Console.WriteLine("Error: the sole additional argument item in regular function was null. "); return(Nil.getInstance()); } } } // done with first step in two levels descendents // get rest of fringes while (hasMoreDescendents) { if (args_given.getCdr() == null) { Console.WriteLine("Error: one of the later argument items in regular function was null. "); return(Nil.getInstance()); } // precaution for null pointer so it is legal to use the cdr after this test if (args_given.getCdr().isPair()) { // build new environment for this to be computed for. Environment envExtend2 = new Environment(env1); // get next fringe descendent. args_given = args_given.getCdr(); // start this off as unassigned. Cons added_fringe_con = null; // check if additional eval items are not null Node evalItem_more = args_given.getCar().eval(envExtend2); if (evalItem_more != null) { fringe_cons.setCdr(new Cons(evalItem_more, added_fringe_con)); } else { Console.WriteLine("Error: one of the later argument items in regular function was null. "); return(Nil.getInstance()); } fringe_cons = (Cons)fringe_cons.getCdr(); } else if (args_given.getCdr().isNull()) { fringe_cons.setCdr(Nil.getInstance()); hasMoreDescendents = false; } else { // build new environment for this to be computed for. Environment envExtend2 = new Environment(env1); // get one remaining fringe descendent. args_given = args_given.getCdr(); // check if additional eval items are not null Node evalItem_more = args_given.getCar().eval(envExtend2); if (evalItem_more != null) { fringe_cons.setCdr(new Cons(evalItem_more, Nil.getInstance())); } else { Console.WriteLine("Error: one of the later argument items in regular function was null. "); return(Nil.getInstance()); } hasMoreDescendents = false; } } return(firstElem_car.apply(evaluated_argsList__in_progress)); } return(firstElem_car.apply(Nil.getInstance())); }
// TODO: The method apply() should be defined in class Node // to report an error. It should be overridden only in classes // BuiltIn and Closure. public override Node apply(Node args) { // note for all built in functions that need arguments... // // the function will never do a test to check whether args is a pair, because // args is always made a pair in special Regular for launching builtin_function apply. if (this.symbol.getName().Equals("read")) { if (args == null || !args.isNull()) { Console.WriteLine("Error: Read only needs no arguments for use."); return(Nil.getInstance()); } return((Node)Scheme4101.parser.parseExp()); } else if (this.symbol.getName().Equals("write")) { if (args == null || args.isNull()) { Console.WriteLine("Error: incorrect arguments. Nil passed, which cannot be used."); return(Nil.getInstance()); } args.getCar().print(0); return(Nil.getInstance()); } else if (this.symbol.getName().equals("set-car!")) { arg1.setCar(arg2); return(arg1); } else if (this.symbol.getName().equals("set-cdr!")) { arg1.setCdr(arg2); return(arg1); } else if (this.symbol.getName().Equals("display")) { if (args == null || args.isNull()) { Console.WriteLine("Error: incorrect arguments. Nil passed, which cannot be used."); return(Nil.getInstance()); } Tree.BuiltIn.builtIn_display__do_not_print_double_quotes = true; args.getCar().print(0); Tree.BuiltIn.builtIn_display__do_not_print_double_quotes = false; return(Nil.getInstance()); } else if (this.symbol.getName().Equals("b+")) { // if there are no arguments, report error if (args == null) { Console.WriteLine("Error: no arguments given for binary addition operation."); return(Nil.getInstance()); } // return zero if there are no arguments if (args.isNull()) { return(new IntLit(0)); } // extend for all argument vars // and //check if first args have null if (args.getCar() != null && args.getCdr() != null) { bool twoArguments_or_more; // check if second argument is is nil. if (args.getCdr().isNull()) { twoArguments_or_more = false; } // see if there is a second item , ... and check that last tail of args is nil. else if (args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { twoArguments_or_more = true; } else if (args.getCdr().getCar() != null && !args.getCdr().getCdr().isNull()) { Console.WriteLine("Error: cannot process more than two args for binary addition."); return(Nil.getInstance()); } else { Console.WriteLine("Error: in b+ , one of arguments for expression has null node."); return(Nil.getInstance()); } if (twoArguments_or_more == false) { // check if argument is an intLit if (args.getCar().isNumber()) { // return the sole int lit node. return(args.getCar()); } else { Console.WriteLine("Error: in b+ , one of arguments for expression has null node."); return(Nil.getInstance()); } } else { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary addition."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); return(new IntLit(int1.getInt() + int2.getInt())); } } } else { Console.WriteLine("Error: in b+ , there is a null external node"); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b-")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary subtraction operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary subtraction."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); return(new IntLit(int1.getInt() - int2.getInt())); } } else { Console.WriteLine("Error: more than two arguments for binary subtraction is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b*")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary multiplication operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary multiplication."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); return(new IntLit(int1.getInt() * int2.getInt())); } } else { Console.WriteLine("Error: more than two arguments for binary multiplication is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b/")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary division operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary division."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); if (int2.getInt() == 0) { Console.WriteLine("Error: input not acceptable. cannot divide by zero."); return(Nil.getInstance()); } else { return(new IntLit(int1.getInt() / int2.getInt())); } } } else { Console.WriteLine("Error: more than two arguments for binary division is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b=")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary equality test operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary equality test."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); bool resultOfTest = (int1.getInt() == int2.getInt()); if (resultOfTest) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } } else { Console.WriteLine("Error: more than two arguments for binary equality test is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b<")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary less than test operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary less than test."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); bool resultOfTest = (int1.getInt() < int2.getInt()); if (resultOfTest) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } } else { Console.WriteLine("Error: more than two arguments for binary less than test is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b>")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary greater than test operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary greater than test."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); bool resultOfTest = (int1.getInt() > int2.getInt()); if (resultOfTest) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } } else { Console.WriteLine("Error: more than two arguments for binary greater than test is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b<=")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary less than equal than test operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary less than equal than test."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); bool resultOfTest = (int1.getInt() <= int2.getInt()); if (resultOfTest) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } } else { Console.WriteLine("Error: more than two arguments for binary less than equal than test is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("b>=")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for binary greater than equal than test operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { if (!args.getCar().isNumber() || !args.getCdr().getCar().isNumber()) { Console.WriteLine("Error: arguments must be IntLit for binary greater than equal than test."); return(Nil.getInstance()); } else { IntLit int1 = (IntLit)args.getCar(); IntLit int2 = (IntLit)args.getCdr().getCar(); bool resultOfTest = (int1.getInt() >= int2.getInt()); if (resultOfTest) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } } else { Console.WriteLine("Error: more than two arguments for binary greater than equal than test is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("null?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing null evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isNull()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("symbol?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing symbol evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isSymbol()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("number?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing number evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isNumber()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("boolean?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing boolean evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isBool()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("procedure?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing procedure evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isProcedure()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("pair?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing pair evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isPair()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("environment?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing environment evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isEnvironment()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("string?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for testing string evaluation."); return(Nil.getInstance()); } // extend for all argument vars // check if number of args is correct bool argument_number_good = false; if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { argument_number_good = true; } if (argument_number_good) { if (args.getCar().isString()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } else { Console.WriteLine("Error: wrong number of arguments for test. only need 1 cons node with nil tail for argument."); return(Nil.getInstance()); } } // working on predicate built in : eq? else if (this.symbol.getName().Equals("eq?")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for eq? test operation."); return(Nil.getInstance()); } // extend for all argument vars // and //check if any args have null or nil. if (args != null && args.getCar() != null && args.getCdr() != null && args.getCdr().getCar() != null && args.getCdr().getCdr().isNull()) { //if (!args.getCar () || !args.getCdr ().getCar () ) // check nil/null? first // first car is nil but second item is not nil... // or the other way around (vice versa) if ((args.getCar().isNull() && !args.getCdr().getCar().isNull()) || (!args.getCar().isNull() && args.getCdr().getCar().isNull())) { return(BoolLit.getInstance(false)); } // success: both nil else if (args.getCar().isNull() && args.getCdr().getCar().isNull()) { return(BoolLit.getInstance(true)); } // first car is type symbol but second item is not symbol... // or the other way around (vice versa) else if ((args.getCar().isSymbol() && !args.getCdr().getCar().isSymbol()) || (!args.getCar().isSymbol() && args.getCdr().getCar().isSymbol())) { return(BoolLit.getInstance(false)); } // check if both symbol now... else if (args.getCar().isSymbol() && args.getCdr().getCar().isSymbol()) { // check if the symbol's are identical if (args.getCar().getName().Equals(args.getCdr().getCar().getName())) { // success: both same symbol! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // first car is type number but second item is not number... // or the other way around (vice versa) else if ((args.getCar().isNumber() && !args.getCdr().getCar().isNumber()) || (!args.getCar().isNumber() && args.getCdr().getCar().isNumber())) { return(BoolLit.getInstance(false)); } // check if both number now... else if (args.getCar().isNumber() && args.getCdr().getCar().isNumber()) { // cast to new IntLits IntLit intLit_1 = (IntLit)args.getCar(); IntLit intLit_2 = (IntLit)args.getCdr().getCar(); // check if the int values's are equal if (intLit_1.getInt() == intLit_2.getInt()) { // success: both same integer! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // first car is type boolean but second item is not boolean... // or the other way around (vice versa) else if ((args.getCar().isBool() && !args.getCdr().getCar().isBool()) || (!args.getCar().isBool() && args.getCdr().getCar().isBool())) { return(BoolLit.getInstance(false)); } // check if both boolean now... else if (args.getCar().isBool() && args.getCdr().getCar().isBool()) { // cast nodes as new booleanNodes BoolLit boolVal1 = (BoolLit)args.getCar(); BoolLit boolVal2 = (BoolLit)args.getCdr().getCar(); // check if the bool's equal if (boolVal1.Equals(boolVal2)) { // success: both same bool! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // first car is type builtIn but second item is not builtIn... // or the other way around (vice versa) else if ((args.getCar().isBuiltIn() && !args.getCdr().getCar().isBuiltIn()) || (!args.getCar().isBuiltIn() && args.getCdr().getCar().isBuiltIn())) { return(BoolLit.getInstance(false)); } // check if both builtIn now... else if (args.getCar().isBuiltIn() && args.getCdr().getCar().isBuiltIn()) { // cast nodes as new builtIn BuiltIn builtIn_val_1 = (BuiltIn)args.getCar(); BuiltIn builtIn_val_2 = (BuiltIn)args.getCdr().getCar(); // check if the builtIn's are identical if (builtIn_val_1.getSymbol().Equals(builtIn_val_2.getSymbol())) { // success: both same builtIn! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // by process of elimination //now // a object that ends up tested here would be surely a closure... // first car is type closure but second item is not closure... // or the other way around (vice versa) else if ((args.getCar().isProcedure() && !args.getCdr().getCar().isProcedure()) || (!args.getCar().isProcedure() && args.getCdr().getCar().isProcedure())) { return(BoolLit.getInstance(false)); } // check if both closure now... else if (args.getCar().isProcedure() && args.getCdr().getCar().isProcedure()) { // cast nodes as new builtIn Closure closure_val_1 = (Closure)args.getCar(); Closure closure_val_2 = (Closure)args.getCdr().getCar(); // check if the closure's are identical if (closure_val_1.Equals(closure_val_2)) { // success: both same closure! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // first car is type environment but second item is not environment... // or the other way around (vice versa) else if ((args.getCar().isEnvironment() && !args.getCdr().getCar().isEnvironment()) || (!args.getCar().isEnvironment() && args.getCdr().getCar().isEnvironment())) { return(BoolLit.getInstance(false)); } // check if both environment now... else if (args.getCar().isEnvironment() && args.getCdr().getCar().isEnvironment()) { // cast nodes as new Environment Environment environ_1 = (Environment)args.getCar(); Environment environ_2 = (Environment)args.getCdr().getCar(); // check if the environment's are identical if (environ_1.Equals(environ_2)) { // success: both same environment! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // first car is type String but second item is not String... // or the other way around (vice versa) else if ((args.getCar().isString() && !args.getCdr().getCar().isString()) || (!args.getCar().isString() && args.getCdr().getCar().isString())) { return(BoolLit.getInstance(false)); } // check if both String now... else if (args.getCar().isString() && args.getCdr().getCar().isString()) { // cast nodes as new StringLits StringLit String_1 = (StringLit)args.getCar(); StringLit String_2 = (StringLit)args.getCdr().getCar(); // check if the StringLit's are identical if (String_1.getString().Equals(String_2.getString())) { // success: both same StringLit! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } // eq? test note: there is one caveat. If the items are both quote terms... this will be handled directly in regular eval // first car is type Pair but second item is not Pair... // or the other way around (vice versa) else if ((args.getCar().isPair() && !args.getCdr().getCar().isPair()) || (!args.getCar().isPair() && args.getCdr().getCar().isPair())) { return(BoolLit.getInstance(false)); } // check if both are type Pair now... else if (args.getCar().isPair() && args.getCdr().getCar().isPair()) { // cast nodes as new cons Pair Cons cons_1 = (Cons)args.getCar(); Cons cons_2 = (Cons)args.getCdr().getCar(); // check if the Cons's are identical if (cons_1.Equals(cons_2)) { // success: both same pair reference! return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } // illegal function for argument } else { Console.WriteLine("Error: Argument types for eq? cannot be recognized in context."); return(Nil.getInstance()); } } else { Console.WriteLine("Error: null parameter _ or _ more than two arguments for eq? test is not permissable."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("car")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for car operation."); return(Nil.getInstance()); } // check if args first item given is a pair and check if the number of arguments given is correctly 1 if (args.getCar() != null && args.getCdr() != null && args.getCdr().isNull()) { if (args.getCar().isPair()) { if (args.getCar().getCar() != null) { return(args.getCar().getCar()); } else { Console.WriteLine("Error: for car function_ , one of arguments to return is null."); return(Nil.getInstance()); } } else { Console.WriteLine("Error: for car function_ , item given is not a pair."); return(Nil.getInstance()); } } else { Console.WriteLine("Error: wrong number of arguments for car, tail is not nil. or element in arguments is null."); return(Nil.getInstance()); } } else if (this.symbol.getName().Equals("cdr")) { // if there are no arguments, report error if (args == null || args.isNull()) { Console.WriteLine("Error: no arguments given for cdr operation."); return(Nil.getInstance()); } // check if args first item given is a pair and check if the number of arguments given is correctly 1 if (args.getCar() != null && args.getCar().isPair() && args.getCdr() != null && args.getCdr().isNull()) { // check if argument's cdr is not null if (args.getCar().getCdr() != null) { return(args.getCar().getCdr()); } else { Console.WriteLine("Error: for cdr function_ , one of arguments to return is null."); return(Nil.getInstance()); } } else { Console.WriteLine("Error: for cdr, item is not pair or wrong number of arguments for cdr: tail is not nil. or element in arguments is null."); return(Nil.getInstance()); } } else { Console.WriteLine("Error: builtin is not identifiable."); return(Nil.getInstance()); } }
public void define(Node id, Node value) { Node a = new Cons(id, new Cons(value, Nil.getInstance())); this.frame = new Cons(a, this.frame); }
public override Node eval(Node cons_expression, Environment env1) { bool it_is_variable_Identifier__notFunction = false; // check for null in construct of (define elem1 elem2)... and ends current method // test1 checks if there might even be elements in expression // test 2 checks if elem1 is a Identifier or not // test 3 checks if elem2 exists if (cons_expression.getCdr().isNull() || cons_expression.getCdr().getCar().isNull() || cons_expression.getCdr().getCdr().isNull()) { return(new StringLit("Error: lacking items to be defined in (define ...) .")); } // the key of a frame is represented by the alist.getCar().getCar().getName(); // the val of a frame is represented by the alist.getCar().getCdr // check if thing being defined is a function ... or just a variable if (!cons_expression.getCdr().getCar().isPair()) { it_is_variable_Identifier__notFunction = true; } else { it_is_variable_Identifier__notFunction = false; } if (it_is_variable_Identifier__notFunction) { if (cons_expression.getCdr().getCdr().getCar() == null) { return(new StringLit("Error: node with value in definition is null. cannot define.")); } Node place_of_Node_with_Value = cons_expression.getCdr().getCdr().getCar(); if (place_of_Node_with_Value.isPair()) { // assign val to id variable // this in fact might assign our variable to point to a function term [indirectly.] env1.define(cons_expression.getCdr().getCar(), place_of_Node_with_Value.eval(env1)); // finish here. return(null); } else { if (place_of_Node_with_Value.isSymbol()) { Node lookedUp_val_term = env1.lookup(place_of_Node_with_Value); // error ... value to be assigned is undefined. if (lookedUp_val_term == null) { return(new StringLit("Error: value to be assigned is undefined expression.")); } else { // assign val looked up , unto id variable // this in fact might assign our variable to point to a function term [indirectly.] env1.define(cons_expression.getCdr().getCar(), lookedUp_val_term); } } else { // assign val onto id variable // this in fact might assign our variable to point to a function term [indirectly.] env1.define(cons_expression.getCdr().getCar(), place_of_Node_with_Value); } // finish here. return(null); } } // work out storing function in environment else { // "function assignment"; if (cons_expression.getCdr().getCar().getCdr().isNull() || cons_expression.getCdr().getCar().getCdr().isPair()) { // normal case without dot in parameters of express // create a lambda of this definition of a function // lambda node = (cons 'lambda (cons (cdr (car (cdr a))) (cdr (cdr a)))) Node lambda_function = new Cons(new Ident("lambda"), new Cons(cons_expression.getCdr().getCar().getCdr(), cons_expression.getCdr().getCdr())); Closure defined_closure = new Closure(lambda_function, env1); env1.define(cons_expression.getCdr().getCar().getCar(), defined_closure); } else { // particular spec case with a dot expression for parameters ... that ends the list without a nil // create a lambda of this definition of a function // lambda node = (cons 'lambda (cons (cdr (car (cdr a))) (cdr (cdr a)))) Node lambda_function = new Cons(new Ident("lambda"), new Cons( new Cons(cons_expression.getCdr().getCar().getCdr(), Nil.getInstance()) , cons_expression.getCdr().getCdr())); Closure defined_closure = new Closure(lambda_function, env1); env1.define(cons_expression.getCdr().getCar().getCar(), defined_closure); } } return(null); }
private Node ConstructList(Hashtable dict) { Node values = new Node(); foreach (object kvp in dict) { values = new Cons(values, new Cons(new Ident((string) kvp), (Node)dict[kvp])); } return values; }
public void define(Node id, Node val) { var newFrame = new Cons(id, new Cons(val, Nil.getInstance())); frame = new Cons(newFrame, frame); }
public void define(Node id, Node val) { Node definition = find(id, frame); if (definition != null) { definition.setCar(val); } else { Node frame = new Cons(id, new Cons(val, Nil.getInstance())); this.frame = new Cons(frame, this.frame); } }
public void define(Node id, Node val) { Node pair = new Cons(id, new Cons(val, Nil.getInstance())); frame = new Cons(pair, frame); }
// TODO: The method apply() should be defined in class Node // to report an error. It should be overridden only in classes // BuiltIn and Closure. public override Node apply(Node args) { if (args == null) { return(null); } String name = symbol.getName(); Node car = args.getCar(); if (car == null || car.isNull()) { car = Nil.getInstance(); } Node cdr = args.getCdr(); if (cdr == null || cdr.isNull()) { cdr = Nil.getInstance(); } else { cdr = cdr.getCar(); } if (name.equals("b+")) { if (car.isNumber() && cdr.isNumber()) { return(new IntLit(car.getVal() + cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b+"); return(new StringLit("")); } } else if (name.equals("b-")) { if (car.isNumber() && cdr.isNumber()) { return(new IntLit(car.getVal() - cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b-"); return(new StringLit("")); } } else if (name.equals("b*")) { if (car.isNumber() && cdr.isNumber()) { return(new IntLit(car.getVal() * cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b*"); return(new StringLit("")); } } else if (name.equals("b/")) { if (car.isNumber() && cdr.isNumber()) { return(new IntLit(car.getVal() / cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b/"); return(new StringLit("")); } } else if (name.equals("b=")) { if (car.isNumber() && cdr.isNumber()) { return(new BoolLit(car.getVal() == cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b="); } } else if (name.equals("b>")) { if (car.isNumber() && cdr.isNumber()) { return(new BoolLit(car.getVal() > cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b>"); } } else if (name.equals("b<")) { if (car.isNumber() && cdr.isNumber()) { return(new BoolLit(car.getVal() < cdr.getVal())); } else { Console.Error.WriteLine("Invalid arguments for b<"); } } else if (name.equals("car")) { if (car.isNull()) { return(car); } return(car.getCar()); } else if (name.equals("cdr")) { if (car.isNull()) { return(cdr); } return(cdr.getCdr()); } else if (name.equals("cons")) { return(new Cons(car, cdr)); } else if (name.equals("set-cdr!")) { car.setCdr(cdr); return(car); } else if (name.equals("set-car!")) { car.setCar(cdr); return(car); } else if (name.equals("symbol?")) { return(new BoolLit(car.isSymbol())); } else if (name.equals("number?")) { return(new BoolLit(car.isNumber())); } else if (name.equals("null?")) { return(new BoolLit(car.isNull())); } else if (name.equals("pair?")) { return(new BoolLit(car.isPair())); } else if (name.equals("eq?")) { if (car.isBoolean() && cdr.isBoolean()) { return(new BoolLit(car.getBoolean() == cdr.getBoolean())); } else if (car.isNumber && cdr.isNumber()) { return(new BoolLit(car.getVal() == cdr.getVal())); } else if (car.isString() && cdr.isString()) { return(new BoolLit(car.getStringVal().equals(cdr.getStringVal()))); } else if (car.isSymbol() && cdr.isSymbol) { return(new BoolLit(car.getName().equals(cdr.getName()))); } else if (car.isNull() && cdr.isNull()) { return(new BoolLit(true)); } else if (car.isPair() && cdr.isPair()) { Node opener = new Cons(car.getCar(), new Cons(cdr.getCar(), Nil.getInstance())); Node closer = new Cons(car.getCdr(), new Cons(cdr.getCdr(), Nil.getInstance())); return(new BoolLit(apply(opener).getBoolean() && apply(closer.getBoolean()))); } return(new BoolLit(false)); } else if (name.equals("procedure?")) { return(new BoolLit(car.isProcedure())); } else if (name.equals("display")) { return(car); } else if (name.equals("newline")) { return(new StringLit("", false)); } else if (name.equals("exit") || name.equals("quit")) { return(0); } else if (name.equals("write")) { car.print(0); return(new StringLit("")); } else if (name.equals("eval")) { return(car); } else if (name.equals("apply")) { return car.apply(cdr) } else if (name.equals("read")) { Parser isParsingMeOff = new Parser(new Scanner(Console.in)); return(isParsingMeOff.parseExp()); } else { car.print(0); return(Nil.getInstance()); } return(new StringLit(">")); }
private Node apply2(Node arg1, Node arg2) { string name = this.symbol.getName(); bool flag = name.Equals("eq?"); Node result; if (flag) { bool flag2 = arg1.isSymbol() && arg2.isSymbol(); if (flag2) { string name2 = arg1.getName(); string name3 = arg2.getName(); result = BoolLit.getInstance(name2.Equals(name3)); } else { result = BoolLit.getInstance(arg1 == arg2); } } else { bool flag3 = name.Equals("cons"); if (flag3) { result = new Cons(arg1, arg2); } else { bool flag4 = name.Equals("set-car!"); if (flag4) { arg1.setCar(arg2); result = Unspecific.getInstance(); } else { bool flag5 = name.Equals("set-cdr!"); if (flag5) { arg1.setCdr(arg2); result = Unspecific.getInstance(); } else { bool flag6 = name.Equals("eval"); if (flag6) { bool flag7 = arg2.isEnvironment(); if (flag7) { result = arg1.eval((Environment)arg2); } else { Console.Error.WriteLine("Error: wrong type of argument"); result = Nil.getInstance(); } } else { bool flag8 = name.Equals("apply"); if (flag8) { result = arg1.apply(arg2); } else { bool flag9 = name[0] == 'b' && name.Length == 2; if (flag9) { bool flag10 = arg1.isNumber() && arg2.isNumber(); if (flag10) { result = this.apply2(arg1.getIntVal(), arg2.getIntVal()); } else { Console.Error.WriteLine("Error: invalid arguments"); result = Nil.getInstance(); } } else { Console.Error.WriteLine("Error: wrong number of arguments"); result = Nil.getInstance(); } } } } } } } return result; }
public override Node eval(Node node1, Environment env1) { // set up environment for scope of this let body Environment current_env_of_let = new Environment(env1); bool need_to_make_bindings = true; // this will hold the list of evaluated arguments cumulatively. // dummy value to start with Cons evaluated_argsList__in_progress = new Cons(new IntLit(1), Nil.getInstance()); // check if there are items to assign to environment... // and // check if there is an body item for evaluation of let. if (node1.getCdr() != null && node1.getCdr().isPair() && node1.getCdr().getCar() != null && node1.getCdr().getCdr() != null && node1.getCdr().getCdr().isPair()) { // Make a list of values to be bound to keys given... // __list_of_terms Node current_lead_binding_node = node1.getCdr().getCar(); // this will hold the list of evaluated arguments cumulatively. // Cons evaluated_argsList__in_progress; // assign a dummy value Cons current_fringe_of_argList = new Cons(new IntLit(1), Nil.getInstance()); bool has_more_bindings_in_list = true; // this is the case that there are no items to be associated in Frame. if (current_lead_binding_node.isNull() || !current_lead_binding_node.isPair()) { has_more_bindings_in_list = false; // now it is not necessary to bind anything need_to_make_bindings = false; } bool first_run = true; while (has_more_bindings_in_list) { if (current_lead_binding_node == null) { Console.WriteLine("Error: in Let, one of items in terms being bound has null lead node."); return(Nil.getInstance()); } //stopping criteria if (current_lead_binding_node.isNull()) { has_more_bindings_in_list = false; break; } // get values if otherwise if (current_lead_binding_node.isPair()) { Node current_key_value_pair_item = current_lead_binding_node.getCar(); // check if this term is null or empty list if (current_key_value_pair_item == null || current_key_value_pair_item.isNull()) { Console.WriteLine("Error: in Let, one of key value pairs is either null or an empty list , nil."); return(Nil.getInstance()); } // check if this term is not a pair if (!current_key_value_pair_item.isPair()) { Console.WriteLine("Error: in Let, one of key value pairs is not a key value pair cons node."); return(Nil.getInstance()); } // get evaluated value here Node node_to_add; if (current_key_value_pair_item.getCdr() != null && !current_key_value_pair_item.getCdr().isNull() && current_key_value_pair_item.getCdr().isPair()) { // first check if there is the right number of value, namely just one if (current_key_value_pair_item.getCdr().getCdr() == null || !current_key_value_pair_item.getCdr().getCdr().isNull()) { Console.WriteLine("Error: in let function call,... one of key value pairs has more than one value or a null for a tail."); return(Nil.getInstance()); } // check if item holding value is an expression that needs to be evaluated if (current_key_value_pair_item.getCdr().getCar() != null && current_key_value_pair_item.getCdr().getCar().isPair()) { // build new environment for this to be computed for. Environment envExtend = new Environment(current_env_of_let); node_to_add = current_key_value_pair_item.getCdr().getCar().eval(envExtend); } // lookup value from symbol in next case... else if (current_key_value_pair_item.getCdr().getCar() != null && !current_key_value_pair_item.getCdr().getCar().isNull() && current_key_value_pair_item.getCdr().getCar().isSymbol()) { node_to_add = current_env_of_let.lookup(current_key_value_pair_item.getCdr().getCar()); if (node_to_add == null) { Console.WriteLine("Error: one of values being bound in let is undefined in lookup, and thus null."); return(Nil.getInstance()); } // case where value is not an expression or a symbol, but only a literal } else if (current_key_value_pair_item.getCdr().getCar() != null) { node_to_add = current_key_value_pair_item.getCdr().getCar(); } else { Console.WriteLine("Error: one of values being bound in let is null."); return(Nil.getInstance()); } } else { Console.WriteLine("Error: in Let, one of items that should represent value, in a key value pair, is null or holds no value."); return(Nil.getInstance()); } // add latest value of key value pairs to cumulative list of values if (first_run) { evaluated_argsList__in_progress = new Cons(node_to_add, Nil.getInstance()); current_fringe_of_argList = evaluated_argsList__in_progress; first_run = false; } else { current_fringe_of_argList.setCdr(new Cons(node_to_add, Nil.getInstance())); current_fringe_of_argList = (Cons)current_fringe_of_argList.getCdr(); } // increment to next fringe key value pair item... current_lead_binding_node = current_lead_binding_node.getCdr(); } else { Console.WriteLine("Error: in Let, one of bindings does not have cons format."); return(Nil.getInstance()); } } } else { Console.WriteLine("Error: In let expression, ... either not enought arguments given , or null node encountered."); return(Nil.getInstance()); } if (need_to_make_bindings) { // bind each variable in key value pair // current pair of all terms being binding Node current_binding_node = node1.getCdr().getCar(); // current fring of value list Node current_fringe_of_list_of_values = evaluated_argsList__in_progress; // this will hold the list of evaluated arguments cumulatively. //Cons evaluated_argsList__in_progress; bool more_key_val_pairs_to_bind = true; while (more_key_val_pairs_to_bind) { if (current_binding_node == null) { Console.WriteLine("Error: one of key value pairs lead node is null"); return(Nil.getInstance()); } if (current_binding_node.isNull()) { more_key_val_pairs_to_bind = false; break; } if (current_binding_node.isPair()) { if (current_binding_node.getCar() == null || current_binding_node.getCar().isNull()) { Console.WriteLine("Error: in Let, one of key value pairs is either null or an empty list , nil."); return(Nil.getInstance()); } else if (!current_binding_node.getCar().isPair()) { Console.WriteLine("Error: in Let, one of bindings does not have cons format."); return(Nil.getInstance()); // go into binding association list } else if (current_binding_node.getCar().isPair()) { if (current_binding_node.getCar().getCar() == null) { Console.WriteLine("Error: in Let, one of key/symbol fields is null."); return(Nil.getInstance()); } // check if this key is actually an identifier. else if (current_binding_node.getCar().getCar().isSymbol()) { current_env_of_let.define(current_binding_node.getCar().getCar(), current_fringe_of_list_of_values.getCar()); current_fringe_of_list_of_values = current_fringe_of_list_of_values.getCdr(); current_binding_node = current_binding_node.getCdr(); } else { Console.WriteLine("Error: in Let, one of keys is not an identifier."); return(Nil.getInstance()); } } } else { Console.WriteLine("Error: in Let, pair field outer group does not have cons format."); return(Nil.getInstance()); } } } // jump ahead to body function expression of let. Node current_locale_of_body = node1.getCdr().getCdr(); if (current_locale_of_body == null) { Console.WriteLine("Error: Let's body is Null"); return(Nil.getInstance()); } // then check if the nil at list end without having anything fulfilled. // also check to rule out there not being a child a cons node. else if (current_locale_of_body.isNull() || !current_locale_of_body.isPair()) { Console.WriteLine("Error: no arguments for evaluating in Begin statement ."); return(Nil.getInstance()); } // start loop that flips through elements until we get at the last destination expression. else { // initialize the item that may be returned. Node returnItem; // set a conditional and (on hold prospect) return element. if (current_locale_of_body.getCar() == null) { Console.WriteLine("Error: one of expressions in begin's arguments null ."); return(Nil.getInstance()); } else { returnItem = current_locale_of_body.getCar().eval(current_env_of_let); } bool hasAdditionalExp = false; Node one_further_outExtending_tail = current_locale_of_body.getCdr(); // set one item extra in store of members of set of further tail items... // if it is something to start a third part in a chain of further tail cycle. // & nil term test if (one_further_outExtending_tail != null && !one_further_outExtending_tail.isNull()) { if (!one_further_outExtending_tail.isPair()) { Console.WriteLine("Error: one of tail expressions is not in correct pair procession ."); return(Nil.getInstance()); } else if (one_further_outExtending_tail.getCar() == null) { Console.WriteLine("Error: one of expressions in begin's arguments null ."); return(Nil.getInstance()); } else { // set a conditional and (on hold prospect) return element. returnItem = one_further_outExtending_tail.getCar().eval(current_env_of_let); hasAdditionalExp = true; } } // terminates with current return item. // because cant go further in chain for begin expression chain else if (one_further_outExtending_tail != null && one_further_outExtending_tail.isNull()) { hasAdditionalExp = false; // end return(returnItem); } else // ends here with error { Console.WriteLine("Error: Null encountered further on in Begin's expressions."); return(Nil.getInstance()); } // loops over each expression leading up to last. while (hasAdditionalExp) { // set end now. if (one_further_outExtending_tail.getCdr() != null && one_further_outExtending_tail.getCdr().isNull()) { //end hasAdditionalExp = false; } // go to next in sequence of cdr's else if (one_further_outExtending_tail.getCdr() != null && !one_further_outExtending_tail.getCdr().isNull()) { if (!one_further_outExtending_tail.getCdr().isPair()) { Console.WriteLine("Error: one of expressions is not in correct pair procession ."); return(Nil.getInstance()); } else if (one_further_outExtending_tail.getCdr().getCar() == null) { Console.WriteLine("Error: one of expressions in begin's arguments null ."); return(Nil.getInstance()); } else { // set a conditional and (on hold prospect) return element. returnItem = one_further_outExtending_tail.getCdr().getCar().eval(current_env_of_let); hasAdditionalExp = true; // increment to next in sequence of cdr's one_further_outExtending_tail = one_further_outExtending_tail.getCdr(); } } else // ends here with error { Console.WriteLine("Error: Null encountered further on in Begin's expressions."); return(Nil.getInstance()); } } // while loop ended return(returnItem); } }