prism 0.17.1 → 0.18.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/Makefile +5 -5
  4. data/README.md +2 -2
  5. data/config.yml +26 -13
  6. data/docs/build_system.md +6 -6
  7. data/docs/building.md +1 -1
  8. data/docs/configuration.md +1 -0
  9. data/docs/encoding.md +68 -32
  10. data/docs/heredocs.md +1 -1
  11. data/docs/javascript.md +29 -1
  12. data/docs/ruby_api.md +14 -0
  13. data/ext/prism/api_node.c +74 -45
  14. data/ext/prism/extconf.rb +91 -127
  15. data/ext/prism/extension.c +1 -1
  16. data/ext/prism/extension.h +1 -1
  17. data/include/prism/ast.h +148 -133
  18. data/include/prism/diagnostic.h +27 -1
  19. data/include/prism/enc/pm_encoding.h +42 -1
  20. data/include/prism/parser.h +6 -0
  21. data/include/prism/version.h +3 -3
  22. data/lib/prism/compiler.rb +3 -3
  23. data/lib/prism/debug.rb +4 -0
  24. data/lib/prism/desugar_compiler.rb +1 -0
  25. data/lib/prism/dispatcher.rb +14 -14
  26. data/lib/prism/dot_visitor.rb +4334 -0
  27. data/lib/prism/dsl.rb +11 -11
  28. data/lib/prism/ffi.rb +3 -3
  29. data/lib/prism/mutation_compiler.rb +6 -6
  30. data/lib/prism/node.rb +182 -113
  31. data/lib/prism/node_ext.rb +61 -3
  32. data/lib/prism/parse_result.rb +46 -12
  33. data/lib/prism/serialize.rb +125 -131
  34. data/lib/prism/visitor.rb +3 -3
  35. data/lib/prism.rb +1 -0
  36. data/prism.gemspec +5 -1
  37. data/rbi/prism.rbi +83 -54
  38. data/sig/prism.rbs +47 -32
  39. data/src/diagnostic.c +61 -3
  40. data/src/enc/pm_big5.c +63 -0
  41. data/src/enc/pm_cp51932.c +57 -0
  42. data/src/enc/pm_euc_jp.c +10 -0
  43. data/src/enc/pm_gbk.c +5 -2
  44. data/src/enc/pm_tables.c +1478 -148
  45. data/src/node.c +33 -21
  46. data/src/prettyprint.c +1027 -925
  47. data/src/prism.c +925 -374
  48. data/src/regexp.c +12 -12
  49. data/src/serialize.c +36 -9
  50. metadata +6 -2
data/rbi/prism.rbi CHANGED
@@ -1025,6 +1025,56 @@ class Prism::CapturePatternNode < Prism::Node
1025
1025
  def inspect(inspector); end
1026
1026
  end
1027
1027
 
1028
+ # Represents the use of a case statement for pattern matching.
1029
+ #
1030
+ # case true
1031
+ # in false
1032
+ # end
1033
+ # ^^^^^^^^^
1034
+ class Prism::CaseMatchNode < Prism::Node
1035
+ sig { returns(T.nilable(Prism::Node)) }
1036
+ def predicate; end
1037
+
1038
+ sig { returns(T::Array[Prism::Node]) }
1039
+ def conditions; end
1040
+
1041
+ sig { returns(T.nilable(Prism::ElseNode)) }
1042
+ def consequent; end
1043
+
1044
+ sig { returns(Prism::Location) }
1045
+ def case_keyword_loc; end
1046
+
1047
+ sig { returns(Prism::Location) }
1048
+ def end_keyword_loc; end
1049
+
1050
+ sig { params(predicate: T.nilable(Prism::Node), conditions: T::Array[Prism::Node], consequent: T.nilable(Prism::ElseNode), case_keyword_loc: Prism::Location, end_keyword_loc: Prism::Location, location: Prism::Location).void }
1051
+ def initialize(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location); end
1052
+
1053
+ sig { params(visitor: Prism::Visitor).void }
1054
+ def accept(visitor); end
1055
+
1056
+ sig { returns(T::Array[T.nilable(Prism::Node)]) }
1057
+ def child_nodes; end
1058
+
1059
+ sig { returns(T::Array[T.nilable(Prism::Node)]) }
1060
+ def deconstruct; end
1061
+
1062
+ sig { params(params: T.untyped).returns(Prism::CaseMatchNode) }
1063
+ def copy(**params); end
1064
+
1065
+ sig { params(keys: T::Array[Symbol]).returns(T::Hash[Symbol, T.nilable(T.any(Prism::Node, T::Array[Prism::Node], String, Prism::Token, T::Array[Prism::Token], Prism::Location))]) }
1066
+ def deconstruct_keys(keys); end
1067
+
1068
+ sig { returns(String) }
1069
+ def case_keyword; end
1070
+
1071
+ sig { returns(String) }
1072
+ def end_keyword; end
1073
+
1074
+ sig { params(inspector: Prism::NodeInspector).returns(String) }
1075
+ def inspect(inspector); end
1076
+ end
1077
+
1028
1078
  # Represents the use of a case statement.
1029
1079
  #
1030
1080
  # case true
@@ -2765,6 +2815,9 @@ class Prism::IfNode < Prism::Node
2765
2815
  sig { returns(Prism::Node) }
2766
2816
  def predicate; end
2767
2817
 
2818
+ sig { returns(T.nilable(Prism::Location)) }
2819
+ def then_keyword_loc; end
2820
+
2768
2821
  sig { returns(T.nilable(Prism::StatementsNode)) }
2769
2822
  def statements; end
2770
2823
 
@@ -2774,8 +2827,8 @@ class Prism::IfNode < Prism::Node
2774
2827
  sig { returns(T.nilable(Prism::Location)) }
2775
2828
  def end_keyword_loc; end
2776
2829
 
2777
- sig { params(if_keyword_loc: T.nilable(Prism::Location), predicate: Prism::Node, statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::Node), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).void }
2778
- def initialize(if_keyword_loc, predicate, statements, consequent, end_keyword_loc, location); end
2830
+ sig { params(if_keyword_loc: T.nilable(Prism::Location), predicate: Prism::Node, then_keyword_loc: T.nilable(Prism::Location), statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::Node), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).void }
2831
+ def initialize(if_keyword_loc, predicate, then_keyword_loc, statements, consequent, end_keyword_loc, location); end
2779
2832
 
2780
2833
  sig { params(visitor: Prism::Visitor).void }
2781
2834
  def accept(visitor); end
@@ -2797,6 +2850,9 @@ class Prism::IfNode < Prism::Node
2797
2850
  sig { returns(T.nilable(String)) }
2798
2851
  def if_keyword; end
2799
2852
 
2853
+ sig { returns(T.nilable(String)) }
2854
+ def then_keyword; end
2855
+
2800
2856
  sig { returns(T.nilable(String)) }
2801
2857
  def end_keyword; end
2802
2858
 
@@ -4211,11 +4267,11 @@ class Prism::MatchWriteNode < Prism::Node
4211
4267
  sig { returns(Prism::CallNode) }
4212
4268
  def call; end
4213
4269
 
4214
- sig { returns(T::Array[Symbol]) }
4215
- def locals; end
4270
+ sig { returns(T::Array[Prism::Node]) }
4271
+ def targets; end
4216
4272
 
4217
- sig { params(call: Prism::CallNode, locals: T::Array[Symbol], location: Prism::Location).void }
4218
- def initialize(call, locals, location); end
4273
+ sig { params(call: Prism::CallNode, targets: T::Array[Prism::Node], location: Prism::Location).void }
4274
+ def initialize(call, targets, location); end
4219
4275
 
4220
4276
  sig { params(visitor: Prism::Visitor).void }
4221
4277
  def accept(visitor); end
@@ -5651,39 +5707,6 @@ class Prism::StatementsNode < Prism::Node
5651
5707
  def inspect(inspector); end
5652
5708
  end
5653
5709
 
5654
- # Represents the use of compile-time string concatenation.
5655
- #
5656
- # "foo" "bar"
5657
- # ^^^^^^^^^^^
5658
- class Prism::StringConcatNode < Prism::Node
5659
- sig { returns(Prism::Node) }
5660
- def left; end
5661
-
5662
- sig { returns(Prism::Node) }
5663
- def right; end
5664
-
5665
- sig { params(left: Prism::Node, right: Prism::Node, location: Prism::Location).void }
5666
- def initialize(left, right, location); end
5667
-
5668
- sig { params(visitor: Prism::Visitor).void }
5669
- def accept(visitor); end
5670
-
5671
- sig { returns(T::Array[T.nilable(Prism::Node)]) }
5672
- def child_nodes; end
5673
-
5674
- sig { returns(T::Array[T.nilable(Prism::Node)]) }
5675
- def deconstruct; end
5676
-
5677
- sig { params(params: T.untyped).returns(Prism::StringConcatNode) }
5678
- def copy(**params); end
5679
-
5680
- sig { params(keys: T::Array[Symbol]).returns(T::Hash[Symbol, T.nilable(T.any(Prism::Node, T::Array[Prism::Node], String, Prism::Token, T::Array[Prism::Token], Prism::Location))]) }
5681
- def deconstruct_keys(keys); end
5682
-
5683
- sig { params(inspector: Prism::NodeInspector).returns(String) }
5684
- def inspect(inspector); end
5685
- end
5686
-
5687
5710
  # Represents a string literal, a string contained within a `%w` list, or
5688
5711
  # plain string content within an interpolated string.
5689
5712
  #
@@ -5927,6 +5950,9 @@ class Prism::UnlessNode < Prism::Node
5927
5950
  sig { returns(Prism::Node) }
5928
5951
  def predicate; end
5929
5952
 
5953
+ sig { returns(T.nilable(Prism::Location)) }
5954
+ def then_keyword_loc; end
5955
+
5930
5956
  sig { returns(T.nilable(Prism::StatementsNode)) }
5931
5957
  def statements; end
5932
5958
 
@@ -5936,8 +5962,8 @@ class Prism::UnlessNode < Prism::Node
5936
5962
  sig { returns(T.nilable(Prism::Location)) }
5937
5963
  def end_keyword_loc; end
5938
5964
 
5939
- sig { params(keyword_loc: Prism::Location, predicate: Prism::Node, statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::ElseNode), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).void }
5940
- def initialize(keyword_loc, predicate, statements, consequent, end_keyword_loc, location); end
5965
+ sig { params(keyword_loc: Prism::Location, predicate: Prism::Node, then_keyword_loc: T.nilable(Prism::Location), statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::ElseNode), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).void }
5966
+ def initialize(keyword_loc, predicate, then_keyword_loc, statements, consequent, end_keyword_loc, location); end
5941
5967
 
5942
5968
  sig { params(visitor: Prism::Visitor).void }
5943
5969
  def accept(visitor); end
@@ -5959,6 +5985,9 @@ class Prism::UnlessNode < Prism::Node
5959
5985
  sig { returns(String) }
5960
5986
  def keyword; end
5961
5987
 
5988
+ sig { returns(T.nilable(String)) }
5989
+ def then_keyword; end
5990
+
5962
5991
  sig { returns(T.nilable(String)) }
5963
5992
  def end_keyword; end
5964
5993
 
@@ -6370,6 +6399,10 @@ class Prism::Visitor < Prism::BasicVisitor
6370
6399
  sig { params(node: Prism::CapturePatternNode).void }
6371
6400
  def visit_capture_pattern_node(node); end
6372
6401
 
6402
+ # Visit a CaseMatchNode node
6403
+ sig { params(node: Prism::CaseMatchNode).void }
6404
+ def visit_case_match_node(node); end
6405
+
6373
6406
  # Visit a CaseNode node
6374
6407
  sig { params(node: Prism::CaseNode).void }
6375
6408
  def visit_case_node(node); end
@@ -6810,10 +6843,6 @@ class Prism::Visitor < Prism::BasicVisitor
6810
6843
  sig { params(node: Prism::StatementsNode).void }
6811
6844
  def visit_statements_node(node); end
6812
6845
 
6813
- # Visit a StringConcatNode node
6814
- sig { params(node: Prism::StringConcatNode).void }
6815
- def visit_string_concat_node(node); end
6816
-
6817
6846
  # Visit a StringNode node
6818
6847
  sig { params(node: Prism::StringNode).void }
6819
6848
  def visit_string_node(node); end
@@ -6932,6 +6961,9 @@ module Prism::DSL
6932
6961
  # Create a new CapturePatternNode node
6933
6962
  sig { params(value: Prism::Node, target: Prism::Node, operator_loc: Prism::Location, location: Prism::Location).returns(Prism::CapturePatternNode) }
6934
6963
  def CapturePatternNode(value, target, operator_loc, location); end
6964
+ # Create a new CaseMatchNode node
6965
+ sig { params(predicate: T.nilable(Prism::Node), conditions: T::Array[Prism::Node], consequent: T.nilable(Prism::ElseNode), case_keyword_loc: Prism::Location, end_keyword_loc: Prism::Location, location: Prism::Location).returns(Prism::CaseMatchNode) }
6966
+ def CaseMatchNode(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location); end
6935
6967
  # Create a new CaseNode node
6936
6968
  sig { params(predicate: T.nilable(Prism::Node), conditions: T::Array[Prism::Node], consequent: T.nilable(Prism::ElseNode), case_keyword_loc: Prism::Location, end_keyword_loc: Prism::Location, location: Prism::Location).returns(Prism::CaseNode) }
6937
6969
  def CaseNode(predicate, conditions, consequent, case_keyword_loc, end_keyword_loc, location); end
@@ -7059,8 +7091,8 @@ module Prism::DSL
7059
7091
  sig { params(constant: T.nilable(Prism::Node), elements: T::Array[Prism::Node], rest: T.nilable(Prism::Node), opening_loc: T.nilable(Prism::Location), closing_loc: T.nilable(Prism::Location), location: Prism::Location).returns(Prism::HashPatternNode) }
7060
7092
  def HashPatternNode(constant, elements, rest, opening_loc, closing_loc, location); end
7061
7093
  # Create a new IfNode node
7062
- sig { params(if_keyword_loc: T.nilable(Prism::Location), predicate: Prism::Node, statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::Node), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).returns(Prism::IfNode) }
7063
- def IfNode(if_keyword_loc, predicate, statements, consequent, end_keyword_loc, location); end
7094
+ sig { params(if_keyword_loc: T.nilable(Prism::Location), predicate: Prism::Node, then_keyword_loc: T.nilable(Prism::Location), statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::Node), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).returns(Prism::IfNode) }
7095
+ def IfNode(if_keyword_loc, predicate, then_keyword_loc, statements, consequent, end_keyword_loc, location); end
7064
7096
  # Create a new ImaginaryNode node
7065
7097
  sig { params(numeric: Prism::Node, location: Prism::Location).returns(Prism::ImaginaryNode) }
7066
7098
  def ImaginaryNode(numeric, location); end
@@ -7152,8 +7184,8 @@ module Prism::DSL
7152
7184
  sig { params(value: Prism::Node, pattern: Prism::Node, operator_loc: Prism::Location, location: Prism::Location).returns(Prism::MatchRequiredNode) }
7153
7185
  def MatchRequiredNode(value, pattern, operator_loc, location); end
7154
7186
  # Create a new MatchWriteNode node
7155
- sig { params(call: Prism::CallNode, locals: T::Array[Symbol], location: Prism::Location).returns(Prism::MatchWriteNode) }
7156
- def MatchWriteNode(call, locals, location); end
7187
+ sig { params(call: Prism::CallNode, targets: T::Array[Prism::Node], location: Prism::Location).returns(Prism::MatchWriteNode) }
7188
+ def MatchWriteNode(call, targets, location); end
7157
7189
  # Create a new MissingNode node
7158
7190
  sig { params(location: Prism::Location).returns(Prism::MissingNode) }
7159
7191
  def MissingNode(location); end
@@ -7262,9 +7294,6 @@ module Prism::DSL
7262
7294
  # Create a new StatementsNode node
7263
7295
  sig { params(body: T::Array[Prism::Node], location: Prism::Location).returns(Prism::StatementsNode) }
7264
7296
  def StatementsNode(body, location); end
7265
- # Create a new StringConcatNode node
7266
- sig { params(left: Prism::Node, right: Prism::Node, location: Prism::Location).returns(Prism::StringConcatNode) }
7267
- def StringConcatNode(left, right, location); end
7268
7297
  # Create a new StringNode node
7269
7298
  sig { params(flags: Integer, opening_loc: T.nilable(Prism::Location), content_loc: Prism::Location, closing_loc: T.nilable(Prism::Location), unescaped: String, location: Prism::Location).returns(Prism::StringNode) }
7270
7299
  def StringNode(flags, opening_loc, content_loc, closing_loc, unescaped, location); end
@@ -7281,8 +7310,8 @@ module Prism::DSL
7281
7310
  sig { params(names: T::Array[Prism::Node], keyword_loc: Prism::Location, location: Prism::Location).returns(Prism::UndefNode) }
7282
7311
  def UndefNode(names, keyword_loc, location); end
7283
7312
  # Create a new UnlessNode node
7284
- sig { params(keyword_loc: Prism::Location, predicate: Prism::Node, statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::ElseNode), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).returns(Prism::UnlessNode) }
7285
- def UnlessNode(keyword_loc, predicate, statements, consequent, end_keyword_loc, location); end
7313
+ sig { params(keyword_loc: Prism::Location, predicate: Prism::Node, then_keyword_loc: T.nilable(Prism::Location), statements: T.nilable(Prism::StatementsNode), consequent: T.nilable(Prism::ElseNode), end_keyword_loc: T.nilable(Prism::Location), location: Prism::Location).returns(Prism::UnlessNode) }
7314
+ def UnlessNode(keyword_loc, predicate, then_keyword_loc, statements, consequent, end_keyword_loc, location); end
7286
7315
  # Create a new UntilNode node
7287
7316
  sig { params(keyword_loc: Prism::Location, closing_loc: T.nilable(Prism::Location), predicate: Prism::Node, statements: T.nilable(Prism::StatementsNode), flags: Integer, location: Prism::Location).returns(Prism::UntilNode) }
7288
7317
  def UntilNode(keyword_loc, closing_loc, predicate, statements, flags, location); end
data/sig/prism.rbs CHANGED
@@ -605,6 +605,35 @@ module Prism
605
605
 
606
606
  def inspect: (inspector: NodeInspector) -> String
607
607
  end
608
+ # Represents the use of a case statement for pattern matching.
609
+ #
610
+ # case true
611
+ # in false
612
+ # end
613
+ # ^^^^^^^^^
614
+ class CaseMatchNode < Node
615
+ attr_reader predicate: Node?
616
+ attr_reader conditions: Array[Node]
617
+ attr_reader consequent: ElseNode?
618
+ attr_reader case_keyword_loc: Location
619
+ attr_reader end_keyword_loc: Location
620
+
621
+ def initialize: (predicate: Node?, conditions: Array[Node], consequent: ElseNode?, case_keyword_loc: Location, end_keyword_loc: Location, location: Location) -> void
622
+ def accept: (visitor: Visitor) -> void
623
+ def set_newline_flag: (newline_marked: Array[bool]) -> void
624
+ def child_nodes: () -> Array[Node?]
625
+ def deconstruct: () -> Array[Node?]
626
+
627
+ def copy: (**untyped) -> CaseMatchNode
628
+
629
+ def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, (Node | Array[Node] | String | Token | Array[Token] | Location)?]
630
+
631
+ def case_keyword: () -> String
632
+
633
+ def end_keyword: () -> String
634
+
635
+ def inspect: (inspector: NodeInspector) -> String
636
+ end
608
637
  # Represents the use of a case statement.
609
638
  #
610
639
  # case true
@@ -1632,11 +1661,12 @@ module Prism
1632
1661
  class IfNode < Node
1633
1662
  attr_reader if_keyword_loc: Location?
1634
1663
  attr_reader predicate: Node
1664
+ attr_reader then_keyword_loc: Location?
1635
1665
  attr_reader statements: StatementsNode?
1636
1666
  attr_reader consequent: Node?
1637
1667
  attr_reader end_keyword_loc: Location?
1638
1668
 
1639
- def initialize: (if_keyword_loc: Location?, predicate: Node, statements: StatementsNode?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> void
1669
+ def initialize: (if_keyword_loc: Location?, predicate: Node, then_keyword_loc: Location?, statements: StatementsNode?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> void
1640
1670
  def accept: (visitor: Visitor) -> void
1641
1671
  def set_newline_flag: (newline_marked: Array[bool]) -> void
1642
1672
  def child_nodes: () -> Array[Node?]
@@ -1648,6 +1678,8 @@ module Prism
1648
1678
 
1649
1679
  def if_keyword: () -> String?
1650
1680
 
1681
+ def then_keyword: () -> String?
1682
+
1651
1683
  def end_keyword: () -> String?
1652
1684
 
1653
1685
  def inspect: (inspector: NodeInspector) -> String
@@ -2471,9 +2503,9 @@ module Prism
2471
2503
  # ^^^^^^^^^^^^^^^^^^^^
2472
2504
  class MatchWriteNode < Node
2473
2505
  attr_reader call: CallNode
2474
- attr_reader locals: Array[Symbol]
2506
+ attr_reader targets: Array[Node]
2475
2507
 
2476
- def initialize: (call: CallNode, locals: Array[Symbol], location: Location) -> void
2508
+ def initialize: (call: CallNode, targets: Array[Node], location: Location) -> void
2477
2509
  def accept: (visitor: Visitor) -> void
2478
2510
  def set_newline_flag: (newline_marked: Array[bool]) -> void
2479
2511
  def child_nodes: () -> Array[Node?]
@@ -3334,26 +3366,6 @@ module Prism
3334
3366
 
3335
3367
  def inspect: (inspector: NodeInspector) -> String
3336
3368
  end
3337
- # Represents the use of compile-time string concatenation.
3338
- #
3339
- # "foo" "bar"
3340
- # ^^^^^^^^^^^
3341
- class StringConcatNode < Node
3342
- attr_reader left: Node
3343
- attr_reader right: Node
3344
-
3345
- def initialize: (left: Node, right: Node, location: Location) -> void
3346
- def accept: (visitor: Visitor) -> void
3347
- def set_newline_flag: (newline_marked: Array[bool]) -> void
3348
- def child_nodes: () -> Array[Node?]
3349
- def deconstruct: () -> Array[Node?]
3350
-
3351
- def copy: (**untyped) -> StringConcatNode
3352
-
3353
- def deconstruct_keys: (keys: Array[Symbol]) -> Hash[Symbol, (Node | Array[Node] | String | Token | Array[Token] | Location)?]
3354
-
3355
- def inspect: (inspector: NodeInspector) -> String
3356
- end
3357
3369
  # Represents a string literal, a string contained within a `%w` list, or
3358
3370
  # plain string content within an interpolated string.
3359
3371
  #
@@ -3505,11 +3517,12 @@ module Prism
3505
3517
  class UnlessNode < Node
3506
3518
  attr_reader keyword_loc: Location
3507
3519
  attr_reader predicate: Node
3520
+ attr_reader then_keyword_loc: Location?
3508
3521
  attr_reader statements: StatementsNode?
3509
3522
  attr_reader consequent: ElseNode?
3510
3523
  attr_reader end_keyword_loc: Location?
3511
3524
 
3512
- def initialize: (keyword_loc: Location, predicate: Node, statements: StatementsNode?, consequent: ElseNode?, end_keyword_loc: Location?, location: Location) -> void
3525
+ def initialize: (keyword_loc: Location, predicate: Node, then_keyword_loc: Location?, statements: StatementsNode?, consequent: ElseNode?, end_keyword_loc: Location?, location: Location) -> void
3513
3526
  def accept: (visitor: Visitor) -> void
3514
3527
  def set_newline_flag: (newline_marked: Array[bool]) -> void
3515
3528
  def child_nodes: () -> Array[Node?]
@@ -3521,6 +3534,8 @@ module Prism
3521
3534
 
3522
3535
  def keyword: () -> String
3523
3536
 
3537
+ def then_keyword: () -> String?
3538
+
3524
3539
  def end_keyword: () -> String?
3525
3540
 
3526
3541
  def inspect: (inspector: NodeInspector) -> String
@@ -3803,6 +3818,9 @@ module Prism
3803
3818
  # Visit a CapturePatternNode node
3804
3819
  def visit_capture_pattern_node: (node: CapturePatternNode) -> void
3805
3820
 
3821
+ # Visit a CaseMatchNode node
3822
+ def visit_case_match_node: (node: CaseMatchNode) -> void
3823
+
3806
3824
  # Visit a CaseNode node
3807
3825
  def visit_case_node: (node: CaseNode) -> void
3808
3826
 
@@ -4133,9 +4151,6 @@ module Prism
4133
4151
  # Visit a StatementsNode node
4134
4152
  def visit_statements_node: (node: StatementsNode) -> void
4135
4153
 
4136
- # Visit a StringConcatNode node
4137
- def visit_string_concat_node: (node: StringConcatNode) -> void
4138
-
4139
4154
  # Visit a StringNode node
4140
4155
  def visit_string_node: (node: StringNode) -> void
4141
4156
 
@@ -4220,6 +4235,8 @@ module Prism
4220
4235
  def CallOrWriteNode: (receiver: Node?, call_operator_loc: Location?, message_loc: Location?, flags: Integer, read_name: Symbol, write_name: Symbol, operator_loc: Location, value: Node, location: Location) -> CallOrWriteNode
4221
4236
  # Create a new CapturePatternNode node
4222
4237
  def CapturePatternNode: (value: Node, target: Node, operator_loc: Location, location: Location) -> CapturePatternNode
4238
+ # Create a new CaseMatchNode node
4239
+ def CaseMatchNode: (predicate: Node?, conditions: Array[Node], consequent: ElseNode?, case_keyword_loc: Location, end_keyword_loc: Location, location: Location) -> CaseMatchNode
4223
4240
  # Create a new CaseNode node
4224
4241
  def CaseNode: (predicate: Node?, conditions: Array[Node], consequent: ElseNode?, case_keyword_loc: Location, end_keyword_loc: Location, location: Location) -> CaseNode
4225
4242
  # Create a new ClassNode node
@@ -4305,7 +4322,7 @@ module Prism
4305
4322
  # Create a new HashPatternNode node
4306
4323
  def HashPatternNode: (constant: Node?, elements: Array[Node], rest: Node?, opening_loc: Location?, closing_loc: Location?, location: Location) -> HashPatternNode
4307
4324
  # Create a new IfNode node
4308
- def IfNode: (if_keyword_loc: Location?, predicate: Node, statements: StatementsNode?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> IfNode
4325
+ def IfNode: (if_keyword_loc: Location?, predicate: Node, then_keyword_loc: Location?, statements: StatementsNode?, consequent: Node?, end_keyword_loc: Location?, location: Location) -> IfNode
4309
4326
  # Create a new ImaginaryNode node
4310
4327
  def ImaginaryNode: (numeric: Node, location: Location) -> ImaginaryNode
4311
4328
  # Create a new ImplicitNode node
@@ -4367,7 +4384,7 @@ module Prism
4367
4384
  # Create a new MatchRequiredNode node
4368
4385
  def MatchRequiredNode: (value: Node, pattern: Node, operator_loc: Location, location: Location) -> MatchRequiredNode
4369
4386
  # Create a new MatchWriteNode node
4370
- def MatchWriteNode: (call: CallNode, locals: Array[Symbol], location: Location) -> MatchWriteNode
4387
+ def MatchWriteNode: (call: CallNode, targets: Array[Node], location: Location) -> MatchWriteNode
4371
4388
  # Create a new MissingNode node
4372
4389
  def MissingNode: (location: Location) -> MissingNode
4373
4390
  # Create a new ModuleNode node
@@ -4440,8 +4457,6 @@ module Prism
4440
4457
  def SplatNode: (operator_loc: Location, expression: Node?, location: Location) -> SplatNode
4441
4458
  # Create a new StatementsNode node
4442
4459
  def StatementsNode: (body: Array[Node], location: Location) -> StatementsNode
4443
- # Create a new StringConcatNode node
4444
- def StringConcatNode: (left: Node, right: Node, location: Location) -> StringConcatNode
4445
4460
  # Create a new StringNode node
4446
4461
  def StringNode: (flags: Integer, opening_loc: Location?, content_loc: Location, closing_loc: Location?, unescaped: String, location: Location) -> StringNode
4447
4462
  # Create a new SuperNode node
@@ -4453,7 +4468,7 @@ module Prism
4453
4468
  # Create a new UndefNode node
4454
4469
  def UndefNode: (names: Array[Node], keyword_loc: Location, location: Location) -> UndefNode
4455
4470
  # Create a new UnlessNode node
4456
- def UnlessNode: (keyword_loc: Location, predicate: Node, statements: StatementsNode?, consequent: ElseNode?, end_keyword_loc: Location?, location: Location) -> UnlessNode
4471
+ def UnlessNode: (keyword_loc: Location, predicate: Node, then_keyword_loc: Location?, statements: StatementsNode?, consequent: ElseNode?, end_keyword_loc: Location?, location: Location) -> UnlessNode
4457
4472
  # Create a new UntilNode node
4458
4473
  def UntilNode: (keyword_loc: Location, closing_loc: Location?, predicate: Node, statements: StatementsNode?, flags: Integer, location: Location) -> UntilNode
4459
4474
  # Create a new WhenNode node
data/src/diagnostic.c CHANGED
@@ -54,12 +54,14 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
54
54
  [PM_ERR_ALIAS_ARGUMENT] = "Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable",
55
55
  [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = "Unexpected `&&=` in a multiple assignment",
56
56
  [PM_ERR_ARGUMENT_AFTER_BLOCK] = "Unexpected argument after a block argument",
57
+ [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = "Unexpected argument after `...`",
57
58
  [PM_ERR_ARGUMENT_BARE_HASH] = "Unexpected bare hash argument",
58
59
  [PM_ERR_ARGUMENT_BLOCK_MULTI] = "Multiple block arguments; only one block is allowed",
59
60
  [PM_ERR_ARGUMENT_FORMAL_CLASS] = "Invalid formal argument; formal argument cannot be a class variable",
60
61
  [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = "Invalid formal argument; formal argument cannot be a constant",
61
62
  [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = "Invalid formal argument; formal argument cannot be a global variable",
62
63
  [PM_ERR_ARGUMENT_FORMAL_IVAR] = "Invalid formal argument; formal argument cannot be an instance variable",
64
+ [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = "Unexpected `...` in an non-parenthesized call",
63
65
  [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = "Unexpected `&` when the parent method is not forwarding",
64
66
  [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = "Unexpected `...` when the parent method is not forwarding",
65
67
  [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = "Unexpected `*` when the parent method is not forwarding",
@@ -85,6 +87,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
85
87
  [PM_ERR_CANNOT_PARSE_STRING_PART] = "Cannot parse the string part",
86
88
  [PM_ERR_CASE_EXPRESSION_AFTER_CASE] = "Expected an expression after `case`",
87
89
  [PM_ERR_CASE_EXPRESSION_AFTER_WHEN] = "Expected an expression after `when`",
90
+ [PM_ERR_CASE_MATCH_MISSING_PREDICATE] = "Expected a predicate for a case matching statement",
88
91
  [PM_ERR_CASE_MISSING_CONDITIONS] = "Expected a `when` or `in` clause after `case`",
89
92
  [PM_ERR_CASE_TERM] = "Expected an `end` to close the `case` statement",
90
93
  [PM_ERR_CLASS_IN_METHOD] = "Unexpected class definition in a method body",
@@ -199,7 +202,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
199
202
  [PM_ERR_PARAMETER_NAME_REPEAT] = "Repeated parameter name",
200
203
  [PM_ERR_PARAMETER_NO_DEFAULT] = "Expected a default value for the parameter",
201
204
  [PM_ERR_PARAMETER_NO_DEFAULT_KW] = "Expected a default value for the keyword parameter",
202
- [PM_ERR_PARAMETER_NUMBERED_RESERVED] = "Token reserved for a numbered parameter",
205
+ [PM_ERR_PARAMETER_NUMBERED_RESERVED] = "%.2s is reserved for a numbered parameter",
203
206
  [PM_ERR_PARAMETER_ORDER] = "Unexpected parameter order",
204
207
  [PM_ERR_PARAMETER_SPLAT_MULTI] = "Unexpected multiple `*` splat parameters",
205
208
  [PM_ERR_PARAMETER_STAR] = "Unexpected parameter `*`",
@@ -244,6 +247,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
244
247
  [PM_ERR_UNARY_RECEIVER_PLUS] = "Expected a receiver for unary `+`",
245
248
  [PM_ERR_UNARY_RECEIVER_TILDE] = "Expected a receiver for unary `~`",
246
249
  [PM_ERR_UNTIL_TERM] = "Expected an `end` to close the `until` statement",
250
+ [PM_ERR_VOID_EXPRESSION] = "Unexpected void value expression",
247
251
  [PM_ERR_WHILE_TERM] = "Expected an `end` to close the `while` statement",
248
252
  [PM_ERR_WRITE_TARGET_READONLY] = "Immutable variable as a write target",
249
253
  [PM_ERR_WRITE_TARGET_UNEXPECTED] = "Unexpected write target",
@@ -252,13 +256,16 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
252
256
  [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = "Ambiguous first argument; put parentheses or a space even after `+` operator",
253
257
  [PM_WARN_AMBIGUOUS_PREFIX_STAR] = "Ambiguous `*` has been interpreted as an argument prefix",
254
258
  [PM_WARN_AMBIGUOUS_SLASH] = "Ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator",
259
+ [PM_WARN_END_IN_METHOD] = "END in method; use at_exit",
255
260
  };
256
261
 
257
262
  static const char*
258
263
  pm_diagnostic_message(pm_diagnostic_id_t diag_id) {
259
264
  assert(diag_id < PM_DIAGNOSTIC_ID_LEN);
265
+
260
266
  const char *message = diagnostic_messages[diag_id];
261
267
  assert(message);
268
+
262
269
  return message;
263
270
  }
264
271
 
@@ -270,7 +277,57 @@ pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t *
270
277
  pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) calloc(sizeof(pm_diagnostic_t), 1);
271
278
  if (diagnostic == NULL) return false;
272
279
 
273
- *diagnostic = (pm_diagnostic_t) { .start = start, .end = end, .message = pm_diagnostic_message(diag_id) };
280
+ *diagnostic = (pm_diagnostic_t) {
281
+ .start = start,
282
+ .end = end,
283
+ .message = pm_diagnostic_message(diag_id),
284
+ .owned = false
285
+ };
286
+
287
+ pm_list_append(list, (pm_list_node_t *) diagnostic);
288
+ return true;
289
+ }
290
+
291
+ /**
292
+ * Append a diagnostic to the given list of diagnostics that is using a format
293
+ * string for its message.
294
+ */
295
+ bool
296
+ pm_diagnostic_list_append_format(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id, ...) {
297
+ va_list arguments;
298
+ va_start(arguments, diag_id);
299
+
300
+ const char *format = pm_diagnostic_message(diag_id);
301
+ int result = vsnprintf(NULL, 0, format, arguments);
302
+ va_end(arguments);
303
+
304
+ if (result < 0) {
305
+ return false;
306
+ }
307
+
308
+ pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) calloc(sizeof(pm_diagnostic_t), 1);
309
+ if (diagnostic == NULL) {
310
+ return false;
311
+ }
312
+
313
+ size_t length = (size_t) (result + 1);
314
+ char *message = (char *) malloc(length);
315
+ if (message == NULL) {
316
+ free(diagnostic);
317
+ return false;
318
+ }
319
+
320
+ va_start(arguments, diag_id);
321
+ vsnprintf(message, length, format, arguments);
322
+ va_end(arguments);
323
+
324
+ *diagnostic = (pm_diagnostic_t) {
325
+ .start = start,
326
+ .end = end,
327
+ .message = message,
328
+ .owned = true
329
+ };
330
+
274
331
  pm_list_append(list, (pm_list_node_t *) diagnostic);
275
332
  return true;
276
333
  }
@@ -284,8 +341,9 @@ pm_diagnostic_list_free(pm_list_t *list) {
284
341
 
285
342
  for (node = list->head; node != NULL; node = next) {
286
343
  next = node->next;
287
-
288
344
  pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) node;
345
+
346
+ if (diagnostic->owned) free((void *) diagnostic->message);
289
347
  free(diagnostic);
290
348
  }
291
349
  }
data/src/enc/pm_big5.c CHANGED
@@ -15,6 +15,22 @@ pm_encoding_big5_char_width(const uint8_t *b, ptrdiff_t n) {
15
15
  return 0;
16
16
  }
17
17
 
18
+ static size_t
19
+ pm_encoding_big5_star_char_width(const uint8_t *b, ptrdiff_t n) {
20
+ // These are the single byte characters.
21
+ if (*b < 0x80) {
22
+ return 1;
23
+ }
24
+
25
+ // These are the double byte characters.
26
+ if ((n > 1) && (b[0] >= 0x87 && b[0] <= 0xFE) &&
27
+ ((b[1] >= 0x40 && b[1] <= 0x7E) || (b[1] >= 0xA1 && b[1] <= 0xFE))) {
28
+ return 2;
29
+ }
30
+
31
+ return 0;
32
+ }
33
+
18
34
  static size_t
19
35
  pm_encoding_big5_alpha_char(const uint8_t *b, ptrdiff_t n) {
20
36
  if (pm_encoding_big5_char_width(b, n) == 1) {
@@ -24,6 +40,15 @@ pm_encoding_big5_alpha_char(const uint8_t *b, ptrdiff_t n) {
24
40
  }
25
41
  }
26
42
 
43
+ static size_t
44
+ pm_encoding_big5_star_alpha_char(const uint8_t *b, ptrdiff_t n) {
45
+ if (pm_encoding_big5_star_char_width(b, n) == 1) {
46
+ return pm_encoding_ascii_alpha_char(b, n);
47
+ } else {
48
+ return 0;
49
+ }
50
+ }
51
+
27
52
  static size_t
28
53
  pm_encoding_big5_alnum_char(const uint8_t *b, ptrdiff_t n) {
29
54
  if (pm_encoding_big5_char_width(b, n) == 1) {
@@ -33,6 +58,15 @@ pm_encoding_big5_alnum_char(const uint8_t *b, ptrdiff_t n) {
33
58
  }
34
59
  }
35
60
 
61
+ static size_t
62
+ pm_encoding_big5_star_alnum_char(const uint8_t *b, ptrdiff_t n) {
63
+ if (pm_encoding_big5_star_char_width(b, n) == 1) {
64
+ return pm_encoding_ascii_alnum_char(b, n);
65
+ } else {
66
+ return 0;
67
+ }
68
+ }
69
+
36
70
  static bool
37
71
  pm_encoding_big5_isupper_char(const uint8_t *b, ptrdiff_t n) {
38
72
  if (pm_encoding_big5_char_width(b, n) == 1) {
@@ -42,6 +76,15 @@ pm_encoding_big5_isupper_char(const uint8_t *b, ptrdiff_t n) {
42
76
  }
43
77
  }
44
78
 
79
+ static bool
80
+ pm_encoding_big5_star_isupper_char(const uint8_t *b, ptrdiff_t n) {
81
+ if (pm_encoding_big5_star_char_width(b, n) == 1) {
82
+ return pm_encoding_ascii_isupper_char(b, n);
83
+ } else {
84
+ return false;
85
+ }
86
+ }
87
+
45
88
  /** Big5 encoding */
46
89
  pm_encoding_t pm_encoding_big5 = {
47
90
  .name = "big5",
@@ -51,3 +94,23 @@ pm_encoding_t pm_encoding_big5 = {
51
94
  .isupper_char = pm_encoding_big5_isupper_char,
52
95
  .multibyte = true
53
96
  };
97
+
98
+ /** Big5-HKSCS encoding */
99
+ pm_encoding_t pm_encoding_big5_hkscs = {
100
+ .name = "big5-hkscs",
101
+ .char_width = pm_encoding_big5_star_char_width,
102
+ .alnum_char = pm_encoding_big5_star_alnum_char,
103
+ .alpha_char = pm_encoding_big5_star_alpha_char,
104
+ .isupper_char = pm_encoding_big5_star_isupper_char,
105
+ .multibyte = true
106
+ };
107
+
108
+ /** Big5-UAO encoding */
109
+ pm_encoding_t pm_encoding_big5_uao = {
110
+ .name = "big5-uao",
111
+ .char_width = pm_encoding_big5_star_char_width,
112
+ .alnum_char = pm_encoding_big5_star_alnum_char,
113
+ .alpha_char = pm_encoding_big5_star_alpha_char,
114
+ .isupper_char = pm_encoding_big5_star_isupper_char,
115
+ .multibyte = true
116
+ };