morten      01/08/16 05:17:15

  Modified:    java/src/org/apache/xalan/xsltc/compiler IdKeyPattern.java
                        KeyCall.java Mode.java Output.java Parser.java
                        TestSeq.java xpath.cup
  Log:
  Forgot an 'import' in DupFilterIterator
  PR:           n/a
  Obtained from:        n/a
  Submitted by: [EMAIL PROTECTED]
  Reviewed by:  [EMAIL PROTECTED]
  
  Revision  Changes    Path
  1.4       +2 -8      
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/IdKeyPattern.java
  
  Index: IdKeyPattern.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/IdKeyPattern.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- IdKeyPattern.java 2001/06/17 12:23:29     1.3
  +++ IdKeyPattern.java 2001/08/16 12:17:15     1.4
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: IdKeyPattern.java,v 1.3 2001/06/17 12:23:29 curcuru Exp $
  + * @(#)$Id: IdKeyPattern.java,v 1.4 2001/08/16 12:17:15 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -69,7 +69,6 @@
   
   abstract class IdKeyPattern extends LocationPathPattern {
   
  -    private StepPattern _kernel = null;
       protected RelativePathPattern _left = null;;
       private String _index = null;
       private String _value = null;;
  @@ -93,15 +92,10 @@
       
       public void setLeft(RelativePathPattern left) {
        _left = left;
  -     _kernel = _left.getKernelPattern();
       }
   
  -    public void setKernelPattern(StepPattern kernel) {
  -     _kernel = kernel;
  -    }
  -
       public StepPattern getKernelPattern() {
  -     return(_kernel);
  +     return(null);
       }
       
       public void reduceKernelPattern() { }
  
  
  
  1.4       +31 -2     
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/KeyCall.java
  
  Index: KeyCall.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/KeyCall.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- KeyCall.java      2001/06/17 12:23:30     1.3
  +++ KeyCall.java      2001/08/16 12:17:15     1.4
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: KeyCall.java,v 1.3 2001/06/17 12:23:30 curcuru Exp $
  + * @(#)$Id: KeyCall.java,v 1.4 2001/08/16 12:17:15 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -78,6 +78,10 @@
        * Get the parameters passed to function:
        *   key(String name, String value)
        *   key(String name, NodeSet value)
  +     * The 'arguments' vector should contain two parameters for key() calls,
  +     * one holding the key name and one holding the value(s) to look up. The
  +     * vector has only one parameter for id() calls (the key name is always
  +     * "##id" for id() calls).
        */
       public KeyCall(QName fname, Vector arguments) {
        super(fname, arguments);
  @@ -97,7 +101,9 @@
       }
   
       /**
  -     *
  +     * Type check the parameters for the id() or key() function.
  +     * The index name (for key() call only) must be a string or convertable
  +     * to a string, and the lookup-value must be a string or a node-set.
        */
       public Type typeCheck(SymbolTable stable) throws TypeCheckError {
        final Type returnType = super.typeCheck(stable);
  @@ -133,6 +139,29 @@
        */
       public void translate(ClassGenerator classGen,
                          MethodGenerator methodGen) {
  +     final ConstantPoolGen cpg = classGen.getConstantPool();
  +     final InstructionList il = methodGen.getInstructionList();
  +
  +     final int dupInit = cpg.addMethodref(DUP_FILTERED_ITERATOR,
  +                                          "<init>",
  +                                          "("+NODE_ITERATOR_SIG+")V");
  +
  +     // Wrap the KeyIndex (iterator) inside a duplicate filter iterator to
  +     // pre-read the indexed nodes and cache them.
  +     il.append(new NEW(cpg.addClass(DUP_FILTERED_ITERATOR)));
  +     il.append(DUP);
  +
  +     translateCall(classGen, methodGen);
  +
  +     il.append(new INVOKESPECIAL(dupInit));
  +    }
  +
  +    /**
  +     * Translate the actual index lookup - leaves KeyIndex (iterator) on 
stack
  +     */
  +    public void translateCall(ClassGenerator classGen,
  +                           MethodGenerator methodGen) {
  +
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = methodGen.getInstructionList();
   
  
  
  
  1.4       +176 -104  
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Mode.java
  
  Index: Mode.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Mode.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Mode.java 2001/07/10 17:45:19     1.3
  +++ Mode.java 2001/08/16 12:17:15     1.4
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Mode.java,v 1.3 2001/07/10 17:45:19 morten Exp $
  + * @(#)$Id: Mode.java,v 1.4 2001/08/16 12:17:15 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -78,110 +78,163 @@
    * for generating an appropriate applyTemplates + (mode name) function
    */
   final class Mode implements Constants {
  -    private final QName _name;
  -    
  -    // the owning stylesheet
  -    private final Stylesheet _stylesheet;
   
  -    private final String _functionName;
  -    
  -    // all the templates in this mode
  -    private final Vector _templates = new Vector();
  -    
  -    // Patterns/test sequences for the stylesheet's templates
  -    private Vector[]  _patternGroups = new Vector[32];
  -    private TestSeq[] _code2TestSeq;
  -    // Pattern/test sequence for pattern with 'node()' kernel
  +    private final QName      _name;       // The QName of this mode
  +    private final Stylesheet _stylesheet; // The owning stylesheet
  +    private final String     _methodName; // The method name for this mode
  +    private final Vector     _templates;  // All templates in this mode
  +
  +    // Pattern/test sequence for pattern with node()-type kernel
       private Vector    _nodeGroup = null;
       private TestSeq   _nodeTestSeq = null;
   
  -    private int _currentIndex;
  +    // Pattern/test sequence for pattern with id() or key()-type kernel
  +    private Vector    _idxGroup = null;
  +    private TestSeq   _idxTestSeq = null;
  +
  +    // Pattern/test sequence for patterns with any other kernel type
  +    private Vector[]  _patternGroups;
  +    private TestSeq[] _testSeq;
   
       private final Hashtable _neededTemplates = new Hashtable();
       private final Hashtable _namedTemplates = new Hashtable();
  -    private final Hashtable _templateInstructionHandles = new Hashtable();
  -    private final Hashtable _templateInstructionLists = new Hashtable();
  -    private LocationPathPattern _explicitRootPattern = null;
  -     
  +    private final Hashtable _templateIHs = new Hashtable();
  +    private final Hashtable _templateILs = new Hashtable();
  +    private LocationPathPattern _rootPattern = null;
  +
  +    // Variable index for the current node - used in code generation
  +    private int _currentIndex;
  +
  +
  +    /**
  +     * Creates a new Mode
  +     * @param name A textual representation of the mode's QName
  +     * @param stylesheet The Stylesheet in which the mode occured
  +     * @param suffix A suffix to append to the method name for this mode
  +     *               (normally a sequence number - still in a String).
  +     */
       public Mode(QName name, Stylesheet stylesheet, String suffix) {
  +     // Save global info
        _name = name;
        _stylesheet = stylesheet;
  -     _functionName = APPLY_TEMPLATES + suffix;
  +     _methodName = APPLY_TEMPLATES + suffix;
  +     // Initialise some data structures
  +     _templates = new Vector();
  +     _patternGroups = new Vector[32];
       }
   
  +    /**
  +     * Returns the name of the method (_not_ function) that will be compiled
  +     * for this mode. Normally takes the form 'applyTemplates()' or
  +     * 'applyTemplates2()'.
  +     * @return Method name for this mode
  +     */
       public String functionName() {
  -     return _functionName;
  +     return _methodName;
       }
   
  +    /**
  +     * Shortcut to get the class compiled for this mode (will be inlined).
  +     */
       private String getClassName() {
        return _stylesheet.getClassName();
       }
   
  +    /**
  +     * Add a template to this mode
  +     * @param template The template to add
  +     */
       public void addTemplate(Template template) {
        _templates.addElement(template);
  -     Util.println("added template, pattern: "+ template.getPattern());
       }
   
  +    /**
  +     * Process all the test patterns in this mode
  +     */
       public void processPatterns(Hashtable keys) {
        // Traverse all templates
        final Enumeration templates = _templates.elements();
        while (templates.hasMoreElements()) {
  +         // Get the next template
            final Template template = (Template)templates.nextElement();
  -         // Is this a named template?
  -         if (template.isNamed()) {
  -             // Only process template with highest priority when there
  -             // are multiple templates with the sanme name
  -             if (!template.disabled()) _namedTemplates.put(template, this);
  -         }
  -         processTemplatePattern(template,keys);
  +
  +         // Add this template to a table of named templates if it has a name.
  +         // If there are multiple templates with the same name, all but one
  +         // (the one with highest priority) will be disabled.
  +         if (template.isNamed() && !template.disabled())
  +             _namedTemplates.put(template, this);
  +
  +         // Add this template to a test sequence if it has a pattern
  +         final Pattern pattern = template.getPattern();
  +         if (pattern != null) flattenAlternative(pattern, template, keys);
        }
        prepareTestSequences();
       }
  -             
  -    private void processTemplatePattern(Template template, Hashtable keys) {
  -     final Pattern matchPattern = template.getPattern();
  -     if (matchPattern != null)
  -         flattenAlternative(matchPattern, template, keys);
  -    }
  -             
  +
  +    /**
  +     * This method will break up alternative patterns (ie. unions of 
patterns,
  +     * such as match="A/B | C/B") and add the basic patterns to their
  +     * respective pattern groups.
  +     */
       private void flattenAlternative(Pattern pattern,
                                    Template template,
                                    Hashtable keys) {
  -
  +     // Patterns on type id() and key() are special since they do not have
  +     // any kernel node type (it can be anything as long as the node is in
  +     // the id's or key's index).
        if (pattern instanceof IdKeyPattern) {
  -         // TODO: Cannot handle this kind of core pattern yet!!!
  +         final IdKeyPattern idkey = (IdKeyPattern)pattern;
  +         idkey.setTemplate(template);
  +         if (_idxGroup == null) _idxGroup = new Vector();
  +         _idxGroup.add(pattern);
        }
  +     // Alternative patterns are broken up and re-processed recursively
        else if (pattern instanceof AlternativePattern) {
            final AlternativePattern alt = (AlternativePattern)pattern;
            flattenAlternative(alt.getLeft(), template, keys);
            flattenAlternative(alt.getRight(), template, keys);
        }
  +     // Finally we have a pattern that can be added to a test sequence!
        else if (pattern instanceof LocationPathPattern) {
            final LocationPathPattern lpp = (LocationPathPattern)pattern;
            lpp.setTemplate(template);
            addPatternToGroup(lpp);
        }
  -     else
  -         Util.println("Bad pattern: " + pattern);
       }
  -    
  -    private void addPattern(int code, LocationPathPattern pattern) {
  -     if (code >= _patternGroups.length) {
  -         Vector[] newGroups = new Vector[code*2];
  -         System.arraycopy(_patternGroups, 0, newGroups, 0,
  -                          _patternGroups.length);
  +
  +    /**
  +     * Adds a pattern to a pattern group
  +     */
  +    private void addPattern(int kernelType, LocationPathPattern pattern) {
  +
  +     // Make sure the array of pattern groups is long enough
  +     final int oldLength = _patternGroups.length;
  +     if (kernelType >= oldLength) {
  +         Vector[] newGroups = new Vector[kernelType * 2];
  +         System.arraycopy(_patternGroups, 0, newGroups, 0, oldLength);
            _patternGroups = newGroups;
        }
  -     
  -     Vector patterns = code == -1
  -         ? _nodeGroup        // node()
  -         : _patternGroups[code];
        
  +     // Find the vector to put this pattern into
  +     Vector patterns;
  +
  +     // Use the vector for id()/key()/node() patterns if no kernel type
  +     if (kernelType == -1)
  +         patterns = _nodeGroup;
  +     else
  +         patterns = _patternGroups[kernelType];
  +
  +     // Create a new vector if needed and insert the very first pattern
        if (patterns == null) {
            patterns = new Vector(2);
            patterns.addElement(pattern);
  +         if (kernelType == -1)
  +             _nodeGroup = patterns;
  +         else
  +             _patternGroups[kernelType] = patterns;
        }
  -     else {  // keep patterns ordered by diminishing precedence/priorities
  +     // Otherwise make sure patterns are ordered by precedence/priorities
  +     else {
            boolean inserted = false;
            for (int i = 0; i < patterns.size(); i++) {
                final LocationPathPattern lppToCompare =
  @@ -196,12 +249,6 @@
                patterns.addElement(pattern);
            }
        }
  -     if (code == -1) {
  -         _nodeGroup = patterns;
  -     }
  -     else {
  -         _patternGroups[code] = patterns;
  -     }
       }
       
       /**
  @@ -209,14 +256,21 @@
        * Keep them sorted by priority within group
        */
       private void addPatternToGroup(final LocationPathPattern lpp) {
  -     // kernel pattern is the last (maybe only) Step
  -     final StepPattern kernel = lpp.getKernelPattern();
  -     if (kernel != null) {
  -         addPattern(kernel.getNodeType(), lpp);
  -     }
  -     else if (_explicitRootPattern == null ||
  -              lpp.noSmallerThan(_explicitRootPattern)) {
  -         _explicitRootPattern = lpp;
  +     // id() and key()-type patterns do not have a kernel type
  +     if (lpp instanceof IdKeyPattern) {
  +         addPattern(-1, lpp);
  +     }
  +     // Otherwise get the kernel pattern from the LPP
  +     else {
  +         // kernel pattern is the last (maybe only) Step
  +         final StepPattern kernel = lpp.getKernelPattern();
  +         if (kernel != null) {
  +             addPattern(kernel.getNodeType(), lpp);
  +         }
  +         else if (_rootPattern == null ||
  +                  lpp.noSmallerThan(_rootPattern)) {
  +             _rootPattern = lpp;
  +         }
        }
       }
   
  @@ -225,7 +279,7 @@
        */
       private void prepareTestSequences() {
        final Vector names = _stylesheet.getXSLTC().getNamesIndex();
  -     _code2TestSeq = new TestSeq[DOM.NTYPES + names.size()];
  +     _testSeq = new TestSeq[DOM.NTYPES + names.size()];
        
        final int n = _patternGroups.length;
        for (int i = 0; i < n; i++) {
  @@ -233,7 +287,7 @@
            if (patterns != null) {
                final TestSeq testSeq = new TestSeq(patterns, this);
                testSeq.reduce();
  -             _code2TestSeq[i] = testSeq;
  +             _testSeq[i] = testSeq;
                testSeq.findTemplates(_neededTemplates);
            }
        }
  @@ -243,10 +297,16 @@
            _nodeTestSeq.reduce();
            _nodeTestSeq.findTemplates(_neededTemplates);
        }
  +
  +     if ((_idxGroup != null) && (_idxGroup.size() > 0)) {
  +         _idxTestSeq = new TestSeq(_idxGroup, this);
  +         _idxTestSeq.reduce();
  +         _idxTestSeq.findTemplates(_neededTemplates);
  +     }
        
  -     if (_explicitRootPattern != null) {
  +     if (_rootPattern != null) {
            // doesn't matter what is 'put', only key matters
  -         _neededTemplates.put(_explicitRootPattern.getTemplate(), this);
  +         _neededTemplates.put(_rootPattern.getTemplate(), this);
        }
       }
   
  @@ -305,12 +365,12 @@
                // !!! TODO templates both named and matched
                InstructionList til = template.compile(classGen, methodGen);
                til.append(new GOTO_W(next));
  -             _templateInstructionLists.put(template, til);
  -             _templateInstructionHandles.put(template, til.getStart());
  +             _templateILs.put(template, til);
  +             _templateIHs.put(template, til.getStart());
            }
            else {
                // empty template
  -             _templateInstructionHandles.put(template, next);
  +             _templateIHs.put(template, next);
            }
        }
       }
  @@ -319,7 +379,7 @@
        final Enumeration templates = _neededTemplates.keys();
        while (templates.hasMoreElements()) {
            final Object iList =
  -             _templateInstructionLists.get(templates.nextElement());
  +             _templateILs.get(templates.nextElement());
            if (iList != null) {
                body.append((InstructionList)iList);
            }
  @@ -327,9 +387,9 @@
       }
   
       private void appendTestSequences(InstructionList body) {
  -     final int n = _code2TestSeq.length;
  +     final int n = _testSeq.length;
        for (int i = 0; i < n; i++) {
  -         final TestSeq testSeq = _code2TestSeq[i];
  +         final TestSeq testSeq = _testSeq[i];
            if (testSeq != null) {
                InstructionList il = testSeq.getInstructionList();
                if (il != null)
  @@ -357,7 +417,6 @@
        */
       private InstructionList compileDefaultRecursion(ClassGenerator classGen,
                                                    MethodGenerator methodGen,
  -                                                 int node,
                                                    InstructionHandle next) {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = new InstructionList();
  @@ -373,7 +432,7 @@
        il.append(methodGen.loadDOM());
        
        il.append(methodGen.loadDOM());
  -     il.append(new ILOAD(node));
  +     il.append(new ILOAD(_currentIndex));
        il.append(new INVOKEVIRTUAL(getChildren));
        il.append(methodGen.loadHandler());
        il.append(new INVOKEVIRTUAL(applyTemplates));
  @@ -387,13 +446,12 @@
        */
       private InstructionList compileDefaultText(ClassGenerator classGen,
                                               MethodGenerator methodGen,
  -                                            int node,
                                               InstructionHandle next) {
        final ConstantPoolGen cpg = classGen.getConstantPool();
        final InstructionList il = new InstructionList();
        final String DOM_CLASS = classGen.getDOMClass();
        il.append(methodGen.loadDOM());
  -     il.append(new ILOAD(node));
  +     il.append(new ILOAD(_currentIndex));
        il.append(methodGen.loadHandler());
        il.append(new INVOKEVIRTUAL(cpg.addMethodref(DOM_CLASS,
                                                     CHARACTERS,
  @@ -438,10 +496,10 @@
                    String namespace = name.substring(0,name.lastIndexOf(':'));
                    final int type = xsltc.registerNamespace(namespace);
                    
  -                 if ((i < _code2TestSeq.length) &&
  -                     (_code2TestSeq[i] != null)) {
  +                 if ((i < _testSeq.length) &&
  +                     (_testSeq[i] != null)) {
                        targets[type] =
  -                         (_code2TestSeq[i]).compile(classGen,
  +                         (_testSeq[i]).compile(classGen,
                                                       methodGen,
                                                       defaultTarget);
                        compiled = true;
  @@ -535,22 +593,22 @@
        ilLoop.append(methodGen.nextNode());
        ilLoop.append(DUP);
        ilLoop.append(new ISTORE(_currentIndex));
  +
        // The body of this code can get very large - large than can be handled
        // by a single IFNE(body.getStart()) instruction - need workaround:
           final BranchHandle ifeq = ilLoop.append(new IFEQ(null));
  -     ilLoop.append(new GOTO_W(body.getStart()));
  -     ifeq.setTarget(ilLoop.append(NOP));
  -
  +     final BranchHandle loop = ilLoop.append(new GOTO_W(null));
  +     ifeq.setTarget(ilLoop.append(RETURN)); // applyTemplates() ends here!
        final InstructionHandle ihLoop = ilLoop.getStart();
   
        // (*) Compile default handling of elements (traverse children)
        InstructionList ilRecurse =
  -       compileDefaultRecursion(classGen, methodGen, _currentIndex, ihLoop);
  +         compileDefaultRecursion(classGen, methodGen, ihLoop);
        InstructionHandle ihRecurse = ilRecurse.getStart();
   
        // (*) Compile default handling of text/attribute nodes (output text)
  -     InstructionList ilText = compileDefaultText(classGen, methodGen,
  -                                                 _currentIndex, ihLoop);
  +     InstructionList ilText =
  +         compileDefaultText(classGen, methodGen, ihLoop);
        InstructionHandle ihText = ilText.getStart();
   
        // Distinguish attribute/element/namespace tests for further processing
  @@ -569,17 +627,27 @@
        compileTemplates(classGen, methodGen, ihLoop);
   
        // (*) Handle template with explicit "*" pattern
  -     final TestSeq elemTest = _code2TestSeq[DOM.ELEMENT];
  +     final TestSeq elemTest = _testSeq[DOM.ELEMENT];
        InstructionHandle ihElem = ihRecurse;
        if (elemTest != null)
            ihElem = elemTest.compile(classGen, methodGen, ihRecurse);
   
        // (*) Handle template with explicit "@*" pattern
  -     final TestSeq attrTest = _code2TestSeq[DOM.ATTRIBUTE];
  +     final TestSeq attrTest = _testSeq[DOM.ATTRIBUTE];
        InstructionHandle ihAttr = ihText;
        if (attrTest != null)
            ihAttr = attrTest.compile(classGen, methodGen, ihText);
   
  +     // Do tests for id() and key() patterns first
  +     InstructionList ilKey = null;
  +     if (_idxTestSeq != null) {
  +         loop.setTarget(_idxTestSeq.compile(classGen, methodGen, 
body.getStart()));
  +         ilKey = _idxTestSeq.getInstructionList();
  +     }
  +     else {
  +         loop.setTarget(body.getStart());
  +     }
  +
        // (*) If there is a match on node() we need to replace ihElem
        //     and ihText (default behaviour for elements & text).
        if (_nodeTestSeq != null) {
  @@ -612,7 +680,7 @@
        // (*) Handle templates with "ns:elem" or "ns:@attr" pattern
        final InstructionHandle[] targets = new InstructionHandle[types.length];
        for (int i = DOM.NTYPES; i < targets.length; i++) {
  -         final TestSeq testSeq = _code2TestSeq[i];
  +         final TestSeq testSeq = _testSeq[i];
            // Jump straight to namespace tests ?
            if (isNamespace[i]) {
                if (isAttribute[i])
  @@ -635,13 +703,13 @@
        }
   
        // Handle pattern with match on root node - default: traverse children
  -     targets[DOM.ROOT] = _explicitRootPattern != null
  -         ? getTemplateInstructionHandle(_explicitRootPattern.getTemplate())
  +     targets[DOM.ROOT] = _rootPattern != null
  +         ? getTemplateInstructionHandle(_rootPattern.getTemplate())
            : ihRecurse;
        
        // Handle any pattern with match on text nodes - default: output text
  -     targets[DOM.TEXT] = _code2TestSeq[DOM.TEXT] != null
  -         ? _code2TestSeq[DOM.TEXT].compile(classGen, methodGen, ihText)
  +     targets[DOM.TEXT] = _testSeq[DOM.TEXT] != null
  +         ? _testSeq[DOM.TEXT].compile(classGen, methodGen, ihText)
            : ihText;
   
        // This DOM-type is not in use - default: process next node
  @@ -655,19 +723,19 @@
   
        // Match on processing instruction - default: process next node
        targets[DOM.PROCESSING_INSTRUCTION] =
  -         _code2TestSeq[DOM.PROCESSING_INSTRUCTION] != null
  -         ? _code2TestSeq[DOM.PROCESSING_INSTRUCTION]
  +         _testSeq[DOM.PROCESSING_INSTRUCTION] != null
  +         ? _testSeq[DOM.PROCESSING_INSTRUCTION]
            .compile(classGen, methodGen, ihLoop)
            : ihLoop;
        
        // Match on comments - default: process next node
  -     targets[DOM.COMMENT] = _code2TestSeq[DOM.COMMENT] != null
  -         ? _code2TestSeq[DOM.COMMENT].compile(classGen, methodGen, ihLoop)
  +     targets[DOM.COMMENT] = _testSeq[DOM.COMMENT] != null
  +         ? _testSeq[DOM.COMMENT].compile(classGen, methodGen, ihLoop)
            : ihLoop;
   
        // Now compile test sequences for various match patterns:
        for (int i = DOM.NTYPES; i < targets.length; i++) {
  -         final TestSeq testSeq = _code2TestSeq[i];
  +         final TestSeq testSeq = _testSeq[i];
            // Jump straight to namespace tests ?
            if ((testSeq == null) || (isNamespace[i])) {
                if (isAttribute[i])
  @@ -686,14 +754,17 @@
            }
        }
   
  +     if (ilKey != null) body.insert(ilKey);
  +
        // Append first code in applyTemplates() - get type of current node
        body.append(methodGen.loadDOM());
        body.append(new ILOAD(_currentIndex));
        body.append(new INVOKEVIRTUAL(cpg.addMethodref(DOM_CLASS,
                                                       "getType", "(I)I")));
  -     
  +
        // Append switch() statement - main dispatch loop in applyTemplates()
  -     body.append(new SWITCH(types, targets, ihLoop));
  +     InstructionHandle disp = body.append(new SWITCH(types, targets, 
ihLoop));
  +
        // Append all the "case:" statements
        appendTestSequences(body);
        // Append the actual template code
  @@ -714,7 +785,6 @@
        mainIL.append(body);
        // fall through to ilLoop
        mainIL.append(ilLoop);
  -     mainIL.append(RETURN);
   
        peepHoleOptimization(methodGen);
        methodGen.stripAttributes(true);
  @@ -794,6 +864,7 @@
        }
   
        // Removes uncessecary GOTOs
  +     /*
        pattern = "`GOTO'`GOTO'`Instruction'";
        ih = find.search(pattern);
        while (ih != null) {
  @@ -815,11 +886,12 @@
            }
            ih = find.search(pattern, match[2]);
        }
  +     */
        
        
       }
   
       public InstructionHandle getTemplateInstructionHandle(Template template) 
{
  -     return (InstructionHandle)_templateInstructionHandles.get(template);
  +     return (InstructionHandle)_templateIHs.get(template);
       }
   }
  
  
  
  1.7       +9 -11     
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Output.java
  
  Index: Output.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Output.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Output.java       2001/08/14 09:16:45     1.6
  +++ Output.java       2001/08/16 12:17:15     1.7
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Output.java,v 1.6 2001/08/14 09:16:45 morten Exp $
  + * @(#)$Id: Output.java,v 1.7 2001/08/16 12:17:15 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -233,16 +233,14 @@
        }
   
        // Set system/public doctype only if both are set
  -     if (_doctypeSystem != null) {
  -         field = cpg.addFieldref(TRANSLET_CLASS,"_doctypeSystem",STRING_SIG);
  -         il.append(DUP);
  -         il.append(new PUSH(cpg, _doctypeSystem));
  -         il.append(new PUTFIELD(field));
  -         field = cpg.addFieldref(TRANSLET_CLASS,"_doctypePublic",STRING_SIG);
  -         il.append(DUP);
  -         il.append(new PUSH(cpg, _doctypePublic));
  -         il.append(new PUTFIELD(field));
  -     }
  +     field = cpg.addFieldref(TRANSLET_CLASS,"_doctypeSystem",STRING_SIG);
  +     il.append(DUP);
  +     il.append(new PUSH(cpg, _doctypeSystem));
  +     il.append(new PUTFIELD(field));
  +     field = cpg.addFieldref(TRANSLET_CLASS,"_doctypePublic",STRING_SIG);
  +     il.append(DUP);
  +     il.append(new PUSH(cpg, _doctypePublic));
  +     il.append(new PUTFIELD(field));
        
        // Add 'medye-type' decaration to output - if used
        if (_mediaType != null) {
  
  
  
  1.23      +7 -3      
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java
  
  Index: Parser.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Parser.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Parser.java       2001/08/14 11:51:26     1.22
  +++ Parser.java       2001/08/16 12:17:15     1.23
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Parser.java,v 1.22 2001/08/14 11:51:26 morten Exp $
  + * @(#)$Id: Parser.java,v 1.23 2001/08/16 12:17:15 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -279,8 +279,8 @@
            else {
                QName name = (QName)space.get(localname);
                if (name == null) {
  -                 space.put(localname,
  -                           name = new QName(namespace, prefix, localname));
  +                 name = new QName(namespace, prefix, localname);
  +                 space.put(localname, name);
                }
                return name;
            }
  @@ -890,6 +890,10 @@
            } 
            reportError(Constants.ERROR,
                new ErrorMsg(ErrorMsg.XPATHPAR_ERR, line, expression));
  +     }
  +     catch (ClassCastException e) {
  +         reportError(Constants.ERROR,
  +                     new ErrorMsg(ErrorMsg.XPATHPAR_ERR, line, expression));
        }
        catch (Exception e) {
            if (_xsltc.debug()) {
  
  
  
  1.3       +134 -71   
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/TestSeq.java
  
  Index: TestSeq.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/TestSeq.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TestSeq.java      2001/07/10 17:45:30     1.2
  +++ TestSeq.java      2001/08/16 12:17:15     1.3
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: TestSeq.java,v 1.2 2001/07/10 17:45:30 morten Exp $
  + * @(#)$Id: TestSeq.java,v 1.3 2001/08/16 12:17:15 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -59,6 +59,7 @@
    * @author Jacek Ambroziak
    * @author Santiago Pericas-Geertsen
    * @author Erwin Bolwidt <[EMAIL PROTECTED]>
  + * @author Morten Jorgensen <[EMAIL PROTECTED]>
    *
    */
   
  @@ -73,124 +74,186 @@
   import org.apache.xalan.xsltc.compiler.util.*;
   
   final class TestSeq {
  -    private Vector _patterns;
  -    private final Mode _mode;
  -    // template to instantiate when all (reduced) tests fail
  -    // and the sequence is not extended
  -    // when the _template is null, control should go to 'NextNode'
  -    private Template _template = null;
  +
  +    /*
  +     * A test sequence is a sequence of patterns that
  +     *
  +     *  (1) occured in templates in the same mode
  +     *  (2) share the same kernel node type (such as A/B and C/C/B).
  +     *
  +     * A test sequence may have a default template, which will be run if
  +     * none of the patterns do not match. This template is always a template
  +     * that matches solely on the shared kernel node type.
  +     */
  +    private Vector   _patterns = null; // all patterns
  +    private Mode     _mode     = null; // the shared mode
  +    private Template _default  = null; // the default template
  +
       private InstructionList _instructionList;
  -     
  +
  +    /**
  +     * Creates a new test sequence, given a set of patterns and a mode.
  +     */
       public TestSeq(Vector patterns, Mode mode) {
        _patterns = patterns;
        _mode = mode;
       }
   
  +    /**
  +     * The priority is only calculated if the test sequence has a default
  +     * template. This is bad, bad, bad. We should get the priority from the
  +     * other templates that make up the test sequence.
  +     */
       public double getPriority() {
  -     if (_template == null)
  -         return(Double.NaN);
  -     else
  -         return(_template.getPriority());
  +     double prio = Double.MIN_VALUE;
  +     final int count = _patterns.size();
  +     for (int i = 0; i < count; i++) {
  +         final Pattern pattern = (Pattern)_patterns.elementAt(i);
  +         final Template template = pattern.getTemplate();
  +         final double tp = template.getPriority();
  +         if (tp > prio) prio = tp;
  +     }
  +     return prio;
       }
   
  +    /**
  +     * This method should return the last position of any template included
  +     * in this test sequence.
  +     */
       public int getPosition() {
  -     if (_template == null)
  -         return(0);
  -     else
  -         return(_template.getPosition());
  +     int pos = Integer.MIN_VALUE;
  +     final int count = _patterns.size();
  +     for (int i = 0; i < count; i++) {
  +         final Pattern pattern = (Pattern)_patterns.elementAt(i);
  +         final Template template = pattern.getTemplate();
  +         final int tp = template.getPosition();
  +         if (tp > pos) pos = tp;
  +     }
  +     return pos;
       }
        
  -    // careful with test ordering
  +    /**
  +     * Reduce the patterns in this test sequence to exclude the shared
  +     * kernel node type. After the switch() in the translet's 
applyTemplates()
  +     * we already know that we have a hit for the kernel node type, we only
  +     * have the check the rest of the pattens.
  +     */
       public void reduce() {
  -     final int nPatterns = _patterns.size();
  -     for (int i = 0; i < nPatterns; i++)
  -         Util.println(_patterns.elementAt(i).toString());
        final Vector newPatterns = new Vector();
  -     for (int i = 0; i < nPatterns; i++) {
  +     final int count = _patterns.size();
  +
  +     // Traverse the existing set of patterns (they are in prioritised order)
  +     for (int i = 0; i < count; i++) {
            final LocationPathPattern pattern =
                (LocationPathPattern)_patterns.elementAt(i);
  +         // Reduce this pattern (get rid of kernel node type)
            pattern.reduceKernelPattern();
                        
  -         // we only retain nontrivial reduced patterns
  -         // also, anything that could follow a trivial pattern
  -         // can be omitted
  +         // Add this pattern to the new vector of patterns.
            if (!pattern.isWildcard()) {
                newPatterns.addElement(pattern);
            }
  +         // Set template as default if its pattern matches purely on kernel
            else {
  -             // failure of the previous test falls through to this fully
  -             // reduced test, succeeding by definition and branching
  -             // unconditionally to the test's template
  -             _template = pattern.getTemplate();
  +             _default = pattern.getTemplate();
  +             // Following patterns can be ignored since default has priority
                break;
            }
        }
        _patterns = newPatterns;
  -     //Util.println("patterns after reduction");
  -     for (int i = 0; i < _patterns.size(); i++)
  -         Util.println(_patterns.elementAt(i).toString());
       }
  -     
  +
  +    /**
  +     * Returns, by reference, the templates that are included in this test
  +     * sequence. Remember that a single template can occur in several test
  +     * sequences if its pattern is a union (ex. match="A/B | A/C").
  +     */
       public void findTemplates(Dictionary templates) {
  -     if (_template != null)
  -         templates.put(_template, this);
  +     if (_default != null)
  +         templates.put(_default, this);
        for (int i = 0; i < _patterns.size(); i++) {
            final LocationPathPattern pattern =
                (LocationPathPattern)_patterns.elementAt(i);
            templates.put(pattern.getTemplate(), this);
        }
       }
  -     
  +
  +    /**
  +     * Get the instruction handle to a template's code. This is used when
  +     * a single template occurs in several test sequences; that is, if its
  +     * pattern is a union of patterns (ex. match="A/B | A/C").
  +     */
       private InstructionHandle getTemplateHandle(Template template) {
        return (InstructionHandle)_mode.getTemplateInstructionHandle(template);
       }
   
  +    /**
  +     * Returns pattern n in this test sequence
  +     */
       private LocationPathPattern getPattern(int n) {
        return (LocationPathPattern)_patterns.elementAt(n);
       }
   
  +    /**
  +     * Copile the code for this test sequence. The code will first test for
  +     * the pattern with the highest priority, then go on to the next ones,
  +     * until it hits or finds the default template.
  +     */
       public InstructionHandle compile(ClassGenerator classGen,
                                     MethodGenerator methodGen,
                                     InstructionHandle continuation) {
  -     if (_patterns.size() == 0) {
  -         //Util.println("compiling trivial testseq " + _template);
  -         return getTemplateHandle(_template);
  -     }
  -     else {
  -         // 'fail' represents a branch to go to when test fails
  -         // it is updated in each iteration so that the tests
  -         // are linked together in the 
  -         // if elseif elseif ... else fashion
  -         InstructionHandle fail = _template == null
  -             ? continuation
  -             : getTemplateHandle(_template);
  -                     
  -         for (int n = _patterns.size() - 1; n >= 0; n--) {
  -             final LocationPathPattern pattern = getPattern(n);
  -             final InstructionList il = new InstructionList();
  -             // patterns expect current node on top of stack
  -             il.append(methodGen.loadCurrentNode());
  -             // apply the actual pattern
  -             il.append(pattern.compile(classGen, methodGen));
  -             // on success (fallthrough) goto template code
  -             final Template template = pattern.getTemplate();
  -             final InstructionHandle gtmpl = getTemplateHandle(template);
  -             final InstructionHandle success = il.append(new GOTO_W(gtmpl));
  -
  -             pattern.backPatchTrueList(success);
  -             pattern.backPatchFalseList(fail);
  -             // the failure of the preceding test will lead to this test
  -             fail = il.getStart();
  -             if (_instructionList != null) {
  -                 il.append(_instructionList);
  -             }
  -             _instructionList = il;
  -         }
  -         return fail;
  +
  +     final int count = _patterns.size();
  +
  +     // EZ DC if there is only one (default) pattern
  +     if (count == 0) getTemplateHandle(_default);
  +
  +     // The 'fail' instruction handle represents a branch to go to when
  +     // test fails. It is updated in each iteration, so that the tests
  +     // are linked together in the  if-elseif-elseif-else fashion.
  +     InstructionHandle fail;
  +
  +     // Initialize 'fail' to either the code for the default template
  +     if (_default != null)
  +         fail = getTemplateHandle(_default);
  +     // ..or if that does not exist, to a location set by the caller.
  +     else
  +         fail = continuation;
  +
  +     for (int n = (count - 1); n >= 0; n--) {
  +         final LocationPathPattern pattern = getPattern(n);
  +         final Template template = pattern.getTemplate();
  +         final InstructionList il = new InstructionList();
  +
  +         // Patterns expect current node on top of stack
  +         il.append(methodGen.loadCurrentNode());
  +         // Apply the test-code compiled for the pattern
  +         il.append(pattern.compile(classGen, methodGen));
  +
  +         // On success branch to the template code
  +         final InstructionHandle gtmpl = getTemplateHandle(template);
  +         final InstructionHandle success = il.append(new GOTO_W(gtmpl));
  +         pattern.backPatchTrueList(success);
  +         pattern.backPatchFalseList(fail);
  +
  +         // We're working backwards here. The next pattern's 'fail' target
  +         // is this pattern's first instruction
  +         fail = il.getStart();
  +
  +         // Append existing instruction list to the end of this one
  +         if (_instructionList != null) il.append(_instructionList);
  +
  +         // Set current instruction list to be this one.
  +         _instructionList = il;
        }
  +     return fail;
       }
  -     
  +
  +    /**
  +     * Returns the instruction list for this test sequence
  +     */
       public InstructionList getInstructionList() {
        return _instructionList;
       }
  +
   }
  
  
  
  1.8       +3 -2      
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/xpath.cup
  
  Index: xpath.cup
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/xpath.cup,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- xpath.cup 2001/08/15 19:25:43     1.7
  +++ xpath.cup 2001/08/16 12:17:15     1.8
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: xpath.cup,v 1.7 2001/08/15 19:25:43 tmiller Exp $
  + * @(#)$Id: xpath.cup,v 1.8 2001/08/16 12:17:15 morten Exp $
    *
    * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved.
    * 
  @@ -85,7 +85,8 @@
                       return(NodeTest.ELEMENT);
                   else if (local.equals("@*"))
                       return(NodeTest.ATTRIBUTE);
  -                name = new QName(null,null,local);
  +             if (local.startsWith("@"))
  +                    name = new QName(null,null,local);
               }
            return axis == Axis.ATTRIBUTE
                ? _xsltc.registerAttribute(name)
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to