-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scope-related mishap in 'my' declaration in quasi #212
Comments
Found a simpler case. The anon sub was not necessary:
|
Bisecting this one was hard. Partly because Rakudo changed semantics recently (see cbc2ee2), and so I needed to float a stash down the bisect. But the (tentative) conclusion of the three bisects I did was that this never worked. We never had a revision of 007 where the above did what we wanted. Which surprises me a little, actually. I was pretty sure we did. |
Weak evidence it never worked: ...and sure enough, it's the assignment that blows up, not the
|
The parameter to the macro is not necessary either:
Here's the rule for the
Note the |
I'm staring at the implications of this issue and slowly coming to the conclusion that Why? Because the Need to test this in a branch. First introducing the block into Might also be a good idea to make sure that things related to static lexpads (such as |
Making some headway. I just pushed a branch some-quasi-mishap-debugging which has one static-lexpad fix and some debug statements. On the simple breaking example above, I get this:
I feel like a less tired version of me might be able to look at that and figure out where some scoping or other goes wrong. For now, I'll just note that |
Whee. If I make this change:
Then the simple breaking example:
doesn't die with the
Also, the same change applied to This is complex, and I'm no less tired today. |
All of the test failures boil down to the same problem, golfed here to remove inessentials:
(Actually, that golf is quite literally the failing test in |
Let's analyze this. - return $thing.new(:name($thing.name), :frame($runtime.current-frame))
+ return $thing.new(:name($thing.name))
if $thing ~~ Q::Identifier; In order to fix the present issue, it seems we need to make this change. Making the change causes four test failures related to hygienically finding variables from the quasi's environment. I think that the (Parenthetical remark: we still don't have a word yet for "the code produced by injecting into the mainline the Qtree returned from a macro (typically produced by a quasi)". Note that this code is not the quasi code itself. It can't be, since a quasi is code-with-holes-in-it. Interpolating the quasi to produce a concrete code block means deep-cloning the quasi completely, filling the holes. Since we still don't have a good word for this, let's for the duration of this issue comment coin a silly one: "conifaq", or "concrete code interpolated from a quasi". Korzybski would be proud.) Stating our goals:
Hygiene could be defined as the first two goals together. It would seem to me that the Here, let me show you what I mean:
The first one should print The pathology can be summarized as "attach all identifiers in the quasi (regardless of depth) to the scope outside the quasi (typically the macro's scope)". This is wildly, hilariously wrong. The
I'd just like to point out that |
As to achieving goal 1 the right way: one thing I've come to understand at depth since 2015 can be summarized like this:
(Hey, we'd better come up with a decent alternative to the silly term before it spreads.) Let's unpack this.
Ok, but what does it matter? Mainly because of this: when we parse a program, we also do a lot of work to prepare an AST for being run later. Most importantly, blocks are entered, variables are declared, static lexpads are built. This needs to happen for synthetic blocks too; logically, the only time to do it is as they are injected into the mainline. I posit that doing so would give us all of goal 1 without the |
Oh, and hey: instead of "conifaq", I propose we call the thing an injection:
|
Or injectile. It's more noun-y than "injection", and it's analogous with "projectile", something that is projected. |
Branch Still, that's rather encouraging. |
s/assignment protocol/location protocol/ Also add #212, because it's an irritating near-term blocker.
This takes care of a particular case of #212. It seems that checking simply wasn't happening for non-blocks, although it should.
We didn't have function terms until 5865342, and the check function apparently never dove into them. Now that it does, it allows the initial reported wrong line of #212 to run just fine: $ bin/007 -e='macro moo(x) { return quasi { (func() { my y = {{{x}}} })() }; }; say(moo(42))' 42 I think #212 can be closed now, but going to have a look around and try to run everything in it, and also check out #207 which I know was affected by this, and also think through what check might be missing.
This one (the original bug report of this issue) now works:
The shorter/golfed cases also work (but don't output anything when they do):
Lexical scoping now works from the injectile to the macro:
Including the two cases constructed to demonstrate the pathology — which now show the expected behavior:
I see nothing further that needs fixing in this issue. Closing. |
While testing out #151 (which remains closed), I found the following:
My guess is that something gets out of kilter with the scopes of sub terms. (The rest of this paragraph was removed since it consisted entirely of various ways to phrase "with such an easy-to-exhibit bug, how hard can it be to fix?". As everyone in IT knows, actually uttering this phrase is a surefire way to curse yourself to horrible, nigh-unfixable bugs.)
The text was updated successfully, but these errors were encountered: