private void AddAnyOptions(IteratorExp node) { if (node.Iterator.Count == 1) { TranslationOption optionFor = new TranslationOption(); optionFor.FormatString = string.Format("(for ${0} in {{0}} return if ({{1}}) then ${0} else ())[1]", node.Iterator[0].Name); optionFor.ParenthesisWhenNotTopLevel = true; SubexpressionTranslations.AddTranslationOption(node, optionFor); bool canRewrite = true; SubexpressionCollector collector = new SubexpressionCollector(); collector.Visit(node); List <LoopExp> loopSubExps = collector.Expressions.OfType <LoopExp>().ToList(); foreach (LoopExp nestedLoopExp in loopSubExps) { collector.Clear(); nestedLoopExp.Accept(collector); if (collector.ReferredVariables.Contains(node.Iterator[0])) { canRewrite = false; break; } } if (canRewrite) { TranslationOption optionFilter = new TranslationOption(); optionFilter.ContextVariableForSubExpressions = node.Iterator[0]; optionFilter.FormatString = string.Format("({{0}}[{{1}}])[1]"); optionFilter.ParenthesisWhenNotTopLevel = true; SubexpressionTranslations.AddTranslationOption(node, optionFilter); } } }
public override void Visit(OperationCallExp node) { if (node.ReferredOperation != null && node.ReferredOperation.Tag is NextOperationTag) { node.Source.Accept(this); TranslationOption option = new TranslationOption(); option.FormatString = "oclX:apply-templates({0})"; SubexpressionTranslations.AddTranslationOption(node, option, node.Source); return; } base.Visit(node); if (OperationRewritings.IsEmpty()) { OperationRewritings[OperationHelper.firstOperationInfo] = AddFirstRewritings; OperationRewritings[OperationHelper.lastOperationInfo] = AddLastRewritings; OperationRewritings[OperationHelper.atOperationInfo] = AddAtRewritings; } { TranslationOption standardTranslation = SubexpressionTranslations.GetSubexpressionTranslation(node); OperationInfo? operationInfo = OperationHelper.LookupOperation(node, standardTranslation.OptionsContainer.SubExpressions.ToArray()); if (operationInfo != null && OperationRewritings.ContainsKey(operationInfo.Value)) { OperationRewritings[operationInfo.Value](node, operationInfo.Value); } } }
private void AddClosureOptions(IteratorExp node) { if (node.Iterator.Count == 1) { if (node.Body is PropertyCallExp) { PSMPath path = PSMPathBuilder.BuildPSMPath((PropertyCallExp)node.Body, OclContext, VariableNamer, buildPathParams); // oclX:closure(departments/department, function($c) { $c/subdepartments/department })/name // departments/department/descendant-or-self::department /* * departments/department + /subdepartments/department */ if (PathsJoinable(path, node) && path.IsDownwards && path.Steps.Count > 0) { TranslationOption descendantOption = new TranslationOption(); string lastStep = path.Steps.Last().ToXPath(); if (lastStep.StartsWith("/")) { lastStep = lastStep.Substring(1); } descendantOption.FormatString = string.Format("{{0}}/descendant-or-self::{0}", lastStep); SubexpressionTranslations.AddTranslationOption(node, descendantOption); } } } }
public virtual void Visit(OperationCallExp node) { AssignIsPartOfIteratorBody(node); OclExpression[] arguments = new OclExpression[node.Arguments.Count + 1]; if (node.Source is PropertyCallExp) { this.Visit((PropertyCallExp)node.Source, true); } else { node.Source.Accept(this); } arguments[0] = node.Source; for (int i = 0; i < node.Arguments.Count; i++) { if (node.Arguments[i] is PropertyCallExp) { this.Visit((PropertyCallExp)node.Arguments[i], true); } else { node.Arguments[i].Accept(this); } arguments[i + 1] = node.Arguments[i]; } TranslationOption option = new TranslationOption(); option.FormatString = OperationHelper.CreateBasicFormatString(node, arguments); this.SubexpressionTranslations.AddTranslationOption(node, option, arguments); }
public override void Visit(IteratorExp node) { base.Visit(node); node.Source.Accept(this); loopStack.Push(node); node.Body.Accept(this); TranslationOption option = new TranslationOption(); if (node.Iterator.Count == 1) { option.FormatString = string.Format("oclX:{0}({{0}}, function(${1}) {{{{ {{1}} }}}})", node.IteratorName, node.Iterator[0].Name); } else { option.FormatString = string.Format("oclX:{0}N({{0}}, function({1}) {{{{ {{1}} }}}})", node.IteratorName, node.Iterator.ConcatWithSeparator(vd => "$" + vd.Name, ", ")); } loopStack.Pop(); SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Body); if (PredefinedIteratorExpressionRewritings.ContainsKey(node.IteratorName)) { PredefinedIteratorExpressionRewritings[node.IteratorName](node); } }
public override void Visit(IteratorExp node) { base.Visit(node); node.Source.Accept(this); loopStack.Push(node); var prevInsideDynamicEvaluation = insideDynamicEvaluation; insideDynamicEvaluation = true; node.Body.Accept(this); insideDynamicEvaluation = prevInsideDynamicEvaluation; string apostrophe = insideDynamicEvaluation ? "''" : "'"; TranslationOption option = new TranslationOption(); if (node.Iterator.Count == 1) { option.FormatString = string.Format("oclX:{0}({{0}}, {2}{1}{2}, {2}{{1}}{2}, $variables)", node.IteratorName, node.Iterator[0].Name, apostrophe); } else { option.FormatString = string.Format("oclX:{0}N({{0}}, {2}{1}{2}, {2}{{1}}{2}, $variables)", node.IteratorName, node.Iterator.ConcatWithSeparator(vd => vd.Name, ", "), apostrophe); } SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Body); loopStack.Pop(); }
public virtual void Visit(PropertyCallExp node, bool isOperationArgument) { AssignIsPartOfIteratorBody(node); PSMPath psmPath = PSMPathBuilder.BuildPSMPath(node, OclContext, VariableNamer, buildPathParams); string xpath = psmPath.ToXPath(delayFirstVariableStep: true); if (!isOperationArgument) { string wrapString = OperationHelper.WrapAtomicOperand(node, null, 0); xpath = string.Format(wrapString, xpath); } var steps = psmPath.Steps.OfType <IPSMPathStepWithCardinality>().Where(s => s.Lower == 0); if (steps.Any()) { Log.AddWarningTaggedFormat("Navigation using '{0}' may result in 'null', which will be an empty sequence in XPath. ", node, steps.ConcatWithSeparator(s => s.ToXPath(), ",")); } TranslationOption option = new TranslationOption(); if (psmPath.StartingVariableExp != null) { option.ContextVariableSubstitution = true; option.StartingVariable = psmPath.StartingVariableExp.referredVariable; } option.FormatString = xpath; SubexpressionTranslations.AddTranslationOption(node, option, psmPath.SubExpressions.ToArray()); }
public virtual void Visit(IfExp node) { node.Condition.Accept(this); node.ThenExpression.Accept(this); node.ElseExpression.Accept(this); TranslationOption option = new TranslationOption(); option.FormatString = "if ({0}) then {1} else {2}"; SubexpressionTranslations.AddTranslationOption(node, option, node.Condition, node.ThenExpression, node.ElseExpression); }
private void AddExistsOptions(IteratorExp node) { if (node.Iterator.Count == 1) { TranslationOption option = new TranslationOption(); option.ParenthesisWhenNotTopLevel = true; option.FormatString = string.Format("some ${0} in {{0}} satisfies {{1}}", node.Iterator[0].Name); SubexpressionTranslations.AddTranslationOption(node, option); } }
public override void Visit(LetExp node) { base.Visit(node); node.Variable.Value.Accept(this); node.InExpression.Accept(this); TranslationOption translationOption = new TranslationOption(); translationOption.FormatString = string.Format("for ${0} in {{0}} return {{1}}", node.Variable.Name); SubexpressionTranslations.AddTranslationOption(node, translationOption, node.Variable.Value, node.InExpression); }
public override void Visit(ClassLiteralExp node) { base.Visit(node); PSMPath psmPath = PSMPathBuilder.BuildPSMPath(node, OclContext, VariableNamer, buildPathParams); string xpath = psmPath.ToXPath(); TranslationOption option = new TranslationOption(); option.FormatString = xpath; SubexpressionTranslations.AddTranslationOption(node, option, psmPath.SubExpressions.ToArray()); }
public TranslationOption GetSubexpressionTranslation(OclExpression expression) { TranslationOption selectedOption = Translations[expression].Options[SelectedTranslations[expression]]; if (Log != null && selectedOption.LogMessagesWhenSelected != null) { foreach (var v in selectedOption.LogMessagesWhenSelected) { Log.AddLogMessage(v); } } return(selectedOption); }
public override void Visit(IterateExp node) { base.Visit(node); node.Source.Accept(this); loopStack.Push(node); node.Body.Accept(this); node.Result.Value.Accept(this); TranslationOption option = new TranslationOption(); option.FormatString = string.Format("oclX:iterate({{0}}, {{1}}, function(${0}, ${1}) {{{{ {{2}} }}}})", node.Iterator[0].Name, node.Result.Name); SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Result.Value, node.Body); loopStack.Pop(); }
public virtual void Visit(VariableExp node) { AssignIsPartOfIteratorBody(node); PSMPath psmPath = PSMPathBuilder.BuildPSMPath(node, OclContext, VariableNamer, buildPathParams); string xpath = psmPath.ToXPath(delayFirstVariableStep: true); TranslationOption option = new TranslationOption(); if (psmPath.StartingVariableExp != null) { option.ContextVariableSubstitution = true; option.StartingVariable = psmPath.StartingVariableExp.referredVariable; } option.FormatString = xpath; SubexpressionTranslations.AddTranslationOption(node, option, psmPath.SubExpressions.ToArray()); }
public void AddTrivialTranslation(OclExpression expression, string translation) { TranslationOptions options = new TranslationOptions(); options.Expression = expression; options.SubexpressionTranslations = this; options.TranslatedExpression = expression; TranslationOption option = new TranslationOption(); option.OptionsContainer = options; option.FormatString = translation; if (this.Translations.ContainsKey(expression)) { throw new InvalidOperationException(string.Format("Expression '{0}' translated reapeatedly. ", expression)); } options.Options.Add(option); this.Translations[expression] = options; this.SelectedTranslations[expression] = 0; }
public void AddTranslationOption(OclExpression expression, TranslationOption option, params OclExpression[] subExpressions) { TranslationOptions options; if (!this.Translations.ContainsKey(expression)) { options = new TranslationOptions(); options.Expression = expression; options.SubexpressionTranslations = this; options.TranslatedExpression = expression; foreach (OclExpression subExpression in subExpressions) { options.SubExpressions.Add(subExpression); } this.Translations[expression] = options; } else { options = this.Translations[expression]; if (subExpressions != null && subExpressions.Length > 0) { if (subExpressions.Length != options.SubExpressions.Count) { throw new InvalidOperationException(string.Format("Inconsistency of subexpressions when adding options for '{0}'", expression)); } for (int index = 0; index < subExpressions.Length; index++) { OclExpression subExpression = subExpressions[index]; if (subExpression != options.SubExpressions[index]) { throw new InvalidOperationException(string.Format("Inconsistency of subexpressions when adding options for '{0}'", expression)); } } } } option.OptionsContainer = options; this.SelectedTranslations[expression] = 0; options.Options.Add(option); }
private void AddCollectionAccessRewritings(OperationCallExp operationCallExp, string accesExpr, OperationInfo operationInfo) { TranslationOption optionIndex = new TranslationOption(); SubexpressionTranslations.AddTranslationOption(operationCallExp, optionIndex); // XPath filter changes context - no variable corresponds to the context in this case optionIndex.ContextVariableForSubExpressions = null; optionIndex.ContextVariableChangeOnlyIn = 1; // in some special cases, parentheses can be omitted bool omitParentheses = false; if (operationCallExp.Source is LiteralExp) { omitParentheses = true; } if (operationCallExp.Source is VariableExp) { omitParentheses = true; } if (!operationInfo.IsXPathInfix && !operationInfo.IsXPathPrefix && !operationInfo.IsAmong(OperationHelper.firstOperationInfo, OperationHelper.lastOperationInfo, OperationHelper.atOperationInfo)) { omitParentheses = true; } if (omitParentheses) { optionIndex.FormatString = string.Format("({{0}})[{0}]", accesExpr); } else { optionIndex.FormatString = string.Format("({{0}})[{0}]", accesExpr); } optionIndex.LogMessagesWhenSelected = new List <LogMessage <OclExpression> >(); optionIndex.LogMessagesWhenSelected.Add(new LogMessage <OclExpression>() { Tag = operationCallExp, MessageText = "Using indexing returns empty sequence when indexes are out of bounds (no error reported, unlike in OCL). " }); }
public override void Visit(IterateExp node) { base.Visit(node); node.Source.Accept(this); loopStack.Push(node); node.Result.Value.Accept(this); var prevInsideDynamicEvaluation = insideDynamicEvaluation; insideDynamicEvaluation = true; node.Body.Accept(this); insideDynamicEvaluation = prevInsideDynamicEvaluation; string apostrophe = insideDynamicEvaluation ? "''" : "'"; TranslationOption option = new TranslationOption(); option.FormatString = string.Format("oclX:iterate({{0}}, {2}{0}{2}, {2}{1}{2}, {2}{{1}}{2}, {2}{{2}}{2}, $variables)", node.Iterator[0].Name, node.Result.Name, apostrophe); loopStack.Pop(); SubexpressionTranslations.AddTranslationOption(node, option, node.Source, node.Result.Value, node.Body); }
protected override string TupleLiteralToXPath(TupleLiteralExp tupleLiteral, List <OclExpression> subExpressions) { StringBuilder formatBuilder = new StringBuilder(); formatBuilder.Append("(map{{"); foreach (KeyValuePair <string, TupleLiteralPart> kvp in tupleLiteral.Parts) { kvp.Value.Value.Accept(this); formatBuilder.AppendFormat("'{0}' := {{{1}}}, ", kvp.Value.Attribute.Name, subExpressions.Count); subExpressions.Add(kvp.Value.Value); } if (formatBuilder.Length > 0) { formatBuilder.Length = formatBuilder.Length - 2; } formatBuilder.Append("}})"); TranslationOption option = new TranslationOption(); option.FormatString = formatBuilder.ToString(); SubexpressionTranslations.AddTranslationOption(tupleLiteral, option, subExpressions.ToArray()); return(option.FormatString); }
private void AddCollectOptions(IteratorExp node) { if (node.Iterator.Count == 1) { TranslationOption option = new TranslationOption(); option.ParenthesisWhenNotTopLevel = true; option.FormatString = string.Format("for ${0} in {{0}} return {{1}}", node.Iterator[0].Name); SubexpressionTranslations.AddTranslationOption(node, option); /* when the body of collect is a navigation that can be chained, replace it */ if (node.Body is PropertyCallExp) { PSMPath path = PSMPathBuilder.BuildPSMPath((PropertyCallExp)node.Body, OclContext, VariableNamer, buildPathParams); if (PathsJoinable(path, node)) { TranslationOption option2 = new TranslationOption(); option2.FormatString = string.Format("{{0}}{0}", path.ToXPath(withoutFirstStep: true)); SubexpressionTranslations.AddTranslationOption(node, option2); } } } }
protected override string ClassLiteralToXPath(ClassLiteralExp tupleLiteral, List <OclExpression> subExpressions) { StringBuilder formatBuilder = new StringBuilder(); string elementName = EvolutionAssignmentStack.Peek() != null ? (EvolutionAssignmentStack.Peek().PSMAssociation != null ? EvolutionAssignmentStack.Peek().PSMAssociation.Name: string.Empty): string.Empty; formatBuilder.AppendFormat("oclX:genericConstructor('{0}', map {{{{", elementName); foreach (KeyValuePair <string, TupleLiteralPart> kvp in tupleLiteral.Parts) { kvp.Value.Value.Accept(this); formatBuilder.AppendFormat("'{0}' := {{{1}}}, ", kvp.Key, subExpressions.Count); subExpressions.Add(kvp.Value.Value); } if (formatBuilder.Length > 0) { formatBuilder.Length = formatBuilder.Length - 2; } formatBuilder.Append("}} )"); TranslationOption option = new TranslationOption(); option.FormatString = formatBuilder.ToString(); SubexpressionTranslations.AddTranslationOption(tupleLiteral, option, subExpressions.ToArray()); return(option.FormatString); }
private VariableDeclaration FindContextVariable() { VariableDeclaration result = null; TranslationOption co = this.CallingOption; while (co != null) { if (co.ContextVariableForSubExpressions != null && (co.ContextVariableChangeOnlyIn == -1 || co.ContextVariableChangeOnlyIn == this.SubexpressionIndex)) { result = co.ContextVariableForSubExpressions; break; } if (co.CallingOption == null) { result = co.OptionsContainer.Expression.ConstraintContext.Self; } co = co.CallingOption; } return(result); }
public virtual void Visit(CollectionLiteralExp node) { AssignIsPartOfIteratorBody(node); StringBuilder formatBuilder = new StringBuilder(); List <OclExpression> subExpressions = new List <OclExpression>(); // opening parenthesis of xpath sequence literal formatBuilder.Append("("); foreach (CollectionLiteralPart clp in node.Parts) { #region helper function Action <OclExpression> appendOne = delegate(OclExpression exp) { if (exp is LiteralExp) { formatBuilder.Append("{"); formatBuilder.Append(subExpressions.Count); formatBuilder.Append("}"); } else { formatBuilder.Append("{("); formatBuilder.Append(subExpressions.Count); formatBuilder.Append(")}"); } }; #endregion if (clp is CollectionRange) { CollectionRange range = ((CollectionRange)clp); range.First.Accept(this); range.Last.Accept(this); appendOne(range.First); subExpressions.Add(range.First); formatBuilder.Append(" to "); appendOne(range.Last); subExpressions.Add(range.Last); } if (clp is CollectionItem) { CollectionItem collectionItem = (CollectionItem)clp; collectionItem.Item.Accept(this); appendOne(collectionItem.Item); subExpressions.Add(collectionItem.Item); } formatBuilder.Append(", "); } if (formatBuilder.Length > 1) // remove last comma { formatBuilder.Length = formatBuilder.Length - 2; } // closing parenthesis of xpath sequence literal formatBuilder.Append(")"); TranslationOption option = new TranslationOption(); option.FormatString = formatBuilder.ToString(); SubexpressionTranslations.AddTranslationOption(node, option, subExpressions.ToArray()); }
private void AddSelectRejectOptions(IteratorExp node, bool select) { // select and reject differ only in not() applied in filter if (node.Iterator.Count == 1) { TranslationOption optionFor = new TranslationOption(); optionFor.ParenthesisWhenNotTopLevel = true; if (select) { optionFor.FormatString = string.Format("for ${0} in {{0}} return if ({{1}}) then ${0} else ()", node.Iterator[0].Name); } else { optionFor.FormatString = string.Format( "for ${0} in {{0}} return if (not({{1}})) then ${0} else ()", node.Iterator[0].Name); } SubexpressionTranslations.AddTranslationOption(node, optionFor); /* * this option can be used only when there is no iterator in body, which references the current iterator variable, * because there is no XPath variable corresponding to the iterator variable (context is used instead). */ { bool canRewrite = true; SubexpressionCollector collector = new SubexpressionCollector(); collector.Visit(node); List <LoopExp> loopSubExps = collector.Expressions.OfType <LoopExp>().ToList(); foreach (LoopExp nestedLoopExp in loopSubExps) { collector.Clear(); nestedLoopExp.Accept(collector); if (collector.ReferredVariables.Contains(node.Iterator[0])) { canRewrite = false; break; } } if (canRewrite) { TranslationOption optionFilter = new TranslationOption(); optionFilter.ContextVariableForSubExpressions = node.Iterator[0]; if (select) { optionFilter.FormatString = string.Format("{{0}}[{{1}}]"); } else { optionFilter.FormatString = string.Format("{{0}}[not({{1}})]"); } SubexpressionTranslations.AddTranslationOption(node, optionFilter); } else // translation with let { TranslationOption optionFilterLet = new TranslationOption(); optionFilterLet.ContextVariableForSubExpressions = node.Iterator[0]; if (select) { optionFilterLet.FormatString = string.Format("{{0}}[let ${0} := . return {{1}}]", node.Iterator[0].Name); } else { optionFilterLet.FormatString = string.Format("{{0}}[let ${0} := . return not({{1}})]", node.Iterator[0].Name); } SubexpressionTranslations.AddTranslationOption(node, optionFilterLet); } } } }
public string GetString(bool topLevel) { object[] translatedSubexpressions = new object[OptionsContainer.SubExpressions.Count]; for (int index = 0; index < OptionsContainer.SubExpressions.Count; index++) { OclExpression subExpression = OptionsContainer.SubExpressions[index]; TranslationOption selectedSubexpressionTranslationOption = OptionsContainer.SubexpressionTranslations.GetSubexpressionTranslation(subExpression); foreach (TranslationOption subexpressionTranslationOption in OptionsContainer.SubexpressionTranslations.Translations[subExpression].Options) { subexpressionTranslationOption.CallingOption = this; subexpressionTranslationOption.SubexpressionIndex = index; } translatedSubexpressions[index] = selectedSubexpressionTranslationOption.GetString(false); } string result = null; if (!ContextVariableSubstitution) { result = string.Format(FormatString, translatedSubexpressions); } else { bool standardVariableTranslation = true; if (StartingVariable == FindContextVariable()) { if (SubexpressionTranslations.XPathContextVariableReplacementMode == SubexpressionTranslations.EContextVariableReplacementMode.AnyContextVariable) { result = string.Format(FormatString, @"."); if (result.StartsWith(@"./")) { result = result.Substring(2); } standardVariableTranslation = false; } else //i.e. SubexpressionTranslations.ContextVariableReplacementMode == SubexpressionTranslations.EContextVariableReplacementMode.OutermostSelfOnly { if (!this.OptionsContainer.Expression.IsPartOfIteratorBody && StartingVariable.IsContextVariable) { result = string.Format(FormatString, @"."); if (result.StartsWith(@"./")) { result = result.Substring(2); } standardVariableTranslation = false; } } } if (standardVariableTranslation) { result = string.Format(FormatString, "$" + StartingVariable.Name); } } if (ParenthesisWhenNotTopLevel && !topLevel) { return("(" + result + ")"); } else { return(result); } }