I sat down with Dan yesterday and finally got my head around his idea of
the multiple forms of some of the vtable methods. Unfortunately, this
kinda interrupts what I was doing implementing Perl scalar PMCs. :)

Anyway, instead of having an array of five different ways to add things
together, each function taking two PMCs, what we actually want is *true*
multimethods: one form which takes a PMC and an INTVAL, a PMC and a
BIGINT, a PMC and another PMC, etc. 

(This means that the implementation of the op add_p_p_i is trivial, for
instance.)

I also finally now understand the "same as you" type - it means "I
am passing you a PMC which is guaranteed to be in the same class as you
- you may break the abstraction and directly fiddle with its data
pointer."

The following patch reworks vtable.h to implement this. It now means
that the still going on in classes/ is out of date; genclass.pl will
need updating and I need to toss what I've written in the C files. 

But that's cool, because it allows me to convince myself that we ought
to use several different vtables to represent a Perl scalar. (which is
*obviously* the Right Way, but once I start doing something my way, it's
non-trivial to convince me to change... ;)

Here's the patch, anyhow:

Index: Makefile.in
===================================================================
RCS file: /home/perlcvs/parrot/Makefile.in,v
retrieving revision 1.48
diff -d -u -r1.48 Makefile.in
--- Makefile.in 2001/11/15 22:29:59     1.48
+++ Makefile.in 2001/11/16 15:29:00
@@ -12,11 +12,14 @@
 
 O_FILES = global_setup$(O) interpreter$(O) parrot$(O) register$(O) \
 core_ops$(O) memory$(O) packfile$(O) stacks$(O) string$(O) encoding$(O) \
-chartype$(O) runops_cores$(O) trace$(O) vtable_ops$(O) pmc$(O) classes/intclass$(O) \
+chartype$(O) runops_cores$(O) trace$(O) vtable_ops$(O) pmc$(O) \
 encodings/singlebyte$(O) encodings/utf8$(O) encodings/utf16$(O) \
 encodings/utf32$(O) chartypes/unicode$(O) chartypes/usascii$(O) resources$(O) \
 platform$(O)
 
+# classes/intclass.o and classes/scalarclass.o removed for now, while
+# multimethods are being reworked
+
 #DO NOT ADD C COMPILER FLAGS HERE
 #Add them in Configure.pl--look for the
 #comment 'ADD C COMPILER FLAGS HERE'
@@ -91,7 +94,8 @@
 
 encoding/utf32$(O): $(H_FILES)
 
-classes/intclass$(O): $(H_FILES)
+# classes/intclass$(O): $(H_FILES)
+# classes/scalarclass$(O): $(H_FILES)
 
 interpreter$(O): interpreter.c $(H_FILES)
 
Index: make_vtable_ops.pl
===================================================================
RCS file: /home/perlcvs/parrot/make_vtable_ops.pl,v
retrieving revision 1.5
diff -d -u -r1.5 make_vtable_ops.pl
--- make_vtable_ops.pl  2001/10/28 08:29:59     1.5
+++ make_vtable_ops.pl  2001/11/16 15:29:00
@@ -25,6 +25,7 @@
 sub multimethod {
     my $type = $vtable{$_[0]}{meth_type};
     return ""               if $type eq "unique";
+    return ""; # Spike it for now, until I'm convinced of how to do this
     return '[$3->vtable->num_type]' if $type eq "num";
     return '[$3->vtable->string_type]' if $type eq "str";
     die "Coding error - undefined type $type\n";
Index: vtable.tbl
===================================================================
RCS file: /home/perlcvs/parrot/vtable.tbl,v
retrieving revision 1.7
diff -d -u -r1.7 vtable.tbl
--- vtable.tbl  2001/11/15 21:24:43     1.7
+++ vtable.tbl  2001/11/16 15:29:00
@@ -11,6 +11,9 @@
 # string       void frob       INTVAL foo      STRING bar
 #
 # Note that we don't include the source "PMC* pmc" - that's done implicitly.
+#
+# "value" in non-unique methods (multimethods) is a magic name. Its type
+# will be replaced appropriately.
 
 unique INTVAL type     
 unique STRING* name
@@ -26,19 +29,19 @@
 unique BOOLVAL get_bool         
 unique void* get_value 
 unique BOOLVAL is_same         PMC* pmc2
-int    void set_integer        INTVAL integer
-float  void set_number         FLOATVAL number
-str    void set_string         STRING* string
+int    void set_integer        INTVAL value
+float  void set_number         FLOATVAL value
+str    void set_string         STRING* value
 unique void set_value          void* value
-num    void add                PMC* other       PMC* dest 
-num    void subtract           PMC* other       PMC* dest 
-num    void multiply           PMC* other       PMC* dest 
-num    void divide             PMC* other       PMC* dest 
-num    void modulus            PMC* other       PMC* dest 
-str    void concatenate        PMC* other       PMC* dest 
-unique BOOLVAL is_equal                PMC* other 
-unique void logical_or         PMC* other       PMC* dest 
-unique void logical_and        PMC* other       PMC* dest 
-unique void logical_not        PMC* other 
-str    void match              PMC* other       REGEX* re
-str    void repeat             PMC* other       PMC* dest 
+num    void add                PMC* value       PMC* dest 
+num    void subtract           PMC* value       PMC* dest 
+num    void multiply           PMC* value       PMC* dest 
+num    void divide             PMC* value       PMC* dest 
+num    void modulus            PMC* value       PMC* dest 
+str    void concatenate        PMC* value       PMC* dest 
+unique BOOLVAL is_equal                PMC* value 
+unique void logical_or         PMC* value       PMC* dest 
+unique void logical_and        PMC* value       PMC* dest 
+unique void logical_not        PMC* value 
+str    void match              PMC* value       REGEX* re
+str    void repeat             PMC* value       PMC* dest 
Index: Parrot/Vtable.pm
===================================================================
RCS file: /home/perlcvs/parrot/Parrot/Vtable.pm,v
retrieving revision 1.7
diff -d -u -r1.7 Vtable.pm
--- Parrot/Vtable.pm    2001/10/28 08:29:59     1.7
+++ Parrot/Vtable.pm    2001/11/16 15:29:00
@@ -4,12 +4,22 @@
 @Parrot::Vtable::ISA = qw(Exporter);
 @Parrot::Vtable::EXPORT = qw(parse_vtable vtbl_defs vtbl_struct vtbl_enumerate);
 
-my(%type_counts) = (unique => 1,
-                   int => 5,
-                   float =>5,
-                   num =>7,
-                   str => 5);
+my(%expand) = (
+    unique => [""], # Dummy element, so we go through the loop exactly once
+    int    => [qw[object native bigint same]],
+    float  => [qw[object native bigfloat same]],
+    num    => [qw[object int bigint float bigfloat same]],
+    str    => [qw[object native unicode other same]]
+);
+
+my (%types)  = (
+    int   => ["PMC *", "INTVAL", "BIGINT", "PMC *"],
+    float => ["PMC *", "FLOATVAL", "BIGFLOAT", "PMC *"],
+    num   => ["PMC *", "INTVAL", "BIGINT", "FLOATVAL", "BIGFLOAT", "PMC *"],
+    str   => ["PMC *", "STRING *", "STRING *", "STRING *", "PMC *"]
+);
 
+
 sub parse_vtable {
     my (%vtbl, @order);
     open IN, shift || "vtable.tbl" or die "Can't open vtable table! $!\n";
@@ -22,38 +32,44 @@
        my $meth_type = shift @line; # Method type
         my $tn = shift @line; # Type and name;
         my ($type, $name) = $tn =~ /(.*?)\s+(\w+)/;
-        $vtbl{$name}{type} = $type;
-       $vtbl{$name}{meth_type} = $meth_type;
-        $vtbl{$name}{proto} = "$type (*$name)(struct Parrot_Interp *interpreter, PMC* 
pmc";
-        for (@line) {
-            my ($argtype, $argname) = /(.*?)\s+(\w+)/;
-            push @{$vtbl{$name}{args}},
-                { type => $argtype, name => $argname };
-            $vtbl{$name}{proto} .= ", $_";
+
+        # You are in a maze of twisty multimethods, all different.
+        for my $i (0..$#{$expand{$meth_type}}) {
+            my $expand_name = $name;
+
+            # If we're in a multimethod, we need to expand the name if
+            # it's not the default argument type of "object".
+            $expand_name .= "_".$expand{$meth_type}[$i] 
+                unless $meth_type eq "unique"
+                    or $expand{$meth_type}[$i] eq "object"; # as a default
+
+            $vtbl{$expand_name}{type} = $type;
+            $vtbl{$expand_name}{proto} = "$type (*$expand_name)(struct Parrot_Interp 
+*interpreter, PMC* pmc";
+
+            # Parse the function parameters
+            for (@line) {
+                my ($argtype, $argname) = /(.*?)\s+(\w+)$/;
+
+                # In multimethods, we need to rewrite the type of
+                # parameters called "value".
+                $argtype = $types{$meth_type}[$i]
+                    if $argname eq "value" and $meth_type ne "unique";
+
+                # Add the function parameters to the prototype
+                push @{$vtbl{$expand_name}{args}},
+                    { type => $argtype, name => $argname };
+                $vtbl{$expand_name}{proto} .= ", $argtype $argname";
+            }
+            $vtbl{$expand_name}{proto} .=")";
+            
+            # So they're ordered according to their position in the file
+            push @order, $expand_name;
         }
-        $vtbl{$name}{proto} .=")";
-        push @order, $name;
     }
     $vtbl{order} = [@order];
     return %vtbl;
 }
 
-# This code is unused, but I'm keeping it around in case
-# we ever go back to using array-based vtables.
-sub vtbl_defs {
-    my %vtbl = @_;
-    my $rv;
-    my $offset = 0;
-
-    # First, typedef all the methods.
-    for (@{$vtbl{order}}) {
-        my $decl = "VTABLE_" . uc($_);
-        $rv .= "#define $decl $offset\n";
-       $offset += $type_counts{$vtbl{$_}{meth_type}};
-    }
-    return $rv;
-}
-
 sub vtbl_struct {
     my %vtbl = @_;
     my $rv;
@@ -85,14 +101,14 @@
     return $rv;
 }
 
-# Returns an array of [type, name, prototype, variations] arrays
+# Returns an array of [type, name, prototype] arrays
 sub vtbl_enumerate {
     my %vtbl = @_;
     my @rv;
     for (@{$vtbl{order}}) {
         my $proto = $vtbl{$_}{proto};
         $proto =~ s/\(\*$_\)/$_ /;
-        push @rv, [ "${_}_method_t", $_, $proto, $type_counts{$vtbl{$_}{meth_type}}];
+        push @rv, [ "${_}_method_t", $_, $proto];
     }
     return @rv;
 }
Index: include/parrot/parrot.h
===================================================================
RCS file: /home/perlcvs/parrot/include/parrot/parrot.h,v
retrieving revision 1.12
diff -d -u -r1.12 parrot.h
--- include/parrot/parrot.h     2001/11/02 12:11:16     1.12
+++ include/parrot/parrot.h     2001/11/16 15:29:00
@@ -64,6 +64,8 @@
 typedef unsigned char BOOLVAL;
 typedef void STRING_FUNCS;
 typedef void REGEX;
+typedef void BIGINT;
+typedef void BIGFLOAT;
 
 #include "parrot/global_setup.h"
 #include "parrot/interpreter.h"

-- 
>Almost any animal is capable learning a stimulus/response association,
>given enough repetition.
Experimental observation suggests that this isn't true if double-clicking
is involved. - Lionel, Malcolm Ray, asr.

Reply via email to