@@ -480,6 +480,10 @@ gen_call(mrc_codegen_scope *s, mrc_node *tree, int val, int safe)
480
480
noop = 1 ;
481
481
blk = 1 ;
482
482
}
483
+ if (cast->arguments && cast->arguments ->base .flags &PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING) {
484
+ blk = 1 ;
485
+ n = 0xFF ;
486
+ }
483
487
push ();pop ();
484
488
s->sp = sp_save;
485
489
@@ -661,12 +665,16 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
661
665
}
662
666
663
667
664
- int ma, mma, oa, ra, pa, ppa, ka, kd, ba, i;
668
+ int ma, mma, oa, ra, pa, ppa, ka, kd, ba, i, forwarding;
669
+ forwarding = 0 ;
670
+ int block_reg = 0 ;
665
671
pm_constant_id_list_t *lv = (pm_constant_id_list_t *)codegen_palloc (s, sizeof (pm_constant_id_list_t ));
666
672
pm_constant_id_t null_mark = pm_constant_pool_insert_constant (&s->c ->p ->constant_pool , NULL , 0 );
667
673
668
674
// Create lv regs from Prism's locals
669
675
if (parameters == NULL ) {
676
+ // TODO: FIXME this doesn't work with numbered parameters
677
+ // TODO: `it`
670
678
mrc_constant_id_list_init_capacity (s, lv, 2 );
671
679
mrc_constant_id_list_append (s, lv, null_mark);
672
680
for (i = 0 ; i < locals->size ; i++) {
@@ -704,7 +712,6 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
704
712
// mandatory
705
713
for (i = 0 ; i < ma; i++) {
706
714
if (nint (parameters->requireds .nodes [i]) == PM_MULTI_TARGET_NODE) {
707
- mrc_constant_id_list_append (s, lv, null_mark);
708
715
} else {
709
716
mrc_constant_id_list_append (s, lv, ((pm_required_parameter_node_t *)parameters->requireds .nodes [i])->name );
710
717
}
@@ -725,7 +732,6 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
725
732
// post
726
733
for (i = 0 ; i < pa; i++) {
727
734
if (nint (parameters->posts .nodes [i]) == PM_MULTI_TARGET_NODE) {
728
- mrc_constant_id_list_append (s, lv, null_mark);
729
735
} else {
730
736
mrc_constant_id_list_append (s, lv, ((pm_required_parameter_node_t *)parameters->posts .nodes [i])->name );
731
737
}
@@ -734,42 +740,60 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
734
740
if (ka || kd || ba) {
735
741
// keyword rest
736
742
mrc_bool write_dastr = false ;
743
+ if (ka || kd) {
744
+ write_dastr = true ;
745
+ }
737
746
if (kd) {
738
- if (!((pm_keyword_rest_parameter_node_t *)parameters->keyword_rest )->name ) {
739
- write_dastr = true ;
740
- }
741
- else {
742
- mrc_constant_id_list_append (s, lv, ((pm_keyword_rest_parameter_node_t *)parameters->keyword_rest )->name );
747
+ switch (nint (parameters->keyword_rest )) {
748
+ case PM_KEYWORD_REST_PARAMETER_NODE: {
749
+ if (((pm_keyword_rest_parameter_node_t *)parameters->keyword_rest )->name ) {
750
+ mrc_constant_id_list_append (s, lv, ((pm_keyword_rest_parameter_node_t *)parameters->keyword_rest )->name );
751
+ }
752
+ break ;
753
+ }
754
+ case PM_FORWARDING_PARAMETER_NODE: {
755
+ forwarding = 1 ;
756
+ write_dastr = false ;
757
+ pm_constant_id_t astr = MRC_OPSYM_2 (mul);
758
+ mrc_constant_id_list_append (s, lv, astr);
759
+ pm_constant_id_t dastr = MRC_OPSYM_2 (pow );
760
+ mrc_constant_id_list_append (s, lv, dastr);
761
+ mrc_constant_id_list_append (s, lv, null_mark);
762
+ pm_constant_id_t and = MRC_OPSYM_2 (and );
763
+ mrc_constant_id_list_append (s, lv, and );
764
+ block_reg = lv->size ;
765
+ break ;
766
+ }
767
+ default :
768
+ codegen_error (s, " Unknown node" );
743
769
}
744
770
}
745
- else if (!ba) {
746
- write_dastr = true ;
747
- }
748
771
if (write_dastr) {
749
772
pm_constant_id_t dastr = MRC_OPSYM_2 (pow );
750
773
mrc_constant_id_list_append (s, lv, dastr);
751
774
}
752
- // block
753
- if (ba) {
754
- if (((pm_block_parameter_node_t *)parameters->block )->name ) {
755
- mrc_constant_id_list_append (s, lv, ((pm_block_parameter_node_t *)parameters->block )->name );
756
- }
757
- else {
758
- pm_constant_id_t and = MRC_OPSYM_2 (and );
759
- mrc_constant_id_list_append (s, lv, and );
760
- }
775
+ }
776
+ if (forwarding == 0 ) {
777
+ mrc_constant_id_list_append (s, lv, null_mark);
778
+ }
779
+ // block
780
+ if (ba) {
781
+ if (((pm_block_parameter_node_t *)parameters->block )->name ) {
782
+ mrc_constant_id_list_append (s, lv, ((pm_block_parameter_node_t *)parameters->block )->name );
761
783
}
762
784
else {
763
- mrc_constant_id_list_append (s, lv, null_mark);
785
+ pm_constant_id_t and = MRC_OPSYM_2 (and );
786
+ mrc_constant_id_list_append (s, lv, and );
764
787
}
765
- // keywords
766
- for (i = 0 ; i < ka; i++) {
767
- if (nint (parameters->keywords .nodes [i]) == PM_REQUIRED_KEYWORD_PARAMETER_NODE) {
768
- mrc_constant_id_list_append (s, lv, ((pm_required_keyword_parameter_node_t *)parameters->keywords .nodes [i])->name );
769
- }
770
- else {
771
- mrc_constant_id_list_append (s, lv, ((pm_optional_keyword_parameter_node_t *)parameters->keywords .nodes [i])->name );
772
- }
788
+ block_reg = lv->size ;
789
+ }
790
+ // keywords
791
+ for (i = 0 ; i < ka; i++) {
792
+ if (nint (parameters->keywords .nodes [i]) == PM_REQUIRED_KEYWORD_PARAMETER_NODE) {
793
+ mrc_constant_id_list_append (s, lv, ((pm_required_keyword_parameter_node_t *)parameters->keywords .nodes [i])->name );
794
+ }
795
+ else {
796
+ mrc_constant_id_list_append (s, lv, ((pm_optional_keyword_parameter_node_t *)parameters->keywords .nodes [i])->name );
773
797
}
774
798
}
775
799
for (i = 0 ; i < ma; i++) {
@@ -789,10 +813,6 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
789
813
}
790
814
}
791
815
}
792
- if (ba == 0 ) {
793
- // Insert implicit block parameter before locals
794
- mrc_constant_id_list_append (s, lv, null_mark);
795
- }
796
816
if (locals) {
797
817
for (i = 0 ; i < locals->size ; i++) {
798
818
if (!pm_constant_id_list_includes (lv, locals->ids [i])) {
@@ -831,6 +851,8 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
831
851
codegen_error (s, " too many formal arguments" );
832
852
}
833
853
/* (23bits = 5:5:1:5:5:1:1) */
854
+ ra = ra|forwarding;
855
+ ba = ba|forwarding;
834
856
a = MRC_ARGS_REQ (ma)
835
857
| MRC_ARGS_OPT (oa)
836
858
| (ra? MRC_ARGS_REST () : 0 )
@@ -909,6 +931,11 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
909
931
}
910
932
}
911
933
934
+ /* block argument */
935
+ if (block_reg) {
936
+ gen_move (s, block_reg, block_reg-1 , 0 );
937
+ }
938
+
912
939
/* argument destructuring */
913
940
if (margs) {
914
941
pos = 1 ;
@@ -2834,6 +2861,36 @@ codegen(mrc_codegen_scope *s, mrc_node *tree, int val)
2834
2861
}
2835
2862
break ;
2836
2863
}
2864
+ case PM_FORWARDING_ARGUMENTS_NODE:
2865
+ {
2866
+ // CAST(forwarding_arguments);
2867
+ if (val) {
2868
+ int idx;
2869
+ genop_1 (s, OP_LOADNIL, cursp ());
2870
+ push ();
2871
+ // *
2872
+ idx = lv_idx (s, MRC_OPSYM_2 (mul));
2873
+ assert (idx != 0 );
2874
+ gen_move (s, cursp (), idx, val);
2875
+ pop ();
2876
+ genop_1 (s, OP_ARYCAT, cursp ());
2877
+ push ();
2878
+ // **
2879
+ genop_2 (s, OP_HASH, cursp (), 0 );
2880
+ push ();
2881
+ idx = lv_idx (s, MRC_OPSYM_2 (pow ));
2882
+ assert (idx != 0 );
2883
+ gen_move (s, cursp (), idx, val);
2884
+ pop ();
2885
+ genop_1 (s, OP_HASHCAT, cursp ());
2886
+ push ();
2887
+ // &
2888
+ idx = lv_idx (s, MRC_OPSYM_2 (and ));
2889
+ assert (idx != 0 );
2890
+ gen_move (s, cursp (), idx, val);
2891
+ }
2892
+ break ;
2893
+ }
2837
2894
default :
2838
2895
{
2839
2896
char buf[256 ];
0 commit comments