Re: RFC 232 (v1) Replace AUTOLOAD by a more flexible mechanism

2000-09-16 Thread Ilya Zakharevich

On Fri, Sep 15, 2000 at 03:11:47PM -0600, Nathan Torkington wrote:
 Perl6 RFC Librarian writes:
  This RFC proposes two-stage autoloading: one stage may be registered
  to act when the symbol is encountered at compile time, the other
  when the subroutine is called.  Autoloading on the second stage does not
  Icall the subroutine, only Iloads it. 
 
 You have a beautiful mind, Mr Zakharevich.  I'd like to frame it on my
 wall.

I can see that the nail that attaches it to my wall is already shaky...
When it is falls down, feel free to pick it...

 Actually, I think I'd like to see this extended.  I'd like to be able
 to hook into the parser so that when it sees a function call:
 
   foo()
 
 I can have it call my subroutine.
 
   foo_handler( $token_stream )
 
 foo_handler can access the token stream that may or may not be part of
 the argument list, decide what is, and then return the code to be
 executed at runtime (normally just a call to foo()):
 
   sub foo_handler {
 return sub { foo() }; # *not* an infinite loop, please
   }

This is just a user-defined operator (which see on p5p).  You register
foo() as a user-defined operator (with the precedence/etc of a
function call - or of a unary or nullary function).  Then your handler
gets the OP trees for the arguments.

By the way, if you do not need to inspect the argument OP trees at
compile time, you may extend the discussed proposal to allow the
compile-time action to return EITHER prototype, OR a subroutine
reference.

Getting arguments at compile time is tricky: you cannot get them
unless you know the prototype already.  RFC18 and user-defined
operators avoid this since they specify the prototype *before* the
call is encountered.

 Context-coercion:
 
   sub foo_handler {
 my $token_stream = shift;
 my $arg_1 = $token_stream-next;  # assuming passed as strings?
 return eval "sub { scalar($arg_1) }";

This is the part of my proposal for user-defined-operators: you can
force context for your arguments.  Keep in mind that UDO are at least
partially orthogonal w.r.t. RFC18: they see already compiled trees
(but can modify them if needed), and not the string arguments.

This is the problem with RFC18: you cannot "partially compile"
things.  How many arguments for f() in

  f($a, $b, g my $c, $d);

3 or 4?  This depends on the arity of g().  But you cannot find this
arity until you compile the call frame for g(), and then lexical $c is
already introduced!  So you cannot make f() to be a "comment", just
the act of determining the arguments to f() has side-effects.

Ilya



Re: RFC 232 (v1) Replace AUTOLOAD by a more flexible mechanism

2000-09-15 Thread Nathan Torkington

Perl6 RFC Librarian writes:
 This RFC proposes two-stage autoloading: one stage may be registered
 to act when the symbol is encountered at compile time, the other
 when the subroutine is called.  Autoloading on the second stage does not
 Icall the subroutine, only Iloads it. 

You have a beautiful mind, Mr Zakharevich.  I'd like to frame it on my
wall.

Actually, I think I'd like to see this extended.  I'd like to be able
to hook into the parser so that when it sees a function call:

  foo()

I can have it call my subroutine.

  foo_handler( $token_stream )

foo_handler can access the token stream that may or may not be part of
the argument list, decide what is, and then return the code to be
executed at runtime (normally just a call to foo()):

  sub foo_handler {
return sub { foo() };   # *not* an infinite loop, please
  }

The anonymous subroutine returned by the foo_handler() is then inlined
into the optree.

This would let us have constants:

  sub foo_handler {
return sub { 42 };
  }

Context-coercion:

  sub foo_handler {
my $token_stream = shift;
my $arg_1 = $token_stream-next;# assuming passed as strings?
return eval "sub { scalar($arg_1) }";
  }

This would give us the ability to have things with both compile-time
and run-time behaviours, as well as being able to remove run-time
behaviours if we wanted.

Perhaps this is no longer the point at which we think of it as
autoloading, but rather as part of the compilation process.  Just as
we can intercept strings and regexes with overloaded strings and
regexes, this would let us intercept functions.

Nat



RFC 232 (v1) Replace AUTOLOAD by a more flexible mechanism

2000-09-15 Thread Perl6 RFC Librarian

This and other RFCs are available on the web at
  http://dev.perl.org/rfc/

=head1 TITLE

Replace AUTOLOAD by a more flexible mechanism

=head1 VERSION

  Maintainer: Ilya Zakharevich [EMAIL PROTECTED]
  Date: 15 September 2000
  Mailing List: [EMAIL PROTECTED]
  Number: 232
  Version: 1
  Status: Developing

=head1 ABSTRACT

This RFC proposes two-stage autoloading: one stage may be registered
to act when the symbol is encountered at compile time, the other
when the subroutine is called.  Autoloading on the second stage does not
Icall the subroutine, only Iloads it. 

=head1 DESCRIPTION

AUTOLOAD interface was created before closures were available.  Because of
this, it combines two actions into one call: it loads the subroutine,
and calls it.

This two actions should be separated.  Additionally, some action may be needed
during compile time.  For example, one may fetch the prototype of the function,
or even call the function, so that its (constant) value may be used in this
and other calls.

[WIth the current implementation Iall the prototypes should be loaded no
matter what, with significant memory and time overheads.]

When a symbol for an undefined subroutine is seen at compile time, the
Cproto action is invoked.  It should return Cundef if no such symbol
could be autoloaded (so that the symbol may be searched further in the @ISA
tree).  It should return the prototype if the symbol could be found.  This
call may have arbitrary side effects, such as defining the subroutine, or even
calling it (useful for constant XSUBs).

When an undefined subroutine is about to be called, the Cload action is
invoked.  It should return a reference to a subroutine, or Cundef to signal
that search should be continued further in the @ISA tree.

In both cases, the argument for the action is the name of the subroutine.
If the subroutine has two different names (it was created with one name, and
was imported with a different name), both names are provided.

The Cproto and Cload subroutines may be registered (both or any one) with
the pragma

  use autoload ':proto' = sub {}, ':load' = sub {};

=head1 MIGRATION ISSUES

None.

[The current AUTOLOAD mechanism saves creation of a subroutine frame, since
the actual call to the subroutine may be done via Cgoto.  If this is proved
to provide some advantage, AUTOLOAD mechanism may be preserved as well.]

=head1 IMPLEMENTATION

Straightforward.

=head1 REFERENCES

None.




Re: RFC 232 (v1) Replace AUTOLOAD by a more flexible mechanism

2000-09-15 Thread Glenn Linderman

Nathan Torkington wrote:

 Actually, I think I'd like to see this extended.  I'd like to be able
 to hook into the parser so that when it sees a function call:

   foo()

 I can have it call my subroutine.

   foo_handler( $token_stream )

 foo_handler can access the token stream that may or may not be part of
 the argument list, decide what is, and then return the code to be
 executed at runtime (normally just a call to foo()):

   sub foo_handler {
 return sub { foo() };   # *not* an infinite loop, please
   }

 The anonymous subroutine returned by the foo_handler() is then inlined
 into the optree.

The above is very, very similar to the effect of defining foo as an
"immediate" sub, per RFC 18.

 Perhaps this is no longer the point at which we think of it as
 autoloading, but rather as part of the compilation process.  Just as
 we can intercept strings and regexes with overloaded strings and
 regexes, this would let us intercept functions.

That's the sense in which RFC was defined.  This is one of the things that has
given FORTH so much extensibility.  I'd vote for RFC 18.  It would also let me
implement RFC 229 as approximately... depending on how the "parameters" to the
immediate sub are dealt with at immediate time (you called it token stream,
and that's probably the right word, or compile time parameters... I think the
need is for the text of the parameters, not the values: call by name not call
by value or reference.)

sub interpolate : immediate { return qq/eval "qq\000"/.join('',@_).qq/"\0"/; }

--
Glenn
=
There  are two kinds of people, those
who finish  what they start,  and  so
on... -- Robert Byrne



_NetZero Free Internet Access and Email__
   http://www.netzero.net/download/index.html