Beispiel #1
0
        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;
        }
Beispiel #2
0
        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;
        }
Beispiel #3
0
        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;
        }
Beispiel #4
0
        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
        }
Beispiel #5
0
        /// <summary>
        /// Applies this sequence.
        /// </summary>
        /// <param name="procEnv">The graph processing environment on which this sequence is to be applied.
        ///     Contains especially the graph on which this sequence is to be applied.
        ///     And the user proxy queried when choices are due.
        ///     The rules will only be chosen during the Sequence object instantiation, so
        ///     exchanging rules will have no effect for already existing Sequence objects.</param>
        /// <returns>True, iff the sequence succeeded</returns>
        public bool Apply(IGraphProcessingEnvironment procEnv)
        {
            procEnv.EnteringSequence(this);
            executionState = SequenceExecutionState.Underway;
#if LOG_SEQUENCE_EXECUTION
            procEnv.Recorder.WriteLine("Before executing sequence " + Id + ": " + Symbol);
#endif
            bool res = ApplyImpl(procEnv);
#if LOG_SEQUENCE_EXECUTION
            procEnv.Recorder.WriteLine("After executing sequence " + Id + ": " + Symbol + " result " + res);
#endif
            executionState = res ? SequenceExecutionState.Success : SequenceExecutionState.Fail;
            procEnv.ExitingSequence(this);
            return res;
        }