Action Language for EMF
In this section we will create the abstract syntax of our language as an Ecore model.
First of all, we need to define the domain of our language.
So what is a FSM?
[A FSM] is a mathematical model of computation. It is an abstract machine that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some external inputs; the change from one state to another is called a transition. A FSM is defined by a list of its states, its initial state, and the conditions for each transition.
File > New > Project...
Eclipse Modeling Framework > Empty EMF Project > Next
Project name
with ‘minifsm’ then Finish
model/
folder and select New > Others...
Eclipse Modeling Framework > Ecore model
, then Next
Finish
Initialize Ecore Diagram ...
Next >
Entities in a Class Diagram
is already selected, click Next >
Finish
Show View > Other... > General > Properties
)Name
with ‘minifsm’Ns URI
with ‘http://minifsm’Ns Prefix
with ‘minifsm’Classifier > Class
and create with a simple click:
Relation > Super Type
InitialState
classState
class to end the relation creationIn a similar way with Relation > Composition
create
End with Relation > Reference
create
Feature > Attribute
State
to create the new featurePropeties
view fill Name
with ‘name’EType
select ‘EString’In a similar way add event
typed EString
into Transition
Feature > Operation
FSM
Properties
view fill Name
with ‘handle’Properties
view, open the Parameter
tabAdd
button at the rightParameter Details
name it ‘event’ and type it ‘EString’Add also an operation:
execute
into StateisActivated
typed EBoolean into TransitionAt this point your metamodel should look as follows:
Now that our metamodel is ready we have to define its runtime behavior. We will use ALE to implement the EOperations defined in the Ecore metamodel.
Make sure you are in the Modeling perspective:
Window > Perspective > Open Perspective > Other...
Modeling
Then we activate the Behavior tools:
Viewpoints Selection
Behavior
and click OK
Behavior
layer in the toolbarA new selection Behavior
is activated in the Palette
at the right
Two new files are also created:
Behavior > Reference
FSM
State
newRef
for currentState
Do the same with Behavior > Attribute
to add String currentEvent
into FSM
isActivated
from Transition
Edit implementation
def boolean isActivated () {
result := self.fsm.currentEvent = self.event and self.incoming = self.fsm.currentState;
}
We are checking:
The content of the variable result
will be returned at the end of isActivated
.
The variable self
refers to the current object (here it is a Transition).
In similar way we implement execute
from State
override void execute () {
(' Execute ' + self.name).log();
}
We just log the name of the State.
And for the implementation of handle
from FSM
:
override void handle (EString event) {
(' Handle ' + event).log();
self.currentEvent := event;
self.currentState :=
self.transitions
->select(t | t.isActivated() )
->first()
.outgoing;
}
Here we simply update currentEvent
, search for an activated Transition
and update currentState
accordingly.
To complete the behavior of our language, we will now define an entry point to run an FSM.
Behavior > Operation
FSM
This tool creates an operation int newMethod()
in FSM. You can notice that newMethod
starts with the keyword def
contrary to implemented EOperation that uses the keyword override
. This distinction is made to raise an error if we try to implement an EOperation that doesn’t exist in the metamodel.
def int newMethod()
to def void entryPoint()
@main
before the entryPoint
declarationWe changed the return type to void
since the entryPoint
returns nothing.
We also added the tag main
to call this operation at the execution of an FSM.
And for the content:
@main
def void entryPoint() {
'Start'.log();
Sequence(String) events := Sequence{'event1','event2'};
self.currentState :=
self.states
->select(s | s.oclIsKindOf(minifsm::InitialState) )
->first();
self.currentState.execute();
for(event in events) {
self.handle(event);
self.currentState.execute();
}
'End'.log();
}
We created a sequence of 2 events
, initialized currentState
with an InitialState
and notify the FSM
with the events.
Your FSM language should now look like:
Before testing our implementation we need an FSM model:
Dynamic > Dynamic instance
FSM
FSM.xmi
and click Finish
FSM.xmi
, right click on FSM
and select New Child > States Initial State
First
in the Properties
viewState
named Second
and a Final State
named Third
Transition
and edit the properties Event
to event1
, Incoming
to First
and Outgoing
to Second
Transition
from Second
to Third
with event2
Your FSM model should look like:
Now we can test!
minifsm.dsl
Run As > ALE launch
*xmi
FSM.xmi
OK
Console output:
Run minifsm.dsl
------------
Start
Execute First
Handle event1
Execute Second
Handle event2
Execute Third
End
Congratulations, you created an executable language from scratch!
With EcoreTools you defined the abstract syntax of a FSM, you then implemented its EOperations with ALE and you run it on an FSM model.