use v6-alpha; class KindaPerl6::Visitor::Emit::Perl5 { has $.visitor_args; # This visitor is a perl5 emitter method visit ( $node ) { $node.emit_perl5($.visitor_args{'secure'}); }; } class CompUnit { sub set_secure_mode( $args_secure ) { my $value := '0'; if ($args_secure) { $value := '1' }; return 'use constant KP6_DISABLE_INSECURE_CODE => ' ~ $value ~ ';' ~ Main::newline(); }; method emit_perl5( $args_secure ) { $KindaPerl6::Visitor::Emit::Perl5::current_compunit := $.name; my $source := ''; if ($.body) { $source := $.body.emit_perl5; }; '{ package ' ~ $.name ~ '; ' ~ Main::newline() ~ '# Do not edit this file - Perl 5 generated by ' ~ $Main::_V6_COMPILER_NAME ~ Main::newline() ~ '# AUTHORS, COPYRIGHT: Please look at the source file.' ~ Main::newline() ~ 'use v5;' ~ Main::newline() ~ 'use strict;' ~ Main::newline() ~ 'no strict "vars";' ~ Main::newline() ~ set_secure_mode($args_secure) ~ 'use '~ Main::get_compiler_target_runtime() ~';' ~ Main::newline() #~ 'use KindaPerl6::Runtime::Perl6::Hash; ' ~ 'my $_MODIFIED; INIT { $_MODIFIED = {} }' ~ Main::newline() # XXX - not sure about $_ scope ~ 'INIT { ' ~ '$_ = ::DISPATCH($::Scalar, "new", { modified => $_MODIFIED, name => "$_" } ); ' ~ '}' ~ Main::newline() ~ $source ~ Main::newline() ~ '; 1 }' ~ Main::newline(); } } class Val::Int { method emit_perl5 { # $.int '::DISPATCH( $::Int, \'new\', ' ~ $.int ~ ' )' ~ Main::newline(); } } class Val::Bit { method emit_perl5 { # $.bit '::DISPATCH( $::Bit, \'new\', ' ~ $.bit ~ ' )' ~ Main::newline(); } } class Val::Num { method emit_perl5 { #$.num '::DISPATCH( $::Num, \'new\', ' ~ $.num ~ ' )' ~ Main::newline(); } } class Val::Buf { method emit_perl5 { # '\'' ~ $.buf ~ '\'' '::DISPATCH( $::Str, \'new\', ' ~ Main::singlequote() ~ Main::mangle_string( $.buf ) ~ Main::singlequote ~ ' )' ~ Main::newline(); } } class Val::Char { method emit_perl5 { '::DISPATCH( $::Str, \'new\', chr( ' ~ $.char ~ ' ) )' ~ Main::newline(); } } class Val::Undef { method emit_perl5 { #'(undef)' '$::Undef' } } class Val::Object { method emit_perl5 { die 'Emitting of Val::Object not implemented'; # 'bless(' ~ %.fields.perl ~ ', ' ~ $.class.perl ~ ')'; } } class Native::Buf { method emit_perl5 { die 'Emitting of Native::Buf not implemented'; # '\'' ~ $.buf ~ '\'' } } class Lit::Seq { method emit_perl5 { '(' ~ (@.seq.>>emit_perl5).join(', ') ~ ')'; } } class Lit::Array { method emit_perl5 { # this is not a Perl 6 object, objects are created with a high-level Array.new or List.new '{ _array => [' ~ (@.array.>>emit_perl5).join(', ') ~ '] }' ~ Main::newline(); } } class Lit::Hash { method emit_perl5 { # this is not a Perl 6 object, objects are created with a high-level Hash.new my $fields := @.hash; my $str := ''; my $field; for @$fields -> $field { $str := $str ~ '[ ' ~ ($field[0]).emit_perl5 ~ ', ' ~ ($field[1]).emit_perl5 ~ ' ],'; }; $str ~ Main::newline(); } } class Lit::Pair { method emit_perl5 { '::DISPATCH( $::Pair, \'new\', ' ~ '{ key => ' ~ $.key.emit_perl5 ~ ', value => ' ~ $.value.emit_perl5 ~ ' } )' ~ Main::newline(); } } class Lit::NamedArgument { method emit_perl5 { '::DISPATCH( $::NamedArgument, \'new\', ' ~ '{ _argument_name_ => ' ~ $.key.emit_perl5 ~ ', value => ' ~ ( defined($.value) ?? $.value.emit_perl5 !! 'undef' ) # XXX ~ ' } )' ~ Main::newline(); } } class Lit::SigArgument { method emit_perl5 { '::DISPATCH( $::Signature::Item, \'new\', ' ~ '{ ' ~ 'sigil => \'' ~ $.key.sigil ~ '\', ' ~ 'twigil => \'' ~ $.key.twigil ~ '\', ' ~ 'name => \'' ~ $.key.name ~ '\', ' ~ 'value => ' ~ ( defined($.value) ?? $.value.emit_perl5 !! 'undef' ) ~ ', ' # XXX ~ 'has_default => ' ~ $.has_default.emit_perl5 ~ ', ' ~ 'is_named_only => ' ~ $.is_named_only.emit_perl5 ~ ', ' ~ 'is_optional => ' ~ $.is_optional.emit_perl5 ~ ', ' ~ 'is_slurpy => ' ~ $.is_slurpy.emit_perl5 ~ ', ' ~ 'is_multidimensional => ' ~ $.is_multidimensional.emit_perl5 ~ ', ' ~ 'is_rw => ' ~ $.is_rw.emit_perl5 ~ ', ' ~ 'is_copy => ' ~ $.is_copy.emit_perl5 ~ ', ' ~ ' } )' ~ Main::newline(); } } class Lit::Code { method emit_perl5 { if ($.CATCH) { 'do { eval {' ~ self.emit_perl5_declarations ~ self.emit_perl5_body ~ '};if ($@) {' ~ $.CATCH.emit_perl5 ~ '}}'; } else { 'do {' ~ self.emit_perl5_declarations ~ self.emit_perl5_body ~ '}' } }; method emit_perl5_body { (@.body.>>emit_perl5).join('; '); }; method emit_perl5_signature { $.sig.emit_perl5 }; method emit_perl5_declarations { my $s; my $name; for @($.pad.lexicals) -> $name { my $decl := Decl.new( decl => 'my', type => '', var => Var.new( sigil => '', twigil => '', name => $name, namespace => [ ], ), ); $s := $s ~ $name.emit_perl5 ~ ';' ~ Main::newline(); }; return $s; }; method emit_perl5_arguments { my $array_ := Var.new( sigil => '@', twigil => '', name => '_', namespace => [ ], ); my $hash_ := Var.new( sigil => '%', twigil => '', name => '_', namespace => [ ], ); my $CAPTURE := Var.new( sigil => '$', twigil => '', name => 'CAPTURE', namespace => [ ],); my $CAPTURE_decl := Decl.new(decl=>'my',type=>'',var=>$CAPTURE); my $str := ''; $str := $str ~ $CAPTURE_decl.emit_perl5; $str := $str ~ (Decl.new(decl=>'my',type=>'',var=>$array_)).emit_perl5; $str := $str ~ '::DISPATCH_VAR($CAPTURE,"STORE",::CAPTURIZE(\@_));'; # XXX s/assign/bind/ ? my $bind_array := Assign.new(parameters=>$array_,arguments=> Call.new(invocant => $CAPTURE,method => 'array',arguments => [])); $str := $str ~ $bind_array.emit_perl5 ~ ';'; my $bind_hash := Bind.new(parameters=>$hash_, arguments=> Call.new(invocant => $CAPTURE,method => 'hash', arguments => [])); $str := $str ~ $bind_hash.emit_perl5 ~ ';'; my $i := 0; my $field; $str := $str ~ '{ my $_param_index = 0; '; for @($.sig.positional) -> $field { my $bind_named := Bind.new( parameters => $field.key, arguments => Call.new( invocant => $hash_, arguments => [ Val::Buf.new( buf => ($field.key).name ) ], method => 'LOOKUP', ), ); my $bind_default := Bind.new( parameters => $field.key, arguments => $field.value, ); $str := $str ~ ' if ( ::DISPATCH( $GLOBAL::Code_exists, ' ~ ' \'APPLY\', ' ~ ' ::DISPATCH( ' ~ ' $Hash__, \'LOOKUP\', ' ~ ' ::DISPATCH( $::Str, \'new\', \'' ~ ($field.key).name ~ '\' ) ' ~ ' ) )->{_value} ' ~ ' ) ' ~ ' { ' ~ $bind_named.emit_perl5 ~ ' } ' ~ ' elsif ( ::DISPATCH( $GLOBAL::Code_exists, ' ~ ' \'APPLY\', ' ~ ' ::DISPATCH( ' ~ ' $List__, \'INDEX\', ' ~ ' ::DISPATCH( $::Int, \'new\', $_param_index ) ' ~ ' ) )->{_value} ' ~ ' ) ' ~ ' { ' ~ ($field.key).emit_perl5 ~ ' = ::DISPATCH( ' ~ ' $List__, \'INDEX\', ' ~ ' ::DISPATCH( $::Int, \'new\', $_param_index++ ) ' ~ ' ); ' ~ ' } '; if ($field.has_default).bit { $str := $str ~ ' else { ' ~ $bind_default.emit_perl5 ~ ' } '; } $i := $i + 1; }; $str := $str ~ '} '; return $str; }; } class Lit::Object { method emit_perl5 { # $.class ~ '->new( ' ~ @.fields.>>emit_perl5.join(', ') ~ ' )'; my $fields := @.fields; my $str := ''; # say @fields.map(sub { $_[0].emit_perl5 ~ ' => ' ~ $_[1].emit_perl5}).join(', ') ~ ')'; my $field; for @$fields -> $field { $str := $str ~ '::DISPATCH( $::NamedArgument, "new", ' ~ '{ ' ~ '_argument_name_ => ' ~ ($field[0]).emit_perl5 ~ ', ' ~ 'value => ' ~ ($field[1]).emit_perl5 ~ ', ' ~ ' } ), ' ; }; '::DISPATCH( $::' ~ $.class ~ ', \'new\', ' ~ $str ~ ' )' ~ Main::newline(); } } class Assign { method emit_perl5 { # TODO - same as ::Bind my $node := $.parameters; if $node.isa( 'Var' ) && @($node.namespace) { # it's a global, # and it should be autovivified $node := Apply.new( code => Var.new( name => 'ternary:', twigil => '', sigil => '&', namespace => [ 'GLOBAL' ], ), arguments => [ Apply.new( arguments => [ $node ], code => Var.new( name => 'VAR_defined', twigil => '', sigil => '&', namespace => [ 'GLOBAL' ] ), ), $node, Bind.new( 'parameters' => $node, 'arguments' => Call.new( 'invocant' => Var.new( name => '::Scalar', twigil => '', sigil => '$', namespace => [ ] ), 'method' => 'new', 'hyper' => '', ), ) ], ); }; '::DISPATCH_VAR( ' ~ $node.emit_perl5 ~ ', \'STORE\', ' ~ $.arguments.emit_perl5 ~ ' )' ~ Main::newline(); } } class Var { method emit_perl5 { # Normalize the sigil here into $ # $x => $x # @x => $List_x # %x => $Hash_x # &x => $Code_x my $table := { '$' => '$', '@' => '$List_', '%' => '$Hash_', '&' => '$Code_', }; if $.twigil eq '.' { return '::DISPATCH( $self, "' ~ $.name ~ '" )' ~ Main::newline() }; if $.twigil eq '!' { return '$self->{_value}{"' ~ $.name ~ '"}' ~ Main::newline() }; if $.name eq '/' { return $table{$.sigil} ~ 'MATCH' }; if @($.namespace) { my $s; my $var := Main::mangle_name( $.sigil, $.twigil, $.name, $.namespace ); if $.sigil eq '$' { $s := '$::Scalar'; }; if $.sigil eq '&' { $s := '$::Routine'; }; if $.sigil eq '%' { $s := '$::HashContainer'; }; if $.sigil eq '@' { $s := '$::ArrayContainer'; }; #return $var; # XXX doesn't work??? return ' ( ' ~ $var ~ ' = ' ~ $var ~ ' || ::DISPATCH( ' ~ $s ~ ', "new", ) ' ~ ' ) ' ~ Main::newline(); } return Main::mangle_name( $.sigil, $.twigil, $.name, $.namespace ); }; #method perl { # # this is used by the signature emitter # # XXX rename this node, it may clash with a User class # '::DISPATCH( $::Var, "new", { ' # ~ 'sigil => \'' ~ $.sigil ~ '\', ' # ~ 'twigil => \'' ~ $.twigil ~ '\', ' # ~ 'name => \'' ~ $.name ~ '\', ' # ~ 'namespace => [ ], ' # ~ '} )' ~ Main::newline() #} } class Bind { method emit_perl5 { # XXX - replace Bind with .BIND if $.parameters.isa('Call') || ( $.parameters.isa('Var') && ( ($.parameters).sigil eq '@' ) ) { return '::DISPATCH_VAR( ' ~ $.parameters.emit_perl5 ~ ', "BIND", ' ~ $.arguments.emit_perl5 ~ ' )' }; # XXX - replace Bind with Assign #if $.parameters.isa('Call') #{ # return Assign.new(parameters=>$.parameters,arguments=>$.arguments).emit_perl5; #}; my $str := '::MODIFIED(' ~ $.parameters.emit_perl5 ~ ');' ~ Main::newline(); $str := $str ~ $.parameters.emit_perl5 ~ ' = ' ~ $.arguments.emit_perl5; return 'do {'~$str~'}'; } } class Proto { method emit_perl5 { return '$::'~$.name; } } class Call { method emit_perl5 { my $invocant; if $.invocant.isa( 'Proto' ) { if $.invocant.name eq 'self' { $invocant := '$self'; } else { $invocant := $.invocant.emit_perl5; } } else { $invocant := $.invocant.emit_perl5; }; if $invocant eq 'self' { $invocant := '$self'; }; my $meth := $.method; if $meth eq 'postcircumfix:<( )>' { $meth := ''; }; my $call := (@.arguments.>>emit_perl5).join(', '); if ($.hyper) { # TODO - hyper + role '::DISPATCH( $::List, "new", { _array => [ ' ~ 'map { ::DISPATCH( $_, "' ~ $meth ~ '", ' ~ $call ~ ') } ' ~ '@{ ::DISPATCH( ' ~ $invocant ~ ', "array" )->{_value}{_array} } ' ~ '] } )' ~ Main::newline(); } else { if ( $meth eq '' ) { # $var.() '::DISPATCH( ' ~ $invocant ~ ', \'APPLY\', ' ~ $call ~ ' )' ~ Main::newline() } else { '::DISPATCH( ' ~ $invocant ~ ', ' ~ '\'' ~ $meth ~ '\', ' ~ $call ~ ' )' ~ Main::newline() }; }; } } class Apply { method emit_perl5 { if ( $.code.isa('Var') ) && ( $.code.name eq 'self' ) { # dlocaus @ #perl6 irc.freenode.net # fglock's comment on this work around # http://irclog.perlgeek.de/perl6/2007-11-21#i_148959 # He stated that the code is return $self, instead of trying to parse # self(). # Removing this hack breaks the test cases when you do: # perl Makefile.PL ; make forcerecompile ; make test # November 21st, 2007 10:51am PDT. return '$self'; } if ( $.code.isa('Var') ) && ( $.code.name eq 'infix:<&&>' ) { # hack for shortcircuiting "&&" # as an alternative hack, see Visitor::ShortCircuit return 'do { ' ~ 'my $_tmp1 = ' ~ ((@.arguments[0]).emit_perl5) ~ '; ' ~ '::DISPATCH( $_tmp1, "true" )->{_value} ' ~ '? ' ~ ((@.arguments[1]).emit_perl5) ~ ': ::DISPATCH( $::Bit, "new", 0 )' ~ ' }' ~ Main::newline(); } if ( $.code.isa('Var') ) && ( $.code.name eq 'infix:<||>' ) { # hack for shortcircuiting "||" # as an alternative hack, see Visitor::ShortCircuit return 'do { ' ~ 'my $_tmp1 = ' ~ ((@.arguments[0]).emit_perl5) ~ '; ' ~ '::DISPATCH( $_tmp1, "true" )->{_value} ' ~ '? $_tmp1' ~ ': ' ~ ((@.arguments[1]).emit_perl5) ~ ' }' ~ Main::newline(); } if ( $.code.isa('Var') ) && ( $.code.name eq 'make' ) { # hack for "make" (S05) return '::DISPATCH_VAR( ' ~ '$GLOBAL::_REGEX_RETURN_, "STORE", ' ~ ((@.arguments[0]).emit_perl5) ~ '' ~ ' )' ~ Main::newline(); } return '::DISPATCH( ' ~ $.code.emit_perl5 ~ ', \'APPLY\', ' ~ (@.arguments.>>emit_perl5).join(', ') ~ ' )' ~ Main::newline(); } } class Return { method emit_perl5 { # call .FETCH just in case it's a Container # 'return( ::DISPATCH(' ~ $.result.emit_perl5 ~ ', "FETCH" ) )' ~ Main::newline(); #'do { print Main::perl(caller(),' ~ $.result.emit_perl5 ~ '); return(' ~ $.result.emit_perl5 ~ ') }'; 'return(' ~ $.result.emit_perl5 ~ ')' ~ Main::newline(); } } class If { method emit_perl5 { 'do { if (::DISPATCH(::DISPATCH(' ~ $.cond.emit_perl5 ~ ',"true"),"p5landish") ) ' ~ ( $.body ?? '{ ' ~ $.body.emit_perl5 ~ ' } ' !! '{ } ' ) ~ ( $.otherwise ?? ' else { ' ~ $.otherwise.emit_perl5 ~ ' }' !! ' else { ::DISPATCH($::Bit, "new", 0) }' ) ~ ' }' ~ Main::newline(); } } class While { method emit_perl5 { my $cond := $.cond; if $cond.isa( 'Var' ) && $cond.sigil eq '@' { } else { $cond := Apply.new( code => Var.new(sigil=>'&',twigil=>'',name=>'prefix:<@>',namespace => [ 'GLOBAL' ],), arguments => [$cond] ); } 'do { while (::DISPATCH(::DISPATCH(' ~ $.cond.emit_perl5 ~ ',"true"),"p5landish") ) ' ~ ' { ' ~ $.body.emit_perl5 ~ ' } }' ~ Main::newline(); } } class Decl { method emit_perl5 { my $decl := $.decl; my $name := $.var.name; if $decl eq 'has' { # obsolete - "has" is handled by Visitor::MetaClass / Perl5::MOP return 'sub ' ~ $name ~ ' { ' ~ '@_ == 1 ' ~ '? ( $_[0]->{' ~ $name ~ '} ) ' ~ ': ( $_[0]->{' ~ $name ~ '} = $_[1] ) ' ~ '}'; }; my $create := ', \'new\', { modified => $_MODIFIED, name => \'' ~ $.var.emit_perl5 ~ '\' } ) '; if $decl eq 'our' { my $s; # ??? use vars --> because compile-time scope is too tricky to use 'our' # ??? $s := 'use vars \'' ~ $.var.emit_perl5 ~ '\'; '; $s := 'our '; if ($.var).sigil eq '$' { return $s ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Scalar' ~ $create ~ ' unless defined ' ~ $.var.emit_perl5 ~ '; ' ~ 'INIT { ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Scalar' ~ $create ~ ' unless defined ' ~ $.var.emit_perl5 ~ '; ' ~ '}' ~ Main::newline() }; if ($.var).sigil eq '&' { return $s ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Routine' ~ $create ~ ';' ~ Main::newline(); }; if ($.var).sigil eq '%' { return $s ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::HashContainer' ~ $create ~ ';' ~ Main::newline(); }; if ($.var).sigil eq '@' { return $s ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::ArrayContainer' ~ $create ~ ';' ~ Main::newline(); }; return $s ~ $.var.emit_perl5 ~ Main::newline(); }; if ($.var).sigil eq '$' { return $.decl ~ ' ' # ~ $.type ~ ' ' ~ $.var.emit_perl5 ~ '; ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Scalar' ~ $create ~ ' unless defined ' ~ $.var.emit_perl5 ~ '; ' ~ 'INIT { ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Scalar' ~ $create ~ '}' ~ Main::newline() ; }; if ($.var).sigil eq '&' { return $.decl ~ ' ' # ~ $.type ~ ' ' ~ $.var.emit_perl5 ~ '; ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Routine' ~ $create ~ ' unless defined ' ~ $.var.emit_perl5 ~ '; ' ~ 'INIT { ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::Routine' ~ $create ~ '}' ~ Main::newline() ; }; if ($.var).sigil eq '%' { return $.decl ~ ' ' # ~ $.type ~ ' ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::HashContainer' ~ $create ~ '; ' ~ Main::newline(); }; if ($.var).sigil eq '@' { return $.decl ~ ' ' # ~ $.type ~ ' ' ~ $.var.emit_perl5 ~ ' = ::DISPATCH( $::ArrayContainer' ~ $create ~ '; ' ~ Main::newline(); }; return $.decl ~ ' ' # ~ $.type ~ ' ' ~ $.var.emit_perl5; } } class Sig { method emit_perl5 { my $inv := '$::Undef'; if $.invocant.isa( 'Var' ) { $inv := $.invocant.perl; } my $pos; my $decl; for @($.positional) -> $decl { $pos := $pos ~ $decl.emit_perl5 ~ ', '; }; my $named := ''; # TODO '::DISPATCH( $::Signature, "new", { ' ~ 'invocant => ' ~ $inv ~ ', ' ~ 'array => ::DISPATCH( $::List, "new", { _array => [ ' ~ $pos ~ ' ] } ), ' # ~ 'hash => ::DISPATCH( $::Hash, "new", { _hash => { ' ~ $named ~ ' } } ), ' ~ 'return => $::Undef, ' ~ '} )' ~ Main::newline(); }; } class Lit::Capture { method emit_perl5 { my $s := '::DISPATCH( $::Capture, "new", { '; if defined $.invocant { $s := $s ~ 'invocant => ' ~ $.invocant.emit_perl5 ~ ', '; } else { $s := $s ~ 'invocant => $::Undef, ' }; if defined $.array { $s := $s ~ 'array => ::DISPATCH( $::List, "new", { _array => [ '; my $item; for @.array -> $item { $s := $s ~ $item.emit_perl5 ~ ', '; } $s := $s ~ ' ] } ),'; }; if defined $.hash { $s := $s ~ 'hash => ::DISPATCH( $::Hash, "new", '; my $item; for @.hash -> $item { $s := $s ~ '[ ' ~ ($item[0]).emit_perl5 ~ ', ' ~ ($item[1]).emit_perl5 ~ ' ], '; } $s := $s ~ ' ),'; }; return $s ~ ' } )' ~ Main::newline(); }; } class Lit::Subset { method emit_perl5 { '::DISPATCH( $::Subset, "new", { ' ~ 'base_class => ' ~ $.base_class.emit_perl5 ~ ', ' ~ 'block => ' ~ 'sub { local $_ = shift; ' ~ ($.block.block).emit_perl5 ~ ' } ' # XXX ~ ' } )' ~ Main::newline(); } } class Method { method emit_perl5 { '::DISPATCH( $::Code, \'new\', { ' ~ 'code => sub { ' ~ Main::newline() ~ '# emit_perl5_declarations' ~ Main::newline() ~ $.block.emit_perl5_declarations ~ Main::newline() ~ '# get $self' ~ Main::newline() ~ '$self = shift; ' ~ Main::newline() ~ '# emit_perl5_arguments' ~ Main::newline() ~ $.block.emit_perl5_arguments ~ Main::newline() ~ '# emit_perl5_body' ~ Main::newline() ~ $.block.emit_perl5_body ~ ' }, ' ~ 'signature => ' ~ $.block.emit_perl5_signature ~ ', ' ~ ' } )' ~ Main::newline(); } } class Sub { method emit_perl5 { '::DISPATCH( $::Code, \'new\', { ' ~ 'code => sub { ' ~ $.block.emit_perl5_declarations ~ $.block.emit_perl5_arguments ~ $.block.emit_perl5_body ~ ' }, ' ~ 'signature => ' ~ $.block.emit_perl5_signature ~ ', ' ~ ' } )' ~ Main::newline(); } } class Macro { method emit_perl5 { '::DISPATCH( $::Macro, \'new\', { ' ~ 'code => sub { ' ~ $.block.emit_perl5_declarations ~ $.block.emit_perl5_arguments ~ $.block.emit_perl5_body ~ ' }, ' ~ 'signature => ' ~ $.block.emit_perl5_signature ~ ', ' ~ ' } )' ~ Main::newline(); } } class Do { method emit_perl5 { 'do { ' ~ $.block.emit_perl5 ~ ' }' ~ Main::newline(); } } class BEGIN { method emit_perl5 { 'INIT { ' ~ $.block.emit_perl5 ~ ' }' } } class Use { method emit_perl5 { if ($.mod eq 'v6') { return Main::newline() ~ '#use v6' ~ Main::newline(); } if ( $.perl5 ) { return 'use ' ~ $.mod ~ ';$::' ~ $.mod ~ '= KindaPerl6::Runtime::Perl5::Wrap::use5(\'' ~ $.mod ~ '\')'; } else { return 'use ' ~ $.mod; } } } =begin =head1 NAME KindaPerl6::Perl5::Emit::Perl5 - Code generator for KindaPerl6-in-Perl5 =head1 DESCRIPTION This module generates Perl 5 code for the KindaPerl6 compiler. This is currently the primary and the most complete emitter. The runtime is located in F. =head1 AUTHORS The Pugs Team Eperl6-compiler@perl.orgE. =head1 SEE ALSO The Perl 6 homepage at L. The Pugs homepage at L. =head1 COPYRIGHT Copyright 2007 by Flavio Soibelmann Glock and others. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L =end