Skip to content
Merged
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
88 changes: 24 additions & 64 deletions include/prism/internal/static_literals.h
Original file line number Diff line number Diff line change
@@ -1,91 +1,51 @@
#ifndef PRISM_INTERNAL_STATIC_LITERALS_H
#define PRISM_INTERNAL_STATIC_LITERALS_H

#include "prism/internal/encoding.h"

#include "prism/ast.h"
#include "prism/buffer.h"
#include "prism/line_offset_list.h"

/*
* An internal hash table for a set of nodes.
*/
typedef struct {
/* The array of nodes in the hash table. */
pm_node_t **nodes;

/* The size of the hash table. */
uint32_t size;

/* The space that has been allocated in the hash table. */
uint32_t capacity;
} pm_node_hash_t;
#include "prism/parser.h"

/*
* Certain sets of nodes (hash keys and when clauses) check for duplicate nodes
* to alert the user of potential issues. To do this, we keep a set of the nodes
* that have been seen so far, and compare whenever we find a new node.
*
* We bucket the nodes based on their type to minimize the number of comparisons
* that need to be performed.
*/
typedef struct {
/*
* This is the set of IntegerNode and SourceLineNode instances.
*/
pm_node_hash_t integer_nodes;
/* The node stored in this slot, or NULL if the slot is empty. */
pm_node_t *node;

/*
* This is the set of FloatNode instances.
*/
pm_node_hash_t float_nodes;
/* The hash of the node, kept so that it is never recomputed. */
uint64_t hash;
} pm_static_literals_entry_t;

/*
* This is the set of RationalNode and ImaginaryNode instances.
*/
pm_node_hash_t number_nodes;

/*
* This is the set of StringNode and SourceFileNode instances.
*/
pm_node_hash_t string_nodes;

/*
* This is the set of RegularExpressionNode instances.
*/
pm_node_hash_t regexp_nodes;
/*
* The number of nodes a set holds directly before it moves them into a hash
* table. Most sets are this small, so they are searched linearly without
* hashing their nodes or allocating any memory.
*/
#define PM_STATIC_LITERALS_INLINE_CAPACITY 4

typedef struct {
/*
* This is the set of SymbolNode instances.
* The nodes in the set while it has no hash table. Once the set outgrows
* this array, its nodes move into the hash table and this is unused.
*/
pm_node_hash_t symbol_nodes;
pm_node_t *nodes[PM_STATIC_LITERALS_INLINE_CAPACITY];

/*
* A pointer to the last TrueNode instance that was inserted, or NULL.
*/
pm_node_t *true_node;
/* The array of entries in the hash table, or NULL if there is none. */
pm_static_literals_entry_t *entries;

/*
* A pointer to the last FalseNode instance that was inserted, or NULL.
*/
pm_node_t *false_node;

/*
* A pointer to the last NilNode instance that was inserted, or NULL.
*/
pm_node_t *nil_node;
/* The number of nodes in the set. */
uint32_t size;

/*
* A pointer to the last SourceEncodingNode instance that was inserted, or
* NULL.
*/
pm_node_t *source_encoding_node;
/* The number of entries allocated in the hash table, or 0 if there is none. */
uint32_t capacity;
} pm_static_literals_t;

/*
* Add a node to the set of static literals.
*/
pm_node_t * pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const pm_encoding_t *encoding, pm_static_literals_t *literals, pm_node_t *node, bool replace);
pm_node_t * pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node, bool replace);

/*
* Free the internal memory associated with the given static literals set.
Expand All @@ -95,6 +55,6 @@ void pm_static_literals_free(pm_static_literals_t *literals);
/*
* Create a string-based representation of the given static literal.
*/
void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const pm_encoding_t *encoding, const pm_node_t *node);
void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node);

#endif
10 changes: 5 additions & 5 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -13890,7 +13890,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) {
static void
pm_hash_key_duplicated_warn(pm_parser_t *parser, const pm_node_t *duplicated, const pm_node_t *node) {
pm_buffer_t buffer = { 0 };
pm_static_literal_inspect(&buffer, &parser->line_offsets, parser->start, parser->start_line, parser->encoding, duplicated);
pm_static_literal_inspect(&buffer, parser, duplicated);

pm_diagnostic_list_append_format(
&parser->metadata_arena,
Expand All @@ -13912,7 +13912,7 @@ pm_hash_key_duplicated_warn(pm_parser_t *parser, const pm_node_t *duplicated, co
*/
static void
pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) {
const pm_node_t *duplicated = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, literals, node, true);
const pm_node_t *duplicated = pm_static_literals_add(parser, literals, node, true);

if (duplicated != NULL) {
pm_hash_key_duplicated_warn(parser, duplicated, node);
Expand All @@ -13936,7 +13936,7 @@ pm_hash_key_static_literals_merge(pm_parser_t *parser, pm_static_literals_t *lit
switch (PM_NODE_TYPE(element)) {
case PM_ASSOC_NODE: {
pm_node_t *key = ((pm_assoc_node_t *) element)->key;
const pm_node_t *duplicated = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, literals, key, true);
const pm_node_t *duplicated = pm_static_literals_add(parser, literals, key, true);

if (duplicated != NULL && PM_NODE_START(duplicated) < boundary) {
pm_hash_key_duplicated_warn(parser, duplicated, key);
Expand Down Expand Up @@ -13967,7 +13967,7 @@ static void
pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) {
pm_node_t *previous;

if ((previous = pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, literals, node, false)) != NULL) {
if ((previous = pm_static_literals_add(parser, literals, node, false)) != NULL) {
pm_diagnostic_list_append_format(
&parser->metadata_arena,
&parser->warning_list,
Expand Down Expand Up @@ -17377,7 +17377,7 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_set_t *cap
*/
static void
parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_t *node) {
if (pm_static_literals_add(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, keys, node, true) != NULL) {
if (pm_static_literals_add(parser, keys, node, true) != NULL) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_KEY_DUPLICATE);
}
}
Expand Down
Loading
Loading