diff options
| author | Jemma Issroff <jemmaissroff@gmail.com> | 2023-12-13 16:41:45 -0500 |
|---|---|---|
| committer | Jemma Issroff <jemmaissroff@gmail.com> | 2023-12-14 11:46:54 -0500 |
| commit | e71f0117137c30db1dd694aa2c91c82174fa05df (patch) | |
| tree | bcddb48a50fe4b059ec15491a7ea531307dd6b35 | |
| parent | 3658798dbb60fe55beaebc157ba43c8fe617c4a0 (diff) | |
[PRISM] Fix bugs in compiling optional keyword parameters
This PR fixes two bugs when compiling optional keyword parameters:
- It moves keyword parameter compilation to STEP 5 in the parameters
sequence, where the rest of compilation happens. This is important
because keyword parameter compilation relies on the value of
body->param.keyword->bits_start which gets set in an earlier step
- It compiles array and hash values for keyword parameters, which
it didn't previously
| -rw-r--r-- | prism_compile.c | 79 | ||||
| -rw-r--r-- | test/ruby/test_compile_prism.rb | 6 |
2 files changed, 71 insertions, 14 deletions
diff --git a/prism_compile.c b/prism_compile.c index 79fff9642f..3a746d3023 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -4692,21 +4692,21 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_node_t *value = cast->value; name = cast->name; - if (pm_static_literal_p(value)) { - rb_ary_push(default_values, pm_static_literal_value(value, scope_node, parser)); - } - else { - LABEL *end_label = NEW_LABEL(nd_line(&dummy_line_node)); - - int index = pm_lookup_local_index(iseq, scope_node, name); - int kw_bits_idx = table_size - body->param.keyword->bits_start; - ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i - 1)); - ADD_INSNL(ret, &dummy_line_node, branchif, end_label); - PM_COMPILE(value); - ADD_SETLOCAL(ret, &dummy_line_node, index, 0); - - ADD_LABEL(ret, end_label); + switch PM_NODE_TYPE(value) { + case PM_FALSE_NODE: + case PM_FLOAT_NODE: + case PM_INTEGER_NODE: + case PM_IMAGINARY_NODE: + case PM_NIL_NODE: + case PM_RATIONAL_NODE: + case PM_STRING_NODE: + case PM_SYMBOL_NODE: + case PM_TRUE_NODE: + rb_ary_push(default_values, pm_static_literal_value(value, scope_node, parser)); + break; + default: { rb_ary_push(default_values, complex_mark); + } } break; @@ -4932,6 +4932,57 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, //********STEP 5************ // Goal: compile anything that needed to be compiled + if (keywords_list && keywords_list->size) { + for (size_t i = 0; i < keywords_list->size; i++, local_index++) { + pm_node_t *keyword_parameter_node = keywords_list->nodes[i]; + pm_constant_id_t name; + + switch (PM_NODE_TYPE(keyword_parameter_node)) { + // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) + // ^^^^ + case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: { + pm_optional_keyword_parameter_node_t *cast = ((pm_optional_keyword_parameter_node_t *)keyword_parameter_node); + + pm_node_t *value = cast->value; + name = cast->name; + + switch PM_NODE_TYPE(value) { + case PM_FALSE_NODE: + case PM_FLOAT_NODE: + case PM_INTEGER_NODE: + case PM_IMAGINARY_NODE: + case PM_NIL_NODE: + case PM_RATIONAL_NODE: + case PM_STRING_NODE: + case PM_SYMBOL_NODE: + case PM_TRUE_NODE: + break; + default: { + LABEL *end_label = NEW_LABEL(nd_line(&dummy_line_node)); + + int index = pm_lookup_local_index(iseq, scope_node, name); + int kw_bits_idx = table_size - body->param.keyword->bits_start; + ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i)); + ADD_INSNL(ret, &dummy_line_node, branchif, end_label); + PM_COMPILE(value); + ADD_SETLOCAL(ret, &dummy_line_node, index, 0); + + ADD_LABEL(ret, end_label); + } + } + } + // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) + // ^^ + case PM_REQUIRED_KEYWORD_PARAMETER_NODE: { + break; + } + default: { + rb_bug("Unexpected keyword parameter node type"); + } + } + } + } + if (optionals_list && optionals_list->size) { LABEL **opt_table = (LABEL **)ALLOC_N(VALUE, optionals_list->size + 1); LABEL *label; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7bd63eb611..f89aabfc0e 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1178,6 +1178,12 @@ module Prism end prism_test_def_node(10, b: 3) CODE + assert_prism_eval(<<-CODE) + def self.prism_test_def_node(a: []) + a + end + prism_test_def_node + CODE # block arguments assert_prism_eval("def self.prism_test_def_node(&block) block end; prism_test_def_node{}.class") |
