Skip to content

Instantly share code, notes, and snippets.

@manuelleduc
Forked from tdegueul/OAMT.xtend
Last active February 16, 2017 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manuelleduc/2a719c26dfb3c19e8aa23e4007fc038c to your computer and use it in GitHub Desktop.
Save manuelleduc/2a719c26dfb3c19e8aa23e4007fc038c 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
@Accessors Long value
}
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.value»] -- «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()
}
/**
* FSMLight is a child of FsmMT but is also a parent of FSM
*/
class FsmLight {
@Accessors List<StateLight> states = newArrayList
}
class StateLight {
@Accessors String name
}
/**
* 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»''']
}
}
interface FsmLightAlg<F, S> {
def F $(FsmLight f)
def S $(StateLight s)
}
class PrintLightAlg implements FsmLightAlg<IPrint, IPrint> {
override $(FsmLight f) {
[
'''
PrintLightAlg «f.hashCode»
«f.states.map[$.print].join(System.lineSeparator)»'''
]
}
override $(StateLight s) {
['''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
}
}
class FsmLightToFsmAlg implements FsmLightAlg<FSM, State> {
override $(FsmLight f) {
return AdaptersFactoryLight::instance.newAdapter(f)
}
override $(StateLight s) {
return AdaptersFactoryLight::instance.newAdapter(s)
}
}
/**
* 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
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
private new() {
}
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)
}
def static AdaptersFactory getInstance() {
if (instance === null)
instance = new AdaptersFactory
return instance
}
}
class AdaptersFactoryLight {
static AdaptersFactoryLight instance
@Accessors(PUBLIC_GETTER) Map<FsmLight, FSM> fsmCache = newHashMap
@Accessors(PUBLIC_GETTER) Map<oamt.StateLight, State> stateCache = newHashMap
private new() {
}
def FSM newAdapter(FsmLight f) {
if (!fsmCache.containsKey(f))
fsmCache.put(f, new FSM() {
override getStates() {
return f.states.map[newAdapter(it)]
}
})
return fsmCache.get(f)
}
def State newAdapter(StateLight s) {
if (!stateCache.containsKey(s))
stateCache.put(s, new State() {
override getName() {
return s.name
}
override getValue() {
return -1L // arbitrary default value
}
})
return stateCache.get(s)
}
def static AdaptersFactoryLight getInstance() {
if (instance === null)
instance = new AdaptersFactoryLight
return instance
}
}
/**
* Main
*/
class OAMT {
def static void main(String[] args) {
val m = makeModel
val mlight = makeModelLight
// 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, wrap(new FsmToFsmMtAlg, m))
// "Adapters" approach:
val c = wrap(new FsmToFsmMtAlg2(new PrintMtAlg), m)
val d = wrapLight(new PrintLightAlg, mlight)
val e = wrap(new PrintAlg, wrapLight(new FsmLightToFsmAlg, mlight))
println(a.print)
println(b.print)
println(c.print)
println(d.print)
println(e.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 FSM downcast(FsmLight light) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}
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> F wrapLight(FsmLightAlg<F, S> alg, FsmLight m) {
return alg.$(m)
}
def static FsmLight makeModelLight() {
return new FsmLight => [
val s1 = new StateLight => [name = "s1l"]
val s2 = new StateLight => [name = "s2l"]
states += s1
states += s2
]
}
def static FSM makeModel() {
return new FSM => [
val s1 = new State => [
name = "s1"
value = 1L
]
val s2 = new State => [
name = "s2"
value = 2L
]
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
]
}
}
@manuelleduc
Copy link
Author

La seule vraie différence c'est que impl est supprimé et wrap est utilisé à la place (puisque c'est la même méthode)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment