19 static inline uint32_t
20 murmur_scramble(uint32_t value) {
22 value = (value << 15) | (value >> 17);
33 murmur_hash(
const uint8_t *key,
size_t length) {
34 uint32_t hash = 0x9747b28c;
37 for (
size_t index = length >> 2; index; index--) {
38 memcpy(&segment, key,
sizeof(uint32_t));
39 key +=
sizeof(uint32_t);
40 hash ^= murmur_scramble(segment);
41 hash = (hash << 13) | (hash >> 19);
42 hash = hash * 5 + 0xe6546b64;
46 for (
size_t index = length & 3; index; index--) {
48 segment |= key[index - 1];
51 hash ^= murmur_scramble(segment);
52 hash ^= (uint32_t) length;
68 hash = murmur_hash((
const uint8_t *) integer->
values,
sizeof(uint32_t) * integer->
length);
70 hash = murmur_hash((
const uint8_t *) &integer->
value,
sizeof(uint32_t));
74 hash ^= murmur_scramble((uint32_t) 1);
91 return integer_hash(&cast->
value);
96 const int32_t *value = &line_column.
line;
97 return murmur_hash((
const uint8_t *) value,
sizeof(int32_t));
102 return murmur_hash((
const uint8_t *) value,
sizeof(
double));
114 return node_hash(metadata, numeric) ^ murmur_scramble((uint32_t) node->
type);
145 assert(
false &&
"unreachable");
164 if (new_nodes == NULL)
return NULL;
170 uint32_t mask = new_capacity - 1;
173 for (uint32_t index = 0; index < hash->
capacity; index++) {
177 uint32_t index = node_hash(metadata, node) & mask;
178 new_nodes[index] = node;
184 hash->
nodes = new_nodes;
190 uint32_t index = node_hash(metadata, node) & mask;
196 while (hash->
nodes[index] != NULL) {
197 if (compare(metadata, hash->
nodes[index], node) == 0)
break;
198 index = (index + 1) & mask;
206 if (result == NULL) {
208 hash->
nodes[index] = node;
209 }
else if (replace) {
210 hash->
nodes[index] = node;
227 #define PM_NUMERIC_COMPARISON(left, right) ((left < right) ? -1 : (left > right) ? 1 : 0)
237 if (integer->
values)
return integer->
negative ? INT64_MIN : INT64_MAX;
239 int64_t value = (int64_t) integer->
value;
240 return integer->
negative ? -value : value;
245 assert(
false &&
"unreachable");
257 int64_t left_value = pm_int64_value(metadata, left);
258 int64_t right_value = pm_int64_value(metadata, right);
259 return PM_NUMERIC_COMPARISON(left_value, right_value);
274 return PM_NUMERIC_COMPARISON(left_value, right_value);
294 if (result != 0)
return result;
299 return pm_compare_integer_nodes(metadata, left, right);
301 return pm_compare_float_nodes(metadata, left, right);
303 assert(
false &&
"unreachable");
321 assert(
false &&
"unreachable");
331 const pm_string_t *left_string = pm_string_value(left);
332 const pm_string_t *right_string = pm_string_value(right);
345 if (result != 0)
return result;
350 #undef PM_NUMERIC_COMPARISON
360 return pm_node_hash_insert(
363 .newline_list = newline_list,
364 .start_line = start_line,
365 .encoding_name = NULL
369 pm_compare_integer_nodes
372 return pm_node_hash_insert(
375 .newline_list = newline_list,
376 .start_line = start_line,
377 .encoding_name = NULL
381 pm_compare_float_nodes
385 return pm_node_hash_insert(
388 .newline_list = newline_list,
389 .start_line = start_line,
390 .encoding_name = NULL
394 pm_compare_number_nodes
398 return pm_node_hash_insert(
401 .newline_list = newline_list,
402 .start_line = start_line,
403 .encoding_name = NULL
407 pm_compare_string_nodes
410 return pm_node_hash_insert(
413 .newline_list = newline_list,
414 .start_line = start_line,
415 .encoding_name = NULL
419 pm_compare_regular_expression_nodes
422 return pm_node_hash_insert(
425 .newline_list = newline_list,
426 .start_line = start_line,
427 .encoding_name = NULL
431 pm_compare_string_nodes
435 if ((duplicated == NULL) || replace) literals->
true_node = node;
440 if ((duplicated == NULL) || replace) literals->
false_node = node;
445 if ((duplicated == NULL) || replace) literals->
nil_node = node;
476 pm_static_literal_positive_p(
const pm_node_t *node) {
487 assert(
false &&
"unreachable");
509 }
else if (value == 0.0) {
522 size_t index = exponent_index == SIZE_MAX ?
pm_buffer_length(buffer) : exponent_index;
533 pm_static_literal_inspect_node(buffer, metadata, numeric);
598 assert(
false &&
"unreachable");
608 pm_static_literal_inspect_node(
611 .newline_list = newline_list,
612 .start_line = start_line,
613 .encoding_name = encoding_name
@ PM_SOURCE_LINE_NODE
SourceLineNode.
@ PM_RATIONAL_NODE
RationalNode.
@ PM_FALSE_NODE
FalseNode.
@ PM_SOURCE_FILE_NODE
SourceFileNode.
@ PM_SYMBOL_NODE
SymbolNode.
@ PM_REGULAR_EXPRESSION_NODE
RegularExpressionNode.
@ PM_IMAGINARY_NODE
ImaginaryNode.
@ PM_SOURCE_ENCODING_NODE
SourceEncodingNode.
@ PM_FLOAT_NODE
FloatNode.
@ PM_INTEGER_NODE
IntegerNode.
@ PM_STRING_NODE
StringNode.
@ PM_STRING_FLAGS_FORCED_BINARY_ENCODING
internal bytes forced the encoding to binary
@ PM_STRING_FLAGS_FORCED_UTF8_ENCODING
internal bytes forced the encoding to UTF-8
#define PM_NODE_FLAG_P(node, flag)
Return true if the given flag is set on the given node.
#define PM_NODE_TYPE_P(node, type)
Return true if the type of the given node matches the given type.
#define PM_NODE_TYPE(node)
Cast the type to an enum to allow the compiler to provide exhaustiveness checking.
@ PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE
i - ignores the case of characters when matching
@ PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT
n - forces the ASCII-8BIT encoding
@ PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE
m - allows $ to match the end of lines within strings
@ PM_REGULAR_EXPRESSION_FLAGS_EXTENDED
x - ignores whitespace and allows comments in regular expressions
uint16_t pm_node_flags_t
These are the flags embedded in the node struct.
#define xfree
Old name of ruby_xfree.
#define xcalloc
Old name of ruby_xcalloc.
size_t pm_buffer_index(const pm_buffer_t *buffer, char value)
Checks if the buffer includes the given value.
void pm_buffer_append_format(pm_buffer_t *buffer, const char *format,...) PRISM_ATTRIBUTE_FORMAT(2
Append a formatted string to the buffer.
void void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length)
Append a string to the buffer.
PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer)
Return the length of the buffer.
void pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t length, pm_buffer_escaping_t escaping)
Append a slice of source code to the buffer.
void pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value)
Append a single byte to the buffer.
void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t length)
Insert the given string into the buffer at the given index.
int pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right)
Compare two integers.
PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer)
Convert an integer to a decimal string.
pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line)
Returns the line and column of the given offset.
PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string)
Returns the length associated with the string.
PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string)
Returns the start pointer associated with the string.
int pm_string_compare(const pm_string_t *left, const pm_string_t *right)
Compare the underlying lengths and bytes of two strings.
#define PRISM_ATTRIBUTE_UNUSED
GCC will warn if you specify a function or parameter that is unused at runtime.
A set of static literal nodes that can be checked for duplicates.
void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_newline_list_t *newline_list, int32_t start_line, const char *encoding_name, const pm_node_t *node)
Create a string-based representation of the given static literal.
pm_node_t * pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line, pm_static_literals_t *literals, pm_node_t *node, bool replace)
Add a node to the set of static literals.
void pm_static_literals_free(pm_static_literals_t *literals)
Free the internal memory associated with the given static literals set.
A pm_buffer_t is a simple memory buffer that stores data in a contiguous block of memory.
pm_integer_t value
IntegerNode::value.
A structure represents an arbitrary-sized integer.
size_t length
The number of allocated values.
uint32_t value
Embedded value for small integer.
uint32_t * values
List of 32-bit integers.
bool negative
Whether or not the integer is negative.
A line and column in a string.
int32_t line
The line number.
const uint8_t * start
A pointer to the start location of the range in the source.
A list of offsets of newlines in a string.
An internal hash table for a set of nodes.
pm_node_t ** nodes
The array of nodes in the hash table.
uint32_t size
The size of the hash table.
uint32_t capacity
The space that has been allocated in the hash table.
This is the base structure that represents a node in the syntax tree.
pm_node_type_t type
This represents the type of the node.
pm_node_flags_t flags
This represents any flags on the node.
pm_location_t location
This is the location of the node in the source.
pm_node_t base
The embedded base node.
pm_integer_t denominator
RationalNode::denominator.
pm_integer_t numerator
RationalNode::numerator.
pm_node_t base
The embedded base node.
pm_string_t unescaped
RegularExpressionNode::unescaped.
Certain sets of nodes (hash keys and when clauses) check for duplicate nodes to alert the user of pot...
pm_node_hash_t string_nodes
This is the set of StringNode and SourceFileNode instances.
pm_node_t * false_node
A pointer to the last FalseNode instance that was inserted, or NULL.
pm_node_hash_t regexp_nodes
This is the set of RegularExpressionNode instances.
pm_node_t * source_encoding_node
A pointer to the last SourceEncodingNode instance that was inserted, or NULL.
pm_node_t * nil_node
A pointer to the last NilNode instance that was inserted, or NULL.
pm_node_hash_t number_nodes
This is the set of RationalNode and ImaginaryNode instances.
pm_node_t * true_node
A pointer to the last TrueNode instance that was inserted, or NULL.
pm_node_hash_t symbol_nodes
This is the set of SymbolNode instances.
pm_node_hash_t float_nodes
This is the set of FloatNode instances.
pm_node_hash_t integer_nodes
This is the set of IntegerNode and SourceLineNode instances.
A generic string type that can have various ownership semantics.