Skip to content

Commit 468a30e

Browse files
committed
PM_FORWARDING_PARAMETER_NODE
1 parent f6fc67e commit 468a30e

File tree

1 file changed

+90
-33
lines changed

1 file changed

+90
-33
lines changed

src/codegen_prism.inc

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,10 @@ gen_call(mrc_codegen_scope *s, mrc_node *tree, int val, int safe)
480480
noop = 1;
481481
blk = 1;
482482
}
483+
if (cast->arguments && cast->arguments->base.flags &PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING) {
484+
blk = 1;
485+
n = 0xFF;
486+
}
483487
push();pop();
484488
s->sp = sp_save;
485489

@@ -661,12 +665,16 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
661665
}
662666

663667

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;
665671
pm_constant_id_list_t *lv = (pm_constant_id_list_t *)codegen_palloc(s, sizeof(pm_constant_id_list_t));
666672
pm_constant_id_t null_mark = pm_constant_pool_insert_constant(&s->c->p->constant_pool, NULL, 0);
667673

668674
// Create lv regs from Prism's locals
669675
if (parameters == NULL) {
676+
// TODO: FIXME this doesn't work with numbered parameters
677+
// TODO: `it`
670678
mrc_constant_id_list_init_capacity(s, lv, 2);
671679
mrc_constant_id_list_append(s, lv, null_mark);
672680
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
704712
// mandatory
705713
for (i = 0; i < ma; i++) {
706714
if (nint(parameters->requireds.nodes[i]) == PM_MULTI_TARGET_NODE) {
707-
mrc_constant_id_list_append(s, lv, null_mark);
708715
} else {
709716
mrc_constant_id_list_append(s, lv, ((pm_required_parameter_node_t *)parameters->requireds.nodes[i])->name);
710717
}
@@ -725,7 +732,6 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
725732
// post
726733
for (i = 0; i < pa; i++) {
727734
if (nint(parameters->posts.nodes[i]) == PM_MULTI_TARGET_NODE) {
728-
mrc_constant_id_list_append(s, lv, null_mark);
729735
} else {
730736
mrc_constant_id_list_append(s, lv, ((pm_required_parameter_node_t *)parameters->posts.nodes[i])->name);
731737
}
@@ -734,42 +740,60 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
734740
if (ka || kd || ba) {
735741
// keyword rest
736742
mrc_bool write_dastr = false;
743+
if (ka || kd) {
744+
write_dastr = true;
745+
}
737746
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");
743769
}
744770
}
745-
else if (!ba) {
746-
write_dastr = true;
747-
}
748771
if (write_dastr) {
749772
pm_constant_id_t dastr = MRC_OPSYM_2(pow);
750773
mrc_constant_id_list_append(s, lv, dastr);
751774
}
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);
761783
}
762784
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);
764787
}
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);
773797
}
774798
}
775799
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
789813
}
790814
}
791815
}
792-
if (ba == 0) {
793-
// Insert implicit block parameter before locals
794-
mrc_constant_id_list_append(s, lv, null_mark);
795-
}
796816
if (locals) {
797817
for (i = 0; i < locals->size; i++) {
798818
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
831851
codegen_error(s, "too many formal arguments");
832852
}
833853
/* (23bits = 5:5:1:5:5:1:1) */
854+
ra = ra|forwarding;
855+
ba = ba|forwarding;
834856
a = MRC_ARGS_REQ(ma)
835857
| MRC_ARGS_OPT(oa)
836858
| (ra? MRC_ARGS_REST() : 0)
@@ -909,6 +931,11 @@ lambda_body(mrc_codegen_scope *s, mrc_node *tree, mrc_node *body, pm_constant_id
909931
}
910932
}
911933

934+
/* block argument */
935+
if (block_reg) {
936+
gen_move(s, block_reg, block_reg-1, 0);
937+
}
938+
912939
/* argument destructuring */
913940
if (margs) {
914941
pos = 1;
@@ -2834,6 +2861,36 @@ codegen(mrc_codegen_scope *s, mrc_node *tree, int val)
28342861
}
28352862
break;
28362863
}
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+
}
28372894
default:
28382895
{
28392896
char buf[256];

0 commit comments

Comments
 (0)