santiagopg 2002/07/29 14:30:52
Modified: java/src/org/apache/xalan/xsltc/compiler Expression.java
FlowList.java Mode.java StepPattern.java
TestSeq.java
Log:
Fix for Bugzilla 11166.
Revision Changes Path
1.14 +9 -1
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Expression.java
Index: Expression.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Expression.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- Expression.java 26 Jun 2002 21:25:35 -0000 1.13
+++ Expression.java 29 Jul 2002 21:30:51 -0000 1.14
@@ -214,6 +214,14 @@
_falseList.add(il.append(new IFEQ(null)));
}
+ public FlowList getFalseList() {
+ return _falseList;
+ }
+
+ public FlowList getTrueList() {
+ return _trueList;
+ }
+
public void backPatchFalseList(InstructionHandle ih) {
_falseList.backPatch(ih);
}
1.3 +31 -1
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FlowList.java
Index: FlowList.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FlowList.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- FlowList.java 1 Feb 2002 20:07:08 -0000 1.2
+++ FlowList.java 29 Jul 2002 21:30:51 -0000 1.3
@@ -64,6 +64,7 @@
package org.apache.xalan.xsltc.compiler;
import java.util.Vector;
+import java.util.Iterator;
import org.apache.bcel.generic.*;
public final class FlowList {
@@ -118,5 +119,34 @@
}
_elements.clear(); // avoid backpatching more than once
}
+ }
+
+ /**
+ * Redirect the handles from oldList to newList. "This" flow list
+ * is assumed to be relative to oldList.
+ */
+ public FlowList copyAndRedirect(InstructionList oldList,
+ InstructionList newList)
+ {
+ final FlowList result = new FlowList();
+ if (_elements == null) {
+ return result;
+ }
+
+ final int n = _elements.size();
+ final Iterator oldIter = oldList.iterator();
+ final Iterator newIter = newList.iterator();
+
+ while (oldIter.hasNext()) {
+ final InstructionHandle oldIh = (InstructionHandle) oldIter.next();
+ final InstructionHandle newIh = (InstructionHandle) newIter.next();
+
+ for (int i = 0; i < n; i++) {
+ if (_elements.elementAt(i) == oldIh) {
+ result.add(newIh);
+ }
+ }
+ }
+ return result;
}
}
1.23 +162 -61
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.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- Mode.java 15 Jul 2002 19:48:19 -0000 1.22
+++ Mode.java 29 Jul 2002 21:30:51 -0000 1.23
@@ -77,8 +77,9 @@
import org.apache.xalan.xsltc.DOM;
/**
- * Mode gathers all the templates belonging to a given mode; it is
responsible
- * for generating an appropriate applyTemplates + (mode name) function
+ * Mode gathers all the templates belonging to a given mode;
+ * it is responsible for generating an appropriate
+ * applyTemplates + (mode name) method in the translet.
*/
final class Mode implements Constants {
@@ -120,32 +121,67 @@
/**
* Test sequence for patterns with id() or key()-type kernel.
*/
- private TestSeq _idxTestSeq = null;
+ private TestSeq _idxTestSeq = null;
/**
* Group for patterns with any other kernel type.
*/
- private Vector[] _patternGroups;
+ private Vector[] _patternGroups;
/**
* Test sequence for patterns with any other kernel type.
*/
private TestSeq[] _testSeq;
+ /**
+ * A mapping between patterns and instruction lists used by
+ * test sequences to avoid compiling the same pattern multiple
+ * times. Note that patterns whose kernels are "*", "node()"
+ * and "@*" can between shared by test sequences.
+ */
+ private Hashtable _preCompiled = new Hashtable();
+
+ /**
+ * A mapping between templates and test sequences.
+ */
private Hashtable _neededTemplates = new Hashtable();
+
+ /**
+ * A mapping between named templates and Mode objects.
+ */
private Hashtable _namedTemplates = new Hashtable();
+
+ /**
+ * A mapping between templates and instruction handles.
+ */
private Hashtable _templateIHs = new Hashtable();
+
+ /**
+ * A mapping between templates and instruction lists.
+ */
private Hashtable _templateILs = new Hashtable();
+
+ /**
+ * A reference to the pattern matching the root node.
+ */
private LocationPathPattern _rootPattern = null;
+ /**
+ * Stores ranges of template precendences for the compilation
+ * of apply-imports (a Hashtable for historical reasons).
+ */
private Hashtable _importLevels = null;
+ /**
+ * A mapping between key names and keys.
+ */
private Hashtable _keys = null;
- // Variable index for the current node - used in code generation
+ /**
+ * Variable index for the current node used in code generation.
+ */
private int _currentIndex;
-
/**
* Creates a new Mode.
*
@@ -155,19 +191,18 @@
* (normally a sequence number - still in a String).
*/
public Mode(QName name, Stylesheet stylesheet, String suffix) {
- // Save global info
_name = name;
_stylesheet = stylesheet;
_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()'.
+ * 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() {
@@ -175,9 +210,28 @@
}
public String functionName(int min, int max) {
- if (_importLevels == null) _importLevels = new Hashtable();
+ if (_importLevels == null) {
+ _importLevels = new Hashtable();
+ }
_importLevels.put(new Integer(max), new Integer(min));
- return _methodName+'_'+max;
+ return _methodName + '_' + max;
+ }
+
+ /**
+ * Add a pre-compiled pattern to this mode.
+ */
+ public void addInstructionList(Pattern pattern,
+ InstructionList ilist)
+ {
+ _preCompiled.put(pattern, ilist);
+ }
+
+ /**
+ * Get the instruction list for a pre-compiled pattern. Used by
+ * test sequences to avoid compiling patterns more than once.
+ */
+ public InstructionList getInstructionList(Pattern pattern) {
+ return (InstructionList) _preCompiled.get(pattern);
}
/**
@@ -187,10 +241,10 @@
return _stylesheet.getClassName();
}
- /**
- * Add a template to this mode
- * @param template The template to add
- */
+ public Stylesheet getStylesheet() {
+ return _stylesheet;
+ }
+
public void addTemplate(Template template) {
_templates.addElement(template);
}
@@ -304,10 +358,32 @@
}
/**
+ * Group patterns by NodeTests of their last Step
+ * Keep them sorted by priority within group
+ */
+ private void addPatternToGroup(final LocationPathPattern 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;
+ }
+ }
+ }
+
+ /**
* 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) {
@@ -326,10 +402,13 @@
if (patterns == null) {
patterns = new Vector(2);
patterns.addElement(pattern);
- if (kernelType == -1)
+
+ if (kernelType == -1) {
_nodeGroup = patterns;
- else
+ }
+ else {
_patternGroups[kernelType] = patterns;
+ }
}
// Otherwise make sure patterns are ordered by precedence/priorities
else {
@@ -350,40 +429,58 @@
}
/**
- * Group patterns by NodeTests of their last Step
- * Keep them sorted by priority within group
+ * Build test sequences. The first step is to complete the test
sequences
+ * by including patterns of "*" and "node()" kernel to all element test
+ * sequences, and of "@*" to all attribute test sequences.
*/
- private void addPatternToGroup(final LocationPathPattern 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;
+ private void prepareTestSequences() {
+ final Vector names = _stylesheet.getXSLTC().getNamesIndex();
+
+ final Vector starGroup = _patternGroups[DOM.ELEMENT];
+ final Vector atStarGroup = _patternGroups[DOM.ATTRIBUTE];
+
+ // Complete test sequences with "*", "@*" and "node()"
+ if (starGroup != null || atStarGroup != null || _nodeGroup != null) {
+ final int n = DOM.NTYPES + names.size();
+
+ for (int m, i = DOM.NTYPES; i < n; i++) {
+ if (_patternGroups[i] == null) continue;
+
+ final String name = (String) names.elementAt(i - DOM.NTYPES);
+
+ if (isAttributeName(name)) {
+ // If an attribute then copy "@*" to its test sequence
+ m = (atStarGroup != null) ? atStarGroup.size() : 0;
+ for (int j = 0; j < m; j++) {
+ addPattern(i,
+ (LocationPathPattern) atStarGroup.elementAt(j));
+ }
+ }
+ else {
+ // If an element then copy "*" to its test sequence
+ m = (starGroup != null) ? starGroup.size() : 0;
+ for (int j = 0; j < m; j++) {
+ addPattern(i,
+ (LocationPathPattern) starGroup.elementAt(j));
+ }
+
+ // And also copy "node()" to its test sequence
+ m = (_nodeGroup != null) ? _nodeGroup.size() : 0;
+ for (int j = 0; j < m; j++) {
+ addPattern(i,
+ (LocationPathPattern) _nodeGroup.elementAt(j));
+ }
+ }
}
}
- }
- /**
- * Build test sequences
- */
- private void prepareTestSequences() {
- final Vector names = _stylesheet.getXSLTC().getNamesIndex();
_testSeq = new TestSeq[DOM.NTYPES + names.size()];
final int n = _patternGroups.length;
for (int i = 0; i < n; i++) {
final Vector patterns = _patternGroups[i];
if (patterns != null) {
- final TestSeq testSeq = new TestSeq(patterns, this);
+ final TestSeq testSeq = new TestSeq(patterns, i, this);
testSeq.reduce();
_testSeq[i] = testSeq;
testSeq.findTemplates(_neededTemplates);
@@ -391,7 +488,7 @@
}
if ((_nodeGroup != null) && (_nodeGroup.size() > 0)) {
- _nodeTestSeq = new TestSeq(_nodeGroup, this);
+ _nodeTestSeq = new TestSeq(_nodeGroup, -1, this);
_nodeTestSeq.reduce();
_nodeTestSeq.findTemplates(_neededTemplates);
}
@@ -619,20 +716,7 @@
}
}
- /**
- * Auxiliary method to determine if a qname describes an
attribute/element
- */
- private static boolean isAttributeName(String qname) {
- final int col = qname.lastIndexOf(':') + 1;
- return (qname.charAt(col) == '@');
- }
-
- private static boolean isNamespaceName(String qname) {
- final int col = qname.lastIndexOf(':');
- return (col > -1 && qname.charAt(qname.length()-1) == '*');
- }
-
- /**
+ /**
* Compiles the applyTemplates() method and adds it to the translet.
* This is the main dispatch method.
*/
@@ -742,7 +826,6 @@
// If there is a match on node() we need to replace ihElem
// and ihText if the priority of node() is higher
if (_nodeTestSeq != null) {
-
// Compare priorities of node() and "*"
double nodePrio = _nodeTestSeq.getPriority();
int nodePos = _nodeTestSeq.getPosition();
@@ -815,6 +898,7 @@
}
}
+
// Handle pattern with match on root node - default: traverse children
targets[DOM.ROOT] = _rootPattern != null
? getTemplateInstructionHandle(_rootPattern.getTemplate())
@@ -1320,5 +1404,22 @@
public InstructionHandle getTemplateInstructionHandle(Template template)
{
return (InstructionHandle)_templateIHs.get(template);
+ }
+
+ /**
+ * Auxiliary method to determine if a qname is an attribute.
+ */
+ private static boolean isAttributeName(String qname) {
+ final int col = qname.lastIndexOf(':') + 1;
+ return (qname.charAt(col) == '@');
+ }
+
+ /**
+ * Auxiliary method to determine if a qname is a namespace
+ * qualified "*".
+ */
+ private static boolean isNamespaceName(String qname) {
+ final int col = qname.lastIndexOf(':');
+ return (col > -1 && qname.charAt(qname.length()-1) == '*');
}
}
1.17 +4 -2
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java
Index: StepPattern.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- StepPattern.java 6 May 2002 13:53:22 -0000 1.16
+++ StepPattern.java 29 Jul 2002 21:30:51 -0000 1.17
@@ -150,7 +150,9 @@
final StringBuffer buffer = new StringBuffer("stepPattern(\"");
buffer.append(Axis.names[_axis])
.append("\", ")
- .append(_isEpsilon ? "epsilon" : Integer.toString(_nodeType));
+ .append(_isEpsilon ?
+ ("epsilon{" + Integer.toString(_nodeType) + "}") :
+ Integer.toString(_nodeType));
if (_predicates != null)
buffer.append(", ").append(_predicates.toString());
return buffer.append(')').toString();
1.8 +154 -101
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.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- TestSeq.java 3 May 2002 14:20:25 -0000 1.7
+++ TestSeq.java 29 Jul 2002 21:30:51 -0000 1.8
@@ -69,6 +69,7 @@
import java.util.Hashtable;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.Iterator;
import org.apache.bcel.generic.*;
import org.apache.xalan.xsltc.compiler.util.*;
@@ -77,110 +78,149 @@
* 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).
+ * (2) share the same kernel node type (e.g. A/B and C/C/B)
+ * (3) may also contain patterns matching "*" and "node()"
+ * (element sequence only) or matching "@*" (attribute
+ * sequence only).
*
- * 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.
+ * A test sequence may have a default template, which will be
+ * instantiated if none of the other patterns match.
*/
final class TestSeq {
- private Vector _patterns = null; // all patterns
- private Mode _mode = null; // the shared mode
- private Template _default = null; // the default template
+ /**
+ * Integer code for the kernel type of this test sequence
+ */
+ private int _kernelType;
+
+ /**
+ * Vector of all patterns in the test sequence. May include
+ * patterns with "*", "@*" or "node()" kernel.
+ */
+ private Vector _patterns = null;
+
+ /**
+ * A reference to the Mode object.
+ */
+ private Mode _mode = null;
+
+ /**
+ * Default template for this test sequence
+ */
+ private Template _default = null;
+ /**
+ * Instruction list representing this test sequence.
+ */
private InstructionList _instructionList;
/**
- * Creates a new test sequence, given a set of patterns and a mode.
+ * Cached handle to avoid compiling more than once.
+ */
+ private InstructionHandle _start = null;
+
+ /**
+ * Creates a new test sequence given a set of patterns and a mode.
*/
public TestSeq(Vector patterns, Mode mode) {
+ this(patterns, -2, mode);
+ }
+
+ public TestSeq(Vector patterns, int kernelType, Mode mode) {
_patterns = patterns;
+ _kernelType = kernelType;
_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.
+ * Returns a string representation of this test sequence. Notice
+ * that test sequences are mutable, so the value returned by this
+ * method is different before and after calling reduce().
*/
- public double getPriority() {
- double prio = (0 - Double.MAX_VALUE);
+ public String toString() {
final int count = _patterns.size();
+ final StringBuffer result = new StringBuffer();
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;
- }
- if (_default != null) {
- final double tp = _default.getPriority();
- if (tp > prio) prio = tp;
+ final LocationPathPattern pattern =
+ (LocationPathPattern) _patterns.elementAt(i);
+
+ if (i == 0) {
+ result.append("Testseq for kernel " + _kernelType)
+ .append('\n');
+ }
+ result.append(" pattern " + i + ": ")
+ .append(pattern.toString())
+ .append('\n');
}
- return prio;
+ return result.toString();
}
/**
- * This method should return the last position of any template included
- * in this test sequence.
+ * Returns the instruction list for this test sequence
*/
- public int getPosition() {
- int pos = Integer.MIN_VALUE;
- final int count = _patterns.size();
+ public InstructionList getInstructionList() {
+ return _instructionList;
+ }
- 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;
- }
- if (_default != null) {
- final int tp = _default.getPosition();
- if (tp > pos) pos = tp;
- }
- return pos;
+ /**
+ * Return the highest priority for a pattern in this test
+ * sequence. This is either the priority of the first or
+ * of the default pattern.
+ */
+ public double getPriority() {
+ final Template template = (_patterns.size() == 0) ? _default
+ : ((Pattern) _patterns.elementAt(0)).getTemplate();
+ return template.getPriority();
}
-
+
+ /**
+ * Returns the position of the highest priority pattern in
+ * this test sequence.
+ */
+ public int getPosition() {
+ final Template template = (_patterns.size() == 0) ? _default
+ : ((Pattern) _patterns.elementAt(0)).getTemplate();
+ return template.getPosition();
+ }
+
/**
- * 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 pattern.
+ * Reduce the patterns in this test sequence. Creates a new
+ * vector of patterns and sets the default pattern if it
+ * finds a patterns that is fully reduced.
*/
public void reduce() {
final Vector newPatterns = new Vector();
- final int count = _patterns.size();
- // Traverse the existing set of patterns (they are in prioritised order)
+ final int count = _patterns.size();
for (int i = 0; i < count; i++) {
final LocationPathPattern pattern =
(LocationPathPattern)_patterns.elementAt(i);
- // Reduce this pattern (get rid of kernel node type)
+
+ // Reduce this pattern
pattern.reduceKernelPattern();
- // Add this pattern to the new vector of patterns.
- if (!pattern.isWildcard()) {
- newPatterns.addElement(pattern);
+ // Is this pattern fully reduced?
+ if (pattern.isWildcard()) {
+ _default = pattern.getTemplate();
+ break; // Ignore following patterns
}
- // Set template as default if its pattern matches purely on kernel
else {
- _default = pattern.getTemplate();
- // Following patterns can be ignored since default has priority
- break;
+ newPatterns.addElement(pattern);
}
}
_patterns = newPatterns;
}
/**
- * 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").
+ * Returns, by reference, the templates that are included in
+ * this test sequence. Note that a single template can occur
+ * in several test sequences if its pattern is a union.
*/
public void findTemplates(Dictionary templates) {
- if (_default != null)
+ if (_default != null) {
templates.put(_default, this);
+ }
for (int i = 0; i < _patterns.size(); i++) {
final LocationPathPattern pattern =
(LocationPathPattern)_patterns.elementAt(i);
@@ -189,9 +229,10 @@
}
/**
- * 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").
+ * 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
+ * (e.g. match="A/B | A/C").
*/
private InstructionHandle getTemplateHandle(Template template) {
return (InstructionHandle)_mode.getTemplateInstructionHandle(template);
@@ -204,71 +245,83 @@
return (LocationPathPattern)_patterns.elementAt(n);
}
-
- private InstructionHandle _start = null;
-
/**
- * 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.
+ * Compile the code for this test sequence. Compile patterns
+ * from highest to lowest priority. Note that since patterns
+ * can be share by multiple test sequences, instruction lists
+ * must be copied before backpatching.
*/
public InstructionHandle compile(ClassGenerator classGen,
MethodGenerator methodGen,
- InstructionHandle continuation) {
+ InstructionHandle continuation)
+ {
+ // Returned cached value if already compiled
+ if (_start != null) {
+ return _start;
+ }
+ // If not patterns, then return handle for default template
final int count = _patterns.size();
-
- if (_start != null) return(_start);
-
- // EZ DC if there is only one (default) pattern
- if (count == 0) getTemplateHandle(_default);
+ if (count == 0) {
+ return (_start = 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;
+ // Init handle to jump when all patterns failed
+ InstructionHandle fail = (_default == null) ? continuation
+ : getTemplateHandle(_default);
- // 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--) {
+ // Compile all patterns in reverse order
+ 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));
+ InstructionList ilist = _mode.getInstructionList(pattern);
+ if (ilist == null) {
+ ilist = pattern.compile(classGen, methodGen);
+ _mode.addInstructionList(pattern, ilist);
+ }
+
+ // Make a copy of the instruction list for backpatching
+ InstructionList copyOfilist = ilist.copy();
+
+ FlowList trueList = pattern.getTrueList();
+ if (trueList != null) {
+ trueList = trueList.copyAndRedirect(ilist, copyOfilist);
+ }
+ FlowList falseList = pattern.getFalseList();
+ if (falseList != null) {
+ falseList = falseList.copyAndRedirect(ilist, copyOfilist);
+ }
+
+ il.append(copyOfilist);
// 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
+ if (trueList != null) {
+ trueList.backPatch(success);
+ }
+ if (falseList != null) {
+ falseList.backPatch(fail);
+ }
+
+ // 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);
+ if (_instructionList != null) {
+ il.append(_instructionList);
+ }
- // Set current instruction list to be this one.
+ // Set current instruction list to be this one
_instructionList = il;
}
- return(_start = fail);
- }
-
- /**
- * Returns the instruction list for this test sequence
- */
- public InstructionList getInstructionList() {
- return _instructionList;
+ return (_start = fail);
}
-
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]