Implementing perl BEGIN blocks

6 views
Skip to first unread message

Leopold Toetsch

unread,
Aug 18, 2005, 10:51:58 AM8/18/05
to Perl 6 Internals
There was some recent discussion [1] [2] on p6l about BEGIN blocks and
constant, which is executed at compile time too.

Parrot has since quite a time the @IMMEDIATE subroutine pragma, which
causes execution of subs during compilation. But these subroutines can't
return a result so it's rather useless now besides testing that printing
something inside thus sub is really done before a print statement in main.

Here is a plan to implement most of the needed bits.

# constant pi = 4 * atan2(1,1);

translates to

.sub anon_1 @IMMEDIATE, @ANON
$N0 = atan 1.0, 1.0
$P0 = new .Float
$P0 = $N0
.return ($P0)
.end

During compilation this subroutine is executed, the resulting PMC gets
frozen and replaces the PMC constant slot of the immediate subroutine.

The constant declaration is then just

.local pmc pi
set_p_pc pi, anon_1

or with a shortcut:

.const pmc pi = anon_1

As PMC constants are already represented as frozen images in PBC this
would work for nested data strucuters, objects, and their classes too.

Comments welcome,
leo

[1] BEGIN {...} and IO
[2] my $pi is constant = 3;

Autrijus Tang

unread,
Aug 18, 2005, 11:28:52 AM8/18/05
to Leopold Toetsch, Perl 6 Internals
On Thu, Aug 18, 2005 at 04:51:58PM +0200, Leopold Toetsch wrote:
> There was some recent discussion [1] [2] on p6l about BEGIN blocks and
> constant, which is executed at compile time too.
>
> Parrot has since quite a time the @IMMEDIATE subroutine pragma, which
> causes execution of subs during compilation.

You mean, during PIR compilation?

> As PMC constants are already represented as frozen images in PBC this
> would work for nested data strucuters, objects, and their classes too.
>
> Comments welcome,

I think it's interesting, but as BEGIN blocks may affect subsequent
parsing, as well as trigger compilation of other source files, I wonder
how to address this. Hmm.

Also I wonder about scoping issues:

{
my $a = $a / 2;
BEGIN { $a = 10 };
}
say $a; # this should to print 5

How is @IMMEDIATE going to handle this?

Thanks,
/Autrijus/

Leopold Toetsch

unread,
Aug 18, 2005, 12:00:43 PM8/18/05
to Autrijus Tang, Perl 6 Internals
Autrijus Tang wrote:
> On Thu, Aug 18, 2005 at 04:51:58PM +0200, Leopold Toetsch wrote:
>
>>There was some recent discussion [1] [2] on p6l about BEGIN blocks and
>>constant, which is executed at compile time too.
>>
>>Parrot has since quite a time the @IMMEDIATE subroutine pragma, which
>>causes execution of subs during compilation.
>
>
> You mean, during PIR compilation?

Yes.

>>As PMC constants are already represented as frozen images in PBC this
>>would work for nested data strucuters, objects, and their classes too.
>>
>>Comments welcome,
>
>
> I think it's interesting, but as BEGIN blocks may affect subsequent
> parsing, as well as trigger compilation of other source files, I wonder
> how to address this. Hmm.

This shouldn't be a problem (at least when the last few globals from
imcc are gone), i.e. compilation / running code should be fully re-rentrant.

> Also I wonder about scoping issues:
>
> {
> my $a = $a / 2;
> BEGIN { $a = 10 };
> }
> say $a; # this should to print 5
>
> How is @IMMEDIATE going to handle this?

@IMEDIATE subs will execute in the initial interpreter context. This
context gets an initial lexical pad. (Either per default or we mandate
that the first BEGIN{} has to create it).
So subsequenct BEGIN blocks can use this pad to communicate lexical state.

Then when @MAIN is frozen to bytecode and *if* there is a lexical pad,
we consider @MAIN being a closure, which should freeze the pad too.

At runtime thawing the closure makes the pad available as the outermost
pad.

BTW can you explain why the above example prints 5?

> Thanks,
> /Autrijus/

leo

Autrijus Tang

unread,
Aug 18, 2005, 12:05:40 PM8/18/05
to Leopold Toetsch, Autrijus Tang, Perl 6 Internals
On Thu, Aug 18, 2005 at 06:00:43PM +0200, Leopold Toetsch wrote:
> This shouldn't be a problem (at least when the last few globals from
> imcc are gone), i.e. compilation / running code should be fully re-rentrant.

Oooh, that will be much better.

> BTW can you explain why the above example prints 5?

That was a typo. Something like this may illustrate the issue better:

my $a;
{ my $b; BEGIN { $a = { say $b++ } } }

Thanks,
/Autrijus/

Leopold Toetsch

unread,
Aug 18, 2005, 4:46:15 PM8/18/05
to Uri Guttman, Perl 6 Internals

On Aug 18, 2005, at 21:54, Uri Guttman wrote:

>
>>>>>> "LT" == Leopold Toetsch <l...@toetsch.at> writes:
>
> LT> Here is a plan to implement most of the needed bits.
>
> LT> # constant pi = 4 * atan2(1,1);
>
> LT> translates to
>
> LT> .sub anon_1 @IMMEDIATE, @ANON
> LT> $N0 = atan 1.0, 1.0
> LT> $P0 = new .Float
> LT> $P0 = $N0
> LT> .return ($P0)
> LT> .end
>
> did you forget the 4 * part of the init value?

Of course. I just wanted to simplify the example a bit ;-)

> and shouldn't atan2(1,1)
> be (possibly) optimized to a constant or looked up in a table of easy
> trig stuff and that value used?

Yep. The former is already done for unary and binary basic math, but
seems to be missing for trig opcodes still:

$ echo "add N0, 1, 1
end" | ./parrot -t1 -a -
0 set N0, 2 - N0=0.000000,
3 end

The 'times 4' part (and creating pi) is another run through the
optimization loop (after constant propagation).

> then you could just generate the
> constant folded value of pi in the compiler and emit that float for the
> init.

That would yield a constant folded FLOATVAL pi, but not a PMC.

constant num pi = ...

vs

constant pi = ...

(I guess)

> if this gets compiled to bytecode this would really reduce the
> runtime (even in BEGIN) to almost nothing.

Yep. But anyway runtime costs are the same. It's read and thaw (for a
PMC) a constant - and thaw is executed once during PBC loading.

> uri

leo

Uri Guttman

unread,
Aug 18, 2005, 3:54:01 PM8/18/05
to Leopold Toetsch, Perl 6 Internals
>>>>> "LT" == Leopold Toetsch <l...@toetsch.at> writes:

LT> Here is a plan to implement most of the needed bits.

LT> # constant pi = 4 * atan2(1,1);

LT> translates to

LT> .sub anon_1 @IMMEDIATE, @ANON
LT> $N0 = atan 1.0, 1.0
LT> $P0 = new .Float
LT> $P0 = $N0
LT> .return ($P0)
LT> .end

did you forget the 4 * part of the init value? and shouldn't atan2(1,1)


be (possibly) optimized to a constant or looked up in a table of easy

trig stuff and that value used? then you could just generate the


constant folded value of pi in the compiler and emit that float for the

init. if this gets compiled to bytecode this would really reduce the


runtime (even in BEGIN) to almost nothing.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Reply all
Reply to author
Forward
0 new messages