I found that the following piece of Stratego code works fine when it is run from the .ctree file and fails when it is compiled to Java:


signature
constructors
elem : String -> X

rules

fetch-elem(|name) = fetch(?x@elem(name)); !x

run-test:
t -> None()
with
test-suite(
!“test suite”,
apply-test(
!" when given one element, fetch-elem works as expected",
fetch-elem(|“fixedType”),
![elem("fixedType")],
!elem(“fixedType”)
);
apply-test(
!" when given two elements, fetch-elem works as expected",
fetch-elem(|“fixedType”),
![elem("category"), elem("fixedType")],
!elem(“fixedType”)
)
)

The first test succeeds both in the .ctree and .jar cases, the second test succeeds in the .ctree case and fails in the .jar case (fetch-elem strategy fails).
Initially I thought it might have to do with string sharing, but the first test seems to exclude that.

Tested with Spoofax 0.6.0.2.

Submitted by Tobi Vollebregt on 3 January 2011 at 13:24

On 3 January 2011 at 13:55 Lennart Kats commented:

Note that this is a strange cornercase: your fetch-elem strategy doesn’t scope the x variable, and doesn’t specify whether to first bind both x or first match name. A better strategy may be:


fetch-elem(|name) = fetch(?elem(name); ?x); !x

or


fetch-elem(|name) = getfirst(?elem(name))

As for the inconsistent semantics, it looks like the compiled .jar version first binds and then matches, causing it to fail the second tests. The interpreter first matches and then binds. I’m not sure how ordering is determined here (left-to-right, binding first, …?) but I assume that the .jar version is the “correct” one, as it should correspond to the original compiler.


On 3 January 2011 at 15:20 Tobi Vollebregt commented:

Ah right, thanks! The scoping rules keep biting me occasionally ;-)

At least that solves the issue at hand for me; will still leave this open as it may be good to fix the semantics of the interpreter at some point. (unless this construct has undefined behaviour by design maybe?)


On 3 January 2011 at 22:32 Karl Trygve Kalleberg commented:

We should probably be bug-for-bug compatible with the old strc, but I personally find the match-then-bind to be the most logical (and that might indeed be why the interpreter does it that way).

Would we break the world if we switched to match-then-build?


On 3 January 2011 at 22:45 Eelco Visser commented:

That was my thought too when reading the issue. I guess I defined the desugaring

|[ x@t ]| -> |[ ?x; ?t ]|

It seems natural to invert ?x and ?t. However, there might be some subtle interactions with embedded matches in t. For example,

?x@Foo( x)

would no longer work, since x would be unbound, whereas currently it is bound.

As an experiment you could change the definition and see what breaks; would need to be an extensive test though.

As a reference point: what is the semantics of the operation in Haskell and Scala?


On 4 January 2011 at 11:45 Lennart Kats commented:

I don’t think it’s actually the desugaring though, since the interpreter also works on a desugared ctree. So it must really be that the interpreter gives precedence to matching over binding. The interpreter’s semantics does seem more intuitive, but I’m not sure if it’s worth changing it. Code that relies on the ordering like this is Bad anyway. Breaking Bad code that hasn’t been written yet is a minor nuisance, but breaking all the old Bad code that probably already exists out there seems like a more significant problem.


On 4 January 2011 at 12:37 Eelco Visser commented:

Quite right. I’ll close the issue then.


On 4 January 2011 at 12:37 Eelco Visser closed this issue.

On 5 January 2011 at 11:28 Lennart Kats commented:

Well, it would still be good to fix the interpreter to be consistent with the compiler w.r.t. this issue. I’m moving it to Stratego/XT and reopening it.


On 5 January 2011 at 11:28 Lennart Kats closed this issue.

On 5 January 2011 at 11:28 Lennart Kats moved this issue to issue 848 on project StrategoXT

On 5 January 2011 at 11:29 Lennart Kats tagged moved

Log in to post comments