...
- Do you model the state machine? If so, what distinguishes initial states from regular states?
- Do you model the Turing Machine's tape?
- In what detail do you model transition labels? Simple Strings, or more complex expressions over the input alphabet?
...
- EClass – Create one for every item that you want to be in your model. Make sure that you have exactly one root element, that is, an element that represents your Turing Machine (perhaps
TuringMachine
would actually be a good name for it...) and provides access to other elements. - EAttribute – Add attributes to classes to give them properties, e.g. a
name
attribute for states in state machines. The most important property of attributes is their type, which you can configure in the Properties view. - EEnum – Create enumerations to define simple enumeration types that you can then use as the type of attributes. Each item of the enumeration is an EEnumLiteral.
- Inheritance Relations – Use these as you would in UML class diagrams or ye plain ol' Java.
- EReference – Use references to provide links between classes. Here's a few things about references:
- Every class (except the root class) requires exactly one Containment reference that specifies where it belongs to and where it will be stored later on when you save your models to XML files.
- Set lower and upper bounds on references to control how many instances of a class can be referenced (just like multiplicities in UML class diagram associations).
- Consider whether a reference should have an opposite reference: a second reference in the other direction to be able to navigate back and forth between the model objects. Let's take two classes as an example to illustrate this:
Parent
andChild
, whereParent
can reference multipleChild
objects. To be able to ask theParent
about all its children, we would add a referencechildren
fromParent
toChild
with the containment flag active (that is,Child
is part of itsParent
). To be able to ask aChild
about itsParent
, we would add a second reference fromChild
toParent
with the EOpposite set to thechildren
reference.
...
One last thing before you get started: While working on your model, save and validate it regularly (Edit -> Validate). This will help you find potential problems with your model while you're still able to fix them easily.
Code Generation
Saving and Loading Models
Implementing a Head Controller
This is where all the model design and model generation pays off and where we will establish the link to the first tutorial: you will write an IHeadController
implementation that can simulate Turing Machines specified as models following the metamodel you just designed. Your simulator should be able to execute arbitrary instances of your metamodel.
Simulating Turing Machines
Right, time to write some simulation code. Go grab a cup of coffee and start working through the following steps:
- Add a new class to one of your plug-ins named TuringHeadController. Make sure it implements the IHeadController interface we defined in the first tutorial and register it with the appropriate extension point.
- Add a new method
initialize()
to your controller that loads a Turing Machine model from a fixed path. - Implement the
nextCommand()
andreset()
methods:- You can access all references and attributes of model elements using generated getter methods.
reset()
selects a state that is marked as being an initial state of the Turing Machine and saves it as the current state in a private field of the controller. (You did think about modeling initial states, right? If not, don't be frustrated, that's not too big of a deal. Just make the necessary changes to your metamodel and regenerate the code.)nextCommand()
analyzes the outgoing transitions of the currently active state and takes the first one that matches the current character. It then selects the target state of that transition as the new active state and returns the actions of the transition asHeadCommand
. If there is no transition that matches the current input, return a command that does nothing.- At the beginning of
nextCommand()
, check if there is an active state. If not, callinitialize()
andreset()
before doing the simulation. - Remember that if you add the new controller to the
de.cau.cs.rtprak.login.simple
plug-in, you will have to add a dependency to the...turingmodel
plug-in and make sure the latter exports the required packages.
Testing Your Head Controller
It's time to test the head controller. Here's one way you can go about it:
Create a Turing Machine model using the tree editor. Assuming that the initial head position is 1, the machine shall copy the input text infinitely often. That is, if the tape initially contains the word "hello", the machine should generate "hellohellohellohe..." You might remember this task from the first tutorial. To avoid an explosion of the number of states, select a rather small input alphabet for your machine, e.g. h, e, l, and o.
Save the model to the fixed path defined in your controller.
Select the new head controller in the Tape view and test it with input from your editor.
EMF Notifications (Optional)