- 1 Introduction
- 2 ATL Plugins
- 3 ATL Language
- 4 ATL API Usage
- 5 ACG (ATL VM Code Generator)
- 6 ATL VM
- 7 ASM format
This documentation aims at contributing to the comprehension of the ATL source code.
TODO: update the schemas with the ATL 3.0 plugins The following schema purposes an overview of the plugins constituting.
Dependencies map : (plugin1 --- [depends] ---> plugin2)
Historically, ATL imports two libraries : ANTLR version 2 and MDR. Those libraries are not authorized in Eclipse because of their non-compliance with the Eclipse IP policy. Consequently, ATL imposes users to download those libraries by themselves and install them into Eclipse plugin folder.
Today, ATL dependencies have been strongly reduced : ATL only needs ANTLR-runtime (version 3) library, which is compliant with the Eclipse IP policy and included into ATL source code. The MDR library is only necessary for the MDR Model Handler. According to the fact that most of people uses EMF Model Handler (which seems to be more powerful), MDR Model Handler has been separated into a single feature, which is not natively required for ATL.
TCS (Textual Concrete Syntax), a tool for parsing and extraction, is used to generate some ATL components (e.g. ATL-Parser). Unlike ATL, TCS uses both ANTLR library, in version 2 and newly in version 3. TCS is available on GMT. ATL doesn't have any dependency with TCS. Specific injectors depend on ANTLR too.
ATL language which can be split into two parts :
- declarative : matched rules, and called rules body. The main use of ATL is declarative. Imperative part should only be used in specific cases.
- imperative : called rules (imperatively called), and action blocks (« do », usable in any rules)
Specifics uses of those parts are described in the ATL Language Troubleshooter section.
ATL architecture is composed of four main components :
ATL VM is intercalated between the ATL compiler and the used frameworks (EMF, MDR), allowing modularity. Consequently, changes on ATL Language only involve ATL compiler. The following schema describes ATL components and their role during the execution of a transformation.
Parsing and Compilation
ATL parsing is done using a parser defined in TCS, which outputs an ATL model conforming to the ATL metamodel. Then, an ATL-WFR transformation (interpreted by the engine) generates a problem model. This model produces errors interpreted by the editor and translated into markers, visible on the ATL file on each compilation.
The ATL Debugger provides tools to support profiling, debugging, etc... of ATL applications. It can be compared to the JVM TI.
In ATL, three debuggers are implemented :
- DummyDebugger : a dummy class implementing the debugger interface without doing anything.
In the ATL VM code, debugger entry points are located into exec methods of operations, materialized by “step” method calls.
The simple debugger is the default ATL debugger : it displays in Eclipse's console the informations traced by the ATL VM during the execution. A “very verbose” option allows to display all possible informations traced by the ATL VM frames, intending to debug the ATL VM. Many options are available, for example :
- step : stop point at every bytecode instruction
- stepops : list of operations for which we want to display bytecode
- deepstepops : same than stepops, also including sub-called operations
The network debugger is the main debugger of ATL, integrated to Eclipse's debug perspective. It uses ADWP, a TCP debugger inspired on JDWP (the java debugger). All debug informations are sent on a TCP port by the executed program (Local). Those informations are received and computed by the debugger (Remote), implemented in the org.eclipse.m2m.atl.adt.debug plugin.
In the current ATL implementation, this plugin provides an “atlvm” extension point, which is implemented in the ATL VM (NetworkDebugger class). This implementation has been done to facilitate coding. The disassembly mode allows to debug the bytecode, without ATL source code, and make easier to debug the ATL VM.
ATL API Usage
TODO: explain the ATL 3.0 core API
ACG (ATL VM Code Generator)
ACG is a compiler-oriented DSL, which intends to make easier to create a compiler targeting the ATL VM. A compiler described with ACG generates ASM files and contains a description of ASM instructions to generate for each type of input elements, coming from a compiled file. Therefore the input of this kind of compiler is a model describing the content of a compiled file (for instance, an ATL file).
An ACG file, when compiled, looks through the input model using a visitor design pattern. ACG is bootstrapped : an ACG.acg file exists and describes the ACG compiler. Since an ACG file describes precisely ASM instructions, the ACG.acg file is rather trivial.
A complete ACG documentation is available here.
ACG in AMMA platform
The following schema places ACG in the AMMA platform.
The ATL VM is a byte code interpreter which manages OCL and ATL types hierarchy and the model handler abstract layer. A complete ATL VM specification is available : ATL_VMSpecification.
This specification consists on a precise description of the ATL VM functionalities, but doesn't describe the implementation. The intent is to allow any developer to create an ATL VM in any language. This section attends to describe the ATL Regular VM implementation.
Several classes can launch the ATL VM, with different goals :
- The ASMInterpreter class launches the ATL VM. The realMain method is used to launch ATL VM in command line.
- The ASMProjector class is only defined to launch injections, extractions, or both without launching any transformation.
- The ASMEngine class is the real ATL VM command-line launcher that dispatches to ASMInterpreter, ASMProjector, or ACTInterpreter, depending on the arguments.
- The ACTInterpreter class is now unused and was historically used to launch ATL VM with ant-like scripts. It depends on XMLInjector. Thus, for coding facilities, this class is located into the ATL VM. For a coherence purpose, XMLExtractor is also located into the ATL VM. However the associated extension points are defined in the engine plugin.
During ATL VM initialization, every operations are registered into a Map. The following schema explains ASMInterpreter functionment :
The ExecEnv Class contains the virtual execution environment. It deals with the operation map which registers all operations used by the transformation. It contains every information used by a given execution, like models, and is recreated for each execution. Operations are executed sequentially, into frames, according to their type. For instance, in ATL, a call of the append() method is directly mapped to a call to the corresponding method in the ASMSequence class. The Frame stores and throws all error messages. The ASMStackFrame is dedicated to ASM methods, when the StackFrame is dedicated to native methods. Execution errors come from ATL VM when the method Frame.printstacktrace is called.
The Native Library (org.eclipse.m2m.atl.engine.vm.nativelib package) gathers all basic type definitions used by the ATL VM : OCL types and ATL specific types. Both are defined at the same level, and use reflexion. OCL appears at several levels in the ATL architecture :
- nativelib implementation
- OCL package in the ATL, ACG and TCS metamodels
Model Handlers consists on an abstraction layer dedicated to model access. This access is implemented by two classes : ASMModel et ASMModelElement.
Input and output models are loaded using the same API and are differenciated with an “isTarget” property. That API implements the “getMetaElementsByName” method which correspond to the “findme” ASM instruction.
ATL contains three plugins drivers corresponding to different Model Handlers : EMF, MDR, UML2. Each plugin implements those abstract classes :
- AtlModelHandler : implementation of the basic tasks “newModel”, “saveModel”, “loadModel”
- ASMModel : getElementsByType implementation, framework oriented “newModelElement” method, etc...
- ASMModelElement : “allInstances” implementation, etc...
The EMF4ATL is a particular case which doesn't contain the ModelHandler, which is placed in the org.eclipse.m2m.atl.engine plugin to facilitate implementation.
ASM language is a kind of assembly language, adapted to model handling. The low level of ASM allows modularity facilities, with the intent to provide easier model management possibilities. The current file format for ASM is XML. Thus it allows not to care about any syntax and to only focus on bytecode. An ASM file only contains names and string constants. No Ecore reference is present. Those are resolved by launch configurations and AMMA Megamodel, with a name binding.
ASM transformations are serialized in a way to increase performance and preempt further serializations like binary files. The ASMXMLWriter class is an ASM extractor used to save ASM into a file. Serialization computes the constant pool, which factorizes constants, values and method calls by generating an ordered constants list at the top of the ASM file. ASMWriter is the parent abstract class which allows a binary implementation of ASM injection and extraction.
All instructions are explained into ATL VM specification. Here are details about some of them:
- The getasm instruction retrieves the ATL Context Module, i.e. The “thisModule” equivalent for ATL.
- N symbolizes a native type, ATL specific
- TransientLink are traceability links
- all functions like “getLinkBySourceElement” are implemented in the nativelib
- Object creation :
- The “new” instruction takes two parameters : the metamodel name and the classifier type. Then it creates an element of this type in the output model (only one is allowed). The parameters are not available in the bytecode because they are pushed on the stack before calling instruction.
- We can notice that ATL allows only one output model, but the ATL VM could be extended two allow many others.
- A delete instruction could be implemented in the ATL VM
- ATL provides the newInstance method which is directly mapped to the Model Handler method. This method doesn't generates a new because the call is dynamic. The main advantage is that the newInstance is directly applied to the class and do not use the ATL VM stack for that (otherwise it should store the class element).