/// <summary> /// Creates a list of changes to be applied on the system /// </summary> /// <param name="context">The context on which the changes should be computed</param> /// <param name="changes">The list of changes to be updated</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> /// <returns>The list to fill with the changes</returns> public virtual void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner) { if (!DeActivated) { long start = Environment.TickCount; try { if (Statement != null) { Statement.GetChanges(context, changes, explanation, apply, runner); } else { AddError("Invalid actions statement"); } } catch (Exception e) { AddException(e); } long stop = Environment.TickCount; long span = (stop - start); if (RuleCondition != null && RuleCondition.EnclosingRule != null) { // Rule execution execution time (as opposed to guard evaluation) RuleCondition.EnclosingRule.ExecutionTimeInMilli += span; RuleCondition.EnclosingRule.ExecutionCount += 1; } } }
/// <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; if (range != null && range.convert(value) == null) { AddError("Value " + value + " is outside range"); } 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); } }
/// <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) { 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) { 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.GetValue(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.ToString()); } } else { Root.AddError("Cannot find value in " + ListExpression.ToString() + " which satisfies " + Condition.ToString()); } } else { Root.AddError("Variable " + ListExpression.ToString() + " does not contain a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression.ToString()); } context.LocalScope.PopContext(index); }
/// <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 changes performed by this statement</param> /// <param name="explanation">The explanatino to fill, if any</param> /// <param name="apply">Indicates that the changes should be applied immediately</param> public abstract void GetChanges(Interpreter.InterpretationContext context, ChangeList changes, Interpreter.ExplanationPart explanation, bool apply);
/// <summary> /// Computes the changes related to this event /// </summary> /// <param name="apply">Indicates that the changes should be applied directly</param> public override bool ComputeChanges(bool apply) { bool retVal = base.ComputeChanges(apply); if (retVal) { Explanation = new Interpreter.ExplanationPart(Action); Explanation.Message = "Action " + Action.Name; Interpreter.InterpretationContext context = new Interpreter.InterpretationContext(Instance); Changes = new ChangeList(); Action.GetChanges(context, Changes, Explanation, apply); Changes.CheckChanges(Action); Message = Explanation.ToString(); } 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> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply) { Variables.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 Values.ListValue listValue = variable.Value.RightSide(variable, false) as Values.ListValue; variable.Value = listValue; if (listValue != null) { Values.ListValue newListValue = new Values.ListValue(listValue); int i = 0; foreach (Values.IValue current in newListValue.Val) { IteratorVariable.Value = current; if (conditionSatisfied(context)) { break; } i += 1; } if (i < newListValue.Val.Count) { Values.IValue value = Value.GetValue(context); if (value != null) { newListValue.Val[i] = value; Rules.Change change = new Rules.Change(variable, variable.Value, newListValue); changes.Add(change, apply); explanation.SubExplanations.Add(new ExplanationPart(Root, change)); } else { Root.AddError("Cannot find value for " + Value.ToString()); } } else { Root.AddError("Cannot find value in " + ListExpression.ToString() + " which satisfies " + Condition.ToString()); } } else { Root.AddError("Variable " + ListExpression.ToString() + " does not contain a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression.ToString()); } }
/// <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> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply) { if (Call != null) { InterpretationContext ctxt = getContext(context); Functions.Procedure procedure = Call.getProcedure(ctxt); if (procedure != null) { ExplanationPart part = new ExplanationPart(Root); part.Message = procedure.FullName; explanation.SubExplanations.Add(part); int token = ctxt.LocalScope.PushContext(); foreach (KeyValuePair<Variables.Actual, Values.IValue> pair in Call.AssignParameterValues(context, procedure, true)) { ctxt.LocalScope.setVariable(pair.Key, pair.Value); } foreach (Rules.Rule rule in Rules) { ApplyRule(rule, changes, ctxt, part); } ctxt.LocalScope.PopContext(token); } else { AddError("Cannot determine the called procedure for " + ToString()); } } else { AddError("Expression " + ToString() + " is not a valid procedure call"); } }
/// <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> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply) { Variables.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 Values.ListValue listValue = variable.Value.RightSide(variable, false) as Values.ListValue; variable.Value = listValue; if (listValue != null) { Values.ListValue newListValue = new Values.ListValue(listValue.CollectionType, new List<Values.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) { Values.IValue value = listValue.Val[index]; index = nextIndex(index); if (value == EFSSystem.EmptyValue) { InsertInResult(newListValue, value); } else { IteratorVariable.Value = value; if (conditionSatisfied(context)) { if (Position != PositionEnum.All) { break; } } else { InsertInResult(newListValue, value); } } } // Complete the list while (index >= 0 && index < listValue.Val.Count) { Values.IValue value = listValue.Val[index]; InsertInResult(newListValue, value); index = nextIndex(index); } // Fill the gap while (newListValue.Val.Count < listValue.Val.Count) { newListValue.Val.Add(EFSSystem.EmptyValue); } Rules.Change change = new Rules.Change(variable, variable.Value, newListValue); changes.Add(change, apply); explanation.SubExplanations.Add(new ExplanationPart(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) { 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) { IValue value = Value.GetValue(context, explanation); if (value != null) { if (!listValue.Val.Contains(value)) { ListValue newListValue = new ListValue(listValue); int index = newListValue.Val.IndexOf(EFSSystem.EmptyValue); if (index >= 0) { newListValue.Val[index] = value; } else { // List is full, try to remove an element before inserting the new element if (ReplaceElement != null) { IValue removeValue = ReplaceElement.GetValue(context, explanation); index = newListValue.Val.IndexOf(removeValue); if (index >= 0) { 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"); } } Change change = new Change(variable, variable.Value, newListValue); changes.Add(change, apply, runner); ExplanationPart.CreateSubExplanation(explanation, Root, change); } else { AddError("Value " + value.LiteralName + " already present in list. It has not been added"); } } else { Root.AddError("Cannot find value for " + Value.ToString()); } } else { Root.AddError("Variable " + ListExpression.ToString() + " does not contain a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression.ToString()); } }
/// <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> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply) { Variables.IVariable var = VariableIdentification.GetVariable(context); if (var != null) { string tmp = var.FullName; Values.IValue value = Expression.GetValue(context); if (value != null) { value = value.RightSide(var, true); } Rules.Change change = new Rules.Change(var, var.Value, value); changes.Add(change, apply); explanation.SubExplanations.Add(new ExplanationPart(Root, change)); } else { AddError("Cannot find variable " + VariableIdentification.ToString()); } }
/// <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); // Evaluate the list on which the APPLY statement shall be evaluated ListValue listValue = null; if (SideEffectOnVariable) { // If the apply statement has side effect, copy the corresponding variable // to be able to roll back the changes (in case of execution step back for instance) 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 = variable.Value.RightSide(variable, false, false) as ListValue; variable.Value = listValue; } } } else { IValue value = ListExpression.GetValue(context, explanation); if (value != null) { listValue = value as ListValue; } } if (listValue != null) { ExplanationPart.CreateSubExplanation(explanation, "Input data = ", listValue); 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 { ExplanationPart.CreateSubExplanation(explanation, "List expression cannot be evaluated as a valid list value"); } }
/// <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> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply) { Variables.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 Values.ListValue listValue = variable.Value.RightSide(variable, false) as Values.ListValue; variable.Value = listValue; if (listValue != null) { Values.IValue value = Value.GetValue(context); if (value != null) { Values.ListValue newListValue = new Values.ListValue(listValue); int index = newListValue.Val.IndexOf(EFSSystem.EmptyValue); if (index >= 0) { newListValue.Val[index] = value; } else { // List is full, try to remove an element before inserting the new element if (ReplaceElement != null) { Values.IValue removeValue = ReplaceElement.GetValue(context); index = newListValue.Val.IndexOf(removeValue); if (index >= 0) { newListValue.Val[index] = value; } else { Root.AddError("Cannot remove replacing element " + removeValue.Name); } } else { Root.AddError("Cannot add new element in list value : list is full"); } } Rules.Change change = new Rules.Change(variable, variable.Value, newListValue); changes.Add(change, apply); explanation.SubExplanations.Add(new ExplanationPart(Root, change)); } else { Root.AddError("Cannot find value for " + Value.ToString()); } } else { Root.AddError("Variable " + ListExpression.ToString() + " does not contain a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression.ToString()); } }
/// <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) { 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) { IEnclosed enclosed = current as IEnclosed; if (enclosed != null) { current = enclosed.Enclosing as ITypedElement; } else { current = null; } } else { ctxt.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()); } } else { AddError("Expression " + ToString() + " is not a valid procedure call"); } }
/// <summary> /// Applies a rule defined in a procedure /// </summary> /// <param name="rule"></param> /// <param name="changes"></param> /// <param name="ctxt"></param> private void ApplyRule(Rules.Rule rule, ChangeList changes, InterpretationContext ctxt, ExplanationPart explanation) { foreach (Rules.RuleCondition condition in rule.RuleConditions) { if (condition.EvaluatePreConditions(ctxt)) { foreach (Rules.Action action in condition.Actions) { action.GetChanges(ctxt, changes, explanation, true); } foreach (Rules.Rule subRule in condition.SubRules) { ApplyRule(subRule, changes, ctxt, explanation); } break; } } }
/// <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.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.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> public override void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply) { Variables.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 Values.ListValue listValue = variable.Value.RightSide(variable, false) as Values.ListValue; variable.Value = listValue; if (listValue != null) { int token = context.LocalScope.PushContext(); context.LocalScope.setVariable(IteratorVariable); foreach (Values.IValue value in listValue.Val) { if (value != EFSSystem.EmptyValue) { IteratorVariable.Value = value; if (conditionSatisfied(context)) { Call.GetChanges(context, changes, explanation, apply); } } } context.LocalScope.PopContext(token); } else { Root.AddError("List expression does not evaluate to a list value"); } } else { Root.AddError("Cannot find variable for " + ListExpression.ToString()); } }
/// <summary> /// Computes the changes related to this event /// </summary> /// <param name="apply">Indicates that the changes should be applied directly</param> /// <param name="runner"></param> public override bool ComputeChanges(bool apply, Runner runner) { bool retVal = base.ComputeChanges(apply, runner); if (retVal) { if (runner.Explain) { Explanation = new ExplanationPart(Action, "Action ", Action); } InterpretationContext context = new InterpretationContext(Instance); Changes = new ChangeList(); Action.GetChanges(context, Changes, Explanation, apply, runner); Changes.CheckChanges(Action); } 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) { 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) { 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); 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) { 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); int index = newListValue.Val.IndexOf(EfsSystem.Instance.EmptyValue); if (index >= 0) { ExplanationPart.CreateSubExplanation(explanation, "Inserting", value); newListValue.Val[index] = value; } 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); 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"); } } Change change = new Change(variable, variable.Value, newListValue); changes.Add(change, apply, runner); ExplanationPart.CreateSubExplanation(explanation, Root, change); } 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); } }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="activations"></param> /// <param name="updates"></param> /// <param name="priority"></param> public void EvaluateActivations(HashSet<Activation> activations, acceptor.RulePriority priority, ref List<VariableUpdate> updates) { Dictionary<IVariable, Change> changes = new Dictionary<IVariable, Change>(); Dictionary<Change, VariableUpdate> traceBack = new Dictionary<Change, VariableUpdate>(); 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, this, 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, this, false); ruleFired.AddVariableUpdate(variableUpdate); if (changesExplanation != null) { changesExplanation.SubExplanations.Add(variableUpdate.Explanation); } updates.Add(variableUpdate); if (CheckForCompatibleChanges) { ChangeList actionChanges = variableUpdate.Changes; if (variableUpdate.Action.Statement is ProcedureCallStatement) { Dictionary<IVariable, Change> procedureChanges = new Dictionary<IVariable, Change>(); foreach (Change change in variableUpdate.Changes.Changes) { procedureChanges[change.Variable] = change; } actionChanges = new ChangeList(); foreach (Change change in procedureChanges.Values) { actionChanges.Add(change, false, this); } } foreach (Change change in actionChanges.Changes) { IVariable variable = change.Variable; if (changes.ContainsKey(change.Variable)) { Change otherChange = changes[change.Variable]; Action otherAction = traceBack[otherChange].Action; if (!variable.Type.CompareForEquality(otherChange.NewValue, change.NewValue)) { string action1 = ((INamable) action.Enclosing).FullName + " : " + variableUpdate.Action.FullName; string action2 = ((INamable) otherAction.Enclosing).FullName + " : " + traceBack[otherChange].Action.FullName; variableUpdate.Action.AddError( "Simultaneous change of the variable " + variable.FullName + " with different values. Conflit between\n" + action1 + "\n and \n" + action2); } } else { changes.Add(change.Variable, change); traceBack.Add(change, variableUpdate); } } } } else { action.AddError("Cannot parse action statement"); } } } } // Handles the leave & enter state rules List<VariableUpdate> updatesToProcess = updates; updates = new List<VariableUpdate>(); // Avoid considering twice the same transition List<Tuple<State, State>> transitions = new List<Tuple<State, State>>(); while (updatesToProcess.Count > 0) { List<VariableUpdate> newUpdates = new List<VariableUpdate>(); foreach (VariableUpdate update in updatesToProcess) { updates.Add(update); foreach (Change change in update.Changes.Changes) { if (change.Variable.Type is StateMachine) { State leavingState = (State) change.PreviousValue; State enteringState = (State) change.NewValue; bool transitionFound = false; foreach (Tuple<State, State> transition in transitions) { if ((transition.Item1 == leavingState) && (transition.Item2 == enteringState)) { transitionFound = true; break; } } if (! transitionFound) { Tuple<State, State> transition = new Tuple<State, State>(leavingState, enteringState); transitions.Add(transition); HandleLeaveState(priority, newUpdates, change.Variable, leavingState, enteringState); HandleEnterState(priority, newUpdates, change.Variable, leavingState, enteringState); } } } } updatesToProcess = newUpdates; } }
/// <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 changes performed by this statement</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 abstract void GetChanges(InterpretationContext context, ChangeList changes, ExplanationPart explanation, bool apply, Runner runner);
/// <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 variable = ListExpression.GetVariable(context); // ReSharper disable once ConditionIsAlwaysTrueOrFalse changes.Add(new InsertInListChange(context, this, variable, explanation), apply, runner); }