1 # Copyright (C) 2007-2008, The Perl Foundation.
4 class Perl6
::Grammar
::Actions
;
7 my $past := $( $<statement_block
> );
8 $past.blocktype
('declaration');
9 declare_implicit_var
($past, '$_', 'new');
10 declare_implicit_var
($past, '$!', 'new');
11 declare_implicit_var
($past, '$/', 'new');
13 # Attach any initialization code.
15 if defined( $?
INIT ) {
23 $?
INIT.blocktype
('declaration');
24 $?
INIT.pirflags
(':init :load');
25 $past.unshift( $?
INIT );
26 $?
INIT := PAST
::Block
.new
(); # For the next eval.
29 # Make sure we have the interpinfo constants.
30 $past.unshift( PAST
::Op
.new
( :inline
('.include "interpinfo.pasm"') ) );
32 # Add code to load perl6.pbc if it's not already present
33 my $loadinit := $past.loadinit
();
35 PAST
::Op
.new
( :inline
('$P0 = compreg "Perl6"',
36 'unless null $P0 goto have_perl6',
37 'load_bytecode "perl6.pbc"',
42 # convert the last operation of the block into a .return op
43 # so that :load block below isn't used as return value
44 $past.push( PAST
::Op
.new
( $past.pop(), :pirop
('return') ) );
45 # automatically invoke mainline on :load (but not :init)
50 '$P0 = interpinfo .INTERPINFO_CURRENT_SUB',
51 '$P0 = $P0."get_outer"()',
63 method statement_block
($/, $key) {
66 our $?BLOCK_SIGNATURED
;
67 ## when entering a block, use any $?BLOCK_SIGNATURED if it exists,
68 ## otherwise create an empty block with an empty first child to
69 ## hold any parameters we might encounter inside the block.
71 if $?BLOCK_SIGNATURED
{
72 $?BLOCK
:= $?BLOCK_SIGNATURED
;
73 $?BLOCK_SIGNATURED
:= 0;
74 $?BLOCK
.symbol
('___HAVE_A_SIGNATURE', :scope
('lexical'));
77 $?BLOCK
:= PAST
::Block
.new
( PAST
::Stmts
.new
(), :node
($/));
79 @?BLOCK
.unshift($?BLOCK
);
82 my $past := @?BLOCK
.shift();
83 $?BLOCK
:= @?BLOCK
[0];
84 $past.push($($<statementlist
>));
91 make
$( $<statement_block
> );
95 method statementlist
($/) {
96 my $past := PAST
::Stmts
.new
( :node
($/) );
104 method statement
($/, $key) {
106 if $key eq 'statement_control' {
107 $past := $( $<statement_control
> );
109 elsif $key eq 'null' {
110 $past := PAST
::Stmts
.new
(); # empty stmts seem eliminated by TGE
113 my $expr := $( $<expr
> );
114 if $expr.WHAT
() eq 'Block' && !$expr.blocktype
() {
115 $expr.blocktype
('immediate');
118 if $key eq 'statement_mod_cond' {
119 $past := $( $<statement_mod_cond
> );
123 $key := 'statement_mod_loop';
124 $<statement_mod_loop
> := $<sml
>[0];
127 elsif $key eq 'statement_mod_loop' {
128 my $mod := $( $<statement_mod_loop
> );
129 if $<statement_mod_loop
><sym
> eq 'for' {
130 my $loop := PAST
::Block
.new
(
141 $loop.symbol
( '$_', :scope
('lexical') );
143 $past := PAST
::Stmts
.new
( $mod, :node
($/) );
147 $past := PAST
::Block
.new
( $mod, :blocktype
('immediate'), :node
($/) );
158 method statement_control
($/, $key) {
163 method if_statement
($/) {
164 my $count := +$<EXPR
> - 1;
165 my $expr := $( $<EXPR
>[$count] );
166 my $then := $( $<block
>[$count] );
167 $then.blocktype
('immediate');
168 declare_implicit_immediate_vars
($then);
169 my $past := PAST
::Op
.new
(
175 my $else := $( $<else>[0] );
176 $else.blocktype
('immediate');
177 declare_implicit_immediate_vars
($else);
181 $count := $count - 1;
182 $expr := $( $<EXPR
>[$count] );
183 $then := $( $<block
>[$count] );
184 $then.blocktype
('immediate');
185 declare_implicit_immediate_vars
($then);
186 $past := PAST
::Op
.new
(
196 method unless_statement
($/) {
197 my $then := $( $<block
> );
198 $then.blocktype
('immediate');
199 declare_implicit_immediate_vars
($then);
200 my $past := PAST
::Op
.new
(
209 method while_statement
($/) {
210 my $cond := $( $<EXPR
> );
211 my $block := $( $<block
> );
212 declare_implicit_immediate_vars
($block);
213 $block.blocktype
('immediate');
214 make PAST
::Op
.new
( $cond, $block, :pasttype
(~$<sym
>), :node
($/) );
217 method repeat_statement
($/) {
218 my $cond := $( $<EXPR
> );
219 my $block := $( $<block
> );
220 $block.blocktype
('immediate');
221 # pasttype is 'repeat_while' or 'repeat_until'
222 my $pasttype := 'repeat_' ~ ~$<loop>;
223 make PAST
::Op
.new
( $cond, $block, :pasttype
($pasttype), :node
($/) );
226 method given_statement
($/) {
227 my $block := $( $<pblock
> );
228 $block.blocktype
('declaration');
229 declare_implicit_function_vars
($block);
230 ## call the block using the expression as an argument
231 my $past := PAST
::Op
.new
(
239 method when_statement
($/) {
240 my $block := $( $<block
> );
241 $block.blocktype
('immediate');
243 # XXX TODO: push a control exception throw onto the end of the block so we
244 # exit the innermost block in which $_ was set.
246 # Invoke smartmatch of the expression.
247 my $match_past := PAST
::Op
.new
(
248 PAST
::Var
.new
( :name
('$_') ),
255 # Use the smartmatch result as the condition.
256 my $past := PAST
::Op
.new
(
264 method default_statement
($/) {
265 # Always executed if reached, so just produce the block.
266 my $past := $( $<block
> );
267 $past.blocktype
('immediate');
271 method loop_statement
($/) {
272 my $block := $( $<block
> );
273 $block.blocktype
('immediate');
274 my $cond := $<e2
> ??
$( $<e2
>[0] ) !! PAST
::Val
.new
( :value
( 1 ) );
276 $block := PAST
::Stmts
.new
( $block, $( $<e3
>[0] ) );
278 my $loop := PAST
::Op
.new
( $cond, $block, :pasttype
('while'), :node
($/) );
280 $loop := PAST
::Stmts
.new
( $( $<e1
>[0] ), $loop, :node
($/) );
285 method for_statement
($/) {
286 my $block := $( $<pblock
> );
287 $block.blocktype
('declaration');
288 declare_implicit_function_vars
($block);
289 my $past := PAST
::Op
.new
(
290 PAST
::Op
.new
(:name
('list'), $($<EXPR
>)),
299 my $block := $( $<block
> );
303 method use_statement
($/) {
304 my $name := ~$<name
>;
306 if $name eq 'v6' || $name eq 'lib' {
307 $past := PAST
::Stmts
.new
( :node
($/) );
310 $past := PAST
::Op
.new
(
311 PAST
::Val
.new
( :value
($name) ),
320 method begin_statement
($/) {
321 my $past := $( $<block
> );
322 $past.blocktype
('declaration');
323 my $sub := PAST
::Compiler
.compile
( $past );
325 # XXX - should emit BEGIN side-effects, and do a proper return()
326 make PAST
::Block
.new
();
329 method end_statement
($/) {
330 my $past := $( $<block
> );
331 $past.blocktype
('declaration');
332 my $sub := PAST
::Compiler
.compile
( $past );
333 PIR q
< $P0 = get_hll_global
['Perl6'], '@?END_BLOCKS' >;
334 PIR q
< $P1 = find_lex
'$sub' >;
335 PIR q
< push $P0, $P1 >;
339 method statement_mod_loop
($/) {
340 my $expr := $( $<EXPR
> );
341 if ~$<sym
> eq 'given' {
342 my $assign := PAST
::Op
.new
(
348 PAST
::Var
.new
( :node
($/), :name
('$_'), :scope
('lexical') )
350 $assign.push( $expr );
352 my $past := PAST
::Stmts
.new
( $assign, :node
($/) );
355 elsif ~$<sym
> eq 'for' {
356 my $past := PAST
::Op
.new
(
357 PAST
::Op
.new
($expr, :name
('list')),
366 :pasttype
( ~$<sym
> ),
372 method statement_mod_cond
($/) {
373 if ~$<sym
> eq 'when' {
374 my $expr := $( $<EXPR
> );
375 my $match_past := PAST
::Op
.new
(
381 PAST
::Var
.new
( :node
($/), :name
('$_'), :scope
('lexical') )
383 $match_past.push( $expr );
385 my $past := PAST
::Op
.new
(
395 :pasttype
( ~$<sym
> ),
402 method statement_prefix
($/) {
403 my $past := $($<statement
>);
407 # fall through, just use the statement itself
409 ## after the code in the try block is executed, bind $! to Failure,
410 ## and set up the code to catch an exception, in case one is thrown
411 elsif $sym eq 'try' {
412 $past := PAST
::Op
.new
( $past, :pasttype
('try') );
414 ## Add a catch node to the try op that captures the
415 ## exception object into $!.
416 my $catchpir := " .get_results (%r, $S0)\n store_lex '$!', %r";
417 $past.push( PAST
::Op
.new
( :inline
( $catchpir ) ) );
419 ## Add an 'else' node to the try op that clears $! if
420 ## no exception occurred.
421 my $elsepir := " new %r, 'Failure'\n store_lex '$!', %r";
422 $past.push( PAST
::Op
.new
( :inline
( $elsepir ) ) );
424 elsif $sym eq 'gather' {
425 if $past.isa
(PAST
::Block
) {
426 $past.blocktype
('declaration');
429 $past := PAST
::Block
.new
(:blocktype
('declaration'), $past)
431 # XXX Workaround for lexicals issue. rt #58854
432 $past := PAST
::Op
.new
(:pirop
('newclosure'), $past);
433 $past := PAST
::Op
.new
( $past, :pasttype
('call'), :name
('gather'), :node
($/) );
436 $/.panic
( $sym ~ ' not implemented');
442 method multi_declarator
($/, $key) {
443 my $past := $( $/{$key} );
445 # If we just got a routine_def, make it a sub.
446 if $key eq 'routine_def' {
447 create_sub
($/, $past);
450 # If it was multi, then emit a :multi and a type list.
451 if $<sym
> eq 'multi' {
452 # For now, if this is a multi we need to add code to transform the sub's
453 # multi container to a Perl6MultiSub.
454 $past.loadinit
().push(
457 :name
('!TOPERL6MULTISUB'),
465 # Flag the sub as multi, but it will get the signature from the
466 # signature object, so don't worry about that here.
467 my $pirflags := $past.pirflags
();
468 unless $pirflags { $pirflags := '' }
469 $past.pirflags
($pirflags ~ ' :multi()');
475 method routine_declarator
($/, $key) {
478 $past := $($<routine_def
>);
479 create_sub
($/, $past);
481 elsif $key eq 'method' {
482 $past := $($<method_def
>);
484 # If it's got a name, only valid inside a class, role or grammar.
489 unless +@?CLASS
|| +@?GRAMMAR
|| +@?ROLE
{
490 $/.panic
("Named methods cannot appear outside of a class, grammar or role.");
494 # Add declaration of leixcal self.
495 $past[0].unshift(PAST
::Op
.new
(
502 PAST
::Var
.new
( :name
('self'), :scope
('register') )
505 # Set up the block details.
506 $past.blocktype
('method');
507 set_block_proto
($past, 'Method');
508 if $<method_def
><multisig
> {
509 set_block_sig
($past, $( $<method_def
><multisig
>[0]<signature
> ));
512 set_block_sig
($past, empty_signature
());
514 $past := add_method_to_class
($past);
518 declare_implicit_var
($past, '$_', 'new');
519 declare_implicit_var
($past, '$!', 'new');
520 declare_implicit_var
($past, '$/', 'new');
523 $past[1].push( PAST
::Op
.new
( :name
('list') ) );
529 method enum_declarator
($/, $key) {
530 my $values := $( $/{$key} );
533 # It's a named enumeration. First, we will get a mapping of all the names
534 # we will introduce with this enumeration to their values. We'll compute
535 # these at compile time, so then we can build as much of the enum as possible
536 # as PAST at compile time too. Note that means that, like a BEGIN block, we
537 # will compile, run and get the return value now.
538 my $block := PAST
::Block
.new
(
539 :blocktype
('declaration'),
548 my $getvals_sub := PAST
::Compiler
.compile
( $block );
549 my %values := $getvals_sub();
551 # Now we need to emit an role of the name of the enum containing:
552 # * One attribute with the same name as the enum
553 # * A method of the same name as the enum
554 # * Methods for each name introduced by the enum that compare the
555 # attribute with the value of that name.
556 my $role_past := PAST
::Stmts
.new
(
565 :name
('!keyword_role'),
566 PAST
::Val
.new
( :value
(~$<name
>[0]) )
571 :name
('!keyword_has'),
576 PAST
::Val
.new
( :value
("$!" ~ ~$<name
>[0]) ),
577 # XXX Set declared type here, when we parse that.
584 :pasttype
('callmethod'),
590 PAST
::Val
.new
( :value
(~$<name
>[0]) ),
591 make_accessor
($/, undef, "$!" ~ ~$<name
>[0], 1, 'attribute')
595 # Method for this value.
596 $role_past.push(PAST
::Op
.new
(
597 :pasttype
('callmethod'),
603 PAST
::Val
.new
( :value
($_) ),
605 :blocktype
('declaration'),
606 :pirflags
(':method'),
610 :name
('infix:eq'), # XXX not generic enough
612 :name
("$!" ~ ~$<name
>[0]),
615 PAST
::Val
.new
( :value
(%values{$_}) )
622 # Now we emit code to create a class for the enum that does the role
623 # that we just defined. Note $def in the init code refers to this
624 # class from now on. Mark the class as an enum.
625 my $class_past := PAST
::Stmts
.new
(
634 :name
('!keyword_enum'),
642 :inline
(' setprop %0, "enum", %1'),
654 # Want to give the class an invoke method that returns the enum value,
655 # and get_string, get_number and get_integer v-table overrides to we
656 # can get data from it..
657 $class_past.push(PAST
::Op
.new
(
658 :pasttype
('callmethod'),
664 PAST
::Val
.new
( :value
('invoke') ),
666 :blocktype
('declaration'),
667 :pirflags
(":method"),
669 :name
("$!" ~ ~$<name
>[0]),
675 :named
( PAST
::Val
.new
( :value
('vtable') ) )
678 $class_past.push(PAST
::Op
.new
(
679 :pasttype
('callmethod'),
685 PAST
::Val
.new
( :value
('get_string') ),
687 :blocktype
('declaration'),
688 :pirflags
(":method"),
693 :name
("$!" ~ ~$<name
>[0]),
700 :named
( PAST
::Val
.new
( :value
('vtable') ) )
703 $class_past.push(PAST
::Op
.new
(
704 :pasttype
('callmethod'),
710 PAST
::Val
.new
( :value
('get_integer') ),
712 :blocktype
('declaration'),
713 :pirflags
(":method"),
718 :name
("$!" ~ ~$<name
>[0]),
725 :named
( PAST
::Val
.new
( :value
('vtable') ) )
728 $class_past.push(PAST
::Op
.new
(
729 :pasttype
('callmethod'),
735 PAST
::Val
.new
( :value
('get_number') ),
737 :blocktype
('declaration'),
738 :pirflags
(":method"),
743 :name
("$!" ~ ~$<name
>[0]),
750 :named
( PAST
::Val
.new
( :value
('vtable') ) )
754 # Now we need to create instances of each of these and install them
755 # in a package starting with the enum's name, plus an alias to them
756 # in the current package.
758 # Instantiate with value.
759 $class_past.push(PAST
::Op
.new
(
763 :namespace
(~$<name
>[0]),
767 :pasttype
('callmethod'),
775 :named
( PAST
::Val
.new
( :value
("$!" ~ ~$<name
>[0]) ) )
780 # Add alias in current package.
781 # XXX Need to do collision detection, once we've a registry.
782 $class_past.push(PAST
::Op
.new
(
790 :namespace
(~$<name
>[0]),
796 # Assemble all that we build into a statement list and then place it
797 # into the init code.
799 unless defined( $?
INIT ) {
800 $?
INIT := PAST
::Block
.new
();
802 $?
INIT.push(PAST
::Stmts
.new
(
807 # Finally, since it's a decl, we don't have anything to emit at this
808 # point; just hand back empty statements block.
809 make PAST
::Stmts
.new
();
812 # Emit runtime call anonymous enum constructor.
822 method routine_def
($/) {
823 my $past := $( $<block
> );
825 $past.name
( ~$<ident
>[0] );
827 $?BLOCK
.symbol
(~$<ident
>[0], :scope
('package'));
829 $past.control
('return_pir');
833 method method_def
($/) {
834 my $past := $( $<block
> );
836 $past.name
( ~$<ident
>[0] );
838 $past.control
('return_pir');
843 method signature
($/) {
844 # In here, we build a signature object and optionally some other things
845 # if $?SIG_BLOCK_NOT_NEEDED is not set to a true value.
846 # * $?BLOCK_SIGNATURED ends up containing the PAST tree for a block that
847 # takes and binds the parameters. This is used for generating subs,
848 # methods and so forth.
849 # * $?PARAM_TYPE_CHECK is used to export details of the types from here
850 # so that the multi plurality declarator can make use of them.
852 # Initialize PAST for the signatured block, if we're going to have it.
853 our $?SIG_BLOCK_NOT_NEEDED
;
857 unless $?SIG_BLOCK_NOT_NEEDED
{
858 $params := PAST
::Stmts
.new
( :node
($/) );
859 $block_past := PAST
::Block
.new
( $params, :blocktype
('declaration') );
860 $type_check := PAST
::Stmts
.new
( :node
($/) );
863 # Initialize PAST for constructing the signature object.
864 my $sig_past := PAST
::Op
.new
(
865 :pasttype
('callmethod'),
874 # Go through the parameters.
876 my $parameter := $($_<parameter
>);
877 my $separator := $_[0];
879 # Add parameter declaration to the block, if we're producing one.
880 unless $?SIG_BLOCK_NOT_NEEDED
{
881 # Register symbol and put parameter PAST into the node.
882 $block_past.symbol
($parameter.name
(), :scope
('lexical'));
883 $params.push($parameter);
885 # If it is invocant, modify it to be just a lexical and bind self to it.
886 if substr($separator, 0, 1) eq ':' {
887 # Make sure it's first parameter.
888 if +@
($params) != 1 {
889 $/.panic
("There can only be one invocant and it must be the first parameter");
893 $parameter.scope
('lexical');
894 $parameter.isdecl
(1);
897 $params.push(PAST
::Op
.new
(
900 :name
($parameter.name
()),
903 PAST
::Var
.new
( :name
('self'), :scope
('register') )
907 # Are we going to take the type of the thing we were passed and bind
908 # it to an abstraction parameter?
909 if $_<parameter
><generic_binder
> {
910 my $tv_var := $( $_<parameter
><generic_binder
>[0]<variable
> );
911 $params.push(PAST
::Op
.new
(
914 :name
($tv_var.name
()),
919 :pasttype
('callmethod'),
922 :name
($parameter.name
()),
927 $block_past.symbol
($tv_var.name
(), :scope
('lexical'));
931 # Now start making a descriptor for the signature.
932 my $descriptor := sig_descriptor_create
();
933 $sig_past.push($descriptor);
934 sig_descriptor_set
($descriptor, 'name',
935 PAST
::Val
.new
( :value
(~$parameter.name
()) ));
936 if $parameter.named
() {
937 sig_descriptor_set
($descriptor, 'named',
938 PAST
::Val
.new
( :value
(~$parameter.named
()) ));
940 if $parameter.viviself
() {
941 sig_descriptor_set
($descriptor, 'optional', PAST
::Val
.new
( :value
(1) ));
943 if $parameter.slurpy
() {
944 sig_descriptor_set
($descriptor, 'slurpy', PAST
::Val
.new
( :value
(1) ));
947 # See if we have any traits. For now, we just handle ro, rw and copy.
948 my $cont_trait := 'readonly';
949 my $cont_traits := 0;
950 for $_<parameter
><trait
> {
951 if $_<trait_auxiliary
> {
952 # Get name of the trait and see if it's one of the special
953 # traits we handle in the compiler.
954 my $name := ~$_<trait_auxiliary
><name
>;
955 if $name eq 'readonly' {
956 $cont_traits := $cont_traits + 1;
958 elsif $name eq 'rw' {
960 $cont_traits := $cont_traits + 1;
962 elsif $name eq 'copy' {
963 $cont_trait := 'copy';
964 $cont_traits := $cont_traits + 1;
967 $/.panic
("Cannot apply trait " ~ $name ~ " to parameters yet.");
971 $/.panic
("Cannot apply traits to parameters yet.");
975 # If we had is copy is rw or some other impossible combination, die.
976 if $cont_traits > 1 {
977 $/.panic
("Can only use one of readonly, rw and copy on a parameter.");
980 # Add any type check that is needed. The scheme for this: $type_check
981 # is a statement block. We create a block for each parameter, which
982 # will be empty if there are no constraints for that parameter. This
983 # is so we can later generate a multi-sig from it.
984 my $cur_param_types := PAST
::Stmts
.new
();
985 if $_<parameter
><type_constraint
> {
986 for $_<parameter
><type_constraint
> {
991 $type_obj := PAST
::Op
.new
(
993 :name
('!TYPECHECKPARAM'),
996 :name
($parameter.name
()),
1002 $type_obj := make_anon_subset
($( $_<EXPR
> ), $parameter);
1005 # Add it to the types list.
1006 $cur_param_types.push($type_obj);
1010 # Add any post-constraints too.
1011 for $_<parameter
><post_constraint
> {
1012 my $type_obj := make_anon_subset
($( $_<EXPR
> ), $parameter);
1013 $cur_param_types.push($type_obj);
1016 # For blocks, we just collect the check into the list of all checks.
1017 unless $?SIG_BLOCK_NOT_NEEDED
{
1018 $type_check.push($cur_param_types);
1021 # For signatures, we build a list from the constraints and store it.
1022 my $sig_type_cons := PAST
::Stmts
.new
(
1024 :inline
(' $P2 = new "List"')
1028 :inline
(' %r = $P2')
1031 for @
($cur_param_types) {
1032 # Just want the type, not the call to the checker.
1033 $sig_type_cons[1].push(PAST
::Op
.new
(
1034 :inline
(' push $P2, %0'),
1038 sig_descriptor_set
($descriptor, 'constraints', $sig_type_cons);
1040 # If we're making a block, emit code for trait types.
1041 unless $?SIG_BLOCK_NOT_NEEDED
{
1042 if $cont_trait eq 'rw' {
1043 # We just leave it as it is.
1045 elsif $cont_trait eq 'readonly' {
1046 # Create a new container with ro set and bind the parameter to it.
1047 $params.push(PAST
::Op
.new
(
1050 :name
($parameter.name
()),
1055 ' %r = new "Perl6Scalar", %0',
1056 ' $P0 = get_hll_global ["Bool"], "True"',
1057 ' setprop %r, "readonly", $P0'
1060 :name
($parameter.name
()),
1066 elsif $cont_trait eq 'copy' {
1067 # Create a new container and copy the value into it..
1068 $params.push(PAST
::Op
.new
(
1071 :name
($parameter.name
()),
1076 ' %r = new "Perl6Scalar"',
1080 :name
($parameter.name
()),
1089 # Finish setting up the signatured block, if we're making one.
1090 unless $?SIG_BLOCK_NOT_NEEDED
{
1091 $block_past.arity
( +$/[0] );
1092 our $?BLOCK_SIGNATURED
:= $block_past;
1093 our $?PARAM_TYPE_CHECK
:= $type_check;
1094 $params.push($type_check);
1097 # Hand back the PAST to construct a signature object.
1102 method parameter
($/) {
1103 my $past := $( $<param_var
> );
1104 my $sigil := $<param_var
><sigil
>;
1105 if $<quant
> eq '*' {
1106 $past.slurpy
( $sigil eq '@' || $sigil eq '%' );
1107 $past.named
( $sigil eq '%' );
1110 if $<named
> eq ':' { # named
1111 $past.named
(~$<param_var
><ident
>);
1112 if $<quant
> ne '!' { # required (optional is default)
1113 $past.viviself
('Failure');
1117 if $<quant
> eq '?' { # optional (required is default)
1118 $past.viviself
('Failure');
1122 if $<default_value
> {
1123 if $<quant
> eq '!' {
1124 $/.panic
("Can't put a default on a required parameter");
1126 if $<quant
> eq '*' {
1127 $/.panic
("Can't put a default on a slurpy parameter");
1129 $past.viviself
( $( $<default_value
>[0]<EXPR
> ) );
1135 method param_var
($/) {
1136 if $<twigil
> && $<twigil
>[0] ne '.' && $<twigil
>[0] ne '!' {
1137 $/.panic
('Invalid twigil used in signature parameter.');
1141 :scope
('parameter'),
1147 method special_variable
($/) {
1148 make PAST
::Var
.new
( :node
($/), :name(~$/), :scope
('lexical') );
1152 method expect_term
($/, $key) {
1156 $past := PAST
::Op
.new
(
1157 :pasttype
('callmethod'),
1169 $past := $( $/{$key} );
1176 if $past.name
() eq 'infix:,' { $past.name
(''); }
1178 if $past.isa
(PAST
::Op
)
1179 && $past.pasttype
() eq 'callmethod'
1181 # indirect call, invocant needs to be second arg
1182 my $meth := $past[0];
1184 $past.unshift($meth);
1187 $past.unshift($term);
1195 method postfix
($/, $key) {
1200 method dotty
($/, $key) {
1204 # Just a normal method call.
1205 $past := $( $<methodop
> );
1208 # Private method call. Need to put ! on the start of the name
1209 # (unless it was call to a code object, in which case we don't do
1211 $past := $( $<methodop
> );
1212 if $<methodop
><name
> {
1213 $past.name
('!' ~ $past.name
());
1215 elsif $<methodop
><quote
> {
1216 $past[0] := PAST
::Op
.new
(
1219 PAST
::Val
.new
( :value
('!') ),
1224 elsif $key eq '.*' {
1225 $past := $( $<methodop
> );
1226 if $/[0] eq '.?' || $/[0] eq '.+' || $/[0] eq '.*' || $/[0] eq '.^' {
1227 my $name := $past.name
();
1229 $/.panic("Cannot use " ~ $/[0] ~ " when method is a code ref");
1231 unless $name.isa
(PAST
::Node
) {
1232 $name := PAST
::Val
.new
( :value
($name) );
1234 $past.unshift($name);
1235 $past.name
('!' ~ $/[0]);
1238 $/.panic($/[0] ~ ' method calls not yet implemented');
1241 elsif $key eq 'VAR' {
1242 $past := PAST
::Op
.new
(
1253 method methodop
($/, $key) {
1257 $past := PAST
::Op
.new
();
1260 $past := build_call
( $( $/{$key} ) );
1262 $past.pasttype
('callmethod');
1266 $past.name
(~$<name
><ident
>[0]);
1269 $past.unshift( $( $<variable
> ) );
1272 $past.name
( $( $<quote
> ) );
1278 method postcircumfix
($/, $key) {
1281 $past := PAST
::Var
.new
(
1283 :scope
('keyed_int'),
1284 :vivibase
('Perl6Array'),
1285 :viviself
('Failure'),
1289 elsif $key eq '( )' {
1290 $past := build_call
( $( $<semilist
> ) );
1293 elsif $key eq '{ }' {
1294 $past := PAST
::Var
.new
(
1297 :vivibase
('Perl6Hash'),
1298 :viviself
('Failure'),
1302 elsif $key eq '< >' {
1303 $past := PAST
::Var
.new
(
1304 $( $<quote_expression
> ),
1306 :vivibase
('Perl6Hash'),
1307 :viviself
('Failure'),
1312 $/.panic
("postcircumfix " ~ $key ~ " not yet implemented");
1318 method noun
($/, $key) {
1321 $past := PAST
::Var
.new
(
1327 elsif $key eq 'dotty' {
1329 $past := $( $/{$key} );
1330 $past.unshift(PAST
::Var
.new
(
1333 :viviself
('Failure'),
1338 $past := $( $/{$key} );
1344 sub apply_package_traits
($package, $traits) {
1346 # Apply any "is" traits through MMD.
1347 if $_<trait_auxiliary
><sym
> eq 'is' {
1351 :name
('trait_auxiliary:is'),
1353 :name
(~$_<trait_auxiliary
><name
>),
1364 elsif $_<trait_auxiliary
><sym
> eq 'does' {
1369 :name
('!keyword_does'),
1375 :name
(~$_<trait_auxiliary
><name
>),
1382 $traits.panic
("Currently only is and does traits are supported on packages.");
1388 method package_declarator
($/, $key) {
1399 # Start of a new package. We create an empty PAST::Stmts node for the
1400 # package definition to be stored in and put it onto the current stack
1401 # of packages and the stack of its package type.
1402 my $decl_past := PAST
::Stmts
.new
();
1403 @?PACKAGE
.unshift($?PACKAGE
);
1404 $?PACKAGE
:= $decl_past;
1405 if $<sym
> eq 'class' {
1406 @?CLASS
.unshift($?CLASS
);
1407 $?CLASS
:= $decl_past;
1409 elsif $<sym
> eq 'role' {
1410 @?ROLE
.unshift( $?ROLE
);
1411 $?ROLE
:= $decl_past;
1413 elsif $<sym
> eq 'grammar' {
1414 @?GRAMMAR
.unshift( $?GRAMMAR
);
1415 $?GRAMMAR
:= $decl_past;
1419 # End of declaration. Our PAST will be that made by the package_def or
1421 my $past := $( $/{$key} );
1423 # Restore outer package.
1424 $?PACKAGE
:= @?PACKAGE
.shift();
1425 if $<sym
> eq 'class' {
1426 $?CLASS
:= @?CLASS
.shift();
1428 elsif $<sym
> eq 'role' {
1429 $?ROLE
:= @?ROLE
.shift();
1431 elsif $<sym
> eq 'grammar' {
1432 $?GRAMMAR
:= @?GRAMMAR
.shift();
1440 method package_def
($/, $key) {
1448 # Start of package definition. Handle class and grammar specially.
1449 if $?PACKAGE
=:= $?CLASS
{
1450 # Start of class definition; make PAST to create class object.
1451 my $class_def := PAST
::Op
.new
(
1459 :name
('!keyword_class')
1463 # Add a name, if we have one.
1465 $class_def[1].push( PAST
::Val
.new
( :value
(~$<name
>[0]) ) );
1468 $?CLASS
.push($class_def);
1470 elsif $?PACKAGE
=:= $?GRAMMAR
{
1471 # Anonymous grammars not supported.
1473 $/.panic
('Anonymous grammars not supported');
1476 # Start of grammar definition. Create grammar class object.
1486 :name
('!keyword_grammar'),
1487 PAST
::Val
.new
( :value
(~$<name
>[0]) )
1493 # Anonymous modules not supported.
1495 $/.panic
('Anonymous modules not supported');
1499 # Also store the current namespace, if we're not anonymous.
1501 $?NS
:= $<name
>[0]<ident
>;
1505 # XXX For now, to work around the :load :init not being allowed to be
1506 # an outer bug, we will enclose the actual package block inside an
1507 # immediate block of its own.
1508 my $inner_block := $( $<package_block
> );
1509 $inner_block.blocktype
('immediate');
1510 my $past := PAST
::Block
.new
(
1514 # Declare the namespace and that the result block holds things that we
1517 $past.namespace
($<name
>[0]<ident
>);
1519 $past.blocktype
('declaration');
1520 $past.pirflags
(':init :load');
1522 if $?PACKAGE
=:= $?CLASS
{
1524 apply_package_traits
($?CLASS
, $<trait
>);
1526 # It's a class. Make proto-object.
1529 :pasttype
('callmethod'),
1534 :namespace
('Perl6Object')
1542 :named
( PAST
::Val
.new
( :value
('parent') ) )
1547 # If this is an anonymous class, the block doesn't want to be a
1548 # :init :load, and it's going to contain the class definition, so
1549 # we need to declare the lexical $def.
1552 $past.blocktype
('immediate');
1553 $past[0].push(PAST
::Var
.new
(
1560 # Attatch any class initialization code to the init code;
1561 # note that we skip blocks, which are method accessors that
1562 # we want to put under this block so they get the correct
1563 # namespace. If it's an anonymous class, everything goes into
1565 unless defined( $?
INIT ) {
1566 $?
INIT := PAST
::Block
.new
();
1569 if $_.WHAT
() eq 'Block' || !$<name
> {
1570 $past[0].push( $_ );
1577 elsif $?PACKAGE
=:= $?GRAMMAR
{
1579 apply_package_traits
($?GRAMMAR
, $<trait
>);
1581 # Make proto-object for grammar.
1584 :pasttype
('callmethod'),
1589 :namespace
('Perl6Object')
1597 :named
( PAST
::Val
.new
( :value
('parent') ) )
1602 # Attatch grammar declaration to the init code.
1603 unless defined( $?
INIT ) {
1604 $?
INIT := PAST
::Block
.new
();
1606 $?
INIT.push( $?GRAMMAR
);
1617 method role_def
($/, $key) {
1623 # Start of role definition. Push on code to create a role object.
1633 :name
('!keyword_role'),
1634 PAST
::Val
.new
( :value
(~$<name
>) )
1639 # Also store the current namespace.
1640 $?NS
:= $<name
><ident
>;
1643 # Declare the namespace and that the result block holds things that we
1645 my $past := $( $<package_block
> );
1646 $past.namespace
($<name
><ident
>);
1647 $past.blocktype
('declaration');
1648 $past.pirflags
(':init :load');
1651 apply_package_traits
($?ROLE
, $<trait
>);
1653 # Attatch role declaration to the init code, skipping blocks since
1654 # those are accessors.
1655 unless defined( $?
INIT ) {
1656 $?
INIT := PAST
::Block
.new
();
1659 if $_.WHAT
() eq 'Block' {
1675 method package_block
($/, $key) {
1676 my $past := $( $/{$key} );
1681 method variable_declarator
($/) {
1682 my $past := $( $<variable
> );
1684 # If it's an attribute declaration, we handle traits elsewhere.
1685 my $twigil := $<variable
><twigil
>[0];
1686 if $<trait
> && $twigil ne '.' && $twigil ne '!' {
1689 if $trait<trait_auxiliary
> {
1690 my $aux := $trait<trait_auxiliary
>;
1691 my $sym := $aux<sym
>;
1693 if $aux<postcircumfix
> {
1694 $/.panic
("'" ~ ~$trait ~ "' not implemented");
1697 $past.viviself
(~$aux<name
>);
1701 $/.panic
("'" ~ $sym ~ "' not implemented");
1704 elsif $trait<trait_verb
> {
1705 my $verb := $trait<trait_verb
>;
1706 my $sym := $verb<sym
>;
1707 if $sym ne 'handles' {
1708 $/.panic
("'" ~ $sym ~ "' not implemented");
1721 # Variable declaration?
1722 if $<declarator
><variable_declarator
> {
1723 $past := $( $<declarator
><variable_declarator
> );
1725 # Unless it's an attribute, emit code to set type and initialize it to
1726 # the correct proto.
1727 if $<fulltypename
> && $past.WHAT
() eq 'Var' {
1728 my $type_pir := " %r = new %0, %1\n setprop %r, 'type', %2\n";
1729 my $type := build_type
($<fulltypename
>);
1733 PAST
::Val
.new
( :value
(~$past.viviself
()) ),
1739 PAST
::Val
.new
( :value
("P6protoobject") )
1753 # Variable declaration, but with a signature?
1754 elsif $<declarator
><signature
> {
1755 if $<fulltypename
> {
1756 $/.panic
("Distributing a type across a signature at declaration unimplemented.");
1758 $past := $( $<declarator
><signature
> );
1761 # Routine declaration?
1763 $past := $( $<routine_declarator
> );
1765 # Don't support setting return type yet.
1766 if $<fulltypename
> {
1767 $/.panic
("Setting return type of a routine not yet implemented.");
1774 sub declare_attribute
($/, $sym, $variable_sigil, $variable_twigil, $variable_name) {
1775 # Get the class or role we're in.
1781 if $?ROLE
=:= $?PACKAGE
{
1782 $class_def := $?ROLE
;
1785 $class_def := $?CLASS
;
1787 unless defined( $class_def ) {
1789 "attempt to define attribute '" ~ $name ~ "' outside of class"
1793 # Is this a role-private or just a normal attribute?
1796 # These are only allowed inside a role.
1797 unless $class_def =:= $?ROLE
{
1798 $/.panic
('Role private attributes can only be declared in a role');
1801 # We need to name-manage this somehow. We'll do $!rolename!attrname
1802 # for now; long term, want some UUID. For the block entry, we enter it
1803 # as $!attrname, add the real name and set the scope as rpattribute,
1804 # then translate it to the right thing when we see it.
1806 $name := ~$variable_sigil ~ '!' ~ $?NS
[0] ~ '!' ~ ~$variable_name;
1807 my $visible_name := ~$variable_sigil ~ '!' ~ ~$variable_name;
1808 my $real_name := '!' ~ $?NS
[0] ~ '!' ~ ~$variable_name;
1809 $?BLOCK
.symbol
($visible_name, :scope
('rpattribute'), :real_name
($real_name));
1812 # Register name as attribute scope.
1813 $name := ~$variable_sigil ~ '!' ~ ~$variable_name;
1814 $?BLOCK
.symbol
($name, :scope
('attribute'));
1817 # Add attribute to class (always name it with ! twigil).
1818 if $/<scoped
><fulltypename
> {
1822 :name
('!keyword_has'),
1827 PAST
::Val
.new
( :value
($name) ),
1828 build_type
($/<scoped
><fulltypename
>)
1836 :name
('!keyword_has'),
1841 PAST
::Val
.new
( :value
($name) )
1846 # Is there any "handles" trait verb or an "is rw" or "is ro"?
1848 if $<scoped
><declarator
><variable_declarator
><trait
> {
1849 for $<scoped
><declarator
><variable_declarator
><trait
> {
1850 if $_<trait_verb
><sym
> eq 'handles' {
1851 # Get the methods for the handles and add them to
1853 my $meths := process_handles
(
1855 $( $_<trait_verb
><EXPR
> ),
1859 $class_def.push($_);
1862 elsif $_<trait_auxiliary
><sym
> eq 'is' {
1863 # Just handle rw for now.
1864 if ~$_<trait_auxiliary
><name
> eq 'rw' {
1868 $/.panic
("Only 'is rw' trait is implemented for attributes");
1872 $/.panic
("Only is and handles trait verbs are implemented for attributes");
1878 if $variable_twigil eq '.' {
1879 # We have a . twigil, so we need to generate an accessor.
1880 my $accessor := make_accessor
($/, ~$variable_name, $name, $rw, 'attribute');
1881 $class_def.push(add_method_to_class
($accessor));
1883 elsif $variable_twigil eq '!' {
1884 # Don't need to do anything.
1886 elsif $variable_twigil eq '' {
1887 # We have no twigil, make $name as an alias to $!name.
1889 ~$variable_sigil ~ ~$variable_name, :scope
('attribute')
1893 # It's a twigil that you canny use in an attribute declaration.
1896 ~ $variable_twigil ~ " in attribute declaration"
1901 method scope_declarator
($/) {
1903 my $declarator := $<sym
>;
1904 my $past := $( $<scoped
> );
1906 # What sort of thing are we scoping?
1907 if $<scoped
><declarator
><variable_declarator
> {
1912 # Variable. If it's declared with "has" it is always an attribute. If
1913 # it is declared with "my" inside a role and has the ! twigil, it is
1914 # a role private attribute.
1915 my $variable := $<scoped
><declarator
><variable_declarator
><variable
>;
1916 my $twigil := $variable<twigil
>[0];
1917 my $role_priv := $?ROLE
=:= $?PACKAGE
&& $declarator eq 'my' && $twigil eq '!';
1918 if $declarator eq 'has' || $role_priv {
1919 # Attribute declarations need special handling.
1920 my $sigil := ~$<scoped
><declarator
><variable_declarator
><variable
><sigil
>;
1921 my $twigil := ~$<scoped
><declarator
><variable_declarator
><variable
><twigil
>[0];
1922 my $name := ~$<scoped
><declarator
><variable_declarator
><variable
><name
>;
1923 declare_attribute
($/, $declarator, $sigil, $twigil, $name);
1925 # We don't have any PAST at the point of the declaration.
1926 $past := PAST
::Stmts
.new
();
1929 # If we're in a class and have something declared with a sigil, then
1930 # we need to generate an accessor method and emit that along with the
1931 # lexical declaration itself.
1932 elsif ($twigil eq '.' || $twigil eq '!') && $?CLASS
=:= $?PACKAGE
{
1933 # This node is just the variable declaration; also register it in
1935 my $orig_past := $past;
1936 $past := PAST
::Var
.new
(
1937 :name
(~$variable<sigil
> ~ '!' ~ ~$variable<name
>),
1940 :viviself
(container_type
(~$variable<sigil
>))
1942 $?BLOCK
.symbol
($past.name
(), :scope
('lexical'));
1944 # Now generate accessor, if it's public.
1946 $?CLASS
.push(make_accessor
($/, $orig_past.name
(), $past.name
(), 1, 'lexical'));
1950 # Otherwise, just a normal variable declaration.
1952 # Has this already been declared?
1953 my $name := $past.name
();
1954 unless $?BLOCK
.symbol
($name) {
1956 my $scope := 'lexical';
1958 if $declarator eq 'our' {
1959 $scope := 'package';
1961 elsif $declarator ne 'my' {
1963 "scope declarator '"
1964 ~ $declarator ~ "' not implemented"
1969 $?BLOCK
.symbol
($name, :scope
($scope));
1975 elsif $<scoped
><declarator
><signature
> {
1976 # We'll emit code to declare each of the parameters, then we'll have
1977 # the declaration evaluate to the signature object, thus allowing an
1979 my @declare := sig_extract_declarables
($/, $past);
1980 $past := PAST
::Stmts
.new
($past);
1982 # Work out sigil and twigil.
1983 my $sigil := substr($_, 0, 1);
1984 my $twigil := substr($_, 1, 1);
1986 if $twigil eq '.' || $twigil eq '!' {
1987 $desigilname := substr($_, 2);
1991 $desigilname := substr($_, 1);
1994 # Decide by declarator.
1995 if $declarator eq 'my' || $declarator eq 'our' {
1996 # Add declaration code.
1998 if $declarator eq 'my' {
2002 $scope := 'package';
2004 $past.unshift(PAST
::Var
.new
(
2008 :viviself
('Perl6Scalar')
2012 $?BLOCK
.symbol
($_, :scope
($scope));
2013 } elsif $declarator eq 'has' {
2014 declare_attribute
($/, $declarator, $sigil, $twigil, $desigilname);
2017 $/.panic
("Scope declarator " ~ $declarator ~ " unimplemented with signatures.");
2023 elsif $<scoped
><routine_declarator
> {
2025 if $declarator eq 'our' {
2026 # Default, nothing to do.
2028 elsif $declarator eq 'my' {
2029 if $<scoped
><routine_declarator
><sym
> eq 'method' {
2030 # Add ! to start of name.
2031 $past.name
('!' ~ $past.name
());
2034 $/.panic
("Lexically scoped subs not yet implemented.");
2038 $/.panic
("Cannot apply declarator '" ~ $declarator ~ "' to a routine.");
2042 # Something else we've not implemetned yet?
2044 $/.panic
("Don't know how to apply a scope declarator here.");
2051 method variable
($/, $key) {
2053 if $key eq 'special_variable' {
2054 $past := $( $<special_variable
> );
2056 elsif $key eq '$0' {
2057 $past := PAST
::Var
.new
(
2058 :scope
('keyed_int'),
2060 :viviself
('Failure'),
2066 :value
(~$<matchidx
>),
2071 elsif $key eq '$<>' {
2072 $past := $( $<postcircumfix
> );
2073 $past.unshift(PAST
::Var
.new
(
2076 :viviself
('Failure')
2082 my @ident := $<name
><ident
>;
2084 PIR q
< $P0 = find_lex
'@ident' >;
2085 PIR q
< $P0 = clone
$P0 >;
2086 PIR q
< store_lex
'@ident', $P0 >;
2087 PIR q
< $P1 = pop $P0 >;
2088 PIR q
< store_lex
'$name', $P1 >;
2090 my $twigil := ~$<twigil
>[0];
2091 my $sigil := ~$<sigil
>;
2092 my $fullname := $sigil ~ $twigil ~ ~$name;
2094 if $fullname eq '@_' || $fullname eq '%_' {
2095 unless $?BLOCK
.symbol
($fullname) {
2096 $?BLOCK
.symbol
( $fullname, :scope
('lexical') );
2099 $var := PAST
::Var
.new
( :name
($fullname), :scope
('parameter'), :slurpy
(1) );
2102 $var := PAST
::Var
.new
( :name
($fullname), :scope
('parameter'), :slurpy
(1), :named
(1) );
2104 $?BLOCK
[0].unshift($var);
2108 if $twigil eq '^' || $twigil eq ':' {
2109 if $?BLOCK
.symbol
('___HAVE_A_SIGNATURE') {
2110 $/.panic
('A signature must not be defined on a sub that uses placeholder vars.');
2112 unless $?BLOCK
.symbol
($fullname) {
2113 $?BLOCK
.symbol
( $fullname, :scope
('lexical') );
2114 $?BLOCK
.arity
( +$?BLOCK
.arity
() + 1 );
2115 my $var := PAST
::Var
.new
(:name
($fullname), :scope
('parameter'));
2116 if $twigil eq ':' { $var.named
( ~$name ); }
2117 my $block := $?BLOCK
[0];
2118 my $i := +@
($block);
2119 while $i > 0 && $block[$i-1]<name
> gt $fullname {
2120 $block[$i] := $block[$i-1];
2127 # If it's $.x, it's a method call, not a variable.
2129 $past := PAST
::Op
.new
(
2131 :pasttype
('callmethod'),
2141 # Variable. [!:^] twigil should be kept in the name.
2142 if $twigil eq '!' || $twigil eq ':' || $twigil eq '^' { $name := $twigil ~ ~$name; }
2144 # All but subs should keep their sigils.
2146 if $<sigil
> ne '&' {
2147 $sigil := ~$<sigil
>;
2150 # If we have no twigil, but we see the name noted as an attribute in
2151 # an enclosing scope, add the ! twigil anyway; it's an alias.
2156 my $sym_table := $_.symbol
($sigil ~ $name);
2157 if defined( $sym_table )
2158 && $sym_table<scope
> eq 'attribute' {
2159 $name := '!' ~ $name;
2165 # If it's a role-private attribute, fix up the name.
2170 my $sym_table := $_.symbol
($sigil ~ $name);
2171 if defined( $sym_table )
2172 && $sym_table<scope
> eq 'rpattribute' {
2173 $name := $sym_table<real_name
>;
2179 $past := PAST
::Var
.new
(
2180 :name
( $sigil ~ $name ),
2183 if @ident || $twigil eq '*' {
2184 $past.namespace
(@ident);
2185 $past.scope
('package');
2188 # If it has a ! twigil, give it attribute scope and add self.
2190 $past.scope
('attribute');
2191 $past.unshift(PAST
::Var
.new
(
2197 # If we have something with an & sigil see if it has any entries
2198 # in the enclosing blocks; otherwise, default to package.
2199 if $<sigil
> eq '&' {
2200 $past.scope
('package');
2204 my $sym_table := $_.symbol
($name);
2205 if defined($sym_table) && defined($sym_table<scope
>) {
2206 $past.scope
( $sym_table<scope
> );
2212 $past.viviself
(container_type
($sigil));
2219 method circumfix
($/, $key) {
2222 $past := $<statementlist
><statement
>
2223 ??
$( $<statementlist
> )
2224 !! PAST
::Op
.new
(:name
('list'));
2227 $past := PAST
::Op
.new
(:name
('circumfix:[ ]'), :node
($/) );
2228 if $<statementlist
><statement
> { $past.push( $( $<statementlist
> ) ); }
2230 elsif $key eq '{ }' {
2231 # If it is completely empty or consists of a single list, the first
2232 # element of which is either a hash or a pair, it's a hash constructor.
2233 $past := $( $<pblock
> );
2235 if +@
($past) == 2 && +@
($past[0]) == 0 {
2236 if +@
($past[1]) == 0 {
2237 # Empty block, so a hash.
2240 elsif +@
($past[1]) == 1 && $past[1][0].WHAT
() eq 'Op' {
2241 if $past[1][0].name
() eq 'infix:=>' {
2242 # Block with just one pair in it, so a hash.
2245 elsif $past[1][0].name
() eq 'infix:,' {
2246 # List, but first elements must be...
2247 if $past[1][0][0].WHAT
() eq 'Op' &&
2248 $past[1][0][0].name
() eq 'infix:=>' {
2252 elsif $past[1][0][0].WHAT
() eq 'Var' &&
2253 substr($past[1][0][0].name
(), 0, 1) eq '%' {
2261 my @children := @
($past[1]);
2262 $past := PAST
::Op
.new
(
2272 declare_implicit_function_vars
($past);
2275 elsif $key eq '$( )' {
2276 my $method := contextualizer_name
($/, $<sigil
>);
2277 my $call_on := $( $<semilist
> );
2278 if $call_on.name
() eq 'infix:,' && +@
($call_on) == 0 {
2279 $call_on := PAST
::Var
.new
(
2284 $past := PAST
::Op
.new
(
2285 :pasttype
('callmethod'),
2295 method value
($/, $key) {
2300 method number
($/, $key) {
2305 ## for a variety of reasons, this is easier in PIR than NQP for now.
2306 ## NQP doesn't have assign yet, and Perl6Str is lighter-weight than Str.
2307 method integer
($/) {
2309 PIR q
< $P0 = find_lex
'$/' >;
2311 PIR q
< $P1 = new
'Perl6Str' >;
2312 PIR q
< assign
$P1, $S0 >;
2313 PIR q
< store_lex
'$str', $P1 >;
2322 method dec_number
($/) {
2323 make PAST
::Val
.new
( :value
( ~$/ ), :returns('Num'), :node( $/ ) );
2326 method radint
($/, $key) {
2330 method rad_number
($/) {
2331 my $radix := ~$<radix
>;
2332 my $intpart := ~$<intpart
>;
2333 my $fracpart := ~$<fracpart
>;
2336 if defined( $<base
>[0] ) { $base := $<base
>[0].text
(); }
2337 if defined( $<exp>[0] ) { $exp := $<exp>[0].text
(); }
2338 if ~$<postcircumfix
> {
2339 my $radcalc := $( $<postcircumfix
> );
2340 $radcalc.name
('radcalc');
2341 $radcalc.pasttype
('call');
2342 $radcalc.unshift( PAST
::Val
.new
( :value
( $radix ), :node
( $/ ) ) );
2346 my $return_type := 'Int';
2347 if $fracpart { $return_type := 'Num'; }
2349 :value
( radcalc
( $radix, $intpart, $fracpart, ~$base, ~$exp ) ),
2350 :returns
($return_type),
2358 make
$( $<quote_expression
> );
2361 method quote_expression
($/, $key) {
2363 if $key eq 'quote_regex' {
2365 $past := PAST
::Block
.new
(
2367 :compiler
('PGE::Perl6Regex'),
2369 :blocktype
('declaration'),
2373 elsif $key eq 'quote_concat' {
2374 if +$<quote_concat
> == 1 {
2375 $past := $( $<quote_concat
>[0] );
2378 $past := PAST
::Op
.new
(
2383 for $<quote_concat
> {
2384 $past.push( $($_) );
2392 method quote_concat
($/) {
2393 my $terms := +$<quote_term
>;
2395 my $past := $( $<quote_term
>[0] );
2396 while ($count != $terms) {
2397 $past := PAST
::Op
.new
(
2399 $( $<quote_term
>[$count] ),
2403 $count := $count + 1;
2409 method quote_term
($/, $key) {
2411 if ($key eq 'literal') {
2412 $past := PAST
::Val
.new
(
2413 :value
( ~$<quote_literal
> ),
2414 :returns
('Perl6Str'), :node
($/)
2417 elsif ($key eq 'variable') {
2418 $past := $( $<variable
> );
2420 elsif ($key eq 'circumfix') {
2421 $past := $( $<circumfix
> );
2422 if $past.WHAT
() eq 'Block' {
2423 $past.blocktype
('immediate');
2430 method typename
($/) {
2431 # Extract shortname part of identifier, if there is one.
2432 my $ns := $<name
><ident
>.clone
();
2433 my $shortname := $ns.pop();
2435 # Create default PAST node for package lookup of type.
2436 my $past := PAST
::Var
.new
(
2441 :viviself
('Failure')
2444 # If there's no namespace, could be lexical abstraction type.
2446 # See if we got lexical with the right name.
2448 my $name := '::' ~ $shortname;
2451 my $sym_table := $_.symbol
($name);
2452 if defined($sym_table) && defined($sym_table<scope
>) {
2453 $past.name
( $name );
2454 $past.scope
( $sym_table<scope
> );
2464 method term
($/, $key) {
2466 if $key eq 'func args' {
2467 $past := build_call
( $( $<semilist
> ) );
2468 $past.name
( ~$<ident
> );
2470 elsif $key eq 'listop args' {
2471 $past := build_call
( $( $<arglist
> ) );
2472 $past.name
( ~$<ident
> );
2474 elsif $key eq 'listop noarg' {
2475 $past := PAST
::Op
.new
( :name
( ~$<ident
> ), :pasttype
('call') );
2477 elsif $key eq 'VAR' {
2478 $past := PAST
::Op
.new
(
2484 elsif $key eq 'sigil' {
2485 my $method := contextualizer_name
($/, $<sigil
>);
2487 $past := PAST
::Op
.new
(
2488 :pasttype
('callmethod'),
2494 else { $past := $( $/{$key} ); }
2500 method semilist
($/) {
2503 !! PAST
::Op
.new
( :node
($/), :name
('infix:,') );
2508 method arglist
($/) {
2511 !! PAST
::Op
.new
( :node
($/), :name
('infix:,') );
2516 method EXPR
($/, $key) {
2520 elsif ~$<type
> eq 'infix:.=' {
2521 my $invocant := $( $/[0] );
2522 my $call := $( $/[1] );
2524 # Check that we have a sub call.
2525 if $call.WHAT
() ne 'Op' || $call.pasttype
() ne 'call' {
2526 $/.panic
('.= must have a call on the right hand side');
2529 # Make a duplicate of the target node to receive result
2530 my $target := PAST
::Var
.new
(
2531 :name
($invocant.name
()),
2532 :scope
($invocant.scope
()),
2536 # Change call node to a callmethod and add the invocant
2537 $call.pasttype
('callmethod');
2538 $call.unshift($invocant);
2540 # and assign result to target
2541 my $past := PAST
::Op
.new
(
2542 :inline
(" %r = %1.'infix:='(%0)"),
2550 elsif ~$<type
> eq 'infix:does' || ~$<type
> eq 'infix:but' {
2551 my $past := PAST
::Op
.new
(
2557 my $rhs := $( $/[1] );
2558 if $rhs.HOW
().isa
($rhs, PAST
::Op
) && $rhs.pasttype
() eq 'call' {
2559 # Make sure we only have one initialization value.
2561 $/.panic
("Role initialization can only supply a value for one attribute");
2563 # Push role name and argument onto infix:does or infix:but.
2564 $past.push($rhs[0]);
2565 $past.push($rhs[1]);
2573 my $past := PAST
::Op
.new
(
2578 if $<top
><subname
> { $past.name
(~$<top
><subname
>); }
2580 unless +$_.from
() == +$_.to
() { $past.push( $($_) ) };
2588 method regex_declarator
($/, $key) {
2593 method regex_declarator_regex
($/) {
2594 my $past := $( $<quote_expression
> );
2595 $past.name
( ~$<ident
>[0] );
2600 method regex_declarator_token
($/) {
2601 my $past := $( $<quote_expression
> );
2602 $past.compiler_args
( :ratchet
(1) );
2603 $past.name
( ~$<ident
>[0] );
2608 method regex_declarator_rule
($/) {
2609 my $past := $( $<quote_expression
> );
2610 $past.compiler_args
( :s
(1), :ratchet
(1) );
2611 $past.name
( ~$<ident
>[0] );
2616 method type_declarator
($/) {
2617 # We need a block containing the constraint condition.
2618 my $past := $( $<EXPR
> );
2619 if $past.WHAT
() ne 'Block' {
2620 # Make block with a smart match of the the expression as its contents.
2621 $past := PAST
::Block
.new
(
2624 :scope
('parameter'),
2630 :pasttype
('callmethod'),
2642 # Make sure it has a parameter and keep hold of it if found.
2644 my $dollar_underscore;
2646 if $_.WHAT
() eq 'Var' {
2647 if $_.scope
() eq 'parameter' {
2650 elsif $_.name
() eq '$_' {
2651 $dollar_underscore := $_;
2656 if $dollar_underscore {
2657 $dollar_underscore.scope
('parameter');
2658 $param := $dollar_underscore;
2661 $param := PAST
::Var
.new
(
2665 $past[0].push($param);
2669 # Do we have an existing constraint to check?
2671 my $new_cond := $past[1];
2672 my $prev_cond := $( $<typename
>[0] );
2673 $past[1] := PAST
::Op
.new
(
2676 :pasttype
('callmethod'),
2680 :name
($param.name
())
2687 # Set block details.
2690 # Now we need to create the block wrapper class.
2691 $past := PAST
::Op
.new
(
2692 :pasttype
('callmethod'),
2698 PAST
::Val
.new
( :value
(~$<name
>) ),
2706 method fatarrow
($/) {
2707 my $past := PAST
::Op
.new
(
2712 PAST
::Val
.new
( :value
(~$<key
>) ),
2719 method colonpair
($/, $key) {
2723 if $key eq 'false' {
2724 $pair_key := PAST
::Val
.new
( :value
(~$<ident
>) );
2725 $pair_val := PAST
::Val
.new
( :value
(0), :returns
('Int') );
2727 elsif $key eq 'value' {
2728 $pair_key := PAST
::Val
.new
( :value
(~$<ident
>) );
2729 if $<postcircumfix
> {
2730 $pair_val := $( $<postcircumfix
>[0] );
2731 if $pair_val.name
() ne 'infix:,' || +@
($pair_val) == 1 {
2732 $pair_val := $pair_val[0];
2736 $pair_val := PAST
::Val
.new
( :value
(1), :returns
('Int') );
2739 elsif $key eq 'varname' {
2740 if $<desigilname
><name
> {
2741 $pair_key := PAST
::Val
.new
( :value
( ~$<desigilname
> ) );
2742 $pair_val := PAST
::Var
.new
(
2743 :name
( ~$<sigil
> ~ ~$<twigil
> ~ ~$<desigilname
> )
2747 $/.panic
('complex varname colonpair case not yet implemented');
2751 $/.panic
($key ~ " pairs not yet implemented.");
2754 my $past := PAST
::Op
.new
(
2766 method capterm
($/) {
2767 # We will create the capture object, passing the things supplied.
2768 my $past := build_call
( $( $<capture
> ) );
2769 $past.name
('prefix:\\');
2774 method capture
($/) {
2779 method sigterm
($/) {
2780 my $past := $( $/<signature
> );
2785 # Used by all calling code to process arguments into the correct form.
2786 sub build_call
($args) {
2787 if $args.WHAT
() ne 'Op' || $args.name
() ne 'infix:,' {
2788 $args := PAST
::Op
.new
( :node
($args), :name
('infix:,'), $args);
2791 my $elems := +@
($args);
2794 if $x.returns
() eq 'Pair' {
2800 $args.pasttype
('call');
2805 sub declare_implicit_var
($block, $name, $type) {
2806 unless $block.symbol
($name) {
2807 my $var := PAST
::Var
.new
( :name
($name), :isdecl
(1) );
2808 $var.scope
($type eq 'parameter' ??
'parameter' !! 'lexical');
2810 $var.viviself
( 'Perl6Scalar' );
2813 my $opast := PAST
::Op
.new
(
2815 PAST
::Val
.new
( :value
($name) )
2817 $var.viviself
($opast);
2819 $block[0].push($var);
2820 $block.symbol
($name, :scope
('lexical') );
2825 sub declare_implicit_function_vars
($block) {
2826 declare_implicit_var
($block, '$_',
2827 defined($block.arity
()) ??
'outer' !! 'parameter');
2828 declare_implicit_var
($block, '$!', 'outer');
2829 declare_implicit_var
($block, '$/', 'outer');
2833 sub declare_implicit_immediate_vars
($block) {
2834 declare_implicit_var
($block, '$_', 'outer');
2835 declare_implicit_var
($block, '$!', 'outer');
2836 declare_implicit_var
($block, '$/', 'outer');
2840 sub contextualizer_name
($/, $sigil) {
2841 ## Contextualizing is calling .item, .list, .hash, etc.
2842 ## on the expression in the brackets
2844 if $sigil eq '$' { $method := 'item'; }
2845 elsif $sigil eq '@' { $method := 'list'; }
2846 elsif $sigil eq '%' { $method := 'hash'; }
2848 $/.panic
("Use of contextualizer " ~ $sigil ~ " not implemented.");
2854 sub container_type
($sigil) {
2855 if $sigil eq '@' { return 'Perl6Array' }
2856 elsif $sigil eq '%' { return 'Perl6Hash' }
2857 else { return 'Perl6Scalar' }
2861 # Processes a handles expression to produce the appropriate method(s).
2862 sub process_handles
($/, $expr, $attr_name) {
2863 my $past := PAST
::Stmts
.new
();
2865 # What type of expression do we have?
2866 if $expr.WHAT
() eq 'Val' && $expr.returns
() eq 'Perl6Str' {
2867 # Just a single string mapping.
2868 my $name := ~$expr.value
();
2869 my $method := make_handles_method
($/, $name, $name, $attr_name);
2870 $past.push(add_method_to_class
($method));
2872 elsif $expr.WHAT
() eq 'Op' && $expr.returns
() eq 'Pair' {
2874 my $method := make_handles_method_from_pair
($/, $expr, $attr_name);
2875 $past.push(add_method_to_class
($method));
2877 elsif $expr.WHAT
() eq 'Op' && $expr.pasttype
() eq 'call' &&
2878 $expr.name
() eq 'list' {
2879 # List of something, but what is it?
2881 if $_.WHAT
() eq 'Val' && $_.returns
() eq 'Perl6Str' {
2883 my $name := ~$_.value
();
2884 my $method := make_handles_method
($/, $name, $name, $attr_name);
2885 $past.push(add_method_to_class
($method));
2887 elsif $_.WHAT
() eq 'Op' && $_.returns
() eq 'Pair' {
2889 my $method := make_handles_method_from_pair
($/, $_, $attr_name);
2890 $past.push(add_method_to_class
($method));
2894 'Only a list of constants or pairs can be used in handles'
2899 elsif $expr.WHAT
() eq 'Stmts' && $expr[0].name
() eq 'infix:,' {
2900 # Also a list, but constructed differently.
2902 if $_.WHAT
() eq 'Val' && $_.returns
() eq 'Perl6Str' {
2904 my $name := ~$_.value
();
2905 my $method := make_handles_method
($/, $name, $name, $attr_name);
2906 $past.push(add_method_to_class
($method));
2908 elsif $_.WHAT
() eq 'Op' && $_.returns
() eq 'Pair' {
2910 my $method := make_handles_method_from_pair
($/, $_, $attr_name);
2911 $past.push(add_method_to_class
($method));
2915 'Only a list of constants or pairs can be used in handles'
2921 $/.panic
('Illegal or unimplemented use of handles');
2928 # Produces a handles method.
2929 sub make_handles_method
($/, $from_name, $to_name, $attr_name) {
2932 :pirflags
(':method'),
2933 :blocktype
('declaration'),
2937 :scope
('parameter'),
2942 :scope
('parameter'),
2948 :pasttype
('callmethod'),
2962 :named
(PAST
::Val
.new
( :value
(1) ))
2969 # Makes a handles method from a pair.
2970 sub make_handles_method_from_pair
($/, $pair, $attr_name) {
2973 # Single pair mapping. Check we have string name and value.
2974 my $key := $pair[0];
2975 my $value := $pair[1];
2976 if $key.WHAT
() eq 'Val' && $value.WHAT
() eq 'Val' {
2977 my $from_name := ~$key.value
();
2978 my $to_name := ~$value.value
();
2979 $meth := make_handles_method
($/, $from_name, $to_name, $attr_name);
2982 $/.panic
('Only constants may be used in a handles pair argument.');
2989 # This takes an array of match objects of type constraints and builds a type
2990 # representation out of them.
2991 sub build_type
($cons_pt) {
2992 # Build the type constraints list for the variable.
2994 my $type_cons := PAST
::Op
.new
();
2996 $type_cons.push( $( $_<typename
> ) );
2997 $num_types := $num_types + 1;
3000 # If there were none, it's Object.
3001 if $num_types == 0 {
3002 $type_cons.push(PAST
::Var
.new
(
3009 # Now need to apply the type constraints. How many are there?
3010 if $num_types == 1 {
3011 # Just the first one.
3012 $type_cons := $type_cons[0];
3015 # Many; make an and junction of types.
3016 $type_cons.pasttype
('call');
3017 $type_cons.name
('all');
3024 # Takes a block and turns it into a sub.
3025 sub create_sub
($/, $past) {
3026 $past.blocktype
('declaration');
3027 set_block_proto
($past, 'Sub');
3028 if $<routine_def
><multisig
> {
3029 set_block_sig
($past, $( $<routine_def
><multisig
>[0]<signature
> ));
3032 set_block_sig
($past, empty_signature
());
3037 # Set the proto object type of a block.
3038 sub set_block_proto
($block, $type) {
3039 my $loadinit := $block.loadinit
();
3042 :inline
('setprop %0, "$!proto", %1'),
3043 PAST
::Var
.new
( :name
('block'), :scope
('register') ),
3044 PAST
::Var
.new
( :name
($type), :scope
('package') )
3050 # Associate a signature object with a block.
3051 sub set_block_sig
($block, $sig_obj) {
3052 my $loadinit := $block.loadinit
();
3055 :inline
('setprop %0, "$!signature", %1'),
3056 PAST
::Var
.new
( :name
('block'), :scope
('register') ),
3063 # Create an empty signautre object for subs with no signatures.
3064 sub empty_signature
() {
3066 :pasttype
('callmethod'),
3077 # Creates a signature descriptor (for now, just a hash).
3078 sub sig_descriptor_create
() {
3080 PAST
::Op
.new
( :inline
(' $P1 = new "Hash"') ),
3082 PAST
::Op
.new
( :inline
(' %r = $P1') )
3086 # Sets a given value in the signature descriptor.
3087 sub sig_descriptor_set
($descriptor, $name, $value) {
3088 $descriptor[1].push(PAST
::Op
.new
(
3089 :inline
(' $P1[%0] = %1'),
3090 PAST
::Val
.new
( :value
(~$name) ),
3095 # Returns a list of variables from a signature that we are to declare. Panics
3096 # if the signature is too complex to unpack.
3097 sub sig_extract_declarables
($/, $sig_setup) {
3098 # Just make sure it's what we expect.
3099 if $sig_setup.WHAT
() ne 'Op' || $sig_setup.pasttype
() ne 'callmethod' ||
3100 $sig_setup[0].name
() ne 'Signature' {
3101 $/.panic
("sig_extract_declarables was not passed signature declaration PAST!");
3104 # Now go through what signature and extract what to declare.
3105 my @result := list
();
3109 # Skip over invocant.
3113 # If it has a name, we're fine; if not, it's something odd - give
3114 # it a miss for now.
3115 my $found_name := undef;
3117 if $_[0].value
() eq 'name' {
3118 $found_name := ~$_[1].value
();
3121 if defined($found_name) {
3122 @result.push($found_name);
3125 $/.panic
("Signature too complex for LHS of assignment.");
3132 # Generates a setter/getter method for an attribute in a class or role.
3133 sub make_accessor
($/, $method_name, $attr_name, $rw, $scope) {
3136 $getset := PAST
::Var
.new
( :name
($attr_name), :scope
($scope) );
3139 $getset := PAST
::Op
.new
(
3141 ' %r = new "Perl6Scalar", %0',
3142 ' $P0 = get_hll_global [ "Bool" ], "True"',
3143 ' setprop %r, "readonly", $P0'
3145 PAST
::Var
.new
( :name
($attr_name), :scope
($scope) )
3148 my $accessor := PAST
::Block
.new
(
3149 PAST
::Stmts
.new
($getset),
3150 :blocktype
('declaration'),
3151 :name
($method_name),
3152 :pirflags
(':method'),
3159 # Adds the given method to the current class. This just returns the method that
3160 # is passed to it if the current class is named; in the case that it is anonymous
3161 # we need instead to emit an add_method call and remove the methods name so it
3162 # doesn't pollute the namespace.
3163 sub add_method_to_class
($method) {
3166 if $?CLASS
=:= $?PACKAGE
&& +@
($?CLASS
[0][1]) == 0 {
3167 # Create new PAST::Block - can't work out how to unset the name of an
3169 my $new_method := PAST
::Block
.new
(
3170 :blocktype
($method.blocktype
()),
3171 :pirflags
($method.pirflags
())
3174 $new_method.push($_);
3177 # Put call to add method into the class definition.
3178 $?CLASS
.push(PAST
::Op
.new
(
3179 :pasttype
('callmethod'),
3180 :name
('add_method'),
3185 PAST
::Val
.new
( :value
($method.name
()) ),
3196 # Creates an anonymous subset type.
3197 sub make_anon_subset
($past, $parameter) {
3198 # We need a block containing the constraint condition.
3199 if $past.WHAT
() ne 'Block' {
3200 # Make block with the expression as its contents.
3201 $past := PAST
::Block
.new
(
3203 PAST
::Stmts
.new
( $past )
3207 # Make sure it has a parameter.
3209 my $dollar_underscore;
3211 if $_.WHAT
() eq 'Var' {
3212 if $_.scope
() eq 'parameter' {
3215 elsif $_.name
() eq '$_' {
3216 $dollar_underscore := $_;
3221 if $dollar_underscore {
3222 $dollar_underscore.scope
('parameter');
3223 $param := $dollar_underscore;
3226 $param := PAST
::Var
.new
(
3230 $past[0].push($param);
3234 # Now we'll just pass this block to the type checker,
3235 # since smart-matching a block invokes it.
3236 return PAST
::Op
.new
(
3238 :name
('!TYPECHECKPARAM'),
3240 :pirop
('newclosure'),
3244 :name
($parameter.name
()),
3252 # cperl-indent-level: 4
3255 # vim: expandtab shiftwidth=4: