diff options
-rw-r--r-- | prism/parser.h | 5 | ||||
-rw-r--r-- | prism/prism.c | 35 | ||||
-rw-r--r-- | test/prism/snapshots/for.txt | 12 | ||||
-rw-r--r-- | test/prism/snapshots/whitequark/for.txt | 4 | ||||
-rw-r--r-- | test/prism/snapshots/whitequark/for_mlhs.txt | 4 |
5 files changed, 46 insertions, 14 deletions
diff --git a/prism/parser.h b/prism/parser.h index 0a5ba80819..0553e29819 100644 --- a/prism/parser.h +++ b/prism/parser.h @@ -293,6 +293,11 @@ typedef struct pm_scope { // This is necessary to determine if child blocks are allowed to use // numbered parameters. bool numbered_params; + + // A transparent scope is a scope that cannot have locals set on itself. + // When a local is set on this scope, it will instead be set on the parent + // scope's local table. + bool transparent; } pm_scope_t; // This struct represents the overall parser. It contains a reference to the diff --git a/prism/prism.c b/prism/prism.c index 303ee2e50e..be227e2198 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -4863,7 +4863,8 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) { .previous = parser->current_scope, .closed = closed, .explicit_params = false, - .numbered_params = false + .numbered_params = false, + .transparent = false }; pm_constant_id_list_init(&scope->locals); @@ -4872,6 +4873,25 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) { return true; } +// Allocate and initialize a new scope. Push it onto the scope stack. +static bool +pm_parser_scope_push_transparent(pm_parser_t *parser) { + pm_scope_t *scope = (pm_scope_t *) malloc(sizeof(pm_scope_t)); + if (scope == NULL) return false; + + *scope = (pm_scope_t) { + .previous = parser->current_scope, + .closed = false, + .explicit_params = false, + .numbered_params = false, + .transparent = true + }; + + parser->current_scope = scope; + + return true; +} + // Check if the current scope has a given local variables. static int pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) { @@ -4880,7 +4900,8 @@ pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) { int depth = 0; while (scope != NULL) { - if (pm_constant_id_list_includes(&scope->locals, constant_id)) return depth; + if (!scope->transparent && + pm_constant_id_list_includes(&scope->locals, constant_id)) return depth; if (scope->closed) break; scope = scope->previous; @@ -4893,8 +4914,12 @@ pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) { // Add a constant id to the local table of the current scope. static inline void pm_parser_local_add(pm_parser_t *parser, pm_constant_id_t constant_id) { - if (!pm_constant_id_list_includes(&parser->current_scope->locals, constant_id)) { - pm_constant_id_list_append(&parser->current_scope->locals, constant_id); + pm_scope_t *scope = parser->current_scope; + while (scope && scope->transparent) scope = scope->previous; + + assert(scope != NULL); + if (!pm_constant_id_list_includes(&scope->locals, constant_id)) { + pm_constant_id_list_append(&scope->locals, constant_id); } } @@ -12755,8 +12780,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power) { pm_statements_node_t *statements = NULL; if (!accept1(parser, PM_TOKEN_KEYWORD_END)) { + pm_parser_scope_push_transparent(parser); statements = parse_statements(parser, PM_CONTEXT_FOR); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM); + pm_parser_scope_pop(parser); } return (pm_node_t *) pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous); diff --git a/test/prism/snapshots/for.txt b/test/prism/snapshots/for.txt index a0485a57ff..cfcf3e4d36 100644 --- a/test/prism/snapshots/for.txt +++ b/test/prism/snapshots/for.txt @@ -23,7 +23,7 @@ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (2,0)-(2,1)) │ │ ├── name: :i - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── for_keyword_loc: (1,0)-(1,3) = "for" │ ├── in_keyword_loc: (1,6)-(1,8) = "in" │ ├── do_keyword_loc: ∅ @@ -48,7 +48,7 @@ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (5,16)-(5,17)) │ │ ├── name: :i - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── for_keyword_loc: (5,0)-(5,3) = "for" │ ├── in_keyword_loc: (5,6)-(5,8) = "in" │ ├── do_keyword_loc: ∅ @@ -80,7 +80,7 @@ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (8,0)-(8,1)) │ │ ├── name: :i - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── for_keyword_loc: (7,0)-(7,3) = "for" │ ├── in_keyword_loc: (7,8)-(7,10) = "in" │ ├── do_keyword_loc: ∅ @@ -115,7 +115,7 @@ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (12,0)-(12,1)) │ │ ├── name: :i - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── for_keyword_loc: (11,0)-(11,3) = "for" │ ├── in_keyword_loc: (11,10)-(11,12) = "in" │ ├── do_keyword_loc: ∅ @@ -140,7 +140,7 @@ │ │ └── body: (length: 1) │ │ └── @ LocalVariableReadNode (location: (16,0)-(16,1)) │ │ ├── name: :i - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── for_keyword_loc: (15,0)-(15,3) = "for" │ ├── in_keyword_loc: (15,6)-(15,8) = "in" │ ├── do_keyword_loc: (15,15)-(15,17) = "do" @@ -165,7 +165,7 @@ │ └── body: (length: 1) │ └── @ LocalVariableReadNode (location: (19,16)-(19,17)) │ ├── name: :i - │ └── depth: 0 + │ └── depth: 1 ├── for_keyword_loc: (19,0)-(19,3) = "for" ├── in_keyword_loc: (19,6)-(19,8) = "in" ├── do_keyword_loc: ∅ diff --git a/test/prism/snapshots/whitequark/for.txt b/test/prism/snapshots/whitequark/for.txt index d4d4dc1602..1006da9272 100644 --- a/test/prism/snapshots/whitequark/for.txt +++ b/test/prism/snapshots/whitequark/for.txt @@ -32,7 +32,7 @@ │ │ │ └── arguments: (length: 1) │ │ │ └── @ LocalVariableReadNode (location: (1,18)-(1,19)) │ │ │ ├── name: :a - │ │ │ └── depth: 0 + │ │ │ └── depth: 1 │ │ ├── closing_loc: ∅ │ │ ├── block: ∅ │ │ ├── flags: ∅ @@ -70,7 +70,7 @@ │ │ └── arguments: (length: 1) │ │ └── @ LocalVariableReadNode (location: (3,16)-(3,17)) │ │ ├── name: :a - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ diff --git a/test/prism/snapshots/whitequark/for_mlhs.txt b/test/prism/snapshots/whitequark/for_mlhs.txt index ef15199a80..93b0eb3297 100644 --- a/test/prism/snapshots/whitequark/for_mlhs.txt +++ b/test/prism/snapshots/whitequark/for_mlhs.txt @@ -39,10 +39,10 @@ │ │ └── arguments: (length: 2) │ │ ├── @ LocalVariableReadNode (location: (1,19)-(1,20)) │ │ │ ├── name: :a - │ │ │ └── depth: 0 + │ │ │ └── depth: 1 │ │ └── @ LocalVariableReadNode (location: (1,22)-(1,23)) │ │ ├── name: :b - │ │ └── depth: 0 + │ │ └── depth: 1 │ ├── closing_loc: ∅ │ ├── block: ∅ │ ├── flags: ∅ |