Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 52 additions & 29 deletions include/prism/internal/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMEN

/*
* This tracks an individual local variable in a certain lexical context, as
* well as the number of times is it read.
* well as the number of times is it read. The locals of every live scope are
* kept on a single stack on the parser, since a local is only ever declared in
* the innermost scope and is discarded when that scope is popped.
*/
typedef struct {
/* The name of the local variable. */
Expand All @@ -480,38 +482,19 @@ typedef struct {
/* The location of the local variable in the source. */
pm_location_t location;

/* The index of the local variable in the local table. */
uint32_t index;

/* The number of times the local variable is read. */
uint32_t reads;

/* The hash of the local variable. */
uint32_t hash;
} pm_local_t;

/*
* This is a set of local variables in a certain lexical context (method, class,
* module, etc.). We need to track how many times these variables are read in
* order to warn if they only get written.
*/
typedef struct pm_locals {
/* The number of local variables in the set. */
uint32_t size;

/* The capacity of the local variables set. */
uint32_t capacity;
/* The level of the scope that declares the local variable. */
uint32_t level;

/*
* A bloom filter over constant IDs stored in this set. Used to quickly
* reject lookups for names that are definitely not present, avoiding the
* cost of a linear scan or hash probe.
* The index in the locals stack of the local with the same name that this
* local hides while its scope is live, or 0 if it hides nothing. It is
* restored as the binding of the name when the scope is popped.
*/
uint32_t bloom;

/* The nullable allocated memory for the local variables in the set. */
pm_local_t *locals;
} pm_locals_t;
uint32_t shadowed;
} pm_local_t;

/* The flags about scope parameters that can be set. */
typedef uint8_t pm_scope_parameters_t;
Expand All @@ -532,8 +515,24 @@ typedef struct pm_scope {
/* A pointer to the previous scope in the linked list. */
struct pm_scope *previous;

/* The IDs of the locals in the given scope. */
pm_locals_t locals;
/*
* The index in the locals stack of the first local of this scope. The
* locals of this scope run from here to the top of the stack.
*/
uint32_t locals_start;

/*
* The position of this scope in the scope stack, where the outermost scope
* is at level 1.
*/
uint32_t level;

/*
* The locals_start of the nearest closed scope at or above this one. Every
* local below this index in the locals stack belongs to a scope that this
* scope cannot see into.
*/
uint32_t floor;

/*
* This is a list of the implicit parameters contained within the block.
Expand Down Expand Up @@ -735,6 +734,30 @@ struct pm_parser_t {
/* The current local scope. */
pm_scope_t *current_scope;

/*
* The locals of every live scope, in the order they were declared. Index 0
* is never used, so that 0 can mean the absence of a local.
*/
pm_local_t *locals;

/* The number of slots in use in locals, including the unused slot 0. */
uint32_t locals_size;

/* The number of slots allocated in locals. */
uint32_t locals_capacity;

/*
* The index in the locals stack of the innermost live local with each
* constant id as its name, or 0 if there is none. A local that is declared
* in a scope replaces the binding of its name, and the binding it replaced
* is restored when the scope is popped. Constant ids at or beyond the
* capacity have never been declared as locals, so they are unbound.
*/
uint32_t *bindings;

/* The number of slots allocated in bindings. */
uint32_t bindings_capacity;

/*
* Scopes that have been popped, kept for reuse by the next push. Scopes
* are allocated from the scratch arena, so they are never freed
Expand Down
2 changes: 1 addition & 1 deletion src/constant_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pm_constant_id_set_insert(pm_arena_t *arena, pm_constant_id_set_t *set, pm_const
assert(id != PM_CONSTANT_ID_UNSET);

/*
* Grow at the same load factor the locals table and the constant pool use.
* Grow at the same load factor the constant pool uses.
* An empty set has no slots at all, so this also builds the first table.
*/
if (set->size >= (set->capacity / 4 * 3)) {
Expand Down
Loading
Loading