protected override bool ApplyImpl(IGraphProcessingEnvironment procEnv) { if(!ChooseRandom) { bool res; try { #if LOG_SEQUENCE_EXECUTION procEnv.Recorder.WriteLine("Applying rule all " + GetRuleCallString(procEnv)); #endif res = procEnv.ApplyRewrite(ParamBindings, -1, -1, Special, Test, Filters) > 0; } catch (NullReferenceException) { System.Console.Error.WriteLine("Null reference exception during rule execution (null parameter?): " + Symbol); throw; } #if LOG_SEQUENCE_EXECUTION if(res) { procEnv.Recorder.WriteLine("Matched/Applied " + Symbol); procEnv.Recorder.Flush(); } #endif return res; } else { // TODO: Code duplication! Compare with BaseGraph.ApplyRewrite. int curMaxMatches = procEnv.MaxMatches; object[] parameters; if(ParamBindings.ArgumentExpressions.Length > 0) { parameters = ParamBindings.Arguments; for(int i = 0; i < ParamBindings.ArgumentExpressions.Length; i++) { if(ParamBindings.ArgumentExpressions[i] != null) parameters[i] = ParamBindings.ArgumentExpressions[i].Evaluate(procEnv); } } else parameters = null; if(ParamBindings.Subgraph!=null) procEnv.SwitchToSubgraph((IGraph)ParamBindings.Subgraph.GetVariableValue(procEnv)); #if DEBUGACTIONS || MATCHREWRITEDETAIL procEnv.PerformanceInfo.StartLocal(); #endif IMatches matches; try { matches = ParamBindings.Action.Match(procEnv, curMaxMatches, parameters); for(int i = 0; i < Filters.Count; ++i) ParamBindings.Action.Filter(procEnv, matches, Filters[i]); } catch (NullReferenceException) { System.Console.Error.WriteLine("Null reference exception during rule execution (null parameter?): " + Symbol); throw; } #if DEBUGACTIONS || MATCHREWRITEDETAIL procEnv.PerformanceInfo.StopMatch(); // total match time does NOT include listeners anymore #endif procEnv.PerformanceInfo.MatchesFound += matches.Count; procEnv.Matched(matches, null, Special); bool result = Rewrite(procEnv, matches, null); if(ParamBindings.Subgraph != null) procEnv.ReturnFromSubgraph(); return result; } }
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 }
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; }
protected bool ApplyRule(SequenceRuleCall rule, IGraphProcessingEnvironment procEnv, IMatches matches, IMatch match) { bool result; 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, null, rule.Special); 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); return result; }