/** * Extracts the morphism from rule nodes to input graph nodes corresponding to the transition's * input parameters. * * @return if {@code null}, the binding cannot be constructed and so the rule cannot match */ private RuleToHostMap extractBinding(Step step) { RuleToHostMap result = this.state.getGraph().getFactory().createRuleToHostMap(); Object[] sourceValues = this.state.getActualValues(); for (Assignment assign : step.getEnterAssignments()) { sourceValues = assign.compute(sourceValues); } for (Pair<Var, Binding> entry : step.getRuleSwitch().getCallBinding()) { Binding bind = entry.two(); HostNode value; if (bind == null) { // this corresponds to an output parameter of the call continue; } switch (bind.getSource()) { case CONST: value = bind.getValue().getNode(); break; case VAR: value = Valuator.get(sourceValues, bind); break; default: assert false; value = null; } RuleNode ruleNode = entry.one().getRuleNode(); if (isCompatible(ruleNode, value)) { result.putNode(ruleNode, value); } else { result = null; break; } } return result; }
/** * Returns the set of matching events for a given control step. * * @param step the control step for which matches are to be found; non-{@code null} */ public MatchResultSet computeMatches(final Step step) { final MatchResultSet result = new MatchResultSet(); if (DEBUG) { System.out.printf("Matches for %s, %s%n ", this.state, this.state.getGraph()); } assert step != null; // there are three reasons to want to use the parent matches: to // save matching time, to reuse added nodes, and to find confluent // diamonds. The first is only relevant if the rule is not (re)enabled, // the third only if the parent match target is already closed final boolean isDisabled = isDisabled(step.getRuleCall()); boolean isModifying = step.isModifying(); if (!isDisabled) { for (GraphTransition trans : this.parentTransMap) { if (trans instanceof RuleTransition) { RuleTransition ruleTrans = (RuleTransition) trans; if (ruleTrans.getEvent().getRule().equals(step.getRule())) { MatchResult match = ruleTrans.getKey(); if (isModifying) { // we can reuse the event but not the control step match = new MatchResult(match.getEvent(), step); } result.add(match); if (DEBUG) { System.out.print(" T" + System.identityHashCode(trans.getEvent())); } } } } } if (isDisabled || isEnabled(step.getRuleCall())) { // the rule was possibly enabled afresh, so we have to add the fresh // matches RuleToHostMap boundMap = extractBinding(step); if (boundMap != null) { final Record record = this.record; Visitor<Proof, Boolean> eventCollector = new Visitor<Proof, Boolean>(false) { @Override protected boolean process(Proof object) { RuleEvent event = record.getEvent(object); // only look up the event in the parent map if // the rule was disabled, as otherwise the result // already contains all relevant parent results MatchResult match = new MatchResult(event, step); if (isDisabled) { match = getParentTrans(match); } result.add(match); if (DEBUG) { System.out.print(" E" + System.identityHashCode(match.getEvent())); checkEvent(match.getEvent()); } setResult(true); return true; } }; step.getRule().traverseMatches(this.state.getGraph(), boundMap, eventCollector); } } if (DEBUG) { System.out.println(); } return result; }