| source cs : 'generated/MiniOCLCS.ecore#/' |
| target as : '/resource/org.eclipse.qvtd.doc.miniocl/model/MiniOCL.ecore#/' |
| |
| helpers { |
| as::Class { |
| commonSupertype(another : Class) : Class := |
| let allSupertypes = self->asOrderedSet()->closure(superClasses), |
| allOtherSupertypes = another->asOrderedSet()->closure(superClasses) |
| in allSupertypes->intersection(allOtherSupertypes)->any(true); |
| conformsTo(another : Class) : Boolean := |
| self = another or |
| superClasses->exists(conformsTo(another)); |
| } |
| |
| cs::NavigationExpCS { |
| parentAsCallExpCS() : CallExpCS := |
| let container = self.oclContainer() |
| in if container.oclIsKindOf(CallExpCS) |
| then container.oclAsType(CallExpCS) |
| else null |
| endif; |
| } |
| cs::NameExpCS { |
| isNavExpOfACallExpCS() : Boolean := |
| let parentCallExpCS = parentAsCallExpCS() |
| in parentCallExpCS <> null and parentCallExpCS.navExp = self; |
| } |
| cs::PropertyCS { |
| computeLowerBound() : Integer := |
| if multiplicity = null then 0 |
| else if multiplicity.opt then 0 |
| else if multiplicity.mult then 0 |
| else if multiplicity.mandatory <> 0 then multiplicity.mandatory |
| else multiplicity.lowerInt |
| endif endif endif |
| endif; |
| computeUpperBound() : Integer := |
| if multiplicity = null then 1 |
| else if multiplicity.opt then 1 |
| else if multiplicity.mult then -1 |
| else if multiplicity.mandatory <> 0 then multiplicity.mandatory |
| else if multiplicity.upperMult then -1 |
| else multiplicity.upperInt |
| endif endif endif endif |
| endif; |
| } |
| } |
| |
| disambiguation { |
| CollectionLiteralPartCS { |
| withoutLastExpression := last = null; |
| withLastExpression := last <> null; |
| } |
| |
| NameExpCS { -- Note: order of the disambiguation rules matters |
| isOpCallExpWithExplicitSource := |
| roundedBrackets <> null and isNavExpOfACallExpCS(); |
| isOpCallExpWithImplicitSource := |
| roundedBrackets <> null and not isNavExpOfACallExpCS(); |
| isPropCallExpWithExplicitSource := |
| roundedBrackets = null and isNavExpOfACallExpCS(); |
| isVariableExp := |
| roundedBrackets = null and not isNavExpOfACallExpCS() |
| and lookup(Variable, expName.pathElements->first()) <> null; |
| isPropCallExpWithImplicitSource := |
| roundedBrackets = null and not isNavExpOfACallExpCS() |
| and lookup(Property, expName) <> null; |
| } |
| |
| LetExpCS { |
| singleVarDecl := letVars->size() = 1; |
| multipleVarDecls := letVars->size() > 1; |
| } |
| } |
| mappings { |
| create Root from RootCS { |
| ownedImports := imports.trace; |
| ownedPackages := packages.trace; |
| ownedConstraints := constraints.invariants.trace; |
| } |
| create Import from ImportCS { |
| alias := if alias = null then null else alias endif; |
| uri := uri; |
| } |
| create Constraint from InvariantCS { |
| ownedSpecification := as::ExpressionInOCL { |
| language = 'OCL', |
| ownedBody = exp.trace, |
| ownedSelfVar = as::Variable { name = 'self', |
| type = trace.constrainedElement } |
| }; |
| constrainedElement := lookup(Class, self.ConstraintsDefCS.typeRef); |
| } |
| create Package from PackageCS { |
| name := name; |
| ownedPackages := packages.trace; |
| ownedClasses := classes.trace; |
| } |
| create Class from ClassCS { |
| name := name; |
| ownedProperties := properties.trace; |
| ownedOperations := operations.trace; |
| superClasses := if _extends ->notEmpty() |
| then _extends->collect(x | lookup(Class,x)) |
| else OrderedSet{} |
| endif; |
| } |
| create Operation from OperationCS { |
| name := name; |
| type := lookup(Class, resultRef); |
| ownedParameters := params.trace; |
| ownedBodyExpression := as::ExpressionInOCL { |
| language = 'OCL', |
| ownedBody = body.trace, |
| ownedSelfVar = as::Variable {name = 'self' , type = trace.owningClass } |
| }; |
| } |
| |
| create Variable from ParameterCS { |
| name := name; |
| type := lookup(Class,typeRef); |
| } |
| |
| create Property from PropertyCS { |
| name := name; |
| lowerBound := computeLowerBound(); |
| upperBound := computeUpperBound(); |
| type := lookup(Class, typeRef); |
| } |
| -- Expressions |
| refer CallExp from CallExpCS := |
| self.navExp.trace; |
| |
| create OperationCallExp from EqualityExpCS { |
| ownedSource := left.trace; |
| ownedArguments := right.trace; |
| referredOperation := lookupExported(Operation, trace.ownedSource.type, |
| opName, trace.ownedArguments); |
| type := lookup(Class, 'Boolean'); |
| } |
| create VariableExp from NameExpCS |
| when fall_back { |
| referredVariable := null; |
| type := lookup(Class, 'OclVoid'); |
| } |
| create VariableExp from NameExpCS |
| when isVariableExp { |
| referredVariable := lookup(Variable, expName.pathElements->first()); |
| type := trace.referredVariable.type; |
| } |
| create PropertyCallExp from NameExpCS |
| when isPropCallExpWithExplicitSource { |
| ownedSource := parentAsCallExpCS()._source.trace; |
| referredProperty := lookupExported(Property,trace.ownedSource.type,expName); |
| type := trace.referredProperty?.type; |
| } |
| create PropertyCallExp from NameExpCS |
| when isPropCallExpWithImplicitSource { |
| ownedSource := let referredVar = lookup(Variable, 'self') |
| in as::VariableExp { |
| referredVariable = referredVar, |
| type = referredVar.type |
| }; |
| referredProperty := lookupExported(Property,trace.ownedSource.type,expName); |
| type := trace.referredProperty?.type; |
| } |
| create OperationCallExp from NameExpCS |
| when isOpCallExpWithExplicitSource { |
| ownedSource := parentAsCallExpCS()._source.trace; |
| ownedArguments := roundedBrackets.args.trace; |
| referredOperation := lookupExported(Operation,trace.ownedSource.type, |
| expName, trace.ownedArguments); |
| type := trace.referredOperation?.type; |
| } |
| create OperationCallExp from NameExpCS |
| when isOpCallExpWithImplicitSource { |
| ownedSource := let referredVar = lookup(Variable, 'self') |
| in as::VariableExp { |
| referredVariable = referredVar, |
| type = referredVar.type |
| }; |
| ownedArguments := roundedBrackets.args.trace; |
| referredOperation:= lookupExported(Operation,trace.ownedSource.type, |
| expName, trace.ownedArguments); |
| type := trace.referredOperation?.type; |
| } |
| |
| create LetExp from LetExpCS |
| when singleVarDecl { |
| ownedVariable := letVars->at(1).trace; |
| ownedIn := inExp.trace; |
| type := inExp.trace.type; |
| } |
| create LetExp from LetExpCS |
| when multipleVarDecls { |
| ownedVariable := letVars->first().trace; |
| ownedIn := letVars->excluding(letVars->first())->reverse() |
| ->iterate(x : LetVarCS; acc : as::OCLExpression = inExp.trace | |
| as::LetExp { |
| ownedVariable = x.trace, |
| ownedIn = acc, |
| type = acc.type |
| }); |
| type := inExp.trace.type; |
| } |
| create Variable from LetVarCS { |
| name := name; |
| ownedInitExp := initExp.trace; |
| type := if typeRef <> null then lookup(Class,typeRef) else trace.ownedInitExp.type endif; |
| } |
| |
| create IterateExp from IterateExpCS { |
| ownedIterator := itVar.trace; |
| ownedResult := accVar.trace; |
| ownedBody := exp.trace; |
| ownedSource := parentAsCallExpCS()._source.trace; |
| type := trace.ownedResult.type; |
| } |
| |
| create IteratorExp from CollectExpCS { |
| iterator := 'collect'; |
| ownedIterator := if itVar = null |
| then as::Variable { name='self', type=lookup(Class,'OclAny') } |
| else itVar.trace |
| endif; |
| ownedBody := exp.trace; |
| ownedSource := parentAsCallExpCS()._source.trace; |
| type := lookup(Class,'Collection'); |
| } |
| create Variable from IteratorVarCS { |
| name := itName; |
| type := if itType <> null then lookup(Class,itType) else lookup(Class,'OclAny') endif; |
| } |
| create Variable from AccVarCS { |
| name := accName; |
| ownedInitExp := accInitExp.trace; |
| type := if accType <> null then lookup(Class,accType) else trace.ownedInitExp.type endif; |
| } |
| create CollectionLiteralExp from CollectionLiteralExpCS { |
| kind := kind; |
| ownedParts := parts.trace; |
| type := lookup(Class,'Collection'); |
| } |
| create CollectionItem from CollectionLiteralPartCS |
| when withoutLastExpression { |
| ownedItem := first.trace; |
| type := trace.ownedItem.type; |
| } |
| create CollectionRange from CollectionLiteralPartCS |
| when withLastExpression { |
| ownedFirst := first.trace; |
| ownedLast := last.trace; |
| type := trace.ownedFirst.type; |
| } |
| } |
| |
| name_resolution { |
| targets { |
| NamedElement using name scaped_with '_'; |
| Package qualifies Package using ownedPackages, |
| Class using ownedClasses; |
| Class qualifies Operation using ownedOperations, |
| Property using ownedProperties; |
| Operation filtered_by arguments : OrderedSet(OCLExpression) |
| when ownedParameters->size() = arguments->size() and |
| arguments->forAll(x | |
| let argIdx = arguments->indexOf(x) |
| in x.type.conformsTo(ownedParameters->at(argIdx).type)); |
| Property; |
| Variable; |
| } |
| inputs { |
| PathElementCS using elementName; |
| qualifier PathNameCS using pathElements; |
| } |
| providers { |
| Root { |
| in current_scope provides adding |
| Package using ownedPackages, exported ownedImports; |
| } |
| |
| Import { |
| in exported_scope provides |
| Package using loaded Package from uri; |
| } |
| Package { |
| in current_scope provides occluding |
| Package using ownedPackages |
| Class using ownedClasses; |
| } |
| |
| Class { |
| vars allSuperClasses = self->closure(superClasses); |
| |
| in current_scope provides occluding |
| Operation using ownedOperations occluding allSuperClasses.ownedOperations |
| Property using ownedProperties occluding allSuperClasses.ownedProperties; |
| |
| in exported_scope provides |
| Operation using ownedOperations occluding allSuperClasses.ownedOperations |
| Property using ownedProperties occluding allSuperClasses.ownedOperations; |
| } |
| |
| Operation { |
| in current_scope provides occluding |
| Variable using ownedParameters; |
| } |
| |
| ExpressionInOCL { |
| in current_scope provides occluding |
| Variable using ownedSelfVar; |
| } |
| |
| LetExp { |
| in current_scope |
| for all excepting ownedVariable |
| provides occluding Variable using ownedVariable; |
| } |
| } |
| } |