private Node evalArithmetic(int arg1, int arg2) { string name = symbol.getName(); if (name.Equals("b+")) { return(new IntLit(arg1 + arg2)); } if (name.Equals("b-")) { return(new IntLit(arg1 - arg2)); } if (name.Equals("b*")) { return(new IntLit(arg1 * arg2)); } if (name.Equals("b/")) { return(new IntLit(arg1 / arg2)); } if (name.Equals("b=")) { return(BoolLit.getInstance(arg1 == arg2)); } if (name.Equals("b<")) { return(BoolLit.getInstance(arg1 < arg2)); } Console.Error.WriteLine("Error: unknown arithmetic symbol"); return(Nil.getInstance()); }
//syntax: if <test> <consequent> <alternate> //syntax: if <test> <consequent> public override Node eval(Node exp, Environment env) { var length = Node.length(exp); if (length < 3 || length > 4) { Console.Error.WriteLine("Error: Invalid length for if expression"); return(Nil.getInstance()); } var test = exp.getCdr().getCar(); var consequent = exp.getCdr().getCdr().getCar(); var alternate = new Node(); if (length == 4) //has alternates { alternate = exp.getCdr().getCdr().getCdr().getCar(); } else //If <test> yields a false value and no <alternate> is specified, then the result of the expression is unspecified. { alternate = Unspecific.getInstance(); } if (test.eval(env) != BoolLit.getInstance(false)) { return(consequent.eval(env)); } return(alternate.eval(env)); }
private Node BinArith(int arg1, int arg2, string s) { switch (s) { case "+": return(new IntLit(arg1 + arg2)); case "-": return(new IntLit(arg1 - arg2)); case "*": return(new IntLit(arg1 * arg2)); case "/": return(new IntLit(arg1 / arg2)); case "=": return(BoolLit.getInstance(arg1 == arg2)); case "<": return(BoolLit.getInstance(arg1 < arg2)); case ">": return(BoolLit.getInstance(arg1 > arg2)); default: return(null); } }
// to evaluate expressions of the form '(if b t e)', // evaluate b, then if b is not the boolean constant #f, // evaluate t and return the result. otherwise, evaluate // e and return the result. public override Node eval(Node t, Environment env) { // if cdr is nil, return nil (error state) if (t.getCdr() == Nil.getInstance()) { Console.Error.WriteLine("Special form 'If' evaluated with no arguments"); return(Nil.getInstance()); } // get cdr of expression (conditional and execution statements) t = t.getCdr(); // if cdr of t is nil, expression has a conditional but no executable statements (error state) if (t.getCdr() == Nil.getInstance()) { Console.Error.WriteLine("Special form 'If' evaluated with insufficient arguments"); return(Nil.getInstance()); } // evaluate car of b (conditional). if b is not #f, evaluate and return t. if (t.getCar().eval(env) != BoolLit.getInstance(false)) { return(t.getCdr().getCar().eval(env)); } else { // otherwise, b is #f. evaluate and return e. // if e is nil, statement is still valid. interpreter will parse and return nil. return(t.getCdr().getCdr().getCar().eval(env)); } }
private Node apply2(Node arg1, Node arg2) { string name = symbol.getName(); if (name.Equals("eq?")) { if (arg1.isSymbol() && arg2.isSymbol()) { return(BoolLit.getInstance(arg1.getName().Equals(arg2.getName()))); } return(BoolLit.getInstance(arg1 == arg2)); } if (name.Equals("cons")) { return(new Cons(arg1, arg2)); } if (name.Equals("set-car!")) { arg1.setCar(arg2); return(Unspecific.getInstance()); } if (name.Equals("set-cdr!")) { arg1.setCdr(arg2); return(Unspecific.getInstance()); } if (name.Equals("eval")) { if (arg2.isEnvironment()) { Environment envArg1 = (Environment)arg1; return(arg1.eval(envArg1)); } Console.Error.WriteLine("Error: argument is not an environment"); return(Nil.getInstance()); } if (name.Equals("apply")) { return(arg1.apply(arg2)); } if (name[0].Equals('b') && name.Length == 2) { if (arg1.isNumber() && arg2.isNumber()) { return(evalArithmetic(arg1.getIntVal(), arg2.getIntVal())); } Console.Error.WriteLine("Error: invalid arguments"); return(Nil.getInstance()); } Console.Error.WriteLine("Error: wrong number of arguments"); return(Nil.getInstance()); }
private Node evalClauses(Node exp, Environment env) { if (exp.isNull()) { return(Unspecific.getInstance()); } var clause = exp.getCar(); if (Node.length(clause) <= 0) { Console.Error.WriteLine("Error: invalid cond expression"); return(Nil.getInstance()); } var testExp = clause.getCar(); var expression = clause.getCdr(); if (testExp.isSymbol() && testExp.getName().Equals("else")) { if (!expression.isNull() && exp.getCdr().isNull()) { return(evalExp(expression, env)); } Console.Error.WriteLine("Error: invalid expression"); return((Node)Nil.getInstance()); } var testValid = testExp.eval(env); if (testValid == BoolLit.getInstance(false)) { var nextExps = exp.getCdr(); return(evalClauses(nextExps, env)); } if (expression.isNull()) { return(BoolLit.getInstance(true)); } var exp1 = expression.getCar(); if (!exp1.isSymbol() || !exp1.getName().Equals("=>")) { return(evalExp(expression, env)); } if (Node.length(expression) != 2) { Console.Error.WriteLine("Error: invalid cond expression"); return(Nil.getInstance()); } var cdr = expression.getCdr().getCar(); return(cdr.eval(env).apply(BoolLit.getInstance(true))); }
public override Node eval(Node t, Environment env) { Node test = t.getCdr().getCar(); Node consq = t.getCdr().getCdr(); Node alt = consq.getCdr(); if (test.eval(env) == BoolLit.getInstance(true)) { return(consq.getCar().eval(env)); } else if (!(alt is Nil)) { return(alt.getCar().eval(env)); } Console.Error.WriteLine("Error: If not properly formatted"); return(Nil.getInstance()); }
private Node apply1(Node arg1) { string name = symbol.getName(); if (name.Equals("car")) { return(arg1.getCar()); } if (name.Equals("cdr")) { return(arg1.getCdr()); } if (name.Equals("number?")) { return(BoolLit.getInstance(arg1.isNumber())); } if (name.Equals("symbol?")) { return(BoolLit.getInstance(arg1.isSymbol())); } if (name.Equals("null?")) { return(BoolLit.getInstance(arg1.isNull())); } if (name.Equals("pair?")) { return(BoolLit.getInstance(arg1.isPair())); } if (name.Equals("procedure?")) { return(BoolLit.getInstance(arg1.isProcedure())); } if (name.Equals("write")) { arg1.print(-1); return(Unspecific.getInstance()); } if (name.Equals("display")) { Console.Write(arg1); return(Unspecific.getInstance()); } Console.Error.WriteLine("Error: wrong number of arguments"); return(Nil.getInstance()); }
public override Node eval(Node t, Environment env) { while (!(t.getCdr() is Nil)) { t = t.getCdr(); if (!(t.getCar() is Cons)) { Console.Error.WriteLine("Error: unexpected argument"); } Node n = t.getCar().getCar().eval(env); if (t.getCar().getCar().eval(env).Equals(BoolLit.getInstance(true))) { t = t.getCar(); return(t.getCdr().getCar().eval(env)); } } // get else to work...? 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(); } Node cnd; Node thn; Node els; if (numArgs < 2 || numArgs > 3) { Console.Error.WriteLine("Error: invalid expression"); return(Nil.getInstance()); } else { cnd = exp.getCdr().getCar(); thn = exp.getCdr().getCdr().getCar(); if (numArgs == 3) { els = exp.getCdr().getCdr().getCdr().getCar(); } else { els = new StringLit("#{Unspecific}", false); } } if (cnd.eval(env) != BoolLit.getInstance(false)) { return(thn.eval(env)); } return(els.eval(env)); }
public override Node eval(Environment env, Node args) { Node result = BoolLit.getInstance(false), test, cases = args; // Iterate through each case test until it evaluates to true or we hit the end do { cases = cases.getCdr(); test = cases.getCar().getCar(); if (test.getName() == "else") { break; } result = test.eval(env); } while (cases.getCdr().isNull() == false && result == BoolLit.getInstance(false)); // if a expr value returned true or we hit an else clause if (result != BoolLit.getInstance(false) || test.getName() == "else") { // If there was a test with no other expressions, apply the test if (cases.getCar().getCdr().isNull() == true) { return(args.getCar().eval(env).apply(result)); } // Otherwise apply the following expressions else { Node debug = cases.getCar().getCdr(), debug2 = args.getCar(); return(args.getCar().eval(env).apply(cases.getCar().getCdr().eval(env))); } } else { return(new StringLit("#unspecified")); } }
// 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) { Node result = null; int numArgs = numArguments(args); switch (symbol.getName()) { case "begin": // The value(s) of the last expression is(are) returned while (args.getCdr().isNull() == false) { args = args.getCdr(); } return(args.getCar()); case "cond": // The value(s) of the last expression is(are) returned while (args.getCdr().isNull() == false) { args = args.getCdr(); } return(args.getCar()); case "if": if (args.getCar() == BoolLit.getInstance(true)) { return(args.getCdr().getCar()); } else if (args.getCdr().getCdr().isPair()) { return(args.getCdr().getCdr().getCar()); } else { return(new StringLit("#unspecified")); } case "let": // The value(s) of the last expression is(are) returned while (args.getCdr().isNull() == false) { args = args.getCdr(); } return(args.getCar()); case "quote": return(args.getCdr().getCar()); case "read": return((Node)args.parser.parseExp()); case "write": args.print(0); // Not sure what Node to return here. Probably just return the blank Node break; case "symbol?": // symbol? only accepts 1 argument if (numArgs != 1) { return(new StringLit("Error: wrong number of arguments for 'symbol?'")); } else { if (args.getCar().isSymbol()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } case "number?": // number? only accepts 1 argument if (numArgs != 1) { return(new StringLit("Error: wrong number of arguments for 'number?'")); } else { if (args.getCar().isNumber()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } } case "car": if (args.isPair() == false) { return(new StringLit("Error: Argument to 'car' is not a pair.")); } else { return(args.getCar()); } case "cdr": if (args.isPair() == false) { return(new StringLit("Error: Argument to 'cdr' is not a pair.")); } else { return(args.getCdr()); } case "cons": // make sure only two arguments are provided if (args.getCdr().isPair() != true && args.getCdr().getCdr().isNull() == false) { return(new StringLit("Error: Function 'cons' requires two arguments.")); } else { return(args); } case "set-car!": // make sure only a list and value are provided if (args.getCar().isPair() == false || args.getCdr().getCar().isPair() == true || args.getCdr().getCdr().isNull() == false) { return(new StringLit("Error: Function 'set-car!' requires a list and value")); } else { args.getCar().setCar(args.getCdr().getCar()); return(new StringLit("no values returned;")); } case "set-cdr!": // make sure only a list and value are provided if (args.getCar().isPair() == false || args.getCdr().getCar().isPair() == true || args.getCdr().getCdr().isNull() == false) { return(new StringLit("Error: Function 'set-cdr!' requires a list and value")); } else { args.getCar().setCdr(args.getCdr().getCar()); return(new StringLit("no values returned;")); } case "null?": if (args.getCar().isNull() == true) { return(BoolLit.getInstance(true)); } // null? only accepts one argument else if (args.getCdr().isPair() == true) { return(new StringLit("Error: 'null?' only accept one argument.")); } else { return(BoolLit.getInstance(false)); } case "pair?": // pair? only accept one argument if (args.getCdr().isPair() == true) { return(new StringLit("Error: 'pair?' only accepts one argument.")); } else if (args.getCar().isPair()) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } case "eq?": // eq? only accepts two arguments if (args.getCdr().getCdr().isNull() == false) { return(new StringLit("Error: 'eq?' only accepts one argument")); } else if (args.getCar() == args.getCdr().getCar()) // Not sure if this is going to work, actually { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } case "procedure?": //procedure only accepts 1 argument (I think) if (args.getCdr().isNull() == false) { return(new StringLit("Error: 'procedure?' only accepts one argument")); } else if (args.getCar().isProcedure() == true) { return(BoolLit.getInstance(true)); } else { return(BoolLit.getInstance(false)); } default: break; } // Now we check for the binary arithmetic builtins IntLit num1 = new IntLit(0), num2; if (symbol.getName() == "b/") // The division function has 1 as the default value instead of 0 when only 1 argument is provided { num1 = new IntLit(1); } // If the arguments aren't numerical, the IntLit casts will fail and the catch block executes. // If there are 0 arguments the first cast will fail, and if there are more than 2 an Exception is thrown try { num2 = (IntLit)args.getCar(); // Check for a second argument if (args.getCdr().isPair() == true) { // We do this swap because if we have only 1 argument, we're doing 0 - num2. If we have 2, we're doing num1-num2. num1 = num2; num2 = (IntLit)args.getCdr().getCar(); if (args.getCdr().getCdr().isNull() == false) { throw new Exception(); } } else if (symbol.getName() == "b=" || symbol.getName() == "b<") { return(result = new StringLit("Error: binary arithmetic operation '" + symbol.getName() + "' expects two numerical 2 arguments.")); } } catch { return(result = new StringLit("Error: binary arithmetic operations expect 1 or 2 numerical arguments.")); } if (symbol.getName() == "b+") { result = new IntLit(num1.getInt() + num2.getInt()); } else if (symbol.getName() == "b-") { result = new IntLit(num1.getInt() - num2.getInt()); } else if (symbol.getName() == "b*") { result = new IntLit(num1.getInt() * num2.getInt()); } else if (symbol.getName() == "b/") { if (num2.getInt() == 0) { return(result = new StringLit("Error: Dividing by 0.")); } result = new IntLit(num1.getInt() / num2.getInt()); } else if (symbol.getName() == "b=") { if (num1.getInt() == num2.getInt()) { result = BoolLit.getInstance(true); } else { result = BoolLit.getInstance(false); } } else if (symbol.getName() == "b<") { if (num1.getInt() < num2.getInt()) { result = BoolLit.getInstance(true); } else { result = BoolLit.getInstance(false); } } return(result); }
public override Node eval(Environment env, Node args = null) { return(BoolLit.getInstance(boolVal)); }
public INode buildBoolLit(bool b) { return(BoolLit.getInstance(b)); }
// TODO: The method apply() should be defined in class Node // to report an error. It should be overridden only in classes // BuiltIn and Closure. Probably will have to include calls to eval public override Node apply(Node args) { if (args == null) { return(null); } String Symbol = symbol.getName(); Node arg1 = args.getCar(), arg2 = args.getCdr().getCar(); switch (Symbol) { case "symbol?": return(BoolLit.getInstance(arg1.isSymbol())); case "number?": return(BoolLit.getInstance(arg1.isNumber())); case "b+": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), "+")); case "b-": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), "-")); case "b*": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), "*")); case "b/": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), "/")); case "b=": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), "=")); case "b>": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), ">")); case "b<": return(BinArith(((IntLit)arg1).getValue(), ((IntLit)arg2).getValue(), "<")); case "car": if (arg1.isNull()) { return(arg1); //arg1==nil or null? } else { return(arg1.getCar()); } case "cdr": // ???????????????? if (arg1.isNull()) { return(arg1); //arg1==nil or null? } else { return(arg1.getCdr()); } case "cons": return(new Cons(arg1, arg2)); case "set-car!": arg1.setCar(arg2); return(arg1); case "set-cdr!": arg1.setCdr(arg2); return(arg1); case "null?": return(BoolLit.getInstance(arg1.isNull())); case "pair?": return(BoolLit.getInstance(arg1.isPair())); case "eq?": return(BoolLit.getInstance(arg1 == arg2)); case "procedure?": return(BoolLit.getInstance(arg1.isProcedure())); case "read": //call parser and returns parse tree Parser parse = new Parser(new Scanner(Console.In), new TreeBuilder()); return((Node)parse.parseExp()); case "write": return(new StringLit("Cha{" + arg1.ToString() + "/*WRITE*\\}")); case "display": return(new StringLit("Cha{" + arg1.ToString() + "/*DISPLAY*\\}")); //not truly implemented, placeholder code I tink case "newline": //\n? return(new StringLit("\n")); case "eval": return(arg1.eval(new Environment())); case "apply": return(arg1.apply(arg2)); case "interaction-environment": //args.env //do //{ // //TODO // env = new Environment(); //} while (env != null); return(new Environment()); } return(null); }
// check if null/end of last clause: // return unspecific // check if else clause: // yes: eval exps and return value of last exp // check if clause has exp // if no exp: return value of test // if test failed: go to next clause // check alt or normal form // eval expression(s) appropriately private Node evalConds(Node clauses, Environment env) { // if end of clauses and nothing has been returned, return unspecific if (clauses.isNull()) { return(new StringLit("#{Unspecific}", false)); } Node cnd = clauses.getCar(); // make sure clause isnt empty if (cnd.isNull()) { Console.Error.WriteLine("Error: invalid expression"); return(Nil.getInstance()); } Node test = cnd.getCar(); Node exprs = cnd.getCdr(); Node expr; if (test.isSymbol() && test.getName().Equals("else")) { //erorr if no expression or else is not last clause if (exprs.isNull() || !clauses.getCdr().isNull()) { Console.Error.WriteLine("Error: invalid expression"); return(Nil.getInstance()); } else { // evaluate each expr in exprs then return the last one Node car = Nil.getInstance(); while (!exprs.isNull()) { expr = exprs.getCar(); car = expr.eval(env); if (expr.isPair()) { Node cdr = expr.getCdr(); while (!cdr.isNull()) { car = cdr.getCar().eval(env); cdr = cdr.getCdr(); } } exprs = exprs.getCdr(); } return(car); } } Node testEval = test.eval(env); // if clause is a test with no expressions if (exprs.isNull()) { return(testEval); } // if test failed go to next clause if (testEval == BoolLit.getInstance(false)) { return(evalConds(clauses.getCdr(), env)); } // if alternate form if (exprs.getCar().getName().Equals("=>")) { return(exprs.getCdr().getCar().eval(env).apply(testEval)); } //normal form: iterate exprs, evaluate each expr, then return last expr else { Node car = Nil.getInstance(); while (!exprs.isNull()) { expr = exprs.getCar(); car = expr.eval(env); if (expr.isPair()) { Node cdr = expr.getCdr(); while (!cdr.isNull()) { car = cdr.getCar().eval(env); cdr = cdr.getCdr(); } } exprs = exprs.getCdr(); } return(car); } }
// DONE :: 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) { string name = symbol.getName(); int numArgs = 0; Node arg1; Node arg2; Node tempArgs = args; while (!tempArgs.isNull()) { numArgs++; tempArgs = tempArgs.getCdr(); } if (numArgs == 0) { if (name.Equals("read")) { Parser parser = new Parser(new Scanner(Console.In), new TreeBuilder()); Node exp = (Node)parser.parseExp(); if (!exp.isNull()) { return(exp); } return(new StringLit("End of file", false)); } else if (name.Equals("newline")) { Console.WriteLine(); return(new StringLit("#{Unspecific}", false)); } else if (name.Equals("interaction-environment")) { return(Scheme4101.env); } Console.Error.WriteLine("Error: invalid input"); return(Nil.getInstance()); } else if (numArgs == 1) { arg1 = args.getCar(); if (name.Equals("symbol?")) { return(BoolLit.getInstance(arg1.isSymbol())); } if (name.Equals("number?")) { return(BoolLit.getInstance(arg1.isNumber())); } if (name.Equals("car")) { return(arg1.getCar()); } if (name.Equals("cdr")) { return(arg1.getCdr()); } if (name.Equals("null?")) { return(BoolLit.getInstance(arg1.isNull())); } if (name.Equals("pair?")) { return(BoolLit.getInstance(arg1.isPair())); } if (name.Equals("procedure?")) { return(BoolLit.getInstance(arg1.isProcedure())); } if (name.Equals("write")) { arg1.print(0); return(new StringLit("#{Unspecific}", false)); } if (name.Equals("display")) { StringLit.printQuotes = false; arg1.print(0); StringLit.printQuotes = true; return(new StringLit("#{Unspecific}", false)); } Console.Error.WriteLine("Error: invalid input"); return(Nil.getInstance()); } else if (numArgs == 2) { arg1 = args.getCar(); arg2 = args.getCdr().getCar(); if (name.Equals("eq?")) { if (arg1.isSymbol() && arg2.isSymbol()) { return(BoolLit.getInstance(arg1.getName().Equals(arg2.getName()))); } return(BoolLit.getInstance(arg1 == arg2)); } if (name.Equals("cons")) { return(new Cons(arg1, arg2)); } if (name.Equals("set-car!")) { arg1.setCar(arg2); return(new StringLit("#{Unspecific}", false)); } if (name.Equals("set-cdr!")) { arg1.setCdr(arg2); return(new StringLit("#{Unspecific}", false)); } if (name.Equals("eval")) { return(arg1.eval((Environment)arg2)); } if (name.Equals("apply")) { return(arg1.apply(arg2)); } int int1; int int2; if (arg1.isNumber() && arg2.isNumber()) { int1 = arg1.getValue(); int2 = arg2.getValue(); } else { Console.Error.WriteLine("Error: invalid argument types"); return(Nil.getInstance()); } if (name.Equals("b+")) { if (arg1.isNumber() && arg2.isNumber()) { return(new IntLit(int1 + int2)); } } if (name.Equals("b-")) { return(new IntLit(int1 - int2)); } if (name.Equals("b*")) { return(new IntLit(int1 * int2)); } if (name.Equals("b/")) { return(new IntLit(int1 / int2)); } if (name.Equals("b=")) { return(BoolLit.getInstance(int1 == int2)); } if (name.Equals("b<")) { return(BoolLit.getInstance(int1 < int2)); } Console.Error.WriteLine("Error: invalid function"); return(Nil.getInstance()); } else { Console.Error.WriteLine("Error: wrong number of args"); return(Nil.getInstance()); } }
// to evaluate expressions of the form '(cond (b1 ...) ... (bn ...))', // evaluate b1 through bn until a condition not equal to #f is found. // if this case is of the form '(bi)', return bi. // if this case is of the form '(bi e1 ... en)', evaluate e1-en and return // the result of evaluating en public override Node eval(Node t, Environment env) { // if cond expression has no cdr, invalid syntax (error state) if (t.getCdr() == Nil.getInstance()) { Console.Error.WriteLine("Special form 'cond' evaluated with no arguments"); return(Nil.getInstance()); } // get cdr of expression t = t.getCdr(); // while cond statement has a cdr and its car (bi) evaluates to #f, keep moving down the tree while (t.getCdr() != Nil.getInstance() && t.getCar().getCar().eval(env) == BoolLit.getInstance(false)) { t = t.getCdr(); } // once a condition is found that is not #f or end of statement, // get car of t to evaluate t = t.getCar(); // if cdr of t is null, statement is of form '(bi)', so return bi if (t.getCdr().eval(env) == Nil.getInstance()) { return(t.getCar()); } // otherwise, statement is of form (bi e1 ... en) // evaluate e1 through en, then return the result of evaluating en // first evaluate e1 through e(n-1) while (t.getCdr() != Nil.getInstance()) { t.getCdr().getCar().eval(env); t = t.getCdr(); } // finally evaluate and return en return(t.getCar().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) { // return new StringLit("Error: BuiltIn.apply not yet implemented"); Node arg1 = Nil.getInstance(); String symName = symbol.getName(); if (symName.Equals("interaction-environment")) { return(global); } if (symName.Equals("newline")) { Console.WriteLine(); return(Void.getInstance()); } if (!(args.getCar() is Nil)) { arg1 = args.getCar(); } Node arg2 = Nil.getInstance(); if (!args.getCdr().isNull()) { arg2 = args.getCdr().getCar(); } if (symName.Equals("symbol?")) { return(BoolLit.getInstance(arg1.isSymbol())); } if (symName.Equals("number?")) { return(BoolLit.getInstance(arg1.isNumber())); } if (symName.Equals("b+")) { if (arg1.isNumber() & arg2.isNumber()) { return(new IntLit(arg1.getVal() + arg2.getVal())); } } if (symName.Equals("b-")) { if (arg1.isNumber() & arg2.isNumber()) { return(new IntLit(arg1.getVal() - arg2.getVal())); } } if (symName.Equals("b*")) { if (arg1.isNumber() & arg2.isNumber()) { return(new IntLit(arg1.getVal() * arg2.getVal())); } } if (symName.Equals("b/")) { if (arg1.isNumber() & arg2.isNumber()) { return(new IntLit(arg1.getVal() / arg2.getVal())); } } if (symName.Equals("b=")) { if (arg1.isNumber() & arg2.isNumber()) { return(BoolLit.getInstance(arg1.getVal() == arg2.getVal())); } } if (symName.Equals("b<")) { if (arg1.isNumber() & arg2.isNumber()) { return(BoolLit.getInstance(arg1.getVal() < arg2.getVal())); } } if (symName.Equals("b>")) { if (arg1.isNumber() & arg2.isNumber()) { return(BoolLit.getInstance(arg1.getVal() > arg2.getVal())); } } if (symName.Equals("b>=")) { if (arg1.isNumber() & arg2.isNumber()) { return(BoolLit.getInstance(arg1.getVal() >= arg2.getVal())); } } if (symName.Equals("b<=")) { if (arg1.isNumber() & arg2.isNumber()) { return(BoolLit.getInstance(arg1.getVal() <= arg2.getVal())); } } if (symName.Equals("car")) { return(arg1.getCar()); } if (symName.Equals("cdr")) { return(arg1.getCdr()); } if (symName.Equals("set-car!")) { arg1.setCar(arg2); return(Void.getInstance()); } if (symName.Equals("set-cdr!")) { arg1.setCdr(arg2); return(Void.getInstance()); } if (symName.Equals("null?")) { return(BoolLit.getInstance(arg1.isNull())); } if (symName.Equals("pair?")) { return(BoolLit.getInstance(arg1.isPair())); } if (symName.Equals("eq?")) { if (arg1.isSymbol() && arg2.isSymbol()) { return(BoolLit.getInstance(arg1.getName().Equals(arg2.getName()))); } return(BoolLit.getInstance(arg1 == arg2)); } if (symName.Equals("procedure?")) { return(BoolLit.getInstance(arg1.isProcedure())); } if (symName.Equals("read")) { Scanner scanner = new Scanner(Console.In); TreeBuilder builder = new TreeBuilder(); Parser parser = new Parser(scanner, builder); Node root = (Node)parser.parseExp(); return(Void.getInstance()); } if (symName.Equals("write")) { arg1.print(0); return(Void.getInstance()); } if (symName.Equals("display")) { ((StringLit)arg1).displayPrint(); return(Void.getInstance()); } if (symName.Equals("eval")) { return(arg1.eval((Environment)arg2)); } if (symName.Equals("apply")) { return(arg1.apply(arg2)); } return(Void.getInstance()); }
public override Node apply(Node args) { //set initial values string argsName = symbol.getName(); int argsAmount = 0; //initialize Node firstArgs = null; bool b1 = false; Node secondArgs = null; bool b2 = false; //setup initial Args while (!args.isNull()) { argsAmount = argsAmount + 1; if (argsAmount == 1) { firstArgs = args.getCar(); b1 = true; } if (argsAmount == 2) { secondArgs = args.getCar(); b2 = true; } args = args.getCdr(); } //start apply based on amount or arguements and type of arguement //switch statement possibly if (argsAmount == 0) { // read if (argsName.Equals("read")) { Scanner s = new Scanner(Console.In); TreeBuilder tb = new TreeBuilder(); Parser p = new Parser(s, tb); Node n = (Node)p.parseExp(); if (n != null) { return(n); } } //newline else if (argsName.Equals("newline")) { Console.WriteLine(); //check value upspecified return(new StringLit(" ")); } //i-e else if (argsName.Equals("interaction-environment")) { return(Scheme4101.env); } //invalid argsName given else { Console.Error.WriteLine("invalid arguemtent name given"); return(Nil.getInstance()); } } else if (argsAmount == 1) { //symbol? if (argsName.Equals("symbol?")) { bool b = firstArgs.isSymbol(); return(BoolLit.getInstance(b)); } //number? else if (argsName.Equals("number?")) { bool b = firstArgs.isNumber(); return(BoolLit.getInstance(b)); } //car else if (argsName.Equals("car")) { return(firstArgs.getCar()); } //cdr else if (argsName.Equals("cdr")) { return(firstArgs.getCdr()); } //null? //b1? else if (argsName.Equals("null?") && b1) { bool b = firstArgs.isNull(); return(BoolLit.getInstance(b)); } //pair else if (argsName.Equals("pair?")) { bool b = firstArgs.isPair(); return(BoolLit.getInstance(b)); } //precedure else if (argsName.Equals("procedure?")) { bool b = firstArgs.isProcedure(); return(BoolLit.getInstance(b)); } //write else if (argsName.Equals("write")) { firstArgs.print(0); //return value unspecified return(new StringLit(" ")); } //display else if (argsName.Equals("display")) { //temp change value StringLit.quoted = false; firstArgs.print(0); //reset changed value StringLit.quoted = true; //return value unspecified return(new StringLit(" ")); } } else if (argsAmount == 2) { //eq? if (argsName.Equals("eq?")) { bool bt1 = firstArgs.isSymbol(); bool bt2 = secondArgs.isSymbol(); if (bt1 && bt2) { bool bt3 = firstArgs.getName().Equals(secondArgs.getName()); return(BoolLit.getInstance(bt3)); } else { bool bt4 = firstArgs == secondArgs; return(BoolLit.getInstance(bt4)); } } //cons else if (argsName.Equals("cons")) { return(new Cons(firstArgs, secondArgs)); } //set-car! else if (argsName.Equals("set-car!")) { firstArgs.setCar(secondArgs); //return value unspecified return(new StringLit(" ")); } //set-cdr! else if (argsName.Equals("set-cdr!")) { firstArgs.setCdr(secondArgs); //return value unspecified return(new StringLit(" ")); } //eval else if (argsName.Equals("eval")) { return(firstArgs.eval((Environment)secondArgs)); } //apply else if (argsName.Equals("apply")) { return(firstArgs.apply(secondArgs)); } else { return(Nil.getInstance()); } //binary arithematic opecations tmp vars int bo1 = 0; int bo2 = 0; if (firstArgs.isNumber()) { bo1 = firstArgs.getValue(); } else if (secondArgs.isNumber()) { bo2 = secondArgs.getValue(); } else { Console.Error.WriteLine("invalid arguemtent name given"); return(Nil.getInstance()); } //b+ if (argsName.Equals("b+")) { return(new IntLit(bo1 + bo2)); } //b- else if (argsName.Equals("b-")) { return(new IntLit(bo1 - bo2)); } //b* else if (argsName.Equals("b*")) { return(new IntLit(bo1 * bo2)); } //b/ else if (argsName.Equals("b/")) { return(new IntLit(bo1 / bo2)); } //b= else if (argsName.Equals("b=")) { bool b = bo1 == bo2; return(BoolLit.getInstance(b)); } //b< else if (argsName.Equals("b<")) { bool b = bo1 < bo2; return(BoolLit.getInstance(b)); } else { Console.Error.WriteLine("Aritheatic Operation Error"); return(Nil.getInstance()); } } //invalid argsName given else { Console.Error.WriteLine("invalid arguemtent name given"); return(Nil.getInstance()); } return(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()); } }