/* * Copyright (c) 1999-2003, Gene Cooperman; Rights to copy and distribute * for non-commercial purposes only are freely granted, but only as * long as this copyright statement remains. No warranty is implied. */ import java.util.ArrayList; class SchemeArrayList extends ArrayList { public SchemeObject getObj(int i) { return (SchemeObject)get(i); } public SchemeList toSchemeList() { SchemeList list = Symbol.schemeNil; for (int i = this.size() - 1; i >= 0; i--) list = new Cons( this.getObj(i), list ); return list; } } abstract class SchemeFunction extends AbstractSchemeObject { SchemeFunction(String name, int numArgs) { this.name = name; this.numArgs = numArgs; } // The value of a function is the function. public SchemeObject eval() { return this; } final public String toString() { return name; } // If Java allowed it, this would be: abstract String name; String name = ""; int numArgs = -2; // Should never be used until changed. SchemeArrayList processArgs ( SchemeList args ) { SchemeArrayList argsArray = new SchemeArrayList(); while ( args != Symbol.schemeNil ) { argsArray.add( args.car() ); args = (SchemeList)args.cdr(); } if ( argsArray.size() != this.numArgs && this.numArgs != -1 ) throw new SchemeWrongNumberOfArgs( this, args, argsArray.size(), this.numArgs ); return argsArray; } // Will eval, or not, depending on if ordinary or special function abstract void evalArgs( SchemeArrayList argsArray ); SchemeObject callFunction(SchemeList args) { SchemeArrayList argsArr = this.processArgs( args ); evalArgs( argsArr ); switch( this.numArgs ) { case -1 : return function( (SchemeObject)argsArr.toSchemeList() ); case 0 : return function( ); case 1 : return function( argsArr.getObj(0) ); case 2 : return function( argsArr.getObj(0), argsArr.getObj(1) ); case 3 : return function( argsArr.getObj(0), argsArr.getObj(1), argsArr.getObj(2) ); case 4 : return function( argsArr.getObj(0), argsArr.getObj(1), argsArr.getObj(2), argsArr.getObj(3) ); default: throw new SchemeError("too many arguments"); } } SchemeObject function (SchemeList x1) { throw new Error("internal error"); } SchemeObject function () { throw new Error("internal error"); } SchemeObject function (SchemeObject x1) { throw new Error("internal error"); } SchemeObject function (SchemeObject x1, SchemeObject x2) { throw new Error("internal error"); } SchemeObject function (SchemeObject x1, SchemeObject x2, SchemeObject x3) { throw new Error("internal error"); } SchemeObject function (SchemeObject x1, SchemeObject x2, SchemeObject x3, SchemeObject x4) { throw new Error("internal error"); } static void initBuiltInFunctions () { Add.install(); SetBang.install(); Define.install(); Quote.install(); Eval.install(); Print.install(); Exit.install(); Lambda.install(); //LambdaFnc.install(); //LambdaBegin.install(); Eq.install(); Begin.install(); GreaterNumber.install(); Car.install(); Cdr.install(); /* SchemeReader sr = new SchemeReader( new StringReader("(set! lambda lambdaBegin)") ); System.out.println( sr.nextExpression().eval() ); ReadString.function("(set! lambda lambdaBegin)"); */ EqualNumber.install(); // Scheme function: = If.install(); } } abstract class OrdinaryFunction extends SchemeFunction { OrdinaryFunction(String name, int numArgs) { super( name, numArgs ); } // A built-in function must evaluate its arguments. void evalArgs ( SchemeArrayList argsArray ) { for (int i = 0; i < argsArray.size(); i++) argsArray.set( i, argsArray.getObj(i).eval() ); } } abstract class BuiltInFunction extends OrdinaryFunction { BuiltInFunction(String name, int numArgs) { super( name, numArgs ); SchemeInterpreter.obArray.add( new Symbol( this ) ); } } abstract class SpecialFunction extends SchemeFunction { SpecialFunction(String name, int numArgs) { super( name, numArgs ); SchemeInterpreter.obArray.add( new Symbol( this ) ); } // A special function does not-evaluate its arguments. void evalArgs ( SchemeArrayList argsArray ) { } } class SchemeWrongNumberOfArgs extends SchemeError { SchemeWrongNumberOfArgs() { super(); } SchemeWrongNumberOfArgs(int actualNumArgs, int formalNumArgs) { super("\n called with " + actualNumArgs + " arg, but " + formalNumArgs + " args required."); } SchemeWrongNumberOfArgs(SchemeFunction fnc, SchemeList args, int actualNumArgs, int formalNumArgs) { super("\n Function " + fnc.toString() + " called with " + actualNumArgs + " arg, but " + formalNumArgs + " args required."); } }