prism 1.6.0 → 1.7.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -1
  3. data/Makefile +3 -3
  4. data/README.md +1 -1
  5. data/config.yml +28 -3
  6. data/docs/build_system.md +2 -2
  7. data/docs/cruby_compilation.md +1 -1
  8. data/docs/releasing.md +2 -2
  9. data/ext/prism/api_node.c +7 -3
  10. data/ext/prism/extconf.rb +1 -1
  11. data/ext/prism/extension.c +2 -3
  12. data/ext/prism/extension.h +1 -1
  13. data/include/prism/ast.h +54 -20
  14. data/include/prism/diagnostic.h +2 -0
  15. data/include/prism/options.h +8 -2
  16. data/include/prism/parser.h +3 -0
  17. data/include/prism/version.h +2 -2
  18. data/include/prism.h +1 -1
  19. data/lib/prism/dot_visitor.rb +5 -0
  20. data/lib/prism/dsl.rb +2 -2
  21. data/lib/prism/ffi.rb +3 -1
  22. data/lib/prism/inspect_visitor.rb +1 -0
  23. data/lib/prism/node.rb +52 -13
  24. data/lib/prism/parse_result.rb +2 -15
  25. data/lib/prism/polyfill/scan_byte.rb +1 -1
  26. data/lib/prism/reflection.rb +1 -1
  27. data/lib/prism/serialize.rb +6 -4
  28. data/lib/prism/translation/parser/compiler.rb +16 -16
  29. data/lib/prism/translation/parser.rb +5 -3
  30. data/lib/prism/translation/parser35.rb +1 -6
  31. data/lib/prism/translation/parser40.rb +13 -0
  32. data/lib/prism/translation/parser41.rb +13 -0
  33. data/lib/prism/translation/parser_current.rb +4 -2
  34. data/lib/prism/translation/ripper.rb +2 -2
  35. data/lib/prism/translation/ruby_parser.rb +53 -18
  36. data/lib/prism/translation.rb +2 -0
  37. data/lib/prism.rb +4 -5
  38. data/prism.gemspec +5 -1
  39. data/rbi/prism/dsl.rbi +3 -3
  40. data/rbi/prism/node.rbi +21 -8
  41. data/rbi/prism/translation/parser35.rbi +0 -2
  42. data/rbi/prism/translation/parser40.rbi +6 -0
  43. data/rbi/prism/translation/parser41.rbi +6 -0
  44. data/sig/prism/dsl.rbs +2 -2
  45. data/sig/prism/node.rbs +18 -8
  46. data/src/diagnostic.c +5 -1
  47. data/src/encoding.c +172 -67
  48. data/src/node.c +9 -0
  49. data/src/options.c +17 -7
  50. data/src/prettyprint.c +16 -0
  51. data/src/prism.c +1192 -1895
  52. data/src/serialize.c +7 -1
  53. data/src/token_type.c +2 -2
  54. data/src/util/pm_constant_pool.c +1 -1
  55. metadata +5 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ef507799374ba0281ff3d8ab78fc29f673b3fc213f695ae68c65cf0d38b4bcc
4
- data.tar.gz: 7610a756cffd1aeb517f135446ae25360568cc00e6d78e748470469bd345463c
3
+ metadata.gz: 34ddf7552f6698f496fba09232eac5bcfb053d0455cdac655d81d4a9e5c60d96
4
+ data.tar.gz: 248141836d3f2502508f3374586bfd6590d1457dd0508494588a8905c56aea91
5
5
  SHA512:
6
- metadata.gz: 539d064482f82c7fd85c7e8269b1c400fd576b20effbcb857636667ce8818367eea35446bc7ee2decf3cdde7171883e8aeaa154c2bf1b8d7f3c7fa5c12203f08
7
- data.tar.gz: 59181adcac710bf7697b1dec0556eb306f9cf79d2b7492e0392d9698401dd3abb5a1406fc5d66d1c4d0acbd85d9ebf8e674683e9ec585d765216953f80a75297
6
+ metadata.gz: 6e46578f5a2dd28f487bd4ffbdc7cd34bf15f230118f53bf932bea0ccff22cc4fcd000804f9a7bc27fd3399099bbd368f9ac89b6408df7de766ad1aef24a3cda
7
+ data.tar.gz: 7e25c7caf0fbf963e7c7aadaf35535f3c770c1813e0b9cfd3f8d4623d2d47c5a1d8e2e487d59d75a711871b9bdf5dca92c9e85af0dd4d3f513e86d3d7a66e37d
data/CHANGELOG.md CHANGED
@@ -6,6 +6,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.7.0] - 2025-12-18
10
+
11
+ ### Added
12
+
13
+ - Support `4.1` as a version option.
14
+ - Add `equal_loc` to `CallNode`.
15
+ - Add `len()`/`is_empty()` to `ConstantList` and `NodeList` in the Rust API.
16
+
17
+ ### Changed
18
+
19
+ - Rename version `3.5` to version `4.0`.
20
+ - Fix compiling the gem from source on Windows.
21
+ - Fix parsing of unary method calls like `42.~@`.
22
+ - Reject `def f a, (b) = 1`.
23
+ - Reject endless method as a block parameter default.
24
+ - Reject variable capture in alternative pattern.
25
+ - Many fixes in regards to memory safety, found through fuzzing.
26
+ - Many fixes to better handle invalid syntax, also found through fuzzing.
27
+ - Fix the ruby version used by the `ripper` translator.
28
+ - Fix `ruby_parser` translation comment processing.
29
+
9
30
  ## [1.6.0] - 2025-10-16
10
31
 
11
32
  ### Added
@@ -695,7 +716,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
695
716
 
696
717
  - 🎉 Initial release! 🎉
697
718
 
698
- [unreleased]: https://github.com/ruby/prism/compare/v1.6.0...HEAD
719
+ [unreleased]: https://github.com/ruby/prism/compare/v1.7.0...HEAD
720
+ [1.7.0]: https://github.com/ruby/prism/compare/v1.6.0...v1.7.0
699
721
  [1.6.0]: https://github.com/ruby/prism/compare/v1.5.2...v1.6.0
700
722
  [1.5.2]: https://github.com/ruby/prism/compare/v1.5.1...v1.5.2
701
723
  [1.5.1]: https://github.com/ruby/prism/compare/v1.5.0...v1.5.1
data/Makefile CHANGED
@@ -63,12 +63,12 @@ build/fuzz.%: $(SOURCES) fuzz/%.c fuzz/fuzz.c
63
63
  $(ECHO) "building $* fuzzer"
64
64
  $(Q) $(MAKEDIRS) $(@D)
65
65
  $(ECHO) "building main fuzz binary"
66
- $(Q) AFL_HARDEN=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^
66
+ $(Q) afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^
67
67
  $(ECHO) "building cmplog binary"
68
- $(Q) AFL_HARDEN=1 AFL_LLVM_CMPLOG=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@.cmplog $^
68
+ $(Q) AFL_LLVM_CMPLOG=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@.cmplog $^
69
69
 
70
70
  build/fuzz.heisenbug.%: $(SOURCES) fuzz/%.c fuzz/heisenbug.c
71
- $(Q) AFL_HARDEN=1 afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^
71
+ $(Q) afl-clang-lto $(DEBUG_FLAGS) $(CPPFLAGS) $(CFLAGS) $(FUZZ_FLAGS) -O0 -fsanitize-ignorelist=fuzz/asan.ignore -fsanitize=fuzzer,address -ggdb3 -std=c99 -Iinclude -o $@ $^
72
72
 
73
73
  fuzz-debug:
74
74
  $(ECHO) "entering debug shell"
data/README.md CHANGED
@@ -116,7 +116,7 @@ Prism has been integrated into the majority of Ruby runtimes, many libraries, an
116
116
  * [JRuby](https://github.com/jruby/jruby/pull/8103) (via Java)
117
117
  * [Natalie](https://github.com/natalie-lang/natalie/pull/1213) (via C++ and Ruby)
118
118
  * [Opal](https://github.com/opal/opal/pull/2642) (via Ruby and WASM)
119
- * [TruffleRuby](https://github.com/oracle/truffleruby/issues/3117) (via Java)
119
+ * [TruffleRuby](https://github.com/truffleruby/truffleruby/issues/3117) (via Java)
120
120
 
121
121
  ### Libraries
122
122
 
data/config.yml CHANGED
@@ -219,6 +219,7 @@ errors:
219
219
  - PARAMETER_WILD_LOOSE_COMMA
220
220
  - PATTERN_ARRAY_MULTIPLE_RESTS
221
221
  - PATTERN_CAPTURE_DUPLICATE
222
+ - PATTERN_CAPTURE_IN_ALTERNATIVE
222
223
  - PATTERN_EXPRESSION_AFTER_BRACKET
223
224
  - PATTERN_EXPRESSION_AFTER_COMMA
224
225
  - PATTERN_EXPRESSION_AFTER_HROCKET
@@ -280,6 +281,7 @@ errors:
280
281
  - UNEXPECTED_INDEX_KEYWORDS
281
282
  - UNEXPECTED_LABEL
282
283
  - UNEXPECTED_MULTI_WRITE
284
+ - UNEXPECTED_PARAMETER_DEFAULT_VALUE
283
285
  - UNEXPECTED_RANGE_OPERATOR
284
286
  - UNEXPECTED_SAFE_NAVIGATION
285
287
  - UNEXPECTED_TOKEN_CLOSE_CONTEXT
@@ -356,6 +358,8 @@ tokens:
356
358
  comment: "a newline character outside of other tokens"
357
359
  - name: PARENTHESIS_RIGHT
358
360
  comment: ")"
361
+ - name: PIPE
362
+ comment: "|"
359
363
  - name: SEMICOLON
360
364
  comment: ";"
361
365
  # Tokens from here on are not used for lookup, and can be in any order.
@@ -589,8 +593,6 @@ tokens:
589
593
  comment: "%I"
590
594
  - name: PERCENT_UPPER_W
591
595
  comment: "%W"
592
- - name: PIPE
593
- comment: "|"
594
596
  - name: PIPE_EQUAL
595
597
  comment: "|="
596
598
  - name: PIPE_PIPE
@@ -1515,6 +1517,16 @@ nodes:
1515
1517
 
1516
1518
  foo(bar)
1517
1519
  ^
1520
+ - name: equal_loc
1521
+ type: location?
1522
+ comment: |
1523
+ Represents the location of the equal sign, in the case that this is an attribute write.
1524
+
1525
+ foo.bar = value
1526
+ ^
1527
+
1528
+ foo[bar] = value
1529
+ ^
1518
1530
  - name: block
1519
1531
  type: node?
1520
1532
  kind:
@@ -2616,11 +2628,18 @@ nodes:
2616
2628
  - name: block
2617
2629
  type: node?
2618
2630
  kind: BlockNode
2631
+ comment: |
2632
+ All other arguments are forwarded as normal, except the original block is replaced with the new block.
2619
2633
  comment: |
2620
- Represents the use of the `super` keyword without parentheses or arguments.
2634
+ Represents the use of the `super` keyword without parentheses or arguments, but which might have a block.
2621
2635
 
2622
2636
  super
2623
2637
  ^^^^^
2638
+
2639
+ super { 123 }
2640
+ ^^^^^^^^^^^^^
2641
+
2642
+ If it has any other arguments, it would be a `SuperNode` instead.
2624
2643
  - name: GlobalVariableAndWriteNode
2625
2644
  fields:
2626
2645
  - name: name
@@ -3287,6 +3306,9 @@ nodes:
3287
3306
  - EmbeddedVariableNode
3288
3307
  - InterpolatedStringNode # `"a" "#{b}"`
3289
3308
  - on error: XStringNode # `<<`FOO` "bar"
3309
+ - on error: InterpolatedXStringNode
3310
+ - on error: SymbolNode
3311
+ - on error: InterpolatedSymbolNode
3290
3312
  - name: closing_loc
3291
3313
  type: location?
3292
3314
  newline: parts
@@ -4496,6 +4518,7 @@ nodes:
4496
4518
  - name: arguments
4497
4519
  type: node?
4498
4520
  kind: ArgumentsNode
4521
+ comment: "Can be only `nil` when there are empty parentheses, like `super()`."
4499
4522
  - name: rparen_loc
4500
4523
  type: location?
4501
4524
  - name: block
@@ -4511,6 +4534,8 @@ nodes:
4511
4534
 
4512
4535
  super foo, bar
4513
4536
  ^^^^^^^^^^^^^^
4537
+
4538
+ If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead.
4514
4539
  - name: SymbolNode
4515
4540
  flags: SymbolFlags
4516
4541
  fields:
data/docs/build_system.md CHANGED
@@ -58,12 +58,12 @@ prism's `Makefile` is not used at all in CRuby. Instead, CRuby's `Makefile` is u
58
58
 
59
59
  ### Building prism as part of TruffleRuby
60
60
 
61
- [This script](https://github.com/oracle/truffleruby/blob/master/tool/import-prism.sh) imports prism sources in TruffleRuby.
61
+ [This script](https://github.com/truffleruby/truffleruby/blob/master/tool/import-prism.sh) imports prism sources in TruffleRuby.
62
62
  The script generates the templates when importing.
63
63
 
64
64
  Then when `mx build` builds TruffleRuby and the `prism` mx project inside, it runs `make`.
65
65
 
66
- Then the `prism bindings` mx project is built, which contains the [bindings](https://github.com/oracle/truffleruby/blob/vm-24.1.1/src/main/c/yarp_bindings/src/yarp_bindings.c)
66
+ Then the `prism bindings` mx project is built, which contains the [bindings](https://github.com/truffleruby/truffleruby/blob/vm-24.1.1/src/main/c/yarp_bindings/src/yarp_bindings.c)
67
67
  and links to `libprism.a` (to avoid exporting symbols, so no conflict when installing the prism gem).
68
68
 
69
69
  ### Building prism as part of JRuby
@@ -1,6 +1,6 @@
1
1
  # Compiling Prism's AST
2
2
 
3
- One important class of consumers of Prism's AST is compilers. Currently [CRuby](https://github.com/ruby/ruby), [JRuby](https://github.com/jruby/jruby), [TruffleRuby](https://github.com/oracle/truffleruby), and [Natalie](https://github.com/natalie-lang/natalie) have all built compilation code on top of Prism's AST.
3
+ One important class of consumers of Prism's AST is compilers. Currently [CRuby](https://github.com/ruby/ruby), [JRuby](https://github.com/jruby/jruby), [TruffleRuby](https://github.com/truffleruby/truffleruby), and [Natalie](https://github.com/natalie-lang/natalie) have all built compilation code on top of Prism's AST.
4
4
 
5
5
  This document will describe, at a high level, how CRuby's compilation of Prism's AST works.
6
6
 
data/docs/releasing.md CHANGED
@@ -40,7 +40,7 @@ ruby -pi -e 'gsub(/^ruby-prism-sys = \{ version = ".+?"/, %Q{ruby-prism-sys = \{
40
40
  * Update the `Gemfile.lock` file:
41
41
 
42
42
  ```sh
43
- chruby ruby-3.5.0-dev
43
+ chruby ruby-4.0.0-dev
44
44
  bundle install
45
45
  ```
46
46
 
@@ -48,7 +48,7 @@ bundle install
48
48
 
49
49
  ```sh
50
50
  for VERSION in "2.7" "3.0" "3.1" "3.2" "3.3" "3.4"; do docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/$VERSION/Gemfile" "ruby:$VERSION" bundle update; done
51
- docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/3.5/Gemfile" ruby:3.5.0-preview1 bundle update
51
+ docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/4.0/Gemfile" ruby:4.0.0-preview2 bundle update
52
52
  docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/jruby/Gemfile" jruby:latest bundle update
53
53
  BUNDLE_GEMFILE=gemfiles/truffleruby/Gemfile chruby-exec truffleruby -- bundle update
54
54
  ```
data/ext/prism/api_node.c CHANGED
@@ -1789,7 +1789,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
1789
1789
  #line 190 "prism/templates/ext/prism/api_node.c.erb"
1790
1790
  case PM_CALL_NODE: {
1791
1791
  pm_call_node_t *cast = (pm_call_node_t *) node;
1792
- VALUE argv[12];
1792
+ VALUE argv[13];
1793
1793
 
1794
1794
  // source
1795
1795
  argv[0] = source;
@@ -1832,11 +1832,15 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
1832
1832
  #line 243 "prism/templates/ext/prism/api_node.c.erb"
1833
1833
  argv[10] = cast->closing_loc.start == NULL ? Qnil : pm_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source, freeze);
1834
1834
 
1835
+ // equal_loc
1836
+ #line 243 "prism/templates/ext/prism/api_node.c.erb"
1837
+ argv[11] = cast->equal_loc.start == NULL ? Qnil : pm_location_new(parser, cast->equal_loc.start, cast->equal_loc.end, source, freeze);
1838
+
1835
1839
  // block
1836
1840
  #line 213 "prism/templates/ext/prism/api_node.c.erb"
1837
- argv[11] = rb_ary_pop(value_stack);
1841
+ argv[12] = rb_ary_pop(value_stack);
1838
1842
 
1839
- VALUE value = rb_class_new_instance(12, argv, rb_cPrismCallNode);
1843
+ VALUE value = rb_class_new_instance(13, argv, rb_cPrismCallNode);
1840
1844
  if (freeze) rb_obj_freeze(value);
1841
1845
 
1842
1846
  rb_ary_push(value_stack, value);
data/ext/prism/extconf.rb CHANGED
@@ -37,7 +37,7 @@ end
37
37
  def generate_templates
38
38
  Dir.chdir(File.expand_path("../..", __dir__)) do
39
39
  if !File.exist?("include/prism/ast.h") && Dir.exist?(".git")
40
- system("templates/template.rb", exception: true)
40
+ system(RbConfig.ruby, "templates/template.rb", exception: true)
41
41
  end
42
42
  end
43
43
  end
@@ -201,10 +201,9 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
201
201
  const char *version = check_string(value);
202
202
 
203
203
  if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
204
- VALUE current_ruby_value = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"));
205
- const char *current_version = RSTRING_PTR(current_ruby_value);
204
+ const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
206
205
  if (!pm_options_version_set(options, current_version, 3)) {
207
- rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, current_ruby_value));
206
+ rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version));
208
207
  }
209
208
  } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
210
209
  rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
@@ -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 "1.6.0"
4
+ #define EXPECTED_PRISM_VERSION "1.7.0"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>
data/include/prism/ast.h CHANGED
@@ -76,6 +76,9 @@ typedef enum pm_token_type {
76
76
  /** ) */
77
77
  PM_TOKEN_PARENTHESIS_RIGHT,
78
78
 
79
+ /** | */
80
+ PM_TOKEN_PIPE,
81
+
79
82
  /** ; */
80
83
  PM_TOKEN_SEMICOLON,
81
84
 
@@ -424,9 +427,6 @@ typedef enum pm_token_type {
424
427
  /** %W */
425
428
  PM_TOKEN_PERCENT_UPPER_W,
426
429
 
427
- /** | */
428
- PM_TOKEN_PIPE,
429
-
430
430
  /** |= */
431
431
  PM_TOKEN_PIPE_EQUAL,
432
432
 
@@ -1050,22 +1050,6 @@ typedef uint16_t pm_node_flags_t;
1050
1050
  static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = 0x1;
1051
1051
  static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2;
1052
1052
 
1053
- /**
1054
- * Cast the type to an enum to allow the compiler to provide exhaustiveness
1055
- * checking.
1056
- */
1057
- #define PM_NODE_TYPE(node) ((enum pm_node_type) (node)->type)
1058
-
1059
- /**
1060
- * Return true if the type of the given node matches the given type.
1061
- */
1062
- #define PM_NODE_TYPE_P(node, type) (PM_NODE_TYPE(node) == (type))
1063
-
1064
- /**
1065
- * Return true if the given flag is set on the given node.
1066
- */
1067
- #define PM_NODE_FLAG_P(node, flag) ((((pm_node_t *)(node))->flags & (flag)) != 0)
1068
-
1069
1053
  /**
1070
1054
  * This is the base structure that represents a node in the syntax tree. It is
1071
1055
  * embedded into every node type.
@@ -1096,6 +1080,32 @@ typedef struct pm_node {
1096
1080
  pm_location_t location;
1097
1081
  } pm_node_t;
1098
1082
 
1083
+ /**
1084
+ * Cast the given node to the base pm_node_t type.
1085
+ */
1086
+ #define PM_NODE_UPCAST(node_) ((pm_node_t *) (node_))
1087
+
1088
+ /**
1089
+ * Cast the type to an enum to allow the compiler to provide exhaustiveness
1090
+ * checking.
1091
+ */
1092
+ #define PM_NODE_TYPE(node_) ((enum pm_node_type) (node_)->type)
1093
+
1094
+ /**
1095
+ * Return true if the type of the given node matches the given type.
1096
+ */
1097
+ #define PM_NODE_TYPE_P(node_, type_) (PM_NODE_TYPE(node_) == (type_))
1098
+
1099
+ /**
1100
+ * Return the flags associated with the given node.
1101
+ */
1102
+ #define PM_NODE_FLAGS(node_) (PM_NODE_UPCAST(node_)->flags)
1103
+
1104
+ /**
1105
+ * Return true if the given flag is set on the given node.
1106
+ */
1107
+ #define PM_NODE_FLAG_P(node_, flag_) ((PM_NODE_FLAGS(node_) & (flag_)) != 0)
1108
+
1099
1109
  /**
1100
1110
  * AliasGlobalVariableNode
1101
1111
  *
@@ -2214,6 +2224,19 @@ typedef struct pm_call_node {
2214
2224
  */
2215
2225
  pm_location_t closing_loc;
2216
2226
 
2227
+ /**
2228
+ * CallNode#equal_loc
2229
+ *
2230
+ * Represents the location of the equal sign, in the case that this is an attribute write.
2231
+ *
2232
+ * foo.bar = value
2233
+ * ^
2234
+ *
2235
+ * foo[bar] = value
2236
+ * ^
2237
+ */
2238
+ pm_location_t equal_loc;
2239
+
2217
2240
  /**
2218
2241
  * CallNode#block
2219
2242
  *
@@ -4084,11 +4107,16 @@ typedef struct pm_forwarding_parameter_node {
4084
4107
  /**
4085
4108
  * ForwardingSuperNode
4086
4109
  *
4087
- * Represents the use of the `super` keyword without parentheses or arguments.
4110
+ * Represents the use of the `super` keyword without parentheses or arguments, but which might have a block.
4088
4111
  *
4089
4112
  * super
4090
4113
  * ^^^^^
4091
4114
  *
4115
+ * super { 123 }
4116
+ * ^^^^^^^^^^^^^
4117
+ *
4118
+ * If it has any other arguments, it would be a `SuperNode` instead.
4119
+ *
4092
4120
  * Type: ::PM_FORWARDING_SUPER_NODE
4093
4121
  *
4094
4122
  * @extends pm_node_t
@@ -4100,6 +4128,8 @@ typedef struct pm_forwarding_super_node {
4100
4128
 
4101
4129
  /**
4102
4130
  * ForwardingSuperNode#block
4131
+ *
4132
+ * All other arguments are forwarded as normal, except the original block is replaced with the new block.
4103
4133
  */
4104
4134
  struct pm_block_node *block;
4105
4135
  } pm_forwarding_super_node_t;
@@ -7539,6 +7569,8 @@ typedef struct pm_string_node {
7539
7569
  * super foo, bar
7540
7570
  * ^^^^^^^^^^^^^^
7541
7571
  *
7572
+ * If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead.
7573
+ *
7542
7574
  * Type: ::PM_SUPER_NODE
7543
7575
  *
7544
7576
  * @extends pm_node_t
@@ -7560,6 +7592,8 @@ typedef struct pm_super_node {
7560
7592
 
7561
7593
  /**
7562
7594
  * SuperNode#arguments
7595
+ *
7596
+ * Can be only `nil` when there are empty parentheses, like `super()`.
7563
7597
  */
7564
7598
  struct pm_arguments_node *arguments;
7565
7599
 
@@ -250,6 +250,7 @@ typedef enum {
250
250
  PM_ERR_PARAMETER_WILD_LOOSE_COMMA,
251
251
  PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS,
252
252
  PM_ERR_PATTERN_CAPTURE_DUPLICATE,
253
+ PM_ERR_PATTERN_CAPTURE_IN_ALTERNATIVE,
253
254
  PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET,
254
255
  PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA,
255
256
  PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET,
@@ -311,6 +312,7 @@ typedef enum {
311
312
  PM_ERR_UNEXPECTED_INDEX_KEYWORDS,
312
313
  PM_ERR_UNEXPECTED_LABEL,
313
314
  PM_ERR_UNEXPECTED_MULTI_WRITE,
315
+ PM_ERR_UNEXPECTED_PARAMETER_DEFAULT_VALUE,
314
316
  PM_ERR_UNEXPECTED_RANGE_OPERATOR,
315
317
  PM_ERR_UNEXPECTED_SAFE_NAVIGATION,
316
318
  PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT,
@@ -91,11 +91,17 @@ typedef enum {
91
91
  /** The vendored version of prism in CRuby 3.4.x. */
92
92
  PM_OPTIONS_VERSION_CRUBY_3_4 = 2,
93
93
 
94
- /** The vendored version of prism in CRuby 3.5.x. */
94
+ /** The vendored version of prism in CRuby 4.0.x. */
95
95
  PM_OPTIONS_VERSION_CRUBY_3_5 = 3,
96
96
 
97
+ /** The vendored version of prism in CRuby 4.0.x. */
98
+ PM_OPTIONS_VERSION_CRUBY_4_0 = 3,
99
+
100
+ /** The vendored version of prism in CRuby 4.1.x. */
101
+ PM_OPTIONS_VERSION_CRUBY_4_1 = 4,
102
+
97
103
  /** The current version of prism. */
98
- PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_3_5
104
+ PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1
99
105
  } pm_options_version_t;
100
106
 
101
107
  /**
@@ -299,6 +299,9 @@ typedef enum {
299
299
  /** a rescue else statement within a do..end block */
300
300
  PM_CONTEXT_BLOCK_ELSE,
301
301
 
302
+ /** expressions in block parameters `foo do |...| end ` */
303
+ PM_CONTEXT_BLOCK_PARAMETERS,
304
+
302
305
  /** a rescue statement within a do..end block */
303
306
  PM_CONTEXT_BLOCK_RESCUE,
304
307
 
@@ -14,7 +14,7 @@
14
14
  /**
15
15
  * The minor version of the Prism library as an int.
16
16
  */
17
- #define PRISM_VERSION_MINOR 6
17
+ #define PRISM_VERSION_MINOR 7
18
18
 
19
19
  /**
20
20
  * The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
24
24
  /**
25
25
  * The version of the Prism library as a constant string.
26
26
  */
27
- #define PRISM_VERSION "1.6.0"
27
+ #define PRISM_VERSION "1.7.0"
28
28
 
29
29
  #endif
data/include/prism.h CHANGED
@@ -314,7 +314,7 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
314
314
  * dependencies. It is currently being integrated into
315
315
  * [CRuby](https://github.com/ruby/ruby),
316
316
  * [JRuby](https://github.com/jruby/jruby),
317
- * [TruffleRuby](https://github.com/oracle/truffleruby),
317
+ * [TruffleRuby](https://github.com/truffleruby/truffleruby),
318
318
  * [Sorbet](https://github.com/sorbet/sorbet), and
319
319
  * [Syntax Tree](https://github.com/ruby-syntax-tree/syntax_tree).
320
320
  *
@@ -724,6 +724,11 @@ module Prism
724
724
  table.field("closing_loc", location_inspect(closing_loc))
725
725
  end
726
726
 
727
+ # equal_loc
728
+ unless (equal_loc = node.equal_loc).nil?
729
+ table.field("equal_loc", location_inspect(equal_loc))
730
+ end
731
+
727
732
  # block
728
733
  unless (block = node.block).nil?
729
734
  table.field("block", port: true)
data/lib/prism/dsl.rb CHANGED
@@ -167,8 +167,8 @@ module Prism
167
167
  end
168
168
 
169
169
  # Create a new CallNode node.
170
- def call_node(source: default_source, node_id: 0, location: default_location, flags: 0, receiver: nil, call_operator_loc: nil, name: :"", message_loc: nil, opening_loc: nil, arguments: nil, closing_loc: nil, block: nil)
171
- CallNode.new(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, block)
170
+ def call_node(source: default_source, node_id: 0, location: default_location, flags: 0, receiver: nil, call_operator_loc: nil, name: :"", message_loc: nil, opening_loc: nil, arguments: nil, closing_loc: nil, equal_loc: nil, block: nil)
171
+ CallNode.new(source, node_id, location, flags, receiver, call_operator_loc, name, message_loc, opening_loc, arguments, closing_loc, equal_loc, block)
172
172
  end
173
173
 
174
174
  # Create a new CallOperatorWriteNode node.
data/lib/prism/ffi.rb CHANGED
@@ -432,8 +432,10 @@ module Prism
432
432
  1
433
433
  when /\A3\.4(\.\d+)?\z/
434
434
  2
435
- when /\A3\.5(\.\d+)?\z/
435
+ when /\A3\.5(\.\d+)?\z/, /\A4\.0(\.\d+)?\z/
436
436
  3
437
+ when /\A4\.1(\.\d+)?\z/
438
+ 4
437
439
  else
438
440
  if current
439
441
  raise CurrentVersionError, RUBY_VERSION
@@ -402,6 +402,7 @@ module Prism
402
402
  commands << [arguments, "#{indent}│ "]
403
403
  end
404
404
  commands << ["├── closing_loc: #{inspect_location(node.closing_loc)}\n", indent]
405
+ commands << ["├── equal_loc: #{inspect_location(node.equal_loc)}\n", indent]
405
406
  if (block = node.block).nil?
406
407
  commands << ["└── block: ∅\n", indent]
407
408
  else