Let us now add some operational semantics to our metamodel. To do so, we are going to add the actions we wish to implement thanks to the weaving mechanism in Kermeta that we've just seen before.
First of all let's prepare the appropriate programming environment needed for this implementation.org.kermeta.kmlogo.logoasm.srcKermeta will be the concerned project during this chapter. We'll setup a graphical UI using java AWT and a Java Math wrapper in order to add an UI to our DSL and add some math operations to Kermeta.
Copy/paste the folders and their content from org.kermeta.kmlogo.logoasm.tutorial/parts/3.behaviour/... into org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/ i.e.:
1.Models where are stored the models we are going to simulate;
3.JavaInterfaces where we can see the needed java program for this tutorial;
4.VirtualMachine where is defined the application domain;
5.Simulator where the execution program is provided.
Inside the org.kermeta.kmlogo.logoasm.srcKermeta/src create two packages org.kermeta.kmLogo.gui and org.kermeta.kmLogo.wrapper.
Move the files from :
3.JavaInterfaces/gui/ into the package org.kermeta.kmLogo.gui;
3.JavaInterfaces/wrapper/ into the package org.kermeta.kmLogowrapper (as they are now empty, you may delete the folder 3.JavaInterfaces/gui/ and 3.JavaInterfaces/wrapper/ after).
Caution | |
---|---|
At this point, you should have errors on your wrapper package. It is normal, we haven't set up the plugin yet. Though these next steps are not really part of Kermeta processing, we have to fix these errors to keep on. |
Replace the file META-INF/MANIFEST.MF by the one you can find in 3.JavaInterfaces/plugin. The manifest tell the project about its configuration (dependencies, exported package, runtime, ...). Have a look at its content and see how to solve the problem (If errors still persist, continue next step).
Copy the file plugin.xml in 3.JavaInterfaces/plugin and paste it on the root of your project. This is the file which handle the plug-in nature of the project. Observe its content (extension, ..). (you may delete the folder 3.JavaInterfaces/plugin and the package src/org.kermeta.kmlogo.logoasm.srckermeta since we don't use it).
At this point your project org.kermeta.kmlogo.logoasm.srcKermeta should have no error and present the structure illustrated below:
Now, still using aspect weaving, we are going to add some operations and properties to the ASMLogo.ecore in order to provide an operational semantics to Logo. We'll also see additional Kermeta features on aspect weaving.
We will weave an interpreter to the ASM by adding "eval" operations to the ASM metaclass where there's a behaviour. This eval operation will pass the actual context of the program.
Open org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/5.Simulator/LogoDynSemantics.kmt and observe how the weaving (obtained through the require statement at the beginning of the LogoDynSemantics.kmt) adds some operations and properties to the ASMLogo.ecore.
In the top right corner of the outline view, unfold kmlogo::ASM package. Then use the red/blue package icon to see what comes from the opened kmt file (ine red) and what comes from the imported files (in blue). So the "blue-red-mix" colored icon tell you that the class has an aspect weaved into it.
Find the class Repeat and observe that it only has a Block property imported from the ecore.
Inside this class, let's now simply add operational behavior in the eval operation as following:
aspect class Repeat { method eval(context : Context) : Integer is do from var i : Integer init condition.eval(context) until i < 1 loop result := block.eval(context) i := i - 1 end end }
Save the file and observe that the method eval was added in the outline view of the class Repeat. And because this aspect comes from this opened kmt file it is colored in red (see figure below).
Finally, find the class Context, and observe what is passed between eval() calls.
At this point, you know how to weave operational semantic to Kermeta and rapidly identify them in the Outline view. Aspected classes are represented in Red/Blue color.
In order to provide the behaviour, the interpreter needs an application domain. In this sample we call it Virtual Machine (VM).
Open the file org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/4.VirtualMachine/VMLogo.ecore, initialize its ecore diagram file to see its representation.
In this ecore file you'll notice the various notions needed for this VM : turtle, segment and points.
Open 4.VirtualMachine/LogoVMSemantics.kmt and observe how the weaving (obtained through the require statement at the beginning of the LogoVMSemantics.kmt) adds some operations and properties to the VMLogo.ecore. Those operations have some impacts on the GUI through command like stdio.writeln.
Like in the section before, use the outline view to identify what has been added (in red) to the structure (in bue).
Find the operation move in the class Turtle and observe some interactions with the UI (stdio.out).
Important | |
---|---|
As you may have noticed inside LogoVMSemantics.kmt, there is a call (require to the beginning of the file) to Math.kmt which is a Java interface needed to properly execute the simulator. So before moving onto the testing the simulator, let's have a look at how to set up this interface into the next section. |
In this step, we will see how some extra feature has been implemented in the operational sematics. It will explain how to call some java code to implement extra features.
This step will show you how a call to java may workaround some missing feature in Kermeta. It will explain how to call java.lang.Math from Kermeta. This is useful since the Kermeta doesn't provides sin, cos, tan operators by default. This may also be useful in case of major performance issue for a specific task.
Open org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/3.JavaInterfaces/Math.kmt which is the Kermeta wrapper. It defines the operations as seen by a kermeta code. The calls to java are done using the extern keyword. It will call the static java operation with the given qualified name.
Then, open the file src/org.kermeta.kmlogo.wrapper/Math.java the Java wrapper. It defines the static operations that the interpreter can call. All parameters must be of type RuntimeObject. This class is in charge of:
translating the RuntimeObject to and from classical java object (here java.lang.Double);
calling the appropriate java code
Important | |
---|---|
Remember that the objects in java side must implement a RuntimeObject in order to be manipulated with Kermeta. This is why all static method contains Runtimeobject parameters which is the Kermeta object kept in memory at runtime, and at last, must return a RuntimeObject. Also notice that the conversion to java types is done by the TYPE.create() method. |
In order to use this wrapper, simply import the Math.kmt (see LogoVMSemantics.kmt). Then, use it as a normal kermeta class. Since both java code is contained by the same plugin, there is no need of classpath declaration. If you need to use java code from another plugin, make sure that your plugin has a dependency to it.
To test this section, open the kermeta file 3.JavaInterfaces/test/testMath.kmt which contains the main operation to launch the java wrapper. Observe how a main class is defined in Kermeta and the use of Math.kmt.
Right-click on testMath.kmt and choose Run > Run as Kermeta Application, you should obtain the results illustrated below :
This section will guide you through the implementation of a graphical interface for the logo turtle. It is similiar to the call to Java.Math previously seen.
Open the file org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/3.JavaInterfaces/TurtleGUI.kmt. Like the java call that we have previously seen, it correspond to the kermeta wrapper. It defines the classes as seen by kermeta programs. For this application, it provides operations like drawLine, drawTurtle or clearDrawing. Note that it need an "initialize" operation in order to correctly create the object.
Then open the fileorg.kermeta.kmlogo.logoasm.srcKermeta/src/org.kermeta.kmlogo.wrapper/TurtleGUIWrapper.java. It defines the static operations that the interpreter can call. All parameters must be of type RuntimeObject. This class is in charge of :
translating the RuntimeObject to and from classical java object;
calling the appropriate java code. The associated java object (here a ITurtleGUI) is stored into the UserData of the RuntimeObject.
Tip | |
---|---|
Again, remember that the objects in java side must implement a RuntimeObject in order to be manipulated with Kermeta. This is why all static method contains Runtimeobject parameters (which are the Kermeta object kept in memory at runtime), and must return a RuntimeObject object type. Also notice that the initialize() method allow the "conversion" into java side i.e.: it creates a java object from the given name so as to represent the GUI (turtleGUI). Then it sets this object inside the RuntimeObject by the method setUserData() to store it for later re-use which is done with getUserData(). The conversion to java types is done by the TYPE.getValue() method in this direction. So if you want to implement yours, be sure that all your java object are not external to the Kermeta (RuntimeObject) domain, otherwise you must implement an internal controller to set up the glue (i.e.: the mapping). |
Then, the extra step here is implementing the graphical user interface. This is done by the classes in org.kermeta.kmlogo.logoasm.srcKermeta/src/org.kermeta.kmlogo.gui/. In order to allow some extensibility, it has been splitted into an interface ITurtleGUI and a simple concrete AWT implementation TurtleSimpleAWTGUI.
The last step before testing is to provide a simple controller that asks to the GUI to update the graphical view of a given Turtle. This is done by the file: 4.VirtualMachine/TurtleControler.kmt which implements 4.VirtualMachine/MoveListener.kmt (merely a turtle movement listener).
After succesfully testing the call to Java.Math, let's now test the virtual machine that we saw in section 7.3. To do so, open 4.VirtualMachine/tests/testVM.kmt. This file will initiate a turtle and draw a square using the kermeta wrappers and the java wrappers that we saw before (look at the required files define at the beginning of the kmt to see the interaction between the files). Right-click on this file an run it as a Kermeta application to see the graphical representation illustred below (notice by the way the console output that illustrate the impact of the GUI as mentioned in the step 2 of section 7.3):
Open org.kermeta.kmlogo.logoasm.srcKermeta/5.Simulator/ LogoSimulator.kmt. This class provides an execute operation. This operation allows to load a model that conforms to the ASMLogo.ecore and start the evaluation of the logo instructions. Finally, it asks to the controller to update the graphical view. This is the main entry and the loader for a logo model instance.
Now that we saw in "step 5" that the VM is working correctly, let's test the whole interpreter that we have set up. To do so, open the file 5.Simulator/tests/carre.kmt. It will instanciate a simulator, load an instance model from 1.Models/carre.logoasm and execute the interpreter. Right-click the file and run as kermeta application, you should obtain the same illustration as before.
Let's have another test. Remember the "dots.xmi" that you've created before inside org.kermeta.kmlogo.logoasm.model/model (if not, a copy is available at "org.kermeta.kmlogo.logoasm.tutorial/parts/1.metamodel/model"). Move it to the folder org.kermeta.kmlogo.logoasm.srcKermeta/kermeta/1.Models/. Open it and save it as dots.logoasm so as to convert it as a model instance understandable by our interpreter (remember the file extension that we've set up in the .genmodel). Now, open the file 5.Simulator/tests/dots.kmt and see that it calls the model we've just renamed. Run it as a Kermeta application to see the results (you can test the other models (*.logoasm) in the folder 5.Simulator/test).