Skip to content

Instantly share code, notes, and snippets.

@tdegueul
Created February 15, 2017 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tdegueul/5d917e1936f570b94de74e7890ebdf8c to your computer and use it in GitHub Desktop.
Save tdegueul/5d917e1936f570b94de74e7890ebdf8c to your computer and use it in GitHub Desktop.
Attempting to map OA and MT theories
package oamt
import java.util.List
import java.util.Map
import org.eclipse.xtend.lib.annotations.Accessors
/**
* Fsm AS
*/
class FSM {
@Accessors List<State> states = newArrayList
@Accessors List<Transition> trans = newArrayList
}
class State {
@Accessors String name
}
class Transition {
@Accessors String evt
@Accessors State src
@Accessors State tgt
}
/**
* Classic Fsm Algebra
*/
interface FsmAlg<F, S, T> {
def F $(FSM f)
def S $(State s)
def T $(Transition t)
}
interface IPrint {
def String print()
}
class PrintAlg implements FsmAlg<IPrint, IPrint, IPrint> {
override $(FSM f) {
return [
'''
PrintAlg: «f.hashCode»
«f.states.map[$.print].join(System::lineSeparator)»
«f.trans.map[$.print].join(System::lineSeparator)»'''
]
}
override $(State s) {
return ['''State «s.name» -- «s.hashCode»''']
}
override $(Transition t) {
return ['''Trans «t.evt» («t.src.name» -> «t.tgt.name») -- «t.hashCode»''']
}
}
/**
* FsmMT AS
*
* Just the same as Fsm, without transitions
*/
interface FsmMT {
def List<StateMT> getStates()
}
interface StateMT {
def String getName()
}
/**
* FsmMT Algebra
*
* We use this one to write denotations (e.g. in PrintMtAlg)
* that can be reused for all the other algebras (e.g. FsmAlg)
* that "implement" it.
*/
interface FsmMtAlg<F, S> {
def F $(FsmMT f)
def S $(StateMT s)
}
class PrintMtAlg implements FsmMtAlg<IPrint, IPrint> {
override $(FsmMT f) {
return [
'''
PrintMtAlg: «f.hashCode»
«f.states.map[$.print].join(System::lineSeparator)»'''
]
}
override $(StateMT s) {
return ['''State «s.name» -- «s.hashCode»''']
}
}
/**
* Fsm -> FsmMT (transfo)
*
* First way of making Fsm "implement" FsmMT: simply write
* denotations from Fsm to in FsmMT through a stupid adapter
* pattern. In the end, it's just a transfo Fsm -> FsmMT.
*/
class FsmToFsmMtAlg implements FsmAlg<FsmMT, StateMT, Void> {
override $(FSM f) {
return AdaptersFactory::instance.newAdapter(f)
}
override $(State s) {
return AdaptersFactory::instance.newAdapter(s)
}
override $(Transition t) {
return null
}
}
/**
* Fsm -> FsmMT (adapters)
*
* Second way: we don't actually generate an output model
* in a "transfo" style, but just wrap Fsm's denotations
* into FsmMT's denotations.
*/
class FsmToFsmMtAlg2<F, S> implements FsmAlg<F, S, Void> {
FsmMtAlg<F, S> alg
private new() {}
new(FsmMtAlg<F, S> alg) { this.alg = alg }
override $(FSM f) {
return alg.$(AdaptersFactory::instance.newAdapter(f))
}
override $(State s) {
return alg.$(AdaptersFactory::instance.newAdapter(s))
}
override $(Transition t) {
return null
}
}
/**
* We don't need to manage that if Melange is in the loop.
* It already generates the appropriate adapters, ensures
* identity, handles reflective calls, whole EMF API, etc.
*/
class AdaptersFactory {
static AdaptersFactory instance
@Accessors(PUBLIC_GETTER) Map<FSM, FsmMT> fsmCache = newHashMap
@Accessors(PUBLIC_GETTER) Map<State, StateMT> stateCache = newHashMap
def FsmMT newAdapter(FSM f) {
if (!fsmCache.containsKey(f))
fsmCache.put(f, new FsmMT() {
override getStates() {
return f.states.map[newAdapter(it)]
}
})
return fsmCache.get(f)
}
def StateMT newAdapter(State s) {
if (!stateCache.containsKey(s))
stateCache.put(s, new StateMT() {
override getName() {
return s.name
}
})
return stateCache.get(s)
}
private new() {}
def static AdaptersFactory getInstance() {
if (instance === null)
instance = new AdaptersFactory
return instance
}
}
/**
* Main
*/
class OAMT {
def static void main(String[] args) {
val m = makeModel
// Classic OA: apply IPrint on FsmAlg
val a = wrap(new PrintAlg, m)
// "Transfo" approach: first translate Fsm to FsmMT
// using impl(), then apply IPrint as usual
val b = wrapMT(new PrintMtAlg, impl(new FsmToFsmMtAlg, m))
// "Adapters" approach:
val c = wrap(new FsmToFsmMtAlg2(new PrintMtAlg), m)
println(a.print)
println(b.print)
println(c.print)
println
println("fsmCache:")
AdaptersFactory::instance.fsmCache.forEach[
println(''' «$0.hashCode» => «$1.hashCode»''')
]
println("stateCache:")
AdaptersFactory::instance.stateCache.forEach[
println(''' «$0.hashCode» => «$1.hashCode»''')
]
}
def static <F, S, T> F wrap(FsmAlg<F, S, T> alg, FSM m) {
return alg.$(m)
}
def static <F, S> F wrapMT(FsmMtAlg<F, S> alg, FsmMT m) {
return alg.$(m)
}
def static <F, S, T> F impl(FsmAlg<F, S, T> alg, FSM m) {
return alg.$(m)
}
def static FSM makeModel() {
return new FSM => [
val s1 = new State => [name = "s1"]
val s2 = new State => [name = "s2"]
val t1 = new Transition => [evt = "on"]
val t2 = new Transition => [evt = "off"]
t1.src = s1 ; t1.tgt = s2
t2.src = s2 ; t2.tgt = s1
states += s1
states += s2
trans += t1
trans += t2
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment