herb 0.7.2-x86_64-darwin → 0.7.3-x86_64-darwin
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.
- checksums.yaml +4 -4
- data/Makefile +2 -0
- data/README.md +1 -1
- data/Rakefile +46 -1
- data/config.yml +714 -0
- data/ext/herb/extconf.rb +2 -1
- data/ext/herb/nodes.c +1 -1
- data/herb.gemspec +3 -0
- data/lib/herb/3.0/herb.bundle +0 -0
- data/lib/herb/3.1/herb.bundle +0 -0
- data/lib/herb/3.2/herb.bundle +0 -0
- data/lib/herb/3.3/herb.bundle +0 -0
- data/lib/herb/3.4/herb.bundle +0 -0
- data/lib/herb/version.rb +1 -1
- data/src/analyze.c +5 -9
- data/src/analyze_helpers.c +17 -6
- data/src/include/pretty_print.h +1 -1
- data/src/include/version.h +1 -1
- data/src/parser.c +1 -0
- data/src/pretty_print.c +1 -1
- data/templates/ext/herb/error_helpers.c.erb +85 -0
- data/templates/ext/herb/error_helpers.h.erb +12 -0
- data/templates/ext/herb/nodes.c.erb +90 -0
- data/templates/ext/herb/nodes.h.erb +9 -0
- data/templates/javascript/packages/core/src/errors.ts.erb +193 -0
- data/templates/javascript/packages/core/src/node-type-guards.ts.erb +325 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +414 -0
- data/templates/javascript/packages/core/src/visitor.ts.erb +29 -0
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +113 -0
- data/templates/javascript/packages/node/extension/error_helpers.h.erb +17 -0
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +111 -0
- data/templates/javascript/packages/node/extension/nodes.h.erb +17 -0
- data/templates/lib/herb/ast/nodes.rb.erb +117 -0
- data/templates/lib/herb/errors.rb.erb +106 -0
- data/templates/lib/herb/visitor.rb.erb +28 -0
- data/templates/sig/serialized_ast_errors.rbs.erb +10 -0
- data/templates/sig/serialized_ast_nodes.rbs.erb +10 -0
- data/templates/src/ast_nodes.c.erb +145 -0
- data/templates/src/ast_pretty_print.c.erb +97 -0
- data/templates/src/errors.c.erb +245 -0
- data/templates/src/include/ast_nodes.h.erb +46 -0
- data/templates/src/include/ast_pretty_print.h.erb +14 -0
- data/templates/src/include/errors.h.erb +58 -0
- data/templates/src/visitor.c.erb +47 -0
- data/templates/template.rb +406 -0
- data/templates/wasm/error_helpers.cpp.erb +93 -0
- data/templates/wasm/error_helpers.h.erb +15 -0
- data/templates/wasm/nodes.cpp.erb +79 -0
- data/templates/wasm/nodes.h.erb +15 -0
- data/vendor/prism/Rakefile +75 -0
- data/vendor/prism/config.yml +4713 -0
- data/vendor/prism/include/prism/ast.h +8190 -0
- data/vendor/prism/include/prism/defines.h +260 -0
- data/vendor/prism/include/prism/diagnostic.h +455 -0
- data/vendor/prism/include/prism/encoding.h +283 -0
- data/vendor/prism/include/prism/node.h +129 -0
- data/vendor/prism/include/prism/options.h +482 -0
- data/vendor/prism/include/prism/pack.h +163 -0
- data/vendor/prism/include/prism/parser.h +933 -0
- data/vendor/prism/include/prism/prettyprint.h +34 -0
- data/vendor/prism/include/prism/regexp.h +43 -0
- data/vendor/prism/include/prism/static_literals.h +121 -0
- data/vendor/prism/include/prism/util/pm_buffer.h +236 -0
- data/vendor/prism/include/prism/util/pm_char.h +204 -0
- data/vendor/prism/include/prism/util/pm_constant_pool.h +218 -0
- data/vendor/prism/include/prism/util/pm_integer.h +130 -0
- data/vendor/prism/include/prism/util/pm_list.h +103 -0
- data/vendor/prism/include/prism/util/pm_memchr.h +29 -0
- data/vendor/prism/include/prism/util/pm_newline_list.h +113 -0
- data/vendor/prism/include/prism/util/pm_string.h +200 -0
- data/vendor/prism/include/prism/util/pm_strncasecmp.h +32 -0
- data/vendor/prism/include/prism/util/pm_strpbrk.h +46 -0
- data/vendor/prism/include/prism/version.h +29 -0
- data/vendor/prism/include/prism.h +408 -0
- data/vendor/prism/src/diagnostic.c +848 -0
- data/vendor/prism/src/encoding.c +5235 -0
- data/vendor/prism/src/node.c +8676 -0
- data/vendor/prism/src/options.c +328 -0
- data/vendor/prism/src/pack.c +509 -0
- data/vendor/prism/src/prettyprint.c +8941 -0
- data/vendor/prism/src/prism.c +23302 -0
- data/vendor/prism/src/regexp.c +790 -0
- data/vendor/prism/src/serialize.c +2268 -0
- data/vendor/prism/src/static_literals.c +617 -0
- data/vendor/prism/src/token_type.c +703 -0
- data/vendor/prism/src/util/pm_buffer.c +357 -0
- data/vendor/prism/src/util/pm_char.c +318 -0
- data/vendor/prism/src/util/pm_constant_pool.c +342 -0
- data/vendor/prism/src/util/pm_integer.c +670 -0
- data/vendor/prism/src/util/pm_list.c +49 -0
- data/vendor/prism/src/util/pm_memchr.c +35 -0
- data/vendor/prism/src/util/pm_newline_list.c +125 -0
- data/vendor/prism/src/util/pm_string.c +383 -0
- data/vendor/prism/src/util/pm_strncasecmp.c +36 -0
- data/vendor/prism/src/util/pm_strpbrk.c +206 -0
- data/vendor/prism/templates/ext/prism/api_node.c.erb +282 -0
- data/vendor/prism/templates/include/prism/ast.h.erb +226 -0
- data/vendor/prism/templates/include/prism/diagnostic.h.erb +130 -0
- data/vendor/prism/templates/java/org/prism/AbstractNodeVisitor.java.erb +22 -0
- data/vendor/prism/templates/java/org/prism/Loader.java.erb +434 -0
- data/vendor/prism/templates/java/org/prism/Nodes.java.erb +403 -0
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +448 -0
- data/vendor/prism/templates/javascript/src/nodes.js.erb +197 -0
- data/vendor/prism/templates/javascript/src/visitor.js.erb +78 -0
- data/vendor/prism/templates/lib/prism/compiler.rb.erb +43 -0
- data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +103 -0
- data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +189 -0
- data/vendor/prism/templates/lib/prism/dsl.rb.erb +133 -0
- data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +131 -0
- data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +19 -0
- data/vendor/prism/templates/lib/prism/node.rb.erb +515 -0
- data/vendor/prism/templates/lib/prism/reflection.rb.erb +136 -0
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +602 -0
- data/vendor/prism/templates/lib/prism/visitor.rb.erb +55 -0
- data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +68 -0
- data/vendor/prism/templates/rbi/prism/node.rbi.erb +164 -0
- data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +18 -0
- data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +45 -0
- data/vendor/prism/templates/sig/prism/dsl.rbs.erb +31 -0
- data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +7 -0
- data/vendor/prism/templates/sig/prism/node.rbs.erb +132 -0
- data/vendor/prism/templates/sig/prism/visitor.rbs.erb +17 -0
- data/vendor/prism/templates/sig/prism.rbs.erb +89 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +523 -0
- data/vendor/prism/templates/src/node.c.erb +333 -0
- data/vendor/prism/templates/src/prettyprint.c.erb +166 -0
- data/vendor/prism/templates/src/serialize.c.erb +406 -0
- data/vendor/prism/templates/src/token_type.c.erb +369 -0
- data/vendor/prism/templates/template.rb +689 -0
- metadata +112 -2
@@ -0,0 +1,689 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# typed: ignore
|
3
|
+
|
4
|
+
require "erb"
|
5
|
+
require "fileutils"
|
6
|
+
require "yaml"
|
7
|
+
|
8
|
+
module Prism
|
9
|
+
module Template
|
10
|
+
SERIALIZE_ONLY_SEMANTICS_FIELDS = ENV.fetch("PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS", false)
|
11
|
+
REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS
|
12
|
+
CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false)
|
13
|
+
|
14
|
+
JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby"
|
15
|
+
JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String"
|
16
|
+
INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby"
|
17
|
+
|
18
|
+
COMMON_FLAGS_COUNT = 2
|
19
|
+
|
20
|
+
class Error
|
21
|
+
attr_reader :name
|
22
|
+
|
23
|
+
def initialize(name)
|
24
|
+
@name = name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Warning
|
29
|
+
attr_reader :name
|
30
|
+
|
31
|
+
def initialize(name)
|
32
|
+
@name = name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# This module contains methods for escaping characters in JavaDoc comments.
|
37
|
+
module JavaDoc
|
38
|
+
ESCAPES = {
|
39
|
+
"'" => "'",
|
40
|
+
"\"" => """,
|
41
|
+
"@" => "@",
|
42
|
+
"&" => "&",
|
43
|
+
"<" => "<",
|
44
|
+
">" => ">"
|
45
|
+
}.freeze
|
46
|
+
|
47
|
+
def self.escape(value)
|
48
|
+
value.gsub(/['&"<>@]/, ESCAPES)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# A comment attached to a field or node.
|
53
|
+
class ConfigComment
|
54
|
+
attr_reader :value
|
55
|
+
|
56
|
+
def initialize(value)
|
57
|
+
@value = value
|
58
|
+
end
|
59
|
+
|
60
|
+
def each_line(&block)
|
61
|
+
value.each_line { |line| yield line.prepend(" ").rstrip }
|
62
|
+
end
|
63
|
+
|
64
|
+
def each_java_line(&block)
|
65
|
+
ConfigComment.new(JavaDoc.escape(value)).each_line(&block)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# This represents a field on a node. It contains all of the necessary
|
70
|
+
# information to template out the code for that field.
|
71
|
+
class Field
|
72
|
+
attr_reader :name, :comment, :options
|
73
|
+
|
74
|
+
def initialize(name:, comment: nil, **options)
|
75
|
+
@name = name
|
76
|
+
@comment = comment
|
77
|
+
@options = options
|
78
|
+
end
|
79
|
+
|
80
|
+
def each_comment_line(&block)
|
81
|
+
ConfigComment.new(comment).each_line(&block) if comment
|
82
|
+
end
|
83
|
+
|
84
|
+
def each_comment_java_line(&block)
|
85
|
+
ConfigComment.new(comment).each_java_line(&block) if comment
|
86
|
+
end
|
87
|
+
|
88
|
+
def semantic_field?
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
def should_be_serialized?
|
93
|
+
SERIALIZE_ONLY_SEMANTICS_FIELDS ? semantic_field? : true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Some node fields can be specialized if they point to a specific kind of
|
98
|
+
# node and not just a generic node.
|
99
|
+
class NodeKindField < Field
|
100
|
+
def initialize(kind:, **options)
|
101
|
+
@kind = kind
|
102
|
+
super(**options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def c_type
|
106
|
+
if specific_kind
|
107
|
+
"pm_#{specific_kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}"
|
108
|
+
else
|
109
|
+
"pm_node"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def ruby_type
|
114
|
+
specific_kind || "Node"
|
115
|
+
end
|
116
|
+
|
117
|
+
def java_type
|
118
|
+
specific_kind || "Node"
|
119
|
+
end
|
120
|
+
|
121
|
+
def java_cast
|
122
|
+
if specific_kind
|
123
|
+
"(Nodes.#{@kind}) "
|
124
|
+
else
|
125
|
+
""
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def specific_kind
|
130
|
+
@kind unless @kind.is_a?(Array)
|
131
|
+
end
|
132
|
+
|
133
|
+
def union_kind
|
134
|
+
@kind if @kind.is_a?(Array)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# This represents a field on a node that is itself a node. We pass them as
|
139
|
+
# references and store them as references.
|
140
|
+
class NodeField < NodeKindField
|
141
|
+
def rbs_class
|
142
|
+
if specific_kind
|
143
|
+
specific_kind
|
144
|
+
elsif union_kind
|
145
|
+
union_kind.join(" | ")
|
146
|
+
else
|
147
|
+
"Prism::node"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def rbi_class
|
152
|
+
if specific_kind
|
153
|
+
"Prism::#{specific_kind}"
|
154
|
+
elsif union_kind
|
155
|
+
"T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")})"
|
156
|
+
else
|
157
|
+
"Prism::Node"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def check_field_kind
|
162
|
+
if union_kind
|
163
|
+
"[#{union_kind.join(', ')}].include?(#{name}.class)"
|
164
|
+
else
|
165
|
+
"#{name}.is_a?(#{ruby_type})"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# This represents a field on a node that is itself a node and can be
|
171
|
+
# optionally null. We pass them as references and store them as references.
|
172
|
+
class OptionalNodeField < NodeKindField
|
173
|
+
def rbs_class
|
174
|
+
if specific_kind
|
175
|
+
"#{specific_kind}?"
|
176
|
+
elsif union_kind
|
177
|
+
[*union_kind, "nil"].join(" | ")
|
178
|
+
else
|
179
|
+
"Prism::node?"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def rbi_class
|
184
|
+
if specific_kind
|
185
|
+
"T.nilable(Prism::#{specific_kind})"
|
186
|
+
elsif union_kind
|
187
|
+
"T.nilable(T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")}))"
|
188
|
+
else
|
189
|
+
"T.nilable(Prism::Node)"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def check_field_kind
|
194
|
+
if union_kind
|
195
|
+
"[#{union_kind.join(', ')}, NilClass].include?(#{name}.class)"
|
196
|
+
else
|
197
|
+
"#{name}.nil? || #{name}.is_a?(#{ruby_type})"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# This represents a field on a node that is a list of nodes. We pass them as
|
203
|
+
# references and store them directly on the struct.
|
204
|
+
class NodeListField < NodeKindField
|
205
|
+
def rbs_class
|
206
|
+
if specific_kind
|
207
|
+
"Array[#{specific_kind}]"
|
208
|
+
elsif union_kind
|
209
|
+
"Array[#{union_kind.join(" | ")}]"
|
210
|
+
else
|
211
|
+
"Array[Prism::node]"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def rbi_class
|
216
|
+
if specific_kind
|
217
|
+
"T::Array[Prism::#{specific_kind}]"
|
218
|
+
elsif union_kind
|
219
|
+
"T::Array[T.any(#{union_kind.map { |kind| "Prism::#{kind}" }.join(", ")})]"
|
220
|
+
else
|
221
|
+
"T::Array[Prism::Node]"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def java_type
|
226
|
+
"#{super}[]"
|
227
|
+
end
|
228
|
+
|
229
|
+
def check_field_kind
|
230
|
+
if union_kind
|
231
|
+
"#{name}.all? { |n| [#{union_kind.join(', ')}].include?(n.class) }"
|
232
|
+
else
|
233
|
+
"#{name}.all? { |n| n.is_a?(#{ruby_type}) }"
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# This represents a field on a node that is the ID of a string interned
|
239
|
+
# through the parser's constant pool.
|
240
|
+
class ConstantField < Field
|
241
|
+
def rbs_class
|
242
|
+
"Symbol"
|
243
|
+
end
|
244
|
+
|
245
|
+
def rbi_class
|
246
|
+
"Symbol"
|
247
|
+
end
|
248
|
+
|
249
|
+
def java_type
|
250
|
+
JAVA_STRING_TYPE
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
# This represents a field on a node that is the ID of a string interned
|
255
|
+
# through the parser's constant pool and can be optionally null.
|
256
|
+
class OptionalConstantField < Field
|
257
|
+
def rbs_class
|
258
|
+
"Symbol?"
|
259
|
+
end
|
260
|
+
|
261
|
+
def rbi_class
|
262
|
+
"T.nilable(Symbol)"
|
263
|
+
end
|
264
|
+
|
265
|
+
def java_type
|
266
|
+
JAVA_STRING_TYPE
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# This represents a field on a node that is a list of IDs that are associated
|
271
|
+
# with strings interned through the parser's constant pool.
|
272
|
+
class ConstantListField < Field
|
273
|
+
def rbs_class
|
274
|
+
"Array[Symbol]"
|
275
|
+
end
|
276
|
+
|
277
|
+
def rbi_class
|
278
|
+
"T::Array[Symbol]"
|
279
|
+
end
|
280
|
+
|
281
|
+
def java_type
|
282
|
+
"#{JAVA_STRING_TYPE}[]"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# This represents a field on a node that is a string.
|
287
|
+
class StringField < Field
|
288
|
+
def rbs_class
|
289
|
+
"String"
|
290
|
+
end
|
291
|
+
|
292
|
+
def rbi_class
|
293
|
+
"String"
|
294
|
+
end
|
295
|
+
|
296
|
+
def java_type
|
297
|
+
"byte[]"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# This represents a field on a node that is a location.
|
302
|
+
class LocationField < Field
|
303
|
+
def semantic_field?
|
304
|
+
false
|
305
|
+
end
|
306
|
+
|
307
|
+
def rbs_class
|
308
|
+
"Location"
|
309
|
+
end
|
310
|
+
|
311
|
+
def rbi_class
|
312
|
+
"Prism::Location"
|
313
|
+
end
|
314
|
+
|
315
|
+
def java_type
|
316
|
+
"Location"
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# This represents a field on a node that is a location that is optional.
|
321
|
+
class OptionalLocationField < Field
|
322
|
+
def semantic_field?
|
323
|
+
false
|
324
|
+
end
|
325
|
+
|
326
|
+
def rbs_class
|
327
|
+
"Location?"
|
328
|
+
end
|
329
|
+
|
330
|
+
def rbi_class
|
331
|
+
"T.nilable(Prism::Location)"
|
332
|
+
end
|
333
|
+
|
334
|
+
def java_type
|
335
|
+
"Location"
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# This represents an integer field.
|
340
|
+
class UInt8Field < Field
|
341
|
+
def rbs_class
|
342
|
+
"Integer"
|
343
|
+
end
|
344
|
+
|
345
|
+
def rbi_class
|
346
|
+
"Integer"
|
347
|
+
end
|
348
|
+
|
349
|
+
def java_type
|
350
|
+
"int"
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
# This represents an integer field.
|
355
|
+
class UInt32Field < Field
|
356
|
+
def rbs_class
|
357
|
+
"Integer"
|
358
|
+
end
|
359
|
+
|
360
|
+
def rbi_class
|
361
|
+
"Integer"
|
362
|
+
end
|
363
|
+
|
364
|
+
def java_type
|
365
|
+
"int"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# This represents an arbitrarily-sized integer. When it gets to Ruby it will
|
370
|
+
# be an Integer.
|
371
|
+
class IntegerField < Field
|
372
|
+
def rbs_class
|
373
|
+
"Integer"
|
374
|
+
end
|
375
|
+
|
376
|
+
def rbi_class
|
377
|
+
"Integer"
|
378
|
+
end
|
379
|
+
|
380
|
+
def java_type
|
381
|
+
"Object"
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# This represents a double-precision floating point number. When it gets to
|
386
|
+
# Ruby it will be a Float.
|
387
|
+
class DoubleField < Field
|
388
|
+
def rbs_class
|
389
|
+
"Float"
|
390
|
+
end
|
391
|
+
|
392
|
+
def rbi_class
|
393
|
+
"Float"
|
394
|
+
end
|
395
|
+
|
396
|
+
def java_type
|
397
|
+
"double"
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
# This class represents a node in the tree, configured by the config.yml file
|
402
|
+
# in YAML format. It contains information about the name of the node and the
|
403
|
+
# various child nodes it contains.
|
404
|
+
class NodeType
|
405
|
+
attr_reader :name, :type, :human, :flags, :fields, :newline, :comment
|
406
|
+
|
407
|
+
def initialize(config, flags)
|
408
|
+
@name = config.fetch("name")
|
409
|
+
|
410
|
+
type = @name.gsub(/(?<=.)[A-Z]/, "_\\0")
|
411
|
+
@type = "PM_#{type.upcase}"
|
412
|
+
@human = type.downcase
|
413
|
+
|
414
|
+
@fields =
|
415
|
+
config.fetch("fields", []).map do |field|
|
416
|
+
type = field_type_for(field.fetch("type"))
|
417
|
+
|
418
|
+
options = field.transform_keys(&:to_sym)
|
419
|
+
options.delete(:type)
|
420
|
+
|
421
|
+
# If/when we have documentation on every field, this should be
|
422
|
+
# changed to use fetch instead of delete.
|
423
|
+
comment = options.delete(:comment)
|
424
|
+
|
425
|
+
if kinds = options[:kind]
|
426
|
+
kinds = [kinds] unless kinds.is_a?(Array)
|
427
|
+
kinds = kinds.map do |kind|
|
428
|
+
case kind
|
429
|
+
when "non-void expression"
|
430
|
+
# the actual list of types would be way too long
|
431
|
+
"Node"
|
432
|
+
when "pattern expression"
|
433
|
+
# the list of all possible types is too long with 37+ different classes
|
434
|
+
"Node"
|
435
|
+
when Hash
|
436
|
+
kind = kind.fetch("on error")
|
437
|
+
REMOVE_ON_ERROR_TYPES ? nil : kind
|
438
|
+
else
|
439
|
+
kind
|
440
|
+
end
|
441
|
+
end.compact
|
442
|
+
if kinds.size == 1
|
443
|
+
kinds = kinds.first
|
444
|
+
kinds = nil if kinds == "Node"
|
445
|
+
end
|
446
|
+
options[:kind] = kinds
|
447
|
+
else
|
448
|
+
if type < NodeKindField
|
449
|
+
raise "Missing kind in config.yml for field #{@name}##{options.fetch(:name)}"
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
type.new(comment: comment, **options)
|
454
|
+
end
|
455
|
+
|
456
|
+
@flags = config.key?("flags") ? flags.fetch(config.fetch("flags")) : nil
|
457
|
+
@newline = config.fetch("newline", true)
|
458
|
+
@comment = config.fetch("comment")
|
459
|
+
end
|
460
|
+
|
461
|
+
def each_comment_line(&block)
|
462
|
+
ConfigComment.new(comment).each_line(&block)
|
463
|
+
end
|
464
|
+
|
465
|
+
def each_comment_java_line(&block)
|
466
|
+
ConfigComment.new(comment).each_java_line(&block)
|
467
|
+
end
|
468
|
+
|
469
|
+
def semantic_fields
|
470
|
+
@semantic_fields ||= @fields.select(&:semantic_field?)
|
471
|
+
end
|
472
|
+
|
473
|
+
# Should emit serialized length of node so implementations can skip
|
474
|
+
# the node to enable lazy parsing.
|
475
|
+
def needs_serialized_length?
|
476
|
+
name == "DefNode"
|
477
|
+
end
|
478
|
+
|
479
|
+
private
|
480
|
+
|
481
|
+
def field_type_for(name)
|
482
|
+
case name
|
483
|
+
when "node" then NodeField
|
484
|
+
when "node?" then OptionalNodeField
|
485
|
+
when "node[]" then NodeListField
|
486
|
+
when "string" then StringField
|
487
|
+
when "constant" then ConstantField
|
488
|
+
when "constant?" then OptionalConstantField
|
489
|
+
when "constant[]" then ConstantListField
|
490
|
+
when "location" then LocationField
|
491
|
+
when "location?" then OptionalLocationField
|
492
|
+
when "uint8" then UInt8Field
|
493
|
+
when "uint32" then UInt32Field
|
494
|
+
when "integer" then IntegerField
|
495
|
+
when "double" then DoubleField
|
496
|
+
else raise("Unknown field type: #{name.inspect}")
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
# This represents a token in the lexer.
|
502
|
+
class Token
|
503
|
+
attr_reader :name, :value, :comment
|
504
|
+
|
505
|
+
def initialize(config)
|
506
|
+
@name = config.fetch("name")
|
507
|
+
@value = config["value"]
|
508
|
+
@comment = config.fetch("comment")
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
# Represents a set of flags that should be internally represented with an enum.
|
513
|
+
class Flags
|
514
|
+
# Represents an individual flag within a set of flags.
|
515
|
+
class Flag
|
516
|
+
attr_reader :name, :camelcase, :comment
|
517
|
+
|
518
|
+
def initialize(config)
|
519
|
+
@name = config.fetch("name")
|
520
|
+
@camelcase = @name.split("_").map(&:capitalize).join
|
521
|
+
@comment = config.fetch("comment")
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
attr_reader :name, :human, :values, :comment
|
526
|
+
|
527
|
+
def initialize(config)
|
528
|
+
@name = config.fetch("name")
|
529
|
+
@human = @name.gsub(/(?<=.)[A-Z]/, "_\\0").downcase
|
530
|
+
@values = config.fetch("values").map { |flag| Flag.new(flag) }
|
531
|
+
@comment = config.fetch("comment")
|
532
|
+
end
|
533
|
+
|
534
|
+
def self.empty
|
535
|
+
new("name" => "", "values" => [], "comment" => "")
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
class << self
|
540
|
+
# This templates out a file using ERB with the given locals. The locals are
|
541
|
+
# derived from the config.yml file.
|
542
|
+
def render(name, write_to: nil)
|
543
|
+
filepath = "templates/#{name}.erb"
|
544
|
+
template = File.expand_path("../#{filepath}", __dir__)
|
545
|
+
|
546
|
+
erb = read_template(template)
|
547
|
+
extension = File.extname(filepath.gsub(".erb", ""))
|
548
|
+
|
549
|
+
heading =
|
550
|
+
case extension
|
551
|
+
when ".rb"
|
552
|
+
<<~HEADING
|
553
|
+
# frozen_string_literal: true
|
554
|
+
# :markup: markdown
|
555
|
+
|
556
|
+
=begin
|
557
|
+
--
|
558
|
+
This file is generated by the templates/template.rb script and should not be
|
559
|
+
modified manually. See #{filepath}
|
560
|
+
if you are looking to modify the template
|
561
|
+
++
|
562
|
+
=end
|
563
|
+
|
564
|
+
HEADING
|
565
|
+
when ".rbs"
|
566
|
+
<<~HEADING
|
567
|
+
# This file is generated by the templates/template.rb script and should not be
|
568
|
+
# modified manually. See #{filepath}
|
569
|
+
# if you are looking to modify the template
|
570
|
+
|
571
|
+
HEADING
|
572
|
+
when ".rbi"
|
573
|
+
<<~HEADING
|
574
|
+
# typed: strict
|
575
|
+
|
576
|
+
=begin
|
577
|
+
This file is generated by the templates/template.rb script and should not be
|
578
|
+
modified manually. See #{filepath}
|
579
|
+
if you are looking to modify the template
|
580
|
+
=end
|
581
|
+
|
582
|
+
HEADING
|
583
|
+
else
|
584
|
+
<<~HEADING
|
585
|
+
/* :markup: markdown */
|
586
|
+
|
587
|
+
/*----------------------------------------------------------------------------*/
|
588
|
+
/* This file is generated by the templates/template.rb script and should not */
|
589
|
+
/* be modified manually. See */
|
590
|
+
/* #{filepath.ljust(74)} */
|
591
|
+
/* if you are looking to modify the */
|
592
|
+
/* template */
|
593
|
+
/*----------------------------------------------------------------------------*/
|
594
|
+
|
595
|
+
HEADING
|
596
|
+
end
|
597
|
+
|
598
|
+
write_to ||= File.expand_path("../#{name}", __dir__)
|
599
|
+
contents = heading + erb.result_with_hash(locals)
|
600
|
+
|
601
|
+
if (extension == ".c" || extension == ".h") && !contents.ascii_only?
|
602
|
+
# Enforce that we only have ASCII characters here. This is necessary
|
603
|
+
# for non-UTF-8 locales that only allow ASCII characters in C source
|
604
|
+
# files.
|
605
|
+
contents.each_line.with_index(1) do |line, line_number|
|
606
|
+
raise "Non-ASCII character on line #{line_number} of #{write_to}" unless line.ascii_only?
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
FileUtils.mkdir_p(File.dirname(write_to))
|
611
|
+
File.write(write_to, contents)
|
612
|
+
end
|
613
|
+
|
614
|
+
private
|
615
|
+
|
616
|
+
def read_template(filepath)
|
617
|
+
template = File.read(filepath, encoding: Encoding::UTF_8)
|
618
|
+
erb = erb(template)
|
619
|
+
erb.filename = filepath
|
620
|
+
erb
|
621
|
+
end
|
622
|
+
|
623
|
+
def erb(template)
|
624
|
+
ERB.new(template, trim_mode: "-")
|
625
|
+
end
|
626
|
+
|
627
|
+
def locals
|
628
|
+
@locals ||=
|
629
|
+
begin
|
630
|
+
config = YAML.load_file(File.expand_path("../config.yml", __dir__))
|
631
|
+
flags = config.fetch("flags").to_h { |flags| [flags["name"], Flags.new(flags)] }
|
632
|
+
|
633
|
+
{
|
634
|
+
errors: config.fetch("errors").map { |name| Error.new(name) },
|
635
|
+
warnings: config.fetch("warnings").map { |name| Warning.new(name) },
|
636
|
+
nodes: config.fetch("nodes").map { |node| NodeType.new(node, flags) }.sort_by(&:name),
|
637
|
+
tokens: config.fetch("tokens").map { |token| Token.new(token) },
|
638
|
+
flags: flags.values
|
639
|
+
}
|
640
|
+
end
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
TEMPLATES = [
|
645
|
+
"ext/prism/api_node.c",
|
646
|
+
"include/prism/ast.h",
|
647
|
+
"include/prism/diagnostic.h",
|
648
|
+
"javascript/src/deserialize.js",
|
649
|
+
"javascript/src/nodes.js",
|
650
|
+
"javascript/src/visitor.js",
|
651
|
+
"java/org/prism/Loader.java",
|
652
|
+
"java/org/prism/Nodes.java",
|
653
|
+
"java/org/prism/AbstractNodeVisitor.java",
|
654
|
+
"lib/prism/compiler.rb",
|
655
|
+
"lib/prism/dispatcher.rb",
|
656
|
+
"lib/prism/dot_visitor.rb",
|
657
|
+
"lib/prism/dsl.rb",
|
658
|
+
"lib/prism/inspect_visitor.rb",
|
659
|
+
"lib/prism/mutation_compiler.rb",
|
660
|
+
"lib/prism/node.rb",
|
661
|
+
"lib/prism/reflection.rb",
|
662
|
+
"lib/prism/serialize.rb",
|
663
|
+
"lib/prism/visitor.rb",
|
664
|
+
"src/diagnostic.c",
|
665
|
+
"src/node.c",
|
666
|
+
"src/prettyprint.c",
|
667
|
+
"src/serialize.c",
|
668
|
+
"src/token_type.c",
|
669
|
+
"rbi/prism/dsl.rbi",
|
670
|
+
"rbi/prism/node.rbi",
|
671
|
+
"rbi/prism/visitor.rbi",
|
672
|
+
"sig/prism.rbs",
|
673
|
+
"sig/prism/dsl.rbs",
|
674
|
+
"sig/prism/mutation_compiler.rbs",
|
675
|
+
"sig/prism/node.rbs",
|
676
|
+
"sig/prism/visitor.rbs",
|
677
|
+
"sig/prism/_private/dot_visitor.rbs"
|
678
|
+
]
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
if __FILE__ == $0
|
683
|
+
if ARGV.empty?
|
684
|
+
Prism::Template::TEMPLATES.each { |filepath| Prism::Template.render(filepath) }
|
685
|
+
else # ruby/ruby
|
686
|
+
name, write_to = ARGV
|
687
|
+
Prism::Template.render(name, write_to: write_to)
|
688
|
+
end
|
689
|
+
end
|