lojix/wam_prolog/src/main/com/thesett/aima/logic/fol/wam/compiler/DefaultBuiltIn.java
public SizeableLinkedList<WAMInstruction> compileBodyArguments(Functor expression, boolean isFirstBody,
        FunctorName clauseName, int bodyNumber)
    {
        // Used to build up the results in.
        SizeableLinkedList<WAMInstruction> instructions = new SizeableLinkedList<WAMInstruction>();

        // Allocate argument registers on the body, to all functors as outermost arguments.
        // Allocate temporary registers on the body, to all terms not already allocated.
        /*if (!isFirstBody)
        {
            lastAllocatedRegister = 0;
        }*/

        allocateArgumentRegisters(expression);
        allocateTemporaryRegisters(expression);

        // Loop over all of the arguments to the outermost functor.
        int numOutermostArgs = expression.getArity();

        for (int j = 0; j < numOutermostArgs; j++)
        {
            Term nextOutermostArg = expression.getArgument(j);
            int allocation =
                (Integer) symbolTable.get(nextOutermostArg.getSymbolKey(), SymbolTableKeys.SYMKEY_ALLOCATION);

            byte addrMode = (byte) ((allocation & 0xff00) >> 8);
            byte address = (byte) (allocation & 0xff);

            // On the first occurrence of a variable output a put_var.
            // On a subsequent variable occurrence output a put_val.
            if (nextOutermostArg.isVar() && !seenRegisters.contains(allocation))
            {
                seenRegisters.add(allocation);

                // The variable has been moved into an argument register.
                //varNames.remove((byte) allocation);
                //varNames.put((byte) j, ((Variable) nextOutermostArg).getName());

                /*log.fine("PUT_VAR " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" + j);*/

                WAMInstruction instruction =
                    new WAMInstruction(WAMInstruction.WAMInstructionSet.PutVar, addrMode, address, (byte) (j & 0xff));
                instructions.add(instruction);

                // Record the way in which this variable was introduced into the clause.
                symbolTable.put(nextOutermostArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VARIABLE_INTRO,
                    VarIntroduction.Put);
            }
            else if (nextOutermostArg.isVar())
            {
                // Check if this is the last body functor in which this variable appears, it does so only in argument
                // position, and this is the first occurrence of these conditions. In which case, an unsafe put is to
                // be used.
                if (isLastBodyTermInArgPositionOnly((Variable) nextOutermostArg, expression) &&
                        (addrMode == WAMInstruction.STACK_ADDR))
                {
                    /*log.fine("PUT_UNSAFE_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" +
                        j);*/

                    WAMInstruction instruction =
                        new WAMInstruction(WAMInstruction.WAMInstructionSet.PutUnsafeVal, addrMode, address,
                            (byte) (j & 0xff));
                    instructions.add(instruction);

                    symbolTable.put(nextOutermostArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VAR_LAST_ARG_FUNCTOR, null);
                }
                else
                {
                    /*log.fine("PUT_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" + j);*/

                    WAMInstruction instruction =
                        new WAMInstruction(WAMInstruction.WAMInstructionSet.PutVal, addrMode, address,
                            (byte) (j & 0xff));
                    instructions.add(instruction);
                }
            }

            // When a functor is encountered, output a put_struc.
            else if (nextOutermostArg.isFunctor())
            {
                Term nextFunctorArg = (Functor) nextOutermostArg;

                // Heap cells are to be created in an order such that no heap cell can appear before other cells that it
                // refers to. A postfix traversal of the functors in the term to compile is used to achieve this, as
                // child functors in a head will be visited first.
                // Walk over the query term in post-fix order, picking out just the functors.
                QueueBasedSearchMethod<Term, Term> postfixSearch = new PostFixSearch<Term, Term>();
                postfixSearch.reset();
                postfixSearch.addStartState(nextFunctorArg);
                postfixSearch.setGoalPredicate(new FunctorTermPredicate());

                Iterator<Term> treeWalker = Searches.allSolutions(postfixSearch);

                // For each functor encountered: put_struc.
                while (treeWalker.hasNext())
                {
                    Functor nextFunctor = (Functor) treeWalker.next();
                    allocation =
                        (Integer) symbolTable.get(nextFunctor.getSymbolKey(), SymbolTableKeys.SYMKEY_ALLOCATION);
                    addrMode = (byte) ((allocation & 0xff00) >> 8);
                    address = (byte) (allocation & 0xff);

                    // Ouput a put_struc instuction, except on the outermost functor.
                    /*log.fine("PUT_STRUC " + interner.getFunctorName(nextFunctor) + "/" + nextFunctor.getArity() +
                        ((addrMode == REG_ADDR) ? ", X" : ", Y") + address);*/

                    WAMInstruction instruction =
                        new WAMInstruction(WAMInstruction.WAMInstructionSet.PutStruc, addrMode, address,
                            interner.getDeinternedFunctorName(nextFunctor.getName()), nextFunctor);
                    instructions.add(instruction);

                    // For each argument of the functor.
                    int numArgs = nextFunctor.getArity();

                    for (int i = 0; i < numArgs; i++)
                    {
                        Term nextArg = nextFunctor.getArgument(i);
                        allocation =
                            (Integer) symbolTable.get(nextArg.getSymbolKey(), SymbolTableKeys.SYMKEY_ALLOCATION);
                        addrMode = (byte) ((allocation & 0xff00) >> 8);
                        address = (byte) (allocation & 0xff);

                        // If it is new variable: set_var or put_var.
                        // If it is variable or functor already seen: set_val or put_val.
                        if (nextArg.isVar() && !seenRegisters.contains(allocation))
                        {
                            seenRegisters.add(allocation);

                            /*log.fine("SET_VAR " + ((addrMode == REG_ADDR) ? "X" : "Y") + address);*/
                            instruction =
                                new WAMInstruction(WAMInstruction.WAMInstructionSet.SetVar, addrMode, address, nextArg);

                            // Record the way in which this variable was introduced into the clause.
                            symbolTable.put(nextArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VARIABLE_INTRO,
                                VarIntroduction.Set);
                        }
                        else
                        {
                            // Check if the variable is 'local' and use a local instruction on the first occurrence.
                            VarIntroduction introduction =
                                (VarIntroduction) symbolTable.get(nextArg.getSymbolKey(),
                                    SymbolTableKeys.SYMKEY_VARIABLE_INTRO);

                            if (isLocalVariable(introduction, addrMode))
                            {
                                /*log.fine("SET_LOCAL_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") +
                                    address);*/

                                instruction =
                                    new WAMInstruction(WAMInstruction.WAMInstructionSet.SetLocalVal, addrMode, address,
                                        nextArg);

                                symbolTable.put(nextArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VARIABLE_INTRO, null);
                            }
                            else
                            {
                                /*log.fine("SET_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address);*/
                                instruction =
                                    new WAMInstruction(WAMInstruction.WAMInstructionSet.SetVal, addrMode, address,
                                        nextArg);
                            }
                        }

                        instructions.add(instruction);
                    }
                }
            }
        }

        return instructions;
    }
public SizeableLinkedList<WAMInstruction> compileBodyArguments(Functor expression, boolean isFirstBody,
        FunctorName clauseName, int bodyNumber)
    {
        // Used to build up the results in.
        SizeableLinkedList<WAMInstruction> instructions = new SizeableLinkedList<WAMInstruction>();

        // Allocate argument registers on the body, to all functors as outermost arguments.
        // Allocate temporary registers on the body, to all terms not already allocated.
        /*if (!isFirstBody)
        {
            lastAllocatedRegister = 0;
        }*/

        allocateArgumentRegisters(expression);
        allocateTemporaryRegisters(expression);

        // Loop over all of the arguments to the outermost functor.
        int numOutermostArgs = expression.getArity();

        for (int j = 0; j < numOutermostArgs; j++)
        {
            Term nextOutermostArg = expression.getArgument(j);
            int allocation =
                (Integer) symbolTable.get(nextOutermostArg.getSymbolKey(), SymbolTableKeys.SYMKEY_ALLOCATION);

            byte addrMode = (byte) ((allocation & 0xff00) >> 8);
            byte address = (byte) (allocation & 0xff);

            // On the first occurrence of a variable output a put_var.
            // On a subsequent variable occurrence output a put_val.
            if (nextOutermostArg.isVar() && !seenRegisters.contains(allocation))
            {
                seenRegisters.add(allocation);

                // The variable has been moved into an argument register.
                //varNames.remove((byte) allocation);
                //varNames.put((byte) j, ((Variable) nextOutermostArg).getName());

                /*log.fine("PUT_VAR " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" + j);*/

                WAMInstruction instruction =
                    new WAMInstruction(WAMInstruction.WAMInstructionSet.PutVar, addrMode, address, (byte) (j & 0xff));
                instructions.add(instruction);

                // Record the way in which this variable was introduced into the clause.
                symbolTable.put(nextOutermostArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VARIABLE_INTRO,
                    VarIntroduction.Put);
            }
            else if (nextOutermostArg.isVar())
            {
                // Check if this is the last body functor in which this variable appears, it does so only in argument
                // position, and this is the first occurrence of these conditions. In which case, an unsafe put is to
                // be used.
                if (isLastBodyTermInArgPositionOnly((Variable) nextOutermostArg, expression) &&
                        (addrMode == WAMInstruction.STACK_ADDR))
                {
                    /*log.fine("PUT_UNSAFE_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" +
                        j);*/

                    WAMInstruction instruction =
                        new WAMInstruction(WAMInstruction.WAMInstructionSet.PutUnsafeVal, addrMode, address,
                            (byte) (j & 0xff));
                    instructions.add(instruction);

                    symbolTable.put(nextOutermostArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VAR_LAST_ARG_FUNCTOR, null);
                }
                else
                {
                    /*log.fine("PUT_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" + j);*/

                    WAMInstruction instruction =
                        new WAMInstruction(WAMInstruction.WAMInstructionSet.PutVal, addrMode, address,
                            (byte) (j & 0xff));
                    instructions.add(instruction);
                }
            }

            // When a functor is encountered, output a put_struc.
            else if (nextOutermostArg.isFunctor())
            {
                Term nextFunctorArg = (Functor) nextOutermostArg;

                // Heap cells are to be created in an order such that no heap cell can appear before other cells that it
                // refers to. A postfix traversal of the functors in the term to compile is used to achieve this, as
                // child functors in a head will be visited first.
                // Walk over the query term in post-fix order, picking out just the functors.
                QueueBasedSearchMethod<Term, Term> postfixSearch = new PostFixSearch<Term, Term>();
                postfixSearch.reset();
                postfixSearch.addStartState(nextFunctorArg);
                postfixSearch.setGoalPredicate(new FunctorTermPredicate());

                Iterator<Term> treeWalker = Searches.allSolutions(postfixSearch);

                // For each functor encountered: put_struc.
                while (treeWalker.hasNext())
                {
                    Functor nextFunctor = (Functor) treeWalker.next();
                    allocation =
                        (Integer) symbolTable.get(nextFunctor.getSymbolKey(), SymbolTableKeys.SYMKEY_ALLOCATION);
                    addrMode = (byte) ((allocation & 0xff00) >> 8);
                    address = (byte) (allocation & 0xff);

                    // Ouput a put_struc instuction, except on the outermost functor.
                    /*log.fine("PUT_STRUC " + interner.getFunctorName(nextFunctor) + "/" + nextFunctor.getArity() +
                        ((addrMode == REG_ADDR) ? ", X" : ", Y") + address);*/

                    WAMInstruction instruction =
                        new WAMInstruction(WAMInstruction.WAMInstructionSet.PutStruc, addrMode, address,
                            interner.getDeinternedFunctorName(nextFunctor.getName()), nextFunctor);
                    instructions.add(instruction);

                    // For each argument of the functor.
                    int numArgs = nextFunctor.getArity();

                    for (int i = 0; i < numArgs; i++)
                    {
                        Term nextArg = nextFunctor.getArgument(i);
                        allocation =
                            (Integer) symbolTable.get(nextArg.getSymbolKey(), SymbolTableKeys.SYMKEY_ALLOCATION);
                        addrMode = (byte) ((allocation & 0xff00) >> 8);
                        address = (byte) (allocation & 0xff);

                        // If it is new variable: set_var or put_var.
                        // If it is variable or functor already seen: set_val or put_val.
                        if (nextArg.isVar() && !seenRegisters.contains(allocation))
                        {
                            seenRegisters.add(allocation);

                            /*log.fine("SET_VAR " + ((addrMode == REG_ADDR) ? "X" : "Y") + address);*/
                            instruction =
                                new WAMInstruction(WAMInstruction.WAMInstructionSet.SetVar, addrMode, address, nextArg);

                            // Record the way in which this variable was introduced into the clause.
                            symbolTable.put(nextArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VARIABLE_INTRO,
                                VarIntroduction.Set);
                        }
                        else
                        {
                            // Check if the variable is 'local' and use a local instruction on the first occurrence.
                            VarIntroduction introduction =
                                (VarIntroduction) symbolTable.get(nextArg.getSymbolKey(),
                                    SymbolTableKeys.SYMKEY_VARIABLE_INTRO);

                            if (isLocalVariable(introduction, addrMode))
                            {
                                /*log.fine("SET_LOCAL_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") +
                                    address);*/

                                instruction =
                                    new WAMInstruction(WAMInstruction.WAMInstructionSet.SetLocalVal, addrMode, address,
                                        nextArg);

                                symbolTable.put(nextArg.getSymbolKey(), SymbolTableKeys.SYMKEY_VARIABLE_INTRO, null);
                            }
                            else
                            {
                                /*log.fine("SET_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address);*/
                                instruction =
                                    new WAMInstruction(WAMInstruction.WAMInstructionSet.SetVal, addrMode, address,
                                        nextArg);
                            }
                        }

                        instructions.add(instruction);
                    }
                }
            }
        }

        return instructions;
    }
public SizeableLinkedList < WAMInstruction > compileBodyArguments ( Functor expression , boolean isFirstBody , FunctorName clauseName , int bodyNumber ) { // Used to build up the results in. SizeableLinkedList < WAMInstruction > instructions = new SizeableLinkedList < WAMInstruction > ( ) ; // Allocate argument registers on the body, to all functors as outermost arguments. // Allocate temporary registers on the body, to all terms not already allocated. /*if (!isFirstBody)
        {
            lastAllocatedRegister = 0;
        }*/ allocateArgumentRegisters ( expression ) ; allocateTemporaryRegisters ( expression ) ; // Loop over all of the arguments to the outermost functor. int numOutermostArgs = expression . getArity ( ) ; for ( int j = 0 ; j < numOutermostArgs ; j ++ ) { Term nextOutermostArg = expression . getArgument ( j ) ; int allocation = ( Integer ) symbolTable . get ( nextOutermostArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_ALLOCATION ) ; byte addrMode = ( byte ) ( ( allocation & 0xff00 ) >> 8 ) ; byte address = ( byte ) ( allocation & 0xff ) ; // On the first occurrence of a variable output a put_var. // On a subsequent variable occurrence output a put_val. if ( nextOutermostArg . isVar ( ) && ! seenRegisters . contains ( allocation ) ) { seenRegisters . add ( allocation ) ; // The variable has been moved into an argument register. //varNames.remove((byte) allocation); //varNames.put((byte) j, ((Variable) nextOutermostArg).getName()); /*log.fine("PUT_VAR " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" + j);*/ WAMInstruction instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . PutVar , addrMode , address , ( byte ) ( j & 0xff ) ) ; instructions . add ( instruction ) ; // Record the way in which this variable was introduced into the clause. symbolTable . put ( nextOutermostArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_VARIABLE_INTRO , VarIntroduction . Put ) ; } else if ( nextOutermostArg . isVar ( ) ) { // Check if this is the last body functor in which this variable appears, it does so only in argument // position, and this is the first occurrence of these conditions. In which case, an unsafe put is to // be used. if ( isLastBodyTermInArgPositionOnly ( ( Variable ) nextOutermostArg , expression ) && ( addrMode == WAMInstruction . STACK_ADDR ) ) { /*log.fine("PUT_UNSAFE_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" +
                        j);*/ WAMInstruction instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . PutUnsafeVal , addrMode , address , ( byte ) ( j & 0xff ) ) ; instructions . add ( instruction ) ; symbolTable . put ( nextOutermostArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_VAR_LAST_ARG_FUNCTOR , null ) ; } else { /*log.fine("PUT_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address + ", A" + j);*/ WAMInstruction instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . PutVal , addrMode , address , ( byte ) ( j & 0xff ) ) ; instructions . add ( instruction ) ; } } // When a functor is encountered, output a put_struc. else if ( nextOutermostArg . isFunctor ( ) ) { Term nextFunctorArg = ( Functor ) nextOutermostArg ; // Heap cells are to be created in an order such that no heap cell can appear before other cells that it // refers to. A postfix traversal of the functors in the term to compile is used to achieve this, as // child functors in a head will be visited first. // Walk over the query term in post-fix order, picking out just the functors. QueueBasedSearchMethod < Term , Term > postfixSearch = new PostFixSearch < Term , Term > ( ) ; postfixSearch . reset ( ) ; postfixSearch . addStartState ( nextFunctorArg ) ; postfixSearch . setGoalPredicate ( new FunctorTermPredicate ( ) ) ; Iterator < Term > treeWalker = Searches . allSolutions ( postfixSearch ) ; // For each functor encountered: put_struc. while ( treeWalker . hasNext ( ) ) { Functor nextFunctor = ( Functor ) treeWalker . next ( ) ; allocation = ( Integer ) symbolTable . get ( nextFunctor . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_ALLOCATION ) ; addrMode = ( byte ) ( ( allocation & 0xff00 ) >> 8 ) ; address = ( byte ) ( allocation & 0xff ) ; // Ouput a put_struc instuction, except on the outermost functor. /*log.fine("PUT_STRUC " + interner.getFunctorName(nextFunctor) + "/" + nextFunctor.getArity() +
                        ((addrMode == REG_ADDR) ? ", X" : ", Y") + address);*/ WAMInstruction instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . PutStruc , addrMode , address , interner . getDeinternedFunctorName ( nextFunctor . getName ( ) ) , nextFunctor ) ; instructions . add ( instruction ) ; // For each argument of the functor. int numArgs = nextFunctor . getArity ( ) ; for ( int i = 0 ; i < numArgs ; i ++ ) { Term nextArg = nextFunctor . getArgument ( i ) ; allocation = ( Integer ) symbolTable . get ( nextArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_ALLOCATION ) ; addrMode = ( byte ) ( ( allocation & 0xff00 ) >> 8 ) ; address = ( byte ) ( allocation & 0xff ) ; // If it is new variable: set_var or put_var. // If it is variable or functor already seen: set_val or put_val. if ( nextArg . isVar ( ) && ! seenRegisters . contains ( allocation ) ) { seenRegisters . add ( allocation ) ; /*log.fine("SET_VAR " + ((addrMode == REG_ADDR) ? "X" : "Y") + address);*/ instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . SetVar , addrMode , address , nextArg ) ; // Record the way in which this variable was introduced into the clause. symbolTable . put ( nextArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_VARIABLE_INTRO , VarIntroduction . Set ) ; } else { // Check if the variable is 'local' and use a local instruction on the first occurrence. VarIntroduction introduction = ( VarIntroduction ) symbolTable . get ( nextArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_VARIABLE_INTRO ) ; if ( isLocalVariable ( introduction , addrMode ) ) { /*log.fine("SET_LOCAL_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") +
                                    address);*/ instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . SetLocalVal , addrMode , address , nextArg ) ; symbolTable . put ( nextArg . getSymbolKey ( ) , SymbolTableKeys . SYMKEY_VARIABLE_INTRO , null ) ; } else { /*log.fine("SET_VAL " + ((addrMode == REG_ADDR) ? "X" : "Y") + address);*/ instruction = new WAMInstruction ( WAMInstruction . WAMInstructionSet . SetVal , addrMode , address , nextArg ) ; } } instructions . add ( instruction ) ; } } } } return instructions ; }
{@inheritDoc}
{