-- @atlcompiler emftvm -- @nsURI EMFTVM=http://www.eclipse.org/m2m/atl/2011/EMFTVM -- @path OCL=/be.ac.vub.simpleocl/metamodel/simpleocl.ecore -- @path Problem=/be.ac.vub.simpleocl/metamodel/problem.ecore -- Transforms SimpleOCL modules into EMFTVM modules -- $Id$ module SimpleOCLtoEMFTVM; create OUT : EMFTVM, PBS : Problem from IN : OCL; uses SimpleOCLExptoEMFTVM; -- ====================================================================== -- helpers begin -- ====================================================================== helper context OCL!OclFeatureDefinition def : isAttribute : Boolean = self.feature.oclIsKindOf(OCL!Attribute); helper context OCL!OclFeatureDefinition def : isOperation : Boolean = self.definition.feature.oclIsKindOf(OCL!Operation); helper context OCL!ModuleElement def : isStatic : String = false; helper context OCL!OclFeatureDefinition def : isStatic : String = self.static; helper context OCL!OclFeature def : isStatic : String = self.definition.isStatic; helper context OCL!OclFeatureDefinition def : contextType : OCL!"OclType" = self.context_.contextType; helper context OCL!OclContextDefinition def : contextType : OCL!"OclType" = self.context_; helper context OclAny def : contextType : OCL!"OclType" = OclUndefined; -- null context helper context OCL!OclFeature def : contextType : OCL!"OclType" = self.definition.contextType; -- ====================================================================== -- helpers end -- ====================================================================== -- ====================================================================== -- matched rules begin -- ====================================================================== rule Module { from s : OCL!Module in IN to t : EMFTVM!Module ( name <- s.name, sourceName <- let index : Integer = s.name.lastIndexOf('::') in if index > 0 then s.name.substring(index + 2, s.name.size()) + '.simpleocl' else s.name + '.simpleocl' endif, imports <- s.imports->collect(i | i.name), features <- s.elements->select(e | e.oclIsKindOf(OCL!OclFeatureDefinition))) } rule ModuleWithoutMain extends Module { from s : OCL!Module in IN ( not s.elements->exists(f | f.isStatic and f.feature.oclIsKindOf(OCL!Operation) and f.feature.name = 'main')) to t : EMFTVM!Module ( features <- s.elements ->select(e | e.oclIsKindOf(OCL!OclFeatureDefinition)) ->including(main)), main : EMFTVM!Operation ( name <- 'main', static <- true, type <- 'Object', typeModel <- '#native', "context" <- 'ExecEnv', contextModel <- 'EMFTVM', body <- cb), cb : EMFTVM!CodeBlock } rule OclInstanceModel { from s : OCL!OclInstanceModel in IN to t : EMFTVM!ModelDeclaration ( modelName <- s.name, metaModelName <- s.metamodel.name) } -------------- OclFeatureDefinitions ----------------- rule Field { from s : OCL!OclFeatureDefinition in IN (s.isAttribute) using { a : OCL!Attribute = s.feature; } to t : EMFTVM!Field ( name <- a.name, static <- s.isStatic, type <- a.type.typeName, typeModel <- a.type.typeModelName, "context" <- s.contextType.typeName, contextModel <- s.contextType.typeModelName, initialiser <- cb), cb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln}, nested <- Sequence{a.initExpression}, code <- Sequence{invokeCb}), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{invokeCb}), invokeCb : EMFTVM!InvokeCb (codeBlock <- a.initExpression, argcount <- 0) } rule InstanceField extends Field { from s : OCL!OclFeatureDefinition in IN (not s.isStatic) to t : EMFTVM!Field, cb : EMFTVM!CodeBlock ( localVariables <- Sequence{lv}), lv : EMFTVM!LocalVariable ( name <- 'self', type <- s.contextType.typeName, typeModel <- s.contextType.typeModelName) } abstract rule Operation { from s : OCL!OclFeatureDefinition in IN (s.feature.oclIsKindOf(OCL!Operation)) using { o : OCL!Operation = s.feature; } to t : EMFTVM!Operation ( name <- o.name, type <- o.returnType.typeName, typeModel <- o.returnType.typeModelName, "context" <- s.contextType.typeName, contextModel <- s.contextType.typeModelName, parameters <- o.parameters, body <- cb), cb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln}, nested <- Sequence{o.body}, code <- Sequence{invokeCb}), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{invokeCb}), invokeCb : EMFTVM!InvokeCb (codeBlock <- o.body, argcount <- 0) } rule StaticOperation extends Operation { from s : OCL!OclFeatureDefinition in IN (s.isStatic) using { o1 : OCL!Operation = s.feature; } to t : EMFTVM!Operation ( static <- true), cb : EMFTVM!CodeBlock ( localVariables <- o1.parameters->collect(p|thisModule.resolveTemp(p, 'lv'))) } rule InstanceOperation extends Operation { from s : OCL!OclFeatureDefinition in IN (not s.isStatic) using { o1 : OCL!Operation = s.feature; } to t : EMFTVM!Operation ( static <- false), cb : EMFTVM!CodeBlock ( localVariables <- Sequence{lv}->union(o1.parameters->collect(p|thisModule.resolveTemp(p, 'lv')))), lv : EMFTVM!LocalVariable ( name <- 'self', type <- s.contextType.typeName, typeModel <- s.contextType.typeModelName) } rule InstanceOperationWithLambda extends InstanceOperation { from s : OCL!OclFeatureDefinition in IN ( s.feature.parameters->size() = 1 and s.feature.parameters->exists(p | let type : OclType = p.type in type.oclIsKindOf(OCL!LambdaType) and type.argumentTypes->size() > 1)) using { o2 : OCL!Operation = s.feature; } to t : EMFTVM!Operation ( name <- o2.name + s.feature.parameters.first().type.argumentTypes->size().toString()) } rule InstanceOperationWithInvalidLambda extends InstanceOperation { from s : OCL!OclFeatureDefinition in IN ( s.feature.parameters->size() > 1 and s.feature.parameters->exists(p | let type : OclType = p.type in type.oclIsKindOf(OCL!LambdaType))) to t : EMFTVM!Operation, pb : Problem!Problem ( description <- 'Only operations with a single Lambda parameter can be invoked from OCL', severity <- #warning, line <- s.line, column <- s.column, charStart <- s.charStart, charEnd <- s.charEnd) } rule Parameter { from s : OCL!Parameter in IN to t : EMFTVM!Parameter ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName), lv : EMFTVM!LocalVariable ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName) } -- ====================================================================== -- matched rules end -- ======================================================================