From 08d8110e7b4e0ef7685bd4ffa4568ee397b2311b Mon Sep 17 00:00:00 2001 From: Henrik Tidefelt Date: Sun, 2 Feb 2020 23:06:09 +0100 Subject: [PATCH 1/5] Restrict 'constant expression' to ensure possibility to evaluate at translation time --- RationaleMCP/0031/differences.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/RationaleMCP/0031/differences.md b/RationaleMCP/0031/differences.md index 2a0f91a4e..bffb2c6d4 100644 --- a/RationaleMCP/0031/differences.md +++ b/RationaleMCP/0031/differences.md @@ -21,5 +21,31 @@ Flat Modelica is designed to avoid such implicit evaluation of parameters, and t In Modelica a separate issue is that `if`-equations may contain connect and similar primitives that cannot easily be counted; but they are gone in Flat Modelica. +## Constant expressions +In Flat Modelica, a _constant expression_ is more restricted than in full Modelica, by adding the following requirement: +- Functions called in a constant expression must be _pure constant_, defined below. + +A _pure constant_ function is informally characterized by the following properties: +- Only the output values of a function call influence the simulation result (considered free of side effects for purposes of program analysis). +- The function itself only contributes with `constant` variability to expressions where it is called. That is, when the function is called with constant arguments, the result is assumed to be the same when evaluated at translation time and when evaluated at any point during simulation. +- It is straight-forward to evaluate a call to a _pure constant_ function at translation time. + +A `pure` function that isn't pure constant contributes with `parameter` variability to the expressions where it is called. Similarly, an `impure` function also contributes with `parameter` variability. Hence, a function call expression with constant arguments is a parameter expression unless the callee is pure constant. + +By requiring functions called in a constant expression to be _pure constant_, it is ensured that a constant expression can always be evaluated to a value at translation time. A function call that is not a constant expression must not be evaluated before simulation starts. + +It is currently not possible to declare a function as _pure constant_. For now, there is just the following implicit formalization (in agreement with the informal characterization above): +- The built-in functions are _pure constant_. +- A `pure` function is _pure constant_ unless: + * It has `external` implementation. + * It contains a `pure(…)` expression. + * It calls another function that isn't _pure constant_. +- An `impure` function is not _pure constant_. + +### Reason for change +By excluding `external` functions, translation time evaluation of constant expressions is greatly simplified. By excluding `impure` functions and `pure(…)` expressions, it is ensured that it doesn't matter whether evaluation happens at translation time or at simulation (initialization) time. + +Forbidding translation time evaluation of function calls in non-constant expressions generalizes the current Modelica rule for `impure` functions and makes it clear that this is not allowed regardless whether this is seen as an optimization or not. (The current Modelica specification only has a non-normative paragraph saying that performing optimizations is not allowd.) + ## Array dimensions with parameter variability In Flat Modelica, an array dimension is allowed to have `parameter` variability, that is, the dimension isn't known until after solving the initialization problem in the simulation. _TO BE ELABORATED…_ From 6896de9db0a32a40679523e08be4eaa022d7b901 Mon Sep 17 00:00:00 2001 From: Henrik Tidefelt Date: Mon, 3 Feb 2020 08:13:48 +0100 Subject: [PATCH 2/5] Handle impure function calls in parameter binding equations by means of variability Excluding impure function calls from parameter expressions is a similar simplification as requiring functions in constant expressions to be pure constant. To me, the two changes belong together and are therefore made part of the same PR. --- RationaleMCP/0031/differences.md | 33 +++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/RationaleMCP/0031/differences.md b/RationaleMCP/0031/differences.md index bffb2c6d4..71014af04 100644 --- a/RationaleMCP/0031/differences.md +++ b/RationaleMCP/0031/differences.md @@ -21,7 +21,9 @@ Flat Modelica is designed to avoid such implicit evaluation of parameters, and t In Modelica a separate issue is that `if`-equations may contain connect and similar primitives that cannot easily be counted; but they are gone in Flat Modelica. -## Constant expressions +## Variability of expressions + +### Constant expressions In Flat Modelica, a _constant expression_ is more restricted than in full Modelica, by adding the following requirement: - Functions called in a constant expression must be _pure constant_, defined below. @@ -30,8 +32,6 @@ A _pure constant_ function is informally characterized by the following properti - The function itself only contributes with `constant` variability to expressions where it is called. That is, when the function is called with constant arguments, the result is assumed to be the same when evaluated at translation time and when evaluated at any point during simulation. - It is straight-forward to evaluate a call to a _pure constant_ function at translation time. -A `pure` function that isn't pure constant contributes with `parameter` variability to the expressions where it is called. Similarly, an `impure` function also contributes with `parameter` variability. Hence, a function call expression with constant arguments is a parameter expression unless the callee is pure constant. - By requiring functions called in a constant expression to be _pure constant_, it is ensured that a constant expression can always be evaluated to a value at translation time. A function call that is not a constant expression must not be evaluated before simulation starts. It is currently not possible to declare a function as _pure constant_. For now, there is just the following implicit formalization (in agreement with the informal characterization above): @@ -42,10 +42,37 @@ It is currently not possible to declare a function as _pure constant_. For now, * It calls another function that isn't _pure constant_. - An `impure` function is not _pure constant_. +### Parameter expressions + +In Flat Modelica, a _parameter expression_ is more restricted than in full Modelica, by adding the following requirement: +- Functions called in a parameter expression must be pure. + +As a consequence, the full Modelica syntactic sugar of using an impure function in the binding equation of a parameter is not allowed in Flat Modelica. Such initialization has to be expressed explicitly using an initial equation. Hence, the rules of variability hold without exception also in the case of components declared as parameter. + +### Discrete-time expressions + +In Flat Modelica, a _discrete expression_ is more restricted than in full Modelica, by adding the following requirement (with emphasis on the difference compared to full Modelica): +- Function calls where all input arguments of the function are discrete-time expressions _are discrete-time provided that the callee is pure_. + +The rule about when-clause bodies, initial equations, and initial algorithms still holds without exception, so purity of functions doesn't matter there. + +### Continuous-time expressions + +Note that a function call expression where the callee is impure is a non-discrete-time expression, regardless of the variability of the argument expressions. + ### Reason for change By excluding `external` functions, translation time evaluation of constant expressions is greatly simplified. By excluding `impure` functions and `pure(…)` expressions, it is ensured that it doesn't matter whether evaluation happens at translation time or at simulation (initialization) time. Forbidding translation time evaluation of function calls in non-constant expressions generalizes the current Modelica rule for `impure` functions and makes it clear that this is not allowed regardless whether this is seen as an optimization or not. (The current Modelica specification only has a non-normative paragraph saying that performing optimizations is not allowd.) +The shifts in variability of function calls could be summarized as _the variability of a function call expression is the highest variability among the argument expressions and the variability of the called function itself_, where the _variability of a function_ is defined by the following table: +| Function classification | Function variability | +| --- | --- | +| pure constant | constant | +| pure, otherwise | parameter | +| impure | continuous-time | + +This covers what one can currently express in full Modelica. In the future, one might also introduce _pure discrete_ functions that don't have side effects, but that must be re-evaluated at events, even if the arguments are constant. + ## Array dimensions with parameter variability In Flat Modelica, an array dimension is allowed to have `parameter` variability, that is, the dimension isn't known until after solving the initialization problem in the simulation. _TO BE ELABORATED…_ From 38d9c940792cecc5245980bdb290b99295634b1b Mon Sep 17 00:00:00 2001 From: Henrik Tidefelt Date: Mon, 3 Feb 2020 08:18:51 +0100 Subject: [PATCH 3/5] Fix markdown table syntax --- RationaleMCP/0031/differences.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RationaleMCP/0031/differences.md b/RationaleMCP/0031/differences.md index 71014af04..54eff5429 100644 --- a/RationaleMCP/0031/differences.md +++ b/RationaleMCP/0031/differences.md @@ -66,6 +66,7 @@ By excluding `external` functions, translation time evaluation of constant expre Forbidding translation time evaluation of function calls in non-constant expressions generalizes the current Modelica rule for `impure` functions and makes it clear that this is not allowed regardless whether this is seen as an optimization or not. (The current Modelica specification only has a non-normative paragraph saying that performing optimizations is not allowd.) The shifts in variability of function calls could be summarized as _the variability of a function call expression is the highest variability among the argument expressions and the variability of the called function itself_, where the _variability of a function_ is defined by the following table: + | Function classification | Function variability | | --- | --- | | pure constant | constant | From 7dedd784b333cb281f892e49c05ac244d770e1d4 Mon Sep 17 00:00:00 2001 From: Henrik Tidefelt Date: Fri, 14 Feb 2020 00:30:56 +0100 Subject: [PATCH 4/5] Change 'pure constant' to be an explicitly declared property --- RationaleMCP/0031/differences.md | 41 ++++++++++++++++++++------------ RationaleMCP/0031/grammar.md | 2 +- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/RationaleMCP/0031/differences.md b/RationaleMCP/0031/differences.md index 54eff5429..8fdf7a44a 100644 --- a/RationaleMCP/0031/differences.md +++ b/RationaleMCP/0031/differences.md @@ -21,26 +21,37 @@ Flat Modelica is designed to avoid such implicit evaluation of parameters, and t In Modelica a separate issue is that `if`-equations may contain connect and similar primitives that cannot easily be counted; but they are gone in Flat Modelica. -## Variability of expressions - -### Constant expressions -In Flat Modelica, a _constant expression_ is more restricted than in full Modelica, by adding the following requirement: -- Functions called in a constant expression must be _pure constant_, defined below. +# Pure Modelica functions -A _pure constant_ function is informally characterized by the following properties: +In addition to full Modelica's classification into _pure_ and _impure_, Flat Modelica adds the concept of a `pure constant` function, informally characterized by the following properties: - Only the output values of a function call influence the simulation result (considered free of side effects for purposes of program analysis). - The function itself only contributes with `constant` variability to expressions where it is called. That is, when the function is called with constant arguments, the result is assumed to be the same when evaluated at translation time and when evaluated at any point during simulation. -- It is straight-forward to evaluate a call to a _pure constant_ function at translation time. +- It is straight-forward to evaluate a call to a `pure constant` function at translation time. + +The built-in functions are `pure constant`, and a user-defined pure `function` or `operator function` can be declared as `pure constant` by adding `constant` in the class prefix right after `pure`. For example: +``` +pure constant function add1 +``` + +The implementation of a `pure constant` functions is more restricted than that of pure functions in general: +- It may not have `external` implementation. +- It may not contain any `pure(…)` expression. +- All called functions must be `pure constant`. + +The rule for `pure(impureFunctionCall(...))` needs to be rephrased to not say _allows calling impure functions in any pure context_, since the body of a `pure constant` function is also a pure context. Perhaps something like this instead: +> meaning that the present occurrence of `impureFunctionCall` should be considered pure (not `pure constant`) for purposes of purity analysis. -By requiring functions called in a constant expression to be _pure constant_, it is ensured that a constant expression can always be evaluated to a value at translation time. A function call that is not a constant expression must not be evaluated before simulation starts. +### Reason for change + +This change was made to support the [changed definitions of _constant expression_](#Constant-expressions). + +## Variability of expressions + +### Constant expressions +In Flat Modelica, a _constant expression_ is more restricted than in full Modelica, by adding the following requirement: +- Functions called in a constant expression must be `pure constant`. -It is currently not possible to declare a function as _pure constant_. For now, there is just the following implicit formalization (in agreement with the informal characterization above): -- The built-in functions are _pure constant_. -- A `pure` function is _pure constant_ unless: - * It has `external` implementation. - * It contains a `pure(…)` expression. - * It calls another function that isn't _pure constant_. -- An `impure` function is not _pure constant_. +By requiring functions called in a constant expression to be `pure constant`, it is ensured that a constant expression can always be evaluated to a value at translation time. A function call that is not a constant expression must not be evaluated before simulation starts. ### Parameter expressions diff --git a/RationaleMCP/0031/grammar.md b/RationaleMCP/0031/grammar.md index 273c14b7a..2a8c2aee1 100644 --- a/RationaleMCP/0031/grammar.md +++ b/RationaleMCP/0031/grammar.md @@ -90,7 +90,7 @@ end _F; >   (\ >   | **type**\ >   | ~~**operator**?~~ **record**\ ->   | ( **pure** | **impure** )? ~~**operator**?~~ **function**\ +>   | ( ( **pure** **constant**? ) | **impure** )? ~~**operator**?~~ **function**\ >   ~~| **class**~~\ >   ~~| **model**~~\ >   ~~| **block**~~\ From f44cf86bf2b80350cc6033660a8082e8b49a229d Mon Sep 17 00:00:00 2001 From: Henrik Tidefelt Date: Fri, 14 Feb 2020 00:32:31 +0100 Subject: [PATCH 5/5] Withdraw changes to definitions of discrete-time and continuous-time expressions According to poll in today's web meeting. --- RationaleMCP/0031/differences.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/RationaleMCP/0031/differences.md b/RationaleMCP/0031/differences.md index 8fdf7a44a..6444e036d 100644 --- a/RationaleMCP/0031/differences.md +++ b/RationaleMCP/0031/differences.md @@ -60,22 +60,13 @@ In Flat Modelica, a _parameter expression_ is more restricted than in full Model As a consequence, the full Modelica syntactic sugar of using an impure function in the binding equation of a parameter is not allowed in Flat Modelica. Such initialization has to be expressed explicitly using an initial equation. Hence, the rules of variability hold without exception also in the case of components declared as parameter. -### Discrete-time expressions - -In Flat Modelica, a _discrete expression_ is more restricted than in full Modelica, by adding the following requirement (with emphasis on the difference compared to full Modelica): -- Function calls where all input arguments of the function are discrete-time expressions _are discrete-time provided that the callee is pure_. - -The rule about when-clause bodies, initial equations, and initial algorithms still holds without exception, so purity of functions doesn't matter there. - -### Continuous-time expressions - -Note that a function call expression where the callee is impure is a non-discrete-time expression, regardless of the variability of the argument expressions. - ### Reason for change By excluding `external` functions, translation time evaluation of constant expressions is greatly simplified. By excluding `impure` functions and `pure(…)` expressions, it is ensured that it doesn't matter whether evaluation happens at translation time or at simulation (initialization) time. Forbidding translation time evaluation of function calls in non-constant expressions generalizes the current Modelica rule for `impure` functions and makes it clear that this is not allowed regardless whether this is seen as an optimization or not. (The current Modelica specification only has a non-normative paragraph saying that performing optimizations is not allowd.) +The change regarding parameter expressions could be extended to discrete-time expressions as well without loss of expressiveness due to the existing restrictions on where an impure function may be called. This could also be expressed more generally by saying that a function call expression where the callee is impure is a non-discrete-time expression. However, it was decided to not include this in the formal description of differences between Modelica and Flat Modelica in order to avoid describing changes that only clarify things without actually making a difference to semantics. + The shifts in variability of function calls could be summarized as _the variability of a function call expression is the highest variability among the argument expressions and the variability of the called function itself_, where the _variability of a function_ is defined by the following table: | Function classification | Function variability | @@ -84,6 +75,8 @@ The shifts in variability of function calls could be summarized as _the variabil | pure, otherwise | parameter | | impure | continuous-time | +Seen this way, the rules about which functions may be called in the body of a function definition ends up being another case of variability enforcement. + This covers what one can currently express in full Modelica. In the future, one might also introduce _pure discrete_ functions that don't have side effects, but that must be re-evaluated at events, even if the arguments are constant. ## Array dimensions with parameter variability