develooper 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
  




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About