/* // $Id: //guest/julian_hyde/saffron/src/main/saffron/opt/RuleCall.java#1 $ // Saffron preprocessor and data engine // Copyright (C) 2002 Julian Hyde <julian.hyde@mail.com> // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the // Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // // See the COPYING file located in the top-level-directory of // the archive of this library for complete text of license. // // jhyde, May 3, 2002 */ package saffron.opt; import openjava.mop.Environment; import openjava.tools.DebugOut; import saffron.Planner; import saffron.rel.Rel; import saffron.util.Util; import java.util.Vector; /** * A <code>RuleCall</code> is an invocation of a {@link Rule} with a * set of {@link Rel relational expression}s as arguments. */ public class RuleCall { Environment env; Operand operand0; public Rel[] rels; Rule rule; private VolcanoPlanner planner; private static final Vector emptyVector = new Vector(); RuleCall(VolcanoPlanner planner, Environment env, Operand operand) { this.planner = planner; this.env = env; this.operand0 = operand; this.rule = operand0.rule; this.rels = new Rel[operand0.rule.operands.length]; } Rule getRule() { return operand0.rule; } void match(int solve) { if (solve == rule.operands.length) { try { rule.onMatch(this); } catch (Exception e) { throw Util.newInternal( e, "while applying rule " + rule.getDescription()); } } else { int operandOrdinal = operand0.solveOrder[solve], previousOperandOrdinal = operand0.solveOrder[solve - 1]; boolean ascending = operandOrdinal < previousOperandOrdinal; Operand operand = rule.operands[operandOrdinal]; Vector successors; if (ascending) { Util.assert( rule.operands[previousOperandOrdinal].parent == operand); RelSubset subset = planner.getSubset( rels[previousOperandOrdinal], rule.getConvention()); if (subset == null) { successors = emptyVector; } else { successors = subset.parents; } } else { int parentOrdinal = operand.parent.ordinalInRule; Rel parentRel = rels[parentOrdinal]; Rel[] inputs = parentRel.getInputs(); RelSubset subset = (RelSubset) inputs[operand.ordinalInParent]; successors = subset.rels; } for (int i = 0, n = successors.size(); i < n; i++) { Rel rel = (Rel) successors.elementAt(i); if (operand.clazz.isAssignableFrom(rel.getClass())) { rels[operandOrdinal] = rel; match(solve + 1); } } } } /** * Called by the rule whenever it finds a match. */ public void transformTo(Rel rel) { // Check that expression supports the desired // convention. DebugOut.println( "Rule " + rule + " arguments " + Util.toString(rels) + " created " + rel); int ruleConvention = rule.getConvention(), relConvention = rel.getConvention(); if (ruleConvention != relConvention && ruleConvention != CallingConvention.NONE) { throw Util.newInternal( "Rule " + rule + " promised convention " + CallingConvention.getName(ruleConvention) + " but produced " + CallingConvention.getName(relConvention)); } RelSubset subset = planner.register( rel, planner.getSet(rels[0]), Planner.MAY_BE_REGISTERED); // Ensure that there is a converter between the // original convention and the new convention. Rel converted = planner.convert( subset, rels[0].getConvention()); } } // End RuleCall.java
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 1801 | Julian Hyde |
saffron: add ObjectSchema; rules can now be matched more than once; started to implement correlations in queries in from list. |