prism 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -42
- data/Makefile +8 -8
- data/README.md +3 -1
- data/docs/fuzzing.md +5 -5
- data/ext/prism/extension.h +1 -1
- data/include/prism/internal/comments.h +2 -1
- data/include/prism/internal/parser.h +26 -15
- data/include/prism/internal/static_literals.h +24 -64
- data/include/prism/version.h +2 -2
- data/lib/prism/serialize.rb +1 -1
- data/prism.gemspec +1 -1
- data/src/arena.c +6 -1
- data/src/comments.c +9 -8
- data/src/diagnostic.c +16 -4
- data/src/integer.c +6 -1
- data/src/prism.c +51 -50
- data/src/static_literals.c +280 -405
- metadata +1 -1
data/src/prism.c
CHANGED
|
@@ -184,27 +184,22 @@ lex_mode_terminator(const uint8_t start) {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
|
-
* Push a new lex state onto the stack
|
|
188
|
-
*
|
|
189
|
-
* allocate a new pointer and use that.
|
|
187
|
+
* Push a new lex state onto the stack, reusing a popped lex mode if there is
|
|
188
|
+
* one and allocating a new one otherwise.
|
|
190
189
|
*/
|
|
191
190
|
static void
|
|
192
191
|
lex_mode_push(pm_parser_t *parser, pm_lex_mode_t lex_mode) {
|
|
193
|
-
|
|
194
|
-
parser->lex_modes.index++;
|
|
195
|
-
|
|
196
|
-
if (parser->lex_modes.index > PM_LEX_STACK_SIZE - 1) {
|
|
197
|
-
parser->lex_modes.current = (pm_lex_mode_t *) xmalloc(sizeof(pm_lex_mode_t));
|
|
198
|
-
if (PRISM_UNLIKELY(parser->lex_modes.current == NULL)) {
|
|
199
|
-
fprintf(stderr, "prism: out of memory; aborting\n");
|
|
200
|
-
abort();
|
|
201
|
-
}
|
|
192
|
+
pm_lex_mode_t *next = parser->lex_modes.free;
|
|
202
193
|
|
|
203
|
-
|
|
194
|
+
if (next != NULL) {
|
|
195
|
+
parser->lex_modes.free = next->prev;
|
|
204
196
|
} else {
|
|
205
|
-
parser->
|
|
206
|
-
parser->lex_modes.current = &parser->lex_modes.stack[parser->lex_modes.index];
|
|
197
|
+
next = (pm_lex_mode_t *) pm_arena_alloc(&parser->scratch_arena, sizeof(pm_lex_mode_t), PRISM_ALIGNOF(pm_lex_mode_t));
|
|
207
198
|
}
|
|
199
|
+
|
|
200
|
+
lex_mode.prev = parser->lex_modes.current;
|
|
201
|
+
*next = lex_mode;
|
|
202
|
+
parser->lex_modes.current = next;
|
|
208
203
|
}
|
|
209
204
|
|
|
210
205
|
/**
|
|
@@ -357,22 +352,20 @@ lex_mode_push_string_eof(pm_parser_t *parser) {
|
|
|
357
352
|
}
|
|
358
353
|
|
|
359
354
|
/**
|
|
360
|
-
* Pop the current lex state off the stack
|
|
361
|
-
*
|
|
362
|
-
*
|
|
355
|
+
* Pop the current lex state off the stack, keeping it for reuse by the next
|
|
356
|
+
* push. The base lex mode is never popped, so popping it instead resets it to
|
|
357
|
+
* the default mode.
|
|
363
358
|
*/
|
|
364
359
|
static void
|
|
365
360
|
lex_mode_pop(pm_parser_t *parser) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
parser->lex_modes.current = &parser->lex_modes.stack[parser->lex_modes.index];
|
|
361
|
+
pm_lex_mode_t *popped = parser->lex_modes.current;
|
|
362
|
+
|
|
363
|
+
if (popped == &parser->lex_modes.base) {
|
|
364
|
+
popped->mode = PM_LEX_DEFAULT;
|
|
371
365
|
} else {
|
|
372
|
-
parser->lex_modes.
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
parser->lex_modes.current = prev;
|
|
366
|
+
parser->lex_modes.current = popped->prev;
|
|
367
|
+
popped->prev = parser->lex_modes.free;
|
|
368
|
+
parser->lex_modes.free = popped;
|
|
376
369
|
}
|
|
377
370
|
}
|
|
378
371
|
|
|
@@ -709,7 +702,7 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
|
|
|
709
702
|
memset(locals.locals, 0, locals.capacity * sizeof(pm_local_t));
|
|
710
703
|
}
|
|
711
704
|
} else {
|
|
712
|
-
scope = (pm_scope_t *) pm_arena_alloc(&parser->
|
|
705
|
+
scope = (pm_scope_t *) pm_arena_alloc(&parser->scratch_arena, sizeof(pm_scope_t), PRISM_ALIGNOF(pm_scope_t));
|
|
713
706
|
}
|
|
714
707
|
|
|
715
708
|
*scope = (pm_scope_t) {
|
|
@@ -7262,7 +7255,7 @@ pm_parser_local_depth(pm_parser_t *parser, pm_token_t *token) {
|
|
|
7262
7255
|
*/
|
|
7263
7256
|
static PRISM_INLINE void
|
|
7264
7257
|
pm_parser_local_add(pm_parser_t *parser, pm_constant_id_t constant_id, const uint8_t *start, const uint8_t *end, uint32_t reads) {
|
|
7265
|
-
pm_locals_write(&parser->
|
|
7258
|
+
pm_locals_write(&parser->scratch_arena, &parser->current_scope->locals, constant_id, U32(start - parser->start), U32(end - start), reads);
|
|
7266
7259
|
}
|
|
7267
7260
|
|
|
7268
7261
|
/**
|
|
@@ -7997,7 +7990,7 @@ context_push(pm_parser_t *parser, pm_context_t context) {
|
|
|
7997
7990
|
if (context_node != NULL) {
|
|
7998
7991
|
parser->free_contexts = context_node->prev;
|
|
7999
7992
|
} else {
|
|
8000
|
-
context_node = (pm_context_node_t *) pm_arena_alloc(&parser->
|
|
7993
|
+
context_node = (pm_context_node_t *) pm_arena_alloc(&parser->scratch_arena, sizeof(pm_context_node_t), PRISM_ALIGNOF(pm_context_node_t));
|
|
8001
7994
|
}
|
|
8002
7995
|
|
|
8003
7996
|
pm_context_node_t *previous = parser->current_context;
|
|
@@ -13890,7 +13883,7 @@ parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) {
|
|
|
13890
13883
|
static void
|
|
13891
13884
|
pm_hash_key_duplicated_warn(pm_parser_t *parser, const pm_node_t *duplicated, const pm_node_t *node) {
|
|
13892
13885
|
pm_buffer_t buffer = { 0 };
|
|
13893
|
-
pm_static_literal_inspect(&buffer,
|
|
13886
|
+
pm_static_literal_inspect(&buffer, parser, duplicated);
|
|
13894
13887
|
|
|
13895
13888
|
pm_diagnostic_list_append_format(
|
|
13896
13889
|
&parser->metadata_arena,
|
|
@@ -13912,7 +13905,7 @@ pm_hash_key_duplicated_warn(pm_parser_t *parser, const pm_node_t *duplicated, co
|
|
|
13912
13905
|
*/
|
|
13913
13906
|
static void
|
|
13914
13907
|
pm_hash_key_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) {
|
|
13915
|
-
const pm_node_t *duplicated = pm_static_literals_add(
|
|
13908
|
+
const pm_node_t *duplicated = pm_static_literals_add(parser, literals, node, true);
|
|
13916
13909
|
|
|
13917
13910
|
if (duplicated != NULL) {
|
|
13918
13911
|
pm_hash_key_duplicated_warn(parser, duplicated, node);
|
|
@@ -13936,7 +13929,7 @@ pm_hash_key_static_literals_merge(pm_parser_t *parser, pm_static_literals_t *lit
|
|
|
13936
13929
|
switch (PM_NODE_TYPE(element)) {
|
|
13937
13930
|
case PM_ASSOC_NODE: {
|
|
13938
13931
|
pm_node_t *key = ((pm_assoc_node_t *) element)->key;
|
|
13939
|
-
const pm_node_t *duplicated = pm_static_literals_add(
|
|
13932
|
+
const pm_node_t *duplicated = pm_static_literals_add(parser, literals, key, true);
|
|
13940
13933
|
|
|
13941
13934
|
if (duplicated != NULL && PM_NODE_START(duplicated) < boundary) {
|
|
13942
13935
|
pm_hash_key_duplicated_warn(parser, duplicated, key);
|
|
@@ -13967,7 +13960,7 @@ static void
|
|
|
13967
13960
|
pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) {
|
|
13968
13961
|
pm_node_t *previous;
|
|
13969
13962
|
|
|
13970
|
-
if ((previous = pm_static_literals_add(
|
|
13963
|
+
if ((previous = pm_static_literals_add(parser, literals, node, false)) != NULL) {
|
|
13971
13964
|
pm_diagnostic_list_append_format(
|
|
13972
13965
|
&parser->metadata_arena,
|
|
13973
13966
|
&parser->warning_list,
|
|
@@ -15981,7 +15974,7 @@ ensure_valid_jump(pm_parser_t *parser, pm_node_t *node) {
|
|
|
15981
15974
|
// block exit to the list of exits for the expression, and
|
|
15982
15975
|
// the node parsing will handle validating it instead.
|
|
15983
15976
|
assert(parser->current_block_exits != NULL);
|
|
15984
|
-
pm_node_list_append_inline(parser->
|
|
15977
|
+
pm_node_list_append_inline(&parser->scratch_arena, parser->current_block_exits, node);
|
|
15985
15978
|
return;
|
|
15986
15979
|
case PM_CONTEXT_BEGIN_ELSE:
|
|
15987
15980
|
case PM_CONTEXT_BEGIN_ENSURE:
|
|
@@ -16073,7 +16066,7 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) {
|
|
|
16073
16066
|
// However, they could still become valid in a higher level context if
|
|
16074
16067
|
// there is another list above this one. In this case we'll push all of
|
|
16075
16068
|
// the block exits up to the previous list.
|
|
16076
|
-
pm_node_list_concat(parser->
|
|
16069
|
+
pm_node_list_concat(&parser->scratch_arena, previous_block_exits, parser->current_block_exits);
|
|
16077
16070
|
parser->current_block_exits = previous_block_exits;
|
|
16078
16071
|
} else {
|
|
16079
16072
|
// If we did not match a trailing while/until and this was the last
|
|
@@ -16719,12 +16712,12 @@ parse_variable(pm_parser_t *parser) {
|
|
|
16719
16712
|
}
|
|
16720
16713
|
|
|
16721
16714
|
pm_node_t *node = UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false));
|
|
16722
|
-
pm_node_list_append_inline(parser->
|
|
16715
|
+
pm_node_list_append_inline(&parser->scratch_arena, ¤t_scope->implicit_parameters, node);
|
|
16723
16716
|
|
|
16724
16717
|
return node;
|
|
16725
16718
|
} else if ((parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
|
|
16726
16719
|
pm_node_t *node = UP(pm_it_local_variable_read_node_create(parser, &parser->previous));
|
|
16727
|
-
pm_node_list_append_inline(parser->
|
|
16720
|
+
pm_node_list_append_inline(&parser->scratch_arena, ¤t_scope->implicit_parameters, node);
|
|
16728
16721
|
|
|
16729
16722
|
return node;
|
|
16730
16723
|
}
|
|
@@ -17111,7 +17104,7 @@ parse_pattern_capture(pm_parser_t *parser, pm_constant_id_set_t *captures, pm_co
|
|
|
17111
17104
|
// Skip this capture if it starts with an underscore.
|
|
17112
17105
|
if (peek_at(parser, parser->start + location->start) == '_') return;
|
|
17113
17106
|
|
|
17114
|
-
if (!pm_constant_id_set_insert(parser->
|
|
17107
|
+
if (!pm_constant_id_set_insert(&parser->scratch_arena, captures, capture)) {
|
|
17115
17108
|
pm_parser_err(parser, location->start, location->length, PM_ERR_PATTERN_CAPTURE_DUPLICATE);
|
|
17116
17109
|
}
|
|
17117
17110
|
}
|
|
@@ -17377,7 +17370,7 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_set_t *cap
|
|
|
17377
17370
|
*/
|
|
17378
17371
|
static void
|
|
17379
17372
|
parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_t *node) {
|
|
17380
|
-
if (pm_static_literals_add(
|
|
17373
|
+
if (pm_static_literals_add(parser, keys, node, true) != NULL) {
|
|
17381
17374
|
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_KEY_DUPLICATE);
|
|
17382
17375
|
}
|
|
17383
17376
|
}
|
|
@@ -21804,7 +21797,7 @@ parse_regular_expression_named_capture(pm_parser_t *parser, const pm_string_t *c
|
|
|
21804
21797
|
* Add this name to the set of constants if it is valid, not duplicated,
|
|
21805
21798
|
* and not a keyword.
|
|
21806
21799
|
*/
|
|
21807
|
-
if (name != 0 && pm_constant_id_set_insert(parser->
|
|
21800
|
+
if (name != 0 && pm_constant_id_set_insert(&parser->scratch_arena, names, name)) {
|
|
21808
21801
|
|
|
21809
21802
|
int depth;
|
|
21810
21803
|
if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
|
|
@@ -22000,7 +21993,7 @@ parse_match(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t binding_pow
|
|
|
22000
21993
|
}
|
|
22001
21994
|
|
|
22002
21995
|
if (!interpolated && total_length > 0) {
|
|
22003
|
-
uint8_t *memory = (uint8_t *) pm_arena_alloc(&parser->
|
|
21996
|
+
uint8_t *memory = (uint8_t *) pm_arena_alloc(&parser->scratch_arena, total_length, PRISM_ALIGNOF(uint8_t));
|
|
22004
21997
|
uint8_t *cursor = memory;
|
|
22005
21998
|
PM_NODE_LIST_FOREACH(parts, index, part) {
|
|
22006
21999
|
pm_string_t *unescaped = &((pm_string_node_t *) part)->unescaped;
|
|
@@ -23261,6 +23254,16 @@ pm_parser_init_shebang(pm_parser_t *parser, const pm_options_t *options, const c
|
|
|
23261
23254
|
parser->frozen_string_literal = next_options.frozen_string_literal;
|
|
23262
23255
|
}
|
|
23263
23256
|
|
|
23257
|
+
/**
|
|
23258
|
+
* The smallest capacity the constant pool starts with, whatever the source
|
|
23259
|
+
* size suggests. An embedder that interns a fixed set of names into the pool
|
|
23260
|
+
* at every parse (a symbol table) can raise it to that set's size, so the
|
|
23261
|
+
* pool does not grow to hold them and leave each outgrown array in the arena.
|
|
23262
|
+
*/
|
|
23263
|
+
#ifndef PM_CONSTANT_POOL_MIN_CAPACITY
|
|
23264
|
+
#define PM_CONSTANT_POOL_MIN_CAPACITY 4
|
|
23265
|
+
#endif
|
|
23266
|
+
|
|
23264
23267
|
/**
|
|
23265
23268
|
* Initialize a parser with the given start and end pointers.
|
|
23266
23269
|
*/
|
|
@@ -23280,9 +23283,8 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si
|
|
|
23280
23283
|
.do_loop_stack = 0,
|
|
23281
23284
|
.accepts_block_stack = 0,
|
|
23282
23285
|
.lex_modes = {
|
|
23283
|
-
.
|
|
23284
|
-
.
|
|
23285
|
-
.current = &parser->lex_modes.stack[0],
|
|
23286
|
+
.current = &parser->lex_modes.base,
|
|
23287
|
+
.base = { .mode = PM_LEX_DEFAULT },
|
|
23286
23288
|
},
|
|
23287
23289
|
.start = source,
|
|
23288
23290
|
.end = source + size,
|
|
@@ -23339,7 +23341,8 @@ pm_parser_init(pm_arena_t *arena, pm_parser_t *parser, const uint8_t *source, si
|
|
|
23339
23341
|
* frequency. Resizes are cheap with arena allocation, so we lean toward
|
|
23340
23342
|
* under-estimating. */
|
|
23341
23343
|
uint32_t constant_size = ((uint32_t) size) / 120;
|
|
23342
|
-
|
|
23344
|
+
if (constant_size < PM_CONSTANT_POOL_MIN_CAPACITY) constant_size = PM_CONSTANT_POOL_MIN_CAPACITY;
|
|
23345
|
+
pm_constant_pool_init(&parser->metadata_arena, &parser->constant_pool, constant_size);
|
|
23343
23346
|
|
|
23344
23347
|
/* Initialize the line offset list. Similar to the constant pool, we are
|
|
23345
23348
|
* going to estimate the number of newlines that we will need based on the
|
|
@@ -23549,10 +23552,7 @@ pm_parser_new(pm_arena_t *arena, const uint8_t *source, size_t size, const pm_op
|
|
|
23549
23552
|
void
|
|
23550
23553
|
pm_parser_cleanup(pm_parser_t *parser) {
|
|
23551
23554
|
pm_arena_cleanup(&parser->metadata_arena);
|
|
23552
|
-
|
|
23553
|
-
while (parser->lex_modes.index >= PM_LEX_STACK_SIZE) {
|
|
23554
|
-
lex_mode_pop(parser);
|
|
23555
|
-
}
|
|
23555
|
+
pm_arena_cleanup(&parser->scratch_arena);
|
|
23556
23556
|
}
|
|
23557
23557
|
|
|
23558
23558
|
/**
|
|
@@ -23734,6 +23734,7 @@ pm_parse(pm_parser_t *parser) {
|
|
|
23734
23734
|
pm_node_t *node = parse_program(parser);
|
|
23735
23735
|
pm_parse_continuable(parser);
|
|
23736
23736
|
if (parser->attach_comments) pm_comments_attach(parser, node);
|
|
23737
|
+
pm_arena_cleanup(&parser->scratch_arena);
|
|
23737
23738
|
return node;
|
|
23738
23739
|
}
|
|
23739
23740
|
|