# New Ticket Created by  Stephane Payrard 
# Please include the string:  [perl #51658]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=51658 >


# use v6-alpha;
# use Test;
# plan 3;
# test for lexical self.
# and for some pair parsing and printing.

# should print :
# hi
# :a
# :!a
# :a(1)
# :a<1>
# :a(" > ")


class A { method h { "hi" }; method g { if (1) { self.h(); }  } };
my $o = A.new;
# ok 'hi' eq $o.g()
say $o.h;

## See S02 for pair semantic
# note the test are dependant on the choice of the perl representation.

say :a.value;  # Method 'perl' not found for invocant of class 'Boolean'
# should print True or Bool::True

say :a.perl;
# ok :a.perl eq ':a'

say :!a.perl;
# ok :!a.perl eq ':!a'

# not that the printing representation does not yet parse
# for the next two examples.

my $a = 1 ;
say :$a.perl;
# ok :$a.perl eq ':a(1)'

my $a = "1";
say :$a.perl;
# ok :$a.perl eq ':a<1>'

my $a = " > ";
say :$a.perl;
# ok :$a.perl eq ':a<1>'


# TBD; parse, but does not yet print
# my @a; @a[0]=1;
# say :@a.perl;
-----------------------

affected files :
languages/perl6/src/parser/actions.pm
languages/perl6/src/parser/grammar.pg
languages/perl6/src/classes/Pair.pir

Index: languages/perl6/src/parser/actions.pm
===================================================================
--- languages/perl6/src/parser/actions.pm       (revision 26310)
+++ languages/perl6/src/parser/actions.pm       (working copy)
@@ -30,10 +30,12 @@
     our $?BLOCK;
     our @?BLOCK;
     our $?BLOCK_SIGNATURED;
+    our $?IS_METHOD;
+    our $?IN_METHOD;
     ##  when entering a block, use any $?BLOCK_SIGNATURED if it exists,
     ##  otherwise create an empty block with an empty first child to
     ##  hold any parameters we might encounter inside the block.
-    if ($key eq 'open') {
+    if $key eq 'open' {
         if $?BLOCK_SIGNATURED {
             $?BLOCK := $?BLOCK_SIGNATURED;
             $?BLOCK_SIGNATURED := 0;
@@ -62,8 +64,18 @@
         unless $?BLOCK.symbol('$!') {
             $init.push( PAST::Var.new( :name('$!'), :isdecl(1) ) );
             $?BLOCK.symbol( '$!', :scope('lexical') ); }
+        if $?IS_METHOD {
+            $init.push(PAST::Var.new(
+              :name('self'),
+              :isdecl(1)
+            ));
+            $?BLOCK.symbol('self', :scope('lexical'));
+            $?IS_METHOD := 0;
+           $init.push( PAST::Op.new( :inline( "    store_lex 'self', self")));
+        }
+
     }
-    if ($key eq 'close') {
+    if $key eq 'close' {
         my $past := @?BLOCK.shift();
         $?BLOCK := @?BLOCK[0];
         $past.push($($<statementlist>));
@@ -122,12 +134,12 @@
                               :pasttype('if'),
                               :node( $/ )
                             );
-    if ( $<else> ) {
+    if  $<else> {
         my $else := $( $<else>[0] );
         $else.blocktype('immediate');
         $past.push( $else );
     }
-    while ($count != 0) {
+    while $count != 0 {
         $count := $count - 1;
         $expr  := $( $<EXPR>[$count] );
         $then  := $( $<block>[$count] );
@@ -294,12 +306,12 @@
 method statement_prefix($/) {
     my $past := $($<statement>);
     my $sym := ~$<sym>;
-    if ($sym eq 'do') {
+    if $sym eq 'do' {
         # fall through, just use the statement itself
     }
     ## after the code in the try block is executed, bind $! to Undef,
     ## and set up the code to catch an exception, in case one is thrown
-    elsif ($sym eq 'try') {
+    elsif $sym eq 'try' {
         ##  Set up code to execute <statement> as a try node, and
         ##  set $! to Undef if successful.
         my $exitpir  := "    new %r, 'Undef'\n    store_lex '$!', %r";
@@ -319,62 +331,58 @@
 }


-method plurality_declarator($/) {
-    my $past := $( $<routine_declarator> );
-    if $<sym> eq 'multi' {
-        my $pirflags := ~ $past.pirflags();
-        my $arity := $past.arity();
-        if    $arity == 0 { $pirflags := $pirflags ~ ' :multi()'; }
-        elsif $arity == 1 { $pirflags := $pirflags ~ ' :multi(_)'; }
-        else {
-            $pirflags := $pirflags ~ ' :multi(_';
-            my $count := 1;
-            while $count != $arity {
-                $pirflags := $pirflags ~ ',_';
-                $count := $count + 1;
+method routine($/, $key) {
+    our $?IS_METHOD;
+    our $?IN_METHOD;
+    if  $key eq 'decls' {
+        $?IS_METHOD := 0;
+         $?IN_METHOD := 0;
+        if (~$<meth> eq 'method') {
+             $?IS_METHOD  := 1;  #  reset in inner blocks
+             $?IN_METHOD  := 1;  #   not reset in inner blocks
+         }
+    } else {
+        my $past := $($<routine_def>);
+        if $<decl> eq 'multi' {
+            my $pirflags := ~ $past.pirflags();
+            my $arity := $past.arity();
+            if    $arity == 0 { $pirflags := $pirflags ~ ' :multi()'; }
+            elsif $arity == 1 { $pirflags := $pirflags ~ ' :multi(_)'; }
+            else {
+                $pirflags := $pirflags ~ ' :multi(_';
+                my $count := 1;
+                while $count != $arity {
+                    $pirflags := $pirflags ~ ',_';
+                    $count := $count + 1;
+                }
+                $pirflags := $pirflags ~ ')';
             }
-            $pirflags := $pirflags ~ ')';
+            $past.pirflags($pirflags);
         }
-        $past.pirflags($pirflags);
-    }
-    make $past;
-}

-
-method routine_declarator($/, $key) {
-    if $key eq 'sub' {
-        my $past := $($<routine_def>);
         $past.blocktype('declaration');
+        if $?IN_METHOD {
+             $past.pirflags(':method');
+        }
         $past.node($/);
         make $past;
+
     }
-    elsif $key eq 'method' {
-        my $past := $($<method_def>);
-        $past.blocktype('declaration');
-        $past.pirflags(':method');
-        $past.node($/);
-        make $past;
-    }
 }

-
 method routine_def($/) {
+    our $?IS_METHOD;
     my $past := $( $<block> );
     if $<ident> {
         $past.name( ~$<ident>[0] );
-        our $?BLOCK;
-        $?BLOCK.symbol(~$<ident>[0], :scope('package'));
+        if $?IS_METHOD {
+          our $?BLOCK;
+          $?BLOCK.symbol(~$<ident>[0], :scope('package'));
+        }
     }
     make $past;
 }

-method method_def($/) {
-    my $past := $( $<block> );
-    if $<ident> {
-        $past.name( ~$<ident>[0] );
-    }
-    make $past;
-}

 method signature($/) {
     my $params := PAST::Stmts.new( :node($/) );
@@ -468,7 +476,7 @@
 method methodop($/, $key) {
     my $past;

-    if ($key eq 'null') {
+    if $key eq 'null' {
         $past := PAST::Op.new();
     }
     else {
@@ -535,8 +543,12 @@

 method noun($/, $key) {
     my $past;
+    our $?IN_METHOD;
     if $key eq 'self' {
-        $past := PAST::Stmts.new( PAST::Op.new( :inline('%r = self'),
:node( $/ ) ) );
+       unless $?IN_METHOD {
+          $/.panic("can't use 'self' outside a method");
+       }
+       $past := PAST::Stmts.new( PAST::Op.new( :inline("    %r =
find_lex 'self'"), :node( $/ ) ) );
     }
     elsif $key eq 'undef' {
         $past := PAST::Op.new(
@@ -781,6 +793,9 @@


 method scoped($/) {
+    if $<typename> {
+        $/.panic('statically typed variables are not yet implemented');
+    }
     my $past := $( $<variable_decl> );
     make $past;
 }
@@ -966,13 +981,13 @@

 method circumfix($/, $key) {
     my $past;
-    if ($key eq '( )') {
+    if $key eq '( )' {
         $past := $( $<statementlist> );
     }
-    if ($key eq '[ ]') {
+    if $key eq '[ ]' {
         $past := $( $<statementlist> );
     }
-    elsif ($key eq '{ }') {
+    elsif $key eq '{ }' {
         $past := $( $<pblock> );
     }
     make $past;
@@ -1048,15 +1063,15 @@

 method quote_expression($/, $key) {
     my $past;
-    if ($key eq 'quote_regex') {
+    if $key eq 'quote_regex' {
         $past := PAST::Block.new( $<quote_regex>,
                                   :compiler('PGE::Perl6Regex'),
                                   :blocktype('declaration'),
                                   :node( $/ )
                                 )
     }
-    elsif ($key eq 'quote_concat') {
-        if ( +$<quote_concat> == 1 ) {
+    elsif $key eq 'quote_concat' {
+        if  +$<quote_concat> == 1 {
             $past := $( $<quote_concat>[0] );
         }
         else {
@@ -1090,10 +1105,10 @@

 method quote_term($/, $key) {
     my $past;
-    if ($key eq 'literal') {
+    if $key eq 'literal' {
         $past := PAST::Val.new( :value( ~$<quote_literal> ),
:returns('Perl6Str'), :node($/) );
     }
-    if ($key eq 'variable') {
+    if $key eq 'variable' {
         $past := $( $<variable> );
     }
     make $past;
@@ -1127,9 +1142,9 @@

 method semilist($/) {
     my $past := PAST::Op.new( :node($/) );
-    if ($<EXPR>) {
+    if $<EXPR> {
         my $expr := $($<EXPR>[0]);
-        if ($expr.name() eq 'infix:,') {
+        if $expr.name() eq 'infix:,' {
             for @($expr) {
                 $past.push( $_ );
             }
@@ -1144,10 +1159,10 @@

 method listop($/, $key) {
     my $past;
-    if ($key eq 'arglist') {
+    if $key eq 'arglist' {
         $past := $( $<arglist> );
     }
-    if ($key eq 'noarg') {
+    if $key eq 'noarg' {
         $past := PAST::Op.new( );
     }
     $past.name( ~$<sym> );
@@ -1160,7 +1175,7 @@
 method arglist($/) {
     my $past := PAST::Op.new( :node($/) );
     my $expr := $($<EXPR>);
-    if ($expr.name() eq 'infix:,') {
+    if $expr.name() eq 'infix:,' {
         for @($expr) {
             $past.push( $_ );
         }
@@ -1173,7 +1188,7 @@


 method EXPR($/, $key) {
-    if ($key eq 'end') {
+    if $key eq 'end' {
         make $($<expr>);
     }
     else {
@@ -1239,13 +1254,12 @@
     make $past;
 }

-
 method colonpair($/, $key) {
     my $pair_key;
     my $pair_val;

     if $key eq 'false' {
-        my $pair_key := PAST::Val.new( :value(~$<key>) );
+        $pair_key := PAST::Val.new( :value(~$<ident>) );
         $pair_val := PAST::Var.new(
             :name('False'),
             :namespace('Bool'),
@@ -1253,10 +1267,9 @@
         );
     }
     elsif $key eq 'value' {
-        my $pair_key := PAST::Val.new( :value(~$<key>) );
+        $pair_key := PAST::Val.new( :value(~$<ident>) );
         if $<postcircumfix> {
-            # XXX TODO
-            $/.panic('postcircumfix on colonpair not yet implemented');
+           $pair_val := PAST::Val.new( :value($<postcircumfix>))
         }
         else {
             $pair_val := PAST::Var.new(
@@ -1266,7 +1279,12 @@
             );
         }
     }
-    else {
+    elsif $key eq 'varname' {
+        my $nm  := $<variable><name>;
+        my $idx := $<variable><matchidx>;
+        $pair_key := PAST::Val.new( :value( ~$nm || ~$idx) );
+        $pair_val := $( $<variable> );
+    } else {
         $/.panic($key ~ " pairs not yet implemented.");
     }

Index: languages/perl6/src/parser/grammar.pg
===================================================================
--- languages/perl6/src/parser/grammar.pg       (revision 26310)
+++ languages/perl6/src/parser/grammar.pg       (working copy)
@@ -299,15 +299,11 @@

 #### Subroutine and method definitions ####

-rule plurality_declarator {
-    $<sym>=[multi|proto|only] <routine_declarator> {*}
+rule routine  {
+   $<decl>=[multi|proto|only|''] $<meth>=[sub|method] {*}  #= decls
+   <routine_def>                                      {*}  #= def
 }

-token routine_declarator {
-    | $<sym>='sub' <routine_def> {*}             #= sub
-    | $<sym>='method' <method_def> {*}           #= method
-}
-
 rule routine_def {
     <ident>? <multisig>?
     <trait>*
@@ -315,13 +311,6 @@
     {*}
 }

-rule method_def {
-    <ident>? <multisig>?
-    <trait>*
-    <block>
-    {*}
-}
-
 rule trait {
     | <trait_auxiliary>
     | <trait_verb>
@@ -431,8 +420,7 @@
 token noun {
     | <package_declarator> {*}                   #= package_declarator
     | <scope_declarator> {*}                     #= scope_declarator
-    | <plurality_declarator> {*}                 #= plurality_declarator
-    | <routine_declarator> {*}                   #= routine_declarator
+    | <routine> {*}                              #= routine
     | <circumfix> {*}                            #= circumfix
     | <variable> {*}                             #= variable
     | <subcall> {*}                              #= subcall
@@ -479,7 +467,7 @@


 rule scoped {
-    <variable_decl> {*}
+    <typename>? <variable_decl> {*}
 }

 rule scope_declarator {
@@ -657,10 +645,10 @@
 token colonpair {
     ':'
     [
-    | '!' <ident>                                        {*}    #= false
+     || '!' <ident>                                      {*}    #= false
     | <ident> [ <.unsp>? <postcircumfix> ]?              {*}    #= value
     | <postcircumfix>                                    {*}    #= structural
-    | <sigil> <twigil>? <desigilname>                    {*}    #= varname
+    | <variable>                                         {*}    #= varname
     ]
 }

Index: languages/perl6/src/classes/Pair.pir
===================================================================
--- languages/perl6/src/classes/Pair.pir        (revision 26310)
+++ languages/perl6/src/classes/Pair.pir        (working copy)
@@ -17,6 +17,84 @@
     $P1('Pair', 'Pair')
 .end

+
+.sub get_string :method
+     $S0 = self.'perl'()
+     return ( $S0 )
+.end
+
+# should be pedagogical and gives the smartest representation of a pair
+.sub perl :method
+     $P0 = self.'key'()
+     $P1 = self.'value'()
+     $S0 = $P0.'WHAT'()
+     $S1 = $P1.'WHAT'()
+     if $S0 != 'Str' goto keyisnotstring
+     $S2 = $P0
+     $S3 = escape $S2
+     if $S3 != $S2 goto keyescaped
+     if $S1 != 'Bool' goto valnobool
+     $S5 = ":"
+     if $P1 goto trueval
+     concat $S5, "!"
+trueval:
+     concat $S5, $S2
+     .return ($S5)
+valnobool:
+     if $S1 == 'Str' goto valliteral
+     if $S1 == 'Int' goto valnum
+     if $S1 == 'Num' goto valnum
+     die "TBD"
+
+valliteral:
+     $S1 = $P1
+     $I0 = index $S1, '>'
+     if $I0  != -1 goto esc_val_litteral
+     $I0 = index $S1, '<'
+     if $I0 != -1 goto esc_val_litteral
+     $S6 = ":"
+     $S7 = $P0
+     concat $S6, $S7
+     concat $S6, '<'
+     $S7 = $P1
+     concat $S6, $S7
+     concat $S6, '>'
+     .return ( $S6 )
+
+esc_val_litteral:
+    $S1 = escape $S1
+    $S1 = concat '"', $S1
+    $S1 = concat $S1, '"'
+    $P1 = $S1   # fall-thru
+valnum:
+     $S6 = ":"
+     $S7 = $P0
+     concat $S6, $S7
+     concat $S6, '('
+     $S7 = $P1
+     concat $S6, $S7
+     concat $S6, ')'
+     .return ( $S6 )
+
+
+keyescaped:
+     die "TBD"
+
+keyisnotstring:
+     # ugly, probably not correct, certainly not yet supported
+     $S2 =  "{ (my $p=Pair.new()), "
+     concat $S2, "$p[ "
+     $S3 = $P0.perl()
+     concat $S2, $S3
+     concat $S2, "] = "
+     $S3 = $P1.perl()
+     concat $S2, $S3
+     concat $S3, "}"
+keyissnottring:
+     die "TBD"
+.end
+
+
 =back

 =cut
bash-3.2$

Reply via email to