OpenModelica Compiler Design
Date: 2011-11-03 12:29:00

[next] [prev] [prev-tail] [tail] [up]

### 3 OpenModelica Compiler Design

This documentation describes how the OpenModelica compiler is designed. The first section will give a brief overview of the design, and the rest of the sections will go into further detail about the different parts of the compiler in an order that roughly follows the compilation process.

This documentation assumes some familiarity with the MetaModelica language, which most of the compiler is implemented in. If you are not familiar with MetaModelica it might be beneficial to read through the first parts of the MetaModelica documentation in section 2 to become familiar with the MetaModelica syntax and data types. Also note that code examples in this documentation might be incomplete when it’s

#### 3.1 Modelica Translation Stages

The translation process of Modelica code to a simulation executable is schematically depicted in figure 1 below.

Figure 1: Translation stages from Modelica code to executing simulation.

Insert references to sections below

The OpenModelica compiler can be seen as divided into a front end and a back end. The input to the front end is Modelica code (typically .mo files), which is parsed and translated to a so-called flat model. This flattening phase removes the object-oriented structure from the model by instantiating the model’s components and performs operations such as inheritance, redeclares, and modifications. It also does type checking, expansion of connect equations, and handles package includes and imports. The result from this instantiation phase is a set of variables, equations, algorithms and functions, with all object-oriented structure removed apart from dot notation within names.

The result from the front end is then passed to the back end, where the first phase is the equation analyzer. In this phase the equations are sorted and transformed from their DAE representation into a Block Lower Triangular DAE form. The sorted equations are then passed to the equation optimizer, which tries to optimize the equations.

The optimized DAE is finally sent to the code generator, which generates code that can be compiled to produce a simulation executable. The default target language is C, but the code generator can be replaced to generate code for other target languages.

The OpenModelica compiler is also capable of compiling MetaModelica code, and the process for doing this is mostly similar to compiling normal Modelica functions with MetaModelica additions. It also handles MetaModelica scripts (.mos files), which is described in section 3.5.

#### 3.2 Simplified Overall Structure of the Compiler

The OpenModelica compiler is separated into a number of modules, implemented as MetaModelica packages. The entry point of the compiler is the Main.main function.

#### 3.3 The front end

##### 3.3.1 Parsing and Abstract Syntax

The parser is implemented as an ANTLR 3 grammar [?], and C code for the parser is generated with the ANTLR parser generator tool. The generated parser is then encapsulated by the Parser module, which provides functions for parsing source code either from file or from memory. These functions are implemented as external C functions which calls the generated C code from ANTLR.

The parser builds an Abstract Syntax Tree (AST) from the source code, using the AST data types in the Absyn module. The Parser.parse functions returns an Absyn.Program, which is simply a list of classes:

uniontype Program
record PROGRAM
list<Class> classes;
end PROGRAM;
end Program;

The Absyn.Class type contains the name of the class, the class’ prefixes and the body of the class:

uniontype Class
record CLASS
Ident name;
Boolean partialPrefix;
Boolean finalPrefix;
Boolean encapsulatedPrefix;
Restriction restriction;
ClassDef body;
Info info;
end CLASS;
end Class;

Something to note is that the type also contains an Absyn.Info object, which contains information about where an AST element was found:

uniontype Info
record INFO
String fileName;
Boolean isReadOnly;
Integer lineNumberStart;
Integer columnNumberStart;
Integer lineNumberEnd;
Integer columnNumberEnd;
TimeStamp buildTimes;
end INFO;
end Info;

Almost all AST elements contains an Absyn.Info object in some way or another. This is one of a few types that are propagated through the different stages of the compiler, and used when printing error messages to give the user a clue about where the errors are.

The AST closely corresponds to the parse tree and keeps the structure of the source file. The Absyn.ClassDef type can represent several different types of class definitions, but for normal classes it keeps a list of Absyn.ClassPart objects. These class parts represents the different declaration sections that a class might contain, such as public, protected, equation, and algorithm sections:

uniontype ClassPart
record PUBLIC
list<ElementItem> contents;
end PUBLIC;
record PROTECTED
list<ElementItem> contents;
end PROTECTED;
record EQUATIONS
list<EquationItem> contents;
end EQUATIONS;
record ALGORITHMS
list<EquationItem> contents;
end ALGORITHMS;
end ClassPart;

Modelica classes are allowed to contain multiple sections of the same type, with an implicit public sections first, so the class definition might similarly contain several ClassParts of the same type.

Class elements are ultimately represented by AbsynElementSpec objects, which can represent class definitions, components and other elements:

uniontype ElementSpec
record CLASSDEF
Boolean replaceable_;
Class class_;
end CLASSDEF;
record COMPONENTS
ElementAttributes attributes;
TypeSpec typeSpec;
list<ComponentItem> components;
end COMPONENTS;
end ElementSpec;

Parsing a Modelica model such as

model M
Real x, y;
equation
x = y;
equation
y = 2;
end M;

will thus produce an Absyn.Program that contains the class M. The class definition for M will contain a public section with the components x and y, and two equation sections: one section for x equals y and another for y equals 2. Note that the x and y components will be stored as a single Absyn.COMPONENTS, since they are declared with the same statement and thus share the same type and attributes.

##### 3.3.2 Rewriting the AST into SCode

Since the AST closely follows the structure of the source code it has several disadvantages when it comes to further translations of the code. Multiple class components might e.g. be grouped together into a single element node. A simpler intermediate form is therefore introduced, called SCode, with the purpose of simplifying further translations. The translation from Absyn to SCode is handled by the SCodeUtil package, with the entry point being SCodeUtil.translateAbsyn2SCode. SCode differs in many ways from Absyn, but some notable differences are:

- All class components are stored separately. A declaration such as Real x, y[17]; is split and stored as two separate elements in the SCode, as if it was declared Real x; Real y[17].
- Class declarations of the same type are merged together, so that e.g. all equations are stored in one list in the class while all algorithm statements are stored in another. Public and protected elements are also merged together, and the public/protected attribute is instead stored in the elements themselves rather than derived from the section they are stored in.

An SCode.Program, the equivalence to Absyn.Program in SCode, is simply defined as a list of SCode.Elements:

type Program = list<Element>;

The SCode.Element type represents the different types of elements, such as classes and components:

uniontype Element
record CLASS
Ident name;
Prefixes prefixes;
Encapsulated encapsulatedPrefix;
Partial partialPrefix;
Restriction restriction;
ClassDef classDef;
Absyn.Info info;
end CLASS;
record COMPONENT
Ident name;
Prefixes prefixes;
Attributes attributes;
Absyn.TypeSpec typeSpec;
Mod modifications;
Option<Comment> comment;
Option<Absyn.Exp> condition;
Absyn.Info info;
end COMPONENT;
end Element;

Not all Absyn data structures are translated into SCode ones, as is evident in the code listing above. Some types are already simple enough that they are reused in the SCode, some notable examples being Absyn.Exp, Absyn.TypeSpec, Absyn.Info, Absyn.ComponentRef, and Absyn.Path.

##### 3.3.3 Model Flattening and Instantiation

#### 3.4 The back end

#### 3.5 Scripting MetaModelica

Describes the Interactive module.

[next] [prev] [prev-tail] [front] [up]