ERCIM News No.36 - January 1999
Dynamic Translator Development: Modelica in the Python TRAP
by Thilo Ernst
Modelica is the new unified, object-oriented description language for dynamical models of physical systems developed in an international effort in which GMD co-operates. GMD is developing a Modelica translator for integration in the Smile dynamic simulation environment. The Python language which is used as an integration platform in Smile, together with associated tool components also proved to be a powerful basis for translator development. By its combination of very high level of abstraction, interpreted execution, and ease of extensibility, Python enables a new development methodology also for language processors; with reference to generic simulation environments, it provides a unique foundation for R&D in dynamic model evolution.
Modelica (http://www.modelica.org) is a unified language for dynamic models of complex physical systems being developed in international effort (formally, a combined EUROSIM technical Committee/SCS Technical Chapter) in which GMD participates (see also ERCIM News Number 32). Smile (http://www.first.gmd.de/smile) is an object-oriented dynamic simulation environment developed by Technische Universität Berlin and GMD. In its latest revision, it heavily builds on Python as an integration platform for both external and internal software components. GMD is developing a prototypical Modelica compiler component for integration into Smile. The Modelica processor is intended to be open, extendible, and reusable.
Python (http://www.python.org) is an interpreted, object- oriented language often referred to as a scripting, extension or glue language, as it is well-suited and popular as a framework for integrating software components across diverse implementation languages and programming paradigms. However beyond that, Python is a full-fledged, platform-independent, modern programming language. Python offers powerful features such as classes, modules, exceptions, dynamic typing and very high level collection data types in a concise, regular and very readable syntax. The languages high level of abstraction and (byte-code-)interpreted execution provide an outstanding development efficiency. Performance bottlenecks can easily be identified and can be effectively attacked by extensions, ie optimised low-level (C/C++) re-implementations of the (typically small) code parts in question. This enables a very efficient rapid prototyping/rapid application development (RP/RAD) methodology. The Python language and software package are free and not subject to legal restrictions hampering any kind of application. Python is mature and reliable, and (thanks to a large and active user community) a huge collection of library components written in or interfaced with Python exists, for the most part free like Python itself.
Using Python for translator implemen-tation was a rather obvious idea in the project setting described above, as a Python interface between the Modelica translator and the Smile-internal equation system data structure was planned anyway. Therefore this option was evaluated in more detail. It turned out that the language has a set of features that very effectively can be exploited to approach common data structure and algorithm patterns found in compilers. For instance:
- Python offers sequence types (lists and tuples) and their standard manipulation methods as built-ins. List manipulation is sufficient to implement algorithms based on incremental set manipulations, which are ubiquitous in compilers.
- Pythons object model and extension concept make it easy to work with sets or graphs of objects (that represent any semantically relevant information) using a class library, and later on transparently migrate to a more efficient bitset implementation.
- Pythons dictionary datatype can be used to represent arbitrary mappings between Python objects. Mappings occur frequently in compilers as well: name space and symbol table both refer to mappings (on different levels of abstraction).
- Pythons object model can be effectively used for object oriented compiler techniques, eg representation of abstract syntax tree (AST) node sorts by a class hierarchy in which standard functionality (eg tree traversal according to the visitor design pattern) is packaged. Python is not statically typed, but has a dynamic type system which can be easily used to enforce compiler-specific constraints, eg local wellformedness constraints for AST nodes can be checked in the node constructors.
- Python, by integrating concepts from both worlds in one language, also allows the user to choose the right mixture of functional and imperative programming adapted to the task at hand.
- Python uses a reference-counting based automatic memory management scheme hidden from the user: Objects can be simply created without caring about the memory allocation that is automatically happening; objects are silently reclaimed as soon as they are no longer referenced.
The transformation phase of a translator is where these advantages can be best exploited; lexical and syntactical analysis of the source text have to be done already. Fortunately, front-end tool components (scanner and parser generators) already were available as Python modules, so only a thin layer of tooling needed to be added to obtain a small, but sufficiently powerful Python-based development environment called TRAP (Translator RApid Prototyping) for building a Modelica translator. TRAP takes a compiler description consisting of an EBNF-style grammar specification (enriched with semantics actions expressed by pieces of Python code attached to the production rules) and a concise hierarchical description of AST node sorts. In addition, type constraints for non-terminals and fields can be specified. From this, a (Python) compiler frame module is automatically generated, providing scanner, parser, the set of node class definitions with standard method instrumentation (printing, dynamic typecheck, traversal, pattern matching) and some auxiliary code. That way, source code of the language to be processed is easily converted into Python data structures; subsequent transformations are implemented directly in Python. The figure presents sample snippets from a compiler description.
Example constructs of the TRAP description. compiler SimpleMod
# comment syntax of language processed
# lexical tokens
tokx`zNT '[A-Za-z][A-Za-z0-9_]*' # default semantics: matched text
token INT_CONST '[0-9]+':
string.atoi(str) # explicit semantics: convert to IntType
# grammar: nonterminals with rules & semantics
# default: pass through constituent's semantics
<- "(" expression=E ")":
E # explicitly pass through semantics of E
nterm name:: # type constraint: Python list
<- ["." IDENT+] # non-optional repetition with separator "."
# automatic semantics: list of strings
nterm class_definition::Mclass # type constraint: a node class
<- class_key=C IDENT=i1 Mcomment=K (component*)=T "end" IDENT=i2 ";":
if i1 != i2: # a simple semantics check
ERR("Name mismatch:", i1, "/", i2)
Mclass(C, i1, K, T) # construct AST node as semantics value
# abstract syntax: a node type definition
key, # default field type: StringType
components::(component) # type: Python tuple of 'component' nodes
Modelica can be categorised as a special-purpose language of medium complexity. TRAP of course should be generally useful for building translators for such languages. Indeed, it was already used for bootstrapping itself. However the emphasis here is not on building yet another compiler tool - TRAP mainly integrates relevant concepts from existing toolkits such as Cocktail, Gentle, and PCCTS. The important point is that this integration was done in the open, dynamic framework provided by Python.
In the context of processing Modelica, expressing semantics transformations in Python is more than merely convenient - this approach indeed provides a unique foundation for further R&D in generic modelling and simulation: Currently, most generic simulation systems have a rigid separation of compilation vs. Simulation phase. However, for certain application classes, it would be desirable to change structure and/or details of the model being worked on during simulation. With a Python-based, dynamic Modelica translator, (re-)doing semantically complex model transformations at simulation time poses no technical problems. A fully dynamic modelling and simulation system architecture in which concepts like dynamic model evolution can be conveniently investigated is an important area of future work.
Thilo Ernst - GMD
Tel: +49 30 6392 1919