protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { long i = 0; while(Seq.Apply(procEnv)) { procEnv.EndOfIteration(true, this); Seq.ResetExecutionState(); i++; } procEnv.EndOfIteration(false, this); return i >= Min; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { long i; bool first = true; for(i = 0; i < Max; i++) { if(!first) procEnv.EndOfIteration(true, this); Seq.ResetExecutionState(); if(!Seq.Apply(procEnv)) break; first = false; } procEnv.EndOfIteration(false, this); return i >= Min; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { bool res = true; // first get all matches of the rule object[] parameters; if(Rule.ParamBindings.ArgumentExpressions.Length > 0) { parameters = Rule.ParamBindings.Arguments; for(int j = 0; j < Rule.ParamBindings.ArgumentExpressions.Length; j++) { if(Rule.ParamBindings.ArgumentExpressions[j] != null) parameters[j] = Rule.ParamBindings.ArgumentExpressions[j].Evaluate(procEnv); } } else parameters = null; #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Matching for rule " + Rule.GetRuleCallString(procEnv)); #endif #if DEBUGACTIONS || MATCHREWRITEDETAIL procEnv.PerformanceInfo.StartLocal(); #endif IMatches matches = Rule.ParamBindings.Action.Match(procEnv, procEnv.MaxMatches, parameters); for(int i=0; i<Rule.Filters.Count; ++i) Rule.ParamBindings.Action.Filter(procEnv, matches, Rule.Filters[i]); #if DEBUGACTIONS || MATCHREWRITEDETAIL procEnv.PerformanceInfo.StopMatch(); // total match time does NOT include listeners anymore #endif procEnv.PerformanceInfo.MatchesFound += matches.Count; if(matches.Count == 0) { procEnv.EndOfIteration(false, this); Rule.executionState = SequenceExecutionState.Fail; return res; } #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Rule " + Rule.GetRuleCallString(procEnv) + " matched " + matches.Count + " times"); #endif // the rule might be called again in the sequence, overwriting the matches object of the action // normally it's safe to assume the rule is not called again until its matches were processed, // allowing for the one matches object memory optimization, but here we must clone to prevent bad side effect // TODO: optimization; if it's ensured the sequence doesn't call this action again, we can omit this, requires call analysis matches = matches.Clone(); // apply the sequence for every match found bool first = true; foreach(IMatch match in matches) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(match, procEnv); #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Iterating match: " + MatchPrinter.ToString(match, procEnv.Graph, "")); #endif procEnv.EnteringSequence(Rule); Rule.executionState = SequenceExecutionState.Underway; procEnv.Matched(matches, match, Rule.Special); Rule.executionState = SequenceExecutionState.Success; procEnv.ExitingSequence(Rule); // rule matching simulated so it can be shown in the debugger, now execute the sequence Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); return res; }
public override bool Apply(SequenceInvocationParameterBindings sequenceInvocation, IGraphProcessingEnvironment procEnv) { // If this sequence definition is currently executed // we must copy it and use the copy in its place // to prevent state corruption. if(executionState == SequenceExecutionState.Underway) { return ApplyCopy(sequenceInvocation, procEnv); } procEnv.EnteringSequence(this); executionState = SequenceExecutionState.Underway; #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Before executing sequence definition " + Id + ": " + Symbol); #endif bool res = ApplyImpl(sequenceInvocation, procEnv); #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("After executing sequence definition " + Id + ": " + Symbol + " result " + res); #endif executionState = res ? SequenceExecutionState.Success : SequenceExecutionState.Fail; procEnv.EndOfIteration(false, this); procEnv.ExitingSequence(this); ResetExecutionState(); // state is shown by call, we don't exist any more for the debugger return res; }
protected bool ApplyImplProfiling(IGraphProcessingEnvironment procEnv) { bool res = true; INode node = (INode)ArgExprs[0].Evaluate(procEnv); int depth = -1; EdgeType edgeType; NodeType nodeType; if(SequenceType == SequenceType.ForBoundedReachableNodes || SequenceType == SequenceType.ForBoundedReachableNodesViaIncoming || SequenceType == SequenceType.ForBoundedReachableNodesViaOutgoing || SequenceType == SequenceType.ForBoundedReachableEdges || SequenceType == SequenceType.ForBoundedReachableEdgesViaIncoming || SequenceType == SequenceType.ForBoundedReachableEdgesViaOutgoing) { depth = (int)ArgExprs[1].Evaluate(procEnv); edgeType = GetEdgeType(procEnv, ArgExprs.Count >= 3 ? ArgExprs[2] : null); nodeType = GetNodeType(procEnv, ArgExprs.Count >= 4 ? ArgExprs[3] : null); } else { edgeType = GetEdgeType(procEnv, ArgExprs.Count >= 2 ? ArgExprs[1] : null); nodeType = GetNodeType(procEnv, ArgExprs.Count >= 3 ? ArgExprs[2] : null); } switch(SequenceType) { case SequenceType.ForAdjacentNodes: { bool first = true; foreach(IEdge edge in node.Incident) { ++procEnv.PerformanceInfo.SearchSteps; if(!edge.InstanceOf(edgeType)) continue; if(!edge.Opposite(node).InstanceOf(nodeType)) continue; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge.Opposite(node), procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForAdjacentNodesViaIncoming: { bool first = true; foreach(IEdge edge in node.Incoming) { ++procEnv.PerformanceInfo.SearchSteps; if(!edge.InstanceOf(edgeType)) continue; if(!edge.Source.InstanceOf(nodeType)) continue; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge.Source, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForAdjacentNodesViaOutgoing: { bool first = true; foreach(IEdge edge in node.Outgoing) { ++procEnv.PerformanceInfo.SearchSteps; if(!edge.InstanceOf(edgeType)) continue; if(!edge.Target.InstanceOf(nodeType)) continue; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge.Target, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForIncidentEdges: { bool first = true; foreach(IEdge edge in node.Incident) { ++procEnv.PerformanceInfo.SearchSteps; if(!edge.InstanceOf(edgeType)) continue; if(!edge.Opposite(node).InstanceOf(nodeType)) continue; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForIncomingEdges: { bool first = true; foreach(IEdge edge in node.Incoming) { ++procEnv.PerformanceInfo.SearchSteps; if(!edge.InstanceOf(edgeType)) continue; if(!edge.Source.InstanceOf(nodeType)) continue; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForOutgoingEdges: { bool first = true; foreach(IEdge edge in node.Outgoing) { ++procEnv.PerformanceInfo.SearchSteps; if(!edge.InstanceOf(edgeType)) continue; if(!edge.Target.InstanceOf(nodeType)) continue; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForReachableNodes: { bool first = true; foreach(INode iter in GraphHelper.Reachable(node, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(iter, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForReachableNodesViaIncoming: { bool first = true; foreach(INode iter in GraphHelper.ReachableIncoming(node, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(iter, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForReachableNodesViaOutgoing: { bool first = true; foreach(INode iter in GraphHelper.ReachableOutgoing(node, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(iter, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForReachableEdges: { bool first = true; foreach(IEdge edge in GraphHelper.ReachableEdges(node, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForReachableEdgesViaIncoming: { bool first = true; foreach(IEdge edge in GraphHelper.ReachableEdgesIncoming(node, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForReachableEdgesViaOutgoing: { bool first = true; foreach(IEdge edge in GraphHelper.ReachableEdgesOutgoing(node, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForBoundedReachableNodes: { bool first = true; foreach(INode iter in GraphHelper.BoundedReachable(node, depth, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(iter, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForBoundedReachableNodesViaIncoming: { bool first = true; foreach(INode iter in GraphHelper.BoundedReachableIncoming(node, depth, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(iter, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForBoundedReachableNodesViaOutgoing: { bool first = true; foreach(INode iter in GraphHelper.BoundedReachableOutgoing(node, depth, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(iter, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForBoundedReachableEdges: { bool first = true; foreach(IEdge edge in GraphHelper.BoundedReachableEdges(node, depth, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForBoundedReachableEdgesViaIncoming: { bool first = true; foreach(IEdge edge in GraphHelper.BoundedReachableEdgesIncoming(node, depth, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForBoundedReachableEdgesViaOutgoing: { bool first = true; foreach(IEdge edge in GraphHelper.BoundedReachableEdgesOutgoing(node, depth, edgeType, nodeType, procEnv.Graph, procEnv)) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } } procEnv.EndOfIteration(false, this); return res; }
protected bool ApplyImplNodesEdgesProfiling(IGraphProcessingEnvironment procEnv) { bool res = true; switch(SequenceType) { case SequenceType.ForNodes: { NodeType nodeType = GetNodeType(procEnv, ArgExprs.Count >= 1 ? ArgExprs[0] : null); bool first = true; foreach(INode node in procEnv.Graph.GetCompatibleNodes(nodeType)) { ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(node, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } case SequenceType.ForEdges: { EdgeType edgeType = GetEdgeType(procEnv, ArgExprs.Count >= 1 ? ArgExprs[0] : null); bool first = true; foreach(IEdge edge in procEnv.Graph.GetCompatibleEdges(edgeType)) { ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(edge, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } break; } } procEnv.EndOfIteration(false, this); return res; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { bool res = true; IAttributeIndex index = (IAttributeIndex)procEnv.Graph.Indices.GetIndex(IndexName); if(Ascending) { if(From() != null && To() != null) { if(IncludingFrom()) { if(IncludingTo()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingFromInclusiveToInclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingFromInclusiveToExclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else { if(IncludingTo()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingFromExclusiveToInclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingFromExclusiveToExclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } } else if(From() != null) { if(IncludingFrom()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingFromInclusive(From().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingFromExclusive(From().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else if(To() != null) { if(IncludingTo()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingToInclusive(To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscendingToExclusive(To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsAscending()) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else { if(From() != null && To() != null) { if(IncludingFrom()) { if(IncludingTo()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingFromInclusiveToInclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingFromInclusiveToExclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else { if(IncludingTo()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingFromExclusiveToInclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingFromExclusiveToExclusive(From().Evaluate(procEnv), To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } } else if(From() != null) { if(IncludingFrom()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingFromInclusive(From().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingFromExclusive(From().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else if(To() != null) { if(IncludingTo()) { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingToInclusive(To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescendingToExclusive(To().Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } else { bool first = true; foreach(IGraphElement elem in index.LookupElementsDescending()) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } } return res; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { bool res = true; IAttributeIndex index = (IAttributeIndex)procEnv.Graph.Indices.GetIndex(IndexName); bool first = true; foreach(IGraphElement elem in index.LookupElements(Expr.Evaluate(procEnv))) { if(EmitProfiling) ++procEnv.PerformanceInfo.SearchSteps; if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(elem, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); return res; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { bool res = true; int entry = (int)Left.Evaluate(procEnv); int limit = (int)Right.Evaluate(procEnv); bool ascending = entry <= limit; bool first = true; while(ascending ? entry <= limit : entry >= limit) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(entry, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); if(ascending) ++entry; else --entry;; first = false; } procEnv.EndOfIteration(false, this); return res; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { bool res = true; if(Container.GetVariableValue(procEnv) is IList) { IList array = (IList)Container.GetVariableValue(procEnv); bool first = true; for(int i = 0; i < array.Count; ++i) { if(!first) procEnv.EndOfIteration(true, this); if(VarDst != null) { Var.SetVariableValue(i, procEnv); VarDst.SetVariableValue(array[i], procEnv); } else { Var.SetVariableValue(array[i], procEnv); } Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else if(Container.GetVariableValue(procEnv) is IDeque) { IDeque deque = (IDeque)Container.GetVariableValue(procEnv); bool first = true; for(int i = 0; i < deque.Count; ++i) { if(!first) procEnv.EndOfIteration(true, this); if(VarDst != null) { Var.SetVariableValue(i, procEnv); VarDst.SetVariableValue(deque[i], procEnv); } else { Var.SetVariableValue(deque[i], procEnv); } Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } else { IDictionary setmap = (IDictionary)Container.GetVariableValue(procEnv); bool first = true; foreach(DictionaryEntry entry in setmap) { if(!first) procEnv.EndOfIteration(true, this); Var.SetVariableValue(entry.Key, procEnv); if(VarDst != null) VarDst.SetVariableValue(entry.Value, procEnv); Seq.ResetExecutionState(); res &= Seq.Apply(procEnv); first = false; } procEnv.EndOfIteration(false, this); } return res; }
protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { // first get all matches of the rule object[] parameters; if(Rule.ParamBindings.ArgumentExpressions.Length > 0) { parameters = Rule.ParamBindings.Arguments; for(int j = 0; j < Rule.ParamBindings.ArgumentExpressions.Length; j++) { if(Rule.ParamBindings.ArgumentExpressions[j] != null) parameters[j] = Rule.ParamBindings.ArgumentExpressions[j].Evaluate(procEnv); } } else parameters = null; #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Matching backtrack all " + Rule.GetRuleCallString(procEnv)); #endif #if DEBUGACTIONS || MATCHREWRITEDETAIL procEnv.PerformanceInfo.StartLocal(); #endif IMatches matches = Rule.ParamBindings.Action.Match(procEnv, procEnv.MaxMatches, parameters); for(int i=0; i<Rule.Filters.Count; ++i) Rule.ParamBindings.Action.Filter(procEnv, matches, Rule.Filters[i]); #if DEBUGACTIONS || MATCHREWRITEDETAIL procEnv.PerformanceInfo.StopMatch(); // total match time does NOT include listeners anymore #endif procEnv.PerformanceInfo.MatchesFound += matches.Count; if(matches.Count == 0) { Rule.executionState = SequenceExecutionState.Fail; return false; } #if LOG_SEQUENCE_EXECUTION for(int i = 0; i < matches.Count; ++i) { procEnv.Recorder.WriteLine("match " + i + ": " + MatchPrinter.ToString(matches.GetMatch(i), procEnv.Graph, "")); } #endif // the rule might be called again in the sequence, overwriting the matches object of the action // normally it's safe to assume the rule is not called again until its matches were processed, // allowing for the one matches object memory optimization, but here we must clone to prevent bad side effect // TODO: optimization; if it's ensured the sequence doesn't call this action again, we can omit this, requires call analysis matches = matches.Clone(); #if LOG_SEQUENCE_EXECUTION for(int i = 0; i < matches.Count; ++i) { procEnv.Recorder.WriteLine("cloned match " + i + ": " + MatchPrinter.ToString(matches.GetMatch(i), procEnv.Graph, "")); } #endif // apply the rule and the following sequence for every match found, // until the first rule and sequence execution succeeded // rolling back the changes of failing executions until then int matchesTried = 0; foreach(IMatch match in matches) { ++matchesTried; #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Applying backtrack match " + matchesTried + "/" + matches.Count + " of " + Rule.GetRuleCallString(procEnv)); procEnv.Recorder.WriteLine("match: " + MatchPrinter.ToString(match, procEnv.Graph, "")); #endif // start a transaction int transactionID = procEnv.TransactionManager.Start(); int oldRewritesPerformed = procEnv.PerformanceInfo.RewritesPerformed; procEnv.EnteringSequence(Rule); Rule.executionState = SequenceExecutionState.Underway; #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Before executing sequence " + Rule.Id + ": " + Rule.Symbol); #endif procEnv.Matched(matches, match, Rule.Special); bool result = Rule.Rewrite(procEnv, matches, match); #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("After executing sequence " + Rule.Id + ": " + Rule.Symbol + " result " + result); #endif Rule.executionState = result ? SequenceExecutionState.Success : SequenceExecutionState.Fail; procEnv.ExitingSequence(Rule); // rule applied, now execute the sequence result = Seq.Apply(procEnv); // if sequence execution failed, roll the changes back and try the next match of the rule if(!result) { procEnv.TransactionManager.Rollback(transactionID); procEnv.PerformanceInfo.RewritesPerformed = oldRewritesPerformed; if(matchesTried < matches.Count) { procEnv.EndOfIteration(true, this); Rule.ResetExecutionState(); Seq.ResetExecutionState(); continue; } else { // all matches tried, all failed later on -> end in fail #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Applying backtrack match exhausted " + Rule.GetRuleCallString(procEnv)); #endif procEnv.EndOfIteration(false, this); return false; } } // if sequence execution succeeded, commit the changes so far and succeed procEnv.TransactionManager.Commit(transactionID); procEnv.EndOfIteration(false, this); return true; } return false; // to satisfy the compiler, we return from inside the loop }