blob: 6aa786429d5f0182f7fc2674875dc8cdfdfc086f [file] [log] [blame]
-- @atlcompiler emftvm
-- @nsURI EMFTVM=http://www.eclipse.org/m2m/atl/2011/EMFTVM
-- @path ATL=/org.eclipse.m2m.atl.common/src/org/eclipse/m2m/atl/common/resources/ATL.ecore
-- @path Problem=/org.eclipse.m2m.atl.common/src/org/eclipse/m2m/atl/common/resources/Problem.ecore
-- Transforms ATL modules into EMFTVM modules
-- $Id: OCLtoEMFTVM.atl,v 1.5 2012/04/08 14:34:47 dwagelaar Exp $
module OCLtoEMFTVM;
create OUT : EMFTVM, PBS : Problem from IN : ATL;
-- ======================================================================
-- helpers begin
-- ======================================================================
helper context String def : lazyOperation : String =
if self = '=' then 'equals'
else if self = 'indexOf' then 'indexOf2'
else if self = 'lastIndexOf' then 'lastIndexOf2'
else self endif endif endif;
helper def : SetType : String = 'Set';
helper def : BagType : String = 'Bag';
helper def : SequenceType : String = 'Sequence';
helper def : OrderedSetType : String= 'OrderedSet';
helper def : MapType : String = 'Map';
helper def : TupleType_ : String = 'Tuple';
helper def : MapImplType : String = 'java.util.HashMap';
helper context ATL!"OclType" def : typeName : String =
'Object'; -- OclType is a direct OclType, which is either a Class or an EClass
helper context ATL!SetType def : typeName : String =
thisModule.SetType;
helper context ATL!BagType def : typeName : String =
thisModule.BagType;
helper context ATL!SequenceType def : typeName : String =
thisModule.SequenceType;
helper context ATL!OrderedSetType def : typeName : String =
thisModule.OrderedSetType;
helper context ATL!IntegerType def : typeName : String =
'Integer';
helper context ATL!StringType def : typeName : String =
'String';
helper context ATL!MapType def : typeName : String =
'Map';
helper context ATL!"TupleType" def : typeName : String =
'Tuple';
helper context ATL!OclAnyType def : typeName : String =
'Object';
helper context ATL!BooleanType def : typeName : String =
'Boolean';
helper context ATL!RealType def : typeName : String =
'Real';
helper context ATL!OclModelElement def : typeName : String =
self.name;
helper context ATL!"OclType" def : modelName : String =
'#native';
helper context ATL!OclModelElement def : modelName : String =
self.model.name;
helper context ATL!"OclType" def : sameAs(other : ATL!"OclType") : Boolean =
self.typeName = other.typeName and self.modelName = other.modelName;
helper context ATL!OclFeatureDefinition def : isAttribute : Boolean =
self.feature.oclIsKindOf(ATL!Attribute);
helper context ATL!OclFeatureDefinition def : isOperation : Boolean =
self.definition.feature.oclIsKindOf(ATL!Operation);
helper context ATL!OclFeatureDefinition def : isStatic : String =
self.context_.oclIsUndefined();
helper context ATL!OclFeature def : isStatic : String =
self.definition.isStatic;
helper context ATL!OclFeatureDefinition def : contextType : ATL!"OclType" =
self.context_.context_;
helper context ATL!OclFeature def : contextType : ATL!"OclType" =
self.definition.contextType;
helper context ATL!OclExpression def : hasSelf : Boolean =
let a : ATL!Attribute = self.owningAttribute in
if a.oclIsUndefined() then
let o : ATL!Operation = self.owningOperation in
if o.oclIsUndefined() then false else
not o.isStatic
endif
else
not a.isStatic
endif;
helper context ATL!OclExpression def : selfType : ATL!"OclType" =
let a : ATL!Attribute = self.owningAttribute in
if a.oclIsUndefined() then
let o : ATL!Operation = self.owningOperation in
if o.oclIsUndefined() then '' else
o.contextType
endif
else
a.contextType
endif;
helper context OclAny def : parentFeatureDef : ATL!OclFeatureDefinition =
let parent : OclAny = self.refImmediateComposite() in
if parent.oclIsKindOf(ATL!OclFeatureDefinition) then parent
else if not parent.oclIsUndefined() then parent.parentFeatureDef
else self.debug('Self variable not found in')
endif endif;
helper context ATL!PropertyCallExp def : isStatic : Boolean =
if self.source.oclIsKindOf(ATL!VariableExp) then
self.source.referredVariable.varName = 'thisModule'
else self.source.oclIsUndefined() endif;
helper context ATL!OclExpression def : parentIterators : Sequence(ATL!Iterator) =
if self.loopExp.oclIsUndefined() then Sequence{}
else self.loopExp.iterators endif;
helper context ATL!OclExpression def : parentAccumulators : Sequence(ATL!VariableDeclaration) =
let loop : ATL!LoopExp = self.loopExp in
if loop.oclIsUndefined() then Sequence{}
else if loop.oclIsKindOf(ATL!IterateExp) then Sequence{loop.result}
else Sequence{} endif endif;
helper context ATL!VariableDeclaration def : isMatchedRuleField : Boolean =
false;
helper context ATL!VariableExp def : localVariable() : EMFTVM!LocalVariable =
thisModule.resolveTemp(self.referredVariable, 'lv');
--- Returns a Sequence of the elements from a location string
--- (e.g. Sequence{278, 1, 283, 14} for '278:1-283:14')
helper context ATL!LocatedElement def : splitLocation : Sequence(String) =
self.location.split('-|:');
--- Returns start line from a location string (e.g. 278 for '278:1-283:14')
helper context ATL!LocatedElement def : startLine : Integer =
self.splitLocation->at(1).toInteger();
--- Returns start column from a location string (e.g. 1 for '278:1-283:14')
helper context ATL!LocatedElement def : startColumn : Integer =
self.splitLocation->at(2).toInteger();
--- Returns end line from a location string (e.g. 283 for '278:1-283:14')
helper context ATL!LocatedElement def : endLine : Integer =
self.splitLocation->at(3).toInteger();
--- Returns end column from a location string (e.g. 14 for '278:1-283:14')
helper context ATL!LocatedElement def : endColumn : Integer =
self.splitLocation->at(4).toInteger();
--- Returns 'true' if this OCL expression is part of a rule's input filter.
helper context OclAny def : isFilterExpression : Boolean =
false;
--- Returns 'true' if this OCL expression is part of a rule's input filter.
helper context ATL!OclExpression def : isFilterExpression : Boolean =
let parent : OclAny = self.refImmediateComposite() in
(parent.oclIsKindOf(ATL!InPattern) and parent.filter = self)
or parent.isFilterExpression;
--- Returns 'true' if this OCL expression is a rule search plan.
helper context OclAny def : isSearchPlan : Boolean =
false;
--- Returns 'true' if this OCL expression is a rule search plan.
helper context ATL!OperationCallExp def : isSearchPlan : Boolean =
not self.isStatic and (
(
(self.operationName = '=' or self.operationName = 'includes') and
self.arguments->includes(a |
a.oclIsKindOf(ATL!VariableExp) and a.referredVariable.isMatchedRuleField
)
) or (
self.operationName = 'and' and
self.arguments->includes(a |
a.isSearchPlan
)
)
);
--- Returns 'true' if this OCL expression is part of a rule search plan.
helper context ATL!NavigationOrAttributeCallExp def : isSearchPlanExpression : Boolean =
not self.isStatic and self.refImmediateComposite().isSearchPlanExpression;
-- ======================================================================
-- helpers end
-- ======================================================================
-- ======================================================================
-- matched rules begin
-- ======================================================================
-------------- OclFeatureDefinitions -----------------
abstract rule Field {
from s : ATL!OclFeatureDefinition in IN (s.isAttribute)
using {
a : ATL!Attribute = s.feature;
}
to t : EMFTVM!Field (
name <:= a.name,
type <:= a.type.typeName,
typeModel <:= a.type.modelName,
initialiser <:= cb),
cb : EMFTVM!CodeBlock (
lineNumbers <:= Sequence{ln},
nested <- Sequence{a.initExpression},
code <:= Sequence{invokeCb}),
ln : EMFTVM!LineNumber (
startLine <:= s.startLine,
startColumn <:= s.startColumn,
endLine <:= s.endLine,
endColumn <:= s.endColumn,
instructions <:= Sequence{invokeCb}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- a.initExpression, argcount <- 0)
}
rule StaticField extends Field {
from s : ATL!OclFeatureDefinition in IN (
s.isAttribute and s.isStatic)
to t : EMFTVM!Field (
static <- true,
"context" <- 'ExecEnv',
contextModel <- 'EMFTVM')
}
rule InstanceField extends Field {
from s : ATL!OclFeatureDefinition in IN (
s.isAttribute and not s.isStatic)
to t : EMFTVM!Field (
static <- false,
"context" <- s.contextType.typeName,
contextModel <- s.contextType.modelName),
cb : EMFTVM!CodeBlock (
localVariables <:= Sequence{lv}),
lv : EMFTVM!LocalVariable (
name <- 'self',
type <- s.contextType.typeName,
typeModel <- s.contextType.modelName)
}
abstract rule Operation {
from s : ATL!OclFeatureDefinition in IN (s.feature.oclIsKindOf(ATL!Operation))
using {
o : ATL!Operation = s.feature;
}
to t : EMFTVM!Operation (
name <- o.name,
type <- o.returnType.typeName,
typeModel <- o.returnType.modelName,
parameters <- o.parameters,
body <- cb),
cb : EMFTVM!CodeBlock (
lineNumbers <:= Sequence{ln},
nested <- Sequence{o.body},
code <:= Sequence{invokeCb}),
ln : EMFTVM!LineNumber (
startLine <:= s.startLine,
startColumn <:= s.startColumn,
endLine <:= s.endLine,
endColumn <:= s.endColumn,
instructions <:= Sequence{invokeCb}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- o.body, argcount <- 0)
}
rule StaticOperation extends Operation {
from s : ATL!OclFeatureDefinition in IN (s.feature.oclIsKindOf(ATL!Operation) and s.isStatic)
using {
o1 : ATL!Operation = s.feature; -- Do not allow access to inherited 'o' variable!!!
}
to t : EMFTVM!Operation (
static <- true,
"context" <- 'ExecEnv',
contextModel <- 'EMFTVM'),
cb : EMFTVM!CodeBlock (
localVariables <- o1.parameters->collect(p|thisModule.resolveTemp(p, 'lv')))
}
rule InstanceOperation extends Operation {
from s : ATL!OclFeatureDefinition in IN (s.feature.oclIsKindOf(ATL!Operation) and not s.isStatic)
using {
o1 : ATL!Operation = s.feature;
}
to t : EMFTVM!Operation (
static <- false,
"context" <- s.contextType.typeName,
contextModel <- s.contextType.modelName),
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.modelName)
}
rule Parameter {
from s : ATL!Parameter in IN
to t : EMFTVM!Parameter (
name <:= s.varName,
type <:= s.type.typeName,
typeModel <:= s.type.modelName),
lv : EMFTVM!LocalVariable (
name <:= s.varName,
type <:= s.type.typeName,
typeModel <:= s.type.modelName)
}
-------------- VariableDeclarations -----------------
rule Iterator {
from s : ATL!Iterator in IN
to lv : EMFTVM!LocalVariable (
name <:= s.varName)
}
rule IteratorWithType extends Iterator {
from s : ATL!Iterator in IN (not s.type.oclIsUndefined())
to lv : EMFTVM!LocalVariable (
type <:= s.type.typeName,
typeModel <:= s.type.modelName)
}
rule IterateResult {
from s : ATL!VariableDeclaration in IN (not s.baseExp.oclIsUndefined())
to lv : EMFTVM!LocalVariable (
name <:= s.varName,
type <:= s.type.typeName,
typeModel <:= s.type.modelName)
}
-------------- OclExpressions -----------------
abstract rule OclExpression {
from s : ATL!OclExpression in IN
to cb : EMFTVM!CodeBlock (
localVariables <- s.parentIterators->union(s.parentAccumulators),
lineNumbers <:= Sequence{ln}),
ln : EMFTVM!LineNumber (
startLine <:= s.startLine,
startColumn <:= s.startColumn,
endLine <:= s.endLine,
endColumn <:= s.endColumn)
}
rule NavigationOrAttributeCallExp extends OclExpression {
from s : ATL!NavigationOrAttributeCallExp in IN (
not s.source.oclIsKindOf(ATL!SuperExp) and
not s.isStatic and
not (s.refImmediateComposite().oclIsKindOf(ATL!BindingStat) and s.refImmediateComposite().source = s))
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.source},
code <:= Sequence{invokeCb, get}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, get}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., result]
get : EMFTVM!Get (fieldname <- s.name) -- [..., value]
}
rule StaticNavigationOrAttributeCallExp extends OclExpression {
from s : ATL!NavigationOrAttributeCallExp in IN (
s.isStatic and
not (s.refImmediateComposite().oclIsKindOf(ATL!BindingStat) and s.refImmediateComposite().source = s))
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.source},
code <:= Sequence{invokeCb, getStatic}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, getStatic}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., result]
getStatic : EMFTVM!GetStatic (fieldname <- s.name) -- [..., value]
}
rule SuperNavigationOrAttributeCallExp extends OclExpression {
from s : ATL!NavigationOrAttributeCallExp in IN (
s.source.oclIsKindOf(ATL!SuperExp))
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.source},
code <:= Sequence{invokeCb, getSuper}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, getSuper}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., result]
getSuper : EMFTVM!GetSuper (fieldname <- s.name) -- [..., value]
}
rule OperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and
not s.source.oclIsKindOf(ATL!SuperExp) and
s.operationName <> 'not' and
s.operationName <> 'and' and
s.operationName <> 'or' and
s.operationName <> 'xor' and
s.operationName <> 'implies' and
s.operationName <> 'oclIsUndefined')
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeAllCbs, invoke}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeAllCbs, invoke}),
invokeAllCbs : EMFTVM!InvokeAllCbs, -- [..., source, args]
invoke : EMFTVM!Invoke ( -- [..., result]
opname <- s.operationName,
argcount <- s.arguments->size())
}
rule NotOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and s.operationName = 'not')
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeCb, _not}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, _not}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
_not : EMFTVM!Not -- [..., result]
}
rule AndOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and s.operationName = 'and')
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeCb, _and}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, _and}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
_and : EMFTVM!And (codeBlock <- s.arguments->first()) -- [..., result]
}
rule OrOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and s.operationName = 'or')
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeCb, _or}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, _or}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
_or : EMFTVM!Or (codeBlock <- s.arguments->first()) -- [..., result]
}
rule ImpliesOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and s.operationName = 'implies')
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeCb, _implies}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, _implies}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
_implies : EMFTVM!Implies (codeBlock <- s.arguments->first()) -- [..., result]
}
rule XorOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and s.operationName = 'xor')
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->including(s.source),
code <:= Sequence{invokeCb, invokeCb2, _xor}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, invokeCb2, _xor}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
invokeCb2 : EMFTVM!InvokeCb (codeBlock <- s.arguments->first(), argcount <- 0), -- [..., source, arg1]
_xor : EMFTVM!Xor -- [..., result]
}
rule OclIsUndefinedOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and s.operationName = 'oclIsUndefined')
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.source},
code <:= Sequence{invokeCb, isnull}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, isnull}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
isnull : EMFTVM!Isnull -- [..., result]
}
rule StaticOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
s.isStatic)
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeAllCbs, invokeStatic}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeAllCbs, invokeStatic}),
invokeAllCbs : EMFTVM!InvokeAllCbs, -- [..., type, args]
invokeStatic : EMFTVM!InvokeStatic ( -- [..., result]
opname <- s.operationName,
argcount <- s.arguments->size())
}
rule SuperOperationCallExp extends OclExpression {
from s : ATL!OperationCallExp in IN (
not s.isStatic and
s.source.oclIsKindOf(ATL!SuperExp))
to cb : EMFTVM!CodeBlock (
nested <- s.arguments->prepend(s.source),
code <:= Sequence{invokeAllCbs, invokeSuper}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeAllCbs, invokeSuper}),
invokeAllCbs : EMFTVM!InvokeAllCbs, -- [..., self, args]
invokeSuper : EMFTVM!InvokeSuper ( -- [..., result]
opname <- s.operationName,
argcount <- s.arguments->size())
}
rule CollectionOperationCallExp extends OperationCallExp {
from s : ATL!CollectionOperationCallExp in IN
to cb : EMFTVM!CodeBlock,
invoke : EMFTVM!Invoke (
opname <- s.operationName.lazyOperation)
}
rule SuperCollectionOperationCallExp extends SuperOperationCallExp {
from s : ATL!CollectionOperationCallExp in IN
to cb : EMFTVM!CodeBlock,
invokeSuper : EMFTVM!InvokeSuper (
opname <- s.operationName.lazyOperation)
}
rule LetExp extends OclExpression {
from s : ATL!LetExp in IN
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.variable},
code <:= Sequence{invokeCb}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.variable, argcount <- 0) -- [..., result]
}
rule LetVariable {
from s : ATL!VariableDeclaration in IN (not s.letExp.oclIsUndefined())
to cb : EMFTVM!CodeBlock (
localVariables <:= Sequence{lv},
lineNumbers <:= Sequence{ln},
nested <- Sequence{s.initExpression, s.letExp.in_},
code <:= Sequence{invokeCb, store, invokeCb2}),
lv : EMFTVM!LocalVariable (
name <:= s.varName,
type <:= s.type.typeName,
typeModel <:= s.type.modelName),
ln : EMFTVM!LineNumber (
startLine <:= s.startLine,
startColumn <:= s.startColumn,
endLine <:= s.endLine,
endColumn <:= s.endColumn,
instructions <:= Sequence{invokeCb, store, invokeCb2}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.initExpression, argcount <- 0), -- [..., value]
store : EMFTVM!Store (localVariable <- lv), -- [...]
invokeCb2 : EMFTVM!InvokeCb (codeBlock <- s.letExp.in_) -- [..., result]
}
abstract rule VariableExp extends OclExpression {
from s : ATL!VariableExp in IN (
s.referredVariable.varName <> 'thisModule' and
not s.referredVariable.isMatchedRuleField and
not (s.refImmediateComposite().oclIsKindOf(ATL!BindingStat) and s.refImmediateComposite().source = s))
to cb : EMFTVM!CodeBlock (
code <:= Sequence{load}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{load}),
load : EMFTVM!Load -- [..., value]
}
rule NotSelfVariableExp extends VariableExp {
from s : ATL!VariableExp in IN (
s.referredVariable.varName <> 'self')
to cb : EMFTVM!CodeBlock,
load : EMFTVM!Load (
localVariable <- s.localVariable())
}
rule SelfVariableExp extends VariableExp {
from s : ATL!VariableExp in IN (
s.referredVariable.varName = 'self')
to cb : EMFTVM!CodeBlock,
load : EMFTVM!Load (
localVariable <- thisModule.resolveTemp(s.parentFeatureDef, 'lv'))
}
rule SuperExp extends OclExpression {
from s : ATL!SuperExp in IN
to cb : EMFTVM!CodeBlock (
code <:= Sequence{load}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{load}),
load : EMFTVM!Load (
localVariable <- thisModule.resolveTemp(s.parentFeatureDef, 'lv'))
}
rule ThisModuleVariableExp extends OclExpression {
from s : ATL!VariableExp in IN (
s.referredVariable.varName = 'thisModule' and
not s.referredVariable.isMatchedRuleField)
to cb : EMFTVM!CodeBlock (
code <:= Sequence{getenvtype}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{getenvtype}),
getenvtype : EMFTVM!Getenvtype -- [..., envtype]
}
rule RuleVariableExp extends OclExpression {
from s : ATL!VariableExp in IN (
s.referredVariable.isMatchedRuleField and
not (s.refImmediateComposite().oclIsKindOf(ATL!BindingStat) and s.refImmediateComposite().source = s))
to cb : EMFTVM!CodeBlock (
code <:= Sequence{load, get}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{load, get}),
load : EMFTVM!Load (localVariable <- s.traceVariable()), -- [..., trace]
get : EMFTVM!Get (fieldname <- s.referredVariable.varName) -- [..., value]
}
rule IteratorExp extends OclExpression {
from s : ATL!IteratorExp in IN
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.source, s.body},
code <:= Sequence{invokesource, getbody, invoke}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokesource, getbody, invoke}),
invokesource : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
getbody : EMFTVM!Getcb (codeBlock <- s.body), -- [..., soure, cb]
invoke : EMFTVM!Invoke (opname <- s.name, argcount <- 1) -- [..., coll]
}
rule IteratorExp2 extends IteratorExp {
from s : ATL!IteratorExp in IN (s.iterators->size() = 2)
to cb : EMFTVM!CodeBlock,
invoke : EMFTVM!Invoke (opname <- s.name + '2', argcount <- 1)
}
rule IterateExp extends OclExpression {
from s : ATL!IterateExp in IN
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.source, s.result.initExpression, s.body},
code <:= Sequence{invokesource, invokeCb, getbody, invoke}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokesource, invokeCb, getbody, invoke}),
invokesource : EMFTVM!InvokeCb (codeBlock <- s.source, argcount <- 0), -- [..., source]
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.result.initExpression), -- [..., source, acc]
getbody : EMFTVM!Getcb (codeBlock <- s.body), -- [..., source, acc, cb]
invoke : EMFTVM!Invoke (opname <- 'iterate', argcount <- 2) -- [..., acc]
}
rule StringExp extends OclExpression {
from s : ATL!StringExp in IN
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Push (value <- s.stringSymbol) -- [..., string]
}
rule IntegerExp extends OclExpression {
from s : ATL!IntegerExp in IN
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Push (value <- s.integerSymbol) -- [..., integer]
}
rule RealExp extends OclExpression {
from s : ATL!RealExp in IN
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Push (value <- s.realSymbol) -- [..., real]
}
rule BooleanTrueExp extends OclExpression {
from s : ATL!BooleanExp in IN (s.booleanSymbol)
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Pusht -- [..., true]
}
rule BooleanFalseExp extends OclExpression {
from s : ATL!BooleanExp in IN (not s.booleanSymbol)
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Pushf -- [..., false]
}
abstract rule CollectionExp extends OclExpression {
from s : ATL!CollectionExp in IN
using {
invokes : Sequence(EMFTVM!Instruction) =
s.elements->collect(e|thisModule.CollectionElement(e))->flatten();
}
to cb : EMFTVM!CodeBlock (
nested <- s.elements,
code <:= Sequence{findtype, new}->union(invokes)),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{findtype, new}->union(invokes)),
findtype : EMFTVM!Findtype, -- override -- [..., colltype]
new : EMFTVM!New -- [..., coll]
}
rule SequenceExp extends CollectionExp {
from s : ATL!SequenceExp in IN
to cb : EMFTVM!CodeBlock,
findtype : EMFTVM!Findtype (modelname <- '#native', typename <- thisModule.SequenceType)
}
rule SetExp extends CollectionExp {
from s : ATL!SetExp in IN
to cb : EMFTVM!CodeBlock,
findtype : EMFTVM!Findtype (modelname <- '#native', typename <- thisModule.SetType)
}
rule BagExp extends CollectionExp {
from s : ATL!BagExp in IN
to cb : EMFTVM!CodeBlock,
findtype : EMFTVM!Findtype (modelname <- '#native', typename <- thisModule.BagType)
}
rule OrderedSetExp extends CollectionExp {
from s : ATL!OrderedSetExp in IN
to cb : EMFTVM!CodeBlock,
findtype : EMFTVM!Findtype (modelname <- '#native', typename <- thisModule.OrderedSetType)
}
rule MapExp extends OclExpression {
from s : ATL!MapExp in IN
using {
puts : Sequence(EMFTVM!Instruction) =
s.elements->collect(e|thisModule.MapElement(e))->flatten();
}
to cb : EMFTVM!CodeBlock (
nested <- s.elements->collect(e | Sequence{e.key, e.value})->flatten(),
code <:= Sequence{findtype, new}->union(puts)),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{findtype, new}->union(puts)),
findtype : EMFTVM!Findtype ( -- [..., MapImplType]
modelname <- '#native',
typename <- thisModule.MapImplType),
new : EMFTVM!New -- [..., map]
}
rule TupleExp extends OclExpression {
from s : ATL!TupleExp in IN
using {
puts : Sequence(EMFTVM!Instruction) =
s.tuplePart->collect(e|thisModule.TuplePart(e))->flatten();
}
to cb : EMFTVM!CodeBlock (
nested <- s.tuplePart->collect(e | e.initExpression),
code <:= Sequence{findtype, findtype2, new}->union(puts)->append(invokeFromMap)),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{findtype, findtype2, new}->union(puts)->append(invokeFromMap)),
findtype : EMFTVM!Findtype ( -- [..., TupleType]
modelname <- '#native',
typename <- thisModule.TupleType_),
findtype2 : EMFTVM!Findtype ( -- [..., TupleType, MapImplType]
modelname <- '#native',
typename <- thisModule.MapImplType),
new : EMFTVM!New, -- [..., TupleType, map]
invokeFromMap : EMFTVM!InvokeStatic ( -- [..., tuple]
opname <- 'fromMap', argcount <- 1)
}
rule OclTypeExp extends OclExpression { -- Only used as an expression, not as a type declaration
from s : ATL!"OclType" in IN (
s.attribute.oclIsUndefined() and -- not used as an attribute type
s.definitions.oclIsUndefined() and -- not used as a context type definition
s.operation.oclIsUndefined() and -- not used as an operation return type
s.mapType2.oclIsUndefined() and -- not used as a map element type(?)
s.mapType.oclIsUndefined() and -- not used as a map element type
s.collectionTypes.oclIsUndefined() and -- not used as a collection element type
s.tupleTypeAttribute.oclIsUndefined() and -- not used as a tuple element type
s.variableDeclaration.oclIsUndefined()) -- not used as a variable declaration type
to cb : EMFTVM!CodeBlock (
code <:= Sequence{findtype}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{findtype}),
findtype : EMFTVM!Findtype ( -- [..., type]
modelname <- s.modelName,
typename <- s.typeName)
}
rule OclUndefinedExp extends OclExpression {
from s : ATL!OclUndefinedExp in IN
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Push -- NULL -- [..., null]
}
rule EnumLiteralExp extends OclExpression {
from s : ATL!EnumLiteralExp in IN
to cb : EMFTVM!CodeBlock (
code <:= Sequence{push}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{push}),
push : EMFTVM!Push (enumValue <- s.name) -- [..., enumValue]
}
rule IfExp extends OclExpression {
from s : ATL!IfExp in IN
to cb : EMFTVM!CodeBlock (
nested <- Sequence{s.condition, s.thenExpression, s.elseExpression},
code <:= Sequence{invokeCb, ifte}),
ln : EMFTVM!LineNumber (
instructions <:= Sequence{invokeCb, ifte}),
invokeCb : EMFTVM!InvokeCb (codeBlock <- s.condition, argcount <- 0), -- [..., cond]
ifte : EMFTVM!Ifte (thenCb <- s.thenExpression, elseCb <- s.elseExpression) -- [..., result]
}
-- ======================================================================
-- matched rules end
-- ======================================================================
-- ======================================================================
-- lazy rules begin
-- ======================================================================
lazy rule CollectionElement {
from s : ATL!OclExpression
to invokeCb : EMFTVM!InvokeCb (codeBlock <- s), -- [..., coll, element]
invoke : EMFTVM!Invoke (opname <- 'including', argcount <- 1) -- [..., coll]
do {
Sequence{invokeCb, invoke};
}
}
lazy rule MapElement {
from s : ATL!MapElement
to dup : EMFTVM!Dup, -- [..., map, map]
invokeKey : EMFTVM!InvokeCb (codeBlock <- s.key), -- [..., map, map, key]
invokeValue : EMFTVM!InvokeCb (codeBlock <- s.value), -- [..., map, map, key, value]
invoke : EMFTVM!Invoke (opname <- 'put', argcount <- 2), -- [..., map, value]
pop : EMFTVM!Pop -- [..., map]
do {
Sequence{dup, invokeKey, invokeValue, invoke, pop};
}
}
lazy rule TuplePart {
from s : ATL!TuplePart
to dup : EMFTVM!Dup, -- [..., map, map]
pushKey : EMFTVM!Push (value <- s.varName), -- [..., map, map, key]
invokeValue : EMFTVM!InvokeCb (codeBlock <- s.initExpression), -- [..., map, map, key, value]
invoke : EMFTVM!Invoke (opname <- 'put', argcount <- 2), -- [..., map, value]
pop : EMFTVM!Pop -- [..., map]
do {
Sequence{dup, pushKey, invokeValue, invoke, pop};
}
}
-- ======================================================================
-- lazy rules end
-- ======================================================================