prism 0.29.0 → 1.3.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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +115 -1
  3. data/CONTRIBUTING.md +0 -4
  4. data/Makefile +1 -1
  5. data/README.md +4 -0
  6. data/config.yml +920 -148
  7. data/docs/build_system.md +8 -11
  8. data/docs/fuzzing.md +1 -1
  9. data/docs/parsing_rules.md +4 -1
  10. data/docs/relocation.md +34 -0
  11. data/docs/ripper_translation.md +22 -0
  12. data/docs/serialization.md +3 -0
  13. data/ext/prism/api_node.c +2863 -2079
  14. data/ext/prism/extconf.rb +14 -37
  15. data/ext/prism/extension.c +241 -391
  16. data/ext/prism/extension.h +2 -2
  17. data/include/prism/ast.h +2156 -453
  18. data/include/prism/defines.h +58 -7
  19. data/include/prism/diagnostic.h +24 -6
  20. data/include/prism/node.h +0 -21
  21. data/include/prism/options.h +94 -3
  22. data/include/prism/parser.h +82 -40
  23. data/include/prism/regexp.h +18 -8
  24. data/include/prism/static_literals.h +3 -2
  25. data/include/prism/util/pm_char.h +1 -2
  26. data/include/prism/util/pm_constant_pool.h +0 -8
  27. data/include/prism/util/pm_integer.h +22 -15
  28. data/include/prism/util/pm_newline_list.h +11 -0
  29. data/include/prism/util/pm_string.h +28 -12
  30. data/include/prism/version.h +3 -3
  31. data/include/prism.h +47 -11
  32. data/lib/prism/compiler.rb +3 -0
  33. data/lib/prism/desugar_compiler.rb +111 -74
  34. data/lib/prism/dispatcher.rb +16 -1
  35. data/lib/prism/dot_visitor.rb +55 -34
  36. data/lib/prism/dsl.rb +660 -468
  37. data/lib/prism/ffi.rb +113 -8
  38. data/lib/prism/inspect_visitor.rb +296 -64
  39. data/lib/prism/lex_compat.rb +1 -1
  40. data/lib/prism/mutation_compiler.rb +11 -6
  41. data/lib/prism/node.rb +4262 -5023
  42. data/lib/prism/node_ext.rb +91 -14
  43. data/lib/prism/parse_result/comments.rb +0 -7
  44. data/lib/prism/parse_result/errors.rb +65 -0
  45. data/lib/prism/parse_result/newlines.rb +101 -11
  46. data/lib/prism/parse_result.rb +183 -6
  47. data/lib/prism/reflection.rb +12 -10
  48. data/lib/prism/relocation.rb +504 -0
  49. data/lib/prism/serialize.rb +496 -609
  50. data/lib/prism/string_query.rb +30 -0
  51. data/lib/prism/translation/parser/compiler.rb +185 -155
  52. data/lib/prism/translation/parser/lexer.rb +26 -4
  53. data/lib/prism/translation/parser.rb +9 -4
  54. data/lib/prism/translation/ripper.rb +23 -25
  55. data/lib/prism/translation/ruby_parser.rb +86 -17
  56. data/lib/prism/visitor.rb +3 -0
  57. data/lib/prism.rb +6 -8
  58. data/prism.gemspec +9 -5
  59. data/rbi/prism/dsl.rbi +521 -0
  60. data/rbi/prism/node.rbi +1115 -1120
  61. data/rbi/prism/parse_result.rbi +29 -0
  62. data/rbi/prism/string_query.rbi +12 -0
  63. data/rbi/prism/visitor.rbi +3 -0
  64. data/rbi/prism.rbi +36 -30
  65. data/sig/prism/dsl.rbs +190 -303
  66. data/sig/prism/mutation_compiler.rbs +1 -0
  67. data/sig/prism/node.rbs +678 -632
  68. data/sig/prism/parse_result.rbs +22 -0
  69. data/sig/prism/relocation.rbs +185 -0
  70. data/sig/prism/string_query.rbs +11 -0
  71. data/sig/prism/visitor.rbs +1 -0
  72. data/sig/prism.rbs +103 -64
  73. data/src/diagnostic.c +64 -28
  74. data/src/node.c +502 -1739
  75. data/src/options.c +76 -27
  76. data/src/prettyprint.c +188 -112
  77. data/src/prism.c +3376 -2293
  78. data/src/regexp.c +208 -71
  79. data/src/serialize.c +182 -50
  80. data/src/static_literals.c +64 -85
  81. data/src/token_type.c +4 -4
  82. data/src/util/pm_char.c +1 -1
  83. data/src/util/pm_constant_pool.c +0 -8
  84. data/src/util/pm_integer.c +53 -25
  85. data/src/util/pm_newline_list.c +29 -0
  86. data/src/util/pm_string.c +131 -80
  87. data/src/util/pm_strpbrk.c +32 -6
  88. metadata +11 -7
  89. data/include/prism/util/pm_string_list.h +0 -44
  90. data/lib/prism/debug.rb +0 -249
  91. data/lib/prism/translation/parser/rubocop.rb +0 -73
  92. data/src/util/pm_string_list.c +0 -28
@@ -21,38 +21,36 @@ VALUE rb_cPrismParseError;
21
21
  VALUE rb_cPrismParseWarning;
22
22
  VALUE rb_cPrismResult;
23
23
  VALUE rb_cPrismParseResult;
24
+ VALUE rb_cPrismLexResult;
24
25
  VALUE rb_cPrismParseLexResult;
26
+ VALUE rb_cPrismStringQuery;
25
27
 
26
28
  VALUE rb_cPrismDebugEncoding;
27
29
 
28
- ID rb_option_id_command_line;
29
- ID rb_option_id_encoding;
30
- ID rb_option_id_filepath;
31
- ID rb_option_id_frozen_string_literal;
32
- ID rb_option_id_line;
33
- ID rb_option_id_scopes;
34
- ID rb_option_id_version;
35
- ID rb_prism_source_id_for;
30
+ ID rb_id_option_command_line;
31
+ ID rb_id_option_encoding;
32
+ ID rb_id_option_filepath;
33
+ ID rb_id_option_frozen_string_literal;
34
+ ID rb_id_option_line;
35
+ ID rb_id_option_main_script;
36
+ ID rb_id_option_partial_script;
37
+ ID rb_id_option_scopes;
38
+ ID rb_id_option_version;
39
+ ID rb_id_source_for;
36
40
 
37
41
  /******************************************************************************/
38
42
  /* IO of Ruby code */
39
43
  /******************************************************************************/
40
44
 
41
45
  /**
42
- * Check if the given VALUE is a string. If it's nil, then return NULL. If it's
43
- * not a string, then raise a type error. Otherwise return the VALUE as a C
44
- * string.
46
+ * Check if the given VALUE is a string. If it's not a string, then raise a
47
+ * TypeError. Otherwise return the VALUE as a C string.
45
48
  */
46
49
  static const char *
47
50
  check_string(VALUE value) {
48
- // If the value is nil, then we don't need to do anything.
49
- if (NIL_P(value)) {
50
- return NULL;
51
- }
52
-
53
51
  // Check if the value is a string. If it's not, then raise a type error.
54
52
  if (!RB_TYPE_P(value, T_STRING)) {
55
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(value));
53
+ rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(value));
56
54
  }
57
55
 
58
56
  // Otherwise, return the value as a C string.
@@ -66,7 +64,7 @@ static void
66
64
  input_load_string(pm_string_t *input, VALUE string) {
67
65
  // Check if the string is a string. If it's not, then raise a type error.
68
66
  if (!RB_TYPE_P(string, T_STRING)) {
69
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected String)", rb_obj_class(string));
67
+ rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(string));
70
68
  }
71
69
 
72
70
  pm_string_constant_init(input, RSTRING_PTR(string), RSTRING_LEN(string));
@@ -135,15 +133,21 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
135
133
  pm_options_t *options = (pm_options_t *) argument;
136
134
  ID key_id = SYM2ID(key);
137
135
 
138
- if (key_id == rb_option_id_filepath) {
136
+ if (key_id == rb_id_option_filepath) {
139
137
  if (!NIL_P(value)) pm_options_filepath_set(options, check_string(value));
140
- } else if (key_id == rb_option_id_encoding) {
141
- if (!NIL_P(value)) pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
142
- } else if (key_id == rb_option_id_line) {
138
+ } else if (key_id == rb_id_option_encoding) {
139
+ if (!NIL_P(value)) {
140
+ if (value == Qfalse) {
141
+ pm_options_encoding_locked_set(options, true);
142
+ } else {
143
+ pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
144
+ }
145
+ }
146
+ } else if (key_id == rb_id_option_line) {
143
147
  if (!NIL_P(value)) pm_options_line_set(options, NUM2INT(value));
144
- } else if (key_id == rb_option_id_frozen_string_literal) {
148
+ } else if (key_id == rb_id_option_frozen_string_literal) {
145
149
  if (!NIL_P(value)) pm_options_frozen_string_literal_set(options, RTEST(value));
146
- } else if (key_id == rb_option_id_version) {
150
+ } else if (key_id == rb_id_option_version) {
147
151
  if (!NIL_P(value)) {
148
152
  const char *version = check_string(value);
149
153
 
@@ -151,9 +155,9 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
151
155
  rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
152
156
  }
153
157
  }
154
- } else if (key_id == rb_option_id_scopes) {
158
+ } else if (key_id == rb_id_option_scopes) {
155
159
  if (!NIL_P(value)) build_options_scopes(options, value);
156
- } else if (key_id == rb_option_id_command_line) {
160
+ } else if (key_id == rb_id_option_command_line) {
157
161
  if (!NIL_P(value)) {
158
162
  const char *string = check_string(value);
159
163
  uint8_t command_line = 0;
@@ -172,6 +176,10 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
172
176
 
173
177
  pm_options_command_line_set(options, command_line);
174
178
  }
179
+ } else if (key_id == rb_id_option_main_script) {
180
+ if (!NIL_P(value)) pm_options_main_script_set(options, RTEST(value));
181
+ } else if (key_id == rb_id_option_partial_script) {
182
+ if (!NIL_P(value)) pm_options_partial_script_set(options, RTEST(value));
175
183
  } else {
176
184
  rb_raise(rb_eArgError, "unknown keyword: %" PRIsVALUE, key);
177
185
  }
@@ -206,6 +214,7 @@ build_options(VALUE argument) {
206
214
  static void
207
215
  extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) {
208
216
  options->line = 1; // default
217
+
209
218
  if (!NIL_P(keywords)) {
210
219
  struct build_options_data data = { .options = options, .keywords = keywords };
211
220
  struct build_options_data *argument = &data;
@@ -246,27 +255,41 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options)
246
255
  * Read options for methods that look like (filepath, **options).
247
256
  */
248
257
  static void
249
- file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) {
258
+ file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, VALUE *encoded_filepath) {
250
259
  VALUE filepath;
251
260
  VALUE keywords;
252
261
  rb_scan_args(argc, argv, "1:", &filepath, &keywords);
253
262
 
254
263
  Check_Type(filepath, T_STRING);
264
+ *encoded_filepath = rb_str_encode_ospath(filepath);
265
+ extract_options(options, *encoded_filepath, keywords);
255
266
 
256
- extract_options(options, filepath, keywords);
257
-
258
- const char * string_source = (const char *) pm_string_source(&options->filepath);
267
+ const char *source = (const char *) pm_string_source(&options->filepath);
268
+ pm_string_init_result_t result;
259
269
 
260
- if (!pm_string_file_init(input, string_source)) {
261
- pm_options_free(options);
270
+ switch (result = pm_string_file_init(input, source)) {
271
+ case PM_STRING_INIT_SUCCESS:
272
+ break;
273
+ case PM_STRING_INIT_ERROR_GENERIC: {
274
+ pm_options_free(options);
262
275
 
263
276
  #ifdef _WIN32
264
- int e = rb_w32_map_errno(GetLastError());
277
+ int e = rb_w32_map_errno(GetLastError());
265
278
  #else
266
- int e = errno;
279
+ int e = errno;
267
280
  #endif
268
281
 
269
- rb_syserr_fail(e, string_source);
282
+ rb_syserr_fail(e, source);
283
+ break;
284
+ }
285
+ case PM_STRING_INIT_ERROR_DIRECTORY:
286
+ pm_options_free(options);
287
+ rb_syserr_fail(EISDIR, source);
288
+ break;
289
+ default:
290
+ pm_options_free(options);
291
+ rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source);
292
+ break;
270
293
  }
271
294
  }
272
295
 
@@ -344,7 +367,8 @@ dump_file(int argc, VALUE *argv, VALUE self) {
344
367
  pm_string_t input;
345
368
  pm_options_t options = { 0 };
346
369
 
347
- file_options(argc, argv, &input, &options);
370
+ VALUE encoded_filepath;
371
+ file_options(argc, argv, &input, &options, &encoded_filepath);
348
372
 
349
373
  VALUE value = dump_input(&input, &options);
350
374
  pm_string_free(&input);
@@ -364,7 +388,7 @@ dump_file(int argc, VALUE *argv, VALUE self) {
364
388
  */
365
389
  static VALUE
366
390
  parser_comments(pm_parser_t *parser, VALUE source) {
367
- VALUE comments = rb_ary_new();
391
+ VALUE comments = rb_ary_new_capa(parser->comment_list.size);
368
392
 
369
393
  for (pm_comment_t *comment = (pm_comment_t *) parser->comment_list.head; comment != NULL; comment = (pm_comment_t *) comment->node.next) {
370
394
  VALUE location_argv[] = {
@@ -386,7 +410,7 @@ parser_comments(pm_parser_t *parser, VALUE source) {
386
410
  */
387
411
  static VALUE
388
412
  parser_magic_comments(pm_parser_t *parser, VALUE source) {
389
- VALUE magic_comments = rb_ary_new();
413
+ VALUE magic_comments = rb_ary_new_capa(parser->magic_comment_list.size);
390
414
 
391
415
  for (pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) parser->magic_comment_list.head; magic_comment != NULL; magic_comment = (pm_magic_comment_t *) magic_comment->node.next) {
392
416
  VALUE key_loc_argv[] = {
@@ -436,7 +460,7 @@ parser_data_loc(const pm_parser_t *parser, VALUE source) {
436
460
  */
437
461
  static VALUE
438
462
  parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
439
- VALUE errors = rb_ary_new();
463
+ VALUE errors = rb_ary_new_capa(parser->error_list.size);
440
464
  pm_diagnostic_t *error;
441
465
 
442
466
  for (error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) {
@@ -479,7 +503,7 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
479
503
  */
480
504
  static VALUE
481
505
  parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
482
- VALUE warnings = rb_ary_new();
506
+ VALUE warnings = rb_ary_new_capa(parser->warning_list.size);
483
507
  pm_diagnostic_t *warning;
484
508
 
485
509
  for (warning = (pm_diagnostic_t *) parser->warning_list.head; warning != NULL; warning = (pm_diagnostic_t *) warning->node.next) {
@@ -556,9 +580,10 @@ static void
556
580
  parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) {
557
581
  parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data;
558
582
 
559
- VALUE yields = rb_ary_new_capa(2);
560
- rb_ary_push(yields, pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source));
561
- rb_ary_push(yields, INT2FIX(parser->lex_state));
583
+ VALUE yields = rb_assoc_new(
584
+ pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source),
585
+ INT2FIX(parser->lex_state)
586
+ );
562
587
 
563
588
  rb_ary_push(parse_lex_data->tokens, yields);
564
589
  }
@@ -599,8 +624,8 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
599
624
  pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback);
600
625
 
601
626
  VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input));
602
- VALUE offsets = rb_ary_new();
603
- VALUE source = rb_funcall(rb_cPrismSource, rb_prism_source_id_for, 3, source_string, LONG2NUM(parser.start_line), offsets);
627
+ VALUE offsets = rb_ary_new_capa(parser.newline_list.size);
628
+ VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets);
604
629
 
605
630
  parse_lex_data_t parse_lex_data = {
606
631
  .source = source,
@@ -628,16 +653,16 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
628
653
  rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index]));
629
654
  }
630
655
 
631
- VALUE value;
656
+ VALUE result;
632
657
  if (return_nodes) {
633
- value = rb_ary_new_capa(2);
658
+ VALUE value = rb_ary_new_capa(2);
634
659
  rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source));
635
660
  rb_ary_push(value, parse_lex_data.tokens);
661
+ result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source);
636
662
  } else {
637
- value = parse_lex_data.tokens;
663
+ result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source);
638
664
  }
639
665
 
640
- VALUE result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source);
641
666
  pm_node_destroy(&parser, node);
642
667
  pm_parser_free(&parser);
643
668
 
@@ -646,10 +671,10 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
646
671
 
647
672
  /**
648
673
  * call-seq:
649
- * Prism::lex(source, **options) -> Array
674
+ * Prism::lex(source, **options) -> LexResult
650
675
  *
651
- * Return an array of Token instances corresponding to the given string. For
652
- * supported options, see Prism::parse.
676
+ * Return a LexResult instance that contains an array of Token instances
677
+ * corresponding to the given string. For supported options, see Prism::parse.
653
678
  */
654
679
  static VALUE
655
680
  lex(int argc, VALUE *argv, VALUE self) {
@@ -666,17 +691,18 @@ lex(int argc, VALUE *argv, VALUE self) {
666
691
 
667
692
  /**
668
693
  * call-seq:
669
- * Prism::lex_file(filepath, **options) -> Array
694
+ * Prism::lex_file(filepath, **options) -> LexResult
670
695
  *
671
- * Return an array of Token instances corresponding to the given file. For
672
- * supported options, see Prism::parse.
696
+ * Return a LexResult instance that contains an array of Token instances
697
+ * corresponding to the given file. For supported options, see Prism::parse.
673
698
  */
674
699
  static VALUE
675
700
  lex_file(int argc, VALUE *argv, VALUE self) {
676
701
  pm_string_t input;
677
702
  pm_options_t options = { 0 };
678
703
 
679
- file_options(argc, argv, &input, &options);
704
+ VALUE encoded_filepath;
705
+ file_options(argc, argv, &input, &options, &encoded_filepath);
680
706
 
681
707
  VALUE value = parse_lex_input(&input, &options, false);
682
708
  pm_string_free(&input);
@@ -728,14 +754,27 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
728
754
  * has been set. This should be a boolean or nil.
729
755
  * * `line` - the line number that the parse starts on. This should be an
730
756
  * integer or nil. Note that this is 1-indexed.
757
+ * * `main_script` - a boolean indicating whether or not the source being parsed
758
+ * is the main script being run by the interpreter. This controls whether
759
+ * or not shebangs are parsed for additional flags and whether or not the
760
+ * parser will attempt to find a matching shebang if the first one does
761
+ * not contain the word "ruby".
762
+ * * `partial_script` - when the file being parsed is considered a "partial"
763
+ * script, jumps will not be marked as errors if they are not contained
764
+ * within loops/blocks. This is used in the case that you're parsing a
765
+ * script that you know will be embedded inside another script later, but
766
+ * you do not have that context yet. For example, when parsing an ERB
767
+ * template that will be evaluated inside another script.
731
768
  * * `scopes` - the locals that are in scope surrounding the code that is being
732
769
  * parsed. This should be an array of arrays of symbols or nil. Scopes are
733
770
  * ordered from the outermost scope to the innermost one.
734
771
  * * `version` - the version of Ruby syntax that prism should used to parse Ruby
735
772
  * code. By default prism assumes you want to parse with the latest version
736
773
  * of Ruby syntax (which you can trigger with `nil` or `"latest"`). You
737
- * may also restrict the syntax to a specific version of Ruby. The
738
- * supported values are `"3.3.0"` and `"3.4.0"`.
774
+ * may also restrict the syntax to a specific version of Ruby, e.g., with `"3.3.0"`.
775
+ * To parse with the same syntax version that the current Ruby is running
776
+ * use `version: RUBY_VERSION`. Raises ArgumentError if the version is not
777
+ * currently supported by Prism.
739
778
  */
740
779
  static VALUE
741
780
  parse(int argc, VALUE *argv, VALUE self) {
@@ -761,6 +800,85 @@ parse(int argc, VALUE *argv, VALUE self) {
761
800
  return value;
762
801
  }
763
802
 
803
+ /**
804
+ * call-seq:
805
+ * Prism::parse_file(filepath, **options) -> ParseResult
806
+ *
807
+ * Parse the given file and return a ParseResult instance. For supported
808
+ * options, see Prism::parse.
809
+ */
810
+ static VALUE
811
+ parse_file(int argc, VALUE *argv, VALUE self) {
812
+ pm_string_t input;
813
+ pm_options_t options = { 0 };
814
+
815
+ VALUE encoded_filepath;
816
+ file_options(argc, argv, &input, &options, &encoded_filepath);
817
+
818
+ VALUE value = parse_input(&input, &options);
819
+ pm_string_free(&input);
820
+ pm_options_free(&options);
821
+
822
+ return value;
823
+ }
824
+
825
+ /**
826
+ * Parse the given input and return nothing.
827
+ */
828
+ static void
829
+ profile_input(pm_string_t *input, const pm_options_t *options) {
830
+ pm_parser_t parser;
831
+ pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options);
832
+
833
+ pm_node_t *node = pm_parse(&parser);
834
+ pm_node_destroy(&parser, node);
835
+ pm_parser_free(&parser);
836
+ }
837
+
838
+ /**
839
+ * call-seq:
840
+ * Prism::profile(source, **options) -> nil
841
+ *
842
+ * Parse the given string and return nothing. This method is meant to allow
843
+ * profilers to avoid the overhead of reifying the AST to Ruby. For supported
844
+ * options, see Prism::parse.
845
+ */
846
+ static VALUE
847
+ profile(int argc, VALUE *argv, VALUE self) {
848
+ pm_string_t input;
849
+ pm_options_t options = { 0 };
850
+
851
+ string_options(argc, argv, &input, &options);
852
+ profile_input(&input, &options);
853
+ pm_string_free(&input);
854
+ pm_options_free(&options);
855
+
856
+ return Qnil;
857
+ }
858
+
859
+ /**
860
+ * call-seq:
861
+ * Prism::profile_file(filepath, **options) -> nil
862
+ *
863
+ * Parse the given file and return nothing. This method is meant to allow
864
+ * profilers to avoid the overhead of reifying the AST to Ruby. For supported
865
+ * options, see Prism::parse.
866
+ */
867
+ static VALUE
868
+ profile_file(int argc, VALUE *argv, VALUE self) {
869
+ pm_string_t input;
870
+ pm_options_t options = { 0 };
871
+
872
+ VALUE encoded_filepath;
873
+ file_options(argc, argv, &input, &options, &encoded_filepath);
874
+
875
+ profile_input(&input, &options);
876
+ pm_string_free(&input);
877
+ pm_options_free(&options);
878
+
879
+ return Qnil;
880
+ }
881
+
764
882
  /**
765
883
  * An implementation of fgets that is suitable for use with Ruby IO objects.
766
884
  */
@@ -773,8 +891,8 @@ parse_stream_fgets(char *string, int size, void *stream) {
773
891
  return NULL;
774
892
  }
775
893
 
776
- const char *cstr = StringValueCStr(line);
777
- size_t length = strlen(cstr);
894
+ const char *cstr = RSTRING_PTR(line);
895
+ long length = RSTRING_LEN(line);
778
896
 
779
897
  memcpy(string, cstr, length);
780
898
  string[length] = '\0';
@@ -815,27 +933,6 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
815
933
  return result;
816
934
  }
817
935
 
818
- /**
819
- * call-seq:
820
- * Prism::parse_file(filepath, **options) -> ParseResult
821
- *
822
- * Parse the given file and return a ParseResult instance. For supported
823
- * options, see Prism::parse.
824
- */
825
- static VALUE
826
- parse_file(int argc, VALUE *argv, VALUE self) {
827
- pm_string_t input;
828
- pm_options_t options = { 0 };
829
-
830
- file_options(argc, argv, &input, &options);
831
-
832
- VALUE value = parse_input(&input, &options);
833
- pm_string_free(&input);
834
- pm_options_free(&options);
835
-
836
- return value;
837
- }
838
-
839
936
  /**
840
937
  * Parse the given input and return an array of Comment objects.
841
938
  */
@@ -888,7 +985,8 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) {
888
985
  pm_string_t input;
889
986
  pm_options_t options = { 0 };
890
987
 
891
- file_options(argc, argv, &input, &options);
988
+ VALUE encoded_filepath;
989
+ file_options(argc, argv, &input, &options, &encoded_filepath);
892
990
 
893
991
  VALUE value = parse_input_comments(&input, &options);
894
992
  pm_string_free(&input);
@@ -899,9 +997,9 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) {
899
997
 
900
998
  /**
901
999
  * call-seq:
902
- * Prism::parse_lex(source, **options) -> ParseResult
1000
+ * Prism::parse_lex(source, **options) -> ParseLexResult
903
1001
  *
904
- * Parse the given string and return a ParseResult instance that contains a
1002
+ * Parse the given string and return a ParseLexResult instance that contains a
905
1003
  * 2-element array, where the first element is the AST and the second element is
906
1004
  * an array of Token instances.
907
1005
  *
@@ -926,9 +1024,9 @@ parse_lex(int argc, VALUE *argv, VALUE self) {
926
1024
 
927
1025
  /**
928
1026
  * call-seq:
929
- * Prism::parse_lex_file(filepath, **options) -> ParseResult
1027
+ * Prism::parse_lex_file(filepath, **options) -> ParseLexResult
930
1028
  *
931
- * Parse the given file and return a ParseResult instance that contains a
1029
+ * Parse the given file and return a ParseLexResult instance that contains a
932
1030
  * 2-element array, where the first element is the AST and the second element is
933
1031
  * an array of Token instances.
934
1032
  *
@@ -943,7 +1041,8 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) {
943
1041
  pm_string_t input;
944
1042
  pm_options_t options = { 0 };
945
1043
 
946
- file_options(argc, argv, &input, &options);
1044
+ VALUE encoded_filepath;
1045
+ file_options(argc, argv, &input, &options, &encoded_filepath);
947
1046
 
948
1047
  VALUE value = parse_lex_input(&input, &options, true);
949
1048
  pm_string_free(&input);
@@ -1013,7 +1112,8 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) {
1013
1112
  pm_string_t input;
1014
1113
  pm_options_t options = { 0 };
1015
1114
 
1016
- file_options(argc, argv, &input, &options);
1115
+ VALUE encoded_filepath;
1116
+ file_options(argc, argv, &input, &options, &encoded_filepath);
1017
1117
 
1018
1118
  VALUE result = parse_input_success_p(&input, &options);
1019
1119
  pm_string_free(&input);
@@ -1035,300 +1135,65 @@ parse_file_failure_p(int argc, VALUE *argv, VALUE self) {
1035
1135
  }
1036
1136
 
1037
1137
  /******************************************************************************/
1038
- /* Utility functions exposed to make testing easier */
1138
+ /* String query methods */
1039
1139
  /******************************************************************************/
1040
1140
 
1041
1141
  /**
1042
- * call-seq:
1043
- * Debug::named_captures(source) -> Array
1044
- *
1045
- * Returns an array of strings corresponding to the named capture groups in the
1046
- * given source string. If prism was unable to parse the regular expression,
1047
- * this function returns nil.
1048
- */
1049
- static VALUE
1050
- named_captures(VALUE self, VALUE source) {
1051
- pm_string_list_t string_list = { 0 };
1052
-
1053
- if (!pm_regexp_named_capture_group_names((const uint8_t *) RSTRING_PTR(source), RSTRING_LEN(source), &string_list, false, PM_ENCODING_UTF_8_ENTRY)) {
1054
- pm_string_list_free(&string_list);
1055
- return Qnil;
1056
- }
1057
-
1058
- VALUE names = rb_ary_new();
1059
- for (size_t index = 0; index < string_list.length; index++) {
1060
- const pm_string_t *string = &string_list.strings[index];
1061
- rb_ary_push(names, rb_str_new((const char *) pm_string_source(string), pm_string_length(string)));
1062
- }
1063
-
1064
- pm_string_list_free(&string_list);
1065
- return names;
1066
- }
1067
-
1068
- /**
1069
- * call-seq:
1070
- * Debug::integer_parse(source) -> [Integer, String]
1071
- *
1072
- * Parses the given source string and returns the integer it represents, as well
1073
- * as a decimal string representation.
1074
- */
1075
- static VALUE
1076
- integer_parse(VALUE self, VALUE source) {
1077
- const uint8_t *start = (const uint8_t *) RSTRING_PTR(source);
1078
- size_t length = RSTRING_LEN(source);
1079
-
1080
- pm_integer_t integer = { 0 };
1081
- pm_integer_parse(&integer, PM_INTEGER_BASE_UNKNOWN, start, start + length);
1082
-
1083
- pm_buffer_t buffer = { 0 };
1084
- pm_integer_string(&buffer, &integer);
1085
-
1086
- VALUE string = rb_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer));
1087
- pm_buffer_free(&buffer);
1088
-
1089
- VALUE result = rb_ary_new_capa(2);
1090
- rb_ary_push(result, pm_integer_new(&integer));
1091
- rb_ary_push(result, string);
1092
- pm_integer_free(&integer);
1093
-
1094
- return result;
1095
- }
1096
-
1097
- /**
1098
- * call-seq:
1099
- * Debug::memsize(source) -> { length: xx, memsize: xx, node_count: xx }
1100
- *
1101
- * Return a hash of information about the given source string's memory usage.
1102
- */
1103
- static VALUE
1104
- memsize(VALUE self, VALUE string) {
1105
- pm_parser_t parser;
1106
- size_t length = RSTRING_LEN(string);
1107
- pm_parser_init(&parser, (const uint8_t *) RSTRING_PTR(string), length, NULL);
1108
-
1109
- pm_node_t *node = pm_parse(&parser);
1110
- pm_memsize_t memsize;
1111
- pm_node_memsize(node, &memsize);
1112
-
1113
- pm_node_destroy(&parser, node);
1114
- pm_parser_free(&parser);
1115
-
1116
- VALUE result = rb_hash_new();
1117
- rb_hash_aset(result, ID2SYM(rb_intern("length")), INT2FIX(length));
1118
- rb_hash_aset(result, ID2SYM(rb_intern("memsize")), INT2FIX(memsize.memsize));
1119
- rb_hash_aset(result, ID2SYM(rb_intern("node_count")), INT2FIX(memsize.node_count));
1120
- return result;
1121
- }
1122
-
1123
- /**
1124
- * call-seq:
1125
- * Debug::profile_file(filepath) -> nil
1126
- *
1127
- * Parse the file, but do nothing with the result. This is used to profile the
1128
- * parser for memory and speed.
1142
+ * Process the result of a call to a string query method and return an
1143
+ * appropriate value.
1129
1144
  */
1130
1145
  static VALUE
1131
- profile_file(VALUE self, VALUE filepath) {
1132
- pm_string_t input;
1133
-
1134
- const char *checked = check_string(filepath);
1135
- Check_Type(filepath, T_STRING);
1136
-
1137
- if (!pm_string_mapped_init(&input, checked)) {
1138
- #ifdef _WIN32
1139
- int e = rb_w32_map_errno(GetLastError());
1140
- #else
1141
- int e = errno;
1142
- #endif
1143
-
1144
- rb_syserr_fail(e, checked);
1146
+ string_query(pm_string_query_t result) {
1147
+ switch (result) {
1148
+ case PM_STRING_QUERY_ERROR:
1149
+ rb_raise(rb_eArgError, "Invalid or non ascii-compatible encoding");
1150
+ return Qfalse;
1151
+ case PM_STRING_QUERY_FALSE:
1152
+ return Qfalse;
1153
+ case PM_STRING_QUERY_TRUE:
1154
+ return Qtrue;
1145
1155
  }
1146
-
1147
- pm_options_t options = { 0 };
1148
- pm_options_filepath_set(&options, checked);
1149
-
1150
- pm_parser_t parser;
1151
- pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
1152
-
1153
- pm_node_t *node = pm_parse(&parser);
1154
- pm_node_destroy(&parser, node);
1155
- pm_parser_free(&parser);
1156
- pm_options_free(&options);
1157
- pm_string_free(&input);
1158
-
1159
- return Qnil;
1156
+ return Qfalse;
1160
1157
  }
1161
1158
 
1162
- #ifndef PRISM_EXCLUDE_PRETTYPRINT
1163
-
1164
1159
  /**
1165
1160
  * call-seq:
1166
- * Debug::inspect_node(source) -> inspected
1161
+ * Prism::StringQuery::local?(string) -> bool
1167
1162
  *
1168
- * Inspect the AST that represents the given source using the prism pretty print
1169
- * as opposed to the Ruby implementation.
1163
+ * Returns true if the string constitutes a valid local variable name. Note that
1164
+ * this means the names that can be set through Binding#local_variable_set, not
1165
+ * necessarily the ones that can be set through a local variable assignment.
1170
1166
  */
1171
1167
  static VALUE
1172
- inspect_node(VALUE self, VALUE source) {
1173
- pm_string_t input;
1174
- input_load_string(&input, source);
1175
-
1176
- pm_parser_t parser;
1177
- pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL);
1178
-
1179
- pm_node_t *node = pm_parse(&parser);
1180
- pm_buffer_t buffer = { 0 };
1181
-
1182
- pm_prettyprint(&buffer, &parser, node);
1183
-
1184
- rb_encoding *encoding = rb_enc_find(parser.encoding->name);
1185
- VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
1186
-
1187
- pm_buffer_free(&buffer);
1188
- pm_node_destroy(&parser, node);
1189
- pm_parser_free(&parser);
1190
-
1191
- return string;
1168
+ string_query_local_p(VALUE self, VALUE string) {
1169
+ const uint8_t *source = (const uint8_t *) check_string(string);
1170
+ return string_query(pm_string_query_local(source, RSTRING_LEN(string), rb_enc_get(string)->name));
1192
1171
  }
1193
1172
 
1194
- #endif
1195
-
1196
1173
  /**
1197
1174
  * call-seq:
1198
- * Debug::format_errors(source, colorize) -> String
1175
+ * Prism::StringQuery::constant?(string) -> bool
1199
1176
  *
1200
- * Format the errors that are found when parsing the given source string.
1177
+ * Returns true if the string constitutes a valid constant name. Note that this
1178
+ * means the names that can be set through Module#const_set, not necessarily the
1179
+ * ones that can be set through a constant assignment.
1201
1180
  */
1202
1181
  static VALUE
1203
- format_errors(VALUE self, VALUE source, VALUE colorize) {
1204
- pm_string_t input;
1205
- input_load_string(&input, source);
1206
-
1207
- pm_parser_t parser;
1208
- pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL);
1209
-
1210
- pm_node_t *node = pm_parse(&parser);
1211
- pm_buffer_t buffer = { 0 };
1212
-
1213
- pm_parser_errors_format(&parser, &parser.error_list, &buffer, RTEST(colorize), true);
1214
-
1215
- rb_encoding *encoding = rb_enc_find(parser.encoding->name);
1216
- VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
1217
-
1218
- pm_buffer_free(&buffer);
1219
- pm_node_destroy(&parser, node);
1220
- pm_parser_free(&parser);
1221
- pm_string_free(&input);
1222
-
1223
- return result;
1182
+ string_query_constant_p(VALUE self, VALUE string) {
1183
+ const uint8_t *source = (const uint8_t *) check_string(string);
1184
+ return string_query(pm_string_query_constant(source, RSTRING_LEN(string), rb_enc_get(string)->name));
1224
1185
  }
1225
1186
 
1226
1187
  /**
1227
1188
  * call-seq:
1228
- * Debug::static_inspect(source) -> String
1229
- *
1230
- * Inspect the node as it would be inspected by the warnings used in static
1231
- * literal sets.
1232
- */
1233
- static VALUE
1234
- static_inspect(int argc, VALUE *argv, VALUE self) {
1235
- pm_string_t input;
1236
- pm_options_t options = { 0 };
1237
- string_options(argc, argv, &input, &options);
1238
-
1239
- pm_parser_t parser;
1240
- pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options);
1241
-
1242
- pm_node_t *program = pm_parse(&parser);
1243
- pm_node_t *node = ((pm_program_node_t *) program)->statements->body.nodes[0];
1244
-
1245
- pm_buffer_t buffer = { 0 };
1246
- pm_static_literal_inspect(&buffer, &parser.newline_list, parser.start_line, parser.encoding->name, node);
1247
-
1248
- rb_encoding *encoding = rb_enc_find(parser.encoding->name);
1249
- VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
1250
-
1251
- pm_buffer_free(&buffer);
1252
- pm_node_destroy(&parser, program);
1253
- pm_parser_free(&parser);
1254
- pm_string_free(&input);
1255
- pm_options_free(&options);
1256
-
1257
- return result;
1258
- }
1259
-
1260
- /**
1261
- * call-seq: Debug::Encoding.all -> Array[Debug::Encoding]
1189
+ * Prism::StringQuery::method_name?(string) -> bool
1262
1190
  *
1263
- * Return an array of all of the encodings that prism knows about.
1191
+ * Returns true if the string constitutes a valid method name.
1264
1192
  */
1265
1193
  static VALUE
1266
- encoding_all(VALUE self) {
1267
- VALUE encodings = rb_ary_new();
1268
-
1269
- for (size_t index = 0; index < PM_ENCODING_MAXIMUM; index++) {
1270
- const pm_encoding_t *encoding = &pm_encodings[index];
1271
-
1272
- VALUE encoding_argv[] = { rb_str_new_cstr(encoding->name), encoding->multibyte ? Qtrue : Qfalse };
1273
- rb_ary_push(encodings, rb_class_new_instance(2, encoding_argv, rb_cPrismDebugEncoding));
1274
- }
1275
-
1276
- return encodings;
1277
- }
1278
-
1279
- static const pm_encoding_t *
1280
- encoding_find(VALUE name) {
1281
- const uint8_t *source = (const uint8_t *) RSTRING_PTR(name);
1282
- size_t length = RSTRING_LEN(name);
1283
-
1284
- const pm_encoding_t *encoding = pm_encoding_find(source, source + length);
1285
- if (encoding == NULL) { rb_raise(rb_eArgError, "Unknown encoding: %s", source); }
1286
-
1287
- return encoding;
1288
- }
1289
-
1290
- /**
1291
- * call-seq: Debug::Encoding.width(source) -> Integer
1292
- *
1293
- * Returns the width of the first character in the given string if it is valid
1294
- * in the encoding. If it is not, this function returns 0.
1295
- */
1296
- static VALUE
1297
- encoding_char_width(VALUE self, VALUE name, VALUE value) {
1298
- return ULONG2NUM(encoding_find(name)->char_width((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)));
1299
- }
1300
-
1301
- /**
1302
- * call-seq: Debug::Encoding.alnum?(source) -> true | false
1303
- *
1304
- * Returns true if the first character in the given string is an alphanumeric
1305
- * character in the encoding.
1306
- */
1307
- static VALUE
1308
- encoding_alnum_char(VALUE self, VALUE name, VALUE value) {
1309
- return encoding_find(name)->alnum_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) > 0 ? Qtrue : Qfalse;
1310
- }
1311
-
1312
- /**
1313
- * call-seq: Debug::Encoding.alpha?(source) -> true | false
1314
- *
1315
- * Returns true if the first character in the given string is an alphabetic
1316
- * character in the encoding.
1317
- */
1318
- static VALUE
1319
- encoding_alpha_char(VALUE self, VALUE name, VALUE value) {
1320
- return encoding_find(name)->alpha_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) > 0 ? Qtrue : Qfalse;
1321
- }
1322
-
1323
- /**
1324
- * call-seq: Debug::Encoding.upper?(source) -> true | false
1325
- *
1326
- * Returns true if the first character in the given string is an uppercase
1327
- * character in the encoding.
1328
- */
1329
- static VALUE
1330
- encoding_isupper_char(VALUE self, VALUE name, VALUE value) {
1331
- return encoding_find(name)->isupper_char((const uint8_t *) RSTRING_PTR(value), RSTRING_LEN(value)) ? Qtrue : Qfalse;
1194
+ string_query_method_name_p(VALUE self, VALUE string) {
1195
+ const uint8_t *source = (const uint8_t *) check_string(string);
1196
+ return string_query(pm_string_query_method_name(source, RSTRING_LEN(string), rb_enc_get(string)->name));
1332
1197
  }
1333
1198
 
1334
1199
  /******************************************************************************/
@@ -1364,22 +1229,24 @@ Init_prism(void) {
1364
1229
  rb_cPrismMagicComment = rb_define_class_under(rb_cPrism, "MagicComment", rb_cObject);
1365
1230
  rb_cPrismParseError = rb_define_class_under(rb_cPrism, "ParseError", rb_cObject);
1366
1231
  rb_cPrismParseWarning = rb_define_class_under(rb_cPrism, "ParseWarning", rb_cObject);
1367
-
1368
1232
  rb_cPrismResult = rb_define_class_under(rb_cPrism, "Result", rb_cObject);
1369
1233
  rb_cPrismParseResult = rb_define_class_under(rb_cPrism, "ParseResult", rb_cPrismResult);
1234
+ rb_cPrismLexResult = rb_define_class_under(rb_cPrism, "LexResult", rb_cPrismResult);
1370
1235
  rb_cPrismParseLexResult = rb_define_class_under(rb_cPrism, "ParseLexResult", rb_cPrismResult);
1371
-
1372
- // Intern all of the options that we support so that we don't have to do it
1373
- // every time we parse.
1374
- rb_option_id_command_line = rb_intern_const("command_line");
1375
- rb_option_id_encoding = rb_intern_const("encoding");
1376
- rb_option_id_filepath = rb_intern_const("filepath");
1377
- rb_option_id_frozen_string_literal = rb_intern_const("frozen_string_literal");
1378
- rb_option_id_line = rb_intern_const("line");
1379
- rb_option_id_scopes = rb_intern_const("scopes");
1380
- rb_option_id_version = rb_intern_const("version");
1381
-
1382
- rb_prism_source_id_for = rb_intern("for");
1236
+ rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
1237
+
1238
+ // Intern all of the IDs eagerly that we support so that we don't have to do
1239
+ // it every time we parse.
1240
+ rb_id_option_command_line = rb_intern_const("command_line");
1241
+ rb_id_option_encoding = rb_intern_const("encoding");
1242
+ rb_id_option_filepath = rb_intern_const("filepath");
1243
+ rb_id_option_frozen_string_literal = rb_intern_const("frozen_string_literal");
1244
+ rb_id_option_line = rb_intern_const("line");
1245
+ rb_id_option_main_script = rb_intern_const("main_script");
1246
+ rb_id_option_partial_script = rb_intern_const("partial_script");
1247
+ rb_id_option_scopes = rb_intern_const("scopes");
1248
+ rb_id_option_version = rb_intern_const("version");
1249
+ rb_id_source_for = rb_intern("for");
1383
1250
 
1384
1251
  /**
1385
1252
  * The version of the prism library.
@@ -1390,8 +1257,10 @@ Init_prism(void) {
1390
1257
  rb_define_singleton_method(rb_cPrism, "lex", lex, -1);
1391
1258
  rb_define_singleton_method(rb_cPrism, "lex_file", lex_file, -1);
1392
1259
  rb_define_singleton_method(rb_cPrism, "parse", parse, -1);
1393
- rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1);
1394
1260
  rb_define_singleton_method(rb_cPrism, "parse_file", parse_file, -1);
1261
+ rb_define_singleton_method(rb_cPrism, "profile", profile, -1);
1262
+ rb_define_singleton_method(rb_cPrism, "profile_file", profile_file, -1);
1263
+ rb_define_singleton_method(rb_cPrism, "parse_stream", parse_stream, -1);
1395
1264
  rb_define_singleton_method(rb_cPrism, "parse_comments", parse_comments, -1);
1396
1265
  rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, -1);
1397
1266
  rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
@@ -1406,28 +1275,9 @@ Init_prism(void) {
1406
1275
  rb_define_singleton_method(rb_cPrism, "dump_file", dump_file, -1);
1407
1276
  #endif
1408
1277
 
1409
- // Next, the functions that will be called by the parser to perform various
1410
- // internal tasks. We expose these to make them easier to test.
1411
- VALUE rb_cPrismDebug = rb_define_module_under(rb_cPrism, "Debug");
1412
- rb_define_singleton_method(rb_cPrismDebug, "named_captures", named_captures, 1);
1413
- rb_define_singleton_method(rb_cPrismDebug, "integer_parse", integer_parse, 1);
1414
- rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1);
1415
- rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
1416
- rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2);
1417
- rb_define_singleton_method(rb_cPrismDebug, "static_inspect", static_inspect, -1);
1418
-
1419
- #ifndef PRISM_EXCLUDE_PRETTYPRINT
1420
- rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1);
1421
- #endif
1422
-
1423
- // Next, define the functions that are exposed through the private
1424
- // Debug::Encoding class.
1425
- rb_cPrismDebugEncoding = rb_define_class_under(rb_cPrismDebug, "Encoding", rb_cObject);
1426
- rb_define_singleton_method(rb_cPrismDebugEncoding, "all", encoding_all, 0);
1427
- rb_define_singleton_method(rb_cPrismDebugEncoding, "_width", encoding_char_width, 2);
1428
- rb_define_singleton_method(rb_cPrismDebugEncoding, "_alnum?", encoding_alnum_char, 2);
1429
- rb_define_singleton_method(rb_cPrismDebugEncoding, "_alpha?", encoding_alpha_char, 2);
1430
- rb_define_singleton_method(rb_cPrismDebugEncoding, "_upper?", encoding_isupper_char, 2);
1278
+ rb_define_singleton_method(rb_cPrismStringQuery, "local?", string_query_local_p, 1);
1279
+ rb_define_singleton_method(rb_cPrismStringQuery, "constant?", string_query_constant_p, 1);
1280
+ rb_define_singleton_method(rb_cPrismStringQuery, "method_name?", string_query_method_name_p, 1);
1431
1281
 
1432
1282
  // Next, initialize the other APIs.
1433
1283
  Init_prism_api_node();