(Followup: http://arclanguage.org/item?id=15659, http://arclanguage.org/item?id=15907) Wart now supports apply on macros -- as long as they are implemented using backquote syntax. I'm still in dread that some show-stopper bug will refute my solution. But if it holds up, this makes macros 'even more first-class'. And it puts Kernel to the question; without quote, Kernel can't use this solution, so it can't use apply with operatives, and so its fexprs are less powerful. === How it works Here's the problematic test macro and call from the previous thread: (mac foo(a b) `(cons ,a ,b))
(foo @'(11 (12 13)))
@ is wart's version of apply. I'm going to take you inside my interpreter from a few days ago to see what used to happen to this call: eval: (foo @'(11 (12 13)))
after splice: (foo 11 (12 13))
eval: (eval ((fn nil `(cons ,a ,b))) caller-scope)
evalArgs: ((fn nil `(cons ,a ,b)))
eval: `(cons ,a ,b)
eval: b
lookup: b => (12 13)
eval: a
lookup: a => 11
eval: (cons 11 (12 13))
evalArgs: (12 13)
Error: 12 is not a function
Today we instead see the following sequence of events: eval: (foo @'(11 (12 13)))
after splice: (foo ''11 ''(12 13)) a)
eval: (eval ((fn nil `(cons ,a ,b))) caller-scope)
evalArgs: ((fn nil `(cons ,a ,b)))
eval: `(cons ,a ,b)
eval: b
lookup1: b => ''(12 13) c)
eval: a
lookup1: a => ''11
eval: (cons ''11 ''(12 13))
evalArgs: ''(12 13)
lookup0: $y => (12 13) b)
There are 3 changes:a) When splicing a list, we tag its elements[1] with ''. That's two single-quotes. (... @'(a b)) -> (... ''a ''b)
'' is an internal detail. The reader provides no way to type it in. If you ever see it printed at the REPL, that's a bug. I recommend pronouncing it as 'already evaluated'.b) When a function evals its args, '' behaves just like ' -- it suppresses evaluation of that arg. The interpreter's evalArgs strips the '' and provides the function body with the quoted value. The final lookup0 lines show this situation in action. This is the default, and it ensures '' is usually quickly consumed. [2] c) However, within a comma expression evalArgs passes '' without stripping it out. The lookup1 lines above show this situation. As a result, '' in macro arguments ripple through until they exit the macro. This prevents (12 13) above from being evaluated as a function call. [3] === Details More tests: http://github.com/akkartik/wart/blob/d863ad0748/030.test#L8 This change costed[4] me 30 LoC[5]. However that underestimates the complexity costs; eval now has an additional parameter to indicate when it's being called within a comma expression. So far I've been focused on just getting this working; now I'll spend some time reclaiming spaghetti. [1] http://github.com/akkartik/wart/blob/a345f64d24/008eval.cc#L85. Why not just tag its elements with quote? http://news.ycombinator.com/item?id=4038195. [2] http://github.com/akkartik/wart/blob/a345f64d24/007scope.cc#L131 [3] http://github.com/akkartik/wart/blob/a345f64d24/008eval.cc#L272. The final 'true' argument suppresses '' stripping. [4] http://akkartik.name/blog/28672493 [5] git diff --stat c7068c0a85 d863ad0748 *.cc (skipping extra tests) |