6macros: discussing the finer points of Perl 6 macros, Qtrees, and how to stay sane | irclog: irclog.perlgeek.de/6macros/today
Set by moderator on 28 July 2015.
05:51 cfloare_ joined, masak_ joined 06:03 cgfbee joined 08:23 vendethiel joined
masak_ morning 08:28
ENOFROGGS
was gonna tell him that, with synthetic Qtrees, his use case (of having a macro auto-creating a sub just based on the name) is possible
masak clumsy-ish (since you have to build a Qtree by hand), but possible 08:32
oh, but it gets slightly better because some parts (like the sub body) could be constructed as a quasi
vendethiel yes, but you can't refer to it then, can you? 08:36
masak you can't, but that's arguably a bug. 08:38
that is, stuff injected by unhygienic mechanisms ought to show up as lexically declared things just as much as stuff that was parsed 08:39
this has to happen at injection-time, that is, after the macro returns and we incorporate its Qtree into the mainline Q 08:42
any unhygienic (=contextless) Q nodes that are also declarations (Q::Statement::My, Q::Statement::Constant, Q::Statement::Sub, more in the future) should trigger a *side effect* of registering a lexical in the static scope 08:43
presumably COMPILING:: could work along the same mechanism, actually
vendethiel right 08:45
masak $ perl6 bin/007 -e='macro moo() { return Q::Statement::My { ident: Q::Identifier { name: "foo" }, expr: "James Bond" } }; moo(); say(foo)' 08:48
Variable 'foo' is not declared
vendethiel: if you have the tuit, please file an issue ^
vendethiel done (based off this irclog) 08:53
masak ossum 08:56
this *almost* addresses pdcawley's "can I do sinful things with hidden lexical stuff?" 08:57
except they show up too late, after the code sent as arguments to the macro is already parsed 08:58
which means that still, to `is parsed` our hope we put, in a hand-waving fashion
vendethiel can do stuff like "map({ it * 2 }, xs)" yet? :P 09:02
probably, actually
masak that's exactly the thing I'm talking about 09:06
in my understanding, no 09:07
the reason `is parsed` is needed there is that something needs to intercept the parser and placate it before it reaches the `it` and cries foul
that's not possible yet, IMU
by the way 09:11
I found something interesting as I was building out the `Object { ... }` syntax 09:12
there's one scenario where `Object { ... }` is not identical to `{ ... }`
and that's when you have overridden "Object" lexically
which, 007 being super-liberal about that stuff, is a thing
if you override it with something not-typey, 007 should crash and burn at parse time 09:13
if you define your own lexical class "Object" (not a thing yet), it should use that
in other words, what's in that type slot by default is not simply an identifier "Object" rooted in the current scope 09:14
it's an identifier "Object" rooted in the built-ins scope
that is, the same kind of "lexical dislocation" mechanism that's in play with quasis, is also in play here
not user-exposed (since if you override that slot with anything, you get the default sane lexical semantics), but used by the language itself, at least conceptually 09:15
vendethiel ah, right 09:16
yes indeed, that's exactly the case that doesn't work 09:17
masak yesterday, I implemented `my s = Str { value: "lol" }`, just for fun/consistency :) 09:18
you can even do `my n = None {};`
vendethiel well 09:19
macro mymelt($s) { return Q::Identifier { name: melt($s) } }; 09:20
masak indeed 09:21
vendethiel macro it { mymelt("it") };
macro map($block, $xs) { quasi { for {{{ $xs }}} -> {{{ Q::Identifier { name: "it" } }}} { {{{ $block }}} } }}
masak should we do melt() next, then? should be fairly easy at this point.
vendethiel or something?
masak poners this
ponders* 09:22
oh, right
vendethiel hables espanol? :P
masak :P
no, no hablo 09:23
any kind of parameter, both for blocks and for subs, are also declaration slots
thanks for reminding me
vendethiel right
masak but the `macro it` is not enough
since you're not calling `it` in the map
it needs to be a macro term or something
also, calling a macro from macro it does not mean what you think it means :) 09:24
calling a sub from the macro is probably what you wanted
vendethiel right 09:25
masak interesting: github.com/tomprimozic/type-systems -- news.ycombinator.com/item?id=10639734 09:46
ok, so melt() can go in the setting 09:55
what would an implementation of it look like?
which things can we reasonable melt()?
literals, terms, identifiers, expressions 09:56
and the implementation is really easy: just run .eval($runtime) on the Qtree
after checking that it has a reasonable type, I guess
vendethiel yeah 09:59
10:02 vendethiel- joined
masak another, less cute name for melt() would be val() 10:38
similar in spirit to Perl 6's val() for evaluating "safe things", like literals or constants 10:39
folks, we've now got the melt() built-in 12:28
hope this ups the stakes further to do something cool with 007 macros/quasis/Qtrees :)
vendethiel- val is a no-go. it's far too vague 12:35
I proposed unwrap, I think? 12:36
also, I'm very interested in trying it out, but I'm also very interested in playing skyrim right now :P.
masak aha. :) 12:39
don't let me stop you ;)
I saw the unwrap suggestion (and replied to it) 12:40
it would be an excellent suggestion if it were only literals we were unwrapping
hup -- travis says I broke master...? :/ 12:43
oh yeah, I broke it. big time. 12:44
missing comma :(
pushed the comma 12:45
vendethiel- yes, I remember the issue 12:46
"cute" names would include "inner-value", some kind of CAPS function to indicate it's doing introspection (Ć  la WHAT/WHY/etc) 12:47
meh, inner-value is bad
masak same problem as 'wrap'
er, 'unwrap' 12:48
it's more dynamic than that -- it actually evaluates variables/constants/expressions
hm, it actually runs function calls o.O
hadn't realized
damn, then it's an eval(), basically
vendethiel- of course, it uses the same .eval()
that's pretty powerful *g* 12:49
maybe a *bit too much*
masak yeah, a function call gives access to all the rest
vendethiel- it's basically a BEGIN
masak with a return value, yes
except you can use it later, too, at runtime
what's the discrepancy here? I wanted something like "the thing that can statically evaluate 'safe' values, kind of like for constant folding", but I ended up with a full-blown eval() 12:50
to a first approximation, it should refuse to evaluate function calls
vendethiel-
.oO( ... and now I have two problms )
masak yep :) 12:51
it feels unfair to allow operators but to disallow function calls
vendethiel- i'm not sure it's a good idea to allow operators, even...
..depends
masak aye
vendethiel- maybe foo(BEGIN 3 + 4) works?
means you explicitly tell it to
the difference between getting the AST and the value, at another stage 12:52
masak the reason constant-folding works on operators is that it's guaranteed that those operators are free of certain bad things like side effects
maybe we need to somehow whitelist the built-in operators (and possibly some safe functions too, like abs())
by the way, I'm toying with the idea that an identifier in 007 shouldn't have a string as data, but a declaration, a Q node somewhere 12:53
I'm unsure enough about the idea to want to try it in a branch to see how it pans out
but the notion of "where was this identifier declared" is a pretty central one, and that's what we keep doing with those strings anyway 12:54
damn, I feel silly for not noticing before that handling expressions means handling function calls :) 12:56
vendethiel- well 12:58
when I think about it...
masak ...when you think about it, you're at a loss for words...? :P 13:04
github.com/masak/007/commit/e98bda...5a2c485347 :) 13:12
vendethiel- no, I think it's cool 13:28
we are able to run function calls at BEGIN time
masak I'm not worried that it doesn't work
I'm more worried that I accidentally introduced the full power of eval() into a construct that I intended to be much more limited 13:29
s/that I/because I/
vendethiel- yeah 13:36
but to be honest 13:43
a macro *is* such an eval construct
masak mmh? 14:35
if it were, we wouldn't need melt()
vendethiel- well, it doesn't happen at the same time 14:41
it's not on the same level
masak right 14:48
that's what strangelyconsistent.org/blog/macros...el-is-hard was about :)
vendethiel- right. 14:50
15:16 FROGGS joined
masak FROGGS: hi, good thing you're here! :D 16:11
irclog.perlgeek.de/6macros/2015-11-28#i_11616987 16:12
vendethiel++ pointed out that github.com/masak/007/issues/88 is preventing it from working right now
but it's close. very close!
vendethiel-: umm. injecting a declaration is basically "adding it to the program", so it makes sense that a thing is declared thereby. 16:24
vendethiel-: but what happens if you remove a Q::Statement::My from an existing program?
(at compile time)
vendethiel- wut? 16:25
you mean in a visitor macro? 16:26
masak yeah 16:31
thinking about it, I can see solutions, but it feels like a classical case of "disallowed pending a convincing use case"
basically, you'd run into trouble if the declaration had any downstream consumers 16:32
same deal with, say, renaming a declaration -- or changing it in various other ways
it feels like it fundamentally breaks the lexical model. adding declarations is fine, but changing or removing declarations that may have been used is asking for trouble 16:33
vendethiel- mmmh
yeah
masak (note that I'm all for mutating/removing other types of statements) 16:41
and presumably removing a whole lexical block is fine, even though it contains declarations, etc
in some sense, it feels like -- if you're going to remove the declaration of something you don't want used later, you might as well make a visitor macro that taboos any usage of that declared thing. and we might as well encourage you to do that, since it's saner. 16:45
FROGGS masak: \\o/ 16:54
masak \\o/ 17:03
007 is racing past Rakudo in capabilities pretty quickly at this point 17:04
we've laid the groundwork well
19:44 vendethiel joined
vendethiel so, what's the difference between 21:30
sub foo...; foo;
sorry
macro foo; foo;
VS
sub foo...; BEGIN melt foo; 21:31
er, well, I guess `melt BEGIN foo`
masak melt is for expressions. macros are for all kinds of things! 21:42
the only thing that currently limits macros to mostly expressions is our inability (so far) to break out of the "macros are function calls or ops" mold 21:44
but the other two types are a step towards breaking out of that mold 21:45
hm, maybe we should make the Val::None slots in the Qtree explicit in the lispy AST format 22:12
instead of just, as now, omitting them
though we can't use 'none', because (sensibly) that's a Q::Literal::None 22:13