prism 0.29.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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();