Logo Search packages:      
Sourcecode: mathpiper version File versions  Download package

Utility.java

/* {{{ License.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */ //}}}
// :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:folding=explicit:collapseFolds=0:
package org.mathpiper.lisp;


import org.mathpiper.lisp.collections.OperatorMap;
import org.mathpiper.lisp.cons.ConsTraverser;
import org.mathpiper.lisp.cons.SublistCons;
import org.mathpiper.lisp.cons.AtomCons;
import org.mathpiper.lisp.cons.ConsPointer;
import org.mathpiper.lisp.cons.Cons;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.mathpiper.io.MathPiperInputStream;
import org.mathpiper.exceptions.EvaluationException;
import org.mathpiper.io.InputStatus;
import org.mathpiper.builtin.BigNumber;
import org.mathpiper.builtin.BuiltinFunction;
import org.mathpiper.io.InputDirectories;
import org.mathpiper.lisp.behaviours.Substitute;
import org.mathpiper.lisp.tokenizers.MathPiperTokenizer;
import org.mathpiper.lisp.userfunctions.MultipleArityUserFunction;
import org.mathpiper.lisp.printers.MathPiperPrinter;
import org.mathpiper.lisp.parsers.MathPiperParser;
import org.mathpiper.io.JarFileInputStream;
import org.mathpiper.io.StandardFileInputStream;
import org.mathpiper.io.StringOutputStream;
import org.mathpiper.lisp.behaviours.BackQuoteSubstitute;
import org.mathpiper.lisp.cons.NumberCons;
import org.mathpiper.lisp.parametermatchers.Pattern;
import org.mathpiper.lisp.parametermatchers.PatternParameter;
import org.mathpiper.lisp.userfunctions.Branch;
import org.mathpiper.lisp.userfunctions.FunctionParameter;
import org.mathpiper.lisp.userfunctions.MacroUserFunction;
import org.mathpiper.lisp.userfunctions.PatternBranch;
import org.mathpiper.lisp.userfunctions.SingleArityBranchingUserFunction;


public class Utility {

    public static final int ATOM = 1;
    public static final int NUMBER = 2;
    public static final int SUBLIST = 3;
    public static final int OBJECT = 4;
    static int log2_table_size = 32;    // A lookup table of Ln(n)/Ln(2) for n = 1 .. 32.
    // With this we don't have to use math.h if all we need is to convert the number of digits from one base to another. This is also faster.
    // Generated by: PrintList(N(Ln(1 .. 32)/Ln(2)), ",") at getPrecision 40.
    static double log2_table[] = {
        0.,
        1.,
        1.5849625007211561814537389439478165087598,
        2.,
        2.3219280948873623478703194294893901758648,
        2.5849625007211561814537389439478165087598,
        2.807354922057604107441969317231830808641,
        3.,
        3.1699250014423123629074778878956330175196,
        3.3219280948873623478703194294893901758648,
        3.4594316186372972561993630467257929587032,
        3.5849625007211561814537389439478165087598,
        3.7004397181410921603968126542566947336284,
        3.807354922057604107441969317231830808641,
        3.9068905956085185293240583734372066846246,
        4.,
        4.0874628412503394082540660108104043540112,
        4.1699250014423123629074778878956330175196,
        4.2479275134435854937935194229068344226935,
        4.3219280948873623478703194294893901758648,
        4.3923174227787602888957082611796473174008,
        4.4594316186372972561993630467257929587032,
        4.5235619560570128722941482441626688444988,
        4.5849625007211561814537389439478165087598,
        4.6438561897747246957406388589787803517296,
        4.7004397181410921603968126542566947336284,
        4.7548875021634685443612168318434495262794,
        4.807354922057604107441969317231830808641,
        4.8579809951275721207197733246279847624768,
        4.9068905956085185293240583734372066846246,
        4.9541963103868752088061235991755544235489,
        5.
    };
    public static java.util.zip.ZipFile zipFile = null;


    public static boolean isNumber(String ptr, boolean aAllowFloat) {

        if (ptr.length() == 0) {
            return false;
        }//end if.

        int pos = 0;
        if (ptr.charAt(pos) == '-' || ptr.charAt(pos) == '+') {
            pos++;
        }
        int nrDigits = 0;
        int index = 0;
        if (pos + index == ptr.length()) {
            return false;
        }
        while (ptr.charAt(pos + index) >= '0' && ptr.charAt(pos + index) <= '9') {
            nrDigits++;
            index++;
            if (pos + index == ptr.length()) {
                return true;
            }
        }
        if (ptr.charAt(pos + index) == '.') {
            if (!aAllowFloat) {
                return false;
            }
            index++;
            if (pos + index == ptr.length()) {
                return true;
            }
            while (ptr.charAt(pos + index) >= '0' && ptr.charAt(pos + index) <= '9') {
                nrDigits++;
                index++;
                if (pos + index == ptr.length()) {
                    return true;
                }
            }
        }
        if (nrDigits == 0) {
            return false;
        }
        if (ptr.charAt(pos + index) == 'e' || ptr.charAt(pos + index) == 'E') {
            if (!aAllowFloat) {
                return false;
            }
            if (!BigNumber.numericSupportForMantissa()) {
                return false;
            }
            index++;
            if (pos + index == ptr.length()) {
                return true;
            }
            if (ptr.charAt(pos + index) == '-' || ptr.charAt(pos + index) == '+') {
                index++;
            }
            while (ptr.charAt(pos + index) >= '0' && ptr.charAt(pos + index) <= '9') {
                index++;
                if (pos + index == ptr.length()) {
                    return true;
                }
            }
        }
        if (ptr.length() != (pos + index)) {
            return false;
        }
        return true;
    }


    public static int listLength(ConsPointer aOriginal) throws Exception {
        ConsPointer consTraverser = new ConsPointer(aOriginal.getCons());
        int length = 0;
        while (consTraverser.getCons() != null) {
            consTraverser.goNext();
            length++;
        }
        return length;
    }


    public static void reverseList(ConsPointer aResult, ConsPointer aOriginal) {
        //ConsPointer iter = new ConsPointer(aOriginal);
        ConsPointer iter = new ConsPointer();
        iter.setCons(aOriginal.getCons());
        ConsPointer previous = new ConsPointer();
        ConsPointer tail = new ConsPointer();
        tail.setCons(aOriginal.getCons());

        while (iter.getCons() != null) {
            tail.setCons(iter.cdr().getCons());
            iter.cdr().setCons(previous.getCons());
            previous.setCons(iter.getCons());
            iter.setCons(tail.getCons());
        }
        aResult.setCons(previous.getCons());
    }


    public static void returnUnEvaluated(ConsPointer aResult, ConsPointer aArguments, Environment aEnvironment) throws Exception {
        ConsPointer full = new ConsPointer();
        full.setCons(aArguments.getCons().copy(aEnvironment, false));
        aResult.setCons(SublistCons.getInstance(aEnvironment, full.getCons()));

        ConsTraverser consTraverser = new ConsTraverser(aArguments);
        consTraverser.goNext();

        while (consTraverser.getCons() != null) {
            ConsPointer next = new ConsPointer();
            aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, next, consTraverser.getPointer());
            full.cdr().setCons(next.getCons());
            full.setCons(next.getCons());
            consTraverser.goNext();
        }
        full.cdr().setCons(null);
    }


    public static void applyString(Environment aEnvironment, ConsPointer aResult,
            String aOperator, ConsPointer aArgs) throws Exception {
        LispError.check(isString(aOperator), LispError.NOT_A_STRING);

        Cons head =
                AtomCons.getInstance(aEnvironment, getSymbolName(aEnvironment, aOperator));
        head.cdr().setCons(aArgs.getCons());
        ConsPointer body = new ConsPointer();
        body.setCons(SublistCons.getInstance(aEnvironment, head));
        aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aResult, body);
    }


    public static void applyPure(ConsPointer oper, ConsPointer args2, ConsPointer aResult, Environment aEnvironment) throws Exception {
        LispError.check(oper.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT);
        LispError.check(((ConsPointer) oper.car()).getCons() != null, LispError.INVALID_ARGUMENT);
        ConsPointer oper2 = new ConsPointer();
        oper2.setCons(((ConsPointer) oper.car()).cdr().getCons());
        LispError.check(oper2.getCons() != null, LispError.INVALID_ARGUMENT);

        ConsPointer body = new ConsPointer();
        body.setCons(oper2.cdr().getCons());
        LispError.check(body.getCons() != null, LispError.INVALID_ARGUMENT);

        LispError.check(oper2.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT);
        LispError.check(((ConsPointer) oper2.car()).getCons() != null, LispError.INVALID_ARGUMENT);
        oper2.setCons(((ConsPointer) oper2.car()).cdr().getCons());

        aEnvironment.pushLocalFrame(false, "Pure");
        try {
            while (oper2.getCons() != null) {
                LispError.check(args2.getCons() != null, LispError.INVALID_ARGUMENT);

                String var = (String) oper2.car();
                LispError.check(var != null, LispError.INVALID_ARGUMENT);
                ConsPointer newly = new ConsPointer();
                newly.setCons(args2.getCons().copy(aEnvironment, false));
                aEnvironment.newLocalVariable(var, newly.getCons());
                oper2.setCons(oper2.cdr().getCons());
                args2.setCons(args2.cdr().getCons());
            }
            LispError.check(args2.getCons() == null, LispError.INVALID_ARGUMENT);
            aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, aResult, body);
        } catch (EvaluationException e) {
            throw e;
        } finally {
            aEnvironment.popLocalFrame();
        }

    }


    public static void putTrueInPointer(Environment aEnvironment, ConsPointer aResult) throws Exception {
        aResult.setCons(aEnvironment.iTrueAtom.copy(aEnvironment, false));
    }


    public static void putFalseInPointer(Environment aEnvironment, ConsPointer aResult) throws Exception {
        aResult.setCons(aEnvironment.iFalseAtom.copy(aEnvironment, false));
    }


    public static void putBooleanInPointer(Environment aEnvironment, ConsPointer aResult, boolean aValue) throws Exception {
        if (aValue) {
            putTrueInPointer(aEnvironment, aResult);
        } else {
            putFalseInPointer(aEnvironment, aResult);
        }
    }


    public static void nth(Environment aEnvironment, ConsPointer aResult, ConsPointer aArg, int n) throws Exception {
        LispError.check(aArg.getCons() != null, LispError.INVALID_ARGUMENT);
        LispError.check(aArg.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT);
        LispError.check(n >= 0, LispError.INVALID_ARGUMENT);
        ConsTraverser consTraverser = new ConsTraverser((ConsPointer) aArg.car());

        while (n > 0) {
            LispError.check(consTraverser.getCons() != null, LispError.INVALID_ARGUMENT);
            consTraverser.goNext();
            n--;
        }
        LispError.check(consTraverser.getCons() != null, LispError.INVALID_ARGUMENT);
        aResult.setCons(consTraverser.getCons().copy(aEnvironment, false));
    }


    public static void tail(Environment aEnvironment, ConsPointer aResult, ConsPointer aArg) throws Exception {
        LispError.check(aArg.getCons() != null, LispError.INVALID_ARGUMENT);
        LispError.check(aArg.car() instanceof ConsPointer, LispError.INVALID_ARGUMENT);

        ConsPointer iter = (ConsPointer) aArg.car();

        LispError.check(iter.getCons() != null, LispError.INVALID_ARGUMENT);
        aResult.setCons(SublistCons.getInstance(aEnvironment, iter.cdr().getCons()));
    }


    public static boolean isTrue(Environment aEnvironment, ConsPointer aExpression) throws Exception {
        LispError.lispAssert(aExpression.getCons() != null);

        //return aExpression.car() == aEnvironment.iTrueAtom.car();
        return aExpression.car() instanceof String && ((String) aExpression.car()) == aEnvironment.iTrueString;

        /* Code which returns True for everything except False and {};
        String expressionString = aExpression.car();

        //return expressionString == aEnvironment.iTrueString;

        if (expressionString == aEnvironment.iTrueString) {
        return true;
        } else if (isSublist(aExpression)) {
        if (listLength(aExpression.car()) == 1) {
        //Empty list.
        return false;
        } else {
        //Non-empty list.
        return true;
        }
        } else {
        //Anything other than False returns true.
        return expressionString != null && expressionString != aEnvironment.iFalseString;
        }*/

    }//end method.


    public static boolean isFalse(Environment aEnvironment, ConsPointer aExpression) throws Exception {
        LispError.lispAssert(aExpression.getCons() != null);
        return aExpression.car() instanceof String && ((String) aExpression.car()) == aEnvironment.iFalseString;

        /* Code which returns True for everything except False and {};
        return aExpression.car() == aEnvironment.iFalseString || (isSublist(aExpression) && (listLength(aExpression.car()) == 1));
         */
    }


    public static String getSymbolName(Environment aEnvironment, String aSymbol) {
        if (aSymbol.charAt(0) == '\"') {
            return aEnvironment.getTokenHash().lookUpUnStringify(aSymbol);
        } else {
            return (String) aEnvironment.getTokenHash().lookUp(aSymbol);
        }
    }


    public static boolean isSublist(ConsPointer aPtr) throws Exception {
        /**
         * todo:tk: I am currently not sure why non nested lists are not supported in Yacas.
         */
        if (aPtr.getCons() == null) {
            return false;
        }
        if (!(aPtr.car() instanceof ConsPointer)) {
            return false;
        }
        if (((ConsPointer) aPtr.car()).getCons() == null) {
            return false;
            //TODO this StrEqual is far from perfect. We could pass in a Environment object...
        }
        if (!((ConsPointer) aPtr.car()).car().equals("List")) {
            return false;
        }
        return true;

    }//end method.


    public static boolean isList(ConsPointer aPtr) throws Exception {
        /**
         * todo:tk: I am currently not sure why non nested lists are not supported in Yacas.
         */
        if (aPtr.getCons() == null) {
            return false;
        }

        if (aPtr.type() == Utility.ATOM) {
            if (((String) aPtr.car()).equalsIgnoreCase("List")) {
                return true;
            }//end if.
        }//end if.

        if (isSublist(aPtr)) {
            return true;
        }//end if.
        return false;

    }//end method.


    public static boolean isNestedList(ConsPointer clientListPointer) throws Exception {

        ConsPointer listPointer = new ConsPointer(clientListPointer.getCons());

        listPointer.goNext(); //Strip List tag.

        while (listPointer.getCons() != null) {
            if (listPointer.car() instanceof ConsPointer && isList((ConsPointer) listPointer.car())) {
                listPointer.goNext();
            } else {
                return false;
            }
        }//end while.
        return true;
    }//end method.


    public static Map optionsListToJavaMap(ConsPointer argumentsPointer, Map defaultOptions) throws Exception {

        Map userOptions = (Map) ((HashMap) defaultOptions).clone();

        while (argumentsPointer.getCons() != null) {
            //Obtain -> operator.
            ConsPointer optionPointer = (ConsPointer) argumentsPointer.car();
            LispError.check(optionPointer.type() == Utility.ATOM, LispError.INVALID_ARGUMENT);
            String operator = (String) optionPointer.car();
            LispError.check(operator.equals("->"), LispError.INVALID_ARGUMENT);

            //Obtain key.
            optionPointer.goNext();
            LispError.check(optionPointer.type() == Utility.ATOM, LispError.INVALID_ARGUMENT);
            String key = (String) optionPointer.car();
            key = Utility.stripEndQuotes(key);

            //Obtain value.
            optionPointer.goNext();
            LispError.check(optionPointer.type() == Utility.ATOM || optionPointer.type() == Utility.NUMBER, LispError.INVALID_ARGUMENT);
            if (optionPointer.type() == Utility.ATOM) {
                String value = (String) optionPointer.car();
                value = Utility.stripEndQuotes(value);
                if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
                    userOptions.put(key, Boolean.parseBoolean(value));
                } else {
                    userOptions.put(key, value);
                }//ende else.
            } else //Number
            {
                NumberCons numberCons = (NumberCons) optionPointer.getCons();
                BigNumber bigNumber = (BigNumber) numberCons.getNumber(10);
                Double value = bigNumber.toDouble();
                userOptions.put(key, value);
            }//end if/else.



            argumentsPointer.goNext();

        }//end while

        return userOptions;
    }//end method.


    public static boolean isString(Object aOriginal) {

        if (!(aOriginal instanceof String)) {
            return false;
        }//end if.

        String stringVersion = (String) aOriginal;

        if (stringVersion != null) {
            if (stringVersion.charAt(0) == '\"') {
                if (stringVersion.charAt(stringVersion.length() - 1) == '\"') {
                    return true;
                }
            }
        }
        return false;
    }//end method


    public static String stripEndQuotes(String aOriginal) throws Exception {
        //If there are not quotes on both ends of the string then return without any changes.
        if (aOriginal.startsWith("\"") && aOriginal.endsWith("\"")) {
            aOriginal = aOriginal.substring(1, aOriginal.length());
            aOriginal = aOriginal.substring(0, aOriginal.length() - 1);
        }//end if.

        return aOriginal;
    }//end method.


    public static void not(ConsPointer aResult, Environment aEnvironment, ConsPointer aExpression) throws Exception {
        if (isTrue(aEnvironment, aExpression)) {
            putFalseInPointer(aEnvironment, aResult);
        } else {
            LispError.check(isFalse(aEnvironment, aExpression), LispError.INVALID_ARGUMENT);
            putTrueInPointer(aEnvironment, aResult);
        }
    }


    public static void flatCopy(Environment aEnvironment, ConsPointer aResult, ConsPointer aOriginal) throws Exception {
        ConsTraverser orig = new ConsTraverser(aOriginal);
        ConsTraverser res = new ConsTraverser(aResult);

        while (orig.getCons() != null) {
            res.getPointer().setCons(orig.getCons().copy(aEnvironment, false));
            orig.goNext();
            res.goNext();
        }
    }


    public static boolean equals(Environment aEnvironment, ConsPointer aExpression1, ConsPointer aExpression2) throws Exception {
        // Handle pointers to same, or null
        if (aExpression1.getCons() == aExpression2.getCons()) {
            return true;
        }
        //LispError.check(aExpression1.type().equals("Number"), LispError.INVALID_ARGUMENT);
        //LispError.check(aExpression2.type().equals("Number"), LispError.INVALID_ARGUMENT);
        BigNumber n1 = (BigNumber) aExpression1.getCons().getNumber(aEnvironment.getPrecision());
        BigNumber n2 = (BigNumber) aExpression2.getCons().getNumber(aEnvironment.getPrecision());
        if (!(n1 == null && n2 == null)) {
            if (n1 == n2) {
                return true;
            }
            if (n1 == null) {
                return false;
            }
            if (n2 == null) {
                return false;
            }
            if (n1.equals(n2)) {
                return true;
            }
            return false;
        }

        //Pointers to strings should be the same
        if ((aExpression1.car() instanceof String) && (aExpression2.car() instanceof String)) {
            if (aExpression1.car() != aExpression2.car()) {
                return false;
            }
        }


        // Handle same sublists, or null
        if (aExpression1.car() == aExpression2.car()) {
            return true;
        }

        // Now check the sublists
        if (aExpression1.car() instanceof ConsPointer) {
            if (!(aExpression2.car() instanceof ConsPointer)) {
                return false;
            }
            ConsTraverser consTraverser1 = new ConsTraverser((ConsPointer) aExpression1.car());
            ConsTraverser consTraverser2 = new ConsTraverser((ConsPointer) aExpression2.car());

            while (consTraverser1.getCons() != null && consTraverser2.getCons() != null) {
                // compare two list elements
                if (!equals(aEnvironment, consTraverser1.getPointer(), consTraverser2.getPointer())) {
                    return false;
                }

                // Step to rest
                consTraverser1.goNext();
                consTraverser2.goNext();
            }
            // Lists don't have the same length
            if (consTraverser1.getCons() != consTraverser2.getCons()) {
                return false;            // Same!
            }
            return true;
        }

        // expressions sublists are not the same!
        return false;
    }


    public static void substitute(Environment aEnvironment, ConsPointer aTarget, ConsPointer aSource, Substitute aBehaviour) throws Exception {
        Cons object = aSource.getCons();
        LispError.lispAssert(object != null);
        if (!aBehaviour.matches(aEnvironment, aTarget, aSource)) {
            Object oldList = object.car();

            ConsPointer oldListPointer = null;
            if (oldList instanceof ConsPointer) {
                oldListPointer = (ConsPointer) oldList;
                oldList = null;
            }
            if (oldListPointer != null) {

                ConsPointer newList = new ConsPointer();
                ConsPointer next = newList;
                while (oldListPointer.getCons() != null) {
                    substitute(aEnvironment, next, oldListPointer, aBehaviour);
                    oldListPointer = oldListPointer.cdr();
                    next = next.cdr();
                }
                aTarget.setCons(SublistCons.getInstance(aEnvironment, newList.getCons()));
            } else {
                aTarget.setCons(object.copy(aEnvironment, false));
            }
        }//end matches if.
    }


    public static String unstringify(String aOriginal) throws Exception {
        LispError.check(aOriginal != null, LispError.INVALID_ARGUMENT);
        LispError.check(aOriginal.charAt(0) == '\"', LispError.INVALID_ARGUMENT);
        int nrc = aOriginal.length() - 1;
        LispError.check(aOriginal.charAt(nrc) == '\"', LispError.INVALID_ARGUMENT);
        return aOriginal.substring(1, nrc);
    }


    private static void doInternalLoad(Environment aEnvironment, MathPiperInputStream aInput) throws Exception {
        MathPiperInputStream previous = aEnvironment.iCurrentInput;
        try {
            aEnvironment.iCurrentInput = aInput;
            // TODO make "EndOfFile" a global thing
            // read-parse-evaluate to the end of file
            String eof = (String) aEnvironment.getTokenHash().lookUp("EndOfFile");
            boolean endoffile = false;
            MathPiperParser parser = new MathPiperParser(new MathPiperTokenizer(),
                    aEnvironment.iCurrentInput, aEnvironment,
                    aEnvironment.iPrefixOperators, aEnvironment.iInfixOperators,
                    aEnvironment.iPostfixOperators, aEnvironment.iBodiedOperators);
            ConsPointer readIn = new ConsPointer();
            while (!endoffile) {
                // Read expression
                parser.parse(aEnvironment, readIn);

                LispError.check(readIn.getCons() != null, LispError.READING_FILE);
                // check for end of file
                if (readIn.car() instanceof String && ((String) readIn.car()) == eof) {
                    endoffile = true;
                } // Else evaluate
                else {
                    ConsPointer result = new ConsPointer();
                    aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, readIn);
                    aEnvironment.setGlobalVariable("LoadResult", result, false);//Note:tk:added to make the result of executing Loaded code available.
                }
            }//end while.



        } catch (Exception e) {
            EvaluationException ee = new EvaluationException(e.getMessage(), aEnvironment.iCurrentInput.iStatus.lineNumber());
            throw ee;
        } finally {
            aEnvironment.iCurrentInput = previous;
        }
    }


    /**
     * Searches for a file on the classpath then in the default directories.  If the file is found, it is loaded.
     * @param aEnvironment
     * @param aFileName
     * @throws java.lang.Exception
     */
    public static void load(Environment aEnvironment, String aFileName) throws Exception {
        String oper = unstringify(aFileName);

        String hashedname = (String) aEnvironment.getTokenHash().lookUp(oper);

        InputStatus oldstatus = new InputStatus(aEnvironment.iInputStatus);
        aEnvironment.iInputStatus.setTo(hashedname);

        MathPiperInputStream newInput = null;

        /*java.io.MathPiperInputStream scriptStream = Scripts.getScriptStream(oper);
        if (scriptStream != null) {
        newInput = new StandardFileInputStream(scriptStream, aEnvironment.iInputStatus);
        LispError.check(newInput != null, LispError.FILE_NOT_FOUND);
        doInternalLoad(aEnvironment, newInput);
        } else {*/
//System.out.println("Loading: " + oper);
        java.net.URL fileURL = java.lang.ClassLoader.getSystemResource(oper);
        if (fileURL != null) //File is on the classpath.
        {
            newInput = new StandardFileInputStream(new InputStreamReader(fileURL.openStream()), aEnvironment.iInputStatus);
            LispError.check(newInput != null, LispError.FILE_NOT_FOUND);
            doInternalLoad(aEnvironment, newInput);
        } else { //File may be in the filesystem.
            try {
                // Open file
                newInput = // new StandardFileInputStream(hashedname, aEnvironment.iInputStatus);
                        openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus);

                LispError.check(newInput != null, LispError.FILE_NOT_FOUND);
                doInternalLoad(aEnvironment, newInput);
            } catch (Exception e) {
                throw e;
            } finally {
                aEnvironment.iInputStatus.restoreFrom(oldstatus);
            }
        }//end else.*/


        aEnvironment.iInputStatus.restoreFrom(oldstatus);


    }


    public static void use(Environment aEnvironment, String aFileName) throws Exception {
        DefFile def = aEnvironment.iDefFiles.getFile(aFileName);
        if (!def.isLoaded()) {
            def.setLoaded();
            load(aEnvironment, aFileName);
        }
    }


    public static String printExpression(ConsPointer aExpression,
            Environment aEnvironment,
            int aMaxChars) throws Exception {
        StringBuffer result = new StringBuffer();
        StringOutputStream newOutput = new StringOutputStream(result);
        MathPiperPrinter infixprinter = new MathPiperPrinter(aEnvironment.iPrefixOperators,
                aEnvironment.iInfixOperators,
                aEnvironment.iPostfixOperators,
                aEnvironment.iBodiedOperators);
        infixprinter.print(aExpression, newOutput, aEnvironment);
        if (aMaxChars > 0 && result.length() > aMaxChars) {
            result.delete(aMaxChars, result.length());
            result.append((char) '.');
            result.append((char) '.');
            result.append((char) '.');
        }
        return result.toString();
    }


    public static MathPiperInputStream openInputFile(String aFileName, InputStatus aInputStatus) throws Exception {//Note:tk:primary method for file opening.
        try {
            if (zipFile != null) {
                java.util.zip.ZipEntry e = zipFile.getEntry(aFileName);
                if (e != null) {
                    java.io.InputStream s = zipFile.getInputStream(e);
                    return new StandardFileInputStream(new InputStreamReader(s), aInputStatus);
                }
            }

            if (aFileName.substring(0, 4).equals("jar:")) {
                return new JarFileInputStream(aFileName, aInputStatus);
            } else {
                return new StandardFileInputStream(aFileName, aInputStatus);
            }
        } catch (Exception e) {
            //MathPiper eats this exception because returning null indicates to higher level code that the file was not found.
        }
        return null;

        //return new StandardFileInputStream(aFileName, aInputStatus);
    }


    public static MathPiperInputStream openInputFile(Environment aEnvironment,
            InputDirectories aInputDirectories, String aFileName,
            InputStatus aInputStatus) throws Exception {
        String othername = aFileName;
        int i = 0;
        MathPiperInputStream f = openInputFile(othername, aInputStatus);
        while (f == null && i < aInputDirectories.size()) {
            othername = ((String) aInputDirectories.get(i)) + aFileName;
            f = openInputFile(othername, aInputStatus);
            i++;
        }
        return f;
    }


    public static String findFile(String aFileName, InputDirectories aInputDirectories) throws Exception {
        InputStatus inputStatus = new InputStatus();
        String othername = aFileName;
        int i = 0;
        MathPiperInputStream f = openInputFile(othername, inputStatus);
        if (f != null) {
            return othername;
        }
        while (i < aInputDirectories.size()) {
            othername = ((String) aInputDirectories.get(i)) + aFileName;
            f = openInputFile(othername, inputStatus);
            if (f != null) {
                return othername;
            }
            i++;
        }
        return "";
    }


    private static void doLoadDefFile(Environment aEnvironment, MathPiperInputStream aInput, DefFile def) throws Exception {
        MathPiperInputStream previous = aEnvironment.iCurrentInput;
        try {
            aEnvironment.iCurrentInput = aInput;
            String eof = (String) aEnvironment.getTokenHash().lookUp("EndOfFile");
            String end = (String) aEnvironment.getTokenHash().lookUp("}");
            boolean endoffile = false;

            MathPiperTokenizer tok = new MathPiperTokenizer();

            while (!endoffile) {
                // Read expression
                String token = tok.nextToken(aEnvironment.iCurrentInput, aEnvironment.getTokenHash());

                // check for end of file
                if (token == eof || token == end) {
                    endoffile = true;
                } // Else evaluate
                else {
                    String str = token;
                    MultipleArityUserFunction multiUser = aEnvironment.getMultipleArityUserFunction(str, true);
                    if (multiUser.iFileToOpen != null) {
                        throw new EvaluationException("[" + str + "]" + "] : def file already chosen: " + multiUser.iFileToOpen.iFileName, -1);
                    }
                    multiUser.iFileToOpen = def;
                    multiUser.iFileLocation = def.fileName();
                }
            }
        } catch (Exception e) {
            throw e;
        } finally {
            aEnvironment.iCurrentInput = previous;
        }
    }


    public static void loadDefFile(Environment aEnvironment, String aFileName) throws Exception {
        LispError.lispAssert(aFileName != null);

        String flatfile = unstringify(aFileName) + ".def";
        DefFile def = aEnvironment.iDefFiles.getFile(aFileName);

        String hashedname = (String) aEnvironment.getTokenHash().lookUp(flatfile);

        InputStatus oldstatus = aEnvironment.iInputStatus;
        aEnvironment.iInputStatus.setTo(hashedname);



        MathPiperInputStream newInput = null;


        /* java.io.MathPiperInputStream scriptStream = Scripts.getScriptStream(flatfile);
        if (scriptStream != null) {
        newInput = new StandardFileInputStream(scriptStream, aEnvironment.iInputStatus);
        LispError.check(newInput != null, LispError.FILE_NOT_FOUND);
        doLoadDefFile(aEnvironment, newInput, def);
        } else {*/
//System.out.println("Loading: " + flatfile);
        java.net.URL fileURL = java.lang.ClassLoader.getSystemResource(flatfile);
        if (fileURL != null) //File is on the classpath.
        {
            newInput = new StandardFileInputStream(new InputStreamReader(fileURL.openStream()), aEnvironment.iInputStatus);
            LispError.check(newInput != null, LispError.FILE_NOT_FOUND);
            doLoadDefFile(aEnvironment, newInput, def);

        } else //File may be in the filesystem.
        {
            newInput = // new StandardFileInputStream(hashedname, aEnvironment.iInputStatus);
                    openInputFile(aEnvironment, aEnvironment.iInputDirectories, hashedname, aEnvironment.iInputStatus);
            LispError.check(newInput != null, LispError.FILE_NOT_FOUND);
            doLoadDefFile(aEnvironment, newInput, def);
        }

        aEnvironment.iInputStatus.restoreFrom(oldstatus);
    }
    //////////////////////////////////////////////////
    ///// bits_to_digits and digits_to_bits implementation
    //////////////////////////////////////////////////

    // lookup table for transforming the number of digits
    // report the table size

    int log2TableRange() {
        return log2_table_size;
    }
    // table look-up of small integer logarithms, for converting the number of digits to binary and back


    static double log2TableLookup(int n) throws Exception {
        if (n <= log2_table_size && n >= 2) {
            return log2_table[n - 1];
        } else {
            throw new EvaluationException("log2_table_lookup: error: invalid argument " + n, -1);
        }
    }


    /**
     * Convert the number of digits in given base to the number of bits.  To make sure there is no hysteresis, the returned
     * value is rounded up.
     *
     * @param digits
     * @param base
     * @return the number of bits
     * @throws java.lang.Exception
     */
    public static long digitsToBits(long digits, int base) throws Exception {
        return (long) Math.ceil(((double) digits) * log2TableLookup(base));
    }


    /**
     * Convert the  number of bits in a given base to the number of digits.  To make sure there is no hysteresis, the returned
     * value is rounded down.
     *
     * @param bits
     * @param base
     * @return the number of digits
     * @throws java.lang.Exception
     */
    public static long bitsToDigits(long bits, int base) throws Exception {
        return (long) Math.floor(((double) bits) / log2TableLookup(base));
    }

    //************************* The following methods were taken from the Functions class.

    /**
     * Construct a {@link BigNumber}.
     * @param aEnvironment the current {@link Environment}.
     * @param aStackTop points to the the top of the argument stack.
     * @param aArgNr the index of the argument to be converted.
     * @return a BigNumber.
     * @throws java.lang.Exception
     */
    public static BigNumber getNumber(Environment aEnvironment, int aStackTop, int aArgNr) throws Exception {
        //LispError.check(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, aArgNr).type().equals("Number"), LispError.INVALID_ARGUMENT);
        BigNumber x = (BigNumber) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, aArgNr).getCons().getNumber(aEnvironment.getPrecision());
        LispError.checkArgument(aEnvironment, aStackTop, x != null, aArgNr);
        return x;
    }


    public static void multiFix(Environment aEnvironment, int aStackTop, OperatorMap aOps) throws Exception {
        // Get operator
        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);
        String orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1);

        ConsPointer precedence = new ConsPointer();
        aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, precedence, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2));
        LispError.checkArgument(aEnvironment, aStackTop, precedence.car() instanceof String, 2);
        int prec = Integer.parseInt((String) precedence.car(), 10);
        LispError.checkArgument(aEnvironment, aStackTop, prec <= MathPiperPrinter.KMaxPrecedence, 2);
        aOps.setOperator(prec, Utility.getSymbolName(aEnvironment, orig));
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static void singleFix(int aPrecedence, Environment aEnvironment, int aStackTop, OperatorMap aOps) throws Exception {
        // Get operator
        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);
        String orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1);
        aOps.setOperator(aPrecedence, Utility.getSymbolName(aEnvironment, orig));
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static InfixOperator operatorInfo(Environment aEnvironment, int aStackTop, OperatorMap aOperators) throws Exception {
        // Get operator
        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);

        ConsPointer evaluated = new ConsPointer();
        evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons());

        String orig = (String) evaluated.car();
        LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1);
        //
        InfixOperator op = (InfixOperator) aOperators.lookUp(Utility.getSymbolName(aEnvironment, orig));
        return op;
    }


    /**
     * Sets a variable in the current {@link Environment}.
     * @param aEnvironment holds the execution environment of the program.
     * @param aStackTop
     * @param aMacroMode boolean which determines whether the getFirstPointer argument should be evaluated.
     * @param aGlobalLazyVariable
     * @throws java.lang.Exception
     */
    public static void setVar(Environment aEnvironment, int aStackTop, boolean aMacroMode, boolean aGlobalLazyVariable) throws Exception {
        String variableString = null;
        if (aMacroMode) {
            ConsPointer result = new ConsPointer();
            aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1));
            variableString = (String) result.car();
        } else {
            variableString = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        }
        LispError.checkArgument(aEnvironment, aStackTop, variableString != null, 1);
        LispError.checkArgument(aEnvironment, aStackTop, !Utility.isNumber(variableString, true), 1);

        ConsPointer result = new ConsPointer();
        aEnvironment.iLispExpressionEvaluator.evaluate(aEnvironment, result, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2));
        aEnvironment.setGlobalVariable(variableString, result, aGlobalLazyVariable); //Variable setting is deligated to Environment.
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static void delete(Environment aEnvironment, int aStackTop, boolean aDestructive) throws Exception {
        ConsPointer evaluated = new ConsPointer();
        evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons());
        LispError.checkIsList(aEnvironment, aStackTop, evaluated, 1);

        ConsPointer copied = new ConsPointer();
        if (aDestructive) {
            copied.setCons(((ConsPointer) evaluated.car()).getCons());
        } else {
            Utility.flatCopy(aEnvironment, copied, (ConsPointer) evaluated.car());
        }

        ConsPointer index = new ConsPointer();
        index.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());
        LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2);
        LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2);
        int ind = Integer.parseInt((String) index.car(), 10);
        LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2);

        ConsTraverser consTraverser = new ConsTraverser(copied);
        while (ind > 0) {
            consTraverser.goNext();
            ind--;
        }
        LispError.check(aEnvironment, aStackTop, consTraverser.getCons() != null, LispError.NOT_LONG_ENOUGH);
        ConsPointer next = new ConsPointer();
        next.setCons(consTraverser.cdr().getCons());
        consTraverser.getPointer().setCons(next.getCons());
        BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, copied.getCons()));
    }


    public static void insert(Environment aEnvironment, int aStackTop, boolean aDestructive) throws Exception {
        ConsPointer evaluated = new ConsPointer();
        evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons());
        LispError.checkIsList(aEnvironment, aStackTop, evaluated, 1);

        ConsPointer copied = new ConsPointer();
        if (aDestructive) {
            copied.setCons(((ConsPointer) evaluated.car()).getCons());
        } else {
            Utility.flatCopy(aEnvironment, copied, (ConsPointer) evaluated.car());
        }

        ConsPointer index = new ConsPointer();
        index.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());
        LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2);
        LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2);
        int ind = Integer.parseInt((String) index.car(), 10);
        LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2);

        ConsTraverser consTraverser = new ConsTraverser(copied);
        while (ind > 0) {
            consTraverser.goNext();
            ind--;
        }

        ConsPointer toInsert = new ConsPointer();
        toInsert.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons());
        toInsert.cdr().setCons(consTraverser.getCons());
        consTraverser.getPointer().setCons(toInsert.getCons());
        BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, copied.getCons()));
    }


    public static void replace(Environment aEnvironment, int aStackTop, boolean aDestructive) throws Exception {
        ConsPointer evaluated = new ConsPointer();
        evaluated.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons());
        // Ok, so lets not check if it is a list, but it needs to be at least a 'function'
        LispError.checkArgument(aEnvironment, aStackTop, evaluated.car() instanceof ConsPointer, 1);

        ConsPointer index = new ConsPointer();
        index.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());
        LispError.checkArgument(aEnvironment, aStackTop, index.getCons() != null, 2);
        LispError.checkArgument(aEnvironment, aStackTop, index.car() instanceof String, 2);
        int ind = Integer.parseInt((String) index.car(), 10);

        ConsPointer copied = new ConsPointer();
        if (aDestructive) {
            copied.setCons(((ConsPointer) evaluated.car()).getCons());
        } else {
            Utility.flatCopy(aEnvironment, copied, (ConsPointer) evaluated.car());
        }
        LispError.checkArgument(aEnvironment, aStackTop, ind > 0, 2);

        ConsTraverser consTraverser = new ConsTraverser(copied);
        while (ind > 0) {
            consTraverser.goNext();
            ind--;
        }

        ConsPointer toInsert = new ConsPointer();
        toInsert.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons());
        LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getPointer() != null, 2);
        LispError.checkArgument(aEnvironment, aStackTop, consTraverser.getPointer().getCons() != null, 2);
        toInsert.cdr().setCons(consTraverser.getPointer().cdr().getCons());
        consTraverser.getPointer().setCons(toInsert.getCons());
        BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop).setCons(SublistCons.getInstance(aEnvironment, copied.getCons()));
    }


    /**
     *Implements the MathPiper functions RuleBase and MacroRuleBase .
     * The real work is done by Environment.declareRulebase().
     */
    public static void ruleDatabase(Environment aEnvironment, int aStackTop, boolean aListed) throws Exception {
        //TESTARGS(3);

        // Get operator
        ConsPointer argsPointer = new ConsPointer();
        String functionName = null;

        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);
        functionName = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        LispError.checkArgument(aEnvironment, aStackTop, functionName != null, 1);
        argsPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());

        // Check the arguments.
        LispError.checkIsList(aEnvironment, aStackTop, argsPointer, 2);

        // Finally define the rule database.
        aEnvironment.declareRulebase(Utility.getSymbolName(aEnvironment, functionName),
                ((ConsPointer) argsPointer.car()).cdr(), aListed);

        // Return true
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static void newRule(Environment aEnvironment, int aStackTop) throws Exception {
        //TESTARGS(6);

        int arity;
        int precedence;

        ConsPointer ar = new ConsPointer();
        ConsPointer pr = new ConsPointer();
        ConsPointer predicate = new ConsPointer();
        ConsPointer body = new ConsPointer();
        String orig = null;

        // Get operator
        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);
        orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1);
        ar.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());
        pr.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons());
        predicate.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 4).getCons());
        body.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 5).getCons());

        // The arity
        LispError.checkArgument(aEnvironment, aStackTop, ar.getCons() != null, 2);
        LispError.checkArgument(aEnvironment, aStackTop, ar.car() instanceof String, 2);
        arity = Integer.parseInt((String) ar.car(), 10);

        // The precedence
        LispError.checkArgument(aEnvironment, aStackTop, pr.getCons() != null, 3);
        LispError.checkArgument(aEnvironment, aStackTop, pr.car() instanceof String, 3);
        precedence = Integer.parseInt((String) pr.car(), 10);

        // Finally define the rule base
        aEnvironment.defineRule(Utility.getSymbolName(aEnvironment, orig),
                arity,
                precedence,
                predicate,
                body);

        // Return true
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static void defMacroRuleBase(Environment aEnvironment, int aStackTop, boolean aListed) throws Exception {
        // Get operator
        ConsPointer args = new ConsPointer();
        ConsPointer body = new ConsPointer();
        String orig = null;

        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);
        orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1);

        // The arguments
        args.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());
        LispError.checkIsList(aEnvironment, aStackTop, args, 2);

        // Finally define the rule base
        aEnvironment.declareMacroRulebase(Utility.getSymbolName(aEnvironment, orig),
                ((ConsPointer) args.car()).cdr(), aListed);

        // Return true
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static void newRulePattern(Environment aEnvironment, int aStackTop, boolean aMacroMode) throws Exception {
        int arity;
        int precedence;

        ConsPointer arityPointer = new ConsPointer();
        ConsPointer precedencePointer = new ConsPointer();
        ConsPointer predicatePointer = new ConsPointer();
        ConsPointer bodyPointer = new ConsPointer();
        String orig = null;

        // Get operator
        LispError.checkArgument(aEnvironment, aStackTop, BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).getCons() != null, 1);
        orig = (String) BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 1).car();
        LispError.checkArgument(aEnvironment, aStackTop, orig != null, 1);
        arityPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 2).getCons());
        precedencePointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 3).getCons());
        predicatePointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 4).getCons());
        bodyPointer.setCons(BuiltinFunction.getArgumentPointer(aEnvironment, aStackTop, 5).getCons());

        // The arity
        LispError.checkArgument(aEnvironment, aStackTop, arityPointer.getCons() != null, 2);
        LispError.checkArgument(aEnvironment, aStackTop, arityPointer.car() instanceof String, 2);
        arity = Integer.parseInt((String) arityPointer.car(), 10);

        // The precedence
        LispError.checkArgument(aEnvironment, aStackTop, precedencePointer.getCons() != null, 3);
        LispError.checkArgument(aEnvironment, aStackTop, precedencePointer.car() instanceof String, 3);
        precedence = Integer.parseInt((String) precedencePointer.car(), 10);

        // Finally define the rule base
        aEnvironment.defineRulePattern(Utility.getSymbolName(aEnvironment, orig),
                arity,
                precedence,
                predicatePointer,
                bodyPointer);

        // Return true
        Utility.putTrueInPointer(aEnvironment, BuiltinFunction.getTopOfStackPointer(aEnvironment, aStackTop));
    }


    public static String dumpRule(Branch branch, Environment aEnvironment, SingleArityBranchingUserFunction userFunction) {
        StringBuilder dumpResult = new StringBuilder();
        try {
            int precedence = branch.getPrecedence();
            ConsPointer predicatePointer1 = branch.getPredicatePointer();
            String predicate = "";
            String predicatePointerString = predicatePointer1.toString();
            if (predicatePointerString == null || predicatePointerString.equalsIgnoreCase("Empty.")) {
                predicate = "None.";
            } else {
                predicate = Utility.printExpression(predicatePointer1, aEnvironment, 0);
            }

            if (predicate.equalsIgnoreCase("\"Pattern\"")) {
                predicate = "(Pattern) ";
                PatternBranch branchPattern = (PatternBranch) branch;
                Pattern pattern = branchPattern.getPattern();

                Iterator variablesIterator = pattern.getVariables().iterator();
                String patternVariables = "";
                while (variablesIterator.hasNext()) {
                    String patternVariable = (String) variablesIterator.next();
                    patternVariables += patternVariable + ", ";
                }
                if (patternVariables.contains(",")) {
                    patternVariables = patternVariables.substring(0, patternVariables.lastIndexOf(","));
                }


                Iterator parameterMatchersIterator = pattern.getParameterMatchers().iterator();
                String parameterTypes = "";
                while (parameterMatchersIterator.hasNext()) {
                    PatternParameter parameter = (PatternParameter) parameterMatchersIterator.next();
                    String parameterType = (String) parameter.getType();
                    parameterTypes += parameterType + ", ";
                }
                if (parameterTypes.contains(",")) {
                    parameterTypes = parameterTypes.substring(0, parameterTypes.lastIndexOf(","));
                }



                Iterator patternPredicatesIterator = pattern.getPredicates().iterator();
                while (patternPredicatesIterator.hasNext()) {
                    ConsPointer predicatePointer = (ConsPointer) patternPredicatesIterator.next();
                    String patternPredicate = Utility.printExpression(predicatePointer, aEnvironment, 0);
                    predicate += patternPredicate + ", ";
                }
                /*if (predicate.contains(",")) {
                predicate = predicate.substring(0, predicate.lastIndexOf(","));
                }*/
                predicate += "\n    Variables: " + patternVariables + ", ";
                predicate += "\n    Types: " + parameterTypes;


            }//end if.

            Iterator paremetersIterator = userFunction.getParameters();
            String parameters = "";
            boolean isHold = false;
            while (paremetersIterator.hasNext()) {
                FunctionParameter branchParameter = (FunctionParameter) paremetersIterator.next();
                String parameter = branchParameter.getParameter();
                isHold = branchParameter.isHold();
                parameters += parameter + "<hold=" + isHold + ">, ";
            }
            if (parameters.contains(",")) {
                parameters = parameters.substring(0, parameters.lastIndexOf(","));
            }

            String body = Utility.printExpression(branch.getBodyPointer(), aEnvironment, 0);
            body = body.replace(",", ", ");
            //System.out.println(data);

            String substitutedMacroBody = "";

            if (userFunction instanceof MacroUserFunction) {
                BackQuoteSubstitute backQuoteSubstitute = new BackQuoteSubstitute(aEnvironment);
                ConsPointer substitutedBodyPointer = new ConsPointer();
                Utility.substitute(aEnvironment, substitutedBodyPointer, branch.getBodyPointer(), backQuoteSubstitute);
                substitutedMacroBody = Utility.printExpression(substitutedBodyPointer, aEnvironment, 0);
            }

            dumpResult.append("Precedence: " + precedence + ", ");
            dumpResult.append("\n" + "Parameters: " + parameters + ", ");
            dumpResult.append("\n" + "Predicates: " + predicate + ",    ");

            if (userFunction instanceof MacroUserFunction) {
                dumpResult.append("\n" + "Body: \n" + body + ", ");
                dumpResult.append("\n" + "Substituted Macro Body: \n" + substitutedMacroBody + "\n");
            } else {
                dumpResult.append("\n" + "Body: \n" + body + "\n");
            }



        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dumpResult.toString();

    }//end method.


    public static Cons associativeListGet(Environment aEnvironment, ConsPointer key, Cons listCons) throws Exception {


        while (listCons != null) {
            if (listCons.car() instanceof ConsPointer) {
                Cons sub = ((ConsPointer) listCons.car()).getCons();
                if (sub != null) {
                    sub = sub.cdr().getCons();
                    ConsPointer temp = new ConsPointer();
                    temp.setCons(sub);
                    if (Utility.equals(aEnvironment, key, temp)) {
                        return listCons;
                    }//end if.

                }//end if.

            }//end if.

            listCons = listCons.cdr().getCons();

        }//end if.

        return null;
    }//end method.


}//end class.


Generated by  Doxygen 1.6.0   Back to index