rascal
rascal copied to clipboard
two regular expressions in the same comprehension breaks
In the code below Rascal complains about a redeclared variable n, but only if the second regular expression is there (/rascal/ := f
). A nested comprehension for the same computation works nicely.
rascal>{ <toInt(n), f> | /\s*<n:[0-9]+>\s*<f:\S+>/ <- raw, /rascal/ := f}
|stdin:///|(64,1,<1,64>,<1,65>): Redeclared variable: n
rascal>{<x,y> | <x,y> <- { <toInt(n), f> | /\s*<n:[0-9]+>\s*<f:\S+>/ <- raw}, /rascal/ := y}
rel[int, str]: {
<1,"/unstable-updates/plugins/rascal_eclipse_0.5.2.201209211516.jar">,
This works now:
rascal>{ <toInt(n), f> | /\s*<n:[0-9]+>\s*<f:\S+>/ := "99srascal", /rascal/ := f}
rel[int,str]: {<99,"srascal">}
I've just noticed a similar behaviour with the if statement that generates the same error
if (/<pre:.*>\/\*/ := line && /\S/ := pre && /"(\w|\s)*/ !:= pre)
commentLinesToIgnore +=1;
This reproduces the bug:
module RegexBug
import IO;
void main() {
line = "\"bla /* hello */\" ";
ii = 0;
if (/<pre:.*>\/\*/ := line && /\S/ := pre && /"(\w|\s)*/ !:= pre)
ii +=1;
println(ii);
}
This does not have the bug, even though it should be functionality equivalent (replaced &&
by ,
):
module RegexBug
import IO;
void main() {
line = "\"bla /* hello */\" ";
ii = 0;
if (/<pre:.*>\/\*/ := line, /\S/ := pre, /"(\w|\s)*/ !:= pre)
ii +=1;
println(ii);
}
@menego that gives you a workaround for today, and we have an hypothesis for the cause of the bug: an buggy interaction between the backtracking behavior of the &&
connective and the declaration behavior of regexps.
Thank you very much, always super responsive :-) I already solved that by nesting the if statements but this is waaay cleaner and elegant.
void d() {
pre = "\"";
if (_ <- [1,2] && /"(.)*/ !:= pre)
println("ok");
}
simplified.
another delta gives some insight (replace implicit group by explicit group):
void d() {
pre = "\"";
if (_ <- [1,2] && /"<xxx:.>*/ !:= pre)
println("ok");
}
gives:
rascal>d()
Reloading module RegexBug
|project://rascal-test-project/src/RegexBug.rsc|(86,3,<7,32>,<7,35>): Redeclared variable: _1
Advice: |http://tutor.rascal-mpl.org/Errors/Static/RedeclaredVariable/RedeclaredVariable.html|
ok
rascal>d()
Reloading module RegexBug
|project://rascal-test-project/src/RegexBug.rsc|(90,3,<7,36>,<7,39>): Redeclared variable: xxx
Advice: |http://tutor.rascal-mpl.org/Errors/Static/RedeclaredVariable/RedeclaredVariable.html|
ok
Flip the conditional and change the match:
void d() {
pre = "\'";
if (_ <- [1,2] && /"<xxx:.>*/ := pre)
println("ok");
}
still produces:
rascal>d()
|project://rascal-test-project/src/RegexBug.rsc|(89,3,<7,35>,<7,38>): Redeclared variable: xxx
means that the difference between !:=
and :=
is irrelevant.
Ok, this is a complex issue. The difference is still made by replacing &&
with ,
and it seems that a variable scope is not properly cleaned up before the second match is tried, and the second instance of xxx
is declared again in the same scope.
The trouble with fixing this issue is that the code around &&
is brittle and highly dependent on the semantics and implementation details of binding patterns such as the ListPattern, the SetPattern and the basic TypedVariablePattern.
So this requires some further study.
rascal> if (_ <- [1,2] && /"<xxx2:.>*/ !:= "\"") println("ok");
|prompt:///|(37,3,<1,37>,<1,40>): Redeclared variable: xxx2
Advice: |https://www.rascal-mpl.org/docs/Rascal/Errors/CompileTimeErrors/RedeclaredVariable|
this is still an issue.
See #1900 for progress; that fix is not correct yet.