# New Ticket Created by Sam Ruby # Please include the string: [perl #31975] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31975 >
Leopold Toetsch wrote: > Sam Ruby <[EMAIL PROTECTED]> wrote: > >>I'm not overly concerned about __init methods, in fact, my concern is >>the opposite: I'd like to solicit opinions on the viability of extending >>pmc2c2.pl to enable non-vtable methods to be defined, in C, in the .pmc >>file itself. > > That sounds great. > > METHOD find(PMC* substr) { > } How about: METHOD INTVAL find(PMC* substr) { } Patch attached. Should the Object parameter be named "pmc" or "self"? - Sam Ruby P.S. I miss embracing elses.
Index: classes/perlstring.pmc =================================================================== RCS file: /cvs/public/parrot/classes/perlstring.pmc,v retrieving revision 1.87 diff -u -r1.87 perlstring.pmc --- classes/perlstring.pmc 21 Jul 2004 08:45:46 -0000 1.87 +++ classes/perlstring.pmc 13 Oct 2004 20:25:53 -0000 @@ -21,24 +21,26 @@ #include "parrot/parrot.h" #include "parrot/perltypes.h" -static PMC* -string_lower(Interp *interpreter, PMC *self) -{ - STRING *s = string_downcase(interpreter, PMC_str_val(self)); - PMC *ret = pmc_new(interpreter, enum_class_PerlString); - string_set(interpreter, PMC_str_val(ret), s); - return ret; -} - pmclass PerlString extends perlscalar { void class_init () { - /* this should be autmatically done - probably */ - if (pass) { - enter_nci_method(INTERP, enum_class_PerlString, - F2DPTR(string_lower), - "lower", "PIO"); - } + } + +/* + +=item C<void* lower(void *next)> + +downcase this string + +=cut + +*/ + + METHOD PMC* lower() { + STRING *s = string_downcase(interpreter, PMC_str_val(pmc)); + PMC *ret = pmc_new(interpreter, enum_class_PerlString); + string_set(interpreter, PMC_str_val(ret), s); + return ret; } /* Index: classes/pmc2c2.pl =================================================================== RCS file: /cvs/public/parrot/classes/pmc2c2.pl,v retrieving revision 1.17 diff -u -r1.17 pmc2c2.pl --- classes/pmc2c2.pl 8 Sep 2004 05:25:12 -0000 1.17 +++ classes/pmc2c2.pl 13 Oct 2004 20:25:54 -0000 @@ -363,6 +363,7 @@ (?:/\*.*?\*/)? # C-like comments )* + (METHOD\s+)? #method flag (\w+\**) #type \s+ (\w+) #method name @@ -380,7 +381,7 @@ while ($classblock =~ s/($signature_re)//) { $lineno += count_newlines($1); - my ($type, $methodname, $parameters) = ($2,$3,$4); + my ($flag, $type, $methodname, $parameters) = ($2,$3,$4,$5); my ($methodblock, $rema, $lines) = extract_balanced($classblock); $lineno += $lines; $methodblock = "" if $opt{nobody}; @@ -390,7 +391,8 @@ 'body' => $methodblock, 'line' => $lineno, 'type' => $type, - 'parameters' => $parameters + 'parameters' => $parameters, + 'loc' => "vtable" }; } else { @@ -401,7 +403,8 @@ 'body' => $methodblock, 'line' => $lineno, 'type' => $type, - 'parameters' => $parameters + 'parameters' => $parameters, + 'loc' => $flag ? "nci" : "vtable" }; } $classblock = $rema; Index: lib/Parrot/Pmc2c.pm =================================================================== RCS file: /cvs/public/parrot/lib/Parrot/Pmc2c.pm,v retrieving revision 1.41 diff -u -r1.41 Pmc2c.pm --- lib/Parrot/Pmc2c.pm 8 Oct 2004 07:08:36 -0000 1.41 +++ lib/Parrot/Pmc2c.pm 13 Oct 2004 20:25:54 -0000 @@ -395,14 +395,71 @@ } } -=item C<rewrite_method($class, $method, $super, $super_table)> +=item C<proto($type,$parameters)> -Rewrites the method body performing the various macro subsitiutions for +Determines the prototype (argument signature) for a method body +(see F<src/call_list>). + +=cut + +my %calltype = ( + "char" => "c", + "short" => "s", + "char" => "c", + "short" => "s", + "int" => "i", + "INTVAL" => "i", + "float" => "f", + "FLOATVAL" => "f", + "double" => "d", + "STRING*" => "t", + "char*" => "t", + "PMC*" => "P", + "short*" => "2", + "int*" => "3", + "long*" => "4", + "void" => "v", + "void*" => "b", + "void**" => "B", + #"BIGNUM*" => "???" # XXX +); + +sub proto ($$) { + my ($type, $parameters) = @_; + + # reduce to a comma separated set of types + $parameters =~ s/ +\w+(,|$)/,/g; + $parameters =~ s/ //g; + + # type method(interpreter, self, parameters...) + my $ret = $calltype{$type or "void"}; + $ret .= "IO"; + $ret .= join('', map {$calltype{$_} or "?"} split(/,/, $parameters)); + + return $ret; +} + +=item C<rewrite_nci_method($class, $method, $super, $super_table)> + +Rewrites the method body performing the various macro substitutions for +nci method bodies (see F<classes/pmc2c.pl>). + +=cut + +sub rewrite_nci_method ($$$) { + my ($class, $method) = @_; + local $_ = $_[2]; + return $_; +} + +=item C<rewrite_vtable_method($class, $method, $super, $super_table)> + +Rewrites the method body performing the various macro substitutions for vtable method bodies (see F<classes/pmc2c.pl>). =cut -sub rewrite_method ($$$$$) { +sub rewrite_vtable_method ($$$$$) { my ($class, $method, $super, $super_table) = @_; local $_ = $_[4]; @@ -465,8 +522,16 @@ $body =~ s/^\t/ /mg; $body =~ s/^[ ]{4}//mg; my $super = $self->{super}{$meth}; - my $total_body = rewrite_method($classname, $meth, $super, - $self->{super}, $body); + + my $total_body; + if ($method->{loc} eq 'vtable') { + $total_body = rewrite_vtable_method($classname, $meth, $super, + $self->{super}, $body); + } + else { + $total_body = rewrite_nci_method($classname, $meth, $body); + } + # now split into MMD if necessary: my $additional_bodies= ''; $total_body = substr $total_body, 1, -1; @@ -513,6 +578,7 @@ my ($self, $line) = @_; my $cout = ""; + # vtable methods foreach my $method (@{ $self->{vtable}{methods}} ) { my $meth = $method->{meth}; next if $meth eq 'class_init'; @@ -522,6 +588,15 @@ $cout .= $ret; } } + + # nci methods + foreach my $method (@{ $self->{methods}} ) { + next unless $method->{loc} eq 'nci'; + my $ret = $self->body($method, $line); + $line += count_newlines($ret); + $cout .= $ret; + } + $cout; } @@ -716,10 +791,32 @@ $cout .= <<"EOC"; } /* pass */ EOC + + # declare each nci method for this class + my $firstnci = 1; + foreach my $method (@{ $self->{methods} }) { + next unless $method->{loc} eq 'nci'; + my $proto = proto($method->{type}, $method->{parameters}); + $cout .= <<"EOC" if $firstnci; + if (pass) { +EOC + $cout .= <<"EOC"; + enter_nci_method(interp, enum_class_${classname}, + F2DPTR(Parrot_${classname}_$method->{meth}), + "$method->{meth}", "$proto"); +EOC + $firstnci = 0; + } + $cout .= <<"EOC" unless $firstnci; + } +EOC + + # include any class specific init code from the .pmc file $cout .= <<"EOC"; $class_init_code if (pass == 1) { EOC + # declare auxiliary variables for dyncpmc IDs foreach my $dynclass (keys %init_mmds) { next if $dynclass eq $classname;