Since the node classes are stored and copied as std::shared_ptr, a given class
instance can actually be shared by two different expressions. Hence, in order
to prevent weird bugs, it’s necessary to make these classes immutable.
This commit deals with the easy cases.
The remaining (and more complex) ones are:
— Variable
— Array
— Include
— IncludePath
In particular, remove the const keyword before arguments passed-by-value,
because otherwise they can't be moved (since they are immutable).
Also add a few missing calls to std::move(), and remove some calls to
std::move() when they are useless (on class enums, which are fundamental
types.)
The idea is to split the expression rule into smaller subrules, hierarchically
organized according to the operator precedence (Bison still does part of the
job of dealing with precedence).
This introduces a shift/reduce compilation warning in the macro processor because at expr COLON expr . COLON expr the parser doesn’t know whether to shift or reduce
Before this commit, a dynare call such as
```
dynare <<mod file>> -Db=“A” -Da=@{b}
```
would not expand the value of `b` in `a` whereas
```
dynare <<mod file>> -Da=“A” -Db=@{a}
```
would expand the value of `a` into `b` because the arguments were stored in a map which printed the `@#define` statements in the .mod file in alphabetic order.
In particular, no need to put both upper and lower case letters in the
patterns, since the lexer is case-insensitive.
The only simplification that we do not perform is removing the quoting of
single quotes (i.e. replacing \' by '), since it confuses the C++ mode of
Emacs.
This feature is ill-designed and no longer needed by the GUI. And is not very
useful: it is not possible to interact with the preprocessor without using the
filesystem, since the preprocessor creates many files anyways.
If we really need to reimplement such a feature, it should rather be redesigned
by reading the modfile from standard input (cin). That could be triggered by
using "-" as the filename argument (as is already done by several standard Unix
utilities).
Due to a limitation of the current implementation, this breaks syntaxes like
[ (i,j) ] (but not [ (2,j) ]; the problem only occurs when an array is
constructed by specifying as first element a tuple whose first element is a
variable name). Solving this problem requires an overhaul of the
macro-processor, with construction of ASTs at parsing time, and evaluation
later on (instead of doing on-the-fly evaluation).
Ref #5
- == and != have now lower priority than <= < >= >, for consistency with the
Dynare modelling language (and incidentally C and C++, but not Julia).
- ^ has now higher priority and no associativity, for consistency with the
Dynare modelling language (and usual arithmetic notation).
- & has now higher priority than |, and both have lower priority than + and -,
but higher than inequality comparators. This is not the same as C and C++ (in
which & and | are just above && and ||), but this allows for expressions such
as "a|b == c" to have their most natural semantics (i.e. this will compare
the union of a and b with c; the C/C++ priority level would have resulted in
a type error).
Ref #5.
- use std::unique_ptr for MacroDriver::lexer
- use std::shared_ptr for MacroValue objects constructed by the parser
This is made possible using Bison 3.0 variant value type.
Using non-pointer type is not possible since MacroValue is polymorphic.
Using std::unique_ptr is not possible since the value type must be
copyable (see
https://lists.gnu.org/archive/html/bug-bison/2015-03/msg00004.html).
Define a new type MacroValuePtr == shared_ptr<const MacroValue> for code
clarity.
Use the following convention for shared_ptr arguments to functions:
+ if pass-by-value, means that the callee acquires ownership
+ if pass-by-const-reference, the callee does not acquire ownership
- naked pointers are still used for tracking the filename in Bison's location
type, since we don't have control over that
Also, by the way:
- arrays can now contain elements of any type
- simplify MacroDriver::loop_stack using std::tuple
- toArray() method now fails on function objects
- no need to use const qualifiers, since all MacroValue objects are immutable
- use an exception for detecting division by zero