-- @atlcompiler emftvm -- @nsURI EMFTVM=http://www.eclipse.org/m2m/atl/2011/EMFTVM -- @nsURI OCL=http://soft.vub.ac.be/simpleocl/2011/SimpleOCL -- @nsURI Problem=http://soft.vub.ac.be/simpleocl/2011/Problem -- @path SimpleGT=/be.ac.vub.simplegt/model/simplegt.ecore -- Translates SimpleGT transformations to EMFTVM -- $Id$ module SimpleGTtoEMFTVM; create OUT : EMFTVM, PBS : Problem from IN : SimpleGT; uses SimpleOCLLib; uses SimpleOCLtoEMFTVM; -- ====================================================================== -- helpers begin -- ====================================================================== helper def : CollectionType : String= 'Collection'; helper context SimpleGT!InputElementPattern def : patternFor : SimpleGT!Rule = OclUndefined; helper context SimpleGT!InPattern def : patternFor : SimpleGT!Rule = self.inputFor; helper context SimpleGT!NacPattern def : patternFor : SimpleGT!Rule = self.nacFor; helper context SimpleGT!OutPattern def : patternFor : SimpleGT!Rule = self.outputFor; helper context SimpleGT!Rule def : allInputPatterns : Sequence(SimpleGT!InputElementPattern) = if self.input.oclIsUndefined() then Sequence{} else Sequence{self.input} endif ->union(self.nac); -- Returns 'true' if any contained rule elements have bindings. helper context SimpleGT!InputElementPattern def : hasBindings : Boolean = self.elements->exists(e|e.bindings->notEmpty()); -- Returns all bindings contained in rule elements of this pattern. helper context SimpleGT!InputElementPattern def : bindings : Sequence(SimpleGT!InputBinding) = self.elements->collect(e|e.bindings)->flatten(); -- Returns 'true' if any contained rule elements have bindings. helper context SimpleGT!OutPattern def : hasBindings : Boolean = self.elements->exists(e|e.bindings->notEmpty()); -- Returns all bindings contained in rule elements of this pattern. helper context SimpleGT!OutPattern def : bindings : Sequence(SimpleGT!OutputBinding) = self.elements->collect(e|e.bindings)->flatten(); -- Returns 'true' if the input pattern rule elements have bindings. helper context SimpleGT!Rule def : hasInputBindings : Boolean = self.inputElements->exists(p|p.bindings->notEmpty()); -- Returns input elements contained in the input pattern, if any. helper context SimpleGT!Rule def : inputElements : Sequence(SimpleGT!InputElement) = if self.input.oclIsUndefined() then Sequence{} else self.input.elements endif; -- Returns the output elements contained in the output pattern, if any. helper context SimpleGT!Rule def : outputElements : Sequence(SimpleGT!OutputElement) = if self.output.oclIsUndefined() then Sequence{} else self.output.elements endif; -- Returns the new output elements contained in the output pattern, if any. helper context SimpleGT!Rule def : newOutputElements : Sequence(SimpleGT!OutputElement) = if self.output.oclIsUndefined() then Sequence{} else self.output.newElements endif; -- Returns all input elements with a name that has not been declared before, -- i.e. all unique input elements. helper context SimpleGT!Rule def : allInputElements : Sequence(SimpleGT!InputElement) = -- NAC elements are local to each NAC pattern, but input pattern elements are -- accessible from each NAC pattern. Therefore, NAC elements that have the same -- name as an input element simply refer to the input element. self.nac->collect(p|p.elements)->flatten() ->iterate(e; acc : Sequence(SimpleGT!InputElement) = self.inputElements | if self.inputElements->exists(i|i.varName = e.varName) then acc else acc->including(e) endif); -- Returns all input element patterns that are relevant for the matcher operation. helper context SimpleGT!Rule def : matcherPatterns : Sequence(SimpleGT!InputElementPattern) = self.allInputPatterns->select(p|p.hasMatcherBindings or p.hasNewElements); -- Returns self. helper context OCL!VariableDeclaration def : refersTo : OCL!VariableDeclaration = self; -- Returns the original rule input element that any input element refers to. -- Applies to NAC and output elements that are aliases/repeats of input pattern elements. helper context SimpleGT!RuleElement def : refersTo : SimpleGT!RuleElement = if self.pattern.oclIsKindOf(SimpleGT!InPattern) then self else let inputElements : Sequence(SimpleGT!InputElement) = self.pattern.patternFor.inputElements ->select(e|e.varName = self.varName) in if inputElements->isEmpty() then self else inputElements->first() endif endif; -- Returns true if both rule elements refer to the same element. helper context SimpleGT!RuleElement def : sameAs(other : SimpleGT!RuleElement) : Boolean = self.refersTo = other.refersTo; helper context SimpleGT!InPattern def : hasNewElements : Boolean = false; helper context SimpleGT!NacPattern def : hasNewElements : Boolean = self.newElements->notEmpty(); helper context SimpleGT!OutPattern def : hasNewElements : Boolean = self.newElements->notEmpty(); helper context SimpleGT!InPattern def : newElements : Sequence(SimpleGT!InputElement) = Sequence{}; -- Returns only the contained rule elements that do not occur in the input pattern. helper context SimpleGT!NacPattern def : newElements : Sequence(SimpleGT!InputElement) = let elements : Sequence(SimpleGT!InputElement) = let input : SimpleGT!InPattern = self.nacFor.input in if input.oclIsUndefined() then self.elements else self.elements->reject(e|input.elements->exists(i|i.varName = e.varName)) endif in elements->reject(e|e.isBound)->union(elements->select(e|e.isBound)); -- Returns only the contained rule elements that do not occur in the input pattern. helper context SimpleGT!OutPattern def : newElements : Sequence(SimpleGT!OutputElement) = let input : SimpleGT!InPattern = self.outputFor.input in if input.oclIsUndefined() then self.elements else self.elements->reject(e|input.elements->exists(i|i.varName = e.varName)) endif; -- Returns the rule elements that occur in the input pattern, but not in the output pattern. helper context SimpleGT!Rule def : deletedElements : Sequence(SimpleGT!InputElement) = let input : SimpleGT!InPattern = self.input in let output : SimpleGT!OutPattern = self.output in if input.oclIsUndefined() then Sequence{} else if output.oclIsUndefined() then input.elements else input.elements->reject(e|output.elements->exists(i|i.varName = e.varName)) endif endif; helper context SimpleGT!OutputElement def : outModelName : String = if self.inModel.oclIsUndefined() then self.pattern.outputFor."module".models ->select(m|self.type.model = m.metamodel) ->first().name else self.inModel.name endif; helper context SimpleGT!Rule def : removedBindings : Sequence(SimpleGT!InputBinding) = let input : SimpleGT!InPattern = self.input in let output : SimpleGT!OutPattern = self.output in if input.oclIsUndefined() then Sequence{} else if output.oclIsUndefined() then input.bindings else input.bindings->reject(ib|output.bindings->exists(ob| ob.element.varName = ib.element.varName and ob.property = ib.property and ob.expr.sameAs(ib.expr))) endif endif; helper context SimpleGT!Rule def : addedBindings : Sequence(SimpleGT!OutputBinding) = let output : SimpleGT!OutPattern = self.output in let input : SimpleGT!InPattern = self.input in if output.oclIsUndefined() then Sequence{} else if input.oclIsUndefined() then output.bindings else output.bindings->reject(ob|input.bindings->exists(ib| ob.element.varName = ib.element.varName and ob.property = ib.property and ob.expr.sameAs(ib.expr))) endif endif; --- Returns false helper context OclAny def : isUsed : Boolean = false; --- Returns whether an OclExpression is used somewhere, and needs to be compiled. helper context OCL!LocatedElement def : isUsed : Boolean = let parent : OclAny = self.refImmediateComposite() in parent.oclIsKindOf(OCL!OclFeature) or if parent.oclIsKindOf(SimpleGT!InputBinding) then not parent.isElementBinding else if parent.oclIsKindOf(SimpleGT!OutputBinding) then parent.element.pattern.patternFor.addedBindings->includes(parent) else parent.isUsed endif endif; --- Returns whether an OclExpression is used in a rule's applier block, and needs to be --- compiled "twice" (i.e. as a secondary set of elements). helper context OCL!LocatedElement def : isUsedTwice : Boolean = let parent : OclAny = self.refImmediateComposite() in if parent.oclIsKindOf(SimpleGT!InputBinding) then parent.element.pattern.patternFor.removedBindings->includes(parent) else parent.isUsedTwice endif; helper context SimpleGT!InputElementPattern def : accessibleBindings : Sequence(SimpleGT!InputBinding) = self.bindings; helper context SimpleGT!NacPattern def : accessibleBindings : Sequence(SimpleGT!InputBinding) = if self.patternFor.input.oclIsUndefined() then self.bindings else self.bindings->union(self.patternFor.input.bindings) endif; helper context SimpleGT!InputElement def : isBound : Boolean = let pattern : SimpleGT!InputElementPattern = self.pattern in pattern.accessibleBindings->exists(b | b.element <> self and b.expr.oclIsKindOf(OCL!VariableExp) and b.expr.referredVariable = self ) and ( -- If all input pattern elements are bound, the first one must become unbound! pattern.oclIsKindOf(SimpleGT!NacPattern) or pattern.elements->first() <> self or pattern.elements->exists(e | e <> self and not e.isBound) ); helper context SimpleGT!InputElement def : bindingExp : OCL!VariableExp = self.pattern.accessibleBindings->any(b | b.element <> self and b.expr.oclIsKindOf(OCL!VariableExp) and b.expr.referredVariable = self ).expr; helper context OCL!VariableExp def : binding : SimpleGT!Binding = let parent : OclAny = self.refImmediateComposite() in if parent.oclIsKindOf(SimpleGT!Binding) then parent else OclUndefined endif; -- Whether self binds the value of another input element helper context SimpleGT!InputBinding def : isElementBinding : Boolean = self.element.pattern.patternFor.allInputElements ->exists(e|e.isBound and e.bindingExp.refImmediateComposite() = self); helper context SimpleGT!InputElement def : matcherBindings : Sequence(SimpleGT!InputBinding) = self.bindings->reject(b|b.isElementBinding); -- Returns 'true' if any contained rule elements have matcher bindings. helper context SimpleGT!InputElementPattern def : hasMatcherBindings : Boolean = self.elements->exists(e|e.matcherBindings->notEmpty()); -- Returns all matcher bindings contained in rule elements of this pattern. helper context SimpleGT!InputElementPattern def : matcherBindings : Sequence(SimpleGT!InputBinding) = self.elements->collect(e|e.matcherBindings)->flatten(); helper context OCL!VariableExp def : localVariable() : EMFTVM!LocalVariable = if self.isInApply then thisModule.resolveTemp(self.referredVariable.refersTo, 'ov') else thisModule.resolveTemp(self.referredVariable.refersTo, 'lv') endif; helper context OclAny def : isInApply : Boolean = let parent : OclAny = self.refImmediateComposite() in not parent.oclIsUndefined() and (parent.oclIsKindOf(SimpleGT!OutputBinding) or parent.isInApply); helper context OCL!VariableExp def : localVariable2() : EMFTVM!LocalVariable = thisModule.resolveTemp(self.referredVariable.refersTo, 'ov'); -- ====================================================================== -- helpers end -- ====================================================================== -- ====================================================================== -- matched rules begin -- ====================================================================== rule Module { from s : SimpleGT!"simplegt::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()) + '.simplegt' else s.name + '.simplegt' endif, imports <- s.imports->collect(i | i.name), inoutModels <- s.models, rules <- s.elements->select(e | e.oclIsKindOf(SimpleGT!Rule)), features <- s.elements->select(e | e.oclIsKindOf(OCL!OclFeatureDefinition))) } rule Rule { from s : SimpleGT!Rule in IN to t : EMFTVM!Rule ( name <- s.name, "abstract" <- s."abstract", default <- false, "unique" <- s."unique", distinctElements <- true, mode <- #automaticRecursive, superRules <- s."extends", inputElements <- s.inputElements, outputElements <- s.newOutputElements, applier <- a), a : EMFTVM!CodeBlock ( localVariables <- Sequence{a_trace} ->union(s.inputElements->collect(e|thisModule.resolveTemp(e, 'ov'))) ->union(s.newOutputElements->collect(e|thisModule.resolveTemp(e, 'ov'))), lineNumbers <- Sequence{a_ln}, nested <- s.addedBindings->select(b|not b.beforeElement.oclIsUndefined()) ->union(s.removedBindings->collect(r|thisModule.resolveTemp(r, 'cb2'))) ->union(s.addedBindings->select(b|b.beforeElement.oclIsUndefined())) ->union(s.deletedElements->collect(e|thisModule.resolveTemp(e, 'cb'))), code <- Sequence{a_invokeAllCbs}), a_ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{a_invokeAllCbs}), a_trace : EMFTVM!LocalVariable ( name <- '__trace__', type <- 'TraceLink', typeModel <- 'TRACE'), a_invokeAllCbs : EMFTVM!InvokeAllCbs -- [null] * nestedCb_size } rule RuleWithDebug extends Rule { from s : SimpleGT!Rule in IN ( s."module".debug) to t : EMFTVM!Rule, a : EMFTVM!CodeBlock ( code <- Sequence{a_invokeAllCbs, a_load, a_push, a_invoke, a_pop}), a_ln : EMFTVM!LineNumber ( instructions <- Sequence{a_invokeAllCbs, a_load, a_push, a_invoke, a_pop}), a_trace : EMFTVM!LocalVariable, a_invokeAllCbs : EMFTVM!InvokeAllCbs, -- [...] a_load : EMFTVM!Load (localVariable <- a_trace), -- [..., trace] a_push : EMFTVM!Push (stringValue <- 'Applied ' + s.name + ' to'), -- [..., trace, 'Applied...'] a_invoke : EMFTVM!Invoke (opname <- 'debug', argcount <- 1), -- [..., trace] a_pop : EMFTVM!Pop -- [...] } rule RuleWithMatcher extends Rule { from s : SimpleGT!Rule in IN ( s.matcherPatterns->notEmpty()) using { fp : SimpleGT!InputElementPattern = s.matcherPatterns->first(); rps : Sequence(SimpleGT!InputElementPattern) = s.matcherPatterns->excluding(fp); } to t : EMFTVM!Rule ( matcher <- m), m : EMFTVM!CodeBlock ( lineNumbers <- Sequence{mln}, localVariables <- s.inputElements ->collect(e|thisModule.resolveTemp(e, 'lv')), nested <- s.matcherPatterns, code <- rps->collect(b|thisModule.resolveTemp(b, 'and_')) ->prepend(invokeCb)), mln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- rps->collect(b|thisModule.resolveTemp(b, 'and_')) ->prepend(invokeCb)), invokeCb : EMFTVM!InvokeCb (codeBlock <- fp) -- [bool] } -- @extends RuleWithMatcher, RuleWithDebug rule RuleWithMatcherWithDebug { from s : SimpleGT!Rule in IN to t : EMFTVM!Rule } rule InPattern { from s : SimpleGT!InPattern in IN ( s.hasMatcherBindings) using { fb : SimpleGT!InputBinding = s.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln}, nested <- s.matcherBindings, code <- rbs->collect(b|thisModule.resolveTemp(b, 'and_')) ->prepend(invokeCb)), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- rbs->collect(b|thisModule.resolveTemp(b, 'and_')) ->prepend(invokeCb)), invokeCb : EMFTVM!InvokeCb (codeBlock <- fb) -- [bool] } rule InputElement { from s : SimpleGT!InputElement in IN ( s.pattern.oclIsKindOf(SimpleGT!InPattern)) to re : EMFTVM!InputRuleElement ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName, models <- if s.inModel.oclIsUndefined() then Sequence{} else Sequence{s.inModel.name} endif), ov : EMFTVM!LocalVariable ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName) } rule BoundInputElement extends InputElement { from s : SimpleGT!InputElement in IN ( s.isBound) using { locals : Sequence(EMFTVM!LocalVariable) = s.pattern.elements->collect(e|thisModule.CreateLocal(e)); } to re : EMFTVM!InputRuleElement ( binding <- bindingCb), bindingCb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{b_ln}, localVariables <- locals, code <- Sequence{b_load, b_get}), b_ln : EMFTVM!LineNumber ( startLine <- s.bindingExp.binding.line, startColumn <- s.bindingExp.binding.column, startChar <- s.bindingExp.binding.charStart, endChar <- s.bindingExp.binding.charEnd, instructions <- Sequence{b_load, b_get}), b_load : EMFTVM!Load ( -- [element] localVariable <- locals->at( s.pattern.elements->indexOf( s.bindingExp.binding.element))), b_get : EMFTVM!Get ( -- [value] fieldname <- s.bindingExp.binding.property) } rule LastBoundInputElement extends BoundInputElement { from s : SimpleGT!InputElement in IN ( s.bindingExp.binding.last) using { locals : Sequence(EMFTVM!LocalVariable) = s.pattern.elements->collect(e|thisModule.CreateLocal(e)); } to re : EMFTVM!InputRuleElement, bindingCb : EMFTVM!CodeBlock ( code <- Sequence{b_load, b_get, b_dup, b_findtype, b_invoke, b_ifn, b_dup2, b_invoke2, b_if, b_invoke3}), b_ln : EMFTVM!LineNumber ( instructions <- Sequence{b_load, b_get, b_dup, b_findtype, b_invoke, b_ifn, b_dup2, b_invoke2, b_if, b_invoke3}), b_load : EMFTVM!Load, -- [..., element] b_get : EMFTVM!Get, -- [..., values] b_dup : EMFTVM!Dup, -- [..., values, values] b_findtype : EMFTVM!Findtype ( -- [..., values, values, type] modelname <- '#native', typename <- thisModule.SequenceType), b_invoke : EMFTVM!Invoke ( -- [..., values, bool] opname <- 'oclIsKindOf', argcount <- 1), b_ifn : EMFTVM!Ifn (target <- b_invoke3), -- [..., values] b_dup2 : EMFTVM!Dup, -- [..., values, values] b_invoke2 : EMFTVM!Invoke ( -- [..., values, bool] opname <- 'isEmpty', argcount <- 0), b_if : EMFTVM!If (target <- b_invoke3), -- [..., values] b_invoke3 : EMFTVM!Invoke ( -- [..., value] opname <- 'last', argcount <- 0) } rule DeletedInputElement extends InputElement { from s : SimpleGT!InputElement in IN ( s.pattern.patternFor.deletedElements->includes(s)) to re : EMFTVM!InputRuleElement, ov : EMFTVM!LocalVariable, cb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln}, code <- Sequence{load, del}), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{load, del}), load : EMFTVM!Load (localVariable <- ov), -- [element] del : EMFTVM!Delete -- [] } -- @extends DeletedInputElement, BoundInputElement rule DeletedBoundInputElement { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } -- @extends DeletedBoundInputElement, LastBoundInputElement rule DeletedLastBoundInputElement { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } rule InputElementWithMatcher extends InputElement { from s : SimpleGT!InputElement in IN ( s.pattern.patternFor.matcherPatterns->notEmpty()) -- no matcher => no lv to re : EMFTVM!InputRuleElement, lv : EMFTVM!LocalVariable ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName) } -- @extends DeletedInputElement, InputElementWithMatcher rule DeletedInputElementWithMatcher { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } -- @extends BoundInputElement, InputElementWithMatcher rule BoundInputElementWithMatcher { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } -- @extends DeletedInputElementWithMatcher, BoundInputElementWithMatcher, DeletedBoundInputElement rule DeletedBoundInputElementWithMatcher { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } -- @extends LastBoundInputElement, BoundInputElementWithMatcher rule LastBoundInputElementWithMatcher { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } -- @extends DeletedBoundInputElementWithMatcher, LastBoundInputElementWithMatcher rule DeletedLastBoundInputElementWithMatcher { from s : SimpleGT!InputElement in IN to re : EMFTVM!InputRuleElement } abstract rule NacPattern { from s : SimpleGT!NacPattern in IN to cb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln}), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd) } rule NacPatternWithNewElements extends NacPattern { from s : SimpleGT!NacPattern in IN ( s.hasNewElements) using { fe : SimpleGT!InputElement = s.newElements->first(); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{fe}, code <- Sequence{invokeCb}), ln : EMFTVM!LineNumber ( instructions <- Sequence{invokeCb}), invokeCb : EMFTVM!InvokeCb (codeBlock <- fe) -- [bool] } rule NonFirstNacPatternWithNewElements extends NacPatternWithNewElements { from s : SimpleGT!NacPattern in IN ( s <> s.nacFor.matcherPatterns->first()) to cb : EMFTVM!CodeBlock, and_ : EMFTVM!And (codeBlock <- cb) -- AND instruction for parent code block } rule NacPatternWithOnlyBindings extends NacPattern { from s : SimpleGT!NacPattern in IN ( not s.hasNewElements and s.hasBindings) using { fb : SimpleGT!InputBinding = s.bindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.bindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( localVariables <- s.newElements, nested <- s.bindings, code <- rbs->collect(b|thisModule.resolveTemp(b, 'and_')) ->prepend(invokeCb)->append(not_)), ln : EMFTVM!LineNumber ( instructions <- rbs->collect(b|thisModule.resolveTemp(b, 'and_')) ->prepend(invokeCb)->append(not_)), invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [bool] not_ : EMFTVM!Not -- [bool] } rule NonFirstNacPatternWithOnlyBindings extends NacPatternWithOnlyBindings { from s : SimpleGT!NacPattern in IN ( s <> s.nacFor.matcherPatterns->first()) to cb : EMFTVM!CodeBlock, and_ : EMFTVM!And (codeBlock <- cb) -- AND instruction for parent code block } rule EmptyNacPattern extends NacPattern { from s : SimpleGT!NacPattern in IN ( s.newElements->isEmpty() and not s.hasBindings) to cb : EMFTVM!CodeBlock ( code <- Sequence{pushf}), ln : EMFTVM!LineNumber ( instructions <- Sequence{pushf}), pushf : EMFTVM!Pushf -- [bool] } abstract rule NacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.oclIsKindOf(SimpleGT!NacPattern) and s.pattern.newElements->includes(s)) to cb : EMFTVM!CodeBlock ( localVariables <- Sequence{lv}, lineNumbers <- Sequence{ln}), lv : EMFTVM!LocalVariable ( name <- s.varName, type <- s.type.typeName, -- NAC input elements have 'forall' semantics typeModel <- s.type.typeModelName), -- NAC elements are not available after matching(!) ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd) } abstract rule UnboundNacInputElement extends NacInputElement { from s : SimpleGT!InputElement in IN ( not s.isBound) to cb : EMFTVM!CodeBlock, findtype : EMFTVM!Findtype ( modelname <- s.type.typeModelName, typename <- s.type.typeName) -- [type] } abstract rule BoundNacInputElement extends NacInputElement { from s : SimpleGT!InputElement in IN ( s.isBound) to cb : EMFTVM!CodeBlock, load : EMFTVM!Load ( -- [..., element] localVariable <- thisModule.resolveTemp( s.bindingExp.binding.element.refersTo, 'lv')), get : EMFTVM!Get ( -- [..., values] fieldname <- s.bindingExp.binding.property), dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype ( -- [..., values, values, type] modelname <- '#native', typename <- thisModule.CollectionType), invoke : EMFTVM!Invoke ( -- [..., values, bool] opname <- 'oclIsKindOf', argcount <- 1) } abstract rule LastBoundNacInputElement extends BoundNacInputElement { from s : SimpleGT!InputElement in IN ( s.bindingExp.binding.last) to cb : EMFTVM!CodeBlock, load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn, -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype ( -- [..., values, values, type] modelname <- '#native', typename <- thisModule.SequenceType), invoke_s : EMFTVM!Invoke ( -- [..., values, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn_s : EMFTVM!Ifn, -- [..., values] invoke_last : EMFTVM!Invoke ( -- [..., value] opname <- 'last', argcount <- 0) } abstract rule UnboundLastNacInputElement extends UnboundNacInputElement { from s : SimpleGT!InputElement in IN ( s = s.pattern.newElements->last()) to cb : EMFTVM!CodeBlock } abstract rule BoundLastNacInputElement extends BoundNacInputElement { from s : SimpleGT!InputElement in IN ( not s.bindingExp.binding.last and s = s.pattern.newElements->last()) to cb : EMFTVM!CodeBlock } abstract rule LastBoundLastNacInputElement extends LastBoundNacInputElement { from s : SimpleGT!InputElement in IN ( s = s.pattern.newElements->last()) to cb : EMFTVM!CodeBlock } rule TerminatingNacInputElement extends UnboundLastNacInputElement { from s : SimpleGT!InputElement in IN ( not s.pattern.hasMatcherBindings and s.inModel.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{findtype, allinst, invoke}), ln : EMFTVM!LineNumber ( instructions <- Sequence{findtype, allinst, invoke}), findtype : EMFTVM!Findtype, -- [..., type] allinst : EMFTVM!Allinst, -- [..., coll] invoke : EMFTVM!Invoke (opname <- 'isEmpty', argcount <- 0) -- [..., bool] } rule TerminatingNacInputElementIn extends UnboundLastNacInputElement { from s : SimpleGT!InputElement in IN ( not s.pattern.hasMatcherBindings and not s.inModel.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{findtype, push, allinst, invoke}), ln : EMFTVM!LineNumber ( instructions <- Sequence{findtype, push, allinst, invoke}), findtype : EMFTVM!Findtype, -- [..., type] push : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., type, modelname] allinst : EMFTVM!AllinstIn, -- [..., coll] invoke : EMFTVM!Invoke (opname <- 'isEmpty', argcount <- 0) -- [..., bool] } rule BoundTerminatingNacInputElement extends BoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( not s.pattern.hasMatcherBindings and s.inModel.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{load, get, dup, findtype, invoke, ifn, it, findtype2, invoke2, if_, endit, pushf, goto, pop, pusht, goto2, findtype3, invoke3, not_}), ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, it, findtype2, invoke2, if_, endit, pushf, goto, pop, pusht, goto2, findtype3, invoke3, not_}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- goto2), -- [..., values] -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), bool] opname <- 'oclIsKindOf', argcount <- 1), if_ : EMFTVM!If (target <- goto), -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- invoke3), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] goto2 : EMFTVM!Goto (target <- invoke3), -- [..., true] -- value is single findtype3 : EMFTVM!Findtype ( -- [..., value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke3 : EMFTVM!Invoke ( -- [..., bool] opname <- 'oclIsKindOf', argcount <- 1), -- invert not_ : EMFTVM!Not -- [..., bool] } rule BoundTerminatingNacInputElementIn extends BoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( not s.pattern.hasMatcherBindings and not s.inModel.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{load, get, dup, findtype, invoke, ifn, it, dup2, findtype2, invoke2, ifn2, push_m, invoke_m, if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, goto2, dup3, findtype3, invoke3, ifn3, push_mv, invoke_mv, goto3, pop_v, pushf_v, not_}), ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, it, dup2, findtype2, invoke2, ifn2, push_m, invoke_m, if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, goto2, dup3, findtype3, invoke3, ifn3, push_mv, invoke_mv, goto3, pop_v, pushf_v, not_}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- goto2), -- [..., values] -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] push_m : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., it(values), value, modelname] invoke_m : EMFTVM!Invoke ( -- [..., it(values), bool] opname <- 'isInModel', argcount <- 1), if_ : EMFTVM!If (target <- goto), -- [..., it(values)] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- pushf_v), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] goto2 : EMFTVM!Goto (target <- pushf_v), -- [..., true] -- value is single dup3 : EMFTVM!Dup, -- [..., value, value] findtype3 : EMFTVM!Findtype ( -- [..., value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke3 : EMFTVM!Invoke ( -- [..., value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn3 : EMFTVM!Ifn (target <- goto3), -- [..., value] push_mv : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., value, modelname] invoke_mv : EMFTVM!Invoke ( -- [..., bool] opname <- 'isInModel', argcount <- 1), goto3 : EMFTVM!Goto (target <- pushf_v), -- [..., bool] pop_v : EMFTVM!Pop, -- [...] pushf_v : EMFTVM!Pushf, -- [..., false] -- invert not_ : EMFTVM!Not -- [..., bool] } rule LastBoundTerminatingNacInputElement extends BoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.bindingExp.binding.last and not s.pattern.hasMatcherBindings and s.inModel.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, goto_s, it, findtype2, invoke2, if_, endit, pushf, goto, pop, pusht, goto2, findtype3, invoke3, not_}), ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, goto_s, it, findtype2, invoke2, if_, endit, pushf, goto, pop, pusht, goto2, findtype3, invoke3, not_}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- goto2), -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype, -- [..., values, values, type] invoke_s : EMFTVM!Invoke, -- [..., values, bool] ifn_s : EMFTVM!Ifn (target <- goto_s), -- [..., values] invoke_last : EMFTVM!Invoke, -- [..., value] goto_s : EMFTVM!Goto (target <- goto2), -- [..., value] -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), bool] opname <- 'oclIsKindOf', argcount <- 1), if_ : EMFTVM!If (target <- goto), -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- invoke3), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] goto2 : EMFTVM!Goto (target <- invoke3), -- [..., true] -- value is single findtype3 : EMFTVM!Findtype ( -- [..., value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke3 : EMFTVM!Invoke ( -- [..., bool] opname <- 'oclIsKindOf', argcount <- 1), -- invert not_ : EMFTVM!Not -- [..., bool] } rule LastBoundTerminatingNacInputElementIn extends BoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.bindingExp.binding.last and not s.pattern.hasMatcherBindings and not s.inModel.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, goto_s, it, dup2, findtype2, invoke2, ifn2, push_m, invoke_m, if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, goto2, dup3, findtype3, invoke3, ifn3, push_mv, invoke_mv, goto3, pop_v, pushf_v, not_}), ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, goto_s, it, dup2, findtype2, invoke2, ifn2, push_m, invoke_m, if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, goto2, dup3, findtype3, invoke3, ifn3, push_mv, invoke_mv, goto3, pop_v, pushf_v, not_}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- goto2), -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype, -- [..., values, values, type] invoke_s : EMFTVM!Invoke, -- [..., values, bool] ifn_s : EMFTVM!Ifn (target <- goto_s), -- [..., values] invoke_last : EMFTVM!Invoke, -- [..., value] goto_s : EMFTVM!Goto (target <- goto2), -- [..., value] -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] push_m : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., it(values), value, modelname] invoke_m : EMFTVM!Invoke ( -- [..., it(values), bool] opname <- 'isInModel', argcount <- 1), if_ : EMFTVM!If (target <- goto), -- [..., it(values)] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- pushf_v), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] goto2 : EMFTVM!Goto (target <- pushf_v), -- [..., true] -- value is single dup3 : EMFTVM!Dup, -- [..., value, value] findtype3 : EMFTVM!Findtype ( -- [..., value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke3 : EMFTVM!Invoke ( -- [..., value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn3 : EMFTVM!Ifn (target <- goto3), -- [..., value] push_mv : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., value, modelname] invoke_mv : EMFTVM!Invoke ( -- [..., bool] opname <- 'isInModel', argcount <- 1), goto3 : EMFTVM!Goto (target <- pushf_v), -- [..., bool] pop_v : EMFTVM!Pop, -- [...] pushf_v : EMFTVM!Pushf, -- [..., false] -- invert not_ : EMFTVM!Not -- [..., bool] } rule LastNacInputElementWithBindings extends UnboundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.hasMatcherBindings and s.inModel.oclIsUndefined()) using { fb : SimpleGT!InputBinding = s.pattern.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.pattern.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( nested <- s.pattern.matcherBindings, code <- Sequence{findtype, allinst, it, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{ifn, pop, pushf, ret, endit, pusht})), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{findtype, allinst, it, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{ifn, pop, pushf, ret, endit, pusht})), findtype : EMFTVM!Findtype, -- [..., type] allinst : EMFTVM!Allinst, -- [..., coll] it : EMFTVM!Iterate (target <- endit), -- [..., it(coll), inst] store : EMFTVM!Store (localVariable <- lv), -- [..., it(coll)] invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [..., it(coll), bool] ifn : EMFTVM!Ifn (target <- ret), -- [..., it(coll)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'true'; pushf : EMFTVM!Pushf, -- [..., false] -- invert result ret : EMFTVM!Return, -- false, [...] endit : EMFTVM!Enditerate (target <- it), -- [...] -- invokeCb returned 'false' pusht : EMFTVM!Pusht -- [..., true] -- invert result } rule LastNacInputElementWithBindingsIn extends UnboundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.hasMatcherBindings and not s.inModel.oclIsUndefined()) using { fb : SimpleGT!InputBinding = s.pattern.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.pattern.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( nested <- s.pattern.matcherBindings, code <- Sequence{findtype, push, allinst, it, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{ifn, pop, pushf, ret, endit, pusht})), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{findtype, push, allinst, it, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{ifn, pop, pushf, ret, endit, pusht})), findtype : EMFTVM!Findtype, -- [..., type] push : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., type, modelname] allinst : EMFTVM!AllinstIn, -- [..., coll] it : EMFTVM!Iterate (target <- endit), -- [..., it(coll), inst] store : EMFTVM!Store (localVariable <- lv), -- [..., it(coll)] invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [..., it(coll), bool] ifn : EMFTVM!Ifn (target <- ret), -- [..., it(coll)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'true'; pushf : EMFTVM!Pushf, -- [..., false] -- invert result ret : EMFTVM!Return, -- false, [...] endit : EMFTVM!Enditerate (target <- it), -- [...] -- invokeCb returned 'false' pusht : EMFTVM!Pusht -- [..., true] -- invert result } rule BoundLastNacInputElementWithBindings extends BoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.hasMatcherBindings and s.inModel.oclIsUndefined()) using { fb : SimpleGT!InputBinding = s.pattern.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.pattern.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( nested <- s.pattern.matcherBindings, code <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] if_c : EMFTVM!If (target <- invoke_c), -- [..., values] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [..., it(values), bool] if_ : EMFTVM!If (target <- goto), -- [..., it(values)] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- pusht), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] -- invert not_ : EMFTVM!Not -- [..., bool] } rule BoundLastNacInputElementWithBindingsIn extends BoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.hasMatcherBindings and not s.inModel.oclIsUndefined()) using { fb : SimpleGT!InputBinding = s.pattern.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.pattern.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( nested <- s.pattern.matcherBindings, code <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] if_c : EMFTVM!If (target <- invoke_c), -- [..., values] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] dup3 : EMFTVM!Dup, -- [..., it(values), value, value] push_m : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., it(values), value, value, modelname] invoke_m : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'isInModel', argcount <- 1), ifn3 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [..., it(values), bool] if_ : EMFTVM!If (target <- goto), -- [..., it(values)] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- pusht), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] -- invert not_ : EMFTVM!Not -- [..., bool] } rule LastBoundLastNacInputElementWithBindings extends LastBoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.hasMatcherBindings and s.inModel.oclIsUndefined()) using { fb : SimpleGT!InputBinding = s.pattern.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.pattern.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( nested <- s.pattern.matcherBindings, code <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- invoke_last), -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype, -- [..., values, values, type] invoke_s : EMFTVM!Invoke, -- [..., values, bool] ifn_s : EMFTVM!Ifn (target <- invoke_c), -- [..., values] invoke_last : EMFTVM!Invoke, -- [..., value] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [..., it(values), bool] if_ : EMFTVM!If (target <- goto), -- [..., it(values)] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- pusht), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] -- invert not_ : EMFTVM!Not -- [..., bool] } rule LastBoundLastNacInputElementWithBindingsIn extends LastBoundLastNacInputElement { from s : SimpleGT!InputElement in IN ( s.pattern.hasMatcherBindings and not s.inModel.oclIsUndefined()) using { fb : SimpleGT!InputBinding = s.pattern.matcherBindings->first(); rbs : Sequence(SimpleGT!InputBinding) = s.pattern.matcherBindings->excluding(fb); } to cb : EMFTVM!CodeBlock ( nested <- s.pattern.matcherBindings, code <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb} ->union(rbs->collect(b|thisModule.resolveTemp(b, 'and_'))) ->union(Sequence{if_, goto_endit, pop_endit, endit, pushf, goto, pop, pusht, not_})), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- invoke_last), -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype, -- [..., values, values, type] invoke_s : EMFTVM!Invoke, -- [..., values, bool] ifn_s : EMFTVM!Ifn (target <- invoke_c), -- [..., values] invoke_last : EMFTVM!Invoke, -- [..., value] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] dup3 : EMFTVM!Dup, -- [..., it(values), value, value] push_m : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., it(values), value, value, modelname] invoke_m : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'isInModel', argcount <- 1), ifn3 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- fb), -- [..., it(values), bool] if_ : EMFTVM!If (target <- goto), -- [..., it(values)] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pushf : EMFTVM!Pushf, -- [..., false] goto : EMFTVM!Goto (target <- pusht), -- [..., false] pop : EMFTVM!Pop, -- [...] pusht : EMFTVM!Pusht, -- [..., true] -- invert not_ : EMFTVM!Not -- [..., bool] } rule NacInputElementWithNextElement extends UnboundNacInputElement { from s : SimpleGT!InputElement in IN ( s <> s.pattern.newElements->last() and s.inModel.oclIsUndefined()) using { next : SimpleGT!InputElement = s.pattern.newElements->at(s.pattern.newElements->indexOf(s)+1); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{next}, code <- Sequence{findtype, allinst, it, store, invokeCb, if_, pop, pushf, ret, endit, pusht}), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{findtype, allinst, it, store, invokeCb, if_, pop, pushf, ret, endit, pusht}), findtype : EMFTVM!Findtype, -- [..., type] allinst : EMFTVM!Allinst, -- [..., coll] it : EMFTVM!Iterate (target <- endit), -- [..., it(coll), inst] store : EMFTVM!Store (localVariable <- lv), -- [..., it(coll)] invokeCb : EMFTVM!InvokeCb (codeBlock <- next), -- [..., it(coll), bool] if_ : EMFTVM!If (target <- ret), -- [..., it(coll)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'false'; pushf : EMFTVM!Pushf, -- [..., false] ret : EMFTVM!Return, -- false, [...] endit : EMFTVM!Enditerate (target <- it), -- [...] -- invokeCb returned 'true' pusht : EMFTVM!Pusht -- [..., true] } rule NacInputElementWithNextElementIn extends UnboundNacInputElement { from s : SimpleGT!InputElement in IN ( s <> s.pattern.newElements->last() and not s.inModel.oclIsUndefined()) using { next : SimpleGT!InputElement = s.pattern.newElements->at(s.pattern.newElements->indexOf(s)+1); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{next}, code <- Sequence{findtype, push, allinst, it, store, invokeCb, if_, pop, pushf, ret, endit, pusht}), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{findtype, push, allinst, it, store, invokeCb, if_, pop, pushf, ret, endit, pusht}), findtype : EMFTVM!Findtype, -- [..., type] push : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., type, modelname] allinst : EMFTVM!AllinstIn, -- [..., coll] it : EMFTVM!Iterate (target <- endit), -- [..., it(coll), inst] store : EMFTVM!Store (localVariable <- lv), -- [..., it(coll)] invokeCb : EMFTVM!InvokeCb (codeBlock <- next), -- [..., it(coll), bool] if_ : EMFTVM!If (target <- ret), -- [..., it(coll)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'false'; pushf : EMFTVM!Pushf, -- [..., false] ret : EMFTVM!Return, -- false, [...] endit : EMFTVM!Enditerate (target <- it), -- [...] -- invokeCb returned 'true' pusht : EMFTVM!Pusht -- [..., true] } rule BoundNacInputElementWithNextElement extends BoundNacInputElement { from s : SimpleGT!InputElement in IN ( s <> s.pattern.newElements->last() and s.inModel.oclIsUndefined()) using { next : SimpleGT!InputElement = s.pattern.newElements->at(s.pattern.newElements->indexOf(s)+1); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{next}, code <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] if_c : EMFTVM!If (target <- invoke_c), -- [..., values] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- next), -- [..., it(values), bool] if_next : EMFTVM!If (target <- ret), -- [..., it(values)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'false'; pushf : EMFTVM!Pushf, -- [..., false] ret : EMFTVM!Return, -- false, [...] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] -- invokeCb returned 'true'; pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pusht : EMFTVM!Pusht -- [..., true] } rule BoundNacInputElementWithNextElementIn extends BoundNacInputElement { from s : SimpleGT!InputElement in IN ( s <> s.pattern.newElements->last() and not s.inModel.oclIsUndefined()) using { next : SimpleGT!InputElement = s.pattern.newElements->at(s.pattern.newElements->indexOf(s)+1); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{next}, code <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, if_c, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] if_c : EMFTVM!If (target <- invoke_c), -- [..., values] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] dup3 : EMFTVM!Dup, -- [..., it(values), value, value] push_m : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., it(values), value, value, modelname] invoke_m : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'isInModel', argcount <- 1), ifn3 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- next), -- [..., it(values), bool] if_next : EMFTVM!If (target <- ret), -- [..., it(values)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'false'; pushf : EMFTVM!Pushf, -- [..., false] ret : EMFTVM!Return, -- false, [...] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] -- invokeCb returned 'true'; pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pusht : EMFTVM!Pusht -- [..., true] } rule LastBoundNacInputElementWithNextElement extends LastBoundNacInputElement { from s : SimpleGT!InputElement in IN ( s <> s.pattern.newElements->last() and s.inModel.oclIsUndefined()) using { next : SimpleGT!InputElement = s.pattern.newElements->at(s.pattern.newElements->indexOf(s)+1); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{next}, code <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- invoke_last), -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype, -- [..., values, values, type] invoke_s : EMFTVM!Invoke, -- [..., values, bool] ifn_s : EMFTVM!Ifn (target <- invoke_c), -- [..., values] invoke_last : EMFTVM!Invoke, -- [..., value] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- next), -- [..., it(values), bool] if_next : EMFTVM!If (target <- ret), -- [..., it(values)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'false'; pushf : EMFTVM!Pushf, -- [..., false] ret : EMFTVM!Return, -- false, [...] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] -- invokeCb returned 'true'; pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pusht : EMFTVM!Pusht -- [..., true] } rule LastBoundNacInputElementWithNextElementIn extends LastBoundNacInputElement { from s : SimpleGT!InputElement in IN ( s <> s.pattern.newElements->last() and not s.inModel.oclIsUndefined()) using { next : SimpleGT!InputElement = s.pattern.newElements->at(s.pattern.newElements->indexOf(s)+1); } to cb : EMFTVM!CodeBlock ( nested <- Sequence{next}, code <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), lv : EMFTVM!LocalVariable, ln : EMFTVM!LineNumber ( instructions <- Sequence{load, get, dup, findtype, invoke, ifn, dup_s, findtype_s, invoke_s, ifn_s, invoke_last, findtype_c, new_c, swap_c, invoke_c, it, dup2, findtype2, invoke2, ifn2, dup3, push_m, invoke_m, ifn3, store, invokeCb, if_next, pop, pushf, ret, goto_endit, pop_endit, endit, pusht}), load : EMFTVM!Load, -- [..., element] get : EMFTVM!Get, -- [..., values] dup : EMFTVM!Dup, -- [..., values, values] findtype : EMFTVM!Findtype, -- [..., values, values, type] invoke : EMFTVM!Invoke, -- [..., values, bool] ifn : EMFTVM!Ifn (target <- invoke_last), -- [..., values] dup_s : EMFTVM!Dup, -- [..., values, values] findtype_s : EMFTVM!Findtype, -- [..., values, values, type] invoke_s : EMFTVM!Invoke, -- [..., values, bool] ifn_s : EMFTVM!Ifn (target <- invoke_c), -- [..., values] invoke_last : EMFTVM!Invoke, -- [..., value] -- value is single; wrap in collection findtype_c : EMFTVM!Findtype ( -- [..., value, type] modelname <- '#native', typename <- thisModule.SequenceType), new_c : EMFTVM!New, -- [..., value, coll] swap_c : EMFTVM!Swap, -- [..., coll, value] invoke_c : EMFTVM!Invoke ( -- [..., values] opname <- 'append', argcount <- 1), -- value is a collection it : EMFTVM!Iterate (target <- endit), -- [..., it(values), value] dup2 : EMFTVM!Dup, -- [..., it(values), value, value] findtype2 : EMFTVM!Findtype ( -- [..., it(values), value, value, type] modelname <- s.type.typeModelName, typename <- s.type.typeName), invoke2 : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'oclIsKindOf', argcount <- 1), ifn2 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] dup3 : EMFTVM!Dup, -- [..., it(values), value, value] push_m : EMFTVM!Push (stringValue <- s.inModel.name), -- [..., it(values), value, value, modelname] invoke_m : EMFTVM!Invoke ( -- [..., it(values), value, bool] opname <- 'isInModel', argcount <- 1), ifn3 : EMFTVM!Ifn (target <- goto_endit), -- [..., it(values), value] store : EMFTVM!Store (localVariable <- lv), -- [..., it(values)] invokeCb : EMFTVM!InvokeCb (codeBlock <- next), -- [..., it(values), bool] if_next : EMFTVM!If (target <- ret), -- [..., it(values)] pop : EMFTVM!Pop, -- [...] -- invokeCb returned 'false'; pushf : EMFTVM!Pushf, -- [..., false] ret : EMFTVM!Return, -- false, [...] goto_endit : EMFTVM!Goto (target <- pop_endit), -- [..., it(values)] -- invokeCb returned 'true'; pop_endit : EMFTVM!Pop, -- [..., it(values)] endit : EMFTVM!Enditerate (target <- it), -- [...] pusht : EMFTVM!Pusht -- [..., true] } rule OutputElement { from s : SimpleGT!OutputElement in IN ( s.pattern.newElements->includes(s)) -- Only elements that should be newly created to re : EMFTVM!OutputRuleElement ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName, models <- Sequence{s.outModelName}), ov : EMFTVM!LocalVariable ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName) } rule InputBinding { from s : SimpleGT!InputBinding in IN ( not s.isElementBinding) to cb : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln}, nested <- Sequence{s.expr}, code <- Sequence{load, get, invokeCb, invoke}), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{load, get, invokeCb, invoke}), load : EMFTVM!Load ( -- [..., element] localVariable <- thisModule.resolveTemp(s.element.refersTo, 'lv')), get : EMFTVM!Get (fieldname <- s.property), -- [..., prop_val] invokeCb : EMFTVM!InvokeCb (codeBlock <- s.expr), -- [..., prop_val, expr_val] invoke : EMFTVM!Invoke ( -- [..., bool] opname <- if s.last then '=~|' else '=~' endif, argcount <- 1) } rule NonFirstInputBinding extends InputBinding { from s : SimpleGT!InputBinding in IN ( s <> s.element.pattern.matcherBindings->first()) to cb : EMFTVM!CodeBlock, and_ : EMFTVM!And (codeBlock <- cb) -- AND instruction for parent code block } rule RemovedInputBinding extends InputBinding { from s : SimpleGT!InputBinding in IN ( s.element.pattern.patternFor.removedBindings->includes(s)) to cb : EMFTVM!CodeBlock, cb2 : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln2}, nested <- Sequence{thisModule.resolveTemp(s.expr, 'cb2')}, code <- Sequence{load2, invokeCb2, remove2}), ln2 : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{load2, invokeCb2, remove2}), load2 : EMFTVM!Load ( -- [..., element] localVariable <- thisModule.resolveTemp(s.element.refersTo, 'ov')), invokeCb2 : EMFTVM!InvokeCb ( -- [..., element, expr_val] codeBlock <- thisModule.resolveTemp(s.expr, 'cb2')), remove2 : EMFTVM!Remove (fieldname <- s.property) -- [...] } -- @extends NonFirstInputBinding, RemovedInputBinding rule NonFirstRemovedInputBinding { from s : SimpleGT!InputBinding in IN to cb : EMFTVM!CodeBlock } rule RemovedInputElementBinding { -- only used in applier from s : SimpleGT!InputBinding in IN ( s.isElementBinding and s.element.pattern.patternFor.removedBindings->includes(s)) to cb2 : EMFTVM!CodeBlock ( lineNumbers <- Sequence{ln2}, nested <- Sequence{thisModule.resolveTemp(s.expr, 'cb2')}, code <- Sequence{load2, invokeCb2, remove2}), ln2 : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd, instructions <- Sequence{load2, invokeCb2, remove2}), load2 : EMFTVM!Load ( -- [..., element] localVariable <- thisModule.resolveTemp(s.element.refersTo, 'ov')), invokeCb2 : EMFTVM!InvokeCb ( -- [..., element, expr_val] codeBlock <- thisModule.resolveTemp(s.expr, 'cb2')), remove2 : EMFTVM!Remove (fieldname <- s.property) -- [...] } abstract rule OutputBinding { from s : SimpleGT!OutputBinding in IN ( s.element.pattern.patternFor.addedBindings->includes(s)) to cb : EMFTVM!CodeBlock ( nested <- Sequence{s.expr}, lineNumbers <- Sequence{ln}), ln : EMFTVM!LineNumber ( startLine <- s.line, startColumn <- s.column, startChar <- s.charStart, endChar <- s.charEnd) } rule SimpleOutputBinding extends OutputBinding { from s : SimpleGT!OutputBinding in IN ( s.beforeElement.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{load, invokeCb, add}), ln : EMFTVM!LineNumber ( instructions <- Sequence{load, invokeCb, add}), load : EMFTVM!Load ( -- [..., element] localVariable <- thisModule.resolveTemp(s.element.refersTo, 'ov')), invokeCb : EMFTVM!InvokeCb (codeBlock <- s.expr), -- [..., element, value] add : EMFTVM!Add (fieldname <- s.property) -- [...] } rule OutputBindingBeforeElement extends OutputBinding { from s : SimpleGT!OutputBinding in IN ( not s.beforeElement.oclIsUndefined()) to cb : EMFTVM!CodeBlock ( code <- Sequence{invokeCb, load, dupX1, get, load2, invoke, insert}), ln : EMFTVM!LineNumber ( instructions <- Sequence{invokeCb, load, dupX1, get, load2, invoke, insert}), invokeCb : EMFTVM!InvokeCb (codeBlock <- s.expr), -- [..., value] load : EMFTVM!Load ( -- [..., value, element] localVariable <- thisModule.resolveTemp(s.element.refersTo, 'ov')), dupX1 : EMFTVM!DupX1, -- [..., element, value, element] get : EMFTVM!Get (fieldname <- s.property), -- [..., element, value, oldValue] load2 : EMFTVM!Load ( -- [..., element, value, oldValue, before] localVariable <- thisModule.resolveTemp(s.beforeElement.refersTo, 'ov')), invoke : EMFTVM!Invoke (opname <- 'indexOf', argcount <- 1), -- [..., element, value, index] insert : EMFTVM!Insert (fieldname <- s.property) -- [...] } -- ====================================================================== -- matched rules end -- ====================================================================== -- ====================================================================== -- lazy rules begin -- ====================================================================== lazy rule CreateLocal { from s : SimpleGT!InputElement to lv : EMFTVM!LocalVariable ( name <- s.varName, type <- s.type.typeName, typeModel <- s.type.typeModelName) do { lv; } } -- ====================================================================== -- lazy rules end -- ======================================================================