herb 0.11.1 → 0.11.2

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 (247) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/config.yml +6 -0
  4. data/ext/herb/extconf.rb +8 -31
  5. data/ext/herb/nodes.c +75 -75
  6. data/ext/herb/parser_options_helpers.c +26 -0
  7. data/lib/herb/analysis/partial_index.rb +1 -1
  8. data/lib/herb/analysis/partial_resolution.rb +27 -0
  9. data/lib/herb/ast/helpers.rb +1 -1
  10. data/lib/herb/configuration.rb +11 -1
  11. data/lib/herb/dev/classifier.rb +1 -1
  12. data/lib/herb/engine/compiler.rb +5 -8
  13. data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
  14. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  15. data/lib/herb/engine/slots/visitor.rb +32 -4
  16. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  17. data/lib/herb/parser_options.rb +6 -3
  18. data/lib/herb/project.rb +19 -8
  19. data/lib/herb/version.rb +1 -1
  20. data/lib/herb.rb +1 -1
  21. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  22. data/sig/herb/configuration.rbs +3 -0
  23. data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
  24. data/sig/herb/engine/slots/visitor.rbs +14 -0
  25. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  26. data/sig/herb/parser_options.rbs +6 -4
  27. data/sig/herb.rbs +2 -2
  28. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  29. data/src/analyze/action_view/generated_handlers.c +36 -36
  30. data/src/analyze/action_view/image_tag.c +7 -3
  31. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  32. data/src/analyze/action_view/link_to.c +23 -23
  33. data/src/analyze/action_view/registry.c +7 -3
  34. data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
  35. data/src/analyze/action_view/tag_helpers.c +139 -90
  36. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  37. data/src/analyze/analyze.c +35 -19
  38. data/src/analyze/analyze_helpers.c +161 -188
  39. data/src/analyze/analyzed_ruby.c +8 -7
  40. data/src/analyze/control_type.c +29 -22
  41. data/src/analyze/herb_directives.c +16 -20
  42. data/src/analyze/iteration_nodes.c +69 -24
  43. data/src/analyze/parse_errors.c +32 -22
  44. data/src/analyze/postfix_conditionals.c +23 -13
  45. data/src/analyze/prism_annotate.c +29 -28
  46. data/src/analyze/render_nodes.c +51 -41
  47. data/src/analyze/strict_locals.c +14 -15
  48. data/src/analyze/ternary_conditionals.c +14 -10
  49. data/src/herb.c +10 -8
  50. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  51. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  52. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  53. data/src/include/analyze/analyze.h +3 -2
  54. data/src/include/analyze/analyzed_ruby.h +4 -2
  55. data/src/include/analyze/helpers.h +6 -6
  56. data/src/include/herb.h +3 -2
  57. data/src/include/parser/parser_options.h +5 -0
  58. data/src/include/prism/prism_context.h +12 -12
  59. data/src/include/prism/prism_helpers.h +30 -0
  60. data/src/include/prism_version.h +11 -0
  61. data/src/include/version.h +1 -1
  62. data/src/parser/parser_helpers.c +1 -2
  63. data/src/parser.c +6 -7
  64. data/src/parser_options_defaults.c +1 -0
  65. data/src/prism/prism_helpers.c +84 -50
  66. data/src/prism/ruby_parser.c +20 -20
  67. data/templates/ext/herb/nodes.c.erb +5 -5
  68. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  69. data/templates/java/nodes.c.erb +6 -6
  70. data/templates/java/parser_options_helpers.c.erb +41 -2
  71. data/templates/java/parser_options_helpers.h.erb +2 -1
  72. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  73. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  74. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  75. data/templates/lib/herb/parser_options.rb.erb +1 -1
  76. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  77. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  78. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  79. data/templates/src/include/parser/parser_options.h.erb +10 -0
  80. data/templates/src/include/prism_version.h.erb +17 -0
  81. data/templates/src/parser_options_defaults.c.erb +1 -1
  82. data/templates/template.rb +17 -2
  83. data/templates/wasm/nodes.cpp.erb +5 -5
  84. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  85. data/vendor/prism/Rakefile +76 -7
  86. data/vendor/prism/config.yml +174 -161
  87. data/vendor/prism/include/prism/arena.h +45 -0
  88. data/vendor/prism/include/prism/arena.hpp +42 -0
  89. data/vendor/prism/include/prism/ast.h +2738 -611
  90. data/vendor/prism/include/prism/ast.hpp +641 -0
  91. data/vendor/prism/include/prism/buffer.h +60 -0
  92. data/vendor/prism/include/prism/buffer.hpp +55 -0
  93. data/vendor/prism/include/prism/comments.h +72 -0
  94. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  95. data/vendor/prism/include/prism/compiler/align.h +36 -0
  96. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  97. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  98. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  99. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  100. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  101. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  102. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  103. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  104. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  105. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  106. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  107. data/vendor/prism/include/prism/compiler/format.h +27 -0
  108. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  109. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  110. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  111. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  112. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  113. data/vendor/prism/include/prism/constant_pool.h +106 -0
  114. data/vendor/prism/include/prism/diagnostic.h +55 -402
  115. data/vendor/prism/include/prism/errors_format.h +61 -0
  116. data/vendor/prism/include/prism/excludes.h +29 -0
  117. data/vendor/prism/include/prism/integer.h +41 -0
  118. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  119. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  120. data/vendor/prism/include/prism/internal/arena.h +108 -0
  121. data/vendor/prism/include/prism/internal/bit.h +42 -0
  122. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  123. data/vendor/prism/include/prism/internal/char.h +145 -0
  124. data/vendor/prism/include/prism/internal/comments.h +54 -0
  125. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  126. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  127. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  128. data/vendor/prism/include/prism/internal/integer.h +68 -0
  129. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  130. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  131. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  132. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  133. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  134. data/vendor/prism/include/prism/internal/node.h +42 -0
  135. data/vendor/prism/include/prism/internal/options.h +232 -0
  136. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  137. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  138. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  139. data/vendor/prism/include/prism/internal/source.h +72 -0
  140. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  141. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  142. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  143. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  144. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  145. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  146. data/vendor/prism/include/prism/json.h +40 -0
  147. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  148. data/vendor/prism/include/prism/magic_comments.h +53 -0
  149. data/vendor/prism/include/prism/node.h +59 -49
  150. data/vendor/prism/include/prism/node.hpp +272 -0
  151. data/vendor/prism/include/prism/node_type.hpp +38 -0
  152. data/vendor/prism/include/prism/options.h +154 -279
  153. data/vendor/prism/include/prism/options.hpp +43 -0
  154. data/vendor/prism/include/prism/parser.h +367 -870
  155. data/vendor/prism/include/prism/parser.hpp +274 -0
  156. data/vendor/prism/include/prism/prettyprint.h +14 -9
  157. data/vendor/prism/include/prism/serialize.h +123 -0
  158. data/vendor/prism/include/prism/source.h +163 -0
  159. data/vendor/prism/include/prism/stream.h +36 -0
  160. data/vendor/prism/include/prism/string_query.h +82 -0
  161. data/vendor/prism/include/prism/stringy.h +61 -0
  162. data/vendor/prism/include/prism/stringy.hpp +31 -0
  163. data/vendor/prism/include/prism/version.h +20 -3
  164. data/vendor/prism/include/prism.h +35 -320
  165. data/vendor/prism/include/prism.hpp +24 -0
  166. data/vendor/prism/src/arena.c +122 -0
  167. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  168. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  169. data/vendor/prism/src/comments.c +455 -0
  170. data/vendor/prism/src/constant_pool.c +406 -0
  171. data/vendor/prism/src/diagnostic.c +120 -68
  172. data/vendor/prism/src/encoding.c +8 -3
  173. data/vendor/prism/src/errors_format.c +519 -0
  174. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  175. data/vendor/prism/src/json.c +5733 -0
  176. data/vendor/prism/src/line_offset_list.c +100 -0
  177. data/vendor/prism/src/list.c +24 -0
  178. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  179. data/vendor/prism/src/node.c +3465 -7787
  180. data/vendor/prism/src/options.c +161 -54
  181. data/vendor/prism/src/parser.c +371 -0
  182. data/vendor/prism/src/prettyprint.c +421 -354
  183. data/vendor/prism/src/prism.c +8522 -7280
  184. data/vendor/prism/src/regexp.c +960 -45
  185. data/vendor/prism/src/serialize.c +2434 -2048
  186. data/vendor/prism/src/source.c +524 -0
  187. data/vendor/prism/src/static_literals.c +303 -360
  188. data/vendor/prism/src/string_query.c +180 -0
  189. data/vendor/prism/src/stringy.c +61 -0
  190. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  191. data/vendor/prism/src/strpbrk.c +447 -0
  192. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  193. data/vendor/prism/src/xxh3.c +292 -0
  194. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  195. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  196. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  197. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  198. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  199. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  200. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  201. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  202. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  203. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  204. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  205. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  206. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  207. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  208. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  209. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  210. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  211. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  212. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  213. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  214. data/vendor/prism/templates/src/json.c.erb +130 -0
  215. data/vendor/prism/templates/src/node.c.erb +79 -236
  216. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  217. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  218. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  219. data/vendor/prism/templates/template.rb +193 -91
  220. metadata +100 -42
  221. data/vendor/prism/include/prism/defines.h +0 -260
  222. data/vendor/prism/include/prism/pack.h +0 -163
  223. data/vendor/prism/include/prism/regexp.h +0 -43
  224. data/vendor/prism/include/prism/static_literals.h +0 -121
  225. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  226. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  227. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  228. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  229. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  230. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  231. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  232. data/vendor/prism/src/pack.c +0 -509
  233. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  234. data/vendor/prism/src/util/pm_list.c +0 -49
  235. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  236. data/vendor/prism/src/util/pm_string.c +0 -381
  237. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  238. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  239. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  240. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  241. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  242. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  243. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  244. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  245. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  246. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  247. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
@@ -1,4 +1,14 @@
1
+ #--
2
+ # rbs_inline: enabled
3
+
1
4
  module Prism
5
+ # @rbs!
6
+ # interface _Visitor
7
+ # <% nodes.each do |node| %>
8
+ # def visit_<%= node.human %>: (<%= node.name %>) -> void
9
+ # <% end %>
10
+ # end
11
+
2
12
  # A class that knows how to walk down the tree. None of the individual visit
3
13
  # methods are implemented on this visitor, so it forces the consumer to
4
14
  # implement each one that they need. For a default implementation that
@@ -6,18 +16,24 @@ module Prism
6
16
  class BasicVisitor
7
17
  # Calls `accept` on the given node if it is not `nil`, which in turn should
8
18
  # call back into this visitor by calling the appropriate `visit_*` method.
19
+ #
20
+ #: (node? node) -> void
9
21
  def visit(node)
10
22
  # @type self: _Visitor
11
23
  node&.accept(self)
12
24
  end
13
25
 
14
26
  # Visits each node in `nodes` by calling `accept` on each one.
27
+ #
28
+ #: (Array[node?] nodes) -> void
15
29
  def visit_all(nodes)
16
30
  # @type self: _Visitor
17
31
  nodes.each { |node| node&.accept(self) }
18
32
  end
19
33
 
20
34
  # Visits the child nodes of `node` by calling `accept` on each one.
35
+ #
36
+ #: (node node) -> void
21
37
  def visit_child_nodes(node)
22
38
  # @type self: _Visitor
23
39
  node.each_child_node { |node| node.accept(self) }
@@ -47,6 +63,8 @@ module Prism
47
63
  <%- nodes.each_with_index do |node, index| -%>
48
64
  <%= "\n" if index != 0 -%>
49
65
  # Visit a <%= node.name %> node
66
+ #
67
+ #: (<%= node.name %> node) -> void
50
68
  def visit_<%= node.human %>(node)
51
69
  node.each_child_node { |node| node.accept(self) }
52
70
  end
@@ -1,4 +1,18 @@
1
- #include "prism/diagnostic.h"
1
+ #include "prism/internal/diagnostic.h"
2
+
3
+ #include "prism/compiler/assume.h"
4
+ #include "prism/compiler/inline.h"
5
+
6
+ #include "prism/internal/allocator.h"
7
+ #include "prism/internal/arena.h"
8
+ #include "prism/internal/list.h"
9
+
10
+ #include <assert.h>
11
+ #include <inttypes.h>
12
+ #include <stdarg.h>
13
+ #include <stdio.h>
14
+ #include <stdlib.h>
15
+ #include <string.h>
2
16
 
3
17
  #define PM_DIAGNOSTIC_ID_MAX <%= errors.length + warnings.length %>
4
18
 
@@ -75,16 +89,16 @@ typedef struct {
75
89
  * * `PM_WARNING_LEVEL_VERBOSE` - Warnings that appear with `-w`, as in `ruby -w -c -e 'code'`.
76
90
  */
77
91
  static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
78
- // Special error that can be replaced
92
+ /* Special error that can be replaced */
79
93
  [PM_ERR_CANNOT_PARSE_EXPRESSION] = { "cannot parse the expression", PM_ERROR_LEVEL_SYNTAX },
80
94
 
81
- // Errors that should raise argument errors
95
+ /* Errors that should raise argument errors */
82
96
  [PM_ERR_INVALID_ENCODING_MAGIC_COMMENT] = { "unknown or invalid encoding in the magic comment", PM_ERROR_LEVEL_ARGUMENT },
83
97
 
84
- // Errors that should raise load errors
98
+ /* Errors that should raise load errors */
85
99
  [PM_ERR_SCRIPT_NOT_FOUND] = { "no Ruby script found in input", PM_ERROR_LEVEL_LOAD },
86
100
 
87
- // Errors that should raise syntax errors
101
+ /* Errors that should raise syntax errors */
88
102
  [PM_ERR_ALIAS_ARGUMENT] = { "invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", PM_ERROR_LEVEL_SYNTAX },
89
103
  [PM_ERR_ALIAS_ARGUMENT_NUMBERED_REFERENCE] = { "invalid argument being passed to `alias`; can't make alias for the number variables", PM_ERROR_LEVEL_SYNTAX },
90
104
  [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = { "unexpected `&&=` in a multiple assignment", PM_ERROR_LEVEL_SYNTAX },
@@ -102,6 +116,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
102
116
  [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX },
103
117
  [PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX },
104
118
  [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX },
119
+ [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA] = { "unexpected ... in lambda argument", PM_ERROR_LEVEL_SYNTAX },
120
+ [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK] = { "unexpected ... in block argument", PM_ERROR_LEVEL_SYNTAX },
105
121
  [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX },
106
122
  [PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR] = { "unexpected `**`; no anonymous keyword rest parameter", PM_ERROR_LEVEL_SYNTAX },
107
123
  [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_SYNTAX },
@@ -146,6 +162,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
146
162
  [PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX },
147
163
  [PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX },
148
164
  [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX },
165
+ [PM_ERR_DEF_ENDLESS_DO_BLOCK] = { "unexpected `do` for block in an endless method definition", PM_ERROR_LEVEL_SYNTAX },
149
166
  [PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX },
150
167
  [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX },
151
168
  [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "unexpected %s; expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX },
@@ -327,13 +344,15 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
327
344
  [PM_ERR_PATTERN_TERM_PAREN] = { "expected a `)` to close the pattern expression", PM_ERROR_LEVEL_SYNTAX },
328
345
  [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = { "unexpected `||=` in a multiple assignment", PM_ERROR_LEVEL_SYNTAX },
329
346
  [PM_ERR_REGEXP_ENCODING_OPTION_MISMATCH] = { "regexp encoding option '%c' differs from source encoding '%s'", PM_ERROR_LEVEL_SYNTAX },
347
+ [PM_ERR_REGEXP_ESCAPED_NON_ASCII_IN_UTF8] = { "escaped non ASCII character in UTF-8 regexp: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
330
348
  [PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING] = { "incompatible character encoding: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
331
- [PM_ERR_REGEXP_NON_ESCAPED_MBC] = { "/.../n has a non escaped non ASCII character in non ASCII-8BIT script: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
349
+ [PM_ERR_REGEXP_INVALID_CHAR_PROPERTY] = { "invalid character property name {%.*s}: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
332
350
  [PM_ERR_REGEXP_INVALID_UNICODE_RANGE] = { "invalid Unicode range: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
351
+ [PM_ERR_REGEXP_NON_ESCAPED_MBC] = { "/.../n has a non escaped non ASCII character in non ASCII-8BIT script: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
333
352
  [PM_ERR_REGEXP_PARSE_ERROR] = { "%s", PM_ERROR_LEVEL_SYNTAX },
334
353
  [PM_ERR_REGEXP_UNKNOWN_OPTIONS] = { "unknown regexp %s - %.*s", PM_ERROR_LEVEL_SYNTAX },
335
354
  [PM_ERR_REGEXP_TERM] = { "unterminated regexp meets end of file; expected a closing delimiter", PM_ERROR_LEVEL_SYNTAX },
336
- [PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP] = { "UTF-8 character in non UTF-8 regexp: /%s/", PM_ERROR_LEVEL_SYNTAX },
355
+ [PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP] = { "UTF-8 character in non UTF-8 regexp: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
337
356
  [PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_LEVEL_SYNTAX },
338
357
  [PM_ERR_RESCUE_MODIFIER_VALUE] = { "expected a value after the `rescue` modifier", PM_ERROR_LEVEL_SYNTAX },
339
358
  [PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_LEVEL_SYNTAX },
@@ -348,7 +367,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
348
367
  [PM_ERR_STRING_INTERPOLATED_TERM] = { "unterminated string; expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_SYNTAX },
349
368
  [PM_ERR_STRING_LITERAL_EOF] = { "unterminated string meets end of file", PM_ERROR_LEVEL_SYNTAX },
350
369
  [PM_ERR_STRING_LITERAL_TERM] = { "unexpected %s, expected a string literal terminator", PM_ERROR_LEVEL_SYNTAX },
351
- [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_SYNTAX }, // TODO expected symbol? prism.c ~9719
370
+ [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_SYNTAX }, /* TODO expected symbol? prism.c ~9719 */
352
371
  [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "unterminated quoted string; expected a closing delimiter for the dynamic symbol", PM_ERROR_LEVEL_SYNTAX },
353
372
  [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "unterminated symbol; expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_SYNTAX },
354
373
  [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_LEVEL_SYNTAX },
@@ -375,7 +394,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
375
394
  [PM_ERR_WRITE_TARGET_UNEXPECTED] = { "unexpected write target", PM_ERROR_LEVEL_SYNTAX },
376
395
  [PM_ERR_XSTRING_TERM] = { "expected a closing delimiter for the `%x` or backtick string", PM_ERROR_LEVEL_SYNTAX },
377
396
 
378
- // Warnings
397
+ /* Warnings */
379
398
  [PM_WARN_AMBIGUOUS_BINARY_OPERATOR] = { "'%s' after local variable or literal is interpreted as binary operator even though it seems like %s", PM_WARNING_LEVEL_VERBOSE },
380
399
  [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = { "ambiguous first argument; put parentheses or a space even after `-` operator", PM_WARNING_LEVEL_VERBOSE },
381
400
  [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_LEVEL_VERBOSE },
@@ -411,8 +430,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
411
430
  /**
412
431
  * Get the human-readable name of the given diagnostic ID.
413
432
  */
414
- const char *
415
- pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) {
433
+ static const char *
434
+ pm_diagnostic_id_name(pm_diagnostic_id_t diag_id) {
416
435
  switch (diag_id) {
417
436
  <%- errors.each do |error| -%>
418
437
  case PM_ERR_<%= error.name %>: return "<%= error.name.downcase %>";
@@ -426,9 +445,10 @@ pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) {
426
445
  return "";
427
446
  }
428
447
 
429
- static inline const char *
430
- pm_diagnostic_message(pm_diagnostic_id_t diag_id) {
448
+ static PRISM_INLINE const char *
449
+ pm_diagnostic_id_message(pm_diagnostic_id_t diag_id) {
431
450
  assert(diag_id < PM_DIAGNOSTIC_ID_MAX);
451
+ PRISM_ASSUME(diag_id < PM_DIAGNOSTIC_ID_MAX);
432
452
 
433
453
  const char *message = diagnostic_messages[diag_id].message;
434
454
  assert(message);
@@ -436,91 +456,122 @@ pm_diagnostic_message(pm_diagnostic_id_t diag_id) {
436
456
  return message;
437
457
  }
438
458
 
439
- static inline uint8_t
440
- pm_diagnostic_level(pm_diagnostic_id_t diag_id) {
459
+ static PRISM_INLINE uint8_t
460
+ pm_diagnostic_id_level(pm_diagnostic_id_t diag_id) {
441
461
  assert(diag_id < PM_DIAGNOSTIC_ID_MAX);
462
+ PRISM_ASSUME(diag_id < PM_DIAGNOSTIC_ID_MAX);
442
463
 
443
464
  return (uint8_t) diagnostic_messages[diag_id].level;
444
465
  }
445
466
 
467
+ /**
468
+ * Get the type of the given diagnostic.
469
+ */
470
+ const char *
471
+ pm_diagnostic_type(const pm_diagnostic_t *diagnostic) {
472
+ return pm_diagnostic_id_name(diagnostic->diag_id);
473
+ }
474
+
475
+ /**
476
+ * Get the location of the given diagnostic.
477
+ */
478
+ pm_location_t
479
+ pm_diagnostic_location(const pm_diagnostic_t *diagnostic) {
480
+ return diagnostic->location;
481
+ }
482
+
483
+ /**
484
+ * Get the message of the given diagnostic.
485
+ */
486
+ const char *
487
+ pm_diagnostic_message(const pm_diagnostic_t *diagnostic) {
488
+ return diagnostic->message;
489
+ }
490
+
491
+ /**
492
+ * Get the error level associated with the given diagnostic.
493
+ */
494
+ pm_error_level_t
495
+ pm_diagnostic_error_level(const pm_diagnostic_t *diagnostic) {
496
+ return (pm_error_level_t) pm_diagnostic_id_level(diagnostic->diag_id);
497
+ }
498
+
499
+ /**
500
+ * Get the warning level associated with the given diagnostic.
501
+ */
502
+ pm_warning_level_t
503
+ pm_diagnostic_warning_level(const pm_diagnostic_t *diagnostic) {
504
+ return (pm_warning_level_t) pm_diagnostic_id_level(diagnostic->diag_id);
505
+ }
506
+
507
+ /**
508
+ * Get the diagnostic that follows the given diagnostic.
509
+ */
510
+ const pm_diagnostic_t *
511
+ pm_diagnostic_next(const pm_diagnostic_t *diagnostic) {
512
+ return (const pm_diagnostic_t *) diagnostic->node.next;
513
+ }
514
+
446
515
  /**
447
516
  * Append an error to the given list of diagnostic.
448
517
  */
449
- bool
450
- pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id) {
451
- pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) xcalloc(1, sizeof(pm_diagnostic_t));
452
- if (diagnostic == NULL) return false;
518
+ void
519
+ pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id) {
520
+ pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) pm_arena_zalloc(arena, sizeof(pm_diagnostic_t), PRISM_ALIGNOF(pm_diagnostic_t));
453
521
 
454
522
  *diagnostic = (pm_diagnostic_t) {
455
- .location = { start, end },
523
+ .location = { .start = start, .length = length },
456
524
  .diag_id = diag_id,
457
- .message = pm_diagnostic_message(diag_id),
458
- .owned = false,
459
- .level = pm_diagnostic_level(diag_id)
525
+ .message = pm_diagnostic_id_message(diag_id),
526
+ .level = pm_diagnostic_id_level(diag_id)
460
527
  };
461
528
 
462
529
  pm_list_append(list, (pm_list_node_t *) diagnostic);
463
- return true;
464
530
  }
465
531
 
466
532
  /**
467
533
  * Append a diagnostic to the given list of diagnostics that is using a format
468
534
  * string for its message.
469
535
  */
470
- bool
471
- pm_diagnostic_list_append_format(pm_list_t *list, const uint8_t *start, const uint8_t *end, pm_diagnostic_id_t diag_id, ...) {
536
+ void
537
+ pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...) {
538
+ /* Format the message into a buffer on the stack, which nearly every message
539
+ * fits in. The result is the length of the whole message whether or not it
540
+ * fit, so a single pass both formats the message and sizes it. */
541
+ char stack[256];
542
+
472
543
  va_list arguments;
473
544
  va_start(arguments, diag_id);
474
545
 
475
- const char *format = pm_diagnostic_message(diag_id);
476
- int result = vsnprintf(NULL, 0, format, arguments);
546
+ const char *format = pm_diagnostic_id_message(diag_id);
547
+ int result = vsnprintf(stack, sizeof(stack), format, arguments);
477
548
  va_end(arguments);
478
549
 
479
550
  if (result < 0) {
480
- return false;
551
+ return;
481
552
  }
482
553
 
483
- pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) xcalloc(1, sizeof(pm_diagnostic_t));
484
- if (diagnostic == NULL) {
485
- return false;
486
- }
554
+ pm_diagnostic_t *diagnostic = (pm_diagnostic_t *) pm_arena_zalloc(arena, sizeof(pm_diagnostic_t), PRISM_ALIGNOF(pm_diagnostic_t));
487
555
 
488
- size_t length = (size_t) (result + 1);
489
- char *message = (char *) xmalloc(length);
490
- if (message == NULL) {
491
- xfree(diagnostic);
492
- return false;
493
- }
556
+ size_t message_length = (size_t) (result + 1);
557
+ char *message = (char *) pm_arena_alloc(arena, message_length, 1);
494
558
 
495
- va_start(arguments, diag_id);
496
- vsnprintf(message, length, format, arguments);
497
- va_end(arguments);
559
+ if (message_length <= sizeof(stack)) {
560
+ memcpy(message, stack, message_length);
561
+ } else {
562
+ /* The message was cut off on the stack, so format it again into an
563
+ * allocation of the right size. */
564
+ va_start(arguments, diag_id);
565
+ vsnprintf(message, message_length, format, arguments);
566
+ va_end(arguments);
567
+ }
498
568
 
499
569
  *diagnostic = (pm_diagnostic_t) {
500
- .location = { start, end },
570
+ .location = { .start = start, .length = length },
501
571
  .diag_id = diag_id,
502
572
  .message = message,
503
- .owned = true,
504
- .level = pm_diagnostic_level(diag_id)
573
+ .level = pm_diagnostic_id_level(diag_id)
505
574
  };
506
575
 
507
576
  pm_list_append(list, (pm_list_node_t *) diagnostic);
508
- return true;
509
- }
510
-
511
- /**
512
- * Deallocate the internal state of the given diagnostic list.
513
- */
514
- void
515
- pm_diagnostic_list_free(pm_list_t *list) {
516
- pm_diagnostic_t *node = (pm_diagnostic_t *) list->head;
517
-
518
- while (node != NULL) {
519
- pm_diagnostic_t *next = (pm_diagnostic_t *) node->node.next;
520
-
521
- if (node->owned) xfree((void *) node->message);
522
- xfree(node);
523
-
524
- node = next;
525
- }
526
577
  }
@@ -0,0 +1,130 @@
1
+ #include "prism/json.h"
2
+
3
+ // Ensure this translation unit is never empty, even when JSON is excluded.
4
+ typedef int pm_json_unused_t;
5
+
6
+ #ifndef PRISM_EXCLUDE_JSON
7
+
8
+ #include "prism/internal/buffer.h"
9
+ #include "prism/internal/constant_pool.h"
10
+ #include "prism/internal/integer.h"
11
+ #include "prism/internal/parser.h"
12
+
13
+ #include <inttypes.h>
14
+
15
+ static void
16
+ pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) {
17
+ const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
18
+ pm_buffer_append_byte(buffer, '"');
19
+ pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON);
20
+ pm_buffer_append_byte(buffer, '"');
21
+ }
22
+
23
+ static void
24
+ pm_dump_json_location(pm_buffer_t *buffer, const pm_location_t *location) {
25
+ pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"length\":%" PRIu32 "}", location->start, location->length);
26
+ }
27
+
28
+ /**
29
+ * Dump JSON to the given buffer.
30
+ */
31
+ void
32
+ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) {
33
+ switch (PM_NODE_TYPE(node)) {
34
+ <%- nodes.each do |node| -%>
35
+ case <%= node.type %>: {
36
+ pm_buffer_append_string(buffer, "{\"type\":\"<%= node.name %>\",\"location\":", <%= node.name.bytesize + 22 %>);
37
+
38
+ const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node;
39
+ pm_dump_json_location(buffer, &cast->base.location);
40
+ <%- [*node.flags, *node.fields].each_with_index do |field, index| -%>
41
+
42
+ // Dump the <%= field.name %> field
43
+ pm_buffer_append_byte(buffer, ',');
44
+ <%- if field.is_a?(Prism::Template::Flags) -%>
45
+ pm_buffer_append_string(buffer, "\"flags\":", 8);
46
+ <%- else -%>
47
+ pm_buffer_append_string(buffer, "\"<%= field.name %>\":", <%= field.name.bytesize + 3 %>);
48
+ <%- end -%>
49
+ <%- case field -%>
50
+ <%- when Prism::Template::NodeField -%>
51
+ pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>);
52
+ <%- when Prism::Template::OptionalNodeField -%>
53
+ if (cast-><%= field.name %> != NULL) {
54
+ pm_dump_json(buffer, parser, (const pm_node_t *) cast-><%= field.name %>);
55
+ } else {
56
+ pm_buffer_append_string(buffer, "null", 4);
57
+ }
58
+ <%- when Prism::Template::NodeListField -%>
59
+ const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>;
60
+ pm_buffer_append_byte(buffer, '[');
61
+
62
+ for (size_t index = 0; index < <%= field.name %>->size; index++) {
63
+ if (index != 0) pm_buffer_append_byte(buffer, ',');
64
+ pm_dump_json(buffer, parser, <%= field.name %>->nodes[index]);
65
+ }
66
+ pm_buffer_append_byte(buffer, ']');
67
+ <%- when Prism::Template::StringField -%>
68
+ const pm_string_t *<%= field.name %> = &cast-><%= field.name %>;
69
+ pm_buffer_append_byte(buffer, '"');
70
+ pm_buffer_append_source(buffer, pm_string_source(<%= field.name %>), pm_string_length(<%= field.name %>), PM_BUFFER_ESCAPING_JSON);
71
+ pm_buffer_append_byte(buffer, '"');
72
+ <%- when Prism::Template::ConstantField -%>
73
+ pm_dump_json_constant(buffer, parser, cast-><%= field.name %>);
74
+ <%- when Prism::Template::OptionalConstantField -%>
75
+ if (cast-><%= field.name %> != PM_CONSTANT_ID_UNSET) {
76
+ pm_dump_json_constant(buffer, parser, cast-><%= field.name %>);
77
+ } else {
78
+ pm_buffer_append_string(buffer, "null", 4);
79
+ }
80
+ <%- when Prism::Template::ConstantListField -%>
81
+ const pm_constant_id_list_t *<%= field.name %> = &cast-><%= field.name %>;
82
+ pm_buffer_append_byte(buffer, '[');
83
+
84
+ for (size_t index = 0; index < <%= field.name %>->size; index++) {
85
+ if (index != 0) pm_buffer_append_byte(buffer, ',');
86
+ pm_dump_json_constant(buffer, parser, <%= field.name %>->ids[index]);
87
+ }
88
+ pm_buffer_append_byte(buffer, ']');
89
+ <%- when Prism::Template::LocationField -%>
90
+ pm_dump_json_location(buffer, &cast-><%= field.name %>);
91
+ <%- when Prism::Template::OptionalLocationField -%>
92
+ if (cast-><%= field.name %>.length != 0) {
93
+ pm_dump_json_location(buffer, &cast-><%= field.name %>);
94
+ } else {
95
+ pm_buffer_append_string(buffer, "null", 4);
96
+ }
97
+ <%- when Prism::Template::UInt8Field -%>
98
+ pm_buffer_append_format(buffer, "%" PRIu8, cast-><%= field.name %>);
99
+ <%- when Prism::Template::UInt32Field -%>
100
+ pm_buffer_append_format(buffer, "%" PRIu32, cast-><%= field.name %>);
101
+ <%- when Prism::Template::Flags -%>
102
+ size_t flags = 0;
103
+ pm_buffer_append_byte(buffer, '[');
104
+ <%- node.flags.values.each_with_index do |value, index| -%>
105
+ if (PM_NODE_FLAG_P(cast, PM_<%= node.flags.human.upcase %>_<%= value.name %>)) {
106
+ if (flags != 0) pm_buffer_append_byte(buffer, ',');
107
+ pm_buffer_append_string(buffer, "\"<%= value.name %>\"", <%= value.name.bytesize + 2 %>);
108
+ flags++;
109
+ }
110
+ <%- end -%>
111
+ pm_buffer_append_byte(buffer, ']');
112
+ <%- when Prism::Template::IntegerField -%>
113
+ pm_integer_string(buffer, &cast-><%= field.name %>);
114
+ <%- when Prism::Template::DoubleField -%>
115
+ pm_buffer_append_format(buffer, "%f", cast-><%= field.name %>);
116
+ <%- else -%>
117
+ <%- raise %>
118
+ <%- end -%>
119
+ <%- end -%>
120
+
121
+ pm_buffer_append_byte(buffer, '}');
122
+ break;
123
+ }
124
+ <%- end -%>
125
+ case PM_SCOPE_NODE:
126
+ break;
127
+ }
128
+ }
129
+
130
+ #endif