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