11#include "prism/static_literals.h"
22
3+ /**
4+ * A small struct used for passing around a subset of the information that is
5+ * stored on the parser. We use this to avoid having static literals explicitly
6+ * depend on the parser struct.
7+ */
8+ typedef struct {
9+ /** The list of newline offsets to use to calculate line numbers. */
10+ const pm_newline_list_t * newline_list ;
11+
12+ /** The line number that the parser starts on. */
13+ int32_t start_line ;
14+
15+ /** The name of the encoding that the parser is using. */
16+ const char * encoding_name ;
17+ } pm_static_literals_metadata_t ;
18+
319static inline uint32_t
420murmur_scramble (uint32_t value ) {
521 value *= 0xcc9e2d51 ;
@@ -48,7 +64,7 @@ murmur_hash(const uint8_t *key, size_t length) {
4864 * these hashes to look for duplicates.
4965 */
5066static uint32_t
51- node_hash (const pm_parser_t * parser , const pm_node_t * node ) {
67+ node_hash (const pm_static_literals_metadata_t * metadata , const pm_node_t * node ) {
5268 switch (PM_NODE_TYPE (node )) {
5369 case PM_INTEGER_NODE : {
5470 // Integers hash their value.
@@ -68,7 +84,7 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) {
6884 }
6985 case PM_SOURCE_LINE_NODE : {
7086 // Source lines hash their line number.
71- const pm_line_column_t line_column = pm_newline_list_line_column (& parser -> newline_list , node -> location .start , parser -> start_line );
87+ const pm_line_column_t line_column = pm_newline_list_line_column (metadata -> newline_list , node -> location .start , metadata -> start_line );
7288 const int32_t * value = & line_column .line ;
7389 return murmur_hash ((const uint8_t * ) value , sizeof (int32_t ));
7490 }
@@ -82,14 +98,14 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) {
8298 // is stored as a subnode, we hash that node and then mix in the
8399 // fact that this is a rational node.
84100 const pm_node_t * numeric = ((const pm_rational_node_t * ) node )-> numeric ;
85- return node_hash (parser , numeric ) ^ murmur_scramble ((uint32_t ) node -> type );
101+ return node_hash (metadata , numeric ) ^ murmur_scramble ((uint32_t ) node -> type );
86102 }
87103 case PM_IMAGINARY_NODE : {
88104 // Imaginaries hash their numeric value. Because their numeric value
89105 // is stored as a subnode, we hash that node and then mix in the
90106 // fact that this is an imaginary node.
91107 const pm_node_t * numeric = ((const pm_imaginary_node_t * ) node )-> numeric ;
92- return node_hash (parser , numeric ) ^ murmur_scramble ((uint32_t ) node -> type );
108+ return node_hash (metadata , numeric ) ^ murmur_scramble ((uint32_t ) node -> type );
93109 }
94110 case PM_STRING_NODE : {
95111 // Strings hash their value and mix in their flags so that different
@@ -132,7 +148,7 @@ node_hash(const pm_parser_t *parser, const pm_node_t *node) {
132148 * and must be able to compare all node types that will be stored in this hash.
133149 */
134150static pm_node_t *
135- pm_node_hash_insert (pm_node_hash_t * hash , const pm_parser_t * parser , pm_node_t * node , int (* compare )(const pm_parser_t * parser , const pm_node_t * left , const pm_node_t * right )) {
151+ pm_node_hash_insert (pm_node_hash_t * hash , const pm_static_literals_metadata_t * metadata , pm_node_t * node , int (* compare )(const pm_static_literals_metadata_t * metadata , const pm_node_t * left , const pm_node_t * right )) {
136152 // If we are out of space, we need to resize the hash. This will cause all
137153 // of the nodes to be rehashed and reinserted into the new hash.
138154 if (hash -> size * 2 >= hash -> capacity ) {
@@ -152,7 +168,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_parser_t *parser, pm_node_t *
152168 pm_node_t * node = hash -> nodes [index ];
153169
154170 if (node != NULL ) {
155- uint32_t index = node_hash (parser , node ) & mask ;
171+ uint32_t index = node_hash (metadata , node ) & mask ;
156172 new_nodes [index ] = node ;
157173 }
158174 }
@@ -165,14 +181,14 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_parser_t *parser, pm_node_t *
165181
166182 // Now, insert the node into the hash.
167183 uint32_t mask = hash -> capacity - 1 ;
168- uint32_t index = node_hash (parser , node ) & mask ;
184+ uint32_t index = node_hash (metadata , node ) & mask ;
169185
170186 // We use linear probing to resolve collisions. This means that if the
171187 // current index is occupied, we will move to the next index and try again.
172188 // We are guaranteed that this will eventually find an empty slot because we
173189 // resize the hash when it gets too full.
174190 while (hash -> nodes [index ] != NULL ) {
175- if (compare (parser , hash -> nodes [index ], node ) == 0 ) break ;
191+ if (compare (metadata , hash -> nodes [index ], node ) == 0 ) break ;
176192 index = (index + 1 ) & mask ;
177193 }
178194
@@ -203,7 +219,7 @@ pm_node_hash_free(pm_node_hash_t *hash) {
203219 * Return the integer value of the given node as an int64_t.
204220 */
205221static int64_t
206- pm_int64_value (const pm_parser_t * parser , const pm_node_t * node ) {
222+ pm_int64_value (const pm_static_literals_metadata_t * metadata , const pm_node_t * node ) {
207223 switch (PM_NODE_TYPE (node )) {
208224 case PM_INTEGER_NODE : {
209225 const pm_integer_t * integer = & ((const pm_integer_node_t * ) node )-> value ;
@@ -213,7 +229,7 @@ pm_int64_value(const pm_parser_t *parser, const pm_node_t *node) {
213229 return integer -> negative ? - value : value ;
214230 }
215231 case PM_SOURCE_LINE_NODE :
216- return (int64_t ) pm_newline_list_line_column (& parser -> newline_list , node -> location .start , parser -> start_line ).line ;
232+ return (int64_t ) pm_newline_list_line_column (metadata -> newline_list , node -> location .start , metadata -> start_line ).line ;
217233 default :
218234 assert (false && "unreachable" );
219235 return 0 ;
@@ -225,10 +241,10 @@ pm_int64_value(const pm_parser_t *parser, const pm_node_t *node) {
225241 * instances.
226242 */
227243static int
228- pm_compare_integer_nodes (const pm_parser_t * parser , const pm_node_t * left , const pm_node_t * right ) {
244+ pm_compare_integer_nodes (const pm_static_literals_metadata_t * metadata , const pm_node_t * left , const pm_node_t * right ) {
229245 if (PM_NODE_TYPE_P (left , PM_SOURCE_LINE_NODE ) || PM_NODE_TYPE_P (right , PM_SOURCE_LINE_NODE )) {
230- int64_t left_value = pm_int64_value (parser , left );
231- int64_t right_value = pm_int64_value (parser , right );
246+ int64_t left_value = pm_int64_value (metadata , left );
247+ int64_t right_value = pm_int64_value (metadata , right );
232248 return PM_NUMERIC_COMPARISON (left_value , right_value );
233249 }
234250
@@ -241,7 +257,7 @@ pm_compare_integer_nodes(const pm_parser_t *parser, const pm_node_t *left, const
241257 * A comparison function for comparing two FloatNode instances.
242258 */
243259static int
244- pm_compare_float_nodes (PRISM_ATTRIBUTE_UNUSED const pm_parser_t * parser , const pm_node_t * left , const pm_node_t * right ) {
260+ pm_compare_float_nodes (PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t * metadata , const pm_node_t * left , const pm_node_t * right ) {
245261 const double left_value = ((const pm_float_node_t * ) left )-> value ;
246262 const double right_value = ((const pm_float_node_t * ) right )-> value ;
247263 return PM_NUMERIC_COMPARISON (left_value , right_value );
@@ -251,20 +267,20 @@ pm_compare_float_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const p
251267 * A comparison function for comparing two nodes that have attached numbers.
252268 */
253269static int
254- pm_compare_number_nodes (const pm_parser_t * parser , const pm_node_t * left , const pm_node_t * right ) {
270+ pm_compare_number_nodes (const pm_static_literals_metadata_t * metadata , const pm_node_t * left , const pm_node_t * right ) {
255271 if (PM_NODE_TYPE (left ) != PM_NODE_TYPE (right )) {
256272 return PM_NUMERIC_COMPARISON (PM_NODE_TYPE (left ), PM_NODE_TYPE (right ));
257273 }
258274
259275 switch (PM_NODE_TYPE (left )) {
260276 case PM_IMAGINARY_NODE :
261- return pm_compare_number_nodes (parser , ((const pm_imaginary_node_t * ) left )-> numeric , ((const pm_imaginary_node_t * ) right )-> numeric );
277+ return pm_compare_number_nodes (metadata , ((const pm_imaginary_node_t * ) left )-> numeric , ((const pm_imaginary_node_t * ) right )-> numeric );
262278 case PM_RATIONAL_NODE :
263- return pm_compare_number_nodes (parser , ((const pm_rational_node_t * ) left )-> numeric , ((const pm_rational_node_t * ) right )-> numeric );
279+ return pm_compare_number_nodes (metadata , ((const pm_rational_node_t * ) left )-> numeric , ((const pm_rational_node_t * ) right )-> numeric );
264280 case PM_INTEGER_NODE :
265- return pm_compare_integer_nodes (parser , left , right );
281+ return pm_compare_integer_nodes (metadata , left , right );
266282 case PM_FLOAT_NODE :
267- return pm_compare_float_nodes (parser , left , right );
283+ return pm_compare_float_nodes (metadata , left , right );
268284 default :
269285 assert (false && "unreachable" );
270286 return 0 ;
@@ -293,7 +309,7 @@ pm_string_value(const pm_node_t *node) {
293309 * A comparison function for comparing two nodes that have attached strings.
294310 */
295311static int
296- pm_compare_string_nodes (PRISM_ATTRIBUTE_UNUSED const pm_parser_t * parser , const pm_node_t * left , const pm_node_t * right ) {
312+ pm_compare_string_nodes (PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t * metadata , const pm_node_t * left , const pm_node_t * right ) {
297313 const pm_string_t * left_string = pm_string_value (left );
298314 const pm_string_t * right_string = pm_string_value (right );
299315 return pm_string_compare (left_string , right_string );
@@ -303,7 +319,7 @@ pm_compare_string_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *parser, const
303319 * A comparison function for comparing two RegularExpressionNode instances.
304320 */
305321static int
306- pm_compare_regular_expression_nodes (PRISM_ATTRIBUTE_UNUSED const pm_parser_t * parser , const pm_node_t * left , const pm_node_t * right ) {
322+ pm_compare_regular_expression_nodes (PRISM_ATTRIBUTE_UNUSED const pm_static_literals_metadata_t * metadata , const pm_node_t * left , const pm_node_t * right ) {
307323 const pm_regular_expression_node_t * left_regexp = (const pm_regular_expression_node_t * ) left ;
308324 const pm_regular_expression_node_t * right_regexp = (const pm_regular_expression_node_t * ) right ;
309325
@@ -319,23 +335,77 @@ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_parser_t *pa
319335 * Add a node to the set of static literals.
320336 */
321337pm_node_t *
322- pm_static_literals_add (const pm_parser_t * parser , pm_static_literals_t * literals , pm_node_t * node ) {
338+ pm_static_literals_add (const pm_newline_list_t * newline_list , int32_t start_line , pm_static_literals_t * literals , pm_node_t * node ) {
323339 switch (PM_NODE_TYPE (node )) {
324340 case PM_INTEGER_NODE :
325341 case PM_SOURCE_LINE_NODE :
326- return pm_node_hash_insert (& literals -> integer_nodes , parser , node , pm_compare_integer_nodes );
342+ return pm_node_hash_insert (
343+ & literals -> integer_nodes ,
344+ & (pm_static_literals_metadata_t ) {
345+ .newline_list = newline_list ,
346+ .start_line = start_line ,
347+ .encoding_name = NULL
348+ },
349+ node ,
350+ pm_compare_integer_nodes
351+ );
327352 case PM_FLOAT_NODE :
328- return pm_node_hash_insert (& literals -> float_nodes , parser , node , pm_compare_float_nodes );
353+ return pm_node_hash_insert (
354+ & literals -> float_nodes ,
355+ & (pm_static_literals_metadata_t ) {
356+ .newline_list = newline_list ,
357+ .start_line = start_line ,
358+ .encoding_name = NULL
359+ },
360+ node ,
361+ pm_compare_float_nodes
362+ );
329363 case PM_RATIONAL_NODE :
330364 case PM_IMAGINARY_NODE :
331- return pm_node_hash_insert (& literals -> number_nodes , parser , node , pm_compare_number_nodes );
365+ return pm_node_hash_insert (
366+ & literals -> number_nodes ,
367+ & (pm_static_literals_metadata_t ) {
368+ .newline_list = newline_list ,
369+ .start_line = start_line ,
370+ .encoding_name = NULL
371+ },
372+ node ,
373+ pm_compare_number_nodes
374+ );
332375 case PM_STRING_NODE :
333376 case PM_SOURCE_FILE_NODE :
334- return pm_node_hash_insert (& literals -> string_nodes , parser , node , pm_compare_string_nodes );
377+ return pm_node_hash_insert (
378+ & literals -> string_nodes ,
379+ & (pm_static_literals_metadata_t ) {
380+ .newline_list = newline_list ,
381+ .start_line = start_line ,
382+ .encoding_name = NULL
383+ },
384+ node ,
385+ pm_compare_string_nodes
386+ );
335387 case PM_REGULAR_EXPRESSION_NODE :
336- return pm_node_hash_insert (& literals -> regexp_nodes , parser , node , pm_compare_regular_expression_nodes );
388+ return pm_node_hash_insert (
389+ & literals -> regexp_nodes ,
390+ & (pm_static_literals_metadata_t ) {
391+ .newline_list = newline_list ,
392+ .start_line = start_line ,
393+ .encoding_name = NULL
394+ },
395+ node ,
396+ pm_compare_regular_expression_nodes
397+ );
337398 case PM_SYMBOL_NODE :
338- return pm_node_hash_insert (& literals -> symbol_nodes , parser , node , pm_compare_string_nodes );
399+ return pm_node_hash_insert (
400+ & literals -> symbol_nodes ,
401+ & (pm_static_literals_metadata_t ) {
402+ .newline_list = newline_list ,
403+ .start_line = start_line ,
404+ .encoding_name = NULL
405+ },
406+ node ,
407+ pm_compare_string_nodes
408+ );
339409 case PM_TRUE_NODE : {
340410 pm_node_t * duplicated = literals -> true_node ;
341411 literals -> true_node = node ;
@@ -435,8 +505,8 @@ pm_rational_inspect(pm_buffer_t *buffer, pm_rational_node_t *node) {
435505/**
436506 * Create a string-based representation of the given static literal.
437507 */
438- PRISM_EXPORTED_FUNCTION void
439- pm_static_literal_inspect (pm_buffer_t * buffer , const pm_parser_t * parser , const pm_node_t * node ) {
508+ static inline void
509+ pm_static_literal_inspect_node (pm_buffer_t * buffer , const pm_static_literals_metadata_t * metadata , const pm_node_t * node ) {
440510 switch (PM_NODE_TYPE (node )) {
441511 case PM_FALSE_NODE :
442512 pm_buffer_append_string (buffer , "false" , 5 );
@@ -473,7 +543,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
473543 const pm_node_t * numeric = ((const pm_imaginary_node_t * ) node )-> numeric ;
474544 pm_buffer_append_string (buffer , "(0" , 2 );
475545 if (pm_static_literal_positive_p (numeric )) pm_buffer_append_byte (buffer , '+' );
476- pm_static_literal_inspect (buffer , parser , numeric );
546+ pm_static_literal_inspect_node (buffer , metadata , numeric );
477547 if (PM_NODE_TYPE_P (numeric , PM_RATIONAL_NODE )) pm_buffer_append_byte (buffer , '*' );
478548 pm_buffer_append_string (buffer , "i)" , 2 );
479549 break ;
@@ -490,7 +560,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
490560 switch (PM_NODE_TYPE (numeric )) {
491561 case PM_INTEGER_NODE :
492562 pm_buffer_append_byte (buffer , '(' );
493- pm_static_literal_inspect (buffer , parser , numeric );
563+ pm_static_literal_inspect_node (buffer , metadata , numeric );
494564 pm_buffer_append_string (buffer , "/1)" , 3 );
495565 break ;
496566 case PM_FLOAT_NODE :
@@ -517,7 +587,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
517587 break ;
518588 }
519589 case PM_SOURCE_ENCODING_NODE :
520- pm_buffer_append_format (buffer , "#<Encoding:%s>" , parser -> encoding -> name );
590+ pm_buffer_append_format (buffer , "#<Encoding:%s>" , metadata -> encoding_name );
521591 break ;
522592 case PM_SOURCE_FILE_NODE : {
523593 const pm_string_t * filepath = & ((const pm_source_file_node_t * ) node )-> filepath ;
@@ -527,7 +597,7 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
527597 break ;
528598 }
529599 case PM_SOURCE_LINE_NODE :
530- pm_buffer_append_format (buffer , "%d" , pm_newline_list_line_column (& parser -> newline_list , node -> location .start , parser -> start_line ).line );
600+ pm_buffer_append_format (buffer , "%d" , pm_newline_list_line_column (metadata -> newline_list , node -> location .start , metadata -> start_line ).line );
531601 break ;
532602 case PM_STRING_NODE : {
533603 const pm_string_t * unescaped = & ((const pm_string_node_t * ) node )-> unescaped ;
@@ -550,3 +620,19 @@ pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const
550620 break ;
551621 }
552622}
623+
624+ /**
625+ * Create a string-based representation of the given static literal.
626+ */
627+ PRISM_EXPORTED_FUNCTION void
628+ 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 ) {
629+ pm_static_literal_inspect_node (
630+ buffer ,
631+ & (pm_static_literals_metadata_t ) {
632+ .newline_list = newline_list ,
633+ .start_line = start_line ,
634+ .encoding_name = encoding_name
635+ },
636+ node
637+ );
638+ }
0 commit comments