https://svn.lrde.epita.fr/svn/xrm/trunk
Index: ChangeLog
from SIGOURE Benoit <sigoure.benoit(a)lrde.epita.fr>
Major changes: new way of handling arrays.
The whole way of handling arrays in XRM has been changed. The former
way of doing it was somewhat simplistic and quickly reached its
limit. We used to have: x[1][2] represented as ArrayAccess(x, [1, 2]),
we now have: ArrayAccess(ArrayAccess(x, [1]), [2]) which means that
the expression is parenthesized as (x[1])[2]. Pretty much like in
Java/C/C++... So far it did not make sense to have this approach
since one cannot access the intermediate dimensions anyway (eg: if x
is a 2D array, say: x[3][3], it doesn't make sense, in XRM, to access
x[2] for instance).
We are moving to an approach which is more Java/C-like because we
want to be able to write things such as: x[1..3,5,7..9][1,3,5][2..6]
which is suddenly more complex than what we used to support before.
This revision provides several new features among this new way of
writing array accesses:
It is now possible to declare an array using ranges, eg:
x[1..3,7][2..4] will declare a 2D array defined only for certain
ranges (it's somewhat like sparse arrays)
It will soon be possible to write equality tests such as:
x[1..3][2,3]=0 to check whether x[1][2]=0 & x[1][3]=0 & x[2][2]=0
etc.
Other new operators added in the grammar (but not yet implemented):
x[1..3][2,3]?=0 is there at least one of the elements
that's equal to 0? x[1..3][2,3]?!=0 same but at least one not equal.
Array declarations have been optimized since the declarations are now
directly generated instead of creating a meta-for loop that will be
later unrolled to generate them. This also introduces a problem (see
the TODO).
* src/lib/xrm/pp/xrm-expression.str: Add boxing for future operators
(not yet implemented) "?=" and "?!=".
* src/syn/xrm/XRM-Expression.sdf: Ditto.
* src/lib/xrm/pp/xrm-arrays.str: Change boxing of arrays according to
the new grammar for arrays.
* src/lib/prism/pp/prism-expression.str: Add `KW' boxes for keywords.
* src/str/flatten-array-access.str: Adapt to the new arrays.
* src/str/check-meta-vars.str: Take the static const and formulas
into account to avoid name clashes.
* src/str/array-decl-desugar.str: Brand new code from scratch.
* src/str/xrm-to-prism.str: Improve the pipeline by reducing the
traversals and performing sanity checks earlier on. Move
collect-* stuff to...
* src/str/collect-static-const-decl.str: ... here.
* src/str/collect-static-const-decl.meta: New.
* src/str/prism-desugar.str: Fix the expansion of static const values
and formulas in constant propagation.
* src/str/eval-meta-code.str: Remove unnecessary checks on meta-vars
(already performed earlier in the pipeline).
* src/str/xrm-front.str: Remove useless FIXME.
* src/str/desugar-array-access.str: New. Hot stuff here.
* src/syn/xrm/XRM-Arrays.sdf: New grammar for arrays in XRM.
* src/syn/prism/PRISM-Expression.sdf: Remove a useless cons.
* tests/xrm/exists-eq.xpm: New.
* tests/xrm/for-loop-using-const-int.xpm: New.
* tests/test-xrm-front.sh.in: Change a message echo'ed.
* tests/test-parse-xrm.sh.in: Fix test counting.
* tests/test-parse-prism.sh.in: Ditto.
* TODO: A new problem arose :(.
TODO | 25 ++
src/lib/prism/pp/prism-expression.str | 10 -
src/lib/xrm/pp/xrm-arrays.str | 17 -
src/lib/xrm/pp/xrm-expression.str | 12 +
src/str/array-decl-desugar.str | 298 +++++++++++++++++++--------------
src/str/check-meta-vars.str | 18 +
src/str/collect-static-const-decl.meta | 1
src/str/collect-static-const-decl.str | 77 ++++++++
src/str/desugar-array-access.str | 176 +++++++++++++++++++
src/str/eval-meta-code.str | 18 +
src/str/flatten-array-access.str | 54 ++---
src/str/prism-desugar.str | 6
src/str/xrm-front.str | 1
src/str/xrm-to-prism.str | 55 ++----
src/syn/prism/PRISM-Expression.sdf | 2
src/syn/xrm/XRM-Arrays.sdf | 26 +-
src/syn/xrm/XRM-Expression.sdf | 32 +++
tests/test-parse-prism.sh.in | 3
tests/test-parse-xrm.sh.in | 3
tests/test-xrm-front.sh.in | 2
tests/xrm/exists-eq.xpm | 12 +
tests/xrm/for-loop-using-const-int.xpm | 8
22 files changed, 630 insertions(+), 226 deletions(-)
Index: src/lib/xrm/pp/xrm-expression.str
--- src/lib/xrm/pp/xrm-expression.str (revision 45)
+++ src/lib/xrm/pp/xrm-expression.str (working copy)
@@ -9,7 +9,15 @@
prism-to-box:
LeftShift(lhs, rhs) -> H hs=1 [~lhs MATH["<<"] ~rhs]
+ prism-to-box:
+ ExistsEq(array-access, rhs)
+ -> H hs=1 [~array-access MATH["?="] ~rhs]
+
+ prism-to-box:
+ ExistsNotEq(array-access, rhs)
+ -> H hs=1 [~array-access MATH["?!="] ~rhs]
+
prism-to-box: // NOTE: we use the old builtin-call style
- Rand(args) // func(rand, ...) is just uggly.
- -> box |[ H hs=0 [ "rand" "(" H hs=1 [ ~args-imploded ]
")" ] ]|
+ Rand(args) // because func(rand, ...) is just uggly.
+ -> box |[ H hs=0 [ KW["rand"] "(" H hs=1 [ ~args-imploded ]
")" ] ]|
where <implode-list(|",")> args => args-imploded
Index: src/lib/xrm/pp/xrm-arrays.str
--- src/lib/xrm/pp/xrm-arrays.str (revision 45)
+++ src/lib/xrm/pp/xrm-arrays.str (working copy)
@@ -2,14 +2,15 @@
rules
- // Identifier ArraySubscript+ -> ArrayAccess
+ // Identifier "[" {Range ","}+ "]" -> ArrayAccess
+ // ArrayAccess "[" {Range ","}+ "]" -> ArrayAccess
prism-to-box:
- ArrayAccess(idf, subscripts) -> H hs=0 [ ~idf ~*subscripts-impl ]
- where
- <mapconcat(\ x -> [S("["), x, S("]")] \)> subscripts
=> subscripts-impl
+ ArrayAccess(idf, subscripts)
+ -> H hs=0 [ ~idf "[" ~subscripts-impl "]" ]
+ where <implode-list(|",")> subscripts => subscripts-impl
- // Identifier ArraySubscript+ "'" -> ArrayAccessPrime
+ // ArrayAccess "[" {Range ","}+ "]" "'"
-> ArrayAccessPrime
prism-to-box:
- ArrayAccessPrime(idf, subscripts) -> H hs=0 [ ~idf ~*subscripts-impl
"'" ]
- where
- <mapconcat(\ x -> [S("["), x, S("]")] \)> subscripts
=> subscripts-impl
+ ArrayAccessPrime(idf, subscripts)
+ -> H hs=0 [ ~idf "[" ~subscripts-impl "]" "'" ]
+ where <implode-list(|",")> subscripts => subscripts-impl
Index: src/lib/prism/pp/prism-expression.str
--- src/lib/prism/pp/prism-expression.str (revision 45)
+++ src/lib/prism/pp/prism-expression.str (working copy)
@@ -72,31 +72,31 @@
prism-to-box:
Min(args)
- -> box |[ H hs=0 [ "func" "(" H hs=1 [ H hs=0["min"
","]
+ -> box |[ H hs=0 [ KW["func"] "(" H hs=1 [ H
hs=0[KW["min"] ","]
~args-imploded ] ")" ] ]|
where <implode-list(|",")> args => args-imploded
prism-to-box:
Max(args)
- -> box |[ H hs=0 [ "func" "(" H hs=1 [ H hs=0["max"
","]
+ -> box |[ H hs=0 [ KW["func"] "(" H hs=1 [ H
hs=0[KW["max"] ","]
~args-imploded ] ")" ] ]|
where <implode-list(|",")> args => args-imploded
prism-to-box:
Floor(args)
- -> box |[ H hs=0 [ "func" "(" H hs=1 [ H
hs=0["floor" ","]
+ -> box |[ H hs=0 [ KW["func"] "(" H hs=1 [ H
hs=0[KW["floor"] ","]
~args-imploded ] ")" ] ]|
where <implode-list(|",")> args => args-imploded
prism-to-box:
Ceil(args)
- -> box |[ H hs=0 [ "func" "(" H hs=1 [ H hs=0["ceil"
","]
+ -> box |[ H hs=0 [ KW["func"] "(" H hs=1 [ H
hs=0[KW["ceil"] ","]
~args-imploded ] ")" ] ]|
where <implode-list(|",")> args => args-imploded
prism-to-box:
Call(idf, args)
- -> box |[ H hs=0 [ "func" "(" H hs=1 [ H hs=0[~idf
","]
+ -> box |[ H hs=0 [ KW["func"] "(" H hs=1 [ H hs=0[~idf
","]
~args-imploded ] ")" ] ]|
where <implode-list(|",")> args => args-imploded
Index: src/str/flatten-array-access.str
--- src/str/flatten-array-access.str (revision 45)
+++ src/str/flatten-array-access.str (working copy)
@@ -6,43 +6,40 @@
** Transform an array access into an identifier (eg: x[i] -> x_i)
*/
flatten-array-access:
- ArrayAccess(Identifier(idf), access-list) -> Identifier(idf')
- where flatten-access-list(|idf, access-list) => idf'
+ ArrayAccess(Identifier(idf), [subscript]) -> Identifier(idf')
+ where flatten-access-list(|idf, subscript) => idf'
flatten-array-access:
- ArrayAccessPrime(Identifier(idf), access-list) -> IdentifierPrime(idf')
- where flatten-access-list(|idf, access-list) => idf'
+ ArrayAccessPrime(Identifier(idf), [subscript]) -> IdentifierPrime(idf')
+ where flatten-access-list(|idf, subscript) => idf'
strategies
/**
** @internal
- ** Transform an access list (in array accesses) into a flat variable name
- ** eg: flatten-access-list(|"x", [Int("1"), Int("2")])
-> "x_1_2"
- ** NOTE: The access list can contain expressions as long as it possible to
- ** evaluate them down to a constant positive Int() value.
+ ** Transform simple array access into a flat variable name.
+ ** eg: flatten-array-access(|"x", Int("1")) -> "x_1"
+ ** NOTE: The subscript can contain expressions as long as it possible to
+ ** evaluate it down to a constant positive Int() value.
**
** @param idf String
- ** @param access-list List of Int()
+ ** @param subscript Expression
*/
- flatten-access-list(|idf, access-list) =
- /* eval meta expressions in the access-list
+ flatten-access-list(|idf, subscript) =
+ /* eval expressions in the subscript
* eg: Plus(Int("1"), Int("2")) -> Int("3") */
- <prism-desugar> access-list
+ <prism-desugar> subscript
- /* Now the access must only contain a list of Int: [Int("1"),
Int("2"), ..]
+ /* Now the access must only contain a simple Int(..)
* So we can remove the Int() constructor. */
- ; map(\ Int(i) -> i \ <+ invalid-array-access)
+ ; (\ Int(i) -> i \ <+ invalid-array-access)
- /* Now we have a list of strings such as: ["1", "2", ...]
- * Check that the list only contains positive integers as strings */
- ; map(try(string-to-int; neg; invalid-array-access))
+ /* Now we have an int in a string such as: "1"
+ * Check that the subscript is not negative */
+ ; try(string-to-int; neg; invalid-array-access)
- /* Insert underscores between each integer */
- ; separate-by(|"_")
-
- /* Produce the final identifier: eg: idf_1_2 */
- ; <concat-strings> [idf, "_" | <id>]
+ /* Produce the final identifier: eg: idf_1 */
+ ; <concat-strings> [idf, "_" | [<id>]]
/**
** @internal
@@ -50,17 +47,16 @@
*/
invalid-array-access =
if ?Identifier(i) then
- ice(|"invalid-array-access", <concat-strings>["internal
compiler error: ",
- "undeclared meta-variable: ", i,
- " (should have been detected earlier!)"])
+ err-msg(|<concat-strings>["undeclared meta-variable: ", i])
else
if (is-int; neg) then
- err-msg(|"error: negative array subscript detected:")
+ err-msg(|"negative array subscript detected:")
; debug
- ; <xtc-exit> 2
else
- err-msg(|"error: non constant term in array access:")
+ err-msg(|"invalid array access:")
; debug
- ; <xtc-exit> 2
+ ; err-msg(|<concat-strings>["array subscripts must be evaluable
",
+ "down to constant positive integers."])
end
end
+ ; <xtc-exit> 5
Index: src/str/check-meta-vars.str
--- src/str/check-meta-vars.str (revision 45)
+++ src/str/check-meta-vars.str (working copy)
@@ -53,10 +53,16 @@
check-meta-var-unicity
; ?meta-var
; rules(MetaVars: meta-var)
+ ; rules(UnscopedMetaVarList: meta-var)
check-meta-var-declared =
?Identifier(idf)
- ; if not(<MetaVars> Identifier(idf)) then
+ ; if not(<MetaVars> Identifier(idf)
+ /* static consts can be seen as a meta-vars here. */
+ + <ExpandStaticConsts> Identifier(idf)
+ /* formulas too, as long as they are statically evaluable. */
+ + (<ExpandFormulas> Identifier(idf)
+ ; check-all-identifers-are-meta-vars)) then
err-msg(|<concat-strings>["undeclared meta-var: ", idf])
; <xtc-exit> 2
end
@@ -67,3 +73,13 @@
err-msg(|<concat-strings>["meta-var already defined: ", idf])
; <xtc-exit> 2
end
+ ; if <ExpandStaticConsts> Identifier(idf) then
+ err-msg(|<concat-strings>["cannot redefine `", idf, "':
already ",
+ "defined as a constant value"])
+ ; <xtc-exit> 2
+ end
+ ; if <ExpandFormulas> Identifier(idf) then
+ err-msg(|<concat-strings>["cannot redefine `", idf, "':
already ",
+ "defined as a formula"])
+ ; <xtc-exit> 2
+ end
Index: src/str/array-decl-desugar.str
--- src/str/array-decl-desugar.str (revision 45)
+++ src/str/array-decl-desugar.str (working copy)
@@ -1,141 +1,199 @@
/**
-** This sub-module is used to desugar multi-dimension array declarations.
-** Each dimension will by handled by a meta for loop unrolled later.
-** So if we have a N-dimensions array declaration, it will be rewritten as
-** N nested for loops.
+** This sub-module is used to desugar array declarations into simple
+** declarations.
**
-** eg: x[4][3] : [1..2];
-** for meta_i_0 from 0 to 4 do
-** for meta_i_1 from 0 to 3 do
-** x[meta_i_0][meta_i_1] : [1..2];
-** end
-** end
-** Since this will unrolled and flattened later in by the submodule evaluating
-** meta-code we will end up having all the x_i_j variables declared.
-**
-** NOTE: Each dimension is handled separately and recursion is not handled by
-** array-decl-desugar. The rule must be called in a topdown(try(..)) in order
-** to naturally traverse generated code and thus, handle all dimensions.
+** eg: x[4][6,7] : [1..2];
+** is desugared to x[0..3][6,7] : [1..2];
+** and then to the declaration of x_0_6, x_0_7, x_1_6, x_1_7, x_2_6, etc.
*/
module array-decl-desugar
+imports desugar-array-access
strategies
/**
- ** Patch the list of dimensions with the meta-var used in the meta for loop.
- ** Basically this strategy generates a new meta-var used as the iterator
- ** in the meta-for loop and updates the dimensions of the declared array.
- ** The dimension updated is the first one matching Int(_)
- **
- ** eg: x[4][3] : bool;
- ** => BoolDecNoInit(Identifier("x"),
- ** ArrayAccess( [Identifier("meta_i_0"), Int(3)] ))
- ** will needs to be transformed as:
- ** BoolDecNoInit(Identifier("x"),
- ** ArrayAccess( [Identifier("meta_i_0"),
- ** Identifier("meta_i_1")] ))
- ** @type List(dims) -> List(meta-var, current-dim, List(all-dims-patched))
+ ** Desugar dimensions in array declarations in explicit ranges.
+ ** eg: x[4] is desugared to x[0..3]
*/
- update-dimensions(|dims) =
- <newname> "__meta_i" => x
-
- /* Ensure that the list of dimensions is desugared */
- ; <prism-desugar> dims => dims'
-
- /* find the first element in the list which matches ?Int(_)
- * eg: [Identifier("..."), Int("1"), Int("2")] will be
transformed in
- * ([Identifier("...")], Int("1"), [Int("2")]) */
- ; <split-fetch-keep(?Int(_))> dims'
- => (dims-done, Int(current-dim), dims-todo)
-
- /* array[N] has N elements ranging from 0 to N-1 */
- ; <subtS>(current-dim, "1") => current-dim'
-
- /* replace the dimension we're working on by the meta-var */
- ; <concat> [dims-done, [Identifier(x)], dims-todo]
-
- /* return the result in a tuple */
- ; !(x, Int(current-dim'), <id>)
+ desugar-array-access-for-decl =
+ ArrayAccess(try(desugar-array-access-for-decl), prism-desugar;try(add-range))
rules
-// FIXME: Try to figure out why concrete syntax fails to work here
-
- array-decl-desugar:
- IntDecNoInit(ArrayAccess(idf, dims), low, up)
- //-> |[ for x from 0 to ~dim step 1 do x[i] : [~low..~up]; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ IntDecNoInit(ArrayAccess(idf, dims'), low, up) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
-
- array-decl-desugar:
- IntDec(ArrayAccess(idf, dims), low, up, value)
- //-> |[ for x from 0 to ~dim step 1 do
- // x[i] : [~low..~up] init ~value;
- // end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ IntDec(ArrayAccess(idf, dims'), low, up, value) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
-
-
-
- array-decl-desugar:
- BoolDecNoInit(ArrayAccess(idf, dims))
- //-> |[ for x from 0 to ~dim step 1 do x[i] : bool; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ BoolDecNoInit(ArrayAccess(idf, dims')) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
-
- array-decl-desugar:
- BoolDec(ArrayAccess(idf, dims), value)
- //-> |[ for x from 0 to ~dim step 1 do x[i] : bool init ~value; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ BoolDec(ArrayAccess(idf, dims'), value) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
-
-
-
- array-decl-desugar:
- ConstInt(ArrayAccess(idf, dims), value)
- //-> |[ for x from 0 to ~dim step 1 do const int x[i] = ~value; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ ConstInt(ArrayAccess(idf, dims'), value) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
-
- array-decl-desugar:
- ConstIntNoInit(ArrayAccess(idf, dims))
- //-> |[ for x from 0 to ~dim step 1 do const int x[i]; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ ConstIntNoInit(ArrayAccess(idf, dims')) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
+ /** @internal Rewrite simple dimensions with ranges (x[4] -> x[0..3]). */
+ add-range:
+ [Int(i)] -> [Range(Int("0"), Int(j))]
+ where if <eq>(i, "0") then
+ err-msg(|"array declared with a size of 0 element")
+ ; debug
+ ; <xtc-exit> 2
+ else
+ if <ltS>(i, "0") then
+ err-msg(|"array declared with a negative number of elements")
+ ; debug
+ ; <xtc-exit> 2
+ end
+ end
+ ; <subtS>(i, "1") => j
+rules
+// FIXME: Try to figure out why concrete syntax fails to work here.
+// FIXME: Try to put some code in common in order to shorten the rules.
- array-decl-desugar:
- ConstDouble(ArrayAccess(idf, dims), value)
- //-> |[ for x from 0 to ~dim step 1 do const double x[i] = ~value; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ ConstDouble(ArrayAccess(idf, dims'), value) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
+/*
+** ## ============ ##
+** ## Local arrays ##
+** ## ============ ##
+*/
+ // int without init
array-decl-desugar:
- ConstDoubleNoInit(ArrayAccess(idf, dims))
- //-> |[ for x from 0 to ~dim step 1 do const double x[i]; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ ConstDoubleNoInit(ArrayAccess(idf, dims')) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
+ IntDecNoInit(aa@ArrayAccess(aa_idf, _), low, up)
+ -> int-decl-no-init-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !IntDecNoInit(Identifier(var-name), low, up)
+ })
+ ; ?int-decl-no-init-list
+
+ // int with init
+ array-decl-desugar:
+ IntDec(aa@ArrayAccess(aa_idf, _), low, up, value)
+ -> int-decl-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !IntDec(Identifier(var-name), low, up, value)
+ })
+ ; ?int-decl-list
- array-decl-desugar:
- ConstBool(ArrayAccess(idf, dims), value)
- //-> |[ for x from 0 to ~dim step 1 do const bool x[i] = ~value; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ ConstBool(ArrayAccess(idf, dims'), value) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
+ // bool without init
+ array-decl-desugar:
+ BoolDecNoInit(aa@ArrayAccess(aa_idf, _))
+ -> bool-decl-no-init-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !BoolDecNoInit(Identifier(var-name))
+ })
+ ; ?bool-decl-no-init-list
+
+ // bool with init
+ array-decl-desugar:
+ BoolDec(aa@ArrayAccess(aa_idf, _), value)
+ -> bool-decl-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !BoolDec(Identifier(var-name), value)
+ })
+ ; ?bool-decl-list
+
+/*
+** ## =================== ##
+** ## Static const arrays ##
+** ## =================== ##
+*/
+ // const int with init
array-decl-desugar:
- ConstBoolNoInit(ArrayAccess(idf, dims))
- //-> |[ for x from 0 to ~dim step 1 do const bool x[i]; end ]|
- -> MetaFor(Identifier(x), Int("0"), current-dim',
Int("1"),
- [ ConstBoolNoInit(ArrayAccess(idf, dims')) ])
- where update-dimensions(|dims) => (x, current-dim', dims')
+ ConstInt(aa@ArrayAccess(aa_idf, _), value)
+ -> const-int-decl-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !ConstInt(Identifier(var-name), value)
+ })
+ ; ?const-int-decl-list
+
+ // const int without init
+ array-decl-desugar:
+ ConstIntNoInit(aa@ArrayAccess(aa_idf, _))
+ -> const-int-decl-no-init-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !ConstIntNoInit(Identifier(var-name))
+ })
+ ; ?const-int-decl-no-init-list
+
+
+
+ // const double with init
+ array-decl-desugar:
+ ConstDouble(aa@ArrayAccess(aa_idf, _), value)
+ -> const-double-decl-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !ConstDouble(Identifier(var-name), value)
+ })
+ ; ?const-double-decl-list
+
+ // const double without init
+ array-decl-desugar:
+ ConstDoubleNoInit(aa@ArrayAccess(aa_idf, _))
+ -> const-double-decl-no-init-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !ConstDoubleNoInit(Identifier(var-name))
+ })
+ ; ?const-double-decl-no-init-list
+
+
+
+ // const bool with init
+ array-decl-desugar:
+ ConstBool(aa@ArrayAccess(aa_idf, _), value)
+ -> const-bool-decl-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !ConstBool(Identifier(var-name), value)
+ })
+ ; ?const-bool-decl-list
+
+ // const bool without init
+ array-decl-desugar:
+ ConstBoolNoInit(aa@ArrayAccess(aa_idf, _))
+ -> const-bool-decl-no-init-list
+ where <fetch-idf> aa_idf => idf
+ ; <desugar-array-access-for-decl> aa
+ ; desugar-array-access
+ ; desugared-array-access-list-to-identifier-list(|idf)
+ ; map({var-name:
+ ?var-name
+ ; !ConstBoolNoInit(Identifier(var-name))
+ })
+ ; ?const-bool-decl-no-init-list
Index: src/str/xrm-to-prism.str
--- src/str/xrm-to-prism.str (revision 45)
+++ src/str/xrm-to-prism.str (working copy)
@@ -20,10 +20,15 @@
** - RandGenModules: each call to the XRM builtin rand generates a module
** which is stored in this DR. Just before xrm-to-prism finishes, we
** paste these modules at the end of the source code.
+** - MetaVars: (scoped) temporary used by check-meta-vars to store the list
+** of meta-vars declared in the current scope.
+** - UnscopedMetaVarList: Same as MetaVars but unscoped. Used as a *dirty*
+** workaround to allow declarations using meta-vars.
*/
module xrm-to-prism
imports
XRM
+ collect-static-const-decl
prism-desugar
flatten-array-access
check-meta-vars
@@ -39,14 +44,24 @@
DesugarRightShift <+ DesugarLeftShift
<+ DesugarImplicitForStep <+ DesugarImplicitElse
<+ DesugarRand <+ EvalRand
+ /*FIXME: to be implemented.
+ <+ DesugarArrayEq <+ DesugarArrayNotEq
+ <+ DesugarArrayExistsEq <+ DesugarArrayExistsNotEq*/
)
; notice-msg(|"xrm-to-prism: XRM sugar removed")
/* Collect static const variables
* Two goals: expand them if needed, look for variable name conflicts. */
- ; topdown(try(collect-static-const-decl); try(collect-formulas))
+ ; ModulesFile(id, map(try(collect-static-const-decl); try(collect-formulas)))
; notice-msg(|"xrm-to-prism: static const and formulas collected")
+ /* Check that meta vars are always defined in the current scope when used
+ * and that they are not redefined twice in the same scope. This must come
+ * AFTER collect-static-const-decl/collect-formulas since it needs some of
+ * the information gathered by them (in DR's). */
+ ; check-meta-vars
+ ; notice-msg(|"xrm-to-prism: meta-vars checked")
+
/* Desugar array declarations
* eg: x[4][5] is transformed into two nested meta for loops
* We can't do this in xrm-to-prism-desugar because the innermost
@@ -58,11 +73,6 @@
; topdown(try(array-decl-desugar))
; notice-msg(|"xrm-to-prism: array declarations desugared")
- /* Check that meta vars are always defined in the current scope when used
- * and that they are not redefined twice in the same scope */
- ; check-meta-vars
- ; notice-msg(|"xrm-to-prism: meta-vars checked")
-
/* unroll meta loops, eval meta if */
; eval-meta-code
; notice-msg(|"xrm-to-prism: eval-meta-code done")
@@ -105,32 +115,19 @@
//|[ if e then s* end ]| -> |[ if e then s* else end ]|
MetaIf(e, m*) -> MetaIf(e, m*, [])
-signature constructors
- Type : String -> Type
-
-strategies
+ /* FIXME: to be implemented.
+ DesugarArrayEq:
+ Eq(aa@ArrayAccess(_, _), rhs) -> Eq(rhs, rhs)
- collect-static-const-decl =
- ?ConstInt(idf, value)
- ; where(!value{Type("int")} => v)
- ; rules(ExpandStaticConsts: idf -> v)
-
- collect-static-const-decl =
- ?ConstDouble(idf, value)
- ; where(!value{Type("double")} => v)
- ; rules(ExpandStaticConsts: idf -> v)
-
- collect-static-const-decl =
- ?ConstBool(idf, value)
- ; where(!value{Type("bool")} => v)
- ; rules(ExpandStaticConsts: idf -> v)
+ DesugarArrayNotEq:
+ NotEq(aa@ArrayAccess(_, _), rhs) -> NotEq(rhs, rhs)
-rules
+ DesugarArrayExistsEq:
+ ExistsEq(aa@ArrayAccess(_, _), rhs) -> Eq(rhs, rhs)
- collect-formulas =
- //?|[ formula x = e; ]|
- ?FormulaDef(x, e)
- ; rules(ExpandFormulas: x -> e)
+ DesugarArrayExistsNotEq:
+ ExistsNotEq(aa@ArrayAccess(_, _), rhs) -> NotEq(rhs, rhs)
+ */
strategies
Index: src/str/collect-static-const-decl.meta
--- src/str/collect-static-const-decl.meta (revision 0)
+++ src/str/collect-static-const-decl.meta (revision 0)
@@ -0,0 +1 @@
+Meta([Syntax("StrategoXRM")])
Index: src/str/prism-desugar.str
--- src/str/prism-desugar.str (revision 45)
+++ src/str/prism-desugar.str (working copy)
@@ -46,9 +46,9 @@
<+ ConstBool(id, prism-desugar)
<+ FormulaDef(id, prism-desugar)
<+ ?Int(_); IntToDouble
- <+ all(try(ExpandStaticConsts)
- ; try(ExpandFormulas)
- ; prism-desugar-first-pass)
+ <+ ExpandStaticConsts
+ <+ ExpandFormulas
+ <+ all(prism-desugar-first-pass)
rules
Index: src/str/eval-meta-code.str
--- src/str/eval-meta-code.str (revision 45)
+++ src/str/eval-meta-code.str (working copy)
@@ -67,8 +67,7 @@
///*DEBUG*/; printf(|" meta-var = ", meta-var)
///*DEBUG*/; printf(|" from = ", ifrom)
///*DEBUG*/; printf(|" to = ", ito);
- where(<check-meta-var-unicity> meta-var) // FIXME: is this still needed?
- ; for-loop(gen-meta-for | ifrom, ito, istep, [])
+ for-loop(gen-meta-for | ifrom, ito, istep, [])
///*DEBUG*/; say(!" ~~~ unroll-meta-for: before bagof-MetaModule")
///*DEBUG*/; debug
; bagof-MetaCode
@@ -78,16 +77,20 @@
|}
check-loop-validity(|meta-var, from, to, step) =
- if not(!from => Int(_); !to => Int(_); !step => Int(_)) then
- err-msg(|<concat-strings>["invalid meta for loop: the value of the
",
+ !meta-var => Identifier(idf)
+ ; if not(!from => Int(_); !to => Int(_); !step => Int(_)) then
+ err-msg(|<concat-strings>["invalid meta-for loop on the meta-var
`",
+ idf, "': the value of the ",
"fields `from', `to' and `step' must be
",
"statically evaluable down to a ",
"simple integer"])
+ ; <debug> from
+ ; <debug> to
+ ; <debug> step
; <xtc-exit> 2
end
; if <gtS>(from, to) then
- !meta-var => Identifier(idf)
- ; err-msg(|<concat-strings>["bad `for' loop on the meta-var ",
+ err-msg(|<concat-strings>["bad `for' loop on the meta-var ",
idf, " starts at ", from,
" which is less than ", to])
; <xtc-exit> 2
@@ -122,8 +125,7 @@
///*DEBUG*/say(!" @@@ unroll-meta-forin: starting:")
///*DEBUG*/; printf(|" meta-var = ", meta-var)
///*DEBUG*/; printf(|" exp-list = ", exp-list);
- where(<check-meta-var-unicity> meta-var) // FIXME: is this still needed?
- ; <map(gen-meta-forin(|meta-var, body))> exp-list
+ <map(gen-meta-forin(|meta-var, body))> exp-list
///*DEBUG*/; say(!" ~~~ unroll-meta-forin: before bagof-MetaModule")
///*DEBUG*/; debug
; bagof-MetaCode
Index: src/str/xrm-front.str
--- src/str/xrm-front.str (revision 45)
+++ src/str/xrm-front.str (working copy)
@@ -46,7 +46,6 @@
prism-desugar
; dbg(|"prism-desugar finished")
end
- ; id // FIXME: add more transformations here
/** list of available options for xrm-front */
xrm-front-options =
Index: src/str/collect-static-const-decl.str
--- src/str/collect-static-const-decl.str (revision 0)
+++ src/str/collect-static-const-decl.str (revision 0)
@@ -0,0 +1,77 @@
+/**
+** This sub-module is used to collect static constants and formulas
+** declarations so they can be used in constant propagation.
+** (see prism-desugar)
+*/
+module collect-static-const-decl
+
+/**
+** `Type' is used to annotate the static const collected.
+** This might be useful in the future.
+*/
+signature constructors
+ Type : String -> Type
+
+strategies
+
+ collect-static-const-decl =
+ ?ConstInt(idf, value)
+ ; where(!value{Type("int")} => v)
+ ; if <ExpandStaticConsts> idf then
+ cannot-redefine-static-const(|idf)
+ end
+ ; if <ExpandFormulas> idf then
+ cannot-redefine-formula(|idf)
+ end
+ ; rules(ExpandStaticConsts: idf -> v)
+
+ collect-static-const-decl =
+ ?ConstDouble(idf, value)
+ ; where(!value{Type("double")} => v)
+ ; if <ExpandStaticConsts> idf then
+ cannot-redefine-static-const(|idf)
+ end
+ ; if <ExpandFormulas> idf then
+ cannot-redefine-formula(|idf)
+ end
+ ; rules(ExpandStaticConsts: idf -> v)
+
+ collect-static-const-decl =
+ ?ConstBool(idf, value)
+ ; where(!value{Type("bool")} => v)
+ ; if <ExpandStaticConsts> idf then
+ cannot-redefine-static-const(|idf)
+ end
+ ; if <ExpandFormulas> idf then
+ cannot-redefine-formula(|idf)
+ end
+ ; rules(ExpandStaticConsts: idf -> v)
+
+rules
+
+ collect-formulas =
+ //?|[ formula x = e; ]|
+ ?FormulaDef(x, e)
+ ; if <ExpandStaticConsts> x then
+ cannot-redefine-static-const(|x)
+ end
+ ; if <ExpandFormulas> x then
+ cannot-redefine-formula(|x)
+ end
+ ; rules(ExpandFormulas: x -> e)
+
+strategies
+
+ cannot-redefine-static-const(|idf) =
+ !idf => Identifier(idf')
+ ; err-msg(|<concat-strings>["Cannot redefine `", idf',
"': already defined",
+ " as a static const variable."])
+ ; <debug> (<ExpandStaticConsts> idf)
+ ; <xtc-exit> 2
+
+ cannot-redefine-formula(|idf) =
+ !idf => Identifier(idf')
+ ; err-msg(|<concat-strings>["Cannot redefine `", idf',
"': already defined",
+ " as a formula."])
+ ; <debug> (<ExpandFormulas> idf)
+ ; <xtc-exit> 2
Index: src/str/desugar-array-access.str
--- src/str/desugar-array-access.str (revision 0)
+++ src/str/desugar-array-access.str (revision 0)
@@ -0,0 +1,176 @@
+/**
+** This sub-module provides several strategies used to handle arrays in XRM
+** and desugar them down to simple variables for PRISM.
+**
+** Support is provided for any kind of array (including multi-demensional ones)
+** The main strategies are:
+** - desugar-array-access: provided with the root of an ArrayAccess as
+** current term, this strategy will return the list of all the possibles
+** array accesses generated by the sugared ArrayAccess in the current
+** term.
+** - desugared-array-access-list-to-identifier-list: applied to the result
+** of desugar-array-access, this enables to easily get a list of
+** identifiers involved in complex array accesses.
+** - fetch-idf: finds which identifier is pertains to the current
+** ArrayAccess. This is useful because the identifier one which the
+** real ArrayAccess is done can be "hidden" in nested ArrayAccesses.
+*/
+module desugar-array-access
+
+strategies
+
+ /** Yield the list of all possible array accesses generated by a sugared
+ ** array access. (See the comments of desugar-subscripts and
+ ** list-all-array-accesses)
+ */
+ desugar-array-access =
+ desugar-subscripts
+ ; list-all-array-accesses
+
+strategies
+
+ /** Collects all subscripts in array accesses and desugar ranges.
+ ** eg: x[1][2] -> [[1], [2]]
+ ** x[1..3][2,4] -> [[1,2,3], [2,4]]
+ ** NOTE: we have a 2D list. The first level of lists represents the
+ ** dimension, the second level, the subscripts accessed for that
+ ** dimension.
+ ** NOTE: If the subscripts contain at least one meta-var, we completely
+ ** discard this array-access (by failing) and let the eval-meta-code
+ ** part take care of it. This is a *dirty* hack to allow declarations
+ ** using meta-vars. This implies that it's impossible to declare
+ ** something only partially using meta-vars. :|
+ */
+ desugar-subscripts =
+ collect-all(?ArrayAccess(_, <id>), conc) // collect gives us the list...
+ ; reverse // ... with deepest array accesses first (we want the opposite)
+ ; prism-desugar
+ ; if has-meta-vars then fail end // see the 2nd NOTE above.
+ ; map( // traverse the list of dimensions
+ map( // traverse the subscripts for a given dimension
+ if ?Int(_) then
+ (\ Int(i) -> i \ // get rid of Int() constructor
+ ; where(string-to-int; not(neg))) // ensure that i>=0
+ <+ invalid-array-access // if anything above failed, report it
+ else
+ if ?Range(_, _) then
+ desugar-range
+ else // we are neither on an Int nor on a Range => invalid
+ invalid-array-access
+ end
+ end
+ ) // end inner map
+ ; flatten-list // because Ranges create nested lists
+ ) // end outer map
+
+ has-meta-vars =
+ oncetd(?Identifier(_); UnscopedMetaVarList)
+
+strategies
+
+ /** Create the Cartesian product of all possible array subscripts.
+ ** eg: [[1,2,3], [2,4]] -> [[1,2], [1,4], [2,2], [2,4], [3,2], [3,4]]
+ ** [[1,2],[3,4],[5,6]] -> [[1,3,5], [1,3,6], [1,4,5], [1,4,6],
+ ** [2,3,5], [2,3,6], [2,4,5], [2,4,6]]
+ ** Here we use the black magic of the rule below (cartesian-product).
+ */
+ list-all-array-accesses =
+ /* remember: 1st-level of the list = dimensions => this if matches array
+ * accesses in 1D arrays, where a Cartesian product is not needed.
+ */
+ if ?[single-list] then
+ /* since we're not doing a Cartesian product, we must separate each
+ * element in its own sub list so that x[1,2] yields [["1"],
["2"]] and
+ * not [["1", "2"]] which means x[1][2] (not obvious, I admit)
*/
+ <map(\ x -> [x] \)> single-list
+ else
+ /* Use Cartesian product to generate the list of all the possible
+ * accesses. */
+ foldr(![], ?(<id>,[]) <+ cartesian-product)
+ end
+
+rules
+
+ /** Perform a cartesian-product between two lists.
+ ** FIXME: this is just NOT human readable.
+ **
+ ** OK so here xs is a list of elements (eg: [1,2]) and ys too (eg: [3,4]).
+ ** First foldr executes the \ x -> ... \ for each element x in xs. This
+ ** combines each element of x with ys. Dammit, this part is a bit tricky:
+ ** If the current term is a list (with one or more elements) it will match
+ ** ?[_|_] so what we do is add x at the beginning of the list.
+ ** Else we create a new list with two elements, x and the current term.
+ ** => This way we end with [x,ys]
+ **
+ ** Then all the resulting tuples are of the form ([x1, ys], [x2, ys])
+ ** concatenated together by conc, which indeed, is a Cartesian product.
+ */
+ cartesian-product: (xs,ys)
+ -> <foldr(![]
+ , conc
+ , \ x -> <map( (?[_|_];![x|<id>]) <+ ![x|[<id>]])>
ys \
+ )> xs
+
+strategies
+
+ /** Desugar a Range(Int(low), Int(high)) in a list [low,...,high].
+ ** eg: Range(Int(1), Int(5)) -> [1,2,3,4,5]
+ */
+ desugar-range =
+ (?Range(Int(from),Int(to)) <+ non-const-range-in-array-access)
+ ; if <ltS>(to, from) then
+ invalid-range-in-array-access
+ end
+ ; ![to] // start with the highest value
+ ; rec x(
+ {h,t: // restrict h and t to this scope
+ ?[h|t]
+ ; if not(<eq>(h, from)) then
+ ![<subtS>(h, "1") | <id>]
+ ; x
+ end
+ }
+ )
+
+ non-const-range-in-array-access =
+ err-msg(|"error: non constant term used in a range in an array access:")
+ ; debug
+ ; <xtc-exit> 2
+
+ invalid-range-in-array-access =
+ err-msg(|"error: invalid range in an array access [x..y] where x>y:")
+ ; debug
+ ; <xtc-exit> 2
+
+strategies
+
+ /** Given an identifier and a desugared array access list (as provided by
+ ** desugar-array-access), produce a single list of identifiers.
+ ** The desugared array access list must be passed as current term.
+ **
+ ** eg: idf="i"
+ ** current term=[["1","2"], ["1","3"]]
+ ** yields => ["i_1_2", "i_1_3"]
+ **
+ ** this is usefull to translate i[1][2,3] in i_1_2 and i_1_3 (using
+ ** desugar-array-access)
+ */
+ desugared-array-access-list-to-identifier-list(|idf) =
+ map(![idf|<id>]
+ ; separate-by(|"_")
+ ; concat-strings
+ )
+
+rules
+
+ /** Used to find the identifier in an ArrayAccess.
+ ** x[1] => ArrayAccess(Identifier(x), [1])
+ ** x[1][2] => ArrayAccess(ArrayAccess(Identifier(x), [1]), [2])
+ ** We dig into the first child of ArrayAccess looking for an Identifier as
+ ** long as we haven't got it.
+ **
+ ** We return the identifier itself (without the Identifier(_) constructor).
+ */
+ fetch-idf =
+ (?Identifier(i); !i)
+ <+ (?ArrayAccess(aa_idf, _); <fetch-idf> aa_idf)
Index: src/syn/xrm/XRM-Arrays.sdf
--- src/syn/xrm/XRM-Arrays.sdf (revision 45)
+++ src/syn/xrm/XRM-Arrays.sdf (working copy)
@@ -2,25 +2,25 @@
imports
PRISM-to-XRM
exports
+ %% FIXME: we can probably make this look nicer.
%% EBNF Grammar: Arrays
- %% ArrayAccess ::= Identifier ArraySubscript {ArraySubscript}
+ %% ArrayAccess ::=
+ %% Identifier "[" Range {"," Range} "]"
+ %% | ArrayAccess "[" Range {"," Range} "]"
%%
- %% ArraySubscript ::= "[" Identifier "]"
- %%
- %% ArrayAccessPrime ::= Identifier ArraySubscript+ "'"
+ %% ArrayAccessPrime ::=
+ %% Identifier "[" Range {"," Range} "]"
"'"
+ %% | ArrayAccess "[" Range {"," Range} "]"
"'"
- sorts ArrayAccess ArraySubscript
+ sorts ArrayAccess
context-free syntax
- Identifier ArraySubscript+ -> ArrayAccess {cons("ArrayAccess")}
- "[" Expression "]" -> ArraySubscript {bracket}
-
- %% Note: why use bracket here?
- %% This is a work around. In SDF, if a production contains literals,
- %% a constructor is required. With brackets, we specify that literals
- %% are allowed there, however this does not create a node in the AST.
+ Identifier "[" {Range ","}+ "]" -> ArrayAccess
{cons("ArrayAccess")}
+ ArrayAccess "[" {Range ","}+ "]" -> ArrayAccess
{cons("ArrayAccess")}
sorts ArrayAccessPrime
context-free syntax
- Identifier ArraySubscript+ "'"
+ ArrayAccess "[" {Range ","}+ "]" "'"
+ -> ArrayAccessPrime {cons("ArrayAccessPrime")}
+ Identifier "[" {Range ","}+ "]" "'"
-> ArrayAccessPrime {cons("ArrayAccessPrime")}
Index: src/syn/xrm/XRM-Expression.sdf
--- src/syn/xrm/XRM-Expression.sdf (revision 45)
+++ src/syn/xrm/XRM-Expression.sdf (working copy)
@@ -8,6 +8,8 @@
%% ArrayAccess
%% | Expression "<<" Expression
%% | Expression ">>" Expression
+ %% | ArrayAccess "?=" Range {"," Range}
+ %% | ArrayAccess "?!=" Range {"," Range}
%%
%% ExpressionFunc ::=
%% (* older builtin functions for backwards compat. *)
@@ -20,19 +22,43 @@
Expression ">>" Expression -> Expression
{left,cons("RightShift")}
Expression "<<" Expression -> Expression
{left,cons("LeftShift")}
+ %% NOTE: The two following rules should have a `non-assoc' keyword
+ %% which is omitted on purpose. See the README in ../prism
+ ArrayAccess "?=" {Range ","}+ -> Expression
{cons("ExistsEq")}
+ ArrayAccess "?!=" {Range ","}+ -> Expression
{cons("ExistsNotEq")}
+
"rand" "(" {Expression ","}+ ")" ->
Expression {cons("Rand")}
"func" "(" "rand" "," {Expression
","}+ ")" -> Expression {cons("Rand")}
+ %% NOTE: remember: priorities are transitive in SDF.
+ %% The following priorities are marked either with "inherited" or
"new".
+ %% The former means that these priorities are inherited from the base
+ %% grammar (../prism/PRISM-Expression.sdf) and the latter means that
+ %% these priorities are inserted in the right place in the "priority chain".
context-free priorities
- {
+ { %% inherited
"+" Expression -> Expression
"-" Expression -> Expression
}
- > {left:
+ > {left: %% new
Expression ">>" Expression -> Expression
Expression "<<" Expression -> Expression
}
- > {left:
+ > {left: %% inherited
Expression "*" Expression -> Expression
Expression "/" Expression -> Expression
}
+ > {left: %% inherited
+ Expression "+" Expression -> Expression
+ Expression "-" Expression -> Expression
+ }
+ > {non-assoc: %% new
+ ArrayAccess "?=" {Range ","}+ -> Expression
+ ArrayAccess "?!=" {Range ","}+ -> Expression
+ }
+ > {non-assoc: %% inherited
+ Expression ".." Expression -> Range
+ }
+ > { %% inherited
+ Expression -> Range
+ }
Index: src/syn/prism/PRISM-Expression.sdf
--- src/syn/prism/PRISM-Expression.sdf (revision 45)
+++ src/syn/prism/PRISM-Expression.sdf (working copy)
@@ -210,7 +210,7 @@
%% As we can see, it doesn't make sense to allow a range 1..0 to be a LHS
%% or a RHS for a logical operation.
{non-assoc:
- Expression ".."
Expression -> Range {cons("Range")}
+ Expression ".." Expression -> Range
}
{
Expression -> Range
Index: tests/xrm/exists-eq.xpm
--- tests/xrm/exists-eq.xpm (revision 0)
+++ tests/xrm/exists-eq.xpm (revision 0)
@@ -0,0 +1,12 @@
+formula N = 4;
+
+module test
+ x[N] : [0..42];
+ y[4][4] : [0..42] init 0;
+
+ [] x[3]?=0 -> true;
+ [] y[3][2]?=0 -> true;
+ [] y[1..3][2]?=0 -> true;
+ [] y[1..3][1,2]?=0 -> true;
+ [] y[1,0..3][2]?=0 -> true;
+endmodule
Index: tests/xrm/for-loop-using-const-int.xpm
--- tests/xrm/for-loop-using-const-int.xpm (revision 0)
+++ tests/xrm/for-loop-using-const-int.xpm (revision 0)
@@ -0,0 +1,8 @@
+const int N=3;
+
+for i from 0 to N do
+ module dummy[i]
+ x[i] : [0..i];
+ [] true -> true;
+ endmodule
+end
Index: tests/test-xrm-front.sh.in
--- tests/test-xrm-front.sh.in (revision 45)
+++ tests/test-xrm-front.sh.in (working copy)
@@ -28,7 +28,7 @@
echo ">>> Starting the test for $basefile"
test_cnt=$((test_cnt + 1))
- echo @ECHO_N@ " Converting $basefile into standard PRISM ... "
+ echo @ECHO_N@ " Converting $basefile into standard PRISM AST... "
"@top_builddir@/src/str/xrm-front" -A \
-i "$file" -o "$outdir/$bfile.pm.aterm"
if [ $? -ne 0 ]; then
Index: tests/test-parse-xrm.sh.in
--- tests/test-parse-xrm.sh.in (revision 45)
+++ tests/test-parse-xrm.sh.in (working copy)
@@ -17,13 +17,14 @@
echo @ECHO_N@ " Parsing `basename $file` ... "
"@top_builddir@/src/tools/parse-xrm" -i "$file" -o /dev/null
rv=$?
+ test_cnt=$((test_cnt + 1))
if [ $? -eq 0 ]; then
echo 'OK, no ambiguities found'
test_pass=$((test_pass + 1))
else
echo " * $file: FAILED (bad return value: $rv)" >> failed_tests.$$
+ continue
fi
- test_cnt=$((test_cnt + 1))
done
echo "$0: $test_pass/$test_cnt tests passed"
echo "`date` $0: $test_pass/$test_cnt tests passed" >> test_summary
Index: tests/test-parse-prism.sh.in
--- tests/test-parse-prism.sh.in (revision 45)
+++ tests/test-parse-prism.sh.in (working copy)
@@ -17,13 +17,14 @@
echo @ECHO_N@ " Parsing `basename $file` ... "
"@top_builddir@/src/tools/parse-prism" -i "$file" -o /dev/null
rv=$?
+ test_cnt=$((test_cnt + 1))
if [ $rv -eq 0 ]; then
echo 'OK, no ambiguities found'
test_pass=$((test_pass + 1))
else
echo " * $file: FAILED (bad return value: $rv)" >> failed_tests.$$
+ continue
fi
- test_cnt=$((test_cnt + 1))
done
echo "$0: $test_pass/$test_cnt tests passed"
echo "`date` $0: $test_pass/$test_cnt tests passed" >> test_summary
Index: TODO
--- TODO (revision 45)
+++ TODO (working copy)
@@ -107,6 +107,31 @@
end
end
+ * It is currently impossible to declare something partially with meta-vars.
+ eg: for i from 0 to 3 do
+ const int N[i][5] = 0;
+ end
+ This is because array declarations are desugared down to simple
+ declarations before the meta-code has been evaluated in the pipeline.
+ On the other hand, if we evaluate the meta-code before desugaring array
+ declarations, we will end up with N_i_5 for all `i' and not with
+ N_i_0 ... N_i_5. Moreover, this will most likely fail because we have
+ generated something like: const int N[0][5] = 0;
+ const int N[1][5] = 0;
+ ...
+ const int N[2][5] = 0;
+ but how can we know that we should interpret this as:
+ const int N[0][0..5] = 0;
+ const int N[1][0..5] = 0;
+ ...
+ that is: the meta-var which has been expanded must no go further
+ expansions (eg: const int N[0..1][0..5] = 0;) We will also get an error
+ about declaring an array with a size of 0 element.
+
+ Idea to work around the problem: tag the expanded meta-vars with an
+ annotation on the AST and handle the special case when desugaring array
+ declarations.
+
## -------------- ##
## Desugarisation ##
## -------------- ##