From de1288467873b35338edf4dad057090314f3f539 Mon Sep 17 00:00:00 2001 From: Christoph Otto Date: Thu, 25 Jun 2009 23:47:17 +0000 Subject: [PATCH] [pmcc] finish code to emit class_init, now for cleanup git-svn-id: https://svn.parrot.org/parrot/branches/pmc_pct@39785 d31e2699-5ff4-0310-a27c-f18f2fbe73fe --- compilers/pmcc/src/builtins.pir | 4 ++ compilers/pmcc/src/emitter/c.pir | 2 - compilers/pmcc/src/emitter/pmc.pm | 58 +++++++++++++++++++--------- compilers/pmcc/src/nodes.pir | 30 +++++++------- compilers/pmcc/src/parser/actions.pm | 40 ++++++++++++++++--- compilers/pmcc/src/parser/grammar.pg | 10 +++-- 6 files changed, 98 insertions(+), 46 deletions(-) diff --git a/compilers/pmcc/src/builtins.pir b/compilers/pmcc/src/builtins.pir index 6390e8695b..a4f80ab720 100644 --- a/compilers/pmcc/src/builtins.pir +++ b/compilers/pmcc/src/builtins.pir @@ -147,7 +147,11 @@ is not intended to be a general-use sub. frozen = pio.'readall'(filename) $P0 = thaw frozen .return ($P0) +.end +.sub 'die' + .param string msg + die msg .end # Extend various Parrot's PMCs to play nicely with NQP. diff --git a/compilers/pmcc/src/emitter/c.pir b/compilers/pmcc/src/emitter/c.pir index 0358f16755..8c107d8f20 100644 --- a/compilers/pmcc/src/emitter/c.pir +++ b/compilers/pmcc/src/emitter/c.pir @@ -45,10 +45,8 @@ TODO: Parse c_body properly and implement all other functions. .param pmc pmclass .param pmc past .local string res - res = "{\n" $S0 = self.'!generate_children_body_part'(pmclass, past) concat res, $S0 - concat res, "}\n" .return (res) .end diff --git a/compilers/pmcc/src/emitter/pmc.pm b/compilers/pmcc/src/emitter/pmc.pm index 2f80e8c2e9..63f0ebb13e 100644 --- a/compilers/pmcc/src/emitter/pmc.pm +++ b/compilers/pmcc/src/emitter/pmc.pm @@ -311,6 +311,18 @@ Generate C file's contents for this PMC. =cut method generate_c_code($past) { + + my %vtables := thaw('../../vtable.frozen'); + #make sure there aren't any misnamed VTABLE functions + for self.past.vtables{'default'} { + if !%vtables{$_} { + #XXX: check that the return type and parameter types are good too + #XXX: show a nicer message that points to the failure + die("Found an invalid vtable function '"~$_~"'. Perhaps you misnamed it?"); + } + } + + self.pre_method_gen(); my $res := self.past ~ "\n\n" @@ -385,12 +397,6 @@ method generate_class_init_func() { @res.push( self.generate_multis() ); @res.push( self.generate_passes() ); - my $past := self.past; - if ($past) { - @res.push("/* class_init */\n"); - @res.push(PMC::Emitter::C.new().emit($past, $past)); - } - @res.push("\n}\n"); join('', @res); } @@ -521,16 +527,16 @@ method generate_passes() { @res.push(' } /* pass 2 */'); @res.push(' else {'); - my $hll := self.past.hll(); + my $hll := self.past.traits{'hll'}; - if $hll ne '' && elements(self.past.maps()) { + if $hll ne '' && elements(self.past.maps) { @res.push(' {'); @res.push(' /* Register this PMC as a HLL mapping */'); @res.push(' const INTVAL pmc_id = Parrot_get_HLL_id( interp, CONST_STRING_GEN(interp, "'~$hll~'"));'); @res.push(' if (pmc_id > 0) {'); - for self.past.maps() { + for self.past.maps { @res.push(' Parrot_register_HLL_type( interp, pmc_id, enum_class_'~$_~', entry);'); } @@ -539,18 +545,33 @@ method generate_passes() { @res.push(''); } - @res.push(' /* set up MRO and _namespace */'); - @res.push(' {'); - @res.push(' VTABLE * const vt = interp->vtables[entry];'); - @res.push(' vt->mro = Parrot_'~self.name~'_get_mro(interp, PMCNULL);'); - @res.push(' if (vt->ro_variant_vtable)'); - @res.push(' vt->ro_variant_vtable->mro = vt->mro;'); - @res.push(' }'); + @res.push(' /* set up MRO and _namespace */'); + @res.push(' {'); + @res.push(' VTABLE * const vt = interp->vtables[entry];'); + @res.push(' vt->mro = Parrot_'~self.name~'_get_mro(interp, PMCNULL);'); + @res.push(' if (vt->ro_variant_vtable)'); + @res.push(' vt->ro_variant_vtable->mro = vt->mro;'); + @res.push(' }'); @res.push(''); - @res.push(' Parrot_create_mro(interp, entry);'); + @res.push(' Parrot_create_mro(interp, entry);'); + for self.past.methods { + @res.push(' register_raw_nci_method_in_ns(interp, entry, F2DPTR(Parrot_'~self.name~'_nci_'~$_~'), CONST_STRING_GEN(interp, "'~$_~'"));'); + if self.past.methods{$_}{'attrs'}{'write'} { + @res.push(' Parrot_mark_method_writes(interp, entry, "nci_'~$_~'");'); + } + } + @res.push(''); - @res.push('}'); + if self.past.class_init { + @res.push(' /* class_init */'); + @res.push(' {'); + @res.push(PMC::Emitter::C.new().emit(self.past, self.past.class_init)); + #@res.push(self.past.class_init); + @res.push(' }'); + } + + @res.push(' }'); join("\n", @res); } @@ -575,7 +596,6 @@ method generate_get_vtable_func() { else { $first_parent := @other_parents.shift; } - say("first parent is "~$first_parent); @res.push('PARROT_EXPORT'); @res.push('PARROT_CANNOT_RETURN_NULL'); diff --git a/compilers/pmcc/src/nodes.pir b/compilers/pmcc/src/nodes.pir index 116b478284..267de7cc55 100644 --- a/compilers/pmcc/src/nodes.pir +++ b/compilers/pmcc/src/nodes.pir @@ -41,6 +41,9 @@ PMC class by it self. res.'init'(children :flat, adverbs :flat :named) # Initialize various attributes + $P1 = new ['ResizableStringArray'] + res.'attr'('does', $P1, 1) + $P1 = new ['ResizableStringArray'] res.'attr'('parents', $P1, 1) @@ -66,15 +69,22 @@ PMC class by it self. $P1 = new ['Hash'] res.'attr'('traits', $P1, 1) - $P1 = new ['String'] - res.'attr'('hll', $P1, 1) - $P1 = new ['ResizableStringArray'] res.'attr'('maps', $P1, 1) .return (res) .end +=item C + +How does this PMC act?. + +=cut + +.sub 'does' :method + .tailcall self.'attr'('does',0,0) +.end + =item C Get PMC parents. @@ -165,20 +175,6 @@ Get PMC traits. .tailcall self.'attr'('traits',0,0) .end -=item hll - -Get PMC hll name. - -=cut - -.sub 'hll' :method - .tailcall self.'attr'('hll',0,0) -.end - -.sub 'set_hll' :method - .param pmc name - .tailcall self.'attr'('hll',name,1) -.end .sub 'maps' :method .tailcall self.'attr'('maps',0,0) diff --git a/compilers/pmcc/src/parser/actions.pm b/compilers/pmcc/src/parser/actions.pm index 124f6412f8..9664fc8770 100644 --- a/compilers/pmcc/src/parser/actions.pm +++ b/compilers/pmcc/src/parser/actions.pm @@ -44,23 +44,30 @@ method traits($/, $key) { our $?PMC; if $key eq 'does' { + $?PMC.does.push(~$); } elsif $key eq 'group' { + #XXX: only one group is possible + #XXX: only valid for dynpmcs + $?PMC.traits{'group'} := ~$; } elsif $key eq 'hll' { - $?PMC.set_hll(~$); + #XXX: only one HLL is possible + $?PMC.traits{'hll'} := ~$; } elsif $key eq 'provides' { - $?PMC.provides().push(~$); + $?PMC.provides.push(~$); } elsif $key eq 'extends' { - $?PMC.parents().push(~$); + #XXX: some sanity checking here would probably be advisable + $?PMC.parents.push(~$); $?PMC.thaw_pmc_attrs(~$); } elsif $key eq 'maps' { - $?PMC.maps().push(~$); + $?PMC.maps.push(~$); } elsif $key eq 'lib' { + $?PMC.traits{'lib'} := ~$; } else { $?PMC.traits{$key} := 1; @@ -137,25 +144,42 @@ method vtable($/) { $.ast ); $past := $.ast; + + my %attrs; + for $ { + %attrs{~$_} := 1; + } + $past := %attrs; + make $past; } method method($/) { #say('METHOD ' ~$); + my $method_body := $.ast; + my $past := PAST::Block.new( :name(~$), :blocktype('declaration'), :returns('void'), # PCC METHODS returns void :node($/), - $.ast + $method_body ); #$past := $.ast; + + my %attrs; + for $ { + %attrs{~$_} := 1; + } + $past := %attrs; + make $past; } method multi($/) { #say('MULTI ' ~$); + my $past := PAST::Block.new( :name(~$), :blocktype('method'), @@ -201,6 +225,12 @@ method multi($/) { $past := join(',', @long_sig); $past := "multi_" ~ $past.name ~ "_" ~ join('_', @long_sig); + my %attrs; + for $ { + %attrs{~$_} := 1; + } + $past := %attrs; + make $past; } diff --git a/compilers/pmcc/src/parser/grammar.pg b/compilers/pmcc/src/parser/grammar.pg index 48723952cc..b19c1beb2b 100644 --- a/compilers/pmcc/src/parser/grammar.pg +++ b/compilers/pmcc/src/parser/grammar.pg @@ -118,22 +118,26 @@ rule class_init { rule method { 'METHOD' :: [ - [ '(' ')' ] + [ '(' ')' * ] | <.panic: "Unexpected METHOD content"> ] {*} } rule vtable { - 'VTABLE' :: + 'VTABLE' :: * {*} } rule multi { - 'MULTI' :: + 'MULTI' :: * {*} } +rule method_attr { + ':' +} + # Nested list of something rule c_body { '{' * '}' {*}