develooper Front page | perl.cvs.parrot | Postings from January 2009

[svn:parrot] r36096 - trunk/languages/perl6/src/parser

From:
jonathan
Date:
January 28, 2009 07:55
Subject:
[svn:parrot] r36096 - trunk/languages/perl6/src/parser
Message ID:
20090128155423.10F14CB9AE@x12.develooper.com
Author: jonathan
Date: Wed Jan 28 07:54:20 2009
New Revision: 36096

Modified:
   trunk/languages/perl6/src/parser/actions.pm
   trunk/languages/perl6/src/parser/methods.pir

Log:
[rakudo] Compile time detection of type re-declaration, as well as making class A is B { } and class A does B { } a compile time error when B is not declared.

Modified: trunk/languages/perl6/src/parser/actions.pm
==============================================================================
--- trunk/languages/perl6/src/parser/actions.pm	(original)
+++ trunk/languages/perl6/src/parser/actions.pm	Wed Jan 28 07:54:20 2009
@@ -588,11 +588,15 @@
 
     my $name := ~$<name>[0];
     if $name {
-        # It's a named enumeration. First, we will get a mapping of all the names
-        # we will introduce with this enumeration to their values. We'll compute
-        # these at compile time, so then we can build as much of the enum as possible
-        # as PAST at compile time too. Note that means that, like a BEGIN block, we
-        # will compile, run and get the return value now.
+        # It's a named enumeration. Ensure the type isn't already declared.
+        if $/.type_redaclaration() {
+            $/.panic("Re-declaration of type " ~ $name);
+        }
+        
+        # Get a mapping of all the names we will introduce with this enumeration to their
+        # values. We'll compute these at compile time, so then we can build as much of the
+        # enum as possible as PAST at compile time too. Note that means that, like a
+        # BEGIN block, we will compile, run and get the return value now.
         my $block := PAST::Block.new(
             :blocktype('declaration'),
             PAST::Stmts.new(
@@ -1615,6 +1619,13 @@
             my $trait := $( $_ );
             if $trait[1] eq 'also' { $block<isalso> := 1; }
             else {
+                ##  If it is a trait_auxiliary:does or a trait_auxiliary:is we
+                ##  should check the name is a type.
+                if $trait[0] eq 'trait_auxiliary:is' || $trait[0] eq 'trait_auxiliary:does' {
+                    unless $/.is_type($trait[1]) {
+                        $_.panic("The type " ~ $trait[1] ~ " does not exist.");
+                    }
+                }
                 $trait.name('!meta_trait');
                 $trait.unshift($?METACLASS);
                 $init.push($trait);
@@ -1622,6 +1633,14 @@
         }
     }
 
+    #  If it's not an "is also", have a name and aren't a role (since they can
+    #  have many declarations) we need to check it's not a duplicate.
+    if !$block<isalso> && $<module_name> && $?PKGDECL ne 'role' {
+        if $/.type_redaclaration() {
+            $/.panic("Re-declaration of type " ~ ~$<module_name>[0]);
+        }
+    }
+
     #  At the beginning, create the "class/module/grammar/role/etc"
     #  metaclass handle on which we do the other operations.
     $init.unshift(
@@ -2507,6 +2526,11 @@
 
 
 method type_declarator($/) {
+    # Make sure it's not a re-declaration.
+    if $/.type_redaclaration() {
+        $/.panic("Re-declaration of type " ~ ~$<name>);
+    }
+
     # We need a block containing the constraint condition.
     my $past := $( $<EXPR> );
     if (!$past.isa(PAST::Block) || $past.compiler() eq 'PGE::Perl6Regex') {

Modified: trunk/languages/perl6/src/parser/methods.pir
==============================================================================
--- trunk/languages/perl6/src/parser/methods.pir	(original)
+++ trunk/languages/perl6/src/parser/methods.pir	Wed Jan 28 07:54:20 2009
@@ -27,9 +27,10 @@
     ns = $P0.'parse_name'(name)
     short_name = pop ns
 
-    # Check if the symbol already exists in the NS; if so we're done.
+    # Check if the symbol already exists in the NS; if so we record it as
+    # an existing type.
     $P0 = get_hll_global ns, short_name
-    unless null $P0 goto done
+    unless null $P0 goto type_exists
 
     # Work outwards to find a block defining a package and put the type
     # there. XXX This makes it too visible for lexical types, but if we
@@ -45,22 +46,33 @@
     if null $P0 goto it_loop
     if $P0 == '' goto it_loop
   it_loop_end:
+    $P0 = cur_block.'symbol'(name)
+    if $P0 goto type_exists
     cur_block.'symbol'(name, 'does_abstraction'=>1)
 
     # We also need to register it under it's fully qualified name at the outermost
     # block.
+    .local pmc bottom_block
+    $I0 = elements blocks
+    dec $I0
+    bottom_block = blocks[$I0]
     $P0 = get_hll_global ['Perl6';'Grammar';'Actions'], '@?NS'
     unless $P0 goto no_ns
     $S0 = $P0[0]
     concat $S0, '::'
     name = concat $S0, name
+    $P0 = bottom_block.'symbol'(name)
+    if $P0 goto type_exists
   no_ns:
-    $I0 = elements blocks
-    dec $I0
-    $P0 = blocks[$I0]
-    $P0.'symbol'(name, 'does_abstraction'=>1)
+    bottom_block.'symbol'(name, 'does_abstraction'=>1)
 
-  done:
+    # Record that a type was added or already existed.
+    $P0 = box 0
+    goto set_redecl
+  type_exists:
+    $P0 = box 1
+  set_redecl:
+    setprop self, '$!type_redecl', $P0
 .end
 
 
@@ -129,6 +141,18 @@
         .return (0)
 .end
 
+
+=item type_redeclaration
+
+Checks if the most recently added type was a re-declaration.
+
+=cut
+
+.sub 'type_redaclaration' :method
+    $P0 = getprop '$!type_redecl', self
+    .return ($P0)
+.end
+
 =back
 
 =cut



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About