Front page | perl.perl5.porters |
Postings from February 2000
[questions] [bogus patch] potential new uses for typeglobs
From:
Stephane Payrard
Date:
February 10, 2000 06:18
Subject:
[questions] [bogus patch] potential new uses for typeglobs
Message ID:
20000203133212.B619@freesurf.fr
This mail is messy. I tried to get deep in the Perl sources and got
quite lost. It triggered many differents questions. Any comment and
answer welcome.
=head1 Why perl does not support autovivifying of an entry in a typeglob?
=head2 accessing a glob from a typeglob
=head1 proposed syntax extensions
=head2 motivation
=head1 extending perl syntax
=head2 methods using blessed objects
=head2 anonymous typeglob
=head1 what it may break?
=head1 attempts at a patch
=head2 A test file
=head2 The patch
First, two questions:
=head1 Why perl does not support autovivifying of an entry in a typeglob?
local *a; $a[0]=1;
fails with Modification of a read-only value attempted at -e line 1.
local *a = []; $a[0]=1;
does works.
Is that a deliberate choice? what is the motivation?
=head2 accessing a glob from a typeglob
local *a;
# **a does not cut it.
=head1 proposed syntax extensions
Supporting the blessed object as the first parameter of a method call (in
addition to a reference to the blessed object).
%a->clear; # new syntax (see below for why we want this)
(\%a)->clear; # too heavy
Anonymous type glob
+*{ ( href => 'whatever }, [] }
These extensions add no semantic, they are potential syntactic
commodities.
=head2 motivation
The motivation is to implement a XML::LiteDOM that would be
more efficient than XML::DOM.
Typeglob can be seen as an aggregate of an array and a hash and of
other things. It seems a natural structure to represent nodes of an
attribute tree. Indeed, kids of a node are naturally represented by an
array and the set of attribute/value as a hash.
Suppose C<*a> is a typeglob, accessing its kids and attributes
is straightforward.
# example 1 : smart typeglob use
local *a;
$kid = $a[0]; # get first son
$kids = \@a; # get a reference to son arry
$val = $a{href}
This is to be contrasted to nodes as a class implemented
thru a hash.
# example 2a: a constructor
sub new { my ( $class, $kids, $attrs) = @_
bless { kids => $kids, attr => $attrs }, $class;
}
Accessing attributes becomes more cumbersome.
# example 2b: accessing data in the created object
$a->{attrs}{href}
This leads to implement an accessor à la XML::DOM
# examle 2c: still more chaff
sub getAttribute { my ($elf, $attr ) = @_;
$elf->{attrs}{$attr};
}
Perl has no mechanism for inlining, so layers of OO bigotry costs a lot.
=head1 extending perl syntax
I want to extend perl syntax to get lighter source code.
=head2 methods using blessed objects
The first example is too simple; Soon we need to bless the stuff in
the glob. For example the glob may be tied to use a different filehandle
for input and output.
Problem: But what is the syntax to access it: *a is the typeglob, not the
underlying glob.
To get a lighter syntax, I want to support use the blessed object itself instead of the
reference to it returned by the bless operator.
I think the
%a->clear; # new syntax
(\%a)->clear; # too heavy
=head2 anonymous typeglob
Note: C<*{ }> has already a meaning
+*{ ( href => 'whatever }, [] } # re
Should contains at most one object (or reference to) of each type.
=head1 what it may break?
I can't see.
=head1 attempts at a patch
The bogus patch addresses only the the extension of method call syntax.
It passes the op/method but fails on more heavy uses:
Bizarre copy of ARRAY in anonlist at pragma/overload.t line 442.
What did I do wrong?
=head2 A test file
#! /usr/bin/perl
print "1..5\n";
local *x;
$ref = Any->new( {} );
*x = \%$ref;
$ref = Any->new( [] );
*x = \@$ref;
print eval { %x->meth(); } eq 'ok' ? "ok 1\n" : "not ok 1\n";
print eval { @x->meth(); } eq 'ok' ? "ok 2\n" : "not ok 2\n";
*x = Any->new( { beast => 666 } ) ;
*x = Any->new( [ 666, 666 ] );
print eval { %x->meth(); } eq 'ok' ? "ok 3\n" : "not ok 3\n";
print eval { @x->meth(); } eq 'ok' ? "ok 4\n" : "not ok 4\n";
$str = "rubrique à brac";
*x = Any->new( \$str );
print eval { $x->meth(); } eq 'ok' ? "ok 5\n" : "not ok 5\n";
local *a = [ 'un', 'deux' ];
local *b;
*b = []; # why is that necessary?
$b[0] = 1;
package Any;
sub new { bless $_[1], $_[0] }
sub meth { 'ok' }
=head2 The patch
@@ -6395,6 +6404,8 @@
case OP_RV2AV:
case OP_RV2HV:
+ if ( o->op_next->op_type == OP_METHOD_NAMED || o->op_next->op_type == OP_METHOD)
+ o->op_flags |= OPf_REF;
if (!(o->op_flags & OPf_WANT)
|| (o->op_flags & OPf_WANT) == OPf_WANT_LIST)
{
--- pp_hot.c.orig Wed Dec 8 07:23:14 1999
+++ pp_hot.c Wed Feb 2 23:17:49 2000
@@ -2720,17 +2720,20 @@
STRLEN namelen;
char* packname;
STRLEN packlen;
+ GV* iogv;
name = SvPV(meth, namelen);
sv = *(PL_stack_base + TOPMARK + 1);
if (SvGMAGICAL(sv))
mg_get(sv);
- if (SvROK(sv))
- ob = (SV*)SvRV(sv);
- else {
- GV* iogv;
-
+/* do_sv_dump( 0 , PerlIO_stderr(), sv, 0, 100, 1, 1000); */
+ if (SvROK(sv))
+ ob = (SV*)SvRV(sv);
+ else if ( SvOBJECT(sv) ) {
+ ob = sv;
+ goto gotobj;
+ } else {
packname = Nullch;
if (!SvOK(sv) ||
!(packname = SvPV(sv, packlen)) ||
@@ -2756,7 +2759,7 @@
if (!ob || !SvOBJECT(ob))
Perl_croak(aTHX_ "Can't call method \"%s\" on unblessed reference",
name);
-
+ gotobj:
stash = SvSTASH(ob);
fetch:
--
Stéphane Payrard
email : properler@freesurf.fr
portable: 06 60 95 82 69
-
[questions] [bogus patch] potential new uses for typeglobs
by Stephane Payrard