prism 0.29.0 → 0.30.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -1
  3. data/CONTRIBUTING.md +0 -4
  4. data/README.md +1 -0
  5. data/config.yml +66 -9
  6. data/docs/fuzzing.md +1 -1
  7. data/docs/ripper_translation.md +22 -0
  8. data/ext/prism/api_node.c +30 -12
  9. data/ext/prism/extension.c +107 -372
  10. data/ext/prism/extension.h +1 -1
  11. data/include/prism/ast.h +138 -70
  12. data/include/prism/diagnostic.h +7 -2
  13. data/include/prism/node.h +0 -21
  14. data/include/prism/parser.h +23 -25
  15. data/include/prism/regexp.h +17 -8
  16. data/include/prism/static_literals.h +3 -2
  17. data/include/prism/util/pm_char.h +1 -2
  18. data/include/prism/util/pm_constant_pool.h +0 -8
  19. data/include/prism/util/pm_integer.h +16 -9
  20. data/include/prism/util/pm_string.h +0 -8
  21. data/include/prism/version.h +2 -2
  22. data/include/prism.h +0 -11
  23. data/lib/prism/compiler.rb +3 -0
  24. data/lib/prism/dispatcher.rb +14 -0
  25. data/lib/prism/dot_visitor.rb +22 -3
  26. data/lib/prism/dsl.rb +7 -2
  27. data/lib/prism/ffi.rb +24 -3
  28. data/lib/prism/inspect_visitor.rb +10 -8
  29. data/lib/prism/mutation_compiler.rb +6 -1
  30. data/lib/prism/node.rb +166 -241
  31. data/lib/prism/node_ext.rb +21 -5
  32. data/lib/prism/parse_result/comments.rb +0 -7
  33. data/lib/prism/parse_result/newlines.rb +101 -11
  34. data/lib/prism/parse_result.rb +17 -0
  35. data/lib/prism/reflection.rb +3 -1
  36. data/lib/prism/serialize.rb +80 -67
  37. data/lib/prism/translation/parser/compiler.rb +134 -114
  38. data/lib/prism/translation/parser.rb +6 -1
  39. data/lib/prism/translation/ripper.rb +8 -6
  40. data/lib/prism/translation/ruby_parser.rb +23 -5
  41. data/lib/prism/visitor.rb +3 -0
  42. data/lib/prism.rb +0 -4
  43. data/prism.gemspec +1 -4
  44. data/rbi/prism/node.rbi +63 -6
  45. data/rbi/prism/visitor.rbi +3 -0
  46. data/rbi/prism.rbi +6 -0
  47. data/sig/prism/dsl.rbs +4 -1
  48. data/sig/prism/mutation_compiler.rbs +1 -0
  49. data/sig/prism/node.rbs +28 -4
  50. data/sig/prism/visitor.rbs +1 -0
  51. data/sig/prism.rbs +21 -0
  52. data/src/diagnostic.c +27 -17
  53. data/src/node.c +408 -1666
  54. data/src/prettyprint.c +49 -6
  55. data/src/prism.c +958 -991
  56. data/src/regexp.c +133 -68
  57. data/src/serialize.c +6 -1
  58. data/src/static_literals.c +63 -84
  59. data/src/token_type.c +2 -2
  60. data/src/util/pm_constant_pool.c +0 -8
  61. data/src/util/pm_integer.c +39 -11
  62. data/src/util/pm_string.c +0 -12
  63. data/src/util/pm_strpbrk.c +32 -6
  64. metadata +2 -5
  65. data/include/prism/util/pm_string_list.h +0 -44
  66. data/lib/prism/debug.rb +0 -249
  67. data/src/util/pm_string_list.c +0 -28
data/src/token_type.c CHANGED
@@ -362,7 +362,7 @@ const char *
362
362
  pm_token_type_human(pm_token_type_t token_type) {
363
363
  switch (token_type) {
364
364
  case PM_TOKEN_EOF:
365
- return "end of file";
365
+ return "end-of-input";
366
366
  case PM_TOKEN_MISSING:
367
367
  return "missing token";
368
368
  case PM_TOKEN_NOT_PROVIDED:
@@ -684,7 +684,7 @@ pm_token_type_human(pm_token_type_t token_type) {
684
684
  case PM_TOKEN_USTAR:
685
685
  return "*";
686
686
  case PM_TOKEN_USTAR_STAR:
687
- return "'**'";
687
+ return "**";
688
688
  case PM_TOKEN_WORDS_SEP:
689
689
  return "string separator";
690
690
  case PM_TOKEN___END__:
@@ -61,14 +61,6 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) {
61
61
  return false;
62
62
  }
63
63
 
64
- /**
65
- * Get the memory size of a list of constant ids.
66
- */
67
- size_t
68
- pm_constant_id_list_memsize(pm_constant_id_list_t *list) {
69
- return sizeof(pm_constant_id_list_t) + (list->capacity * sizeof(pm_constant_id_t));
70
- }
71
-
72
64
  /**
73
65
  * Free the memory associated with a list of constant ids.
74
66
  */
@@ -48,7 +48,7 @@ big_add(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *right, uint
48
48
 
49
49
  /**
50
50
  * Internal use for karatsuba_multiply. Calculates `a - b - c` with the given
51
- * base. Assume a, b, c, a - b - c all to be poitive.
51
+ * base. Assume a, b, c, a - b - c all to be positive.
52
52
  * Return pm_integer_t with values allocated. Not normalized.
53
53
  */
54
54
  static void
@@ -471,15 +471,18 @@ pm_integer_parse_big(pm_integer_t *integer, uint32_t multiplier, const uint8_t *
471
471
  * has already been validated, as internal validation checks are not performed
472
472
  * here.
473
473
  */
474
- PRISM_EXPORTED_FUNCTION void
474
+ void
475
475
  pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *start, const uint8_t *end) {
476
- // Ignore unary +. Unary + is parsed differently and will not end up here.
476
+ // Ignore unary +. Unary - is parsed differently and will not end up here.
477
477
  // Instead, it will modify the parsed integer later.
478
478
  if (*start == '+') start++;
479
479
 
480
480
  // Determine the multiplier from the base, and skip past any prefixes.
481
481
  uint32_t multiplier = 10;
482
482
  switch (base) {
483
+ case PM_INTEGER_BASE_DEFAULT:
484
+ while (*start == '0') start++; // 01 -> 1
485
+ break;
483
486
  case PM_INTEGER_BASE_BINARY:
484
487
  start += 2; // 0b
485
488
  multiplier = 2;
@@ -533,14 +536,6 @@ pm_integer_parse(pm_integer_t *integer, pm_integer_base_t base, const uint8_t *s
533
536
  integer->value = (uint32_t) value;
534
537
  }
535
538
 
536
- /**
537
- * Return the memory size of the integer.
538
- */
539
- size_t
540
- pm_integer_memsize(const pm_integer_t *integer) {
541
- return sizeof(pm_integer_t) + integer->length * sizeof(uint32_t);
542
- }
543
-
544
539
  /**
545
540
  * Compare two integers. This function returns -1 if the left integer is less
546
541
  * than the right integer, 0 if they are equal, and 1 if the left integer is
@@ -572,6 +567,39 @@ pm_integer_compare(const pm_integer_t *left, const pm_integer_t *right) {
572
567
  return 0;
573
568
  }
574
569
 
570
+ /**
571
+ * Reduce a ratio of integers to its simplest form.
572
+ */
573
+ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator) {
574
+ // If either the numerator or denominator do not fit into a 32-bit integer,
575
+ // then this function is a no-op. In the future, we may consider reducing
576
+ // even the larger numbers, but for now we're going to keep it simple.
577
+ if (
578
+ // If the numerator doesn't fit into a 32-bit integer, return early.
579
+ numerator->length != 0 ||
580
+ // If the denominator doesn't fit into a 32-bit integer, return early.
581
+ denominator->length != 0 ||
582
+ // If the numerator is 0, then return early.
583
+ numerator->value == 0 ||
584
+ // If the denominator is 1, then return early.
585
+ denominator->value == 1
586
+ ) return;
587
+
588
+ // Find the greatest common divisor of the numerator and denominator.
589
+ uint32_t divisor = numerator->value;
590
+ uint32_t remainder = denominator->value;
591
+
592
+ while (remainder != 0) {
593
+ uint32_t temporary = remainder;
594
+ remainder = divisor % remainder;
595
+ divisor = temporary;
596
+ }
597
+
598
+ // Divide the numerator and denominator by the greatest common divisor.
599
+ numerator->value /= divisor;
600
+ denominator->value /= divisor;
601
+ }
602
+
575
603
  /**
576
604
  * Convert an integer to a decimal string.
577
605
  */
data/src/util/pm_string.c CHANGED
@@ -245,18 +245,6 @@ pm_string_file_init(pm_string_t *string, const char *filepath) {
245
245
  #endif
246
246
  }
247
247
 
248
- /**
249
- * Returns the memory size associated with the string.
250
- */
251
- size_t
252
- pm_string_memsize(const pm_string_t *string) {
253
- size_t size = sizeof(pm_string_t);
254
- if (string->type == PM_STRING_OWNED) {
255
- size += string->length;
256
- }
257
- return size;
258
- }
259
-
260
248
  /**
261
249
  * Ensure the string is owned. If it is not, then reinitialize it as owned and
262
250
  * copy over the previous source.
@@ -8,6 +8,27 @@ pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, const uint8_t *start
8
8
  pm_diagnostic_list_append_format(&parser->error_list, start, end, PM_ERR_INVALID_MULTIBYTE_CHARACTER, *start);
9
9
  }
10
10
 
11
+ /**
12
+ * Set the explicit encoding for the parser to the current encoding.
13
+ */
14
+ static inline void
15
+ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, const uint8_t *source, size_t width) {
16
+ if (parser->explicit_encoding != NULL) {
17
+ if (parser->explicit_encoding == parser->encoding) {
18
+ // Okay, we already locked to this encoding.
19
+ } else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) {
20
+ // Not okay, we already found a Unicode escape sequence and this
21
+ // conflicts.
22
+ pm_diagnostic_list_append_format(&parser->error_list, source, source + width, PM_ERR_MIXED_ENCODING, parser->encoding->name);
23
+ } else {
24
+ // Should not be anything else.
25
+ assert(false && "unreachable");
26
+ }
27
+ }
28
+
29
+ parser->explicit_encoding = parser->encoding;
30
+ }
31
+
11
32
  /**
12
33
  * This is the default path.
13
34
  */
@@ -52,7 +73,7 @@ pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *chars
52
73
  * This is the path when the encoding is ASCII-8BIT.
53
74
  */
54
75
  static inline const uint8_t *
55
- pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maximum) {
76
+ pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
56
77
  size_t index = 0;
57
78
 
58
79
  while (index < maximum) {
@@ -60,6 +81,7 @@ pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maxi
60
81
  return source + index;
61
82
  }
62
83
 
84
+ if (validate && source[index] >= 0x80) pm_strpbrk_explicit_encoding_set(parser, source, 1);
63
85
  index++;
64
86
  }
65
87
 
@@ -72,6 +94,7 @@ pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maxi
72
94
  static inline const uint8_t *
73
95
  pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
74
96
  size_t index = 0;
97
+ const pm_encoding_t *encoding = parser->encoding;
75
98
 
76
99
  while (index < maximum) {
77
100
  if (strchr((const char *) charset, source[index]) != NULL) {
@@ -81,7 +104,8 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t
81
104
  if (source[index] < 0x80) {
82
105
  index++;
83
106
  } else {
84
- size_t width = parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
107
+ size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
108
+ if (validate) pm_strpbrk_explicit_encoding_set(parser, source, width);
85
109
 
86
110
  if (width > 0) {
87
111
  index += width;
@@ -96,7 +120,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t
96
120
 
97
121
  do {
98
122
  index++;
99
- } while (index < maximum && parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
123
+ } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
100
124
 
101
125
  pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
102
126
  }
@@ -113,6 +137,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t
113
137
  static inline const uint8_t *
114
138
  pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
115
139
  size_t index = 0;
140
+ const pm_encoding_t *encoding = parser->encoding;
116
141
 
117
142
  while (index < maximum) {
118
143
  if (strchr((const char *) charset, source[index]) != NULL) {
@@ -122,7 +147,8 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t
122
147
  if (source[index] < 0x80 || !validate) {
123
148
  index++;
124
149
  } else {
125
- size_t width = parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
150
+ size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
151
+ pm_strpbrk_explicit_encoding_set(parser, source, width);
126
152
 
127
153
  if (width > 0) {
128
154
  index += width;
@@ -135,7 +161,7 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t
135
161
 
136
162
  do {
137
163
  index++;
138
- } while (index < maximum && parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
164
+ } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
139
165
 
140
166
  pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
141
167
  }
@@ -171,7 +197,7 @@ pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, p
171
197
  } else if (!parser->encoding_changed) {
172
198
  return pm_strpbrk_utf8(parser, source, charset, (size_t) length, validate);
173
199
  } else if (parser->encoding == PM_ENCODING_ASCII_8BIT_ENTRY) {
174
- return pm_strpbrk_ascii_8bit(source, charset, (size_t) length);
200
+ return pm_strpbrk_ascii_8bit(parser, source, charset, (size_t) length, validate);
175
201
  } else if (parser->encoding->multibyte) {
176
202
  return pm_strpbrk_multi_byte(parser, source, charset, (size_t) length, validate);
177
203
  } else {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.0
4
+ version: 0.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-10 00:00:00.000000000 Z
11
+ date: 2024-06-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -69,13 +69,11 @@ files:
69
69
  - include/prism/util/pm_memchr.h
70
70
  - include/prism/util/pm_newline_list.h
71
71
  - include/prism/util/pm_string.h
72
- - include/prism/util/pm_string_list.h
73
72
  - include/prism/util/pm_strncasecmp.h
74
73
  - include/prism/util/pm_strpbrk.h
75
74
  - include/prism/version.h
76
75
  - lib/prism.rb
77
76
  - lib/prism/compiler.rb
78
- - lib/prism/debug.rb
79
77
  - lib/prism/desugar_compiler.rb
80
78
  - lib/prism/dispatcher.rb
81
79
  - lib/prism/dot_visitor.rb
@@ -155,7 +153,6 @@ files:
155
153
  - src/util/pm_memchr.c
156
154
  - src/util/pm_newline_list.c
157
155
  - src/util/pm_string.c
158
- - src/util/pm_string_list.c
159
156
  - src/util/pm_strncasecmp.c
160
157
  - src/util/pm_strpbrk.c
161
158
  homepage: https://github.com/ruby/prism
@@ -1,44 +0,0 @@
1
- /**
2
- * @file pm_string_list.h
3
- *
4
- * A list of strings.
5
- */
6
- #ifndef PRISM_STRING_LIST_H
7
- #define PRISM_STRING_LIST_H
8
-
9
- #include "prism/defines.h"
10
- #include "prism/util/pm_string.h"
11
-
12
- #include <stddef.h>
13
- #include <stdlib.h>
14
-
15
- /**
16
- * A list of strings.
17
- */
18
- typedef struct {
19
- /** The length of the string list. */
20
- size_t length;
21
-
22
- /** The capacity of the string list that has been allocated. */
23
- size_t capacity;
24
-
25
- /** A pointer to the start of the string list. */
26
- pm_string_t *strings;
27
- } pm_string_list_t;
28
-
29
- /**
30
- * Append a pm_string_t to the given string list.
31
- *
32
- * @param string_list The string list to append to.
33
- * @param string The string to append.
34
- */
35
- void pm_string_list_append(pm_string_list_t *string_list, pm_string_t *string);
36
-
37
- /**
38
- * Free the memory associated with the string list.
39
- *
40
- * @param string_list The string list to free.
41
- */
42
- PRISM_EXPORTED_FUNCTION void pm_string_list_free(pm_string_list_t *string_list);
43
-
44
- #endif
data/lib/prism/debug.rb DELETED
@@ -1,249 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Prism
4
- # This module is used for testing and debugging and is not meant to be used by
5
- # consumers of this library.
6
- module Debug
7
- # A wrapper around a RubyVM::InstructionSequence that provides a more
8
- # convenient interface for accessing parts of the iseq.
9
- class ISeq # :nodoc:
10
- attr_reader :parts
11
-
12
- def initialize(parts)
13
- @parts = parts
14
- end
15
-
16
- def type
17
- parts[0]
18
- end
19
-
20
- def local_table
21
- parts[10]
22
- end
23
-
24
- def instructions
25
- parts[13]
26
- end
27
-
28
- def each_child
29
- instructions.each do |instruction|
30
- # Only look at arrays. Other instructions are line numbers or
31
- # tracepoint events.
32
- next unless instruction.is_a?(Array)
33
-
34
- instruction.each do |opnd|
35
- # Only look at arrays. Other operands are literals.
36
- next unless opnd.is_a?(Array)
37
-
38
- # Only look at instruction sequences. Other operands are literals.
39
- next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat"
40
-
41
- yield ISeq.new(opnd)
42
- end
43
- end
44
- end
45
- end
46
-
47
- private_constant :ISeq
48
-
49
- # :call-seq:
50
- # Debug::cruby_locals(source) -> Array
51
- #
52
- # For the given source, compiles with CRuby and returns a list of all of the
53
- # sets of local variables that were encountered.
54
- def self.cruby_locals(source)
55
- verbose, $VERBOSE = $VERBOSE, nil
56
-
57
- begin
58
- locals = [] #: Array[Array[Symbol | Integer]]
59
- stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)]
60
-
61
- while (iseq = stack.pop)
62
- names = [*iseq.local_table]
63
- names.map!.with_index do |name, index|
64
- # When an anonymous local variable is present in the iseq's local
65
- # table, it is represented as the stack offset from the top.
66
- # However, when these are dumped to binary and read back in, they
67
- # are replaced with the symbol :#arg_rest. To consistently handle
68
- # this, we replace them here with their index.
69
- if name == :"#arg_rest"
70
- names.length - index + 1
71
- else
72
- name
73
- end
74
- end
75
-
76
- locals << names
77
- iseq.each_child { |child| stack << child }
78
- end
79
-
80
- locals
81
- ensure
82
- $VERBOSE = verbose
83
- end
84
- end
85
-
86
- # Used to hold the place of a local that will be in the local table but
87
- # cannot be accessed directly from the source code. For example, the
88
- # iteration variable in a for loop or the positional parameter on a method
89
- # definition that is destructured.
90
- AnonymousLocal = Object.new
91
- private_constant :AnonymousLocal
92
-
93
- # :call-seq:
94
- # Debug::prism_locals(source) -> Array
95
- #
96
- # For the given source, parses with prism and returns a list of all of the
97
- # sets of local variables that were encountered.
98
- def self.prism_locals(source)
99
- locals = [] #: Array[Array[Symbol | Integer]]
100
- stack = [Prism.parse(source).value] #: Array[Prism::node]
101
-
102
- while (node = stack.pop)
103
- case node
104
- when BlockNode, DefNode, LambdaNode
105
- names = node.locals
106
- params =
107
- if node.is_a?(DefNode)
108
- node.parameters
109
- elsif node.parameters.is_a?(NumberedParametersNode)
110
- nil
111
- else
112
- node.parameters&.parameters
113
- end
114
-
115
- # prism places parameters in the same order that they appear in the
116
- # source. CRuby places them in the order that they need to appear
117
- # according to their own internal calling convention. We mimic that
118
- # order here so that we can compare properly.
119
- if params
120
- sorted = [
121
- *params.requireds.map do |required|
122
- if required.is_a?(RequiredParameterNode)
123
- required.name
124
- else
125
- AnonymousLocal
126
- end
127
- end,
128
- *params.optionals.map(&:name),
129
- *((params.rest.name || :*) if params.rest && !params.rest.is_a?(ImplicitRestNode)),
130
- *params.posts.map do |post|
131
- if post.is_a?(RequiredParameterNode)
132
- post.name
133
- else
134
- AnonymousLocal
135
- end
136
- end,
137
- *params.keywords.grep(RequiredKeywordParameterNode).map(&:name),
138
- *params.keywords.grep(OptionalKeywordParameterNode).map(&:name),
139
- ]
140
-
141
- sorted << AnonymousLocal if params.keywords.any?
142
-
143
- if params.keyword_rest.is_a?(ForwardingParameterNode)
144
- sorted.push(:*, :**, :&, :"...")
145
- elsif params.keyword_rest.is_a?(KeywordRestParameterNode)
146
- sorted << (params.keyword_rest.name || :**)
147
- end
148
-
149
- # Recurse down the parameter tree to find any destructured
150
- # parameters and add them after the other parameters.
151
- param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse
152
- while (param = param_stack.pop)
153
- case param
154
- when MultiTargetNode
155
- param_stack.concat(param.rights.reverse)
156
- param_stack << param.rest if param.rest&.expression && !sorted.include?(param.rest.expression.name)
157
- param_stack.concat(param.lefts.reverse)
158
- when RequiredParameterNode
159
- sorted << param.name
160
- when SplatNode
161
- sorted << param.expression.name
162
- end
163
- end
164
-
165
- if params.block
166
- sorted << (params.block.name || :&)
167
- end
168
-
169
- names = sorted.concat(names - sorted)
170
- end
171
-
172
- names.map!.with_index do |name, index|
173
- if name == AnonymousLocal
174
- names.length - index + 1
175
- else
176
- name
177
- end
178
- end
179
-
180
- locals << names
181
- when ClassNode, ModuleNode, ProgramNode, SingletonClassNode
182
- locals << node.locals
183
- when ForNode
184
- locals << [2]
185
- when PostExecutionNode
186
- locals.push([], [])
187
- when InterpolatedRegularExpressionNode
188
- locals << [] if node.once?
189
- end
190
-
191
- stack.concat(node.compact_child_nodes)
192
- end
193
-
194
- locals
195
- end
196
-
197
- # :call-seq:
198
- # Debug::newlines(source) -> Array
199
- #
200
- # For the given source string, return the byte offsets of every newline in
201
- # the source.
202
- def self.newlines(source)
203
- Prism.parse(source).source.offsets
204
- end
205
-
206
- # A wrapping around prism's internal encoding data structures. This is used
207
- # for reflection and debugging purposes.
208
- class Encoding
209
- # The name of the encoding, that can be passed to Encoding.find.
210
- attr_reader :name
211
-
212
- # Initialize a new encoding with the given name and whether or not it is
213
- # a multibyte encoding.
214
- def initialize(name, multibyte)
215
- @name = name
216
- @multibyte = multibyte
217
- end
218
-
219
- # Whether or not the encoding is a multibyte encoding.
220
- def multibyte?
221
- @multibyte
222
- end
223
-
224
- # Returns the number of bytes of the first character in the source string,
225
- # if it is valid for the encoding. Otherwise, returns 0.
226
- def width(source)
227
- Encoding._width(name, source)
228
- end
229
-
230
- # Returns true if the first character in the source string is a valid
231
- # alphanumeric character for the encoding.
232
- def alnum?(source)
233
- Encoding._alnum?(name, source)
234
- end
235
-
236
- # Returns true if the first character in the source string is a valid
237
- # alphabetic character for the encoding.
238
- def alpha?(source)
239
- Encoding._alpha?(name, source)
240
- end
241
-
242
- # Returns true if the first character in the source string is a valid
243
- # uppercase character for the encoding.
244
- def upper?(source)
245
- Encoding._upper?(name, source)
246
- end
247
- end
248
- end
249
- end
@@ -1,28 +0,0 @@
1
- #include "prism/util/pm_string_list.h"
2
-
3
- /**
4
- * Append a pm_string_t to the given string list.
5
- */
6
- void
7
- pm_string_list_append(pm_string_list_t *string_list, pm_string_t *string) {
8
- if (string_list->length + 1 > string_list->capacity) {
9
- if (string_list->capacity == 0) {
10
- string_list->capacity = 1;
11
- } else {
12
- string_list->capacity *= 2;
13
- }
14
-
15
- string_list->strings = xrealloc(string_list->strings, string_list->capacity * sizeof(pm_string_t));
16
- if (string_list->strings == NULL) abort();
17
- }
18
-
19
- string_list->strings[string_list->length++] = *string;
20
- }
21
-
22
- /**
23
- * Free the memory associated with the string list
24
- */
25
- void
26
- pm_string_list_free(pm_string_list_t *string_list) {
27
- xfree(string_list->strings);
28
- }