ruby macros

27 views
Skip to first unread message

rogerdpack

unread,
Jun 2, 2011, 7:41:08 PM6/2/11
to ruby optimization
Hello all. Well mostly caleb, if you're still around.

After seeing mirah macros, I wonder if something like

macro "
<something>.go(<args>)
=>
<something>.go2(<args>)
"

macro "
<something>.andand.go(<args>)
=>
if(_v = <something>)
_v.go(<args>)
end
"

or the like, though I'm not sure how that would work with blocks.
Does ruby macros do this already? It seemed to only work for method
calls?

how would andand be written with ruby macros?

Also I am guessing the "holy grail" of macros is that you can somehow
nest them...I wonder how that could ever look/operate well on.

This feels almost like erb but for ruby code :)
I know so little about them.

Cheers!
-roger-
http://www.mirah.org/wiki/Macros

Caleb Clausen

unread,
Jun 2, 2011, 11:26:28 PM6/2/11
to ruby-opt...@googlegroups.com
On 06/02/2011 04:41 PM, rogerdpack wrote:
> Hello all. Well mostly caleb, if you're still around.
>
> After seeing mirah macros, I wonder if something like
>
> macro "
> <something>.go(<args>)
> =>
> <something>.go2(<args>)
> "

This should work, in git trunk, but doesn't:

macro go(*args)
:( (^receiver).go2(^*args) )
end

* arg to a macro looks like it's broken. guess I gotta make a test case
for that.... in addition, ^* definitely won't work in the current release :(

I hope I can get this to work soon, in git trunk anyway.

> macro "
> <something>.andand.go(<args>)
> =>
> if(_v =<something>)
> _v.go(<args>)
> end
> "

there's an andand.rb in my example/ dir, but it's not really quite the
same as what you have above. (I first saw this in reg braithwaite's
macro library.... I tried to imitate his, but maybe missed the point. In
fact, these mirah macros look a lot like reg's macros-by-example.)

It's not really possible to do andand currently. macros have access to
their args, block, and receiver, but not to subsequent expressions on
the same line, from which they are separated by a dot operator (or any
other operator, for that matter). Such expressions are not (directly or
indirectly) subnodes of the macro callsite node in the unexpanded parse
tree, so it's difficult to see how this could really be accomplished in
my rubymacros given the current design.... Maybe with up-pointers in the
syntax trees, but that's still giving me conceptual headaches, so I
don't know how to implement it.

Really, tho, something like andand should be an operator (and named
differently too). Macro operators have been on my list of features to
add for a long time.

So for example, you'd want:

something andand go(arg1, arg2)
should expand to
if (_v=something)
_v.go(arg1,arg2)
end

with syntax maybe like:

macro operator andand(left,right)
#somehow gotta specify precedence and associativity too of the new
operator, tho

fail unless RedParse::CallNode===right and right.receiver.nil?

action=right.deep_copy
action.receiver=:(_v)

:(
if (_v=^left)
^action
end
)
end

That's klunky by comparison, I realize. Whenever you start referring to
parse nodes, it gets a lot more confusing/involved. For complicated
cases, that may be necessary, but 'simple' things should be simple. This
particular case should be 'simple', and talking directly to node classes
should be avoidable here.....

Maybe I can come up with a better way. Something like forms with reg
expressions in them for the <holes> was what I wanted to do when I last
thought about this....

> Also I am guessing the "holy grail" of macros is that you can somehow
> nest them...I wonder how that could ever look/operate well on.

hmm, define "nest", please.

It should be possible currently to call macros from within macros
(including in the forms returned from macros), to pass macro invocations
as args to macros, and for macros to recursively call themselves (with
the danger of infinite regress, of course).

> This feels almost like erb but for ruby code :)
> I know so little about them.

Not a bad analogy at all. The resemblance is closer in the mirah
examples you give above and reg's macros-by-example thing. (Wish I could
remember the name....)

> http://www.mirah.org/wiki/Macros

I will queue this up for careful perusal.


PS: I am going to respond to your previous email too. I just haven't had
any time to look into it at all. (Just warning you, I might not be able
to do anything about it.......)

Roger Pack

unread,
Jun 2, 2011, 11:42:42 PM6/2/11
to ruby-opt...@googlegroups.com
Interesting. Actually my current thoughts were somewhat inspired by
redparse's unparse, which has access to "left and right" or what not.
That was fun :)
-roger-

Caleb Clausen

unread,
Jun 3, 2011, 1:41:27 PM6/3/11
to ruby-opt...@googlegroups.com
On 06/02/2011 08:42 PM, Roger Pack wrote:
> Interesting. Actually my current thoughts were somewhat inspired by
> redparse's unparse, which has access to "left and right" or what not.
> That was fun :)
> -roger-

Yeah, for operators. But I guess dot isn't exactly treated like an operator.

the parse tree for
something.andand.go(args)
looks like this:
+Call name="go"
+receiver: Call name="andand"
+receiver: Call name="something"
+params:
+Call name="args"

if you make andand into a macro, it can 'see' the nodes below it in the
parse tree. That is to say, it 'sees' this portion of the tree:
+receiver: Call name="andand"
+receiver: Call name="something"

But go, and its args, are above (or beside, anyway not below) it in the
parse tree, so andand cannot 'see' them. Not right now, anyway.

Hope that makes sense.

Reply all
Reply to author
Forward
0 new messages