lojix/wam_prolog/src/main/com/thesett/aima/logic/fol/wam/compiler/InstructionCompiler.java
private void compileQuery(Clause clause) throws SourceCodeException
    {
        // Used to build up the compiled result in.
        WAMCompiledQuery result;

        // A mapping from top stack frame slots to interned variable names is built up in this.
        // This is used to track the stack positions that variables in a query are assigned to.
        Map<Byte, Integer> varNames = new TreeMap<Byte, Integer>();

        // Used to keep track of registers as they are seen during compilation. The first time a variable is seen,
        // a variable is written onto the heap, subsequent times its value. The first time a functor is seen,
        // its structure is written onto the heap, subsequent times it is compared with.
        seenRegisters = new TreeSet<Integer>();

        // This is used to keep track of the next temporary register available to allocate.
        lastAllocatedTempReg = findMaxArgumentsInClause(clause);

        // This is used to keep track of the number of permanent variables.
        numPermanentVars = 0;

        // This is used to keep track of the allocation slot for the cut level variable, when needed. -1 means it is
        // not needed, so it is initialized to this.
        cutLevelVarSlot = -1;

        // These are used to generate pre and post instructions for the clause, for example, for the creation and
        // clean-up of stack frames.
        SizeableList<WAMInstruction> preFixInstructions = new SizeableLinkedList<WAMInstruction>();
        SizeableList<WAMInstruction> postFixInstructions = new SizeableLinkedList<WAMInstruction>();

        // Find all the free non-anonymous variables in the clause.
        Set<Variable> freeVars = TermUtils.findFreeNonAnonymousVariables(clause);
        Set<Integer> freeVarNames = new TreeSet<Integer>();

        for (Variable var : freeVars)
        {
            freeVarNames.add(var.getName());
        }

        // Allocate permanent variables for a query. In queries all variables are permanent so that they are preserved
        // on the stack upon completion of the query.
        allocatePermanentQueryRegisters(clause, varNames);

        // Gather information about the counts and positions of occurrence of variables and constants within the clause.
        gatherPositionAndOccurrenceInfo(clause);

        result = new WAMCompiledQuery(varNames, freeVarNames);

        // Generate the prefix code for the clause. Queries require a stack frames to hold their environment.
        /*log.fine("ALLOCATE " + numPermanentVars);*/
        preFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.AllocateN, REG_ADDR,
                (byte) (numPermanentVars & 0xff)));

        // Deep cuts require the current choice point to be kept in a permanent variable, so that it can be recovered
        // once deeper choice points or environments have been reached.
        if (cutLevelVarSlot >= 0)
        {
            /*log.fine("GET_LEVEL "+ cutLevelVarSlot);*/
            preFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.GetLevel, STACK_ADDR,
                    (byte) cutLevelVarSlot));
        }

        result.addInstructions(preFixInstructions);

        // Compile all of the conjunctive parts of the body of the clause, if there are any.
        Functor[] expressions = clause.getBody();

        // The current query does not have a name, so invent one for it.
        FunctorName fn = new FunctorName("tq", 0);

        for (int i = 0; i < expressions.length; i++)
        {
            Functor expression = expressions[i];
            boolean isFirstBody = i == 0;

            // Select a non-default built-in implementation to compile the functor with, if it is a built-in.
            BuiltIn builtIn;

            if (expression instanceof BuiltIn)
            {
                builtIn = (BuiltIn) expression;
            }
            else
            {
                builtIn = this;
            }

            // The 'isFirstBody' parameter is only set to true, when this is the first functor of a rule, which it
            // never is for a query.
            SizeableLinkedList<WAMInstruction> instructions = builtIn.compileBodyArguments(expression, false, fn, i);
            result.addInstructions(expression, instructions);

            // Queries are never chain rules, and as all permanent variables are preserved, bodies are never called
            // as last calls.
            instructions = builtIn.compileBodyCall(expression, isFirstBody, false, false, numPermanentVars);
            result.addInstructions(expression, instructions);
        }

        // Generate the postfix code for the clause.
        /*log.fine("DEALLOCATE");*/
        postFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.Suspend));
        postFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.Deallocate));

        result.addInstructions(postFixInstructions);

        // Run the optimizer on the output.
        result = optimizer.apply(result);

        displayCompiledQuery(result);

        observer.onQueryCompilation(result);
    }
private void compileQuery(Clause clause) throws SourceCodeException
    {
        // Used to build up the compiled result in.
        WAMCompiledQuery result;

        // A mapping from top stack frame slots to interned variable names is built up in this.
        // This is used to track the stack positions that variables in a query are assigned to.
        Map<Byte, Integer> varNames = new TreeMap<Byte, Integer>();

        // Used to keep track of registers as they are seen during compilation. The first time a variable is seen,
        // a variable is written onto the heap, subsequent times its value. The first time a functor is seen,
        // its structure is written onto the heap, subsequent times it is compared with.
        seenRegisters = new TreeSet<Integer>();

        // This is used to keep track of the next temporary register available to allocate.
        lastAllocatedTempReg = findMaxArgumentsInClause(clause);

        // This is used to keep track of the number of permanent variables.
        numPermanentVars = 0;

        // This is used to keep track of the allocation slot for the cut level variable, when needed. -1 means it is
        // not needed, so it is initialized to this.
        cutLevelVarSlot = -1;

        // These are used to generate pre and post instructions for the clause, for example, for the creation and
        // clean-up of stack frames.
        SizeableList<WAMInstruction> preFixInstructions = new SizeableLinkedList<WAMInstruction>();
        SizeableList<WAMInstruction> postFixInstructions = new SizeableLinkedList<WAMInstruction>();

        // Find all the free non-anonymous variables in the clause.
        Set<Variable> freeVars = TermUtils.findFreeNonAnonymousVariables(clause);
        Set<Integer> freeVarNames = new TreeSet<Integer>();

        for (Variable var : freeVars)
        {
            freeVarNames.add(var.getName());
        }

        // Allocate permanent variables for a query. In queries all variables are permanent so that they are preserved
        // on the stack upon completion of the query.
        allocatePermanentQueryRegisters(clause, varNames);

        // Gather information about the counts and positions of occurrence of variables and constants within the clause.
        gatherPositionAndOccurrenceInfo(clause);

        result = new WAMCompiledQuery(varNames, freeVarNames);

        // Generate the prefix code for the clause. Queries require a stack frames to hold their environment.
        /*log.fine("ALLOCATE " + numPermanentVars);*/
        preFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.AllocateN, REG_ADDR,
                (byte) (numPermanentVars & 0xff)));

        // Deep cuts require the current choice point to be kept in a permanent variable, so that it can be recovered
        // once deeper choice points or environments have been reached.
        if (cutLevelVarSlot >= 0)
        {
            /*log.fine("GET_LEVEL "+ cutLevelVarSlot);*/
            preFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.GetLevel, STACK_ADDR,
                    (byte) cutLevelVarSlot));
        }

        result.addInstructions(preFixInstructions);

        // Compile all of the conjunctive parts of the body of the clause, if there are any.
        Functor[] expressions = clause.getBody();

        // The current query does not have a name, so invent one for it.
        FunctorName fn = new FunctorName("tq", 0);

        for (int i = 0; i < expressions.length; i++)
        {
            Functor expression = expressions[i];
            boolean isFirstBody = i == 0;

            // Select a non-default built-in implementation to compile the functor with, if it is a built-in.
            BuiltIn builtIn;

            if (expression instanceof BuiltIn)
            {
                builtIn = (BuiltIn) expression;
            }
            else
            {
                builtIn = this;
            }

            // The 'isFirstBody' parameter is only set to true, when this is the first functor of a rule, which it
            // never is for a query.
            SizeableLinkedList<WAMInstruction> instructions = builtIn.compileBodyArguments(expression, false, fn, i);
            result.addInstructions(expression, instructions);

            // Queries are never chain rules, and as all permanent variables are preserved, bodies are never called
            // as last calls.
            instructions = builtIn.compileBodyCall(expression, isFirstBody, false, false, numPermanentVars);
            result.addInstructions(expression, instructions);
        }

        // Generate the postfix code for the clause.
        /*log.fine("DEALLOCATE");*/
        postFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.Suspend));
        postFixInstructions.add(new WAMInstruction(WAMInstruction.WAMInstructionSet.Deallocate));

        result.addInstructions(postFixInstructions);

        // Run the optimizer on the output.
        result = optimizer.apply(result);

        displayCompiledQuery(result);

        observer.onQueryCompilation(result);
    }
private void compileQuery ( Clause clause ) throws SourceCodeException { // Used to build up the compiled result in. WAMCompiledQuery result ; // A mapping from top stack frame slots to interned variable names is built up in this. // This is used to track the stack positions that variables in a query are assigned to. Map < Byte , Integer > varNames = new TreeMap < Byte , Integer > ( ) ; // Used to keep track of registers as they are seen during compilation. The first time a variable is seen, // a variable is written onto the heap, subsequent times its value. The first time a functor is seen, // its structure is written onto the heap, subsequent times it is compared with. seenRegisters = new TreeSet < Integer > ( ) ; // This is used to keep track of the next temporary register available to allocate. lastAllocatedTempReg = findMaxArgumentsInClause ( clause ) ; // This is used to keep track of the number of permanent variables. numPermanentVars = 0 ; // This is used to keep track of the allocation slot for the cut level variable, when needed. -1 means it is // not needed, so it is initialized to this. cutLevelVarSlot = - 1 ; // These are used to generate pre and post instructions for the clause, for example, for the creation and // clean-up of stack frames. SizeableList < WAMInstruction > preFixInstructions = new SizeableLinkedList < WAMInstruction > ( ) ; SizeableList < WAMInstruction > postFixInstructions = new SizeableLinkedList < WAMInstruction > ( ) ; // Find all the free non-anonymous variables in the clause. Set < Variable > freeVars = TermUtils . findFreeNonAnonymousVariables ( clause ) ; Set < Integer > freeVarNames = new TreeSet < Integer > ( ) ; for ( Variable var : freeVars ) { freeVarNames . add ( var . getName ( ) ) ; } // Allocate permanent variables for a query. In queries all variables are permanent so that they are preserved // on the stack upon completion of the query. allocatePermanentQueryRegisters ( clause , varNames ) ; // Gather information about the counts and positions of occurrence of variables and constants within the clause. gatherPositionAndOccurrenceInfo ( clause ) ; result = new WAMCompiledQuery ( varNames , freeVarNames ) ; // Generate the prefix code for the clause. Queries require a stack frames to hold their environment. /*log.fine("ALLOCATE " + numPermanentVars);*/ preFixInstructions . add ( new WAMInstruction ( WAMInstruction . WAMInstructionSet . AllocateN , REG_ADDR , ( byte ) ( numPermanentVars & 0xff ) ) ) ; // Deep cuts require the current choice point to be kept in a permanent variable, so that it can be recovered // once deeper choice points or environments have been reached. if ( cutLevelVarSlot >= 0 ) { /*log.fine("GET_LEVEL "+ cutLevelVarSlot);*/ preFixInstructions . add ( new WAMInstruction ( WAMInstruction . WAMInstructionSet . GetLevel , STACK_ADDR , ( byte ) cutLevelVarSlot ) ) ; } result . addInstructions ( preFixInstructions ) ; // Compile all of the conjunctive parts of the body of the clause, if there are any. Functor [ ] expressions = clause . getBody ( ) ; // The current query does not have a name, so invent one for it. FunctorName fn = new FunctorName ( "tq" , 0 ) ; for ( int i = 0 ; i < expressions . length ; i ++ ) { Functor expression = expressions [ i ] ; boolean isFirstBody = i == 0 ; // Select a non-default built-in implementation to compile the functor with, if it is a built-in. BuiltIn builtIn ; if ( expression instanceof BuiltIn ) { builtIn = ( BuiltIn ) expression ; } else { builtIn = this ; } // The 'isFirstBody' parameter is only set to true, when this is the first functor of a rule, which it // never is for a query. SizeableLinkedList < WAMInstruction > instructions = builtIn . compileBodyArguments ( expression , false , fn , i ) ; result . addInstructions ( expression , instructions ) ; // Queries are never chain rules, and as all permanent variables are preserved, bodies are never called // as last calls. instructions = builtIn . compileBodyCall ( expression , isFirstBody , false , false , numPermanentVars ) ; result . addInstructions ( expression , instructions ) ; } // Generate the postfix code for the clause. /*log.fine("DEALLOCATE");*/ postFixInstructions . add ( new WAMInstruction ( WAMInstruction . WAMInstructionSet . Suspend ) ) ; postFixInstructions . add ( new WAMInstruction ( WAMInstruction . WAMInstructionSet . Deallocate ) ) ; result . addInstructions ( postFixInstructions ) ; // Run the optimizer on the output. result = optimizer . apply ( result ) ; displayCompiledQuery ( result ) ; observer . onQueryCompilation ( result ) ; }
Compiles a clause as a query. The clause should have no head, only a body.

@param  clause The clause to compile as a query.

@throws SourceCodeException If there is an error in the source code preventing its compilation.
Compiles a clause as a query . The clause should have no head only a body .