On Sat, 2002-03-30 at 21:41, Michel J Lambert wrote: > > > Too late. I'm going there... :) > > Good for you. I was hoping transformations could make it :) > > Why didn't you chime in support before, then? I feel like Aaron and I are > the only ones who are opinionated on this matter...
Hopefully, this has been a productive debate, and I'm not just sucking up bits on everyone's disk. I tend to assume that when a small number of people are debating on a mailing list that the others who are reading are in agreement with one (or more?) of the stated opinions. > > Here's something I was wondering. Say you wanted to write a pow() macro > > (from a previous example) that would forward to C's pow() unless the > > exponent was an integer, in which case it would optimize to many *'s. If > > it was called like so: > > > > pow(2.718, 2 * 6 / 3) > > Yeah, this is part of the problem of scheduling transformations. I believe > it was mentioned to be NP-complete in the literature I read, but so are > most compiler optimizations, and compilers usually use heuristics, so this > problem shouldn't be unsolveable. > > As Nick said in a different email, this particular constant-folding > problem can be solved by using a bottom-up approach. > > 2*pow(2.718,2*6); > > 2*6=>12 > pow(2.718,12)=>constant > 2*whatever=another constant It sounds like you're proposing that a macro be executed the way the peephole optimizations in GCC's RTL are executed (GCC is about the only other compiler that I know as well as Perl, so pardon the forced example). This has some merit, and I don't want to discount the idea. However, I see the following problems that we would have to resolve: 1. The programmer is thinking in Perl (we hope!), but at the stage of transformation that you're discussing, they will have to manipulate Perl's internal form which may be structured counter-intuitively to a Perl programmer. 2. As others have pointed out, a good deal of the magic of Perl is performed at the syntax, not the grammar level (unlike, for example, LISP). In order to resolve these, I think we'd have to drop down to concrete examples of implementation. What do you see this sort of macro looking like? > The problem comes in when we allow additions to these transformations. Say > we have a simple arithmetic constant-folding transformation that handles > the operators. The pow operator, when we 'use' it from some module, would > import the pow() constant-folding transformation, or somesuch. It's a bit > of a contrived example since pow() will probably be included by default, > and not be imported, but I think the scenario is still a valid one. We're speaking about how we manipulate Perl and do the same sorts of things that the Perl compiler is doing, so I see your example as ideal (if not practical). So, let me see if I can get a handle on how your pow might work: macro pow($a,$b) { if ($b.is_constant() && int($b) == $b) { my $func = sub { 1; }; for(my $i = 0;$i<$b;$i++) { $func = sub { $func.() * $a }; } return $func; } else { return \&CORE::pow; } } I'm not 100% happy with the syntax, but I think it's pretty clear as an example. First off, there's some things here which look like normal Perl but aren't so they should be explained: * $a and $b are not plain scalars. They are objects which represent the operands to pow(). When evaluated in a numerical context, we try to peer into $b and determine its value, but undef might be a valid response. Thus, the test for is_constant. * Since we're building an anonymous function during compilation, we expect automatic inlining to take place after macro transformation. Thus our return value for "pow(3,2)" would be: sub { (sub { (sub { 1; } ).() * $a}).() * $a} But we expect Perl to transform this into: sub {1*$a*$a} via inlining and then to inline this subroutine where the macro is being evaluated. At that stage, Perl will have to root through the tree that it's injecting and pull out any macro operand objects and replace them with the variables that they represent. Thus "pow(3,2)" should become "9" after macro expansion and optimization. So, think this will handle your case of: my $y = 0; forall(my $x, @list, sub{$y += $x}); Though the handling of "my $x" gets a little hairy, and puts some requirements on macro evaluation that may turn out to be cumbersome. What I guess I'm saying is that I think I get it. So, what have we bought? We're not using string handling to build code, and that makes me happier. But, how much value does this add to the language, really? > If we have these two different constant-folding transformations, no > ordering of them can solve the one I just presented. They need to be > applied in an interleaved manner. > > In the worst case, after every transformation, the entire tree needs to be > rechecked for every possible transformation. In this case, these > transformations depend *only* on the nodes and subnodes, so we can limit > the scope of where we have to re-check these constant-folding operations. > If we define a constant-folding transformation category, then we can limit > the checks to just those category of transformations. Now I'm growing concerned. It sounds to me like macro authors would have a very hard time determining exactly how their macros will be applied. > PS: Yes, I know I write too much. :) Your vision of the internals is interesting, but I'm lost without a concrete example. There are just too many "Perls" that could come from what you suggest.