prism 2.0.0.rc1-x86_64-linux-gnu → 2.0.0-x86_64-linux-gnu

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -2
  3. data/CODE_OF_CONDUCT.md +1 -1
  4. data/LICENSE.md +1 -1
  5. data/docs/serialization.md +20 -6
  6. data/ext/prism/api_node.c +81 -81
  7. data/ext/prism/extension.c +54 -69
  8. data/ext/prism/extension.h +1 -1
  9. data/include/prism/arena.h +8 -0
  10. data/include/prism/arena.hpp +42 -0
  11. data/include/prism/ast.h +11 -1
  12. data/include/prism/ast.hpp +641 -0
  13. data/include/prism/buffer.h +8 -0
  14. data/include/prism/buffer.hpp +55 -0
  15. data/include/prism/comments.h +17 -0
  16. data/include/prism/compiler/accel.h +3 -1
  17. data/include/prism/compiler/branch.h +26 -0
  18. data/include/prism/compiler/bswap.h +46 -0
  19. data/include/prism/compiler/cplusplus.hpp +16 -0
  20. data/include/prism/compiler/endianness.h +34 -0
  21. data/include/prism/compiler/exceptions.hpp +17 -0
  22. data/include/prism/compiler/format.h +2 -0
  23. data/include/prism/compiler/lifetimebound.hpp +25 -0
  24. data/include/prism/constant_pool.h +25 -0
  25. data/include/prism/diagnostic.h +18 -0
  26. data/include/prism/errors_format.h +8 -0
  27. data/include/prism/internal/buffer.h +3 -0
  28. data/include/prism/internal/node.h +8 -4
  29. data/include/prism/internal/parser.h +20 -0
  30. data/include/prism/internal/stringy.h +1 -6
  31. data/include/prism/internal/xxh3.h +16 -0
  32. data/include/prism/json.h +8 -0
  33. data/include/prism/line_offset_list.h +8 -0
  34. data/include/prism/magic_comments.h +18 -0
  35. data/include/prism/node.h +55 -10
  36. data/include/prism/node.hpp +272 -0
  37. data/include/prism/node_type.hpp +38 -0
  38. data/include/prism/options.h +10 -1
  39. data/include/prism/options.hpp +43 -0
  40. data/include/prism/parser.h +93 -64
  41. data/include/prism/parser.hpp +274 -0
  42. data/include/prism/prettyprint.h +8 -0
  43. data/include/prism/serialize.h +8 -0
  44. data/include/prism/source.h +8 -0
  45. data/include/prism/stream.h +8 -0
  46. data/include/prism/string_query.h +19 -0
  47. data/include/prism/stringy.h +16 -27
  48. data/include/prism/stringy.hpp +31 -0
  49. data/include/prism/version.h +9 -1
  50. data/include/prism.h +0 -8
  51. data/include/prism.hpp +24 -0
  52. data/lib/prism/3.3/prism.so +0 -0
  53. data/lib/prism/3.4/prism.so +0 -0
  54. data/lib/prism/4.0/prism.so +0 -0
  55. data/lib/prism/ffi.rb +6 -0
  56. data/lib/prism/node.rb +736 -0
  57. data/lib/prism/parse_result.rb +23 -8
  58. data/lib/prism/serialize.rb +2567 -3286
  59. data/lib/prism/string_query.rb +8 -0
  60. data/prism.gemspec +21 -4
  61. data/rbi/generated/prism/node.rbi +2430 -968
  62. data/rbi/generated/prism/parse_result.rbi +16 -4
  63. data/rbi/generated/prism/serialize.rbi +8 -4
  64. data/rbi/generated/prism/string_query.rbi +7 -0
  65. data/sig/generated/prism/node.rbs +2439 -967
  66. data/sig/generated/prism/parse_result.rbs +16 -4
  67. data/sig/generated/prism/serialize.rbs +9 -4
  68. data/sig/generated/prism/string_query.rbs +7 -0
  69. data/src/buffer.c +9 -0
  70. data/src/comments.c +2 -2
  71. data/src/diagnostic.c +8 -0
  72. data/src/node.c +216 -368
  73. data/src/options.c +7 -13
  74. data/src/parser.c +70 -48
  75. data/src/prism.c +581 -419
  76. data/src/regexp.c +0 -1
  77. data/src/serialize.c +2301 -1950
  78. data/src/source.c +8 -2
  79. data/src/string_query.c +14 -0
  80. data/src/stringy.c +3 -33
  81. data/src/xxh3.c +292 -0
  82. metadata +20 -3
@@ -192,7 +192,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) {
192
192
  // Add the local to the scope.
193
193
  pm_string_t *scope_local = pm_options_scope_local_mut(options_scope, local_index);
194
194
  const char *name = rb_id2name(SYM2ID(local));
195
- pm_string_constant_init(scope_local, name, strlen(name));
195
+ pm_string_init(scope_local, (const uint8_t *) name, strlen(name));
196
196
  }
197
197
 
198
198
  // Now set the forwarding options.
@@ -633,28 +633,19 @@ parser_comment(VALUE source, bool freeze, const pm_comment_t *comment) {
633
633
  return rb_class_new_instance_freeze(1, argv, type, freeze);
634
634
  }
635
635
 
636
- typedef struct {
637
- VALUE comments;
638
- VALUE source;
639
- bool freeze;
640
- long index;
641
- } parser_comments_each_data_t;
642
-
643
- static void
644
- parser_comments_each(const pm_comment_t *comment, void *data) {
645
- parser_comments_each_data_t *each_data = (parser_comments_each_data_t *) data;
646
- VALUE value = parser_comment(each_data->source, each_data->freeze, comment);
647
- rb_ary_store(each_data->comments, each_data->index++, value);
648
- }
649
-
650
636
  /**
651
637
  * Extract the comments out of the parser into the given array, which was
652
- * created before the source so that the source could hold it.
638
+ * created before the source so that the source could hold it. The caller may
639
+ * have already resized it to the number of comments, so each comment is stored
640
+ * at its index rather than pushed.
653
641
  */
654
642
  static void
655
643
  parser_comments(const pm_parser_t *parser, VALUE comments, VALUE source, bool freeze) {
656
- parser_comments_each_data_t each_data = { .comments = comments, .source = source, .freeze = freeze };
657
- pm_parser_comments_each(parser, parser_comments_each, &each_data);
644
+ long index = 0;
645
+ for (const pm_comment_t *comment = pm_parser_comments_first(parser); comment != NULL; comment = pm_comment_next(comment)) {
646
+ rb_ary_store(comments, index++, parser_comment(source, freeze, comment));
647
+ }
648
+
658
649
  if (freeze) rb_obj_freeze(comments);
659
650
  }
660
651
 
@@ -673,19 +664,6 @@ parser_magic_comment(VALUE source, bool freeze, const pm_magic_comment_t *magic_
673
664
  return rb_class_new_instance_freeze(2, argv, rb_cPrismMagicComment, freeze);
674
665
  }
675
666
 
676
- typedef struct {
677
- VALUE magic_comments;
678
- VALUE source;
679
- bool freeze;
680
- } parser_magic_comments_each_data_t;
681
-
682
- static void
683
- parser_magic_comments_each(const pm_magic_comment_t *magic_comment, void *data) {
684
- parser_magic_comments_each_data_t *each_data = (parser_magic_comments_each_data_t *) data;
685
- VALUE value = parser_magic_comment(each_data->source, each_data->freeze, magic_comment);
686
- rb_ary_push(each_data->magic_comments, value);
687
- }
688
-
689
667
  /**
690
668
  * Extract the magic comments out of the parser into an array.
691
669
  */
@@ -693,8 +671,9 @@ static VALUE
693
671
  parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) {
694
672
  VALUE magic_comments = rb_ary_new_capa(pm_parser_magic_comments_size(parser));
695
673
 
696
- parser_magic_comments_each_data_t each_data = { magic_comments, source, freeze };
697
- pm_parser_magic_comments_each(parser, parser_magic_comments_each, &each_data);
674
+ for (const pm_magic_comment_t *magic_comment = pm_parser_magic_comments_first(parser); magic_comment != NULL; magic_comment = pm_magic_comment_next(magic_comment)) {
675
+ rb_ary_push(magic_comments, parser_magic_comment(source, freeze, magic_comment));
676
+ }
698
677
 
699
678
  if (freeze) rb_obj_freeze(magic_comments);
700
679
  return magic_comments;
@@ -715,20 +694,14 @@ parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) {
715
694
  }
716
695
  }
717
696
 
718
- typedef struct {
719
- VALUE errors;
720
- rb_encoding *encoding;
721
- VALUE source;
722
- bool freeze;
723
- } parser_errors_each_data_t;
724
-
725
- static void
726
- parser_errors_each(const pm_diagnostic_t *diagnostic, void *data) {
727
- parser_errors_each_data_t *each_data = (parser_errors_each_data_t *) data;
728
-
697
+ /**
698
+ * Build a new ParseError instance from the given error.
699
+ */
700
+ static VALUE
701
+ parser_error(const pm_diagnostic_t *diagnostic, rb_encoding *encoding, VALUE source, bool freeze) {
729
702
  VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(diagnostic)));
730
- VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(diagnostic), each_data->encoding));
731
- VALUE location = PARSER_LOCATION(each_data->source, each_data->freeze, pm_diagnostic_location(diagnostic));
703
+ VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(diagnostic), encoding));
704
+ VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(diagnostic));
732
705
 
733
706
  pm_error_level_t error_level = pm_diagnostic_error_level(diagnostic);
734
707
  VALUE level = Qnil;
@@ -748,8 +721,7 @@ parser_errors_each(const pm_diagnostic_t *diagnostic, void *data) {
748
721
  }
749
722
 
750
723
  VALUE argv[] = { type, message, location, level };
751
- VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, each_data->freeze);
752
- rb_ary_push(each_data->errors, value);
724
+ return rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, freeze);
753
725
  }
754
726
 
755
727
  /**
@@ -759,27 +731,22 @@ static VALUE
759
731
  parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) {
760
732
  VALUE errors = rb_ary_new_capa(pm_parser_errors_size(parser));
761
733
 
762
- parser_errors_each_data_t each_data = { errors, encoding, source, freeze };
763
- pm_parser_errors_each(parser, parser_errors_each, &each_data);
734
+ for (const pm_diagnostic_t *error = pm_parser_errors_first(parser); error != NULL; error = pm_diagnostic_next(error)) {
735
+ rb_ary_push(errors, parser_error(error, encoding, source, freeze));
736
+ }
764
737
 
765
738
  if (freeze) rb_obj_freeze(errors);
766
739
  return errors;
767
740
  }
768
741
 
769
- typedef struct {
770
- VALUE warnings;
771
- rb_encoding *encoding;
772
- VALUE source;
773
- bool freeze;
774
- } parser_warnings_each_data_t;
775
-
776
- static void
777
- parser_warnings_each(const pm_diagnostic_t *diagnostic, void *data) {
778
- parser_warnings_each_data_t *each_data = (parser_warnings_each_data_t *) data;
779
-
742
+ /**
743
+ * Build a new ParseWarning instance from the given warning.
744
+ */
745
+ static VALUE
746
+ parser_warning(const pm_diagnostic_t *diagnostic, rb_encoding *encoding, VALUE source, bool freeze) {
780
747
  VALUE type = ID2SYM(rb_intern(pm_diagnostic_type(diagnostic)));
781
- VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(diagnostic), each_data->encoding));
782
- VALUE location = PARSER_LOCATION(each_data->source, each_data->freeze, pm_diagnostic_location(diagnostic));
748
+ VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(pm_diagnostic_message(diagnostic), encoding));
749
+ VALUE location = PARSER_LOCATION(source, freeze, pm_diagnostic_location(diagnostic));
783
750
 
784
751
  pm_warning_level_t warning_level = pm_diagnostic_warning_level(diagnostic);
785
752
  VALUE level = Qnil;
@@ -796,8 +763,7 @@ parser_warnings_each(const pm_diagnostic_t *diagnostic, void *data) {
796
763
  }
797
764
 
798
765
  VALUE argv[] = { type, message, location, level };
799
- VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, each_data->freeze);
800
- rb_ary_push(each_data->warnings, value);
766
+ return rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, freeze);
801
767
  }
802
768
 
803
769
  /**
@@ -807,8 +773,9 @@ static VALUE
807
773
  parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) {
808
774
  VALUE warnings = rb_ary_new_capa(pm_parser_warnings_size(parser));
809
775
 
810
- parser_warnings_each_data_t each_data = { warnings, encoding, source, freeze };
811
- pm_parser_warnings_each(parser, parser_warnings_each, &each_data);
776
+ for (const pm_diagnostic_t *warning = pm_parser_warnings_first(parser); warning != NULL; warning = pm_diagnostic_next(warning)) {
777
+ rb_ary_push(warnings, parser_warning(warning, encoding, source, freeze));
778
+ }
812
779
 
813
780
  if (freeze) rb_obj_freeze(warnings);
814
781
  return warnings;
@@ -983,8 +950,9 @@ parse_lex_input(const uint8_t *input, size_t input_length, const pm_options_t *o
983
950
 
984
951
  result_t result = check_raise_error_option(parser, options, path_encoding);
985
952
  if (result.type == RESULT_OK) {
986
- /* Update the Source object with the correct encoding and line offsets,
987
- * which are only available after pm_parse() completes. */
953
+ /* Update the Source object with the correct encoding, line offsets,
954
+ * and source hash, which are only available after pm_parse()
955
+ * completes. */
988
956
  rb_encoding *encoding = rb_enc_find(pm_parser_encoding_name(parser));
989
957
  rb_enc_associate(source_string, encoding);
990
958
 
@@ -993,6 +961,8 @@ parse_lex_input(const uint8_t *input, size_t input_length, const pm_options_t *o
993
961
  rb_ary_store(offsets, (long) index, ULONG2NUM(line_offsets->offsets[index]));
994
962
  }
995
963
 
964
+ rb_funcall(source, rb_intern("replace_checksum"), 1, ULL2NUM(pm_parser_checksum(parser)));
965
+
996
966
  if (pm_options_freeze(options)) {
997
967
  rb_obj_freeze(source_string);
998
968
  rb_obj_freeze(offsets);
@@ -1678,6 +1648,20 @@ string_query_method_name_p(VALUE self, VALUE string) {
1678
1648
  return string_query(pm_string_query_method_name(source, RSTRING_LEN(string), rb_enc_get(string)->name));
1679
1649
  }
1680
1650
 
1651
+ /**
1652
+ * :markup: markdown
1653
+ * call-seq:
1654
+ * keyword?(string) -> bool
1655
+ *
1656
+ * Returns true if the string is a valid keyword, such as `if`, `defined?`, or
1657
+ * `__FILE__`.
1658
+ */
1659
+ static VALUE
1660
+ string_query_keyword_p(VALUE self, VALUE string) {
1661
+ const uint8_t *source = (const uint8_t *) check_string(string);
1662
+ return string_query(pm_string_query_keyword(source, RSTRING_LEN(string), rb_enc_get(string)->name));
1663
+ }
1664
+
1681
1665
  /******************************************************************************/
1682
1666
  /* Initialization of the extension */
1683
1667
  /******************************************************************************/
@@ -1778,6 +1762,7 @@ Init_prism(void) {
1778
1762
  rb_define_singleton_method(rb_cPrismStringQuery, "local?", string_query_local_p, 1);
1779
1763
  rb_define_singleton_method(rb_cPrismStringQuery, "constant?", string_query_constant_p, 1);
1780
1764
  rb_define_singleton_method(rb_cPrismStringQuery, "method_name?", string_query_method_name_p, 1);
1765
+ rb_define_singleton_method(rb_cPrismStringQuery, "keyword?", string_query_keyword_p, 1);
1781
1766
 
1782
1767
  Init_prism_api_node();
1783
1768
  }
@@ -1,7 +1,7 @@
1
1
  #ifndef PRISM_EXT_NODE_H
2
2
  #define PRISM_EXT_NODE_H
3
3
 
4
- #define EXPECTED_PRISM_VERSION "2.0.0.rc1"
4
+ #define EXPECTED_PRISM_VERSION "2.0.0"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>
@@ -12,6 +12,10 @@
12
12
 
13
13
  #include <stddef.h>
14
14
 
15
+ #ifdef __cplusplus
16
+ extern "C" {
17
+ #endif
18
+
15
19
  /**
16
20
  * An opaque pointer to an arena that is used for allocations.
17
21
  */
@@ -34,4 +38,8 @@ PRISM_NODISCARD PRISM_EXPORTED_FUNCTION pm_arena_t * pm_arena_new(void);
34
38
  */
35
39
  PRISM_EXPORTED_FUNCTION void pm_arena_free(pm_arena_t *arena) PRISM_NONNULL(1);
36
40
 
41
+ #ifdef __cplusplus
42
+ }
43
+ #endif
44
+
37
45
  #endif
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @file arena.hpp
3
+ *
4
+ * Ownership of arenas from C++.
5
+ */
6
+ #ifndef PRISM_ARENA_HPP
7
+ #define PRISM_ARENA_HPP
8
+
9
+ #include "prism/compiler/cplusplus.hpp"
10
+
11
+ #include "prism/arena.h"
12
+
13
+ #include <memory>
14
+
15
+ namespace prism {
16
+
17
+ /** Frees an arena with pm_arena_free. */
18
+ struct arena_deleter {
19
+ /**
20
+ * Frees the given arena.
21
+ *
22
+ * @param arena The arena to free.
23
+ */
24
+ void operator()(pm_arena_t *arena) const noexcept { pm_arena_free(arena); }
25
+ };
26
+
27
+ /** An owned arena. */
28
+ using unique_arena = std::unique_ptr<pm_arena_t, arena_deleter>;
29
+
30
+ /**
31
+ * Allocate a new arena. Allocation failure aborts, so this never throws.
32
+ *
33
+ * @return A unique_arena managing the newly allocated arena.
34
+ */
35
+ [[nodiscard]] inline unique_arena
36
+ make_arena() noexcept {
37
+ return unique_arena(pm_arena_new());
38
+ }
39
+
40
+ }
41
+
42
+ #endif
data/include/prism/ast.h CHANGED
@@ -27,6 +27,10 @@
27
27
  #include <stddef.h>
28
28
  #include <stdint.h>
29
29
 
30
+ #ifdef __cplusplus
31
+ extern "C" {
32
+ #endif
33
+
30
34
  /**
31
35
  * This enum represents every type of token in the Ruby source.
32
36
  */
@@ -1103,7 +1107,9 @@ typedef struct pm_node {
1103
1107
 
1104
1108
  /**
1105
1109
  * The unique identifier for this node, which is deterministic based on the
1106
- * source. It is used to identify unique nodes across parses.
1110
+ * source. It is used to identify unique nodes across parses. Nodes created
1111
+ * outside of parsing have no position in the source and can use 0, which
1112
+ * no parsed node uses.
1107
1113
  */
1108
1114
  uint32_t node_id;
1109
1115
 
@@ -10368,4 +10374,8 @@ PRISM_EXPORTED_FUNCTION pm_yield_node_t * pm_yield_node_new(pm_arena_t *arena, u
10368
10374
  */
10369
10375
  #define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS 0
10370
10376
 
10377
+ #ifdef __cplusplus
10378
+ }
10379
+ #endif
10380
+
10371
10381
  #endif