| /* |
| * @(#)$Id$ |
| * |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2001 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xalan" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2001, Sun |
| * Microsystems., http://www.sun.com. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * @author Jacek Ambroziak |
| * @author Santiago Pericas-Geertsen |
| * |
| */ |
| |
| package org.apache.xalan.xsltc.compiler; |
| |
| import java.util.Vector; |
| import java.util.Hashtable; |
| import java.util.Dictionary; |
| import java.util.Enumeration; |
| |
| import de.fub.bytecode.generic.*; |
| 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; |
| private InstructionList _instructionList; |
| |
| public TestSeq(Vector patterns, Mode mode) { |
| _patterns = patterns; |
| _mode = mode; |
| } |
| |
| public double getPriority() { |
| if (_template == null) |
| return(Double.NaN); |
| else |
| return(_template.getPriority()); |
| } |
| |
| public int getPosition() { |
| if (_template == null) |
| return(0); |
| else |
| return(_template.getPosition()); |
| } |
| |
| // careful with test ordering |
| 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 LocationPathPattern pattern = |
| (LocationPathPattern)_patterns.elementAt(i); |
| pattern.reduceKernelPattern(); |
| |
| // we only retain nontrivial reduced patterns |
| // also, anything that could follow a trivial pattern |
| // can be omitted |
| if (!pattern.isWildcard()) { |
| newPatterns.addElement(pattern); |
| } |
| 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(); |
| break; |
| } |
| } |
| _patterns = newPatterns; |
| //Util.println("patterns after reduction"); |
| for (int i = 0; i < _patterns.size(); i++) |
| Util.println(_patterns.elementAt(i).toString()); |
| } |
| |
| public void findTemplates(Dictionary templates) { |
| if (_template != null) |
| templates.put(_template, this); |
| for (int i = 0; i < _patterns.size(); i++) { |
| final LocationPathPattern pattern = |
| (LocationPathPattern)_patterns.elementAt(i); |
| templates.put(pattern.getTemplate(), this); |
| } |
| } |
| |
| private InstructionHandle getTemplateHandle(Template template) { |
| return (InstructionHandle)_mode.getTemplateInstructionHandle(template); |
| } |
| |
| private LocationPathPattern getPattern(int n) { |
| return (LocationPathPattern)_patterns.elementAt(n); |
| } |
| |
| 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 InstructionHandle success = |
| il.append(new GOTO(getTemplateHandle(pattern.getTemplate()))); |
| 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; |
| } |
| } |
| |
| public InstructionList getInstructionList() { |
| return _instructionList; |
| } |
| } |