alma icon indicating copy to clipboard operation
alma copied to clipboard

Disallow using macro expansion to create lexical lookups outside of the code's environment

Open masak opened this issue 6 years ago • 4 comments

After my recent insights in how variable lookup needs to work in injectiles, I've been trying to test whether the rule of "injectile variables are always direct, mainline variables are always lookup" is enough. In doing so, I came up with this code:

my q;

macro m1(expr) {
    q = expr;
}

macro m2() {
    return q;
}

for [1, 2, 3] -> v {
    m1(v);
}

for [4, 5, 6] -> v {
    say(m2());
}

Current 007 outputs 4\n5\n6. I believe it should output 3\n3\n3\n, if it outputs anything.

After some discussion on #perl6, we have tentatively concluded it should probably be an expansion-time error. I'm somewhat relieved at this.

So as things stand, this is a bug because 007 currently allows this when it shouldn't.

masak avatar Oct 05 '18 20:10 masak

I was going to drop in here and say that it fits nicely with the things later described in #410. But then I looked at the example and had to pause a bit.

#410 doesn't mention the thing going on here, but I think it fits well with its world view. The v that's being sent into m1 here is being reintegrated by m2 into another scope... one which can't see that original v declaration. And that should be enough to throw the needed exception.

masak avatar Feb 11 '19 14:02 masak

And that should be enough to throw the needed exception.

Should it, really? Isn't the "can't see the original declaration" criterion the one we wanted to use for regular macro hygiene stuff?

I call bullsh my old self confused (as usual), and I'm back to wanting the behavior of OP to be 3\n3\n3\n.

masak avatar Oct 07 '19 14:10 masak

And that should be enough to throw the needed exception.

Should it, really? Isn't the "can't see the original declaration" criterion the one we wanted to use for regular macro hygiene stuff?

Still don't know whether this is a good idea, but...

...there is one thing that could distinguish the v here from regular macro hygiene stuff. Namely, the v sent to m1 was uniquified as part of macro argument detachment, whereas in regular macro hygiene, variables are uniquified as part of quasiquote detachment.

My current status: happy and a little bit relieved that there actually is a distinction after all (and so it would probably be possible to throw an exception in this case), but not at all sure yet that it's a good idea to make the distinction.

In some sense, there are three types of code:

  • (a) mainline code that hasn't been managed by macros at all;
  • (b) code that originates from inside a quasi;
  • (c) mainline code that was passed through macro processing because it was an "argument" (in a more or less strict sense) to a macro.

If we can distinguish (b)-uniquified variables from (c)-uniquified variables, we might be able to throw an exception only for (c)-uniquified variables that, when re-integrated, can't see their original declaration.

masak avatar Dec 16 '20 06:12 masak

...the rationale for this difference in treatment being that (b)-style code "knows what it's doing" playing with fire^Wdetached lexical lookups, whereas (c)-style code is by its definition hapless, acted-upon, and in all ways an NPC. Allowing (c)-style code to make such an advanced lookup when it's not even privy to macro/quasi technology would be tantamount to letting a bunch of energetic children into a fireworks factory, while handing them a box of matches.

masak avatar Dec 16 '20 07:12 masak