prism 2.0.0.rc1-arm-linux-gnu → 2.1.0-arm-linux-gnu

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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -41
  3. data/CODE_OF_CONDUCT.md +1 -1
  4. data/LICENSE.md +1 -1
  5. data/Makefile +8 -8
  6. data/README.md +3 -1
  7. data/docs/fuzzing.md +5 -5
  8. data/docs/serialization.md +20 -6
  9. data/ext/prism/api_node.c +81 -81
  10. data/ext/prism/extension.c +54 -69
  11. data/ext/prism/extension.h +1 -1
  12. data/include/prism/arena.h +8 -0
  13. data/include/prism/arena.hpp +42 -0
  14. data/include/prism/ast.h +11 -1
  15. data/include/prism/ast.hpp +641 -0
  16. data/include/prism/buffer.h +8 -0
  17. data/include/prism/buffer.hpp +55 -0
  18. data/include/prism/comments.h +17 -0
  19. data/include/prism/compiler/accel.h +3 -1
  20. data/include/prism/compiler/branch.h +26 -0
  21. data/include/prism/compiler/bswap.h +46 -0
  22. data/include/prism/compiler/cplusplus.hpp +16 -0
  23. data/include/prism/compiler/endianness.h +34 -0
  24. data/include/prism/compiler/exceptions.hpp +17 -0
  25. data/include/prism/compiler/format.h +2 -0
  26. data/include/prism/compiler/lifetimebound.hpp +25 -0
  27. data/include/prism/constant_pool.h +25 -0
  28. data/include/prism/diagnostic.h +18 -0
  29. data/include/prism/errors_format.h +8 -0
  30. data/include/prism/internal/buffer.h +3 -0
  31. data/include/prism/internal/comments.h +2 -1
  32. data/include/prism/internal/node.h +8 -4
  33. data/include/prism/internal/parser.h +44 -13
  34. data/include/prism/internal/static_literals.h +24 -64
  35. data/include/prism/internal/stringy.h +1 -6
  36. data/include/prism/internal/xxh3.h +16 -0
  37. data/include/prism/json.h +8 -0
  38. data/include/prism/line_offset_list.h +8 -0
  39. data/include/prism/magic_comments.h +18 -0
  40. data/include/prism/node.h +55 -10
  41. data/include/prism/node.hpp +272 -0
  42. data/include/prism/node_type.hpp +38 -0
  43. data/include/prism/options.h +10 -1
  44. data/include/prism/options.hpp +43 -0
  45. data/include/prism/parser.h +93 -64
  46. data/include/prism/parser.hpp +274 -0
  47. data/include/prism/prettyprint.h +8 -0
  48. data/include/prism/serialize.h +8 -0
  49. data/include/prism/source.h +8 -0
  50. data/include/prism/stream.h +8 -0
  51. data/include/prism/string_query.h +19 -0
  52. data/include/prism/stringy.h +16 -27
  53. data/include/prism/stringy.hpp +31 -0
  54. data/include/prism/version.h +10 -2
  55. data/include/prism.h +0 -8
  56. data/include/prism.hpp +24 -0
  57. data/lib/prism/3.3/prism.so +0 -0
  58. data/lib/prism/3.4/prism.so +0 -0
  59. data/lib/prism/4.0/prism.so +0 -0
  60. data/lib/prism/ffi.rb +6 -0
  61. data/lib/prism/node.rb +736 -0
  62. data/lib/prism/parse_result.rb +23 -8
  63. data/lib/prism/serialize.rb +2568 -3287
  64. data/lib/prism/string_query.rb +8 -0
  65. data/prism.gemspec +21 -4
  66. data/rbi/generated/prism/node.rbi +2430 -968
  67. data/rbi/generated/prism/parse_result.rbi +16 -4
  68. data/rbi/generated/prism/serialize.rbi +8 -4
  69. data/rbi/generated/prism/string_query.rbi +7 -0
  70. data/sig/generated/prism/node.rbs +2439 -967
  71. data/sig/generated/prism/parse_result.rbs +16 -4
  72. data/sig/generated/prism/serialize.rbs +9 -4
  73. data/sig/generated/prism/string_query.rbs +7 -0
  74. data/src/arena.c +6 -1
  75. data/src/buffer.c +9 -0
  76. data/src/comments.c +11 -10
  77. data/src/diagnostic.c +24 -4
  78. data/src/integer.c +6 -1
  79. data/src/node.c +216 -368
  80. data/src/options.c +7 -13
  81. data/src/parser.c +70 -48
  82. data/src/prism.c +625 -462
  83. data/src/regexp.c +0 -1
  84. data/src/serialize.c +2301 -1950
  85. data/src/source.c +8 -2
  86. data/src/static_literals.c +280 -405
  87. data/src/string_query.c +14 -0
  88. data/src/stringy.c +3 -33
  89. data/src/xxh3.c +292 -0
  90. metadata +20 -3
@@ -30,8 +30,11 @@ module Prism
30
30
  # empty when the source is created by the parser and filled in afterward,
31
31
  # because the comments themselves refer to the source.
32
32
  #
33
- # : (String source, Integer start_line, Array[Integer] offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges) -> Source
34
- def self.for: (String source, Integer start_line, Array[Integer] offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges) -> Source
33
+ # The checksum parameter is the value described by the attribute of the same
34
+ # name. It is nil when the source is not created by the parser.
35
+ #
36
+ # : (String source, Integer start_line, Array[Integer] offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges, ?Integer? checksum) -> Source
37
+ def self.for: (String source, Integer start_line, Array[Integer] offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges, ?Integer? checksum) -> Source
35
38
 
36
39
  # The source code that this source object represents.
37
40
  attr_reader source: String
@@ -39,6 +42,10 @@ module Prism
39
42
  # The line number where this source starts.
40
43
  attr_reader start_line: Integer
41
44
 
45
+ # The checksum of the source code which can be used to quickly determine if
46
+ # the source has changed.
47
+ attr_reader checksum: Integer?
48
+
42
49
  # The list of comments that were encountered during parsing. When the source
43
50
  # is parsed with the attach_comments option, these are sorted by start
44
51
  # offset.
@@ -66,14 +73,19 @@ module Prism
66
73
  # parameter can be either an Array of Integer byte offsets or a packed
67
74
  # binary string of uint32_t values (from the C extension).
68
75
  #
69
- # : (String source, Integer start_line, Array[Integer] | String offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges) -> void
70
- def initialize: (String source, Integer start_line, Array[Integer] | String offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges) -> void
76
+ # : (String source, Integer start_line, Array[Integer] | String offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges, ?Integer? checksum) -> void
77
+ def initialize: (String source, Integer start_line, Array[Integer] | String offsets, ?Array[Comment] comments, ?Array[Comment] comment_attachments, ?Array[Integer?] comment_ranges, ?Integer? checksum) -> void
71
78
 
72
79
  # Replace the value of start_line with the given value.
73
80
  #
74
81
  # : (Integer start_line) -> void
75
82
  def replace_start_line: (Integer start_line) -> void
76
83
 
84
+ # Replace the value of checksum with the given value.
85
+ #
86
+ # : (Integer checksum) -> void
87
+ def replace_checksum: (Integer checksum) -> void
88
+
77
89
  # Replace the value of offsets with the given value.
78
90
  #
79
91
  # : (Array[Integer] offsets) -> void
@@ -149,8 +149,8 @@ module Prism
149
149
  # : () -> Integer
150
150
  def load_uint32: () -> Integer
151
151
 
152
- # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node?
153
- def load_optional_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node?
152
+ # : () -> Integer
153
+ def load_uint64: () -> Integer
154
154
 
155
155
  # : (Encoding encoding) -> String
156
156
  def load_string: (Encoding encoding) -> String
@@ -181,8 +181,13 @@ module Prism
181
181
  # : (ConstantPool constant_pool, Encoding encoding) -> Symbol?
182
182
  def load_optional_constant: (ConstantPool constant_pool, Encoding encoding) -> Symbol?
183
183
 
184
- # : (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node
185
- def load_node: (ConstantPool constant_pool, Encoding encoding, bool freeze) -> node
184
+ # Load the nodes that are serialized before the given offset and return
185
+ # the root. Nodes are serialized in post-order, so the children of each
186
+ # node are the topmost values on the stack, in field order, by the time
187
+ # its record is read.
188
+ #
189
+ # : (ConstantPool constant_pool, Encoding encoding, bool freeze, Integer finish) -> node
190
+ def load_nodes: (ConstantPool constant_pool, Encoding encoding, bool freeze, Integer finish) -> node
186
191
 
187
192
  @load_node_lambdas: Array[Proc]
188
193
 
@@ -10,6 +10,8 @@ module Prism
10
10
 
11
11
  def self.method_name?: (String string) -> bool
12
12
 
13
+ def self.keyword?: (String string) -> bool
14
+
13
15
  # The string that this query is wrapping.
14
16
  attr_reader string: String
15
17
 
@@ -32,5 +34,10 @@ module Prism
32
34
  #
33
35
  # : () -> bool
34
36
  def method_name?: () -> bool
37
+
38
+ # Whether or not this string is a valid keyword.
39
+ #
40
+ # : () -> bool
41
+ def keyword?: () -> bool
35
42
  end
36
43
  end
data/src/arena.c CHANGED
@@ -12,8 +12,13 @@
12
12
  */
13
13
  #define PM_ARENA_BLOCK_SIZE(data_size) (offsetof(pm_arena_block_t, data) + (data_size))
14
14
 
15
- /** Initial block data size: 8 KB. */
15
+ /**
16
+ * Initial block data size: 8 KB. An embedder on a small heap can define a
17
+ * smaller one; a parse of a short program then takes blocks of that size.
18
+ */
19
+ #ifndef PM_ARENA_INITIAL_SIZE
16
20
  #define PM_ARENA_INITIAL_SIZE 8192
21
+ #endif
17
22
 
18
23
  /** Double the block size every this many blocks. */
19
24
  #define PM_ARENA_GROWTH_INTERVAL 8
data/src/buffer.c CHANGED
@@ -186,6 +186,15 @@ pm_buffer_append_double(pm_buffer_t *buffer, double value) {
186
186
  pm_buffer_append(buffer, source, sizeof(double));
187
187
  }
188
188
 
189
+ /**
190
+ * Append a 64-bit unsigned integer to the buffer in native endian order.
191
+ */
192
+ void
193
+ pm_buffer_append_uint64(pm_buffer_t *buffer, uint64_t value) {
194
+ const void *source = &value;
195
+ pm_buffer_append(buffer, source, sizeof(uint64_t));
196
+ }
197
+
189
198
  /**
190
199
  * Append a unicode codepoint to the buffer.
191
200
  */
data/src/comments.c CHANGED
@@ -11,7 +11,10 @@
11
11
 
12
12
  /* The state used while walking the tree to find the owner of each comment. */
13
13
  typedef struct {
14
- /* The arena for memory that is only needed during the walk. */
14
+ /*
15
+ * The arena for memory that is only needed during the walk, which is the
16
+ * scratch arena of the parser.
17
+ */
15
18
  pm_arena_t *arena;
16
19
 
17
20
  /* The start of the source that was parsed. */
@@ -223,7 +226,7 @@ pm_comments_blank_after(const pm_comments_walk_t *walk, uint32_t offset, uint32_
223
226
  * descends itself, so that it can visit children in source order and handle
224
227
  * each node after all of its descendants.
225
228
  */
226
- static bool
229
+ static pm_visit_result_t
227
230
  pm_comments_push(const pm_node_t *node, void *data) {
228
231
  pm_comments_walk_t *walk = (pm_comments_walk_t *) data;
229
232
 
@@ -237,7 +240,7 @@ pm_comments_push(const pm_node_t *node, void *data) {
237
240
  }
238
241
 
239
242
  walk->stack.nodes[walk->stack.size++] = node;
240
- return false;
243
+ return PM_VISIT_SKIP;
241
244
  }
242
245
 
243
246
  /*
@@ -389,15 +392,15 @@ pm_comments_attach(pm_parser_t *parser, const pm_node_t *root) {
389
392
  uint32_t size = (uint32_t) parser->comment_list.size;
390
393
  if (size == 0) return;
391
394
 
392
- pm_arena_t arena = { 0 };
395
+ pm_arena_t *arena = &parser->scratch_arena;
393
396
  pm_comments_walk_t walk = {
394
- .arena = &arena,
397
+ .arena = arena,
395
398
  .source = parser->start,
396
399
  .comments = pm_comments_sort(parser, size),
397
400
  .size = size,
398
- .starts = (uint32_t *) pm_arena_alloc(&arena, sizeof(uint32_t) * size, PRISM_ALIGNOF(uint32_t)),
399
- .attached = (const pm_node_t **) pm_arena_zalloc(&arena, sizeof(pm_node_t *) * size, PRISM_ALIGNOF(pm_node_t *)),
400
- .unclaimed = (uint32_t *) pm_arena_alloc(&arena, sizeof(uint32_t) * (size + 1), PRISM_ALIGNOF(uint32_t))
401
+ .starts = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * size, PRISM_ALIGNOF(uint32_t)),
402
+ .attached = (const pm_node_t **) pm_arena_zalloc(arena, sizeof(pm_node_t *) * size, PRISM_ALIGNOF(pm_node_t *)),
403
+ .unclaimed = (uint32_t *) pm_arena_alloc(arena, sizeof(uint32_t) * (size + 1), PRISM_ALIGNOF(uint32_t))
401
404
  };
402
405
 
403
406
  for (uint32_t index = 0; index < size; index++) walk.starts[index] = walk.comments[index]->location.start;
@@ -443,8 +446,6 @@ pm_comments_attach(pm_parser_t *parser, const pm_node_t *root) {
443
446
  attachments[range->index + range->length++] = index;
444
447
  }
445
448
 
446
- pm_arena_cleanup(&arena);
447
-
448
449
  parser->comment_attachments = (pm_comment_attachments_t) {
449
450
  .comments = walk.comments,
450
451
  .attachments = attachments,
data/src/diagnostic.c CHANGED
@@ -20,6 +20,7 @@
20
20
  #include <stdarg.h>
21
21
  #include <stdio.h>
22
22
  #include <stdlib.h>
23
+ #include <string.h>
23
24
 
24
25
  #define PM_DIAGNOSTIC_ID_MAX 327
25
26
 
@@ -832,6 +833,14 @@ pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic) {
832
833
  return (pm_warning_level_t) pm_diagnostic_id_level(diagnostic->diag_id);
833
834
  }
834
835
 
836
+ /**
837
+ * Get the diagnostic that follows the given diagnostic.
838
+ */
839
+ const pm_diagnostic_t *
840
+ pm_diagnostic_next(const pm_diagnostic_t *diagnostic) {
841
+ return (const pm_diagnostic_t *) diagnostic->node.next;
842
+ }
843
+
835
844
  /**
836
845
  * Append an error to the given list of diagnostic.
837
846
  */
@@ -855,11 +864,16 @@ pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, ui
855
864
  */
856
865
  void
857
866
  pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...) {
867
+ /* Format the message into a buffer on the stack, which nearly every message
868
+ * fits in. The result is the length of the whole message whether or not it
869
+ * fit, so a single pass both formats the message and sizes it. */
870
+ char stack[256];
871
+
858
872
  va_list arguments;
859
873
  va_start(arguments, diag_id);
860
874
 
861
875
  const char *format = pm_diagnostic_id_message(diag_id);
862
- int result = vsnprintf(NULL, 0, format, arguments);
876
+ int result = vsnprintf(stack, sizeof(stack), format, arguments);
863
877
  va_end(arguments);
864
878
 
865
879
  if (result < 0) {
@@ -871,9 +885,15 @@ pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t st
871
885
  size_t message_length = (size_t) (result + 1);
872
886
  char *message = (char *) pm_arena_alloc(arena, message_length, 1);
873
887
 
874
- va_start(arguments, diag_id);
875
- vsnprintf(message, message_length, format, arguments);
876
- va_end(arguments);
888
+ if (message_length <= sizeof(stack)) {
889
+ memcpy(message, stack, message_length);
890
+ } else {
891
+ /* The message was cut off on the stack, so format it again into an
892
+ * allocation of the right size. */
893
+ va_start(arguments, diag_id);
894
+ vsnprintf(message, message_length, format, arguments);
895
+ va_end(arguments);
896
+ }
877
897
 
878
898
  *diagnostic = (pm_diagnostic_t) {
879
899
  .location = { .start = start, .length = length },
data/src/integer.c CHANGED
@@ -3,8 +3,13 @@
3
3
  #include "prism/internal/allocator.h"
4
4
  #include "prism/internal/buffer.h"
5
5
 
6
- #include <assert.h>
6
+ /* Include sys/types.h before inttypes.h to work around an issue with certain
7
+ * versions of GCC and newlib which causes omission of PRIu64 and the other
8
+ * 64-bit macros. */
9
+ #include <sys/types.h>
7
10
  #include <inttypes.h>
11
+
12
+ #include <assert.h>
8
13
  #include <stdbool.h>
9
14
  #include <stddef.h>
10
15
  #include <stdlib.h>