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(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 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(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(); }
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(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()); }
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 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); }
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 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()); }
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); }
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); } } } }