/// <summary> /// Applies a rule defined in a procedure /// </summary> /// <param name="rule"></param> /// <param name="changes"></param> /// <param name="ctxt"></param> /// <param name="explanation"></param> /// <param name="runner"></param> private void ApplyRule(Rule rule, ChangeList changes, InterpretationContext ctxt, ExplanationPart explanation, Runner runner) { foreach (RuleCondition condition in rule.RuleConditions) { ExplanationPart conditionExplanation = ExplanationPart.CreateSubExplanation(explanation, condition); if (condition.EvaluatePreConditions(ctxt, conditionExplanation, runner)) { ExplanationPart.SetNamable(conditionExplanation, EfsSystem.Instance.BoolType.True); foreach (Action action in condition.Actions) { action.GetChanges(ctxt, changes, conditionExplanation, true, runner); } foreach (Rule subRule in condition.SubRules) { ApplyRule(subRule, changes, ctxt, conditionExplanation, runner); } break; } else { ExplanationPart.SetNamable(conditionExplanation, EfsSystem.Instance.BoolType.False); } } }
/// <summary> /// Provides the changes performed by this statement /// </summary> /// <param name="context">The context on which the changes should be computed</param> /// <param name="changes">The list to fill with the changes</param> /// <param name="explanation">The explanatino to fill, if any</param> /// <param name="apply">Indicates that the changes should be applied immediately</param> /// <param name="runner"></param> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner) { IVariable var = VariableIdentification.GetVariable(context); if (var != null) { IValue value = Expression.GetExpressionValue(context, explanation); if (value != null) { value = value.RightSide(var, true, true); } Range range = var.Type as Range; Collection collection = var.Type as Collection; if (range != null && range.convert(value) == null) { AddError("Value " + value + " is outside range", RuleChecksEnum.ExecutionFailed); } else if (collection != null && collection.convert(value) == null) { AddError("Value " + value + " cannot be assigned to variable", RuleChecksEnum.ExecutionFailed); } else { Change change = new Change(var, var.Value, value); changes.Add(change, apply, runner); ExplanationPart.CreateSubExplanation(explanation, Root, change); } } else { AddError("Cannot find variable " + VariableIdentification, RuleChecksEnum.ExecutionFailed); } }
/// <summary> /// Ends the iteration /// </summary> /// <param name="context"></param> /// <param name="explain"></param> /// <param name="token"></param> protected virtual void EndIteration(InterpretationContext context, ExplanationPart explain, int token) { if (!ElementFound) { ExplanationPart.CreateSubExplanation(explain, "Empty collection"); } else if (!MatchingElementFound) { ExplanationPart.CreateSubExplanation(explain, "No matching element found"); } context.LocalScope.PopContext(token); }
/// <summary> /// Indicates whether the condition is satisfied with the value provided /// Hyp : the value of the iterator variable has been assigned before /// </summary> /// <param name="context"></param> /// <param name="explain"></param> /// <returns></returns> public bool ConditionSatisfied(InterpretationContext context, ExplanationPart explain) { bool retVal = true; if (ConditionExpression != null) { BoolValue b = ConditionExpression.GetExpressionValue(context, explain) as BoolValue; ExplanationPart.CreateSubExplanation(explain, ConditionExpression, b); if (b == null) { retVal = false; } else { retVal = b.Val; } } return(retVal); }
/// <summary> /// Evaluates the rule and its sub rules /// </summary> /// <param name="runner"></param> /// <param name="priority">the priority level : a rule can be activated only if its priority level == priority</param> /// <param name="instance">The instance on which the rule must be evaluated</param> /// <param name="ruleConditions">the rule conditions to be activated</param> /// <param name="explanation">The explanation part to be filled</param> /// <param name="runner"></param> /// <returns>the number of actions that were activated during this evaluation</returns> public bool Evaluate(Runner runner, acceptor.RulePriority?priority, IModelElement instance, HashSet <Activation> activations, ExplanationPart explanation) { bool retVal = false; ExplanationPart conditionExplanation = ExplanationPart.CreateSubExplanation(explanation, this); InterpretationContext context = new InterpretationContext(instance); retVal = EvaluatePreConditions(context, conditionExplanation, runner); if (retVal) { if (conditionExplanation != null) { conditionExplanation.Message = "Condition " + Name + " satisfied"; } foreach (Rule subRule in SubRules) { subRule.Evaluate(runner, priority, instance, activations, conditionExplanation); } if (priority == null || EnclosingRule.getPriority() == priority) { activations.Add(new Activation(this, instance, conditionExplanation)); } } else { if (conditionExplanation != null) { conditionExplanation.Message = "Condition " + Name + " not satisfied"; } } return(retVal); }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="activations"></param> /// <param name="priority"></param> /// <param name="updates">Provides all the updates that have been evaluated</param> public void EvaluateActivations(HashSet <Activation> activations, acceptor.RulePriority?priority, List <VariableUpdate> updates) { foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered RuleFired ruleFired = new RuleFired(activation, priority); EventTimeLine.AddModelEvent(ruleFired, true); ExplanationPart changesExplanation = ExplanationPart.CreateSubExplanation(activation.Explanation, "Changes"); // Registers all model updates due to this rule triggering foreach (Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { VariableUpdate variableUpdate = new VariableUpdate(action, activation.Instance, priority); variableUpdate.ComputeChanges(false, this); EventTimeLine.AddModelEvent(variableUpdate, false); ruleFired.AddVariableUpdate(variableUpdate); if (changesExplanation != null) { changesExplanation.SubExplanations.Add(variableUpdate.Explanation); } updates.Add(variableUpdate); } else { action.AddError("Cannot parse action statement"); } } } } HandleEnterAndLeaveStateActions(priority, updates); }
/// <summary> /// Provides the changes performed by this statement /// </summary> /// <param name="context">The context on which the changes should be computed</param> /// <param name="changes">The list to fill with the changes</param> /// <param name="explanation">The explanatino to fill, if any</param> /// <param name="apply">Indicates that the changes should be applied immediately</param> /// <param name="runner"></param> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner) { // Explain what happens in this statement explanation = ExplanationPart.CreateSubExplanation(explanation, this); IVariable variable = ListExpression.GetVariable(context); if (variable != null) { if (variable.Value != EfsSystem.Instance.EmptyValue) { // HacK : ensure that the value is a correct rigth side // and keep the result of the right side operation ListValue listValue = variable.Value.RightSide(variable, false, false) as ListValue; variable.Value = listValue; ExplanationPart.CreateSubExplanation(explanation, "Input data = ", listValue); if (listValue != null) { int token = context.LocalScope.PushContext(); context.LocalScope.SetVariable(IteratorVariable); bool elementFound = false; bool matchingElementFound = false; foreach (IValue value in listValue.Val) { if (value != EfsSystem.Instance.EmptyValue) { // All elements should always be != from EmptyValue elementFound = true; IteratorVariable.Value = value; if (ConditionSatisfied(context, explanation)) { matchingElementFound = true; AppliedStatement.GetChanges(context, changes, explanation, apply, runner); } } } if (!elementFound) { ExplanationPart.CreateSubExplanation(explanation, "Empty collection"); } else if (!matchingElementFound) { ExplanationPart.CreateSubExplanation(explanation, "No matching element found"); } context.LocalScope.PopContext(token); } else { Root.AddError("List expression does not evaluate to a list value"); } } } else { Root.AddError("Cannot find variable for " + ListExpression); } }
/// <summary> /// Provides the changes performed by this statement /// </summary> /// <param name="context">The context on which the changes should be computed</param> /// <param name="changes">The list to fill with the changes</param> /// <param name="explanation">The explanatino to fill, if any</param> /// <param name="apply">Indicates that the changes should be applied immediately</param> /// <param name="runner"></param> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner) { // Explain what happens in this statement explanation = ExplanationPart.CreateSubExplanation(explanation, this); int index = context.LocalScope.PushContext(); context.LocalScope.SetVariable(IteratorVariable); IVariable variable = ListExpression.GetVariable(context); if (variable != null) { // HacK : ensure that the value is a correct rigth side // and keep the result of the right side operation ListValue listValue = variable.Value.RightSide(variable, false, false) as ListValue; variable.Value = listValue; if (listValue != null) { // Provide the state of the list before removing elements from it ExplanationPart.CreateSubExplanation(explanation, "Input data = ", listValue); ListValue newListValue = new ListValue(listValue); int i = 0; foreach (IValue current in newListValue.Val) { IteratorVariable.Value = current; if (ConditionSatisfied(context, explanation)) { break; } i += 1; } if (i < newListValue.Val.Count) { IValue value = Value.GetExpressionValue(context, explanation); if (value != null) { newListValue.Val[i] = value; Change change = new Change(variable, variable.Value, newListValue); changes.Add(change, apply, runner); ExplanationPart.CreateSubExplanation(explanation, Root, change); } else { Root.AddError("Cannot find value for " + Value); } } else { Root.AddError("Cannot find value in " + ListExpression + " which satisfies " + Condition); } } else { Root.AddError("Variable " + ListExpression + " does not contain a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression); } context.LocalScope.PopContext(index); }
/// <summary> /// Provides the change for this insert statement /// </summary> /// <param name="context"></param> /// <param name="variable"></param> /// <param name="explanation"></param> /// <param name="apply"></param> /// <param name="runner"></param> /// <returns></returns> public Change GetChange(InterpretationContext context, IVariable variable, ExplanationPart explanation, bool apply, Runner runner) { Change retVal = null; // Explain what happens in this statement explanation = ExplanationPart.CreateSubExplanation(explanation, this); if (variable != null) { // HacK : ensure that the value is a correct rigth side // and keep the result of the right side operation ListValue listValue = variable.Value.RightSide(variable, false, false) as ListValue; variable.Value = listValue; if (listValue != null) { ExplanationPart.CreateSubExplanation(explanation, "Input data = ", listValue); IValue value = Value.GetExpressionValue(context, explanation); if (value != null) { if (!listValue.Val.Contains(value)) { ListValue newListValue = new ListValue(listValue); if (newListValue.Val.Count < newListValue.CollectionType.getMaxSize()) { ExplanationPart.CreateSubExplanation(explanation, "Inserting", value); newListValue.Val.Add(value.RightSide(variable, true, true)); } else { // List is full, try to remove an element before inserting the new element if (ReplaceElement != null) { IValue removeValue = ReplaceElement.GetExpressionValue(context, explanation); ExplanationPart.CreateSubExplanation(explanation, "Replaced element", removeValue); int index = newListValue.Val.IndexOf(removeValue); if (index >= 0) { ExplanationPart.CreateSubExplanation(explanation, "Replacing", value); newListValue.Val[index] = value.RightSide(variable, true, true); } else { Root.AddError("Cannot remove replacing element " + removeValue.Name); } } else { Root.AddError("Cannot add new element in list value : list is full"); } } retVal = new Change(variable, variable.Value, newListValue); ExplanationPart.CreateSubExplanation(explanation, Root, retVal); } else { ExplanationPart.CreateSubExplanation(explanation, "NOT added : Already present in collection", value); } } else { Root.AddError("Cannot find value for " + Value); } } else { Root.AddError("Variable " + ListExpression + " does not contain a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression); } return(retVal); }
/// <summary> /// Provides the changes performed by this statement /// </summary> /// <param name="context">The context on which the changes should be computed</param> /// <param name="changes">The list to fill with the changes</param> /// <param name="explanation">The explanatino to fill, if any</param> /// <param name="apply">Indicates that the changes should be applied immediately</param> /// <param name="runner"></param> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner) { // Explain what happens in this statement explanation = ExplanationPart.CreateSubExplanation(explanation, this); IVariable variable = ListExpression.GetVariable(context); if (variable != null) { // HacK : ensure that the value is a correct rigth side // and keep the result of the right side operation ListValue listValue = variable.Value.RightSide(variable, false, false) as ListValue; variable.Value = listValue; if (listValue != null) { // Provide the state of the list before removing elements from it ExplanationPart.CreateSubExplanation(explanation, "Input data = ", listValue); ListValue newListValue = new ListValue(listValue.CollectionType, new List <IValue>()); int token = context.LocalScope.PushContext(); context.LocalScope.SetVariable(IteratorVariable); int index = 0; if (Position == PositionEnum.Last) { index = listValue.Val.Count - 1; } // Remove the element while required to do so while (index >= 0 && index < listValue.Val.Count) { IValue value = listValue.Val[index]; index = NextIndex(index); IteratorVariable.Value = value; if (ConditionSatisfied(context, explanation)) { if (Position != PositionEnum.All) { break; } } else { InsertInResult(newListValue, value); } } // Complete the list while (index >= 0 && index < listValue.Val.Count) { IValue value = listValue.Val[index]; InsertInResult(newListValue, value); index = NextIndex(index); } Change change = new Change(variable, variable.Value, newListValue); changes.Add(change, apply, runner); ExplanationPart.CreateSubExplanation(explanation, Root, change); context.LocalScope.PopContext(token); } } }
/// <summary> /// Provides the changes performed by this statement /// </summary> /// <param name="context">The context on which the changes should be computed</param> /// <param name="changes">The list to fill with the changes</param> /// <param name="explanation">The explanatino to fill, if any</param> /// <param name="apply">Indicates that the changes should be applied immediately</param> /// <param name="runner"></param> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner) { if (Call != null) { // Explain what happens in this statement explanation = ExplanationPart.CreateSubExplanation(explanation, this); InterpretationContext ctxt = GetContext(context, explanation); Procedure procedure = Call.GetProcedure(ctxt, explanation); if (procedure != null) { ctxt.HasSideEffects = true; // If the procedure has been defined in a structure, // ensure that it is applied to an instance of that structure Structure structure = procedure.Enclosing as Structure; if (structure != null) { ITypedElement current = ctxt.Instance as ITypedElement; while (current != null) { if (current.Type != structure) { current = current.Enclosing as ITypedElement; } else { ctxt.Instance = current; ExplanationPart.CreateSubExplanation(explanation, "Instance", current); current = null; } } } ExplanationPart part = ExplanationPart.CreateSubExplanation(explanation, procedure); if (ctxt.Instance is IVariable) { ExplanationPart.SetNamable(part, ctxt.Instance); ExplanationPart instanceExplanation = ExplanationPart.CreateSubExplanation(part, "instance = "); ExplanationPart.SetNamable(instanceExplanation, ctxt.Instance); } int token = ctxt.LocalScope.PushContext(); foreach ( KeyValuePair <Actual, IValue> pair in Call.AssignParameterValues(context, procedure, true, part)) { ctxt.LocalScope.SetVariable(pair.Key, pair.Value); } foreach (Rule rule in procedure.Rules) { ApplyRule(rule, changes, ctxt, part, runner); } ctxt.LocalScope.PopContext(token); } else { AddError("Cannot determine the called procedure for " + ToString(), RuleChecksEnum.ExecutionFailed); } } else { AddError("Expression " + ToString() + " is not a valid procedure call", RuleChecksEnum.ExecutionFailed); } }