@@ -668,124 +668,133 @@ class QAST::MASTCompiler {
668
668
push_op(@ pre , ' takeclosure' , $ reg , $ reg );
669
669
}
670
670
671
- # Analyze parameters to get count of required/optional and make sure
672
- # all is in order.
673
- my $ param_index := 0 ;
674
- my int $ pos_required := 0 ;
675
- my int $ pos_optional := 0 ;
676
- my int $ pos_slurpy := 0 ;
677
- for $ block . params {
678
- if $ _ . named {
679
- # Don't count.
680
- }
681
- elsif $ _ . slurpy {
682
- if $ pos_slurpy {
683
- nqp ::die(" Only one slurpy positional allowed" );
671
+ if $ node . custom_args {
672
+ # The block does the arg processing by itself, so we accept any number
673
+ # of args here.
674
+ push_op(@ pre , ' checkarity' ,
675
+ MAST::IVal. new ( : size(16 ), : value(0 )),
676
+ MAST::IVal. new ( : size(16 ), : value(-1 )));
677
+ }
678
+ else {
679
+ # Analyze parameters to get count of required/optional and make sure
680
+ # all is in order.
681
+ my $ param_index := 0 ;
682
+ my int $ pos_required := 0 ;
683
+ my int $ pos_optional := 0 ;
684
+ my int $ pos_slurpy := 0 ;
685
+ for $ block . params {
686
+ if $ _ . named {
687
+ # Don't count.
684
688
}
685
- $ pos_slurpy := 1 ;
686
- }
687
- elsif $ _ . default {
688
- if $ pos_slurpy {
689
- nqp ::die( " Optional positionals must come before all slurpy positionals " ) ;
689
+ elsif $ _ . slurpy {
690
+ if $ pos_slurpy {
691
+ nqp ::die( " Only one slurpy positional allowed " );
692
+ }
693
+ $ pos_slurpy := 1 ;
690
694
}
691
- $ pos_optional ++ ;
692
- }
693
- else {
694
- if $ pos_optional {
695
- nqp ::die( " Required positionals must come before all optional positionals " ) ;
695
+ elsif $ _ . default {
696
+ if $ pos_slurpy {
697
+ nqp ::die( " Optional positionals must come before all slurpy positionals " );
698
+ }
699
+ $ pos_optional ++ ;
696
700
}
697
- if $ pos_slurpy {
698
- nqp ::die(" Required positionals must come before all slurpy positionals" );
701
+ else {
702
+ if $ pos_optional {
703
+ nqp ::die(" Required positionals must come before all optional positionals" );
704
+ }
705
+ if $ pos_slurpy {
706
+ nqp ::die(" Required positionals must come before all slurpy positionals" );
707
+ }
708
+ $ pos_required ++ ;
699
709
}
700
- $ pos_required ++ ;
701
710
}
702
- }
703
711
704
- # check the arity
705
- push_op(@ pre , ' checkarity' ,
706
- MAST::IVal. new ( : size(16 ), : value($ pos_required )),
707
- MAST::IVal. new ( : size(16 ), : value($ pos_slurpy ?? -1 !! $ pos_required + $ pos_optional )));
712
+ # check the arity
713
+ push_op(@ pre , ' checkarity' ,
714
+ MAST::IVal. new ( : size(16 ), : value($ pos_required )),
715
+ MAST::IVal. new ( : size(16 ), : value($ pos_slurpy ?? -1 !! $ pos_required + $ pos_optional )));
708
716
709
- # build up instructions to bind the params
710
- for $ block . params -> $ var {
717
+ # build up instructions to bind the params
718
+ for $ block . params -> $ var {
711
719
712
- my $ scope := $ var . scope;
713
- nqp ::die(" Param scope must be 'local' or 'lexical'" )
714
- if $ scope ne ' lexical' && $ scope ne ' local' ;
720
+ my $ scope := $ var . scope;
721
+ nqp ::die(" Param scope must be 'local' or 'lexical'" )
722
+ if $ scope ne ' lexical' && $ scope ne ' local' ;
715
723
716
- my $ param_kind := self . type_to_register_kind($ var . returns );
717
- my $ opslot := @ kind_to_op_slot [$ param_kind ];
724
+ my $ param_kind := self . type_to_register_kind($ var . returns );
725
+ my $ opslot := @ kind_to_op_slot [$ param_kind ];
718
726
719
- my $ opname_index := ($ var . named ?? 8 !! 0 ) + ($ var . default ?? 4 !! 0 ) + $ opslot ;
720
- my $ opname := @ param_opnames [$ opname_index ];
727
+ my $ opname_index := ($ var . named ?? 8 !! 0 ) + ($ var . default ?? 4 !! 0 ) + $ opslot ;
728
+ my $ opname := @ param_opnames [$ opname_index ];
721
729
722
- # what will be put in the value register
723
- my $ val ;
730
+ # what will be put in the value register
731
+ my $ val ;
724
732
725
- if $ var . slurpy {
726
- if $ var . named {
727
- $ opname := " param_sn" ;
733
+ if $ var . slurpy {
734
+ if $ var . named {
735
+ $ opname := " param_sn" ;
736
+ }
737
+ else {
738
+ $ opname := " param_sp" ;
739
+ }
728
740
}
729
- else {
730
- $ opname := " param_sp" ;
741
+ elsif $ var . named {
742
+ $ val := MAST::SVal. new ( : value($ var . named) );
743
+ }
744
+ else { # positional
745
+ $ val := MAST::IVal. new ( : size(16 ), : value($ param_index ));
731
746
}
732
- }
733
- elsif $ var . named {
734
- $ val := MAST::SVal. new ( : value($ var . named) );
735
- }
736
- else { # positional
737
- $ val := MAST::IVal. new ( : size(16 ), : value($ param_index ));
738
- }
739
747
740
- # the variable register
741
- my $ valreg := $ scope eq ' lexical'
742
- ?? $ block . lexical_param($ var . name )
743
- !! $ block . local($ var . name );
748
+ # the variable register
749
+ my $ valreg := $ scope eq ' lexical'
750
+ ?? $ block . lexical_param($ var . name )
751
+ !! $ block . local($ var . name );
744
752
745
- # NQP->QAST always provides a default value for optional NQP params
746
- # even if no default initializer expression is provided.
747
- if $ var . default {
748
- # generate end label to skip initialization code
749
- my $ endlbl := MAST::Label. new ( : name(self . unique (' param' ) ~ ' _end' ) );
753
+ # NQP->QAST always provides a default value for optional NQP params
754
+ # even if no default initializer expression is provided.
755
+ if $ var . default {
756
+ # generate end label to skip initialization code
757
+ my $ endlbl := MAST::Label. new ( : name(self . unique (' param' ) ~ ' _end' ) );
750
758
751
- # generate default initialization code. Could also be
752
- # wrapped in another QAST::Block.
753
- my $ default_mast := self . as_mast($ var . default, : want($ param_kind ));
759
+ # generate default initialization code. Could also be
760
+ # wrapped in another QAST::Block.
761
+ my $ default_mast := self . as_mast($ var . default, : want($ param_kind ));
754
762
755
- # nqp::die("default initialization result type doesn't match the param type")
756
- # unless $default_mast.result_kind == $param_kind;
763
+ # nqp::die("default initialization result type doesn't match the param type")
764
+ # unless $default_mast.result_kind == $param_kind;
757
765
758
- # emit param grabbing op
759
- push_op(@ pre , $ opname , $ valreg , $ val , $ endlbl );
766
+ # emit param grabbing op
767
+ push_op(@ pre , $ opname , $ valreg , $ val , $ endlbl );
760
768
761
- # emit default initialization code
762
- push_ilist(@ pre , $ default_mast );
769
+ # emit default initialization code
770
+ push_ilist(@ pre , $ default_mast );
763
771
764
- # put the initialization result in the variable register
765
- push_op(@ pre , ' set' , $ valreg , $ default_mast . result_reg);
766
- $ * REGALLOC . release_register($ default_mast . result_reg, $ default_mast . result_kind);
772
+ # put the initialization result in the variable register
773
+ push_op(@ pre , ' set' , $ valreg , $ default_mast . result_reg);
774
+ $ * REGALLOC . release_register($ default_mast . result_reg, $ default_mast . result_kind);
767
775
768
- # end label to skip initialization code
769
- nqp :: push (@ pre , $ endlbl );
770
- }
771
- elsif $ var . slurpy {
772
- if $ var . named {
773
- push_op(@ pre , $ opname , $ valreg );
776
+ # end label to skip initialization code
777
+ nqp :: push (@ pre , $ endlbl );
778
+ }
779
+ elsif $ var . slurpy {
780
+ if $ var . named {
781
+ push_op(@ pre , $ opname , $ valreg );
782
+ }
783
+ else {
784
+ push_op(@ pre , $ opname , $ valreg , MAST::IVal. new ( : value($ pos_required + $ pos_optional ) ));
785
+ }
774
786
}
775
787
else {
776
- push_op(@ pre , $ opname , $ valreg , MAST::IVal. new ( : value($ pos_required + $ pos_optional ) ));
788
+ # emit param grabbing op
789
+ push_op(@ pre , $ opname , $ valreg , $ val );
777
790
}
778
- }
779
- else {
780
- # emit param grabbing op
781
- push_op(@ pre , $ opname , $ valreg , $ val );
782
- }
783
791
784
- if $ scope eq ' lexical' {
785
- # emit the op to bind the lexical to the result register
786
- push_op(@ pre , ' bindlex' , $ block . lexical($ var . name ), $ valreg );
792
+ if $ scope eq ' lexical' {
793
+ # emit the op to bind the lexical to the result register
794
+ push_op(@ pre , ' bindlex' , $ block . lexical($ var . name ), $ valreg );
795
+ }
796
+ $ param_index ++ ;
787
797
}
788
- $ param_index ++ ;
789
798
}
790
799
791
800
nqp :: splice ($ frame . instructions, @ pre , 0 , 0 );
0 commit comments