prism 0.17.1 → 0.18.0

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