diff options
Diffstat (limited to 'prism_compile.c')
-rw-r--r-- | prism_compile.c | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/prism_compile.c b/prism_compile.c index 3aeb9d0e8e..08e2c4cc85 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3443,19 +3443,83 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_c dtype = DEFINED_FALSE; break; case PM_ARRAY_NODE: { - const pm_array_node_t *cast = (const pm_array_node_t *) node; + const pm_array_node_t *cast = (const pm_array_node_t *) node; - if (!PM_NODE_FLAG_P(cast, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT)) { - for (size_t index = 0; index < cast->elements.size; index++) { - pm_compile_defined_expr0(iseq, cast->elements.nodes[index], node_location, ret, popped, scope_node, true, lfinish, false); + if (cast->elements.size > 0 && !lfinish[1]) { + lfinish[1] = NEW_LABEL(location.line); + } - if (!lfinish[1]) { - lfinish[1] = NEW_LABEL(location.line); - } + for (size_t index = 0; index < cast->elements.size; index++) { + pm_compile_defined_expr0(iseq, cast->elements.nodes[index], node_location, ret, popped, scope_node, true, lfinish, false); + PUSH_INSNL(ret, location, branchunless, lfinish[1]); + } + + dtype = DEFINED_EXPR; + break; + } + case PM_HASH_NODE: + case PM_KEYWORD_HASH_NODE: { + const pm_node_list_t *elements; + + if (PM_NODE_TYPE_P(node, PM_HASH_NODE)) { + elements = &((const pm_hash_node_t *) node)->elements; + } + else { + elements = &((const pm_keyword_hash_node_t *) node)->elements; + } + + if (elements->size > 0 && !lfinish[1]) { + lfinish[1] = NEW_LABEL(location.line); + } + + for (size_t index = 0; index < elements->size; index++) { + const pm_node_t *element = elements->nodes[index]; - PUSH_INSNL(ret, location, branchunless, lfinish[1]); + switch (PM_NODE_TYPE(element)) { + case PM_ASSOC_NODE: { + const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element; + + pm_compile_defined_expr0(iseq, assoc->key, node_location, ret, popped, scope_node, true, lfinish, false); + PUSH_INSNL(ret, location, branchunless, lfinish[1]); + + pm_compile_defined_expr0(iseq, assoc->value, node_location, ret, popped, scope_node, true, lfinish, false); + PUSH_INSNL(ret, location, branchunless, lfinish[1]); + + break; } - } + case PM_ASSOC_SPLAT_NODE: { + const pm_assoc_splat_node_t *assoc_splat = (const pm_assoc_splat_node_t *) element; + + pm_compile_defined_expr0(iseq, assoc_splat->value, node_location, ret, popped, scope_node, true, lfinish, false); + PUSH_INSNL(ret, location, branchunless, lfinish[1]); + + break; + } + default: + rb_bug("unexpected node type in hash node: %s", pm_node_type_to_str(PM_NODE_TYPE(element))); + break; + } + } + + dtype = DEFINED_EXPR; + break; + } + case PM_SPLAT_NODE: { + const pm_splat_node_t *cast = (const pm_splat_node_t *) node; + pm_compile_defined_expr0(iseq, cast->expression, node_location, ret, popped, scope_node, in_condition, lfinish, false); + + if (!lfinish[1]) { + lfinish[1] = NEW_LABEL(location.line); + } + + PUSH_INSNL(ret, location, branchunless, lfinish[1]); + dtype = DEFINED_EXPR; + break; + } + case PM_IMPLICIT_NODE: { + const pm_implicit_node_t *cast = (const pm_implicit_node_t *) node; + pm_compile_defined_expr0(iseq, cast->value, node_location, ret, popped, scope_node, in_condition, lfinish, explicit_receiver); + return; } case PM_AND_NODE: case PM_BEGIN_NODE: @@ -3467,7 +3531,6 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_c case PM_DEFINED_NODE: case PM_FLOAT_NODE: case PM_FOR_NODE: - case PM_HASH_NODE: case PM_IF_NODE: case PM_IMAGINARY_NODE: case PM_INTEGER_NODE: @@ -3475,7 +3538,6 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_c case PM_INTERPOLATED_STRING_NODE: case PM_INTERPOLATED_SYMBOL_NODE: case PM_INTERPOLATED_X_STRING_NODE: - case PM_KEYWORD_HASH_NODE: case PM_LAMBDA_NODE: case PM_MATCH_PREDICATE_NODE: case PM_MATCH_REQUIRED_NODE: |