Skip to content

Commit 79d83eb

Browse files
committed
Refactor around pm_parser_scope_find
1 parent c739f8e commit 79d83eb

File tree

1 file changed

+121
-116
lines changed

1 file changed

+121
-116
lines changed

src/prism.c

Lines changed: 121 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,122 @@ pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id
672672
#define PM_PARSER_WARN_NODE_FORMAT(parser, node, diag_id, ...) \
673673
PM_PARSER_WARN_FORMAT(parser, (node)->location.start, (node)->location.end, diag_id, __VA_ARGS__)
674674

675+
/******************************************************************************/
676+
/* Scope-related functions */
677+
/******************************************************************************/
678+
679+
/**
680+
* Allocate and initialize a new scope. Push it onto the scope stack.
681+
*/
682+
static bool
683+
pm_parser_scope_push(pm_parser_t *parser, bool closed) {
684+
pm_scope_t *scope = (pm_scope_t *) xmalloc(sizeof(pm_scope_t));
685+
if (scope == NULL) return false;
686+
687+
*scope = (pm_scope_t) {
688+
.previous = parser->current_scope,
689+
.locals = { 0 },
690+
.parameters = PM_SCOPE_PARAMETERS_NONE,
691+
.numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_NONE,
692+
.shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
693+
.closed = closed
694+
};
695+
696+
parser->current_scope = scope;
697+
return true;
698+
}
699+
700+
/**
701+
* Determine if the current scope is at the top level. This means it is either
702+
* the top-level scope or it is open to the top-level.
703+
*/
704+
static bool
705+
pm_parser_scope_toplevel_p(pm_parser_t *parser) {
706+
pm_scope_t *scope = parser->current_scope;
707+
708+
do {
709+
if (scope->previous == NULL) return true;
710+
if (scope->closed) return false;
711+
} while ((scope = scope->previous) != NULL);
712+
713+
assert(false && "unreachable");
714+
return true;
715+
}
716+
717+
/**
718+
* Retrieve the scope at the given depth.
719+
*/
720+
static pm_scope_t *
721+
pm_parser_scope_find(pm_parser_t *parser, uint32_t depth) {
722+
pm_scope_t *scope = parser->current_scope;
723+
724+
while (depth-- > 0) {
725+
assert(scope != NULL);
726+
scope = scope->previous;
727+
}
728+
729+
return scope;
730+
}
731+
732+
static void
733+
pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag) {
734+
pm_scope_t *scope = parser->current_scope;
735+
while (scope) {
736+
if (scope->parameters & mask) {
737+
if (!scope->closed) {
738+
pm_parser_err_token(parser, token, diag);
739+
return;
740+
}
741+
return;
742+
}
743+
if (scope->closed) break;
744+
scope = scope->previous;
745+
}
746+
747+
pm_parser_err_token(parser, token, diag);
748+
}
749+
750+
static inline void
751+
pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token) {
752+
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
753+
}
754+
755+
static inline void
756+
pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token) {
757+
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
758+
}
759+
760+
static inline void
761+
pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token) {
762+
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
763+
}
764+
765+
static inline void
766+
pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token) {
767+
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR);
768+
}
769+
770+
/**
771+
* Get the current state of constant shareability.
772+
*/
773+
static inline pm_shareable_constant_value_t
774+
pm_parser_scope_shareable_constant_get(pm_parser_t *parser) {
775+
return parser->current_scope->shareable_constant;
776+
}
777+
778+
/**
779+
* Set the current state of constant shareability. We'll set it on all of the
780+
* open scopes so that reads are quick.
781+
*/
782+
static void
783+
pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constant_value_t shareable_constant) {
784+
pm_scope_t *scope = parser->current_scope;
785+
786+
do {
787+
scope->shareable_constant = shareable_constant;
788+
} while (!scope->closed && (scope = scope->previous) != NULL);
789+
}
790+
675791
/******************************************************************************/
676792
/* Local variable-related functions */
677793
/******************************************************************************/
@@ -5108,11 +5224,7 @@ pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, c
51085224
*/
51095225
static pm_local_variable_read_node_t *
51105226
pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth, bool missing) {
5111-
if (!missing) {
5112-
pm_scope_t *scope = parser->current_scope;
5113-
for (uint32_t index = 0; index < depth; index++) scope = scope->previous;
5114-
pm_locals_read(&scope->locals, name_id);
5115-
}
5227+
if (!missing) pm_locals_read(&pm_parser_scope_find(parser, depth)->locals, name_id);
51165228

51175229
pm_local_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_read_node_t);
51185230

@@ -7181,107 +7293,6 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo
71817293

71827294
#undef PM_ALLOC_NODE
71837295

7184-
/******************************************************************************/
7185-
/* Scope-related functions */
7186-
/******************************************************************************/
7187-
7188-
/**
7189-
* Allocate and initialize a new scope. Push it onto the scope stack.
7190-
*/
7191-
static bool
7192-
pm_parser_scope_push(pm_parser_t *parser, bool closed) {
7193-
pm_scope_t *scope = (pm_scope_t *) xmalloc(sizeof(pm_scope_t));
7194-
if (scope == NULL) return false;
7195-
7196-
*scope = (pm_scope_t) {
7197-
.previous = parser->current_scope,
7198-
.locals = { 0 },
7199-
.parameters = PM_SCOPE_PARAMETERS_NONE,
7200-
.numbered_parameters = PM_SCOPE_NUMBERED_PARAMETERS_NONE,
7201-
.shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
7202-
.closed = closed
7203-
};
7204-
7205-
parser->current_scope = scope;
7206-
return true;
7207-
}
7208-
7209-
/**
7210-
* Determine if the current scope is at the top level. This means it is either
7211-
* the top-level scope or it is open to the top-level.
7212-
*/
7213-
static bool
7214-
pm_parser_scope_toplevel_p(pm_parser_t *parser) {
7215-
pm_scope_t *scope = parser->current_scope;
7216-
7217-
do {
7218-
if (scope->previous == NULL) return true;
7219-
if (scope->closed) return false;
7220-
} while ((scope = scope->previous) != NULL);
7221-
7222-
assert(false && "unreachable");
7223-
return true;
7224-
}
7225-
7226-
static void
7227-
pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag) {
7228-
pm_scope_t *scope = parser->current_scope;
7229-
while (scope) {
7230-
if (scope->parameters & mask) {
7231-
if (!scope->closed) {
7232-
pm_parser_err_token(parser, token, diag);
7233-
return;
7234-
}
7235-
return;
7236-
}
7237-
if (scope->closed) break;
7238-
scope = scope->previous;
7239-
}
7240-
7241-
pm_parser_err_token(parser, token, diag);
7242-
}
7243-
7244-
static inline void
7245-
pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token) {
7246-
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP);
7247-
}
7248-
7249-
static inline void
7250-
pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token) {
7251-
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR);
7252-
}
7253-
7254-
static inline void
7255-
pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token) {
7256-
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
7257-
}
7258-
7259-
static inline void
7260-
pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token) {
7261-
pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR);
7262-
}
7263-
7264-
/**
7265-
* Get the current state of constant shareability.
7266-
*/
7267-
static inline pm_shareable_constant_value_t
7268-
pm_parser_scope_shareable_constant_get(pm_parser_t *parser) {
7269-
return parser->current_scope->shareable_constant;
7270-
}
7271-
7272-
/**
7273-
* Set the current state of constant shareability. We'll set it on all of the
7274-
* open scopes so that reads are quick.
7275-
*/
7276-
static void
7277-
pm_parser_scope_shareable_constant_set(pm_parser_t *parser, pm_shareable_constant_value_t shareable_constant) {
7278-
pm_scope_t *scope = parser->current_scope;
7279-
7280-
do {
7281-
scope->shareable_constant = shareable_constant;
7282-
} while (!scope->closed && (scope = scope->previous) != NULL);
7283-
}
7284-
72857296
/**
72867297
* Check if any of the currently visible scopes contain a local variable
72877298
* described by the given constant id.
@@ -12470,10 +12481,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target) {
1247012481
const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) target;
1247112482
uint32_t name = cast->name;
1247212483
uint32_t depth = cast->depth;
12473-
12474-
pm_scope_t *scope = parser->current_scope;
12475-
for (uint32_t index = 0; index < depth; index++) scope = scope->previous;
12476-
pm_locals_unread(&scope->locals, name);
12484+
pm_locals_unread(&pm_parser_scope_find(parser, depth)->locals, name);
1247712485

1247812486
assert(sizeof(pm_local_variable_target_node_t) == sizeof(pm_local_variable_read_node_t));
1247912487
target->type = PM_LOCAL_VARIABLE_TARGET_NODE;
@@ -12624,17 +12632,14 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
1262412632
pm_refute_numbered_parameter(parser, target->location.start, target->location.end);
1262512633
pm_local_variable_read_node_t *local_read = (pm_local_variable_read_node_t *) target;
1262612634

12627-
pm_constant_id_t constant_id = local_read->name;
12635+
pm_constant_id_t name = local_read->name;
1262812636
uint32_t depth = local_read->depth;
12629-
12630-
pm_scope_t *scope = parser->current_scope;
12631-
for (uint32_t index = 0; index < depth; index++) scope = scope->previous;
12632-
pm_locals_unread(&scope->locals, constant_id);
12637+
pm_locals_unread(&pm_parser_scope_find(parser, depth)->locals, name);
1263312638

1263412639
pm_location_t name_loc = target->location;
1263512640
pm_node_destroy(parser, target);
1263612641

12637-
return (pm_node_t *) pm_local_variable_write_node_create(parser, constant_id, depth, value, &name_loc, operator);
12642+
return (pm_node_t *) pm_local_variable_write_node_create(parser, name, depth, value, &name_loc, operator);
1263812643
}
1263912644
case PM_INSTANCE_VARIABLE_READ_NODE: {
1264012645
pm_node_t *write_node = (pm_node_t *) pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value);

0 commit comments

Comments
 (0)