Skip to content

Instantly share code, notes, and snippets.

@masak
Created January 16, 2018 10:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masak/4ed7ec0fe455b5e70c0f52eb20cb113a to your computer and use it in GitHub Desktop.
Save masak/4ed7ec0fe455b5e70c0f52eb20cb113a to your computer and use it in GitHub Desktop.
Privmsg explaining setting the OUTER of macro arguments
12:40 <masak> I feel I have finally made some (conceptual) progress with the thing blocking `macro infix:<ff>`
12:40 <masak> I'm now hoping a piece of undisturbed time will manifest so that I can implement it
12:41 <masak> it's not an easy thing, but it's necessary
12:44 <sergot> what's the progress ?
12:44 <sergot> I mean, what is the problem?
12:45 <masak> here's an illustration of the problem, with a minimal program:
12:45 <masak> macro moo(y) { my x = 1; return quasi { say(x); say({{{y}}}) } }; my z = 2; moo(z)
12:46 <masak> take your time -- what should it output?
13:05 <sergot> hmm
13:05 <sergot> 1\n2?
13:05 <masak> correct
13:05 <masak> ...why? :)
13:06 <sergot> x is obvious, because in this scope we have x = 1; {{{y}}} because it evaluates the argument, which is 2
13:06 <sergot> I don't know if this is the answer you expect :P
13:06 <masak> it is
13:07 <masak> but the mechanics to get it to work is a bit messier than that
13:07 <masak> it's supposed to be hidden from you, so your answer is fine :)
13:08 <sergot> what's behind the scenes?
13:15 <masak> ok, so
13:15 <masak> conceptually, we like to think of the things that happen on the code-text level, like so:
13:15 <masak> 1. mark `z`, Ctrl+C
13:16 <masak> 2. mark `{{{y}}}`, Ctrl+V
13:16 <masak> 3. mark the whole inside of the quasi (with `{{{y}}}` now replaced by `z`), Ctrl+C
13:16 <masak> 4. mark `moo(z)`, Ctrl+V
13:16 <masak> so the resulting code after the macro becomes `my z = 2; say(x); say(z);`
13:17 <masak> waiting for you to nod :)
14:03 <sergot> reading
14:03 * sergot nods
14:18 <masak> :)
14:19 <masak> of course, if copy-pasting were all there is to it, the code would not run
14:19 <masak> because `x` is not in scope in the mainline
14:19 <masak> I'm gonna use a special symbol here to demonstrate what happens instead
14:20 <masak> `my z = 2; ⟦say(x); say(⦃z⦄);⟧`
14:22 <masak> those ⟦⟧ mean "use the injectile's scope" (recall, the injectile is the thing that's copied from the quasi
block)
14:22 <masak> and the ⦃⦄ mean "use the macro argument's scope" (that is, the mainline)
14:23 <masak> this is typical of a macro expansion/injection: needing to switch into the macro's/quasi's scope, and then
back into the mainline's scope here and there
14:25 <masak> I guess you can see that we need ⟦⟧ in order to see `x`, and ⦃⦄ in order to (again) see `z`
14:27 <masak> the past few weeks I've been thinking about how to get the ⦃⦄ to work
14:36 <masak> the main problem is that, at the time the macro runs, there is only one mainline scope: the static one. and
that's the wrong one.
14:36 <masak> to make that clear, if we don't do anything about that, the output would be "1\nNone\n"
14:37 <masak> because at compile time, the value of `z` is None
14:37 <masak> that's clearly wrong -- the output *should* be "1\n2\n", like you said
15:17 <masak> what needs to happen is: as we enter the mainline at runtime, the ⦃z⦄ thing needs to refresh so that it gets
the runtime-mainline's scope as its new OUTER
15:18 <masak> then the `z` lookup will find the `z` with the 2 in it
15:18 <masak> presto, everyone's happy
15:28 <masak> the recent breakthrough I had is I figured out how to do that refresh of the ⦃z⦄
15:30 <masak> basically, the situation is quite similar to what would be needed here:
15:32 <masak> sub foo(x) { my y = x + 1; sub bar() { say(y) }; return bar }; say(foo(10)()); say(foo(20)());
15:33 <masak> there's only one sub `bar` in the code, but there are two *values* of `bar`, one for each call to `foo`
15:33 <masak> every time we enter `foo`, we need to "refresh" `bar` so that it points to the OUTER frame we just created as
we entered `foo`
15:34 <masak> ...that's all :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment