Hi all,

Here is a patch I promised Nicholas a while ago to generate
src/extends.c automatically.  It's not complete and it's not perfect,
but it's a good first step that someone (including potentially myself)
can refine as we see where and how it fails.

-- c


Index: lib/Parrot/Vtable.pm
===================================================================
--- lib/Parrot/Vtable.pm	(revision 8971)
+++ lib/Parrot/Vtable.pm	(working copy)
@@ -26,13 +26,14 @@
 
 package Parrot::Vtable;
 
-use FileHandle;
+use strict;
 
 use Exporter;
-use strict;
+use FileHandle;
 
[EMAIL PROTECTED]::Vtable::ISA = qw(Exporter);
[EMAIL PROTECTED]::Vtable::EXPORT = qw(parse_vtable vtbl_defs vtbl_struct vtbl_macros);
[EMAIL PROTECTED]::Vtable::ISA    = qw(Exporter);
[EMAIL PROTECTED]::Vtable::EXPORT =
+    qw( parse_vtable vtbl_defs vtbl_struct vtbl_macros vtbl_extend );
 
 sub make_re {
     my $re = shift;
@@ -53,10 +54,10 @@
 
 Returns a reference to an array containing
 
-  [ return_type method_name parameters section ]
+  [ return_type method_name parameters section MMD_type ]
 
-for each vtable method defined in C<$file>. If C<$file> is unspecified
-it defaults to F<vtable.tbl>.
+for each vtable method defined in C<$file>. If C<$file> is unspecified it
+defaults to F<vtable.tbl>.  If it is not an MMD method, C<MMD_type> is -1.
 
 =cut
 
@@ -64,7 +65,7 @@
 
     my $file = defined $_[0] ? shift() : 'vtable.tbl';
     my $vtable = [];
-    my $fh = new FileHandle ($file, O_RDONLY) or
+    my $fh = FileHandle->new($file, O_RDONLY) or
         die "Can't open $file for reading: $!\n";
     my $section = 'MAIN';
 
@@ -74,15 +75,15 @@
 
         next if /^\s*#/ or /^\s*$/;
 
-	if (/^\[(\w+)\]/) {
-	    $section = $1;
-	}
+    if (/^\[(\w+)\]/) {
+        $section = $1;
+    }
         elsif (m/^\s*
-	        ($type_re)\s+
-	        ($ident_re)\s*
-		\(($arglist_re)\)
-		(?:\s+(MMD_\w+))?\s*$/x) {
-	    my $mmd = defined $4 ? $4 : -1;
+            ($type_re)\s+
+            ($ident_re)\s*
+        \(($arglist_re)\)
+        (?:\s+(MMD_\w+))?\s*$/x) {
+        my $mmd = defined $4 ? $4 : -1;
             push @{$vtable}, [ $1, $2, $3, $section, $mmd ];
         } else {
             die "Syntax error at $file line ".$fh->input_line_number()."\n";
@@ -105,7 +106,7 @@
     my $entry;
 
     for $entry (@{$vtable}) {
-	next if ($entry->[4] =~ /MMD_/);
+    next if ($entry->[4] =~ /MMD_/);
         my $args = join(", ", 'Interp* interpreter', 'PMC* pmc', split(/\s*,\s*/, $entry->[2]));
         $defs .= "typedef $entry->[0] (*$entry->[1]_method_t)($args);\n";
     }
@@ -140,8 +141,8 @@
     INTVAL base_type;        /* 'type' value for MMD */
     STRING* whoami;          /* Name of class this vtable is for */
     UINTVAL flags;           /* Flags. Duh */
-    STRING* does_str;	     /* space separated list of interfaces */
-    STRING* isa_str;	     /* space separated list of classes */
+    STRING* does_str;         /* space separated list of interfaces */
+    STRING* isa_str;         /* space separated list of classes */
     PMC *class;              /* for PMCs: a PMC of that type
                                 for objects: the class PMC */
     PMC *mro;                /* array PMC of [class, parents ... ] */
@@ -149,7 +150,7 @@
 
 EOF
     for $entry (@{$vtable}) {
-	next if ($entry->[4] =~ /MMD_/);
+    next if ($entry->[4] =~ /MMD_/);
         $struct .= "    $entry->[1]_method_t $entry->[1];\n";
     }
 
@@ -177,11 +178,11 @@
 
 EOM
     for my $entry (@{$vtable}) {
-	next if ($entry->[4] =~ /MMD_/);
-	my @args = split /,\s*/, $entry->[2];
-	unshift @args, "i interp", "p pmc";
-	my $args = join ', ', map { (split / /, $args[$_])[1] } (0..$#args);
-	$macros .= <<"EOM";
+    next if ($entry->[4] =~ /MMD_/);
+    my @args = split /,\s*/, $entry->[2];
+    unshift @args, "i interp", "p pmc";
+    my $args = join ', ', map { (split / /, $args[$_])[1] } (0..$#args);
+    $macros .= <<"EOM";
 #define VTABLE_$entry->[1]($args) \\
     (pmc)->vtable->$entry->[1]($args)
 EOM
@@ -195,8 +196,8 @@
 /* &gen_from_def(vtable_methods.pasm) */
 EOM
     for my $entry (@{$vtable}) {
-	my $uc_meth = uc $entry->[1];
-	$macros .= <<"EOM";
+    my $uc_meth = uc $entry->[1];
+    $macros .= <<"EOM";
 #define PARROT_VTABLE_${uc_meth}_METHNAME \"__$entry->[1]\"
 EOM
 
@@ -217,16 +218,16 @@
     "",     /* 'type' value for MMD */
     "",     /* Name of class this vtable is for */
     "",     /* Flags. Duh */
-    "",	    /* space separated list of interfaces */
-    "",	    /* space separated list of classes */
+    "",        /* space separated list of interfaces */
+    "",        /* space separated list of classes */
     "",     /* class */
-    "",	    /* mro */
+    "",        /* mro */
 
     /* Vtable Functions */
 EOM
     for my $entry (@{$vtable}) {
-	next if ($entry->[4] =~ /MMD_/);
-	$macros .= <<"EOM";
+    next if ($entry->[4] =~ /MMD_/);
+    $macros .= <<"EOM";
         \"__$entry->[1]\",
 EOM
     }
@@ -245,11 +246,11 @@
 typedef enum {
 EOM
     for my $entry (@{$vtable}) {
-	next unless ($entry->[4] =~ /MMD_/);
-	next if ($entry->[4] =~ /_INT$/);
-	next if ($entry->[4] =~ /_STR$/);
-	next if ($entry->[4] =~ /_FLOAT$/);
-	$macros .= <<"EOM";
+    next unless ($entry->[4] =~ /MMD_/);
+    next if ($entry->[4] =~ /_INT$/);
+    next if ($entry->[4] =~ /_STR$/);
+    next if ($entry->[4] =~ /_FLOAT$/);
+    $macros .= <<"EOM";
         $entry->[4],
 EOM
     }
@@ -264,11 +265,11 @@
 EOM
 
     for my $entry (@{$vtable}) {
-	next unless ($entry->[4] =~ /MMD_/);
-	next if ($entry->[4] =~ /_INT$/);
-	next if ($entry->[4] =~ /_STR$/);
-	next if ($entry->[4] =~ /_FLOAT$/);
-	$macros .= <<"EOM";
+    next unless ($entry->[4] =~ /MMD_/);
+    next if ($entry->[4] =~ /_INT$/);
+    next if ($entry->[4] =~ /_STR$/);
+    next if ($entry->[4] =~ /_FLOAT$/);
+    $macros .= <<"EOM";
         \"__$entry->[1]\",
 EOM
     }
@@ -282,6 +283,84 @@
     $macros;
 }
 
+=item C<vtbl_extend($vtable)>
+
+Returns the C function definitions to call the vtable methods on a PMC for the
+elements in the referenced vtable array.
+
+=cut
+
+sub vtbl_embed
+{
+    my $vtable = shift;
+
+    for my $entry (@$vtable)
+    {
+        my ($return_type, $name, $params, $section, $mmd) = @$entry;
+        next unless $mmd eq '-1';
+
+        my @params    = parse_params( $params );
+        my @sig       = ( 'Parrot_INTERP interp', 'Parrot_PMC pmc' );
+        my @args      = ( 'interp', 'pmc' );
+
+        while (my ($type, $name) = splice( @params, 0, 2 ))
+        {
+            push @sig, find_type( $type ) . ' ' . $name;
+            push @args, $name;
+        }
+
+        my $signature = join( ', ', @sig  );
+        my $arguments = join( ', ', @args );
+
+        my $ret_type  = find_type( $return_type );
+
+        printf 
+"%s Parrot_PMC_%s( %s )
+{
+    %s retval;
+    PARROT_CALLIN_START( interp );
+    retval = VTABLE_%s( %s );
+    PARROT_CALLIN_END( interp );
+    return retval;
+}\n\n", $ret_type, $name, $signature, $ret_type, $name, $arguments;
+
+    }
+}
+
+sub find_type
+{
+    my $type    = shift;
+
+    my %typemap =
+    (
+        'STRING*'  => 'Parrot_STRING',
+        'void*'    => 'void*',
+        'INTVAL'   => 'Parrot_Int',
+        'PMC*'     => 'Parrot_PMC',
+        'FLOATVAL' => 'Parrot_Float',
+        'void'     => 'void',
+        'UINTVAL'  => 'Parrot_Int',
+    );
+
+    die "Unknown type $type\n" unless exists $typemap{ $type };
+
+    return $typemap{ $type };
+}
+
+sub parse_params
+{
+    my $params = shift;
+
+    my @params;
+
+    while ($params =~ m/(\w+\*?) (\w+)/g)
+    {
+        push @params, $1, $2;
+    }
+
+    return @params;
+}
+
 =back
 
 =head1 SEE ALSO
@@ -301,4 +380,3 @@
 =back
 
 1;
-

Reply via email to