herb 0.7.1-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/error_helpers.c +27 -27
- data/ext/herb/extconf.rb +2 -1
- data/ext/herb/extension.c +6 -6
- data/ext/herb/extension_helpers.c +3 -3
- data/ext/herb/nodes.c +35 -35
- 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/engine/debug_visitor.rb +41 -21
- data/lib/herb/engine.rb +20 -6
- data/lib/herb/version.rb +1 -1
- data/sig/herb/engine/debug_visitor.rbs +3 -3
- data/sig/herb/engine.rbs +5 -0
- 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 +6 -9
- 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,406 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: false
|
3
|
+
|
4
|
+
require "erb"
|
5
|
+
require "fileutils"
|
6
|
+
require "yaml"
|
7
|
+
|
8
|
+
module Herb
|
9
|
+
module Template
|
10
|
+
class Field
|
11
|
+
attr_reader :name, :options
|
12
|
+
|
13
|
+
def initialize(name:, **options)
|
14
|
+
@name = name
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ArrayField < Field
|
20
|
+
def initialize(kind:, **options)
|
21
|
+
@kind = kind
|
22
|
+
super(**options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def ruby_type
|
26
|
+
return "Array" unless specific_kind
|
27
|
+
return "Array[Herb::AST::#{specific_kind}]" if specific_kind.end_with?("Node")
|
28
|
+
|
29
|
+
"Array[#{specific_kind}]"
|
30
|
+
end
|
31
|
+
|
32
|
+
def c_type
|
33
|
+
"array_T*"
|
34
|
+
end
|
35
|
+
|
36
|
+
def c_item_type
|
37
|
+
if specific_kind
|
38
|
+
"AST_#{specific_kind.gsub(/(?<=[a-zA-Z])(?=[A-Z][a-z])/, "_").upcase}_T*"
|
39
|
+
else
|
40
|
+
"void*"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def specific_kind
|
45
|
+
@kind unless @kind.is_a?(Array)
|
46
|
+
end
|
47
|
+
|
48
|
+
def union_kind
|
49
|
+
@kind if @kind.is_a?(Array)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class NodeField < Field
|
54
|
+
def initialize(kind:, **options)
|
55
|
+
@kind = kind
|
56
|
+
super(**options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def c_type
|
60
|
+
if specific_kind
|
61
|
+
"struct AST_#{specific_kind.gsub(/(?<=[a-zA-Z])(?=[A-Z][a-z])/, "_").upcase}_STRUCT*"
|
62
|
+
else
|
63
|
+
"AST_NODE_T*"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def ruby_type
|
68
|
+
"Herb::AST::#{specific_kind || "Node"}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def specific_kind
|
72
|
+
@kind unless @kind.is_a?(Array)
|
73
|
+
end
|
74
|
+
|
75
|
+
def union_kind
|
76
|
+
@kind if @kind.is_a?(Array)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class TokenField < Field
|
81
|
+
def ruby_type
|
82
|
+
"Herb::Token"
|
83
|
+
end
|
84
|
+
|
85
|
+
def c_type
|
86
|
+
"token_T*"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class TokenTypeField < Field
|
91
|
+
def ruby_type
|
92
|
+
"String"
|
93
|
+
end
|
94
|
+
|
95
|
+
def c_type
|
96
|
+
"token_type_T"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class StringField < Field
|
101
|
+
def ruby_type
|
102
|
+
"String"
|
103
|
+
end
|
104
|
+
|
105
|
+
def c_type
|
106
|
+
"const char*"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class PositionField < Field
|
111
|
+
def ruby_type
|
112
|
+
"Herb::Position"
|
113
|
+
end
|
114
|
+
|
115
|
+
def c_type
|
116
|
+
"position_T*"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class IntegerField < Field
|
121
|
+
def ruby_type
|
122
|
+
"Integer"
|
123
|
+
end
|
124
|
+
|
125
|
+
def c_type
|
126
|
+
"const int"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class SizeTField < Field
|
131
|
+
def ruby_type
|
132
|
+
"Integer"
|
133
|
+
end
|
134
|
+
|
135
|
+
def c_type
|
136
|
+
"size_t"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class BooleanField < Field
|
141
|
+
def ruby_type
|
142
|
+
"bool"
|
143
|
+
end
|
144
|
+
|
145
|
+
def c_type
|
146
|
+
"bool"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class PrismNodeField < Field
|
151
|
+
def ruby_type
|
152
|
+
"Prism::Node"
|
153
|
+
end
|
154
|
+
|
155
|
+
def c_type
|
156
|
+
"pm_node_t*"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class VoidPointerField < Field
|
161
|
+
def ruby_type
|
162
|
+
"nil"
|
163
|
+
end
|
164
|
+
|
165
|
+
def c_type
|
166
|
+
"void*"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class AnalyzedRubyField < Field
|
171
|
+
def ruby_type
|
172
|
+
"nil"
|
173
|
+
end
|
174
|
+
|
175
|
+
def c_type
|
176
|
+
"analyzed_ruby_T*"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class ElementSourceField < Field
|
181
|
+
def ruby_type
|
182
|
+
"String"
|
183
|
+
end
|
184
|
+
|
185
|
+
def c_type
|
186
|
+
"element_source_t"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
module ConfigType
|
191
|
+
private
|
192
|
+
|
193
|
+
def normalize_kind(kind, type, name, field_name)
|
194
|
+
if kind
|
195
|
+
kind = [kind] unless kind.is_a?(Array)
|
196
|
+
|
197
|
+
kind = kind.first if kind.size == 1
|
198
|
+
elsif type < NodeField
|
199
|
+
raise "Missing kind in config.yml for field #{name}##{field_name}"
|
200
|
+
end
|
201
|
+
|
202
|
+
kind
|
203
|
+
end
|
204
|
+
|
205
|
+
def field_type_for(name)
|
206
|
+
case name
|
207
|
+
when "array" then ArrayField
|
208
|
+
when "node" then NodeField
|
209
|
+
when "token" then TokenField
|
210
|
+
when "token_type" then TokenTypeField
|
211
|
+
when "string" then StringField
|
212
|
+
when "position" then PositionField
|
213
|
+
when "size_t" then SizeTField
|
214
|
+
when "boolean" then BooleanField
|
215
|
+
when "prism_node" then PrismNodeField
|
216
|
+
when "analyzed_ruby" then AnalyzedRubyField
|
217
|
+
when "element_source" then ElementSourceField
|
218
|
+
when "void*" then VoidPointerField
|
219
|
+
else raise("Unknown field type: #{name.inspect}")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class ErrorType
|
225
|
+
include ConfigType
|
226
|
+
|
227
|
+
attr_reader :name, :type, :struct_type, :struct_name, :human, :fields, :message_template, :message_arguments
|
228
|
+
|
229
|
+
def initialize(config)
|
230
|
+
@name = config.fetch("name")
|
231
|
+
@message_template = config.dig("message", "template")
|
232
|
+
@message_arguments = config.dig("message", "arguments")
|
233
|
+
|
234
|
+
camelized = @name.gsub(/(?<=[a-zA-Z])(?=[A-Z][a-z])/, "_")
|
235
|
+
@type = camelized.upcase
|
236
|
+
@struct_type = "#{camelized.upcase}_T"
|
237
|
+
@struct_name = "#{camelized.upcase}_STRUCT"
|
238
|
+
@human = camelized.downcase
|
239
|
+
|
240
|
+
@fields = config.fetch("fields", []).map do |field|
|
241
|
+
field_name = field.fetch("name")
|
242
|
+
type = field_type_for(field.fetch("type"))
|
243
|
+
kind = normalize_kind(field.fetch("kind", nil), type, @name, field_name)
|
244
|
+
|
245
|
+
type.new(name: field_name, kind: kind)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class NodeType
|
251
|
+
include ConfigType
|
252
|
+
|
253
|
+
attr_reader :name, :type, :struct_type, :struct_name, :human, :fields
|
254
|
+
|
255
|
+
def initialize(config)
|
256
|
+
@name = config.fetch("name")
|
257
|
+
camelized = @name.gsub(/(?<=[a-zA-Z])(?=[A-Z][a-z])/, "_")
|
258
|
+
@type = "AST_#{camelized.upcase}"
|
259
|
+
@struct_type = "AST_#{camelized.upcase}_T"
|
260
|
+
@struct_name = "AST_#{camelized.upcase}_STRUCT"
|
261
|
+
@human = camelized.downcase
|
262
|
+
|
263
|
+
@fields = config.fetch("fields", []).map do |field|
|
264
|
+
field_name = field.fetch("name")
|
265
|
+
type = field_type_for(field.fetch("type"))
|
266
|
+
kind = normalize_kind(field.fetch("kind", nil), type, @name, field_name)
|
267
|
+
|
268
|
+
type.new(name: field_name, kind: kind)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class PrintfMessageTemplate
|
274
|
+
MAX_STRING_SIZE = 128
|
275
|
+
|
276
|
+
# Estimated sizes for different format specifiers
|
277
|
+
ESTIMATED_SIZES = {
|
278
|
+
"%s" => MAX_STRING_SIZE, # Strings are truncated
|
279
|
+
"%d" => 11, # INT_MAX is 10 digits + sign
|
280
|
+
"%u" => 10, # UINT_MAX fits in 10 digits
|
281
|
+
"%zu" => 20, # Large enough for size_t
|
282
|
+
"%llu" => 20, # Large enough for long long unsigned
|
283
|
+
"%ld" => 20, # Large enough for long int
|
284
|
+
"%f" => 32, # Floating point with precision
|
285
|
+
"%lf" => 32, # Long double
|
286
|
+
}.freeze
|
287
|
+
|
288
|
+
def self.estimate_buffer_size(template)
|
289
|
+
base_length = template.length
|
290
|
+
total_size = base_length
|
291
|
+
|
292
|
+
format_specifiers = template.scan(/%[sdulfz]/)
|
293
|
+
|
294
|
+
format_specifiers.each_with_index do |specifier, _i|
|
295
|
+
estimated_size = ESTIMATED_SIZES[specifier] || 16 # Default extra buffer
|
296
|
+
total_size += estimated_size
|
297
|
+
end
|
298
|
+
|
299
|
+
total_size += 1 # Null terminator
|
300
|
+
total_size
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.heading_for(file, template_file)
|
305
|
+
case File.extname(file)
|
306
|
+
when ".rb", ".rbs"
|
307
|
+
<<~HEADING
|
308
|
+
# frozen_string_literal: true
|
309
|
+
# typed: true
|
310
|
+
|
311
|
+
# NOTE: This file is generated by the templates/template.rb script and should not be
|
312
|
+
# modified manually. See #{template_file}
|
313
|
+
|
314
|
+
HEADING
|
315
|
+
else
|
316
|
+
<<~HEADING
|
317
|
+
// NOTE: This file is generated by the templates/template.rb script and should not
|
318
|
+
// be modified manually. See #{template_file}
|
319
|
+
|
320
|
+
HEADING
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def self.check_gitignore(name)
|
325
|
+
file = Pathname.new(name)
|
326
|
+
file = file.absolute? ? file.relative_path_from(File.expand_path("../", __dir__)).to_s : file.to_s
|
327
|
+
return if gitignore_lines.include?(file)
|
328
|
+
|
329
|
+
puts "[WARNING]: make sure to add `#{file}` to the `.gitignore`"
|
330
|
+
puts
|
331
|
+
end
|
332
|
+
|
333
|
+
def self.render(template_file)
|
334
|
+
name = Pathname.new(template_file)
|
335
|
+
name = if name.absolute?
|
336
|
+
template_file.gsub(
|
337
|
+
"#{__dir__}/",
|
338
|
+
__dir__.delete_suffix("templates").to_s
|
339
|
+
)
|
340
|
+
else
|
341
|
+
name.to_s.delete_prefix("templates/")
|
342
|
+
end
|
343
|
+
|
344
|
+
name = name.delete_suffix(".erb")
|
345
|
+
|
346
|
+
destination = if Pathname.new(name).absolute?
|
347
|
+
Pathname.new(name)
|
348
|
+
else
|
349
|
+
Pathname.new(
|
350
|
+
File.expand_path("../#{name}", __dir__)
|
351
|
+
)
|
352
|
+
end
|
353
|
+
|
354
|
+
puts "Rendering #{template_file.delete_prefix("#{File.expand_path("../", __dir__)}/")} → #{destination}"
|
355
|
+
|
356
|
+
template_file = Pathname.new(template_file)
|
357
|
+
template_path = if template_file.absolute?
|
358
|
+
template_file
|
359
|
+
else
|
360
|
+
Pathname(
|
361
|
+
File.expand_path("../#{template_file}", __dir__)
|
362
|
+
)
|
363
|
+
end
|
364
|
+
|
365
|
+
rendered_template = read_template(template_path.to_s).result_with_hash({ nodes: nodes, errors: errors })
|
366
|
+
content = heading_for(name, template_file) + rendered_template
|
367
|
+
|
368
|
+
check_gitignore(name)
|
369
|
+
|
370
|
+
FileUtils.mkdir_p(File.dirname(destination))
|
371
|
+
File.write(destination, content)
|
372
|
+
rescue SyntaxError => e
|
373
|
+
puts
|
374
|
+
puts "Error while rendering #{template_file}:"
|
375
|
+
puts e
|
376
|
+
puts
|
377
|
+
end
|
378
|
+
|
379
|
+
def self.read_template(path)
|
380
|
+
content = File.read(path, encoding: Encoding::UTF_8)
|
381
|
+
|
382
|
+
ERB.new(content, trim_mode: "-").tap do |erb|
|
383
|
+
erb.filename = path
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def self.gitignore_lines
|
388
|
+
@gitignore_lines ||= File.readlines(".gitignore").map(&:chomp)
|
389
|
+
rescue Errno::ENOENT
|
390
|
+
puts "[Herb Templates] Couldn't find .gitignore"
|
391
|
+
[]
|
392
|
+
end
|
393
|
+
|
394
|
+
def self.nodes
|
395
|
+
(config.dig("nodes", "types") || []).map { |node| NodeType.new(node) }
|
396
|
+
end
|
397
|
+
|
398
|
+
def self.errors
|
399
|
+
(config.dig("errors", "types") || []).map { |node| ErrorType.new(node) }
|
400
|
+
end
|
401
|
+
|
402
|
+
def self.config
|
403
|
+
YAML.load_file("config.yml")
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
#include <emscripten/bind.h>
|
2
|
+
#include <emscripten/val.h>
|
3
|
+
|
4
|
+
#include <stdio.h>
|
5
|
+
#include <stdlib.h>
|
6
|
+
#include <string.h>
|
7
|
+
|
8
|
+
#include "extension_helpers.h"
|
9
|
+
|
10
|
+
extern "C" {
|
11
|
+
#include "../src/include/herb.h"
|
12
|
+
#include "../src/include/token.h"
|
13
|
+
#include "../src/include/array.h"
|
14
|
+
#include "../src/include/errors.h"
|
15
|
+
#include "../src/include/ast_node.h"
|
16
|
+
#include "../src/include/ast_nodes.h"
|
17
|
+
}
|
18
|
+
|
19
|
+
using namespace emscripten;
|
20
|
+
|
21
|
+
val CreateLocation(location_T* location);
|
22
|
+
val CreateToken(token_T* token);
|
23
|
+
val NodeFromCStruct(AST_NODE_T* node);
|
24
|
+
val NodesArrayFromCArray(array_T* array);
|
25
|
+
val ErrorFromCStruct(ERROR_T* error);
|
26
|
+
val ErrorsArrayFromCArray(array_T* array);
|
27
|
+
|
28
|
+
<%- errors.each do |error| -%>
|
29
|
+
val <%= error.name %>FromCStruct(<%= error.struct_type %>* <%= error.human %>) {
|
30
|
+
if (!<%= error.human %>) {
|
31
|
+
return val::null();
|
32
|
+
}
|
33
|
+
|
34
|
+
val Object = val::global("Object");
|
35
|
+
val result = Object.new_();
|
36
|
+
|
37
|
+
result.set("type", CreateString(error_type_to_string(&<%= error.human %>->base)));
|
38
|
+
result.set("message", CreateString(<%= error.human %>->base.message));
|
39
|
+
result.set("location", CreateLocation(<%= error.human %>->base.location));
|
40
|
+
<%- error.fields.each do |field| -%>
|
41
|
+
<%- case field -%>
|
42
|
+
<%- when Herb::Template::StringField -%>
|
43
|
+
result.set("<%= field.name %>", CreateString(<%= error.human %>-><%= field.name %>));
|
44
|
+
<%- when Herb::Template::NodeField -%>
|
45
|
+
result.set("<%= field.name %>", NodeFromCStruct((AST_NODE_T*)<%= error.human %>-><%= field.name %>));
|
46
|
+
<%- when Herb::Template::TokenField -%>
|
47
|
+
result.set("<%= field.name %>", CreateToken(<%= error.human %>-><%= field.name %>));
|
48
|
+
<%- when Herb::Template::TokenTypeField -%>
|
49
|
+
result.set("<%= field.name %>", CreateString(token_type_to_string(<%= error.human %>-><%= field.name %>)));
|
50
|
+
<%- when Herb::Template::BooleanField -%>
|
51
|
+
result.set("<%= field.name %>", <%= error.human %>-><%= field.name %>);
|
52
|
+
<%- when Herb::Template::ArrayField -%>
|
53
|
+
result.set("<%= field.name %>", NodesArrayFromCArray(<%= error.human %>-><%= field.name %>));
|
54
|
+
<%- else -%>
|
55
|
+
result.set("<%= field.name %>", val::null());
|
56
|
+
<%- end -%>
|
57
|
+
<%- end -%>
|
58
|
+
|
59
|
+
return result;
|
60
|
+
}
|
61
|
+
|
62
|
+
<%- end -%>
|
63
|
+
|
64
|
+
val ErrorsArrayFromCArray(array_T* array) {
|
65
|
+
val Array = val::global("Array");
|
66
|
+
val result = Array.new_();
|
67
|
+
|
68
|
+
if (array) {
|
69
|
+
for (size_t i = 0; i < array_size(array); i++) {
|
70
|
+
ERROR_T* error = (ERROR_T*)array_get(array, i);
|
71
|
+
if (error) {
|
72
|
+
result.call<void>("push", ErrorFromCStruct(error));
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
return result;
|
78
|
+
}
|
79
|
+
|
80
|
+
val ErrorFromCStruct(ERROR_T* error) {
|
81
|
+
if (!error) {
|
82
|
+
return val::null();
|
83
|
+
}
|
84
|
+
|
85
|
+
switch (error->type) {
|
86
|
+
<%- errors.each do |error| -%>
|
87
|
+
case <%= error.type %>:
|
88
|
+
return <%= error.name %>FromCStruct((<%= error.struct_type %>*)error);
|
89
|
+
<%- end -%>
|
90
|
+
default:
|
91
|
+
return val::null();
|
92
|
+
}
|
93
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef HERB_EXTENSION_ERRORS_H
|
2
|
+
#define HERB_EXTENSION_ERRORS_H
|
3
|
+
|
4
|
+
extern "C" {
|
5
|
+
#include "../src/include/herb.h"
|
6
|
+
}
|
7
|
+
|
8
|
+
emscripten::val ErrorFromCStruct(ERROR_T* error);
|
9
|
+
emscripten::val ErrorsArrayFromCArray(array_T* array);
|
10
|
+
|
11
|
+
<%- errors.each do |error| -%>
|
12
|
+
emscripten::val <%= error.name %>FromCStruct(<%= error.struct_type %>* <%= error.human %>);
|
13
|
+
<%- end -%>
|
14
|
+
|
15
|
+
#endif
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#include <emscripten/bind.h>
|
2
|
+
#include <emscripten/val.h>
|
3
|
+
|
4
|
+
#include "error_helpers.h"
|
5
|
+
#include "extension_helpers.h"
|
6
|
+
|
7
|
+
#include "../src/include/herb.h"
|
8
|
+
#include "../src/include/token.h"
|
9
|
+
#include "../src/include/array.h"
|
10
|
+
#include "../src/include/ast_node.h"
|
11
|
+
#include "../src/include/ast_nodes.h"
|
12
|
+
#include "../src/include/location.h"
|
13
|
+
|
14
|
+
using namespace emscripten;
|
15
|
+
|
16
|
+
val NodeFromCStruct(AST_NODE_T* node);
|
17
|
+
val NodesArrayFromCArray(array_T* array);
|
18
|
+
|
19
|
+
<%- nodes.each do |node| -%>
|
20
|
+
val <%= node.name %>FromCStruct(<%= node.struct_type %>* <%= node.human %>) {
|
21
|
+
if (!<%= node.human %>) return val::null();
|
22
|
+
|
23
|
+
val result = val::object();
|
24
|
+
result.set("type", CreateString(ast_node_type_to_string(&<%= node.human %>->base)));
|
25
|
+
result.set("location", CreateLocation(<%= node.human %>->base.location));
|
26
|
+
result.set("errors", ErrorsArrayFromCArray(<%= node.human %>->base.errors));
|
27
|
+
|
28
|
+
<%- node.fields.each do |field| -%>
|
29
|
+
<%- case field -%>
|
30
|
+
<%- when Herb::Template::StringField -%>
|
31
|
+
result.set("<%= field.name %>", CreateString(<%= node.human %>-><%= field.name %>));
|
32
|
+
<%- when Herb::Template::NodeField -%>
|
33
|
+
result.set("<%= field.name %>", NodeFromCStruct((AST_NODE_T*) <%= node.human %>-><%= field.name %>));
|
34
|
+
<%- when Herb::Template::TokenField -%>
|
35
|
+
result.set("<%= field.name %>", CreateToken(<%= node.human %>-><%= field.name %>));
|
36
|
+
<%- when Herb::Template::BooleanField -%>
|
37
|
+
result.set("<%= field.name %>", <%= node.human %>-><%= field.name %> ? true : false);
|
38
|
+
<%- when Herb::Template::ArrayField -%>
|
39
|
+
result.set("<%= field.name %>", NodesArrayFromCArray(<%= node.human %>-><%= field.name %>));
|
40
|
+
<%- when Herb::Template::ElementSourceField -%>
|
41
|
+
result.set("<%= field.name %>", CreateString(element_source_to_string(<%= node.human %>-><%= field.name %>)));
|
42
|
+
<%- else -%>
|
43
|
+
result.set("<%= field.name %>", val::null());
|
44
|
+
<%- end -%>
|
45
|
+
<%- end -%>
|
46
|
+
|
47
|
+
return result;
|
48
|
+
}
|
49
|
+
|
50
|
+
<%- end -%>
|
51
|
+
|
52
|
+
val NodeFromCStruct(AST_NODE_T* node) {
|
53
|
+
if (!node) return val::null();
|
54
|
+
|
55
|
+
switch (node->type) {
|
56
|
+
<%- nodes.each do |node| -%>
|
57
|
+
case <%= node.type %>:
|
58
|
+
return <%= node.name %>FromCStruct((<%= node.struct_type %>*) node);
|
59
|
+
<%- end -%>
|
60
|
+
default:
|
61
|
+
return val::null();
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
val NodesArrayFromCArray(array_T* array) {
|
66
|
+
if (!array) return val::null();
|
67
|
+
|
68
|
+
val jsArray = val::array();
|
69
|
+
|
70
|
+
for (size_t i = 0; i < array_size(array); i++) {
|
71
|
+
AST_NODE_T* child_node = (AST_NODE_T*) array_get(array, i);
|
72
|
+
|
73
|
+
if (child_node) {
|
74
|
+
jsArray.set(i, NodeFromCStruct(child_node));
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
return jsArray;
|
79
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef HERB_EXTENSION_NODES_H
|
2
|
+
#define HERB_EXTENSION_NODES_H
|
3
|
+
|
4
|
+
extern "C" {
|
5
|
+
#include "../src/include/herb.h"
|
6
|
+
}
|
7
|
+
|
8
|
+
emscripten::val NodeFromCStruct(AST_NODE_T* node);
|
9
|
+
emscripten::val NodesArrayFromCArray(array_T* array);
|
10
|
+
|
11
|
+
<%- nodes.each do |node| -%>
|
12
|
+
emscripten::val <%= node.human %>NodeFromCStruct(<%= node.struct_type %>* <%= node.human %>);
|
13
|
+
<%- end -%>
|
14
|
+
|
15
|
+
#endif
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/clean"
|
5
|
+
|
6
|
+
task default: %i[compile test]
|
7
|
+
|
8
|
+
require_relative "templates/template"
|
9
|
+
|
10
|
+
desc "Generate all ERB template based files"
|
11
|
+
task templates: Prism::Template::TEMPLATES
|
12
|
+
|
13
|
+
make = RUBY_PLATFORM.match?(/openbsd|freebsd/) ? "gmake" : "make"
|
14
|
+
task(make: :templates) { sh(make) }
|
15
|
+
task(make_no_debug: :templates) { sh("#{make} all-no-debug") }
|
16
|
+
task(make_minimal: :templates) { sh("#{make} minimal") }
|
17
|
+
|
18
|
+
task compile: :make
|
19
|
+
task compile_no_debug: %i[make_no_debug compile]
|
20
|
+
task compile_minimal: %i[make_minimal compile]
|
21
|
+
|
22
|
+
# decorate the gem build task with prerequisites
|
23
|
+
task build: [:check_manifest, :templates]
|
24
|
+
|
25
|
+
# the C extension
|
26
|
+
task "compile:prism" => ["templates"] # must be before the ExtensionTask is created
|
27
|
+
|
28
|
+
if RUBY_ENGINE == "ruby" and !ENV["PRISM_FFI_BACKEND"]
|
29
|
+
require "rake/extensiontask"
|
30
|
+
|
31
|
+
Rake::ExtensionTask.new(:compile) do |ext|
|
32
|
+
ext.name = "prism"
|
33
|
+
ext.ext_dir = "ext/prism"
|
34
|
+
ext.lib_dir = "lib/prism"
|
35
|
+
ext.gem_spec = Gem::Specification.load("prism.gemspec")
|
36
|
+
end
|
37
|
+
elsif RUBY_ENGINE == "jruby"
|
38
|
+
require "rake/javaextensiontask"
|
39
|
+
|
40
|
+
# This compiles java to make sure any templating changes produces valid code.
|
41
|
+
Rake::JavaExtensionTask.new(:compile) do |ext|
|
42
|
+
ext.name = "prism"
|
43
|
+
ext.ext_dir = "java"
|
44
|
+
ext.lib_dir = "tmp"
|
45
|
+
ext.source_version = "1.8"
|
46
|
+
ext.target_version = "1.8"
|
47
|
+
ext.gem_spec = Gem::Specification.load("prism.gemspec")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# So `rake clobber` will delete generated files
|
52
|
+
CLOBBER.concat(Prism::Template::TEMPLATES)
|
53
|
+
CLOBBER.concat(["build"])
|
54
|
+
CLOBBER << "lib/prism/prism.#{RbConfig::CONFIG["DLEXT"]}"
|
55
|
+
|
56
|
+
Prism::Template::TEMPLATES.each do |filepath|
|
57
|
+
desc "Generate #{filepath}"
|
58
|
+
file filepath => ["templates/#{filepath}.erb", "templates/template.rb", "config.yml"] do |t|
|
59
|
+
Prism::Template.render(t.name)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
namespace :build do
|
64
|
+
task :dev_version_set do
|
65
|
+
filepath = File.expand_path("prism.gemspec", __dir__)
|
66
|
+
File.write(filepath, File.read(filepath).sub(/spec\.version = ".+?"/, %Q{spec.version = "9999.9.9"}))
|
67
|
+
end
|
68
|
+
|
69
|
+
task :dev_version_clear do
|
70
|
+
sh "git checkout -- prism.gemspec Gemfile.lock"
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "Build a development version of the gem"
|
74
|
+
task dev: ["build:dev_version_set", "build", "build:dev_version_clear"]
|
75
|
+
end
|