prism 0.23.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/BSDmakefile +58 -0
  3. data/CHANGELOG.md +65 -1
  4. data/Makefile +5 -2
  5. data/README.md +45 -6
  6. data/config.yml +499 -4
  7. data/docs/build_system.md +31 -0
  8. data/docs/configuration.md +2 -0
  9. data/docs/cruby_compilation.md +1 -1
  10. data/docs/parser_translation.md +14 -9
  11. data/docs/releasing.md +3 -3
  12. data/docs/ripper_translation.md +50 -0
  13. data/docs/ruby_api.md +1 -0
  14. data/docs/serialization.md +26 -5
  15. data/ext/prism/api_node.c +2342 -1801
  16. data/ext/prism/api_pack.c +9 -0
  17. data/ext/prism/extconf.rb +27 -11
  18. data/ext/prism/extension.c +313 -66
  19. data/ext/prism/extension.h +5 -4
  20. data/include/prism/ast.h +213 -64
  21. data/include/prism/defines.h +106 -2
  22. data/include/prism/diagnostic.h +134 -71
  23. data/include/prism/encoding.h +22 -4
  24. data/include/prism/node.h +93 -0
  25. data/include/prism/options.h +82 -7
  26. data/include/prism/pack.h +11 -0
  27. data/include/prism/parser.h +198 -53
  28. data/include/prism/prettyprint.h +8 -0
  29. data/include/prism/static_literals.h +118 -0
  30. data/include/prism/util/pm_buffer.h +65 -2
  31. data/include/prism/util/pm_constant_pool.h +18 -1
  32. data/include/prism/util/pm_integer.h +119 -0
  33. data/include/prism/util/pm_list.h +1 -1
  34. data/include/prism/util/pm_newline_list.h +12 -3
  35. data/include/prism/util/pm_string.h +26 -2
  36. data/include/prism/version.h +2 -2
  37. data/include/prism.h +59 -1
  38. data/lib/prism/compiler.rb +8 -1
  39. data/lib/prism/debug.rb +46 -3
  40. data/lib/prism/desugar_compiler.rb +225 -80
  41. data/lib/prism/dispatcher.rb +29 -0
  42. data/lib/prism/dot_visitor.rb +87 -16
  43. data/lib/prism/dsl.rb +315 -300
  44. data/lib/prism/ffi.rb +165 -84
  45. data/lib/prism/lex_compat.rb +17 -15
  46. data/lib/prism/mutation_compiler.rb +11 -0
  47. data/lib/prism/node.rb +4857 -3750
  48. data/lib/prism/node_ext.rb +77 -29
  49. data/lib/prism/pack.rb +4 -0
  50. data/lib/prism/parse_result/comments.rb +34 -17
  51. data/lib/prism/parse_result/newlines.rb +3 -1
  52. data/lib/prism/parse_result.rb +88 -34
  53. data/lib/prism/pattern.rb +16 -4
  54. data/lib/prism/polyfill/string.rb +12 -0
  55. data/lib/prism/serialize.rb +960 -327
  56. data/lib/prism/translation/parser/compiler.rb +152 -50
  57. data/lib/prism/translation/parser/lexer.rb +103 -22
  58. data/lib/prism/translation/parser/rubocop.rb +47 -11
  59. data/lib/prism/translation/parser.rb +134 -10
  60. data/lib/prism/translation/parser33.rb +12 -0
  61. data/lib/prism/translation/parser34.rb +12 -0
  62. data/lib/prism/translation/ripper/sexp.rb +125 -0
  63. data/lib/prism/translation/ripper/shim.rb +5 -0
  64. data/lib/prism/translation/ripper.rb +3248 -379
  65. data/lib/prism/translation/ruby_parser.rb +35 -18
  66. data/lib/prism/translation.rb +3 -1
  67. data/lib/prism/visitor.rb +10 -0
  68. data/lib/prism.rb +8 -2
  69. data/prism.gemspec +35 -4
  70. data/rbi/prism/compiler.rbi +14 -0
  71. data/rbi/prism/desugar_compiler.rbi +5 -0
  72. data/rbi/prism/mutation_compiler.rbi +5 -0
  73. data/rbi/prism/node.rbi +8221 -0
  74. data/rbi/prism/node_ext.rbi +102 -0
  75. data/rbi/prism/parse_result.rbi +304 -0
  76. data/rbi/prism/translation/parser/compiler.rbi +13 -0
  77. data/rbi/prism/translation/ripper/ripper_compiler.rbi +5 -0
  78. data/rbi/prism/translation/ripper.rbi +25 -0
  79. data/rbi/prism/translation/ruby_parser.rbi +11 -0
  80. data/rbi/prism/visitor.rbi +470 -0
  81. data/rbi/prism.rbi +39 -7749
  82. data/sig/prism/compiler.rbs +9 -0
  83. data/sig/prism/dispatcher.rbs +16 -0
  84. data/sig/prism/dot_visitor.rbs +6 -0
  85. data/sig/prism/dsl.rbs +462 -0
  86. data/sig/prism/mutation_compiler.rbs +158 -0
  87. data/sig/prism/node.rbs +3529 -0
  88. data/sig/prism/node_ext.rbs +78 -0
  89. data/sig/prism/pack.rbs +43 -0
  90. data/sig/prism/parse_result.rbs +127 -0
  91. data/sig/prism/pattern.rbs +13 -0
  92. data/sig/prism/serialize.rbs +7 -0
  93. data/sig/prism/visitor.rbs +168 -0
  94. data/sig/prism.rbs +188 -4767
  95. data/src/diagnostic.c +575 -230
  96. data/src/encoding.c +211 -108
  97. data/src/node.c +7526 -447
  98. data/src/options.c +36 -12
  99. data/src/pack.c +33 -17
  100. data/src/prettyprint.c +1297 -1388
  101. data/src/prism.c +3665 -1121
  102. data/src/regexp.c +17 -2
  103. data/src/serialize.c +47 -28
  104. data/src/static_literals.c +552 -0
  105. data/src/token_type.c +1 -0
  106. data/src/util/pm_buffer.c +147 -20
  107. data/src/util/pm_char.c +4 -4
  108. data/src/util/pm_constant_pool.c +35 -11
  109. data/src/util/pm_integer.c +629 -0
  110. data/src/util/pm_list.c +1 -1
  111. data/src/util/pm_newline_list.c +20 -8
  112. data/src/util/pm_string.c +134 -5
  113. data/src/util/pm_string_list.c +2 -2
  114. metadata +37 -6
  115. data/docs/ripper.md +0 -36
  116. data/rbi/prism_static.rbi +0 -207
  117. data/sig/prism_static.rbs +0 -201
@@ -6,8 +6,8 @@
6
6
  #ifndef PRISM_PARSER_H
7
7
  #define PRISM_PARSER_H
8
8
 
9
- #include "prism/ast.h"
10
9
  #include "prism/defines.h"
10
+ #include "prism/ast.h"
11
11
  #include "prism/encoding.h"
12
12
  #include "prism/options.h"
13
13
  #include "prism/util/pm_constant_pool.h"
@@ -173,7 +173,7 @@ typedef struct pm_lex_mode {
173
173
  * This is the character set that should be used to delimit the
174
174
  * tokens within the regular expression.
175
175
  */
176
- uint8_t breakpoints[6];
176
+ uint8_t breakpoints[7];
177
177
  } regexp;
178
178
 
179
179
  struct {
@@ -206,7 +206,7 @@ typedef struct pm_lex_mode {
206
206
  * This is the character set that should be used to delimit the
207
207
  * tokens within the string.
208
208
  */
209
- uint8_t breakpoints[6];
209
+ uint8_t breakpoints[7];
210
210
  } string;
211
211
 
212
212
  struct {
@@ -234,6 +234,9 @@ typedef struct pm_lex_mode {
234
234
  * a tilde heredoc.
235
235
  */
236
236
  size_t common_whitespace;
237
+
238
+ /** True if the previous token ended with a line continuation. */
239
+ bool line_continuation;
237
240
  } heredoc;
238
241
  } as;
239
242
 
@@ -265,12 +268,30 @@ typedef enum {
265
268
  /** a begin statement */
266
269
  PM_CONTEXT_BEGIN,
267
270
 
271
+ /** an ensure statement with an explicit begin */
272
+ PM_CONTEXT_BEGIN_ENSURE,
273
+
274
+ /** a rescue else statement with an explicit begin */
275
+ PM_CONTEXT_BEGIN_ELSE,
276
+
277
+ /** a rescue statement with an explicit begin */
278
+ PM_CONTEXT_BEGIN_RESCUE,
279
+
268
280
  /** expressions in block arguments using braces */
269
281
  PM_CONTEXT_BLOCK_BRACES,
270
282
 
271
283
  /** expressions in block arguments using do..end */
272
284
  PM_CONTEXT_BLOCK_KEYWORDS,
273
285
 
286
+ /** an ensure statement within a do..end block */
287
+ PM_CONTEXT_BLOCK_ENSURE,
288
+
289
+ /** a rescue else statement within a do..end block */
290
+ PM_CONTEXT_BLOCK_ELSE,
291
+
292
+ /** a rescue statement within a do..end block */
293
+ PM_CONTEXT_BLOCK_RESCUE,
294
+
274
295
  /** a case when statements */
275
296
  PM_CONTEXT_CASE_WHEN,
276
297
 
@@ -280,12 +301,33 @@ typedef enum {
280
301
  /** a class declaration */
281
302
  PM_CONTEXT_CLASS,
282
303
 
304
+ /** an ensure statement within a class statement */
305
+ PM_CONTEXT_CLASS_ENSURE,
306
+
307
+ /** a rescue else statement within a class statement */
308
+ PM_CONTEXT_CLASS_ELSE,
309
+
310
+ /** a rescue statement within a class statement */
311
+ PM_CONTEXT_CLASS_RESCUE,
312
+
283
313
  /** a method definition */
284
314
  PM_CONTEXT_DEF,
285
315
 
316
+ /** an ensure statement within a method definition */
317
+ PM_CONTEXT_DEF_ENSURE,
318
+
319
+ /** a rescue else statement within a method definition */
320
+ PM_CONTEXT_DEF_ELSE,
321
+
322
+ /** a rescue statement within a method definition */
323
+ PM_CONTEXT_DEF_RESCUE,
324
+
286
325
  /** a method definition's parameters */
287
326
  PM_CONTEXT_DEF_PARAMS,
288
327
 
328
+ /** a defined? expression */
329
+ PM_CONTEXT_DEFINED,
330
+
289
331
  /** a method definition's default parameter */
290
332
  PM_CONTEXT_DEFAULT_PARAMS,
291
333
 
@@ -298,12 +340,6 @@ typedef enum {
298
340
  /** an interpolated expression */
299
341
  PM_CONTEXT_EMBEXPR,
300
342
 
301
- /** an ensure statement */
302
- PM_CONTEXT_ENSURE,
303
-
304
- /** an ensure statement within a method definition */
305
- PM_CONTEXT_ENSURE_DEF,
306
-
307
343
  /** a for loop */
308
344
  PM_CONTEXT_FOR,
309
345
 
@@ -319,12 +355,30 @@ typedef enum {
319
355
  /** a lambda expression with do..end */
320
356
  PM_CONTEXT_LAMBDA_DO_END,
321
357
 
358
+ /** an ensure statement within a lambda expression */
359
+ PM_CONTEXT_LAMBDA_ENSURE,
360
+
361
+ /** a rescue else statement within a lambda expression */
362
+ PM_CONTEXT_LAMBDA_ELSE,
363
+
364
+ /** a rescue statement within a lambda expression */
365
+ PM_CONTEXT_LAMBDA_RESCUE,
366
+
322
367
  /** the top level context */
323
368
  PM_CONTEXT_MAIN,
324
369
 
325
370
  /** a module declaration */
326
371
  PM_CONTEXT_MODULE,
327
372
 
373
+ /** an ensure statement within a module statement */
374
+ PM_CONTEXT_MODULE_ENSURE,
375
+
376
+ /** a rescue else statement within a module statement */
377
+ PM_CONTEXT_MODULE_ELSE,
378
+
379
+ /** a rescue statement within a module statement */
380
+ PM_CONTEXT_MODULE_RESCUE,
381
+
328
382
  /** a parenthesized expression */
329
383
  PM_CONTEXT_PARENS,
330
384
 
@@ -337,20 +391,23 @@ typedef enum {
337
391
  /** a BEGIN block */
338
392
  PM_CONTEXT_PREEXE,
339
393
 
340
- /** a rescue else statement */
341
- PM_CONTEXT_RESCUE_ELSE,
394
+ /** a modifier rescue clause */
395
+ PM_CONTEXT_RESCUE_MODIFIER,
342
396
 
343
- /** a rescue else statement within a method definition */
344
- PM_CONTEXT_RESCUE_ELSE_DEF,
397
+ /** a singleton class definition */
398
+ PM_CONTEXT_SCLASS,
345
399
 
346
- /** a rescue statement */
347
- PM_CONTEXT_RESCUE,
400
+ /** an ensure statement with a singleton class */
401
+ PM_CONTEXT_SCLASS_ENSURE,
348
402
 
349
- /** a rescue statement within a method definition */
350
- PM_CONTEXT_RESCUE_DEF,
403
+ /** a rescue else statement with a singleton class */
404
+ PM_CONTEXT_SCLASS_ELSE,
351
405
 
352
- /** a singleton class definition */
353
- PM_CONTEXT_SCLASS,
406
+ /** a rescue statement with a singleton class */
407
+ PM_CONTEXT_SCLASS_RESCUE,
408
+
409
+ /** a ternary expression */
410
+ PM_CONTEXT_TERNARY,
354
411
 
355
412
  /** an unless statement */
356
413
  PM_CONTEXT_UNLESS,
@@ -445,42 +502,80 @@ typedef struct {
445
502
  void (*callback)(void *data, pm_parser_t *parser, pm_token_t *token);
446
503
  } pm_lex_callback_t;
447
504
 
505
+ /** The type of shareable constant value that can be set. */
506
+ typedef uint8_t pm_shareable_constant_value_t;
507
+ static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0;
508
+ static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = 0x1;
509
+ static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = 0x2;
510
+ static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = 0x4;
511
+
512
+ /**
513
+ * This tracks an individual local variable in a certain lexical context, as
514
+ * well as the number of times is it read.
515
+ */
516
+ typedef struct {
517
+ /** The name of the local variable. */
518
+ pm_constant_id_t name;
519
+
520
+ /** The location of the local variable in the source. */
521
+ pm_location_t location;
522
+
523
+ /** The index of the local variable in the local table. */
524
+ uint32_t index;
525
+
526
+ /** The number of times the local variable is read. */
527
+ uint32_t reads;
528
+
529
+ /** The hash of the local variable. */
530
+ uint32_t hash;
531
+ } pm_local_t;
532
+
533
+ /**
534
+ * This is a set of local variables in a certain lexical context (method, class,
535
+ * module, etc.). We need to track how many times these variables are read in
536
+ * order to warn if they only get written.
537
+ */
538
+ typedef struct pm_locals {
539
+ /** The number of local variables in the set. */
540
+ uint32_t size;
541
+
542
+ /** The capacity of the local variables set. */
543
+ uint32_t capacity;
544
+
545
+ /** The nullable allocated memory for the local variables in the set. */
546
+ pm_local_t *locals;
547
+ } pm_locals_t;
548
+
448
549
  /**
449
550
  * This struct represents a node in a linked list of scopes. Some scopes can see
450
551
  * into their parent scopes, while others cannot.
451
552
  */
452
553
  typedef struct pm_scope {
453
- /** The IDs of the locals in the given scope. */
454
- pm_constant_id_list_t locals;
455
-
456
554
  /** A pointer to the previous scope in the linked list. */
457
555
  struct pm_scope *previous;
458
556
 
459
- /**
460
- * A boolean indicating whether or not this scope can see into its parent.
461
- * If closed is true, then the scope cannot see into its parent.
462
- */
463
- bool closed;
464
-
465
- /**
466
- * A boolean indicating whether or not this scope has explicit parameters.
467
- * This is necessary to determine whether or not numbered parameters are
468
- * allowed.
469
- */
470
- bool explicit_params;
557
+ /** The IDs of the locals in the given scope. */
558
+ pm_locals_t locals;
471
559
 
472
560
  /**
473
- * Booleans indicating whether the parameters for this scope have declared
474
- * forwarding parameters.
561
+ * This is a bitfield that indicates the parameters that are being used in
562
+ * this scope. It is a combination of the PM_SCOPE_PARAMS_* constants. There
563
+ * are three different kinds of parameters that can be used in a scope:
475
564
  *
476
- * For example, some combinations of:
477
- * def foo(*); end
478
- * def foo(**); end
479
- * def foo(&); end
480
- * def foo(...); end
565
+ * - Ordinary parameters (e.g., def foo(bar); end)
566
+ * - Numbered parameters (e.g., def foo; _1; end)
567
+ * - The it parameter (e.g., def foo; it; end)
568
+ *
569
+ * If ordinary parameters are being used, then certain parameters can be
570
+ * forwarded to another method/structure. Those are indicated by four
571
+ * additional bits in the params field. For example, some combinations of:
572
+ *
573
+ * - def foo(*); end
574
+ * - def foo(**); end
575
+ * - def foo(&); end
576
+ * - def foo(...); end
481
577
  */
482
-
483
- uint8_t forwarding_params;
578
+ uint8_t parameters;
484
579
 
485
580
  /**
486
581
  * An integer indicating the number of numbered parameters on this scope.
@@ -488,13 +583,34 @@ typedef struct pm_scope {
488
583
  * numbered parameters, and to pass information to consumers of the AST
489
584
  * about how many numbered parameters exist.
490
585
  */
491
- uint8_t numbered_parameters;
586
+ int8_t numbered_parameters;
587
+
588
+ /**
589
+ * The current state of constant shareability for this scope. This is
590
+ * changed by magic shareable_constant_value comments.
591
+ */
592
+ pm_shareable_constant_value_t shareable_constant;
593
+
594
+ /**
595
+ * A boolean indicating whether or not this scope can see into its parent.
596
+ * If closed is true, then the scope cannot see into its parent.
597
+ */
598
+ bool closed;
492
599
  } pm_scope_t;
493
600
 
494
- static const uint8_t PM_FORWARDING_POSITIONALS = 0x1;
495
- static const uint8_t PM_FORWARDING_KEYWORDS = 0x2;
496
- static const uint8_t PM_FORWARDING_BLOCK = 0x4;
497
- static const uint8_t PM_FORWARDING_ALL = 0x8;
601
+ static const uint8_t PM_SCOPE_PARAMETERS_NONE = 0x0;
602
+ static const uint8_t PM_SCOPE_PARAMETERS_ORDINARY = 0x1;
603
+ static const uint8_t PM_SCOPE_PARAMETERS_NUMBERED = 0x2;
604
+ static const uint8_t PM_SCOPE_PARAMETERS_IT = 0x4;
605
+ static const uint8_t PM_SCOPE_PARAMETERS_TYPE_MASK = 0x7;
606
+
607
+ static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS = 0x8;
608
+ static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS = 0x10;
609
+ static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_BLOCK = 0x20;
610
+ static const uint8_t PM_SCOPE_PARAMETERS_FORWARDING_ALL = 0x40;
611
+
612
+ static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_DISALLOWED = -1;
613
+ static const int8_t PM_SCOPE_NUMBERED_PARAMETERS_NONE = 0;
498
614
 
499
615
  /**
500
616
  * This struct represents the overall parser. It contains a reference to the
@@ -688,12 +804,41 @@ struct pm_parser {
688
804
  */
689
805
  const pm_encoding_t *explicit_encoding;
690
806
 
691
- /** The current parameter name id on parsing its default value. */
692
- pm_constant_id_t current_param_name;
807
+ /**
808
+ * When parsing block exits (e.g., break, next, redo), we need to validate
809
+ * that they are in correct contexts. For the most part we can do this by
810
+ * looking at our parent contexts. However, modifier while and until
811
+ * expressions can change that context to make block exits valid. In these
812
+ * cases, we need to keep track of the block exits and then validate them
813
+ * after the expression has been parsed.
814
+ *
815
+ * We use a pointer here because we don't want to keep a whole list attached
816
+ * since this will only be used in the context of begin/end expressions.
817
+ */
818
+ pm_node_list_t *current_block_exits;
693
819
 
694
820
  /** The version of prism that we should use to parse. */
695
821
  pm_options_version_t version;
696
822
 
823
+ /** The command line flags given from the options. */
824
+ uint8_t command_line;
825
+
826
+ /**
827
+ * Whether or not we have found a frozen_string_literal magic comment with
828
+ * a true or false value.
829
+ * May be:
830
+ * - PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED
831
+ * - PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED
832
+ * - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET
833
+ */
834
+ int8_t frozen_string_literal;
835
+
836
+ /**
837
+ * Whether or not we are parsing an eval string. This impacts whether or not
838
+ * we should evaluate if block exits/yields are valid.
839
+ */
840
+ bool parsing_eval;
841
+
697
842
  /** Whether or not we're at the beginning of a command. */
698
843
  bool command_start;
699
844
 
@@ -723,10 +868,10 @@ struct pm_parser {
723
868
  bool semantic_token_seen;
724
869
 
725
870
  /**
726
- * Whether or not we have found a frozen_string_literal magic comment with
727
- * a true value.
871
+ * True if the current regular expression being lexed contains only ASCII
872
+ * characters.
728
873
  */
729
- bool frozen_string_literal;
874
+ bool current_regular_expression_ascii_only;
730
875
  };
731
876
 
732
877
  #endif
@@ -8,6 +8,12 @@
8
8
 
9
9
  #include "prism/defines.h"
10
10
 
11
+ #ifdef PRISM_EXCLUDE_PRETTYPRINT
12
+
13
+ void pm_prettyprint(void);
14
+
15
+ #else
16
+
11
17
  #include <stdio.h>
12
18
 
13
19
  #include "prism/ast.h"
@@ -24,3 +30,5 @@
24
30
  PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node);
25
31
 
26
32
  #endif
33
+
34
+ #endif
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @file static_literals.h
3
+ *
4
+ * A set of static literal nodes that can be checked for duplicates.
5
+ */
6
+ #ifndef PRISM_STATIC_LITERALS_H
7
+ #define PRISM_STATIC_LITERALS_H
8
+
9
+ #include "prism/defines.h"
10
+ #include "prism/ast.h"
11
+ #include "prism/node.h"
12
+ #include "prism/parser.h"
13
+
14
+ #include <assert.h>
15
+ #include <stdbool.h>
16
+
17
+ /**
18
+ * An internal hash table for a set of nodes.
19
+ */
20
+ typedef struct {
21
+ /** The array of nodes in the hash table. */
22
+ pm_node_t **nodes;
23
+
24
+ /** The size of the hash table. */
25
+ uint32_t size;
26
+
27
+ /** The space that has been allocated in the hash table. */
28
+ uint32_t capacity;
29
+ } pm_node_hash_t;
30
+
31
+ /**
32
+ * Certain sets of nodes (hash keys and when clauses) check for duplicate nodes
33
+ * to alert the user of potential issues. To do this, we keep a set of the nodes
34
+ * that have been seen so far, and compare whenever we find a new node.
35
+ *
36
+ * We bucket the nodes based on their type to minimize the number of comparisons
37
+ * that need to be performed.
38
+ */
39
+ typedef struct {
40
+ /**
41
+ * This is the set of IntegerNode and SourceLineNode instances.
42
+ */
43
+ pm_node_hash_t integer_nodes;
44
+
45
+ /**
46
+ * This is the set of FloatNode instances.
47
+ */
48
+ pm_node_hash_t float_nodes;
49
+
50
+ /**
51
+ * This is the set of RationalNode and ImaginaryNode instances.
52
+ */
53
+ pm_node_hash_t number_nodes;
54
+
55
+ /**
56
+ * This is the set of StringNode and SourceFileNode instances.
57
+ */
58
+ pm_node_hash_t string_nodes;
59
+
60
+ /**
61
+ * This is the set of RegularExpressionNode instances.
62
+ */
63
+ pm_node_hash_t regexp_nodes;
64
+
65
+ /**
66
+ * This is the set of SymbolNode instances.
67
+ */
68
+ pm_node_hash_t symbol_nodes;
69
+
70
+ /**
71
+ * A pointer to the last TrueNode instance that was inserted, or NULL.
72
+ */
73
+ pm_node_t *true_node;
74
+
75
+ /**
76
+ * A pointer to the last FalseNode instance that was inserted, or NULL.
77
+ */
78
+ pm_node_t *false_node;
79
+
80
+ /**
81
+ * A pointer to the last NilNode instance that was inserted, or NULL.
82
+ */
83
+ pm_node_t *nil_node;
84
+
85
+ /**
86
+ * A pointer to the last SourceEncodingNode instance that was inserted, or
87
+ * NULL.
88
+ */
89
+ pm_node_t *source_encoding_node;
90
+ } pm_static_literals_t;
91
+
92
+ /**
93
+ * Add a node to the set of static literals.
94
+ *
95
+ * @param parser The parser that created the node.
96
+ * @param literals The set of static literals to add the node to.
97
+ * @param node The node to add to the set.
98
+ * @return A pointer to the node that is being overwritten, if there is one.
99
+ */
100
+ pm_node_t * pm_static_literals_add(const pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node);
101
+
102
+ /**
103
+ * Free the internal memory associated with the given static literals set.
104
+ *
105
+ * @param literals The set of static literals to free.
106
+ */
107
+ void pm_static_literals_free(pm_static_literals_t *literals);
108
+
109
+ /**
110
+ * Create a string-based representation of the given static literal.
111
+ *
112
+ * @param buffer The buffer to write the string to.
113
+ * @param parser The parser that created the node.
114
+ * @param node The node to create a string representation of.
115
+ */
116
+ PRISM_EXPORTED_FUNCTION void pm_static_literal_inspect(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node);
117
+
118
+ #endif
@@ -7,6 +7,7 @@
7
7
  #define PRISM_BUFFER_H
8
8
 
9
9
  #include "prism/defines.h"
10
+ #include "prism/util/pm_char.h"
10
11
 
11
12
  #include <assert.h>
12
13
  #include <stdbool.h>
@@ -59,7 +60,7 @@ PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer);
59
60
  * @param buffer The buffer to get the value of.
60
61
  * @returns The value of the buffer.
61
62
  */
62
- PRISM_EXPORTED_FUNCTION char * pm_buffer_value(pm_buffer_t *buffer);
63
+ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer);
63
64
 
64
65
  /**
65
66
  * Return the length of the buffer.
@@ -67,7 +68,7 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(pm_buffer_t *buffer);
67
68
  * @param buffer The buffer to get the length of.
68
69
  * @returns The length of the buffer.
69
70
  */
70
- PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(pm_buffer_t *buffer);
71
+ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer);
71
72
 
72
73
  /**
73
74
  * Append the given amount of space as zeroes to the buffer.
@@ -128,6 +129,33 @@ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value);
128
129
  */
129
130
  void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value);
130
131
 
132
+ /**
133
+ * Append a double to the buffer.
134
+ *
135
+ * @param buffer The buffer to append to.
136
+ * @param value The double to append.
137
+ */
138
+ void pm_buffer_append_double(pm_buffer_t *buffer, double value);
139
+
140
+ /**
141
+ * The different types of escaping that can be performed by the buffer when
142
+ * appending a slice of Ruby source code.
143
+ */
144
+ typedef enum {
145
+ PM_BUFFER_ESCAPING_RUBY,
146
+ PM_BUFFER_ESCAPING_JSON
147
+ } pm_buffer_escaping_t;
148
+
149
+ /**
150
+ * Append a slice of source code to the buffer.
151
+ *
152
+ * @param buffer The buffer to append to.
153
+ * @param source The source code to append.
154
+ * @param length The length of the source code to append.
155
+ * @param escaping The type of escaping to perform.
156
+ */
157
+ void pm_buffer_append_source(pm_buffer_t *buffer, const uint8_t *source, size_t length, pm_buffer_escaping_t escaping);
158
+
131
159
  /**
132
160
  * Prepend the given string to the buffer.
133
161
  *
@@ -145,6 +173,41 @@ void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t len
145
173
  */
146
174
  void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source);
147
175
 
176
+ /**
177
+ * Clear the buffer by reducing its size to 0. This does not free the allocated
178
+ * memory, but it does allow the buffer to be reused.
179
+ *
180
+ * @param buffer The buffer to clear.
181
+ */
182
+ void pm_buffer_clear(pm_buffer_t *buffer);
183
+
184
+ /**
185
+ * Strip the whitespace from the end of the buffer.
186
+ *
187
+ * @param buffer The buffer to strip.
188
+ */
189
+ void pm_buffer_rstrip(pm_buffer_t *buffer);
190
+
191
+ /**
192
+ * Checks if the buffer includes the given value.
193
+ *
194
+ * @param buffer The buffer to check.
195
+ * @param value The value to check for.
196
+ * @returns The index of the first occurrence of the value in the buffer, or
197
+ * SIZE_MAX if the value is not found.
198
+ */
199
+ size_t pm_buffer_index(const pm_buffer_t *buffer, char value);
200
+
201
+ /**
202
+ * Insert the given string into the buffer at the given index.
203
+ *
204
+ * @param buffer The buffer to insert into.
205
+ * @param index The index to insert at.
206
+ * @param value The string to insert.
207
+ * @param length The length of the string to insert.
208
+ */
209
+ void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size_t length);
210
+
148
211
  /**
149
212
  * Free the memory associated with the buffer.
150
213
  *
@@ -51,6 +51,14 @@ typedef struct {
51
51
  */
52
52
  void pm_constant_id_list_init(pm_constant_id_list_t *list);
53
53
 
54
+ /**
55
+ * Initialize a list of constant ids with a given capacity.
56
+ *
57
+ * @param list The list to initialize.
58
+ * @param capacity The initial capacity of the list.
59
+ */
60
+ void pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity);
61
+
54
62
  /**
55
63
  * Append a constant id to a list of constant ids. Returns false if any
56
64
  * potential reallocations fail.
@@ -61,6 +69,15 @@ void pm_constant_id_list_init(pm_constant_id_list_t *list);
61
69
  */
62
70
  bool pm_constant_id_list_append(pm_constant_id_list_t *list, pm_constant_id_t id);
63
71
 
72
+ /**
73
+ * Insert a constant id into a list of constant ids at the specified index.
74
+ *
75
+ * @param list The list to insert into.
76
+ * @param index The index at which to insert.
77
+ * @param id The id to insert.
78
+ */
79
+ void pm_constant_id_list_insert(pm_constant_id_list_t *list, size_t index, pm_constant_id_t id);
80
+
64
81
  /**
65
82
  * Checks if the current constant id list includes the given constant id.
66
83
  *
@@ -186,7 +203,7 @@ pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const
186
203
  * @param length The length of the constant.
187
204
  * @return The id of the constant.
188
205
  */
189
- pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, const uint8_t *start, size_t length);
206
+ pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, uint8_t *start, size_t length);
190
207
 
191
208
  /**
192
209
  * Insert a constant into a constant pool from memory that is constant. Returns