Google 網路論壇不再支援新的 Usenet 貼文或訂閱項目,但過往內容仍可供查看。

Macro arguments themselves

瀏覽次數:9 次
跳到第一則未讀訊息

Luke Palmer

未讀,
2003年8月2日 下午3:18:012003/8/2
收件者:perl6-l...@perl.org
While we seem to be on the subject of hashing out macro semantics,
here's a question I've had awhile.

What do macros do about being passed variables?

Let's say I make a C<square> macro:

macro square ($x) {
{ $x * $x }
}

And then I have code.

my $var = 10;
print square $var;

Does that turn that into (at compile time):

print($var * $var);

Or does it use the compile time value of $x, turning it into:

print(undef * undef);

I would hope the former. However, what about this compile-time
integral power macro[1]?

macro power ($x, $p) {
if $p > 0 {
{ $x * power($x, $p-1) }
}
else {
{ 1 }
}
}

That would hopefully turn:

my $var = 10;
print power $var, 4;

Into

print($var * $var * $var * $var * 1);

But what about

my $var = 10;
my $ex = 4;
print power $var, $ex;

Thanks.

Luke

[1] That one's kind of interesting actually. If the macro is called
right upon parsing it, it will be called before it's done compiling
it. Which is a problem. Is there a way to get around this, because
recusive macros are useful (as demonstrated above).

Luke

Larry Wall

未讀,
2003年8月2日 下午4:07:552003/8/2
收件者:perl6-l...@perl.org
On Sat, Aug 02, 2003 at 01:18:01PM -0600, Luke Palmer wrote:
: While we seem to be on the subject of hashing out macro semantics,

: here's a question I've had awhile.
:
: What do macros do about being passed variables?
:
: Let's say I make a C<square> macro:
:
: macro square ($x) {
: { $x * $x }
: }
:
: And then I have code.
:
: my $var = 10;
: print square $var;
:
: Does that turn that into (at compile time):
:
: print($var * $var);
:
: Or does it use the compile time value of $x, turning it into:
:
: print(undef * undef);
:
: I would hope the former.

It's the former. The block is essentially inlined.

: However, what about this compile-time


: integral power macro[1]?
:
: macro power ($x, $p) {
: if $p > 0 {
: { $x * power($x, $p-1) }
: }
: else {
: { 1 }
: }
: }
:
: That would hopefully turn:
:
: my $var = 10;
: print power $var, 4;
:
: Into
:
: print($var * $var * $var * $var * 1);

Nope. $x and $p are syntax trees. If you want compile-time evaluation
you'd have to do something explicit in there to evaluate $p:

macro power ($x, $p) {
my $count = $p.run();
if $count > 0 {
$count--;
{ $x * power($x, $count) }
}
else {
{ 1 }
}
}

That might be reducable to:

macro power ($x, $p is run) {
if $p > 0 {
$p--;
{ $x * power($x, $p) }
}
else {
{ 1 }
}
}

But you can't decrement $p inside the block, or it just becomes part of
the inlined code.

: But what about


:
: my $var = 10;
: my $ex = 4;
: print power $var, $ex;

Depends on how power is written. Can't have it both ways unless power is
written to finesse it somehow.

: [1] That one's kind of interesting actually. If the macro is called


: right upon parsing it, it will be called before it's done compiling
: it. Which is a problem. Is there a way to get around this, because
: recusive macros are useful (as demonstrated above).

I suppose one could defer the expansion of a nested macro till it's
called for real. That might mean that we need an explicit keyword
on the block though to suppress immediate expansion:

macro power ($x, $p is run) {
if $p > 0 {
$p--;
template { $x * power($x, $p) }
}
else {
template { 1 }
}
}

Alternately, we just defer the expansion of any declared but undefined
macro till it is defined somehow. That would presumably handle
mutually recursive macros even.

Those are both hard. Unless someone volunteers to implement it,
we could just say that you have to write a helper sub if you want
recursion.

Larry

Benjamin Goldberg

未讀,
2003年8月2日 晚上11:52:022003/8/2
收件者:perl6-l...@perl.org
Larry Wall wrote:
[snip]

> Nope. $x and $p are syntax trees.

<blink>

Macros are passed syntax trees as arguments, but return coderefs?

That's... odd.

I would expect that a macro would be expected to *return* a syntax
tree... which could then undergo (more) macro-expansion.

Sortof like how in lisp, a macro recieves lists as arguments (those
lists being un-evaluated code) and then returns a list, which then has
more macro expansion done on it, and then gets parsed and evaluated.

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Luke Palmer

未讀,
2003年8月3日 凌晨12:58:432003/8/3
收件者:ben.go...@hotpop.com、perl6-l...@perl.org
> Larry Wall wrote:
> [snip]
> > Nope. $x and $p are syntax trees.
>
> <blink>
>
> Macros are passed syntax trees as arguments, but return coderefs?
>
> That's... odd.
>
> I would expect that a macro would be expected to *return* a syntax
> tree... which could then undergo (more) macro-expansion.

Keep in mind, a macro can return a lot of things to get a lot of
different behavior. It can return a string which will be inserted in
the input stream in place of the macro call; it can return a closure
which will be inserted into the generated code at that point. Along
the same lines, you can return a syntax tree to be inserted into the,
um, syntax tree at that point.

Perhaps with C<template>, as Larry mentioned earlier (though I'm not
sure that he intended this meaning):

template { $x + 1 }

Would return a syntax tree for $x + 1. Obviously, the syntax tree
would have to be closure-like, because the string '$x' isn't enough to
represent this $x. It would have to keep some sort of reference to
the lexical... or lexical table entry... or something.

And indeed, that would solve the macro recursion bit, if the
just-inserted syntax tree underwent more macro expansion.

Luke

Alex Burr

未讀,
2003年9月12日 上午11:43:582003/9/12
收件者:perl6-l...@perl.org
fibo...@babylonia.flatirons.org (Luke Palmer) writes:

> I would hope the former. However, what about this compile-time
> integral power macro[1]?
>
> macro power ($x, $p) {
> if $p > 0 {
> { $x * power($x, $p-1) }
> }
> else {
> { 1 }
> }
> }
>
> That would hopefully turn:
>
> my $var = 10;
> print power $var, 4;
>
> Into
>
> print($var * $var * $var * $var * 1);
>

The complete answer to this would be partial evaluation. Partial
evaluators exist for langauges such as lisp, ML, and even C. See
http://www.dina.dk/~sestoft/pebook/pebook.html

A partial evaluator simplifies a function with respect to some of its
inputs, if possible. This can be quite powerful: If P is a partial
evaluator, I an interpreter, and C some code, the P(I,C) compiles C
(in a rudimentary sort of way) and P(P,I) produces a compiler. But
code has to be written with an eye to making it possible to simplify it,
otherwise you just get the original code back.

In theory you could write one as a perl6 macro, although it would be
more convenient if there was someway of obtaining the syntax tree of a
previously defined function other than quoting it (unless I've missed
that?).
But I confidently predict that no-one with write a useful partial
evaluator for perl6. The language is simply too big.

Alex


Luke Palmer

未讀,
2003年9月12日 下午3:42:222003/9/12
收件者:Alex Burr、perl6-l...@perl.org
Alex Burr writes:
> In theory you could write one as a perl6 macro, although it would be
> more convenient if there was someway of obtaining the syntax tree of a
> previously defined function other than quoting it (unless I've missed
> that?).

There is a large class of cool optimizations possible when you combine
notifications with storing the syntax tree at runtime, so I think it
will be possible to get the syntax tree of a previously defined
function. Probably just a method on Code objects.

> But I confidently predict that no-one with write a useful
> partial evaluator for perl6. The language is simply too big.

Then again, there are some very talented people with a lot of free time
in the Perl community; I wouldn't count it out.

Luke

Mark A. Biggar

未讀,
2003年9月12日 下午3:49:472003/9/12
收件者:perl6-l...@perl.org

As it is currently defined the default "is parsed" trait includes
evaluating the arguments before the marco is called, so the above
macro doesn't do what you want with out adding some magic.

One way to do what you want is to use a string returning macro with
an "is parsed" trait that return the unevaluated args as strings and
then concat up the string for the expression you want.

Another possibility is a built-in trait orthoginal to "is parsed"
that turns off argument evaluation and allow the args to be passed
in as syntax trees, allowing the macro to built the syntax tree
to be returned.

I imagine that by the time all is done there will be a whole set
if trait definitions to make various types of macros easy to do.
Which brings us back to the need for a way to bundle up a set of
traits and give it a name.


--
ma...@biggar.org
mark.a...@comcast.net


Austin Hastings

未讀,
2003年9月12日 下午4:05:502003/9/12
收件者:Luke Palmer、Alex Burr、perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> Alex Burr writes:

> > But I confidently predict that no-one with write a useful
> > partial evaluator for perl6. The language is simply too big.
>
> Then again, there are some very talented people with a lot of free
> time in the Perl community; I wouldn't count it out.

That looked to me like a "Damian troll", hoping that DC would pop up
and say, "Oh, no. It can be done in six lines of P6. See: ..."

=Austin

Alex Burr

未讀,
2003年9月12日 下午6:40:042003/9/12
收件者:perl6-l...@perl.org

I admit that last bit was tonge in cheek.:-) I
don't want to impune anyone's talent. But seriously,
I think it would be a lot of work.

Alex

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

Piers Cawley

未讀,
2003年9月15日 凌晨4:26:082003/9/15
收件者:Luke Palmer、Alex Burr、perl6-l...@perl.org
Luke Palmer <fibo...@babylonia.flatirons.org> writes:

> Alex Burr writes:
>> In theory you could write one as a perl6 macro, although it would be
>> more convenient if there was someway of obtaining the syntax tree of a
>> previously defined function other than quoting it (unless I've missed
>> that?).
>
> There is a large class of cool optimizations possible when you combine
> notifications with storing the syntax tree at runtime, so I think it
> will be possible to get the syntax tree of a previously defined
> function. Probably just a method on Code objects.

I'll be very disappointed if you can't get the syntax tree at
runtime, though I have the feeling that it might require a
compilation switch of some sort.

Piers Cawley

未讀,
2003年9月15日 凌晨4:26:372003/9/15
收件者:Austin_...@yahoo.com、Luke Palmer、Alex Burr、perl6-l...@perl.org
Austin Hastings <austin_...@yahoo.com> writes:

No fair trolling someone when he's on holiday.

Dan Sugalski

未讀,
2003年9月15日 上午9:50:192003/9/15
收件者:Piers Cawley、Luke Palmer、Alex Burr、perl6-l...@perl.org

The syntax tree will be stored by default, though it will be strippable
from the bytecode files for space and/or paranoia reasons.

Dan

Larry Wall

未讀,
2003年9月25日 晚上10:43:092003/9/25
收件者:perl6-l...@perl.org
: >fibo...@babylonia.flatirons.org (Luke Palmer) writes:
: >
: >
: >>I would hope the former. However, what about this compile-time
: >>integral power macro[1]?
: >>
: >> macro power ($x, $p) {
: >> if $p > 0 {
: >> { $x * power($x, $p-1) }
: >> }
: >> else {
: >> { 1 }
: >> }
: >> }

Note that you have to explicitly return a closure, otherwise they look like
bare blocks. Which might accidentally do what you want, if $x knows how
to be a number, and any return value that's not a closure gets coerced to
string. But it wouldn't be doing what you think it's doing.

: >>That would hopefully turn:


: >>
: >> my $var = 10;
: >> print power $var, 4;
: >>
: >>Into
: >>
: >> print($var * $var * $var * $var * 1);

: >>

: Alex Burr wrote:
: >The complete answer to this would be partial evaluation. Partial


: >evaluators exist for langauges such as lisp, ML, and even C. See
: >http://www.dina.dk/~sestoft/pebook/pebook.html

I tend to think of it inside out from that, in terms of deferred
evaluation of the parts that are known to be still undefined.
Note that we can know how to parse a macro from its declaration even
before we know how to call its body, so we can tell easily when we
hit power() that it can parse but can't run yet.

: >A partial evaluator simplifies a function with respect to some of its


: >inputs, if possible. This can be quite powerful: If P is a partial
: >evaluator, I an interpreter, and C some code, the P(I,C) compiles C
: >(in a rudimentary sort of way) and P(P,I) produces a compiler. But
: >code has to be written with an eye to making it possible to simplify it,
: >otherwise you just get the original code back.
: >
: >In theory you could write one as a perl6 macro, although it would be
: >more convenient if there was someway of obtaining the syntax tree of a
: >previously defined function other than quoting it (unless I've missed
: >that?).
: >But I confidently predict that no-one with write a useful partial
: >evaluator for perl6. The language is simply too big.

On Fri, Sep 12, 2003 at 12:49:47PM -0700, Mark A. Biggar wrote:
: As it is currently defined the default "is parsed" trait includes


: evaluating the arguments before the marco is called, so the above
: macro doesn't do what you want with out adding some magic.

I don't think it evaluates unless you tell it to explicitly.

: One way to do what you want is to use a string returning macro with


: an "is parsed" trait that return the unevaluated args as strings and
: then concat up the string for the expression you want.

Shouldn't be a problem--the arguments are pattern match result objects
that can behave as strings if you want them to.

: Another possibility is a built-in trait orthoginal to "is parsed"


: that turns off argument evaluation and allow the args to be passed
: in as syntax trees, allowing the macro to built the syntax tree
: to be returned.

That's the default. You'd need to use .run or some such to execute
a chunk of syntax tree. Remember that the definition of eval($str)
is something like $str.parse.run. I suppose evalharder($str) would
be $str.parse.optimize_the_heck_out_of.run. :-)

: I imagine that by the time all is done there will be a whole set


: if trait definitions to make various types of macros easy to do.
: Which brings us back to the need for a way to bundle up a set of
: traits and give it a name.

If we work it right, that's just called a "module". I think of traits
as funny class definitions, and we're already planning to be able to
bundle related classes in a module. Could go so far as to have derived
modules that can retarget an entire collection of classes in parallel.

Larry

0 則新訊息