/// <summary> /// Merges the other return value with this one /// </summary> /// <param name="previous">The previous ReturnValueElement which lead to this ReturnValueElement</param> /// <param name="other">The other return value to merge with</param> public void Merge(ReturnValueElement previous, ReturnValue other) { foreach (ReturnValueElement elem in other.Values) { Add(elem.Value, previous); } }
/// <summary> /// Indicates that the referenced value has been removed /// </summary> /// <param name="element"></param> /// <returns></returns> private bool ValueIsRemoved(ReturnValueElement element) { bool retVal = false; ModelElement model = element.Value as ModelElement; if (model != null) { retVal = model.IsRemoved; } return(retVal); }
/// <summary> /// Performs the semantic analysis of the expression /// </summary> /// <param name="instance">the reference instance on which this element should analysed</param> /// <param name="expectation">Indicates the kind of element we are looking for</param> /// <returns>True if semantic analysis should be continued</returns> public override bool SemanticAnalysis(INamable instance, BaseFilter expectation) { bool retVal = base.SemanticAnalysis(instance, expectation); if (retVal) { Ref = null; ReturnValue tmp = GetReferences(instance, expectation, false); if (tmp.IsUnique) { // Unique element has been found. Reference it and perform the semantic analysis // on all dereferenced expression, now that the context is known for each expression Ref = tmp.Values[0].Value; StaticUsage.AddUsage(Ref, Root, null); References referenceFilter; ReturnValueElement current = tmp.Values[0]; for (int i = Arguments.Count - 1; i > 0; i--) { referenceFilter = new References(current.Value); current = current.PreviousElement; Arguments[i].SemanticAnalysis(current.Value, referenceFilter); StaticUsage.AddUsages(Arguments[i].StaticUsage, null); StaticUsage.AddUsage(Arguments[i].Ref, Root, null); } referenceFilter = new References(current.Value); Arguments[0].SemanticAnalysis(null, referenceFilter); StaticUsage.AddUsages(Arguments[0].StaticUsage, null); StaticUsage.AddUsage(Arguments[0].Ref, Root, null); } else if (tmp.IsAmbiguous) { // Several possible interpretations for this deref expression, not allowed AddError("Expression " + ToString() + " may have several interpretations " + tmp + ", please disambiguate", RuleChecksEnum.SemanticAnalysisError); } else { // No possible interpretation for this deref expression, not allowed AddError("Expression " + ToString() + " has no interpretation", RuleChecksEnum.SemanticAnalysisError); } } return(retVal); }
/// <summary> /// Adds a new value in the set of return values /// </summary> /// <param name="value">The value to add</param> /// <param name="previous">The previous element in the chain</param> public void Add(Utils.INamable value, ReturnValueElement previous = null) { if (value != null) { bool found = false; foreach (ReturnValueElement elem in Values) { if (elem.Value == value) { found = true; break; } } if (!found) { Values.Add(new ReturnValueElement(value, previous)); } } }
/// <summary> /// Adds a new value in the set of return values /// </summary> /// <param name="value">The value to add</param> /// <param name="previous">The previous element in the chain</param> /// <param name="asType"></param> public void Add(INamable value, ReturnValueElement previous = null, bool asType = false) { if (value != null) { ReturnValueElement element = new ReturnValueElement(value, previous, asType); foreach (ReturnValueElement elem in Values) { if (elem.CompareTo(element) == 0) { element = null; break; } } if (element != null) { Values.Add(element); } } }
/// <summary> /// Constructor /// </summary> /// <param name="value"></param> /// <param name="previous"></param> public ReturnValueElement(Utils.INamable value, ReturnValueElement previous = null) { PreviousElement = previous; Value = value; }
/// <summary> /// Performs the semantic analysis of the expression /// </summary> /// <param name="instance">the reference instance on which this element should analysed</param> /// <paraparam name="expectation">Indicates the kind of element we are looking for</paraparam> /// <returns>True if semantic analysis should be continued</returns> public override bool SemanticAnalysis(Utils.INamable instance, Filter.AcceptableChoice expectation) { bool retVal = base.SemanticAnalysis(instance, expectation); if (retVal) { Ref = null; ReturnValue tmp = Arguments[0].getReferences(instance, Filter.AllMatches, false); if (tmp.IsEmpty) { tmp = Arguments[0].getReferenceTypes(instance, Filter.AllMatches, false); } if (!tmp.IsEmpty) { for (int i = 1; i < Arguments.Count; i++) { ReturnValue tmp2 = tmp; tmp = new ReturnValue(Arguments[i]); foreach (ReturnValueElement elem in tmp2.Values) { tmp.Merge(elem, Arguments[i].getReferences(elem.Value, Filter.AllMatches, i == (Arguments.Count - 1))); } if (tmp.IsEmpty) { AddError("Cannot find " + Arguments[i].ToString() + " in " + Arguments[i - 1].ToString()); } } } else { AddError("Cannot evaluate " + Arguments[0].ToString()); } tmp.filter(expectation); if (tmp.IsUnique) { // Unique element has been found. Reference it and perform the semantic analysis // on all dereferenced expression, now that the context is known for each expression Ref = tmp.Values[0].Value; ReturnValueElement current = tmp.Values[0]; for (int i = Arguments.Count - 1; i > 0; i--) { current = current.PreviousElement; Arguments[i].SemanticAnalysis(current.Value); } Arguments[0].SemanticAnalysis(); } else if (tmp.IsAmbiguous) { // Several possible interpretations for this deref expression, not allowed AddError("Expression " + ToString() + " may have several interpretations " + tmp.ToString() + ", please disambiguate"); } else { // No possible interpretation for this deref expression, not allowed AddError("Expression " + ToString() + " has no interpretation"); } } return(retVal); }
/// <summary> /// Indicates that the referenced value has been removed /// </summary> /// <param name="element"></param> /// <returns></returns> private bool ValueIsRemoved(ReturnValueElement element) { bool retVal = false; ModelElement model = element.Value as ModelElement; if (model != null) { retVal = model.IsRemoved; } return retVal; }
/// <summary> /// Provides the possible references for this expression (only available during semantic analysis) /// </summary> /// <param name="instance">the instance on which this element should be found.</param> /// <param name="expectation">the expectation on the element found</param> /// <param name="last">indicates that this is the last element in a dereference chain</param> /// <returns></returns> public override ReturnValue GetReferences(INamable instance, BaseFilter expectation, bool last) { ReturnValue retVal = Arguments[0].GetReferences(instance, AllMatches.INSTANCE, false); if (retVal.IsEmpty) { retVal = Arguments[0].GetReferenceTypes(instance, AllMatches.INSTANCE, false); } // When variables & parameters are found, only consider the first one // which is the one that is closer in the tree { ReturnValue tmp2 = retVal; retVal = new ReturnValue(); ReturnValueElement variable = null; foreach (ReturnValueElement elem in tmp2.Values) { if (elem.Value is Parameter || elem.Value is IVariable) { if (variable == null) { variable = elem; retVal.Values.Add(elem); } } else { retVal.Values.Add(elem); } } } if (retVal.IsUnique) { Arguments[0].Ref = retVal.Values[0].Value; } if (!retVal.IsEmpty) { for (int i = 1; i < Arguments.Count; i++) { ReturnValue tmp2 = retVal; retVal = new ReturnValue(Arguments[i]); foreach (ReturnValueElement elem in tmp2.Values) { bool removed = false; ModelElement model = elem.Value as ModelElement; if (model != null) { removed = model.IsRemoved; } if (!removed) { retVal.Merge(elem, Arguments[i].GetReferences(elem.Value, AllMatches.INSTANCE, i == (Arguments.Count - 1))); } } if (retVal.IsEmpty) { AddError("Cannot find " + Arguments[i] + " in " + Arguments[i - 1], RuleChecksEnum.SemanticAnalysisError); } if (retVal.IsUnique) { Arguments[i].Ref = retVal.Values[0].Value; } } } else { AddError("Cannot evaluate " + Arguments[0], RuleChecksEnum.SemanticAnalysisError); } retVal.Filter(expectation); return(retVal); }
/// <summary> /// Filters out value according to predicate /// </summary> /// <param name="accept"></param> public void Filter(BaseFilter accept) { ApplyUpdates(); DiscardRemoved(); // Only keep the most specific elements. string mostSpecific = null; foreach (ReturnValueElement element in Values) { if (accept.AcceptableChoice(element.Value)) { if (mostSpecific == null) { mostSpecific = element.Value.FullName; } else { if (mostSpecific.Length < element.Value.FullName.Length) { mostSpecific = element.Value.FullName; } } } } // if the filtering is about variables, ensure that there is at least one variable in the element chain if (accept is IsVariable) { List <ReturnValueElement> tmp = new List <ReturnValueElement>(); foreach (ReturnValueElement element in Values) { bool variableFound = false; bool onlyStructureElement = true; ReturnValueElement current = element; while (!variableFound && current != null) { variableFound = IsStrictVariableOrValue.INSTANCE.AcceptableChoice(current.Value) || current.AsType; onlyStructureElement = onlyStructureElement && current.Value is StructureElement; current = current.PreviousElement; } if (variableFound) { tmp.Add(element); } else if (onlyStructureElement) { tmp.Add(element); } } // HaCK : If tmp is empty, this indicates that the filter above is too restrictive. // Keep the original set if (tmp.Count > 0) { Values = tmp; } } // Build a new list with the filtered out elements bool variable = false; { List <ReturnValueElement> tmp = new List <ReturnValueElement>(); foreach (ReturnValueElement element in Values) { if (accept.AcceptableChoice(element.Value) && (mostSpecific == null || mostSpecific.Equals(element.Value.FullName))) { tmp.Add(element); variable = variable || element.Value is IVariable; } } Values = tmp; } // HaCK : If both Variable and StructureElement are found, only keep the variable if (variable) { List <ReturnValueElement> tmp = new List <ReturnValueElement>(); foreach (ReturnValueElement element in Values) { if (!(element.Value is StructureElement) && !(element.Value is Type)) { tmp.Add(element); } } Values = tmp; } }