Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: {Perl6} Macros and native compilation

by rg0now (Chaplain)
on Apr 11, 2005 at 10:19 UTC ( #446549=note: print w/ replies, xml ) Need Help??


in reply to {Perl6} Macros and native compilation

Since I was just into A6 when I read your question, I wanted to write up a nice tutorial on Perl 6 macros for you. But I ended up just repeating the original text, so I decided to copy-paste here the relevant parts instead:

Macros

A macro is a function that is called immediately upon completion of the parsing of its arguments. Macros must be defined before they are used--there are no forward declarations of macros, and while a macro's name may be installed in either a package or a lexical scope, its syntactic effect can only be lexical, from the point of declaration (or importation) to the end of the current lexical scope.

Every macro is associated (implicitly or explicitly) with a particular grammar rule that parses and reduces the arguments to the macro. The formal parameters of a macro are special in that they must be derived somehow from the results of that associated grammar rule. We treat macros as if they were methods on the parse object returned by the grammar rule, so the first argument is passed as if it were an invocant, and it is always bound to the current parse tree object, known as $0 in Apocalypse 5. (A macro is not a true method of that class, however, because its name is in your scope, not the class's.)

Update: That's now the $/ object. $0 has been "demoted" to being the entire matched string.

...

A macro can do anything it likes with the parse tree, but the return value is treated specially by the parser. You can return one of several kinds of values:

  • A parse tree (the same one, a modified one, or a synthetic one) to be passed up to the outer grammar rule that was doing pattern matching when we hit the macro.
  • A closure functioning as a generic routine that is to be immediately inlined, treating the closure as a template. Within the template, any variable referring back to one of the macro's parse parameters will interpolate that parameter's value at that point in the template. (It will be interpolated as a parse tree, a string, or a number depending on the declaration of the parameter.) Any variable not referring back to a parameter is left alone, so that your template can declare its own lexical variables, or refer to a package variable.
  • A string, to be shoved into the input stream and reparsed at the point the macro was found, starting in exactly the same grammar state we were before the macro. This is slightly different from returning the same string parsed into a parse tree, because a parse tree must represent a complete construct at some level, while the string could introduce a construct without terminating it. This is the most dangerous kind of return value, and the least likely to produce coherent error messages with decent line numbers for the end user. But it's also very powerful. Hee, hee.
  • An undef, indicating that the macro is only used for its side effects. Such a macro would be one way of introducing an alternate commenting mechanism, for instance. I suppose returning "" has the same effect, though.

A macro by default parses any subsequent text using whatever macro rule is currently in effect. Generally this will be the standard Perl::macro rule, which parses subsequent arguments as a list operator would--that is, as a comma-separated list with the same policy on using or omitting parentheses as any other list operator. This default may be overridden with the "is parsed" trait.

...

If there is no signature at all, macro defaults to using the null rule, meaning it looks for no argument at all. You can use it for simple word substitutions where no argument processing is needed. Instead of the long-winded:

my macro this () is parsed(/<null>/) { "self" }
you can just quietly turn your program into C++:
my macro this { "self" }
A lot of Perl is fun, and macros are fun, but in general, you should never use a macro just for the fun of it. It's far too easy to poke someone's eye out with a macro.

Now, it's up to you to decide, how this compares to LISP et co.

rg0now


Comment on Re: {Perl6} Macros and native compilation
Select or Download Code
Re^2: {Perl6} Macros and native compilation
by spurperl (Priest) on Apr 11, 2005 at 11:37 UTC
    It sounds really good, just one thing is unclear...

    When the macro body is a string that is "shoved back into the input and reparsed", can I ask which variables to evaluate and which not ? I.e.

    my macro this {"self{$foo}"}

    Will $foo be interpolated/evaluated at compile-time, when the macro is expanded, or at runtime, in the context of the macro's usage ? In Lisp, using special syntax you can have both, which is very, *very* powerful.

      In my understanding, you absolutely can do this with Perl 6 macros. If you want $foo to be avaluated at compile time, you just return a string as you did. Contrariwise, if you return a closure (maybe using the simple my macro this { self{$foo} } syntax?), you get "a generic routine that is to be immediately inlined, treating the closure as a template", such that "any variable not referring back to a parameter is left alone, so that your template can declare its own lexical variables, or refer to a package variable". This way, $foo will be evaluated at runtime...

      But, as always with Perl 6, don't take my words for granted...:-)

      rg0now

      I'd say you'd have to use single quotes, e.g.:

      my macro this { 'self{$foo}' }

      I don't think rg0now's idea will work, because $foo would refer to some outer $foo. If my understanding is correct, you can do things like the following:

      my $compilation_time = BEGIN { time }; macro uptime { time - $compilation_time } # And then... say "$*PROGRAM_NAME has been running for {uptime} seconds.";

      (Update: Doing s/macro/sub/ here would work just fine, too.)

      But, as rg0now said, that may be wrong, of course.

      --Ingo

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://446549]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2014-07-12 13:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    When choosing user names for websites, I prefer to use:








    Results (240 votes), past polls