// 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 static int Main(string[] args) { // Create scanner that reads from standard input Scanner scanner = new Scanner(Console.In); if (args.Length > 1 || (args.Length == 1 && ! args[0].Equals("-d"))) { Console.Error.WriteLine("Usage: mono SPP [-d]"); return 1; } // If command line option -d is provided, debug the scanner. if (args.Length == 1 && args[0].Equals("-d")) { // Console.Write("Scheme 4101> "); Token tok = scanner.getNextToken(); while (tok != null) { TokenType tt = tok.getType(); Console.Write(tt); if (tt == TokenType.INT) Console.WriteLine(", intVal = " + tok.getIntVal()); else if (tt == TokenType.STRING) Console.WriteLine(", stringVal = " + tok.getStringVal()); else if (tt == TokenType.IDENT) Console.WriteLine(", name = " + tok.getName()); else Console.WriteLine(); // Console.Write("Scheme 4101> "); tok = scanner.getNextToken(); } return 0; } // Create parser TreeBuilder builder = new TreeBuilder(); Parser parser = new Parser(scanner, builder); Node root = new Node(); // TODO: Create and populate the built-in environment and // create the top-level environment Tree.Environment env = new Tree.Environment(); Ident id = new Ident("b+"); env.define(id, new BuiltIn(id)); env = new Tree.Environment(env); Ident test = new Ident("xxxx"); IntLit test2 = new IntLit(3); env.define(test, test2); root = (Node) parser.parseExp(); while (root != null) { root.eval(env).print(0); root = (Node) parser.parseExp(); } // Read-eval-print loop // TODO: print prompt and evaluate the expression /* root = (Node) parser.parseExp(); while (root != null) { root.print(0); root = (Node) parser.parseExp(); } */ return 0; }
//Function for evaluating binary arithmetic operations private Node apply2(int arg1, int arg2) { string name = this.symbol.getName(); bool flag = name.Equals("b+"); Node result; if (flag) { result = new IntLit(arg1 + arg2); } else { bool flag2 = name.Equals("b-"); if (flag2) { result = new IntLit(arg1 - arg2); } else { bool flag3 = name.Equals("b*"); if (flag3) { result = new IntLit(arg1 * arg2); } else { bool flag4 = name.Equals("b/"); if (flag4) { result = new IntLit(arg1 / arg2); } else { bool flag5 = name.Equals("b="); if (flag5) { result = BoolLit.getInstance(arg1 == arg2); } else { bool flag6 = name.Equals("b<"); if (flag6) { result = BoolLit.getInstance(arg1 < arg2); } else { Console.Error.WriteLine("Error: unknown built-in function"); result = Nil.getInstance(); } } } } } } return result; }
// 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()); } }