Skip to content

Commit 53bbcfe

Browse files
committed
Fix support for 'it' implicit local variable
1 parent 15e3f8e commit 53bbcfe

File tree

10 files changed

+292
-284
lines changed

10 files changed

+292
-284
lines changed

config.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2570,6 +2570,12 @@ nodes:
25702570
25712571
`foo #{bar} baz`
25722572
^^^^^^^^^^^^^^^^
2573+
- name: ItLocalVariableReadNode
2574+
comment: |
2575+
Represents reading from the implicit `it` local variable.
2576+
2577+
-> { it }
2578+
^^
25732579
- name: ItParametersNode
25742580
comment: |
25752581
Represents an implicit set of parameters through the use of the `it` keyword within a block or lambda.
@@ -2695,10 +2701,6 @@ nodes:
26952701
26962702
_1 # name `:_1`
26972703
2698-
Finally, for the default `it` block parameter, the name is `0it`. This is to distinguish it from an `it` local variable that is explicitly declared.
2699-
2700-
it # name `:0it`
2701-
27022704
- name: depth
27032705
type: uint32
27042706
comment: |

include/prism/parser.h

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,17 @@ typedef struct pm_locals {
546546
pm_local_t *locals;
547547
} pm_locals_t;
548548

549+
/** The flags about scope parameters that can be set. */
550+
typedef uint8_t pm_scope_parameters_t;
551+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NONE = 0x0;
552+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x1;
553+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x2;
554+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x4;
555+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x8;
556+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED = 0x10;
557+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_INNER = 0x20;
558+
static const pm_scope_parameters_t PM_SCOPE_PARAMETERS_NUMBERED_FOUND = 0x40;
559+
549560
/**
550561
* This struct represents a node in a linked list of scopes. Some scopes can see
551562
* into their parent scopes, while others cannot.
@@ -557,10 +568,19 @@ typedef struct pm_scope {
557568
/** The IDs of the locals in the given scope. */
558569
pm_locals_t locals;
559570

571+
/**
572+
* This is a list of the implicit parameters contained within the block.
573+
* These will be processed after the block is parsed to determine the kind
574+
* of parameters node that should be used and to check if any errors need to
575+
* be added.
576+
*/
577+
pm_node_list_t implicit_parameters;
578+
560579
/**
561580
* This is a bitfield that indicates the parameters that are being used in
562-
* this scope. It is a combination of the PM_SCOPE_PARAMS_* constants. There
563-
* are three different kinds of parameters that can be used in a scope:
581+
* this scope. It is a combination of the PM_SCOPE_PARAMETERS_* constants.
582+
* There are three different kinds of parameters that can be used in a
583+
* scope:
564584
*
565585
* - Ordinary parameters (e.g., def foo(bar); end)
566586
* - Numbered parameters (e.g., def foo; _1; end)
@@ -575,15 +595,7 @@ typedef struct pm_scope {
575595
* - def foo(&); end
576596
* - def foo(...); end
577597
*/
578-
uint8_t parameters;
579-
580-
/**
581-
* An integer indicating the number of numbered parameters on this scope.
582-
* This is necessary to determine if child blocks are allowed to use
583-
* numbered parameters, and to pass information to consumers of the AST
584-
* about how many numbered parameters exist.
585-
*/
586-
int8_t numbered_parameters;
598+
pm_scope_parameters_t parameters;
587599

588600
/**
589601
* The current state of constant shareability for this scope. This is
@@ -598,21 +610,6 @@ typedef struct pm_scope {
598610
bool closed;
599611
} pm_scope_t;
600612

601-
static const uint8_t PM_SCOPE_PARAMETERS_NONE = 0x0;
602-
static const uint8_t PM_SCOPE_PARAMETERS_ORDINARY = 0x1;
603-
static const uint8_t PM_SCOPE_PARAMETERS_NUMBERED = 0x2;
604-
static const uint8_t PM_SCOPE_PARAMETERS_IT = 0x4;
605-
static const uint8_t PM_SCOPE_PARAMETERS_TYPE_MASK = 0x7;
606-
607-
static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x8;
608-
static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x10;
609-
static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x20;
610-
static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x40;
611-
612-
static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_INNER = -2;
613-
static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED = -1;
614-
static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_NONE = 0;
615-
616613
/**
617614
* A struct that represents a stack of boolean values.
618615
*/

lib/prism/translation/parser/compiler.rb

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,12 @@ def visit_interpolated_x_string_node(node)
11481148
end
11491149
end
11501150

1151+
# -> { it }
1152+
# ^^
1153+
def visit_it_local_variable_read_node(node)
1154+
builder.ident([:it, srange(node.location)]).updated(:lvar)
1155+
end
1156+
11511157
# -> { it }
11521158
# ^^^^^^^^^
11531159
def visit_it_parameters_node(node)
@@ -1201,14 +1207,7 @@ def visit_lambda_node(node)
12011207
# foo
12021208
# ^^^
12031209
def visit_local_variable_read_node(node)
1204-
name = node.name
1205-
1206-
# This is just a guess. parser doesn't have support for the implicit
1207-
# `it` variable yet, so we'll probably have to visit this once it
1208-
# does.
1209-
name = :it if name == :"0it"
1210-
1211-
builder.ident([name, srange(node.location)]).updated(:lvar)
1210+
builder.ident([node.name, srange(node.location)]).updated(:lvar)
12121211
end
12131212

12141213
# foo = 1

lib/prism/translation/ripper.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,13 @@ def visit_interpolated_x_string_node(node)
22172217
end
22182218
end
22192219

2220+
# -> { it }
2221+
# ^^
2222+
def visit_it_local_variable_read_node(node)
2223+
bounds(node.location)
2224+
on_vcall(on_ident(node.slice))
2225+
end
2226+
22202227
# -> { it }
22212228
# ^^^^^^^^^
22222229
def visit_it_parameters_node(node)
@@ -2312,12 +2319,7 @@ def visit_lambda_node(node)
23122319
# ^^^
23132320
def visit_local_variable_read_node(node)
23142321
bounds(node.location)
2315-
2316-
if node.name == :"0it"
2317-
on_vcall(on_ident(node.slice))
2318-
else
2319-
on_var_ref(on_ident(node.slice))
2320-
end
2322+
on_var_ref(on_ident(node.slice))
23212323
end
23222324

23232325
# foo = 1

lib/prism/translation/ruby_parser.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,12 @@ def visit_interpolated_x_string_node(node)
916916
end
917917
end
918918

919+
# -> { it }
920+
# ^^
921+
def visit_it_local_variable_read_node(node)
922+
s(node, :call, nil, :it)
923+
end
924+
919925
# foo(bar: baz)
920926
# ^^^^^^^^
921927
def visit_keyword_hash_node(node)

0 commit comments

Comments
 (0)