Index: lib/Parrot/Pmc2c.pm
===================================================================
RCS file: /cvs/public/parrot/lib/Parrot/Pmc2c.pm,v
retrieving revision 1.36
diff -u -2 -r1.36 Pmc2c.pm
--- lib/Parrot/Pmc2c.pm	19 Jul 2004 10:48:32 -0000	1.36
+++ lib/Parrot/Pmc2c.pm	14 Aug 2004 22:20:00 -0000
@@ -24,4 +24,5 @@
 use strict;
 use vars qw(@EXPORT_OK @writes %writes );
+use Parrot::PMC qw(%pmc_types);
 
 use base qw( Exporter );
@@ -126,4 +127,5 @@
 #include "parrot/dynext.h"
 
+PMC* Parrot_lib_${lc_classname}_load(Interp *interpreter); /* don't warn */
 PMC* Parrot_lib_${lc_classname}_load(Interp *interpreter)
 {
@@ -502,4 +504,15 @@
 }
 
+=item C<pmc_is_dynpmc>
+
+Determines if a given PMC type is dynamically loaded or not.
+
+=cut
+
+sub pmc_is_dynpmc {
+    # surely core PMCs aren't dynamic
+    return exists($pmc_types{$_[1]}) ? 0 : 1;
+}
+
 =item C<init_func()>
 
@@ -528,5 +541,5 @@
         $vtbl_flag .= '|VTABLE_IS_SHARED_FLAG';
     }
-    my (@meths, @mmds);
+    my (@meths, @mmds, @init_mmds, %init_mmds);
     foreach my $method (@{ $self->{vtable}{methods}} ) {
         my $meth = $method->{meth};
@@ -555,5 +568,12 @@
             push @mmds, [ $func, $left, $right, $meth_name ];
             foreach my $variant (@{ $self->{mmd_variants}{$meth} }) {
-                $right = "enum_class_$variant->[0]";
+                if ($self->pmc_is_dynpmc($variant->[0])) {
+                    $right = 'enum_class_default';
+                    push @init_mmds, [$#mmds + 1, $variant->[0]];
+                    $init_mmds{$variant->[0]} = 1;
+                }
+                else {
+                    $right = "enum_class_$variant->[0]";
+                }
                 $meth_name = $variant->[1] . '_' .$variant->[0];
                 push @mmds, [ $func, $left, $right, $meth_name];
@@ -572,4 +592,5 @@
     my $class_init_code = $n >= 0 ? $self->{methods}[$n]{body} : "";
     $class_init_code =~ s/INTERP/interp/g;
+    my $enum_name = $self->{flags}{dynpmc} ? -1 : "enum_class_$classname";
     $cout .= <<"EOC";
 void
@@ -578,5 +599,5 @@
     struct _vtable temp_base_vtable = {
         NULL,	/* package */
-        enum_class_$classname,	/* base_type */
+        $enum_name,	/* base_type */
         NULL,	/* whoami */
         $vtbl_flag, /* flags */
@@ -590,5 +611,5 @@
     $cout .= <<"EOC";
 
-    const MMD_init _temp_mmd_init[] = {
+    MMD_init _temp_mmd_init[] = {
         $mmd_list
     };
@@ -597,4 +618,38 @@
     */
 EOC
+    # init vtable slot
+    if ($self->{flags}{dynpmc}) {
+        $cout .= <<"EOC";
+
+    temp_base_vtable.base_type = entry;
+EOC
+    }
+    # declare auxiliary variables for dyncpmc IDs
+    foreach my $dynclass (keys %init_mmds) {
+        next if $dynclass eq $classname;
+        $cout .= <<"EOC";
+    int my_enum_class_$dynclass = Parrot_PMC_typenum(interp, "$dynclass");
+EOC
+    }
+    # init MMD "right" slots with the dynpmc types
+    foreach my $entry (@init_mmds) {
+        if ($entry->[1] eq $classname) {
+            $cout .= <<"EOC";
+    _temp_mmd_init[$entry->[0]].right = entry;
+EOC
+        }
+        else {
+            $cout .= <<"EOC";
+    _temp_mmd_init[$entry->[0]].right = my_enum_class_$entry->[1];
+EOC
+        }
+    }
+    # just to be safe
+    foreach my $dynclass (keys %init_mmds) {
+        next if $dynclass eq $classname;
+        $cout .= <<"EOC";
+    assert(my_enum_class_$dynclass != enum_class_default);
+EOC
+    }
     $cout .= <<"EOC";
     if (!pass) {
