While reading through actions.pm I found that method scope_declarator
wasn't very readable because it was very long.

A big part of that is the declaration of attributes which needs some
special handling.

The attached patch moves that code to a separate function called
declare_attribute. It doesn't change any semantics.

Cheers,
Moritz

-- 
Moritz Lenz
http://moritz.faui2k3.org/ |  http://perl-6.de/
Index: languages/perl6/src/parser/actions.pm
===================================================================
--- languages/perl6/src/parser/actions.pm	(revision 27393)
+++ languages/perl6/src/parser/actions.pm	(working copy)
@@ -1228,7 +1228,98 @@
     make $past;
 }
 
+sub declare_attribute($/) {
+    # Get the
+    # class or role we're in.
+    our $?CLASS;
+    our $?ROLE;
+    our $?PACKAGE;
+    our $?BLOCK;
+    my $class_def;
+    if $?ROLE =:= $?PACKAGE {
+        $class_def := $?ROLE;
+    }
+    else {
+        $class_def := $?CLASS;
+    }
+    unless defined( $class_def ) {
+        $/.panic(
+                "attempt to define attribute '"
+            ~ $name ~ "' outside of class"
+        );
+    }
 
+    # Add attribute to class (always name it with ! twigil).
+    my $variable := $<scoped><variable_decl><variable>;
+    my $name := ~$variable<sigil> ~ '!' ~ ~$variable<name>;
+    $class_def.push(
+        PAST::Op.new(
+            :pasttype('callmethod'),
+            :name('!keyword_has'),
+            PAST::Var.new(
+                :name('Perl6Object'),
+                :scope('package')
+            ),
+            PAST::Var.new(
+                :name('$def'),
+                :scope('lexical')
+            ),
+            PAST::Val.new( :value($name) )
+        )
+    );
+
+    # If we have no twigil, make $name as an alias to $!name.
+    if $variable<twigil>[0] eq '' {
+        $?BLOCK.symbol(
+            ~$variable<sigil> ~ ~$variable<name>, :scope('attribute')
+        );
+    }
+
+    # If we have a . twigil, we need to generate an accessor.
+    elsif $variable<twigil>[0] eq '.' {
+        my $accessor := PAST::Block.new(
+            PAST::Stmts.new(
+                PAST::Var.new( :name($name), :scope('attribute') )
+            ),
+            :name(~$variable<name>),
+            :blocktype('declaration'),
+            :pirflags(':method'),
+            :node( $/ )
+        );
+        $?CLASS.unshift($accessor);
+    }
+
+    # If it's a ! twigil, we're done; otherwise, error.
+    elsif $variable<twigil>[0] ne '!' {
+        $/.panic(
+                "invalid twigil "
+            ~ $variable<twigil>[0] ~ " in attribute declaration"
+        );
+    }
+
+    # Is there any "handles" trait verb?
+    if $<scoped><variable_decl><trait> {
+        for $<scoped><variable_decl><trait> {
+            if $_<trait_verb><sym> eq 'handles' {
+                # Get the methods for the handles and add them to
+                # the class
+                my $meths := process_handles(
+                    $/,
+                    $( $_<trait_verb><EXPR> ),
+                    $name
+                );
+                for @($meths) {
+                    $class_def.push($_);
+                }
+            }
+        }
+    }
+
+    # Register the attribute in the scope.
+    $?BLOCK.symbol($name, :scope('attribute'));
+
+}
+
 method scope_declarator($/) {
     my $past;
     our $?BLOCK;
@@ -1238,94 +1329,9 @@
     if $<scoped><variable_decl> {
         # Variable. Now go by declarator.
         if $declarator eq 'has' {
-            # Has declarations are attributes and need special handling. Get the
-            # class or role we're in.
-            our $?CLASS;
-            our $?ROLE;
-            our $?PACKAGE;
-            my $class_def;
-            if $?ROLE =:= $?PACKAGE {
-                $class_def := $?ROLE;
-            }
-            else {
-                $class_def := $?CLASS;
-            }
-            unless defined( $class_def ) {
-                $/.panic(
-                      "attempt to define attribute '"
-                    ~ $name ~ "' outside of class"
-                );
-            }
+            # Has declarations are attributes and need special handling. 
+            declare_attribute($/);
 
-            # Add attribute to class (always name it with ! twigil).
-            my $variable := $<scoped><variable_decl><variable>;
-            my $name := ~$variable<sigil> ~ '!' ~ ~$variable<name>;
-            $class_def.push(
-                PAST::Op.new(
-                    :pasttype('callmethod'),
-                    :name('!keyword_has'),
-                    PAST::Var.new(
-                        :name('Perl6Object'),
-                        :scope('package')
-                    ),
-                    PAST::Var.new(
-                        :name('$def'),
-                        :scope('lexical')
-                    ),
-                    PAST::Val.new( :value($name) )
-                )
-            );
-
-            # If we have no twigil, make $name as an alias to $!name.
-            if $variable<twigil>[0] eq '' {
-                $?BLOCK.symbol(
-                    ~$variable<sigil> ~ ~$variable<name>, :scope('attribute')
-                );
-            }
-
-            # If we have a . twigil, we need to generate an accessor.
-            elsif $variable<twigil>[0] eq '.' {
-                my $accessor := PAST::Block.new(
-                    PAST::Stmts.new(
-                        PAST::Var.new( :name($name), :scope('attribute') )
-                    ),
-                    :name(~$variable<name>),
-                    :blocktype('declaration'),
-                    :pirflags(':method'),
-                    :node( $/ )
-                );
-                $?CLASS.unshift($accessor);
-            }
-
-            # If it's a ! twigil, we're done; otherwise, error.
-            elsif $variable<twigil>[0] ne '!' {
-                $/.panic(
-                      "invalid twigil "
-                    ~ $variable<twigil>[0] ~ " in attribute declaration"
-                );
-            }
-
-            # Is there any "handles" trait verb?
-            if $<scoped><variable_decl><trait> {
-                for $<scoped><variable_decl><trait> {
-                    if $_<trait_verb><sym> eq 'handles' {
-                        # Get the methods for the handles and add them to
-                        # the class
-                        my $meths := process_handles(
-                            $/,
-                            $( $_<trait_verb><EXPR> ),
-                            $name
-                        );
-                        for @($meths) {
-                            $class_def.push($_);
-                        }
-                    }
-                }
-            }
-
-            # Register the attribute in the scope.
-            $?BLOCK.symbol($name, :scope('attribute'));
-
             # We don't want to generate any PAST at the point of the declaration.
             $past := PAST::Stmts.new();
         }

Reply via email to