module sc2c; -- Module Template create OUT : c from IN : sc; helper context sc!AbstractState def: owner : sc!CompositeState = sc!CompositeState.allInstances()->select(o| o.states->includes(self))->reject(o | o.oclIsKindOf(sc!StateMachine))->first(); helper context sc!AbstractState def: stateMachine : sc!StateMachine = sc!StateMachine.allInstances()->select(sm|sm.allStates->includes(self))->first(); helper context sc!CompositeState def: allStates : Set(sc!AbstractState) = self.states->union(self.states->select(s|s.oclIsKindOf(sc!CompositeState))->collect(s|s.allStates)->flatten()); helper context sc!AbstractState def: qualifiedName : String = (if self.owner.oclIsUndefined() then '' else self.owner.qualifiedName + '_' endif) + self.name; helper context sc!AbstractState def: leafState: OrderedSet(sc!AbstractState) = OrderedSet{}; helper context sc!CompositeState def: leafState: OrderedSet(sc!AbstractState) = self.states->collect(ss| ss.leafState); helper context sc!SimpleState def: leafState: OrderedSet(sc!AbstractState) = OrderedSet{self}; helper context sc!FinalState def: leafState: OrderedSet(sc!AbstractState) = OrderedSet{self}; helper context sc!AbstractState def: startState : sc!State = self; helper context sc!CompositeState def: startState : sc!State = self.states->select(s| s.oclIsKindOf(sc!InitialState))->first().outgoing->first().to; helper context sc!CompositeState def: innerUsefulStates : OrderedSet(sc!AbstractState) = self.states->select(s| s.oclIsKindOf(sc!CompositeState))->select(s|s.states->notEmpty() or s.outgoing->notEmpty())->union(self.states->select(s| s.oclIsKindOf(sc!SimpleState))->select(s|s.outgoing->notEmpty())); helper context sc!CompositeState def: allExecutableStates : OrderedSet(sc!AbstractState) = self.innerUsefulStates->union(self.states->select(s|s.oclIsKindOf(sc!CompositeState))->collect(s|s.allExecutableStates))->flatten(); rule MainRule { from sm : sc!StateMachine to p : c!Program ( name <- sm.name, elements <- OrderedSet {e, s, init, run} ), e : c!Enum ( name <- sm.name + '_states', declared <- true, literals <- sm.leafState ), s : c!Structure ( name <- sm.name, declared <- true, structure <- OrderedSet {cv} ), cv : c!Variable ( name <- 'current', type <- etr ), etr : c!TypeReference ( type <- e ), init : c!Function ( name <- sm.name + '_init', declared <- true, type <- initType, body <- initBody, parameters <- OrderedSet {initArg} ), initType : c!DataType ( kind <- #void ), initArg : c!Variable ( name <- 'a', type <- initArgType ), initArgType : c!PointerType ( type <- initArgTypeType ), initArgTypeType : c!TypeReference ( type <- s ), initBody : c!Block ( instructions <- initSetup ), initSetup : c!Assignation ( target <- initInd, value <- initStartCall ), initPointer : c!Pointer ( pointed <- initParamCall ), initParamCall : c!VariableCall ( called <- initArg ), initInd : c!Indirection ( source <- initPointer, called <- cv ), initStartCall : c!EnumLiteralCall ( value <- sm.startState ), run : c!Function ( name <- sm.name + '_run', declared <- true, type <- runType, body <- runBody, parameters <- OrderedSet {runSelfArg, runMsgArg} ), runType : c!DataType ( kind <- #void ), runSelfArg : c!Variable ( name <- 'a', type <- runSelfArgType ), runSelfArgType : c!PointerType ( type <- runSelfArgTypeType ), runSelfArgTypeType : c!TypeReference ( type <- s ), runMsgArg : c!Variable ( name <- 'msg', type <- runMsgArgType ), runMsgArgType : c!PointerType ( type <- runMsgArgTypeType ), runMsgArgTypeType : c!DataType ( kind <- #char ), runBody : c!Block ( instructions <- sm.allExecutableStates->collect(s|thisModule.resolveTemp(s, 'exec')) ) } rule SimpleStates { from s: sc!SimpleState to el: c!EnumLiteral ( name <- s.qualifiedName + '_state' ), exec : c!If ( condition <- cnd, thenPart <- msgTest ), cnd : c!Equals ( lhs <- cu, rhs <- elc ), cu : c!Indirection ( source <- pc, called <- thisModule.resolveTemp(s.stateMachine, 'cv') ), pc : c!Pointer ( pointed <- vc ), vc : c!VariableCall ( called <- thisModule.resolveTemp(s.stateMachine, 'runSelfArg') ), elc : c!EnumLiteralCall ( value <- el ), msgTest : c!Block ( instructions <- s.outgoing ) } rule CompositeStates { from s: sc!CompositeState ( not s.oclIsKindOf(sc!StateMachine) ) to exec : c!If ( thenPart <- msgTest ), cndOr: distinct c!Or foreach (sc in let ius : OrderedSet(sc!AbstractState) = s.innerUsefulStates in if ius->size() < 2 then OrderedSet{} else ius->excluding(ius->first()) endif), cnd : distinct c!Equals foreach (sc in s.innerUsefulStates) ( lhs <- cu->at(s.innerUsefulStates->indexOf(sc)), rhs <- elc->at(s.innerUsefulStates->indexOf(sc)) ), cu : distinct c!Indirection foreach (sc in s.innerUsefulStates) ( source <- pc->at(s.innerUsefulStates->indexOf(sc)), called <- thisModule.resolveTemp(s.stateMachine, 'cv') ), pc : distinct c!Pointer foreach (sc in s.innerUsefulStates) ( pointed <- vc->at(s.innerUsefulStates->indexOf(sc)) ), vc : distinct c!VariableCall foreach (sc in s.innerUsefulStates) ( called <- thisModule.resolveTemp(s.stateMachine, 'runSelfArg') ), elc : distinct c!EnumLiteralCall foreach (sc in s.innerUsefulStates) ( value <- thisModule.resolveTemp(sc, 'el') ), msgTest : c!Block ( instructions <- s.outgoing ) do { for (oc in cnd) { if (exec.condition.oclIsUndefined()) exec.condition <- oc; else { cndOr->at(cnd->indexOf(oc)-1).lhs <- exec.condition; cndOr->at(cnd->indexOf(oc)-1).rhs <- oc; exec.condition <- cndOr->at(cnd->indexOf(oc)-1); } } } } rule FinalStates { from s: sc!FinalState to el: c!EnumLiteral ( name <- (if s.name.oclIsUndefined() or s.name.size() = 0 then if s.owner.oclIsUndefined() then '' else s.owner.qualifiedName + '_' endif else s.qualifiedName + '_' endif) + 'final_state' ) } rule Transitions { from t: sc!Transition ( not t.from.oclIsKindOf(sc!InitialState) ) to test: c!If ( condition <- cond, thenPart <-go ), cond : c!Equals ( lhs <- strcmp, rhs <- zero ), strcmp: c!ExternalFunctionCall ( name <- 'strcmp', libName <- 'string', arguments <- OrderedSet {msg, event} ), msg : c!VariableCall ( called <- thisModule.resolveTemp(t.from.stateMachine, 'runMsgArg') ), event : c!StringLiteral ( value <- t.event ), zero : c!IntegerLiteral ( value <- 0 ), go : c!Block ( instructions <- OrderedSet {aff, ret} ), aff : c!Assignation ( target <- cu, value <- elc ), cu : c!Indirection ( source <- pc, called <- thisModule.resolveTemp(t.from.stateMachine, 'cv') ), pc : c!Pointer ( pointed <- vc ), vc : c!VariableCall ( called <- thisModule.resolveTemp(t.from.stateMachine, 'runSelfArg') ), elc : c!EnumLiteralCall ( value <- thisModule.resolveTemp(t.to.startState, 'el') ), ret : c!Return }