https://svn.lrde.epita.fr/svn/xrm/trunk
Index: ChangeLog
from SIGOURE Benoit <sigoure.benoit(a)lrde.epita.fr>
Add shell-like meta-for loops.
It is now possible to write meta-for loops a la shell:
for i in x, y, z do const int i = 42; end
yields => const int x = 42; const int y = 42; const int z = 42;
It's a bit ugly but I'm going to need something similar for the next
extension. So I thought it would be "nice" to make this "feature"
not
only some internal hack used to achieve transformations and let the
user play with it if he/she feels so.
* src/lib/xrm/pp/xrm-meta-for.str: Add boxing for meta-for-in loops.
* src/str/check-meta-vars.str: Add checks for meta-for-in loops.
* src/str/xrm-to-prism.str: change the way array-decl-desugar is
called.
* src/str/eval-meta-code.str: Eval (unroll) "meta for in" loops.
* src/syn/xrm/XRM-MetaFor.sdf: Add "meta for in" loops.
* tests/xrm/for-in.xpm: New.
* tests/test-xrm-front.sh.in: Remove useless check.
src/lib/xrm/pp/xrm-meta-for.str | 27 ++++++++++++---
src/str/check-meta-vars.str | 9 +++++
src/str/eval-meta-code.str | 70 ++++++++++++++++++++++++++++++----------
src/str/xrm-to-prism.str | 4 +-
src/syn/xrm/XRM-MetaFor.sdf | 12 ++++--
tests/test-xrm-front.sh.in | 8 ----
tests/xrm/for-in.xpm | 3 +
7 files changed, 97 insertions(+), 36 deletions(-)
Index: src/lib/xrm/pp/xrm-meta-for.str
--- src/lib/xrm/pp/xrm-meta-for.str (revision 43)
+++ src/lib/xrm/pp/xrm-meta-for.str (working copy)
@@ -2,10 +2,10 @@
rules
- // "for" Identifier "from" Int "to" Int "do"
ModulesFileSection* "end"
- // -> MetaFor
- // "for" Identifier "from" Int "to" Int "do"
DeclarationOrCommand* "end"
- // -> MetaFor
+ // "for" Identifier "from" Expression "to" Expression
"do"
+ // ModulesFileSection* "end" -> MetaFor
+ // "for" Identifier "from" Expression "to" Expression
"do"
+ // DeclarationOrCommand* "end" -> MetaFor
prism-to-box:
MetaFor(idf, for-from, for-to, mfs-list)
-> box |[ V[ V is=2 [
@@ -16,9 +16,9 @@
] KW["end"] // in the outermost V box
] ]|
- // "for" Identifier "from" Int "to" Int "step"
Int "do"
+ // "for" Identifier "from" Expression "to" Expression
"step" Expression "do"
// ModulesFileSection* "end" -> MetaFor
- // "for" Identifier "from" Int "to" Int "step"
Int "do"
+ // "for" Identifier "from" Expression "to" Expression
"step" Expression "do"
// DeclarationOrCommand* "end" -> MetaFor
prism-to-box:
MetaFor(idf, for-from, for-to, for-step, mfs-list)
@@ -30,3 +30,18 @@
~*mfs-list // in the innermost V box
] KW["end"] // in the outermost V box
] ]|
+
+ // "for" Identifier "in" {Expression ","} "do"
ModulesFileSection* "end"
+ // -> MetaForIn
+ // "for" Identifier "in" {Expression ","} "do"
DeclarationOrCommand* "end"
+ // -> MetaForIn
+ prism-to-box:
+ MetaForIn(idf, in-list, mfs-list)
+ -> box |[ V[ V is=2 [
+ H hs=1 [ KW["for"] ~idf
+ KW["in"] ~*in-list'
+ KW["do"] ]
+ ~*mfs-list // in the innermost V box
+ ] KW["end"] // in the outermost V box
+ ] ]|
+ where <separate-by(!S(","))> in-list => in-list'
Index: src/str/check-meta-vars.str
--- src/str/check-meta-vars.str (revision 43)
+++ src/str/check-meta-vars.str (working copy)
@@ -13,6 +13,7 @@
check-meta-vars =
check-meta-for
+ <+ check-meta-forin
<+ check-meta-if
<+ ArrayAccess(id, check-all-identifers-are-meta-vars)
<+ ArrayAccessPrime(id, check-all-identifers-are-meta-vars)
@@ -28,6 +29,14 @@
; <check-meta-vars> body
|})
+ check-meta-forin =
+ ?MetaForIn(new-meta-var, exp-list, body)
+ ; where({| MetaVars:
+ <add-meta-var> new-meta-var
+ ; <check-meta-vars> exp-list
+ ; <check-meta-vars> body
+ |})
+
check-meta-if =
?MetaIf(condition, then-part, else-part)
; where(
Index: src/str/xrm-to-prism.str
--- src/str/xrm-to-prism.str (revision 43)
+++ src/str/xrm-to-prism.str (working copy)
@@ -51,9 +51,9 @@
* traversal is bottomup and won't recurse into generated code.
*
* This must come AFTER collect-static-const-decl since we might need
- * to expand an array which relies on static const variables.
+ * to expand an arrays which rely on static const variables.
*/
- ; topdown(try(array-decl-desugar))
+ ; array-decl-desugar
/* Check that meta vars are always defined in the current scope when used
* and that they are not redefined twice in the same scope */
Index: src/str/eval-meta-code.str
--- src/str/eval-meta-code.str (revision 43)
+++ src/str/eval-meta-code.str (working copy)
@@ -19,7 +19,8 @@
eval-meta-code =
eval-meta-if
- <+ unroll-meta-loops
+ <+ unroll-meta-for
+ <+ unroll-meta-forin
<+ all(eval-meta-code)
strategies
@@ -47,7 +48,7 @@
strategies
- unroll-meta-loops =
+ unroll-meta-for =
?MetaFor(meta-var, from, to, step, body)
/* reduce the fields from to and step down to simple integers */
; where( <prism-desugar> from => from'
@@ -62,17 +63,17 @@
; !step' => Int(istep)
)
; {| MetaCode:
- ///*DEBUG*/say(!" @@@ unroll-meta-loops: starting:")
+ ///*DEBUG*/say(!" @@@ unroll-meta-for: starting:")
///*DEBUG*/; printf(|" meta-var = ", meta-var)
///*DEBUG*/; printf(|" from = ", ifrom)
///*DEBUG*/; printf(|" to = ", ito);
- where(<check-meta-var-unicity> meta-var)
- ; for-loop(gen-meta-code | ifrom, ito, istep, [])
- ///*DEBUG*/; say(!" ~~~ unroll-meta-loops: before bagof-MetaModule")
+ where(<check-meta-var-unicity> meta-var) // FIXME: is this still needed?
+ ; for-loop(gen-meta-for | ifrom, ito, istep, [])
+ ///*DEBUG*/; say(!" ~~~ unroll-meta-for: before bagof-MetaModule")
///*DEBUG*/; debug
; bagof-MetaCode
; reverse
- ///*DEBUG*/; say(!" ~~~ unroll-meta-loops: after bagof-MetaModule")
+ ///*DEBUG*/; say(!" ~~~ unroll-meta-for: after bagof-MetaModule")
///*DEBUG*/; debug
|}
@@ -94,24 +95,61 @@
strategies
- gen-meta-code(|i, data) =
- ///*DEBUG*/say(!" ### gen-meta-code starting"); debug;
- (?MetaFor(meta-var, _, _, _, body) <+ fatal-err-msg(|"ICE!"))
- ///*DEBUG*/; say(!" >>> gen-meta-code -- start -- current term
>>>")
+ gen-meta-for(|i, data) =
+ ///*DEBUG*/say(!" ### gen-meta-for starting"); debug;
+ ?MetaFor(meta-var, _, _, _, body)
+ ///*DEBUG*/; say(!" >>> gen-meta-for -- start -- current term
>>>")
///*DEBUG*/; debug
- ///*DEBUG*/; say(!" >>> gen-meta-code -- start -- iterator
>>>")
+ ///*DEBUG*/; say(!" >>> gen-meta-for -- start -- iterator
>>>")
///*DEBUG*/; printf(|" meta-var = ", meta-var)
///*DEBUG*/; printf(|" i = ", i)
- ///*DEBUG*/; say(!" <<< gen-meta-code -- propagating meta-var's
value <<< ")
+ ///*DEBUG*/; say(!" <<< gen-meta-for -- propagating meta-var's
value <<< ")
; !body
; topdown(try(?meta-var; !Int(i)))
///*DEBUG*/; debug
- ///*DEBUG*/; say(!" ~~~ gen-meta-code: now recursing")
+ ///*DEBUG*/; say(!" ~~~ gen-meta-for: now recursing")
; eval-meta-code => generated-code
; rules(MetaCode:+ _ -> generated-code)
- ///*DEBUG*/; say(!" ~~~ gen-meta-code: recursion finished, final result:")
+ ///*DEBUG*/; say(!" ~~~ gen-meta-for: recursion finished, final result:")
///*DEBUG*/; debug
- ///*DEBUG*/; say(!"
<<<<<<<<<<<<<<<<< gen-meta-code
<<<<<<<<<<<<<<<<< ")
+ ///*DEBUG*/; say(!"
<<<<<<<<<<<<<<<<< gen-meta-for
<<<<<<<<<<<<<<<<< ")
+
+strategies
+
+ unroll-meta-forin =
+ ?MetaForIn(meta-var, exp-list, body)
+ ; {| MetaCode:
+ ///*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
+ ///*DEBUG*/; say(!" ~~~ unroll-meta-forin: before bagof-MetaModule")
+ ///*DEBUG*/; debug
+ ; bagof-MetaCode
+ ; reverse
+ ///*DEBUG*/; say(!" ~~~ unroll-meta-forin: after bagof-MetaModule")
+ ///*DEBUG*/; debug
+ |}
+
+ gen-meta-forin(|meta-var, body) =
+ ///*DEBUG*/say(!" ### gen-meta-forin starting"); debug;
+ ?exp-to-replace
+ ///*DEBUG*/; say(!" >>> gen-meta-forin -- start -- current term
>>>")
+ ///*DEBUG*/; debug
+ ///*DEBUG*/; say(!" >>> gen-meta-forin -- start -- iterator
>>>")
+ ///*DEBUG*/; printf(|" meta-var = ", meta-var)
+ ///*DEBUG*/; printf(|" exp-to-replace = ", exp-to-replace)
+ ///*DEBUG*/; say(!" <<< gen-meta-forin -- propagating meta-var's
value <<< ")
+ ; !body
+ ; topdown(try(?meta-var; !exp-to-replace))
+ ///*DEBUG*/; debug
+ ///*DEBUG*/; say(!" ~~~ gen-meta-forin: now recursing")
+ ; eval-meta-code => generated-code
+ ; rules(MetaCode:+ _ -> generated-code)
+ ///*DEBUG*/; say(!" ~~~ gen-meta-forin: recursion finished, final
result:")
+ ///*DEBUG*/; debug
+ ///*DEBUG*/; say(!"
<<<<<<<<<<<<<<<<< gen-meta-forin
<<<<<<<<<<<<<<<<< ")
strategies
///*DEBUG*/printf(|str, term) = where(<fprintnl> (stderr, [str, term]))
Index: src/syn/xrm/XRM-MetaFor.sdf
--- src/syn/xrm/XRM-MetaFor.sdf (revision 43)
+++ src/syn/xrm/XRM-MetaFor.sdf (working copy)
@@ -21,17 +21,21 @@
%% This MetaFor can be found only at top-level
%% So we can see it as a ModulesFileSection
"for" Identifier "from" Expression "to" Expression
"do"
- ModulesFileSection* "end"
- -> ModulesFileSection {cons("MetaFor")}
+ ModulesFileSection* "end" -> ModulesFileSection
{cons("MetaFor")}
"for" Identifier "from" Expression "to" Expression
"step" Expression "do"
ModulesFileSection* "end" -> ModulesFileSection
{cons("MetaFor")}
+ "for" Identifier "in" {Expression ","}+ "do"
+ ModulesFileSection* "end" -> ModulesFileSection
{cons("MetaForIn")}
+
%% This MetaFor can be found only inside Modules
%% So we can see it as a DeclarationOrCommand
"for" Identifier "from" Expression "to" Expression
"do"
- DeclarationOrCommand* "end"
- -> DeclarationOrCommand {cons("MetaFor")}
+ DeclarationOrCommand* "end" -> DeclarationOrCommand
{cons("MetaFor")}
"for" Identifier "from" Expression "to" Expression
"step" Expression "do"
DeclarationOrCommand* "end" -> DeclarationOrCommand
{cons("MetaFor")}
+
+ "for" Identifier "in" {Expression ","}+ "do"
+ ModulesFileSection* "end" -> DeclarationOrCommand
{cons("MetaForIn")}
Index: tests/xrm/for-in.xpm
--- tests/xrm/for-in.xpm (revision 0)
+++ tests/xrm/for-in.xpm (revision 0)
@@ -0,0 +1,3 @@
+for i in x,y,z do
+ const int i = 0;
+end
Index: tests/test-xrm-front.sh.in
--- tests/test-xrm-front.sh.in (revision 43)
+++ tests/test-xrm-front.sh.in (working copy)
@@ -58,14 +58,6 @@
fi
echo 'OK, no ambiguities found'
- diff -q "$outdir/$bfile.pm.aterm" "$outdir/$bfile.pm2.aterm"
-
- if [ $? -ne 0 ]; then
- echo 'FAILED: the two parses did NOT produce the same AST:'
- echo " * $file: both parses did NOT produce the same AST" >>
failed_tests.$$
- diff -u "$outdir/$bfile.pm.aterm.pp"
"$outdir/$bfile.pm2.aterm.pp"
- fi
-
echo "<<< Test for $basefile PASSED"
test_pass=$((test_pass + 1))
done