You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mo...@apache.org on 2001/08/16 14:17:15 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler IdKeyPattern.java KeyCall.java Mode.java Output.java Parser.java TestSeq.java xpath.cup

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:	morten@xml.apache.org
  Reviewed by:	morten@xml.apache.org
  
  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 <ej...@klomp.org>
  + * @author Morten Jorgensen <mo...@sun.com>
    *
    */
   
  @@ -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: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org