Author: allison
Date: Wed Aug 20 12:53:32 2008
New Revision: 30391

Added:
   branches/pdd27mmd/lib/Parrot/Pmc2c/MULTI.pm
Modified:
   branches/pdd27mmd/lib/Parrot/Pmc2c/Method.pm
   branches/pdd27mmd/lib/Parrot/Pmc2c/PMCEmitter.pm
   branches/pdd27mmd/lib/Parrot/Pmc2c/Parser.pm

Log:
[pdd27mmd] Parse and compile MULTI declarations in .pmc files.


Added: branches/pdd27mmd/lib/Parrot/Pmc2c/MULTI.pm
==============================================================================
--- (empty file)
+++ branches/pdd27mmd/lib/Parrot/Pmc2c/MULTI.pm Wed Aug 20 12:53:32 2008
@@ -0,0 +1,116 @@
+# Copyright (C) 2004-2008, The Perl Foundation.
+# $Id: PCCMETHOD.pm 29952 2008-08-02 22:45:13Z allison $
+
+package Parrot::Pmc2c::MULTI;
+#use base 'Parrot::Pmc2c::PCCMETHOD';
+use strict;
+use warnings;
+use Carp qw(longmess croak);
+
+=head1 NAME
+
+Parrot::Pmc2c::MULTI - Parses and preps MULTI dispatch subs
+
+=head1 SYNOPSIS
+
+    use Parrot::Pmc2c::MULTI;
+
+=head1 DESCRIPTION
+
+Parrot::Pmc2c::MULTI - Parses and preps MULTI multiple dispatch declarations
+called from F<Parrot:Pmc2c::Pmc2cMain>
+
+=cut
+
+=head1 FUNCTIONS
+
+=head2 Publicly Available Methods
+
+=head3 C<rewrite_multi_sub($method, $pmc)>
+
+B<Purpose:>  Parse and Build PMC multiple dispatch subs.
+
+B<Arguments:>
+
+=over 4
+
+=item * C<self>
+
+=item * C<method>
+
+Current Method Object
+
+=item * C<body>
+
+Current Method Body
+
+=back
+
+=cut
+
+sub rewrite_parameters {
+    my ($parameters) = @_;
+    my @param_types = ();
+    my @new_params = ();
+    my $new_param_string = "";
+
+    for my $param ( split /,/, $parameters ) {
+        my ( $type, $name, $rest ) = split /\s+/, 
&Parrot::Pmc2c::PCCMETHOD::trim($param), 3;
+
+        die "Invalid MULTI parameter '$param': missing type or name\n"
+             unless defined $name;
+
+        die "Invalid MULTI parameter '$param': attributes not allowed on 
multis\n"
+             if defined $rest;
+
+        if ($name =~ /[\**]?(\"?\w+\"?)/) {
+            $name = $1;
+        }
+
+        # Capture the actual type for the sub name
+        push @param_types, $type;
+
+        # Pass standard parameter types unmodified.
+        # All other param types are rewritten as PMCs.
+        if ($type eq 'STRING' or $type eq 'PMC' or $type eq 'INTVAL' or $type 
eq 'FLOATVAL') {
+            push @new_params, $param;
+        } else {
+            push @new_params, "PMC *$name";
+        }
+    }
+    $new_param_string = join (",", @new_params);
+
+    return ($new_param_string, @param_types);
+}
+
+=head3 C<rewrite_multi_sub()>
+
+    rewrite_multi_sub($method, $pmc);
+
+=cut
+
+sub rewrite_multi_sub {
+    my ( $self, $pmc ) = @_;
+
+    # Fixup the parameters, standardizing PMC types and extracting type names
+    # for the multi name.
+    my ($paramstring, @paramlist) = rewrite_parameters( $self->parameters );
+    $self->parameters($paramstring);
+
+    my $sub_name = "multi_" . $self->name . "_" . join ('_', @paramlist);
+
+    $self->name($sub_name);
+
+    $self->{MULTI} = 1;
+
+    return 1;
+}
+
+1;
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4:

Modified: branches/pdd27mmd/lib/Parrot/Pmc2c/Method.pm
==============================================================================
--- branches/pdd27mmd/lib/Parrot/Pmc2c/Method.pm        (original)
+++ branches/pdd27mmd/lib/Parrot/Pmc2c/Method.pm        Wed Aug 20 12:53:32 2008
@@ -6,6 +6,7 @@
 use constant VTABLE_ENTRY => 'VTABLE_ENTRY';
 use constant VTABLE       => 'VTABLE';
 use constant NON_VTABLE   => 'NON_VTABLE';
+use constant MULTI        => 'MULTI';
 use Parrot::Pmc2c::UtilFunctions qw(count_newlines args_from_parameter_list 
passable_args_from_parameter_list);
 
 sub new {

Modified: branches/pdd27mmd/lib/Parrot/Pmc2c/PMCEmitter.pm
==============================================================================
--- branches/pdd27mmd/lib/Parrot/Pmc2c/PMCEmitter.pm    (original)
+++ branches/pdd27mmd/lib/Parrot/Pmc2c/PMCEmitter.pm    Wed Aug 20 12:53:32 2008
@@ -29,6 +29,7 @@
     qw( gen_ret dont_edit count_newlines dynext_load_code c_code_coda );
 use Text::Balanced 'extract_bracketed';
 use Parrot::Pmc2c::PCCMETHOD;
+use Parrot::Pmc2c::MULTI;
 use Parrot::Pmc2c::PMC::RO;
 use Parrot::Pmc2c::PMC::ParrotClass;
 

Modified: branches/pdd27mmd/lib/Parrot/Pmc2c/Parser.pm
==============================================================================
--- branches/pdd27mmd/lib/Parrot/Pmc2c/Parser.pm        (original)
+++ branches/pdd27mmd/lib/Parrot/Pmc2c/Parser.pm        Wed Aug 20 12:53:32 2008
@@ -158,8 +158,8 @@
 
         ((?:PARROT_\w+\s+)+)? # decorators
 
-        # vtable|method marker
-        (?:(VTABLE|METHOD)\s+)?
+        # vtable, method, or multi marker
+        (?:(VTABLE|METHOD|MULTI)\s+)?
 
         ((?:\w+\s*?\**\s*)?\w+) # method name (includes return type)
         \s*
@@ -226,6 +226,10 @@
             $pmc->set_flag('need_fia_header');
         }
 
+        if ( $marker and $marker =~ /MULTI/ ) {
+            Parrot::Pmc2c::MULTI::rewrite_multi_sub( $method, $pmc );
+        }
+
         # PCCINVOKE needs FixedIntegerArray header
         $pmc->set_flag('need_fia_header') if $methodblock =~ /PCCINVOKE/;
 
@@ -235,13 +239,20 @@
         }
         else {
 
-            # Name-mangle NCI methods to avoid conflict with vtable methods.
-            if ( $marker and $marker !~ /VTABLE/ ) {
-                $method->type(Parrot::Pmc2c::Method::NON_VTABLE);
-                $method->name("nci_$methodname");
-                $method->symbol($methodname);
+            # Name-mangle NCI and multi methods to avoid conflict with vtable 
methods.
+            if ( $marker) {
+                if ( $marker =~ /MULTI/ ) {
+                    $method->type(Parrot::Pmc2c::Method::MULTI);
+                    $method->symbol($methodname);
+                }
+                elsif ( $marker !~ /VTABLE/ ) {
+                    $method->type(Parrot::Pmc2c::Method::NON_VTABLE);
+                    $method->name("nci_$methodname");
+                    $method->symbol($methodname);
+                }
             }
 
+            # To be deprecated
             parse_mmds( $method, $filename, $lineno )
                 if $methodblock =~ /\bMMD_(\w+):/;
 

Reply via email to