Skip to content
Snippets Groups Projects
Commit 1ca754de authored by Reiner Jung's avatar Reiner Jung
Browse files

Merge branch 'main' into 'tdd_file_writer'

Added documentation for arrays and code generation for CP-DSL.

See merge request !19
parents 841e8505 c8dc6a0d
No related branches found
No related tags found
2 merge requests!20Update of TDD DSL: Add Fortran fiel generator with merge function,!19Added documentation for arrays and code generation for CP-DSL.
Pipeline #12928 passed
Showing with 1029 additions and 0 deletions
......@@ -12,6 +12,8 @@ This project contains multiple DSLs for ocean and earth system models.
- TDD-DSL testing DSL for test-driven development
- BGC-DSL language to specify biogeochemical models
Documentation can be found in the `doc`.
## License
Apache 2.0
......
File moved
# OceanDSL Unit System
Units in OceanDSL can be any combination of SI or custom units using
standard prefixes, such as k for kilo or m for milli. They can have
exponents to express areas, volumes or other higher dimensions.
As some values can be unit-less, it is possible to specify a variable,
function or value without a unit. To express more complex unit, it
is necessary to create composite units, such as kg m² / s².
Units are used to ensure that only valid numbers are assigned to values.
The OceanDSL DSLs allow to convert compatible units. That means if a parameter
is declared as using meter, but the assigned value is specified with the unit
km, the value is automatically converted to meter.
Similarly, Celsius and Kelvin are converted accordingly.
## Grammar
```antlr
// ----------------------
// Units
// ----------------------
// substance is of type substanceDeclaration
unit:
':' units=unitElement+ (substance=ID)? |
'::'
;
unitElement:
prefixUnit | groupUnit | exponentUnit
;
// removed unit-label for UNIT_STRING, here
prefixUnit:
(UNIT_STRING | custom=CUSTOM_STRING)
;
groupUnit:
'(' elements+=unitElement+ ')'
;
exponentUnit:
unit=unitElement '^' exponent=NUMBER
```
The rule `unit` allows to compose a unit out of one or more unit
elements, or skip the unit with `::`.
The ability to have a sequence of units in `groupUnit` and `unit`
seems to be unnecessary complicated, but from a users point of view, it
allows you to avoid braces for more basic composites, such as Nm and kg m²/s².
The former would be two `prefixUnit`s and the latter one with `kg` followed by
two `exponentUnit`s, i.e., `m ^ 2` and `s ^-2`.
The negative index value expresses the fraction (/).
Each unit can have an substance identifier. This is used in BGC-DSL to ensure
that substances are not mixed.
In future, this could be extended to allow certain mixtures to create new
kind of substances.
A unit is comprised at least of one `unitElement`. Each `unitElement` is either
a `prefixUnit`, an `groupUnit` or an `exponentUnit`.
A `prefixUnit` is either an SI unit with or without an SI prefix, or a
custom unit identifier. It can be used to specify simple units of measurement.
`groupUnit` allows to group `unitElement`s together. This can be helpful to
express more complex units which may arose during calculations. For example, the
kg m^2 s^2 unit can also be written as kg (m s^-1)^2. While this might not
seem to be necessary in many cases, we have found examples in the literature
that required grouping.
`exponentUnit` is used to express any unit with an exponent, e.g., m^2.
The exponent numbers can be positive or negative.
## SI Unit Parsing
SI units comprise of an optional prefix and one or more character to define a
base unit.
Prefixes are: https://www.nist.gov/pml/owm/metric-si-prefixes
- Q R Y Z E P T G M k h da d c m my n p f a z y r q
Units are: https://en.wikipedia.org/wiki/International_System_of_Units
- s m g A K mol cd Hz J C W rad sr N Pa V F Ohm S Wb T H °C lm lx Bq Gy Sv kat
**Rules**
Here is a list of mapping rules for SI unit string. ($ indicates line end)
m -> meter
mm -> milli mmeter
mmol -> milli mol
my -> micro
**Note:** The original Java code can be found here. However, it is more
complicated as it is also able to process exponents and other symbols.
https://git.se.informatik.uni-kiel.de/oceandsl/cp-dsl/-/blob/master/bundles/org.oceandsl.configuration/src/org/oceandsl/configuration/parser/UnitParser.java
## Representation
The grammar implies a specific CST structure for units. Here we go beyond this,
as it better represents basic units and prefixes.
```
class Unit
units : List<UnitElement>
abstract class UnitElement
```
**Discuss:** Should we use one `PrefixUnit` class for SI and custom units?
*Option* joined class
```
class PrefixUnit extends UnitElement
basicUnit : EUnit
prefix : EPRefix
unitName : String
```
*Option* separate class
```
class PrefixUnit extends UnitElement
class PrefixSIUnit extends PrefixUnit
basicUnit : EUnit
prefix : EPRefix
class PrefixCustomUnit extends PrefixUnit
unitName : String
```
**Discuss:** Should custom units also have a prefix and how do we process these?
*Option* separate class where both can use prefixes
```
class PrefixUnit extends UnitElement
prefix : EPRefix
class PrefixSIUnit extends PrefixUnit
basicUnit : EUnit
class PrefixCustomUnit extends PrefixUnit
unitName : String
```
Classes for units with exponent and grouped units.
```
class ExponentUnit extends UnitElement
unit : UnitElement
exponent : integer
class GroupUnit extends UnitElement
units : List<UnitElement>
```
## Semantics
Unit semantics are similar to normal type system semantics, however, there are
also some subtle differences. Therefore, we explain basic semantic rules here.
Please note that units can be much more complicated (see normalization).
T,R,S are unit type placeholders
t,r,s are variables, functions or values
### Expression: t + r
```
t : T + r : T
-------------
t + r : T
```
This expresses that in an addition both need to have the same unit.
Regarding substances, the substance can be different, as it is possible that
different substances are mixed. They can even create new substances.
### Expression: t - r
```
t : T - r : T
-------------
t - r : T
```
This expresses that in a subtraction both need to have the same unit.
### Expression: t * r
```
t : T * r : R
-------------
t * r : T * R
```
In case the base type of T and R are the same, the unit can be merged, e.g.,
when multiplying two length (m), the result is area (m^2).
```
t * r : T * R and base(T) == base(R)
----------------------------------------------------------------------------
t * r : S and base(S) == base(T) and exponent(S) = exponent(T) + exponent(R)
```
In other cases the unit expression becomes more complex.
### Expression: t / r
Analog the the multiplication, the division leads to a new composite type which
could be merged when both types have the same base unit.
```
t : T / r : R
-------------
t / r : T / R
```
### Expression: f(x_1,...,x_n)
Functions have already a unit type assigned or it can be derived from their
expression. Furthermore, each parameter has a unit assigned.
For mathematical built-in functions, they do not have a type and assume the
type specified by the input type.
Therefore, all input units must be the same unit or without a unit.
### expression: t^i
Exponents require that t has a unit or no unit, but i is a unit less integer
value.
```
t : T ^ i : I
------------------------------------------------------------------
t ^ i : S with base(S) = base(T) and exponent(S) = exponent(T) * i
```
## Normalization
Based on the syntax, the same unit can be expressed in different ways. This
can happen due to the sequence of basic units and grouping. The goal of the
normalization is to have one sequence of exponent units which is sorted in
the same order.
Discuss: Shall we do unit normalization in expression, e.g.,
1 m^3 + 1 l would be codes as 1 m^3 + 0.001 m^3.
The normalization works therefore in two phases.
1. All groups get removed.
2. Merge nested `exponentUnit`s.
3. The remaining units are sorted.
4. Units with the same base unit get combined.
### Group elimination
There are two cases of groups.
(a) Group which is the child of an `exponentUnit`
(b) Group which is the child of another `groupUnit` or `unit`
In case (a) each child of the group element, is embedded by a `exponentUnit`.
For example, kg (m s^-1)^2 becomes kg m^2 s^-1^2.
In case (b) the `groupUnit` can be merged directly with the parent `groupUnit`
or `unit`.
### Exponent Merging
For all `exponentUnit`s in the unit sequence, it is checked whether there is
a nested `exponentUnit`. To eliminate one nesting the outer `exponentUnit`'s
exponent is multiplied with the exponent of the inner `exponentUnit` and the
inner `exponentUnit`'s unit becomes the outer `exponentUnit`'s unit.
This is repeated until all `exponentUnit`s only contain one `prefixUnit`.
### Sort Units
We iterate over the remaining sequence and replace every `prefixUnit` for an
`exponentUnit` with the exponent value of 1 and set the `prefixUnit` as its
`unit`.
Then we sort the units on the basis of `prefixUnit`s, i.e., in case in a
sequence, we find a m and a m^2 they are sorted next to each other.
Discuss: Do we ignore prefixes at this point or must we consider prefixes as
well?
### Merge Base Units
Finally, we run over the sequence and look for each value whether the next
value is of the same `prefixUnit` and merge their exponent accordingly, i.e.,
we create the sum of the exponents.
We then replace the two `exponentUnit`s by one with the same `prefixUnit` as
the original and the sum of both exponents.
Then we repeat this with the next `exponentUnit`.
In case the exponent becomes zero both `exponentUnit`s are removed and nothing
is added.
# Arrays in CP-DSL
Arrays are a common element of programming languages and are widely used to
configure functions in earth system models. In the past, arrays were merely
blocks of memory split in identical elements of one type. They could be
multidimensional which then require a more complex way to map indices to
memory location, e.g., `int[2][4]` would either require two blocks of 4
integers or 4 blocks of 2 integers. The location function would be
```location(i_0,i_1) = (i_0*4+i_1)*sizeof(int)```
This becomes more complex when arrays are dynamic, i.e., they are defined
with dimensions `d_0 ... d_n-1`, but the respective sizes for each dimension are
unknown at compile time. For two dimensions, this would look like
```location(i_0,i_1) = (i_0*d_1+i_1)*sizeof(int)```
This implies an order where the second dimension (d_1) has scalar elements, and
the first dimension (d_0) is a list of array of dimension d_1. Thus, the index
must be multiplied by the length of d_1.
```math
location(i_0,...,i_n) = sizeof(int) * \sum_{j=0}^{n} i_j * \prod_{k=j+1}^{n} d_k
```
The CP-DSL supports dynamic arrays. Thus, dimension sizes can change and are
not fixed in size in the declaration model. Therefore, we can use lists or maps
to implement them.
## Features of Arrays
Arrays can have multiple dimensions. These dimensions can be declared as fixed
in size or dynamic in size in the declaration model. The fixed size can be
defined as size or range.
- size, e.g., `int[5]`, which defines an integer array with values for
0 to 4.
- range, e.g., `int[2:6]`, which defines an array with elements from
2 to 6.
Dynamic arrays start if not specified differently with the index 0. However,
there can also be constraints:
- `int[]`, starts its values from index 0 upwards
- `int[2:]`, starts its values from index 2 upwards
- `int [:4]`, limits the indices to 4 starting from 0, e.g., '[0,1,2,3,4]'
The declaration model declares the dimensions, size constraints and base type of
an array. In the configuration model, an array element selector can select a
subset of an array, e.g., declaration model `int[1:10] data` declares the
attribute data as an integer array with the indices 1 to 10. There is no
element at index 0. The configuration model assignment
```
data[2:5] = [ 1,2,3,4 ]
```
assigns to the attribute **data** 4 values to the indices 2 to 5 of the declared
array. This implies elements 1,6,7,8,9 and 10 are uninitialized.
The specified **values** (here 1,2,3,4) in the configuration model must match
the **sizes** of the remaining dimensions based on the configuration model
modifiers (here the range from 2:5). There the values are moved in the
assignment to the correct indices. The above example
`data[2:5] = [ 1,2,3,4 ]` creates a value array with 4 numbers that are
internally a list of values starting at index 0 up to 3.
`data[2:5]` is an array selector on data, which selects the indices 2 to 5
from the data array. The assignment then places the values 2 to 5 accordingly,
i.e., the element with index 0 of the value array is assigned to `data[2]`,
element 1 is assigned to `data[3]` and so on.
In addition to ranges, element selectors can also select single elements. For
example, `data[2] = 4` assigns the scalar value 4 to the element with the index
number 2 of the data array. Thus, it is possible in our DSL to initialize
arrays in CP-DSL as follows:
- `data[2] = 1`
- `data[3] = 2`
- `data[5:6] = [ 3, 4 ]`
This allows for empty elements in arrays. Not all programming languages
allow for empty cells in arrays, especially not with primitive data
types. Thus, this generates a information indicator in the editor. As some
configurations use this feature, we cannot prohibit such specifications.
## Implementation
The template compiler needs a model for arrays that retains the ranges and
indices to each value. Therefore, the internal representation of arrays
follow the concept of an associative array or map, where indices are map
keys. This has also an impact on for-loops. The template DSL implements a
for-loop that iterates over an array initializing three values available in the
expression of the loop. These are `it` containing one element value of the
array, `icount` containing the loop counter (starting always with 0), and the
index number 'i#'.
Here, the loop iterates over all elements declared in declarations. However,
*it* will only contain a value for those that have a value assigned, *i#* will
contain the respective index value, and *icount* the relevant loop counter.
Array values can also be accessed directly in a template by parameter name and
an index, e.g., `data[4]`. Here, this would return the element with the index 4
from the array data. Using our example above, `data[4]` has no assigned value.
Thus, it would be undefined. When converted to string, this produces the value
`undef`. However, to be able to distinguish whether a value exists or is
undefined, the user can use the function exists, which returns `true` in case a
value is present.
# Code Generation
The CP-DSL comprises a declaration, a configuration and a template DSL.
The declaration DSL declares features, parameter groups, parameters, default
values for parameters and dependencies between features. The default values
can use expressions to compute their values, which is helpful when parameters
depend on each other. The configuration DSL allows to select features and
assign values to parameters. Here, defaults can be replaced by actual
assignments.
To provide the template DSL with an easy-to-access data model, we compute an
interim model containing all resolved values and type descriptors. The
current implementation uses X stages to compose the interim model and generate
template output.
Initially, we create a model containing all parameters groups, parameters and
features. The latter all in a deactivated state. Then the parameters get their
assigned default expressions or values. This is necessary, as the expression
might need (re-)evaluation after configuration values have been assigned.
In case there are circular references between parameters, the declaration DSL
editor would have reported them.
Secondly, the configuration is applied to the interim model. Here,
parameter become their configured values or expressions. These can also include
references to other parameters, and this may also cause circular dependencies.
The generator checks this and reports an error if circular dependencies are found.
Thirdly, the expressions for each parameter are evaluated and only the resulting
value is stored in the interim model.
Fourthly, all templates related to the declaration model are processed based on
the interim model.
# Interim Model
InterimModel
- name : String // experiment name from the configuration model
- declaration : DeclarationModel
- parameterGroups : ParameterGroup[]
- features : Feature[]
ParameterGroup
- name : String
- declaration : ParameterGroupDeclaration
- parameters : Parameter[]
Feature
- name : String
- parameterGroups : ParameterGroup[]
- features : Feature[]
- declaration : FeatureDeclaration
- active : Boolean
Parameter
- name : String
- declaration : ParameterDeclaration
- computedValue: ValueContainer
- dataEntries : ParameterEntry
- specifiedType : TypeAssignment // type including the restrictions due to
the selector used in the configuration. This
is used to support the type cast during
computation of the value for the parameter
ParameterEntry
- expression : Expression
- selectors : Selector
ValueContainer (generic type)
+ ScalarValue
+ ArrayValue
ScalarValue
- value : Value
ArrayValue
- values : IndexToValueContainerMap
- lowerBound : long
- upperBound : long
IndexToValueContainerMap
- key : long
- value : ValueContainer
# Processing Declaration Model
- InterimModel is created and the back reference (DeclarationModel) is set
- for each ParameterGroupDeclaration a interim:ParameterGroup is created and
the back reference (ParameterGroupDeclaration) is set.
- for each Parameter in each ParameterGroupDeclaration a corresponding entry
is created and linked back
- the same applies to all Features
Each interim::Parameter will have set
- name
- declaration
- dataEntries (one entry from the Declaration model)
- specifiedType (??)
# Processing Configuration Model
- Walk over the InterimModel and
- add parameter values from the configuration and add them to dataEntries
- activate and deactivate features
# Computing Values in the Interim Model
In this task, all value expression must be computed. This is done for each
parameter.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
<!--Created by yEd 3.20.1-->
<key attr.name="Description" attr.type="string" for="graph" id="d0"/>
<key for="port" id="d1" yfiles.type="portgraphics"/>
<key for="port" id="d2" yfiles.type="portgeometry"/>
<key for="port" id="d3" yfiles.type="portuserdata"/>
<key attr.name="url" attr.type="string" for="node" id="d4"/>
<key attr.name="description" attr.type="string" for="node" id="d5"/>
<key for="node" id="d6" yfiles.type="nodegraphics"/>
<key for="graphml" id="d7" yfiles.type="resources"/>
<key attr.name="url" attr.type="string" for="edge" id="d8"/>
<key attr.name="description" attr.type="string" for="edge" id="d9"/>
<key for="edge" id="d10" yfiles.type="edgegraphics"/>
<graph edgedefault="directed" id="G">
<data key="d0"/>
<node id="n0">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="95.0" x="366.0" y="335.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="79.44451904296875" x="7.777740478515625" xml:space="preserve" y="4.827942848205566">Declaration n<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n1">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="124.0" x="644.0" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="36.688228607177734" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="88.82861328125" x="17.585693359375" xml:space="preserve" y="-3.344114303588867">Interim Model/
Symbol Table<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n2">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="118.0" x="644.0" y="130.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="92.05662536621094" x="12.971687316894531" xml:space="preserve" y="4.827942848205566">Configuration 1<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n3">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="95.0" x="366.0" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="78.89251708984375" x="8.053741455078125" xml:space="preserve" y="4.827942848205566">Declaration 1<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n4">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="118.0" x="644.0" y="196.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="96.41265869140625" x="10.793670654296875" xml:space="preserve" y="4.827942848205566">Configuration m<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n5">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="124.0" x="955.0" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="36.688228607177734" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="88.82861328125" x="17.585693359375" xml:space="preserve" y="-3.344114303588867">Interim Model/
Symbol Table<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n6">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="30.0" x="534.0" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="53.0323429107666" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="152.39305114746094" x="-61.19652557373047" xml:space="preserve" y="-67.68822860717773">Declaration Interim Model
and Symbol Table
Creation Visitor<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.5" nodeRatioX="0.0" nodeRatioY="-0.5" offsetX="0.0" offsetY="-14.655885696411133" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="ellipse"/>
</y:ShapeNode>
</data>
</node>
<node id="n7">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="30.0" x="846.5" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="53.0323429107666" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="165.55715942382812" x="-67.77857971191406" xml:space="preserve" y="41.65588569641113">Configuration Interim Model
and Smybol Table
Creation Visitor<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="0.5" offsetX="0.0" offsetY="11.655885696411133" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="ellipse"/>
</y:ShapeNode>
</data>
</node>
<node id="n8">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="118.0" x="1221.0" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="20.344114303588867" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="93.08865356445312" x="12.455673217773438" xml:space="preserve" y="4.827942848205566">Resolved Model<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="rectangle"/>
</y:ShapeNode>
</data>
</node>
<node id="n9">
<data key="d5"/>
<data key="d6">
<y:ShapeNode>
<y:Geometry height="30.0" width="30.0" x="1135.0" y="269.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" raised="false" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="36.688228607177734" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="93.90464782714844" x="-31.95232391357422" xml:space="preserve" y="47.65588569641113">Compute Result
Model<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="-0.5" nodeRatioX="0.0" nodeRatioY="0.5" offsetX="0.0" offsetY="17.655885696411133" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
<y:Shape type="ellipse"/>
</y:ShapeNode>
</data>
</node>
<node id="n10">
<data key="d4" xml:space="preserve"/>
<data key="d5"/>
<data key="d6">
<y:UMLNoteNode>
<y:Geometry height="80.0" width="259.0" x="887.5" y="402.0"/>
<y:Fill color="#FFCC00" transparent="false"/>
<y:BorderStyle color="#000000" type="line" width="1.0"/>
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="53.0323429107666" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="247.13372802734375" x="5.933135986328125" xml:space="preserve" y="13.4838285446167">Technically the interim model/symbol table
and the resolved model can be the same
data structure.<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
</y:UMLNoteNode>
</data>
</node>
<edge id="e0" source="n3" target="n6">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e1" source="n0" target="n6">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="7.5" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="517.0" y="350.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e2" source="n6" target="n1">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e3" source="n1" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e4" source="n7" target="n5">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e5" source="n4" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="807.0" y="211.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e6" source="n2" target="n7">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="813.0" y="145.0"/>
</y:Path>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e7" source="n5" target="n9">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e8" source="n9" target="n8">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="line" width="1.0"/>
<y:Arrows source="none" target="standard"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e9" source="n10" target="n1">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="784.0" y="442.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e10" source="n10" target="n5">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
<edge id="e11" source="n10" target="n8">
<data key="d9"/>
<data key="d10">
<y:PolyLineEdge>
<y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
<y:Point x="1208.0" y="442.0"/>
</y:Path>
<y:LineStyle color="#000000" type="dashed" width="1.0"/>
<y:Arrows source="none" target="none"/>
<y:BendStyle smoothed="false"/>
</y:PolyLineEdge>
</data>
</edge>
</graph>
<data key="d7">
<y:Resources/>
</data>
</graphml>
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" width="1003" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" height="382" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
<!--Generated by ySVG 2.5-->
<defs id="genericDefs"/>
<g>
<defs id="defs1">
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath1">
<path d="M0 0 L1003 0 L1003 382 L0 382 L0 0 Z"/>
</clipPath>
<clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
<path d="M351 115 L1354 115 L1354 497 L351 497 L351 115 Z"/>
</clipPath>
</defs>
<g fill="white" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="translate(-351,-115)" stroke="white">
<rect x="351" width="1003" height="382" y="115" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="366" width="95" height="30" y="335" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="366" width="95" height="30" y="335" clip-path="url(#clipPath2)"/>
<text x="375.7777" xml:space="preserve" y="354.656" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Declaration n</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="644" width="124" height="30" y="269" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="644" width="124" height="30" y="269" clip-path="url(#clipPath2)"/>
<text x="663.5857" xml:space="preserve" y="280.484" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Interim Model/</text>
<text x="668.2838" xml:space="preserve" y="296.8281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Symbol Table</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="644" width="118" height="30" y="130" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="644" width="118" height="30" y="130" clip-path="url(#clipPath2)"/>
<text x="658.9717" xml:space="preserve" y="149.656" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Configuration 1</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="366" width="95" height="30" y="269" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="366" width="95" height="30" y="269" clip-path="url(#clipPath2)"/>
<text x="376.0537" xml:space="preserve" y="288.656" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Declaration 1</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="644" width="118" height="30" y="196" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="644" width="118" height="30" y="196" clip-path="url(#clipPath2)"/>
<text x="656.7937" xml:space="preserve" y="215.656" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Configuration m</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="955" width="124" height="30" y="269" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="955" width="124" height="30" y="269" clip-path="url(#clipPath2)"/>
<text x="974.5857" xml:space="preserve" y="280.484" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Interim Model/</text>
<text x="979.2838" xml:space="preserve" y="296.8281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Symbol Table</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<circle r="15" clip-path="url(#clipPath2)" cx="549" cy="284" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<circle fill="none" r="15" clip-path="url(#clipPath2)" cx="549" cy="284"/>
<text x="474.8035" xml:space="preserve" y="216.1399" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Declaration Interim Model</text>
<text x="498.9597" xml:space="preserve" y="232.484" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">and Symbol Table</text>
<text x="505.5237" xml:space="preserve" y="248.8281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Creation Visitor</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<circle r="15" clip-path="url(#clipPath2)" cx="861.5" cy="284" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<circle fill="none" r="15" clip-path="url(#clipPath2)" cx="861.5" cy="284"/>
<text x="780.7214" xml:space="preserve" y="325.484" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Configuration Interim Model</text>
<text x="811.4597" xml:space="preserve" y="341.8281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">and Smybol Table</text>
<text x="818.0237" xml:space="preserve" y="358.1722" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Creation Visitor</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<rect x="1221" width="118" height="30" y="269" clip-path="url(#clipPath2)" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<rect fill="none" x="1221" width="118" height="30" y="269" clip-path="url(#clipPath2)"/>
<text x="1235.4557" xml:space="preserve" y="288.656" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Resolved Model</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<circle r="15" clip-path="url(#clipPath2)" cx="1150" cy="284" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<circle fill="none" r="15" clip-path="url(#clipPath2)" cx="1150" cy="284"/>
<text x="1105.0477" xml:space="preserve" y="331.484" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Compute Result</text>
<text x="1132.3059" xml:space="preserve" y="347.8281" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Model</text>
</g>
<g fill="rgb(255,204,0)" text-rendering="geometricPrecision" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke="rgb(255,204,0)">
<path d="M887.5 402 L1131.5 402 L1131.5 417 L1146.5 417 L1146.5 482 L887.5 482 Z" stroke="none" clip-path="url(#clipPath2)"/>
<path fill="white" d="M1131.5 402 L1131.5 417 L1146.5 417 Z" clip-path="url(#clipPath2)" fill-rule="evenodd" stroke="none"/>
</g>
<g text-rendering="geometricPrecision" stroke-miterlimit="1.45" shape-rendering="geometricPrecision" transform="matrix(1,0,0,1,-351,-115)" stroke-linecap="butt">
<path fill="none" d="M887.5 402 L1131.5 402 L1131.5 417 L1146.5 417 L1146.5 482 L887.5 482 Z" clip-path="url(#clipPath2)"/>
<path fill="none" d="M1131.5 402 L1131.5 417 L1146.5 417 Z" clip-path="url(#clipPath2)" fill-rule="evenodd"/>
<text x="895.4331" xml:space="preserve" y="430.3119" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">Technically the interim model/symbol table</text>
<text x="902.6392" xml:space="preserve" y="446.656" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">and the resolved model can be the same</text>
<text x="975.4017" xml:space="preserve" y="463.0002" clip-path="url(#clipPath2)" font-family="sans-serif" stroke="none">data structure.</text>
<path fill="none" d="M461 284 L526 284" clip-path="url(#clipPath2)"/>
<path d="M534 284 L522 279 L525 284 L522 289 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M460.9844 350 L517 350 L538.9657 304.6957" clip-path="url(#clipPath2)"/>
<path d="M542.4559 297.4972 L532.7215 306.1136 L538.5294 305.5955 L541.7197 310.4763 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M564 284 L636 284" clip-path="url(#clipPath2)"/>
<path d="M644 284 L632 279 L635 284 L632 289 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M768 284 L838.5 284" clip-path="url(#clipPath2)"/>
<path d="M846.5 284 L834.5 279 L837.5 284 L834.5 289 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M762 211 L807 211 L847.7404 265.5698" clip-path="url(#clipPath2)"/>
<path d="M852.5264 271.9803 L849.354 259.3733 L847.1422 264.7685 L841.3409 265.3557 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M762 145 L813 145 L853.9228 262.284" clip-path="url(#clipPath2)"/>
<path d="M856.5583 269.8374 L857.3259 256.86 L853.5933 261.3398 L847.8842 260.1545 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M876.5 284 L947 284" clip-path="url(#clipPath2)"/>
<path d="M955 284 L943 279 L946 284 L943 289 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M1079 284 L1127 284" clip-path="url(#clipPath2)"/>
<path d="M1135 284 L1123 279 L1126 284 L1123 289 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" d="M1165 284 L1213 284" clip-path="url(#clipPath2)"/>
<path d="M1221 284 L1209 279 L1212 284 L1209 289 Z" clip-path="url(#clipPath2)" stroke="none"/>
<path fill="none" stroke-dasharray="6,2" d="M887.5018 442 L784 442 L713.4051 299" clip-path="url(#clipPath2)"/>
<path fill="none" stroke-dasharray="6,2" d="M1017 401.9985 L1017 299" clip-path="url(#clipPath2)"/>
<path fill="none" stroke-dasharray="6,2" d="M1146.4939 442 L1208 442 L1273.1646 299" clip-path="url(#clipPath2)"/>
</g>
</g>
</svg>
# Template Language
The template language allows to define file templates based on a declaration
model. It supports two template types:
- File templates which will generate files
- Text templates which allow to produce text and allow to subdivide the file
generation
## Basic File Structure
Each template file starts with a preamble specifying the declaration model to
use.
```
for DeclarationModelName
```
After that any number of file and sub templates can be specified.
## File Template
A file template starts with the keyword *file*.
```
file "filename expression" : "body expression"
file "filename expression" when exists(exampleGroup) : "body expression"
```
The first example produces a file regardless of the content of the configuration
file. The second example requests that an element *exampleGroup* exists.
## Text Template
A text template starts with the keyword *template* followed by a list of
optional parameters and a template body.
```
template basic "body expression"
template withParameters (ParameterGroup group) "body expression"
```
## Expressions
File names, conditionals and template bodys are expressions in the template
language. In text and file templates the expression must be a text string for
file names and bodys and a boolean for conditionals.
The language supports richstrings starting and ending with '''.
Rich strings can be interupted with « » and between these french quotes, other
expressions and commands can be inserted.
```
'''«for group.parameters join "," it.name»'''
```
## List of Expression Elements
- *, /, % *multiply, divide, modulo*
- +, - *add, subtract*
- if boolean text-expression (then text-expression)?
- for variable (join string)? text-expression
- switch variable cases end
- cases
- case case-text-expression text-expression *case for expression*
- is type-name text-expression *type case expression*
- and, or *logical ops*
- ==, >, <, >=, <=, != *compare ops*
- ! (not)
- use template-name (parameters) *use another template*
- exists(variable), isEmpty(list), size(list) *built-in functions*
- it *referencing the loop variable*
## How to get
- « and » in the editor?
- CTRL-< and SHIFT-CTRL-< (lower left corner on the keyboard)
File moved
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment