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.
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. If we're still within the pre-allocated
188
- * space of the lex state stack, then we'll just use a new slot. Otherwise we'll
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
- lex_mode.prev = parser->lex_modes.current;
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
- *parser->lex_modes.current = lex_mode;
194
+ if (next != NULL) {
195
+ parser->lex_modes.free = next->prev;
204
196
  } else {
205
- parser->lex_modes.stack[parser->lex_modes.index] = lex_mode;
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. If we're within the pre-allocated
361
- * space of the lex state stack, then we'll just decrement the index. Otherwise
362
- * we'll free the current pointer and use the previous pointer.
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
- if (parser->lex_modes.index == 0) {
367
- parser->lex_modes.current->mode = PM_LEX_DEFAULT;
368
- } else if (parser->lex_modes.index < PM_LEX_STACK_SIZE) {
369
- parser->lex_modes.index--;
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.index--;
373
- pm_lex_mode_t *prev = parser->lex_modes.current->prev;
374
- xfree_sized(parser->lex_modes.current, sizeof(pm_lex_mode_t));
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->metadata_arena, sizeof(pm_scope_t), PRISM_ALIGNOF(pm_scope_t));
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->metadata_arena, &parser->current_scope->locals, constant_id, U32(start - parser->start), U32(end - start), reads);
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->metadata_arena, sizeof(pm_context_node_t), PRISM_ALIGNOF(pm_context_node_t));
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, &parser->line_offsets, parser->start, parser->start_line, parser->encoding, duplicated);
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(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, literals, node, true);
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(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, literals, key, true);
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(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, literals, node, false)) != NULL) {
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->arena, parser->current_block_exits, node);
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->arena, previous_block_exits, parser->current_block_exits);
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->arena, &current_scope->implicit_parameters, node);
16715
+ pm_node_list_append_inline(&parser->scratch_arena, &current_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->arena, &current_scope->implicit_parameters, node);
16720
+ pm_node_list_append_inline(&parser->scratch_arena, &current_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->arena, captures, capture)) {
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(&parser->line_offsets, parser->start, parser->start_line, parser->encoding, keys, node, true) != NULL) {
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->arena, names, name)) {
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->metadata_arena, total_length, PRISM_ALIGNOF(uint8_t));
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
- .index = 0,
23284
- .stack = {{ .mode = PM_LEX_DEFAULT }},
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
- pm_constant_pool_init(&parser->metadata_arena, &parser->constant_pool, constant_size < 4 ? 4 : constant_size);
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