herb 0.7.1 → 0.7.3

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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +2 -0
  3. data/README.md +1 -1
  4. data/Rakefile +46 -1
  5. data/config.yml +714 -0
  6. data/ext/herb/error_helpers.c +27 -27
  7. data/ext/herb/extconf.rb +2 -1
  8. data/ext/herb/extension.c +6 -6
  9. data/ext/herb/extension_helpers.c +3 -3
  10. data/ext/herb/nodes.c +35 -35
  11. data/herb.gemspec +3 -0
  12. data/lib/herb/engine/debug_visitor.rb +41 -21
  13. data/lib/herb/engine.rb +20 -6
  14. data/lib/herb/version.rb +1 -1
  15. data/sig/herb/engine/debug_visitor.rbs +3 -3
  16. data/sig/herb/engine.rbs +5 -0
  17. data/src/analyze.c +5 -9
  18. data/src/analyze_helpers.c +17 -6
  19. data/src/include/pretty_print.h +1 -1
  20. data/src/include/version.h +1 -1
  21. data/src/parser.c +6 -9
  22. data/src/pretty_print.c +1 -1
  23. data/templates/ext/herb/error_helpers.c.erb +85 -0
  24. data/templates/ext/herb/error_helpers.h.erb +12 -0
  25. data/templates/ext/herb/nodes.c.erb +90 -0
  26. data/templates/ext/herb/nodes.h.erb +9 -0
  27. data/templates/javascript/packages/core/src/errors.ts.erb +193 -0
  28. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +325 -0
  29. data/templates/javascript/packages/core/src/nodes.ts.erb +414 -0
  30. data/templates/javascript/packages/core/src/visitor.ts.erb +29 -0
  31. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +113 -0
  32. data/templates/javascript/packages/node/extension/error_helpers.h.erb +17 -0
  33. data/templates/javascript/packages/node/extension/nodes.cpp.erb +111 -0
  34. data/templates/javascript/packages/node/extension/nodes.h.erb +17 -0
  35. data/templates/lib/herb/ast/nodes.rb.erb +117 -0
  36. data/templates/lib/herb/errors.rb.erb +106 -0
  37. data/templates/lib/herb/visitor.rb.erb +28 -0
  38. data/templates/sig/serialized_ast_errors.rbs.erb +10 -0
  39. data/templates/sig/serialized_ast_nodes.rbs.erb +10 -0
  40. data/templates/src/ast_nodes.c.erb +145 -0
  41. data/templates/src/ast_pretty_print.c.erb +97 -0
  42. data/templates/src/errors.c.erb +245 -0
  43. data/templates/src/include/ast_nodes.h.erb +46 -0
  44. data/templates/src/include/ast_pretty_print.h.erb +14 -0
  45. data/templates/src/include/errors.h.erb +58 -0
  46. data/templates/src/visitor.c.erb +47 -0
  47. data/templates/template.rb +406 -0
  48. data/templates/wasm/error_helpers.cpp.erb +93 -0
  49. data/templates/wasm/error_helpers.h.erb +15 -0
  50. data/templates/wasm/nodes.cpp.erb +79 -0
  51. data/templates/wasm/nodes.h.erb +15 -0
  52. data/vendor/prism/Rakefile +75 -0
  53. data/vendor/prism/config.yml +4713 -0
  54. data/vendor/prism/include/prism/ast.h +8190 -0
  55. data/vendor/prism/include/prism/defines.h +260 -0
  56. data/vendor/prism/include/prism/diagnostic.h +455 -0
  57. data/vendor/prism/include/prism/encoding.h +283 -0
  58. data/vendor/prism/include/prism/node.h +129 -0
  59. data/vendor/prism/include/prism/options.h +482 -0
  60. data/vendor/prism/include/prism/pack.h +163 -0
  61. data/vendor/prism/include/prism/parser.h +933 -0
  62. data/vendor/prism/include/prism/prettyprint.h +34 -0
  63. data/vendor/prism/include/prism/regexp.h +43 -0
  64. data/vendor/prism/include/prism/static_literals.h +121 -0
  65. data/vendor/prism/include/prism/util/pm_buffer.h +236 -0
  66. data/vendor/prism/include/prism/util/pm_char.h +204 -0
  67. data/vendor/prism/include/prism/util/pm_constant_pool.h +218 -0
  68. data/vendor/prism/include/prism/util/pm_integer.h +130 -0
  69. data/vendor/prism/include/prism/util/pm_list.h +103 -0
  70. data/vendor/prism/include/prism/util/pm_memchr.h +29 -0
  71. data/vendor/prism/include/prism/util/pm_newline_list.h +113 -0
  72. data/vendor/prism/include/prism/util/pm_string.h +200 -0
  73. data/vendor/prism/include/prism/util/pm_strncasecmp.h +32 -0
  74. data/vendor/prism/include/prism/util/pm_strpbrk.h +46 -0
  75. data/vendor/prism/include/prism/version.h +29 -0
  76. data/vendor/prism/include/prism.h +408 -0
  77. data/vendor/prism/src/diagnostic.c +848 -0
  78. data/vendor/prism/src/encoding.c +5235 -0
  79. data/vendor/prism/src/node.c +8676 -0
  80. data/vendor/prism/src/options.c +328 -0
  81. data/vendor/prism/src/pack.c +509 -0
  82. data/vendor/prism/src/prettyprint.c +8941 -0
  83. data/vendor/prism/src/prism.c +23302 -0
  84. data/vendor/prism/src/regexp.c +790 -0
  85. data/vendor/prism/src/serialize.c +2268 -0
  86. data/vendor/prism/src/static_literals.c +617 -0
  87. data/vendor/prism/src/token_type.c +703 -0
  88. data/vendor/prism/src/util/pm_buffer.c +357 -0
  89. data/vendor/prism/src/util/pm_char.c +318 -0
  90. data/vendor/prism/src/util/pm_constant_pool.c +342 -0
  91. data/vendor/prism/src/util/pm_integer.c +670 -0
  92. data/vendor/prism/src/util/pm_list.c +49 -0
  93. data/vendor/prism/src/util/pm_memchr.c +35 -0
  94. data/vendor/prism/src/util/pm_newline_list.c +125 -0
  95. data/vendor/prism/src/util/pm_string.c +383 -0
  96. data/vendor/prism/src/util/pm_strncasecmp.c +36 -0
  97. data/vendor/prism/src/util/pm_strpbrk.c +206 -0
  98. data/vendor/prism/templates/ext/prism/api_node.c.erb +282 -0
  99. data/vendor/prism/templates/include/prism/ast.h.erb +226 -0
  100. data/vendor/prism/templates/include/prism/diagnostic.h.erb +130 -0
  101. data/vendor/prism/templates/java/org/prism/AbstractNodeVisitor.java.erb +22 -0
  102. data/vendor/prism/templates/java/org/prism/Loader.java.erb +434 -0
  103. data/vendor/prism/templates/java/org/prism/Nodes.java.erb +403 -0
  104. data/vendor/prism/templates/javascript/src/deserialize.js.erb +448 -0
  105. data/vendor/prism/templates/javascript/src/nodes.js.erb +197 -0
  106. data/vendor/prism/templates/javascript/src/visitor.js.erb +78 -0
  107. data/vendor/prism/templates/lib/prism/compiler.rb.erb +43 -0
  108. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +103 -0
  109. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +189 -0
  110. data/vendor/prism/templates/lib/prism/dsl.rb.erb +133 -0
  111. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +131 -0
  112. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +19 -0
  113. data/vendor/prism/templates/lib/prism/node.rb.erb +515 -0
  114. data/vendor/prism/templates/lib/prism/reflection.rb.erb +136 -0
  115. data/vendor/prism/templates/lib/prism/serialize.rb.erb +602 -0
  116. data/vendor/prism/templates/lib/prism/visitor.rb.erb +55 -0
  117. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +68 -0
  118. data/vendor/prism/templates/rbi/prism/node.rbi.erb +164 -0
  119. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +18 -0
  120. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +45 -0
  121. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +31 -0
  122. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +7 -0
  123. data/vendor/prism/templates/sig/prism/node.rbs.erb +132 -0
  124. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +17 -0
  125. data/vendor/prism/templates/sig/prism.rbs.erb +89 -0
  126. data/vendor/prism/templates/src/diagnostic.c.erb +523 -0
  127. data/vendor/prism/templates/src/node.c.erb +333 -0
  128. data/vendor/prism/templates/src/prettyprint.c.erb +166 -0
  129. data/vendor/prism/templates/src/serialize.c.erb +406 -0
  130. data/vendor/prism/templates/src/token_type.c.erb +369 -0
  131. data/vendor/prism/templates/template.rb +689 -0
  132. metadata +112 -2
@@ -0,0 +1,434 @@
1
+ <%- string_type = Prism::Template::JAVA_STRING_TYPE -%>
2
+ package org.prism;
3
+
4
+ import org.prism.Nodes;
5
+
6
+ import java.lang.Short;
7
+ import java.math.BigInteger;
8
+ import java.nio.ByteBuffer;
9
+ import java.nio.ByteOrder;
10
+ import java.nio.charset.Charset;
11
+ import java.nio.charset.StandardCharsets;
12
+ import java.util.Locale;
13
+
14
+ // GENERATED BY <%= File.basename(__FILE__) %>
15
+ // @formatter:off
16
+ public class Loader {
17
+
18
+ public static ParseResult load(byte[] serialized, byte[] sourceBytes) {
19
+ return new Loader(serialized, sourceBytes).load();
20
+ }
21
+
22
+ // Overridable methods
23
+
24
+ public Charset getEncodingCharset(String encodingName) {
25
+ encodingName = encodingName.toLowerCase(Locale.ROOT);
26
+ if (encodingName.equals("ascii-8bit")) {
27
+ return StandardCharsets.US_ASCII;
28
+ }
29
+ return Charset.forName(encodingName);
30
+ }
31
+
32
+ public <%= string_type %> bytesToName(byte[] bytes) {
33
+ <%- if string_type == "String" -%>
34
+ return new String(bytes, encodingCharset).intern();
35
+ <%- else -%>
36
+ return null; // Must be implemented by subclassing Loader
37
+ <%- end -%>
38
+ }
39
+
40
+ private static final class ConstantPool {
41
+
42
+ private final Loader loader;
43
+ private final byte[] source;
44
+ private final int bufferOffset;
45
+ private final <%= string_type %>[] cache;
46
+
47
+ ConstantPool(Loader loader, byte[] source, int bufferOffset, int length) {
48
+ this.loader = loader;
49
+ this.source = source;
50
+ this.bufferOffset = bufferOffset;
51
+ cache = new <%= string_type %>[length];
52
+ }
53
+
54
+ <%= string_type %> get(ByteBuffer buffer, int oneBasedIndex) {
55
+ int index = oneBasedIndex - 1;
56
+ <%= string_type %> constant = cache[index];
57
+
58
+ if (constant == null) {
59
+ int offset = bufferOffset + index * 8;
60
+ int start = buffer.getInt(offset);
61
+ int length = buffer.getInt(offset + 4);
62
+
63
+ byte[] bytes = new byte[length];
64
+
65
+ if (Integer.compareUnsigned(start, 0x7FFFFFFF) <= 0) {
66
+ System.arraycopy(source, start, bytes, 0, length);
67
+ } else {
68
+ int position = buffer.position();
69
+ buffer.position(start & 0x7FFFFFFF);
70
+ buffer.get(bytes, 0, length);
71
+ buffer.position(position);
72
+ }
73
+
74
+ constant = loader.bytesToName(bytes);
75
+ cache[index] = constant;
76
+ }
77
+
78
+ return constant;
79
+ }
80
+
81
+ }
82
+
83
+ private final ByteBuffer buffer;
84
+ private final Nodes.Source source;
85
+ protected String encodingName;
86
+ <%- if string_type == "String" -%>
87
+ private Charset encodingCharset;
88
+ <%- end -%>
89
+ private ConstantPool constantPool;
90
+
91
+ protected Loader(byte[] serialized, byte[] sourceBytes) {
92
+ this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder());
93
+ this.source = new Nodes.Source(sourceBytes);
94
+ }
95
+
96
+ protected ParseResult load() {
97
+ expect((byte) 'P', "incorrect prism header");
98
+ expect((byte) 'R', "incorrect prism header");
99
+ expect((byte) 'I', "incorrect prism header");
100
+ expect((byte) 'S', "incorrect prism header");
101
+ expect((byte) 'M', "incorrect prism header");
102
+
103
+ expect((byte) 1, "prism major version does not match");
104
+ expect((byte) 5, "prism minor version does not match");
105
+ expect((byte) 1, "prism patch version does not match");
106
+
107
+ expect((byte) 1, "Loader.java requires no location fields in the serialized output");
108
+
109
+ // This loads the name of the encoding.
110
+ int encodingLength = loadVarUInt();
111
+ byte[] encodingNameBytes = new byte[encodingLength];
112
+ buffer.get(encodingNameBytes);
113
+ this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII);
114
+ <%- if string_type == "String" -%>
115
+ this.encodingCharset = getEncodingCharset(this.encodingName);
116
+ <%- end -%>
117
+
118
+ source.setStartLine(loadVarSInt());
119
+ source.setLineOffsets(loadLineOffsets());
120
+
121
+ ParseResult.MagicComment[] magicComments = loadMagicComments();
122
+ Nodes.Location dataLocation = loadOptionalLocation();
123
+ ParseResult.Error[] errors = loadErrors();
124
+ ParseResult.Warning[] warnings = loadWarnings();
125
+
126
+ int constantPoolBufferOffset = buffer.getInt();
127
+ int constantPoolLength = loadVarUInt();
128
+ this.constantPool = new ConstantPool(this, source.bytes, constantPoolBufferOffset, constantPoolLength);
129
+
130
+ Nodes.Node node;
131
+ if (errors.length == 0) {
132
+ node = loadNode();
133
+
134
+ int left = constantPoolBufferOffset - buffer.position();
135
+ if (left != 0) {
136
+ throw new Error("Expected to consume all bytes while deserializing but there were " + left + " bytes left");
137
+ }
138
+
139
+ boolean[] newlineMarked = new boolean[1 + source.getLineCount()];
140
+ MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source, newlineMarked);
141
+ node.accept(visitor);
142
+ } else {
143
+ node = null;
144
+ }
145
+
146
+ return new ParseResult(node, magicComments, dataLocation, errors, warnings, source);
147
+ }
148
+
149
+ private byte[] loadEmbeddedString() {
150
+ int length = loadVarUInt();
151
+ byte[] bytes = new byte[length];
152
+ buffer.get(bytes);
153
+ return bytes;
154
+ }
155
+
156
+ private byte[] loadString() {
157
+ switch (buffer.get()) {
158
+ case 1:
159
+ int start = loadVarUInt();
160
+ int length = loadVarUInt();
161
+ byte[] bytes = new byte[length];
162
+ System.arraycopy(source.bytes, start, bytes, 0, length);
163
+ return bytes;
164
+ case 2:
165
+ return loadEmbeddedString();
166
+ default:
167
+ throw new Error("Expected 0 or 1 but was " + buffer.get());
168
+ }
169
+ }
170
+
171
+ private int[] loadLineOffsets() {
172
+ int count = loadVarUInt();
173
+ int[] lineOffsets = new int[count];
174
+ for (int i = 0; i < count; i++) {
175
+ lineOffsets[i] = loadVarUInt();
176
+ }
177
+ return lineOffsets;
178
+ }
179
+
180
+ private ParseResult.MagicComment[] loadMagicComments() {
181
+ int count = loadVarUInt();
182
+ ParseResult.MagicComment[] magicComments = new ParseResult.MagicComment[count];
183
+
184
+ for (int i = 0; i < count; i++) {
185
+ Nodes.Location keyLocation = loadLocation();
186
+ Nodes.Location valueLocation = loadLocation();
187
+
188
+ ParseResult.MagicComment magicComment = new ParseResult.MagicComment(keyLocation, valueLocation);
189
+ magicComments[i] = magicComment;
190
+ }
191
+
192
+ return magicComments;
193
+ }
194
+
195
+ private ParseResult.Error[] loadErrors() {
196
+ int count = loadVarUInt();
197
+ ParseResult.Error[] errors = new ParseResult.Error[count];
198
+
199
+ // error messages only contain ASCII characters
200
+ for (int i = 0; i < count; i++) {
201
+ Nodes.ErrorType type = Nodes.ERROR_TYPES[loadVarUInt()];
202
+ byte[] bytes = loadEmbeddedString();
203
+ String message = new String(bytes, StandardCharsets.US_ASCII);
204
+ Nodes.Location location = loadLocation();
205
+ ParseResult.ErrorLevel level = ParseResult.ERROR_LEVELS[buffer.get()];
206
+
207
+ ParseResult.Error error = new ParseResult.Error(type, message, location, level);
208
+ errors[i] = error;
209
+ }
210
+
211
+ return errors;
212
+ }
213
+
214
+ private ParseResult.Warning[] loadWarnings() {
215
+ int count = loadVarUInt();
216
+ ParseResult.Warning[] warnings = new ParseResult.Warning[count];
217
+
218
+ // warning messages only contain ASCII characters
219
+ for (int i = 0; i < count; i++) {
220
+ Nodes.WarningType type = Nodes.WARNING_TYPES[loadVarUInt() - <%= errors.length %>];
221
+ byte[] bytes = loadEmbeddedString();
222
+ String message = new String(bytes, StandardCharsets.US_ASCII);
223
+ Nodes.Location location = loadLocation();
224
+ ParseResult.WarningLevel level = ParseResult.WARNING_LEVELS[buffer.get()];
225
+
226
+ ParseResult.Warning warning = new ParseResult.Warning(type, message, location, level);
227
+ warnings[i] = warning;
228
+ }
229
+
230
+ return warnings;
231
+ }
232
+
233
+ private Nodes.Node loadOptionalNode() {
234
+ if (buffer.get(buffer.position()) != 0) {
235
+ return loadNode();
236
+ } else {
237
+ buffer.position(buffer.position() + 1); // continue after the 0 byte
238
+ return null;
239
+ }
240
+ }
241
+
242
+ private <%= string_type %> loadConstant() {
243
+ return constantPool.get(buffer, loadVarUInt());
244
+ }
245
+
246
+ private <%= string_type %> loadOptionalConstant() {
247
+ if (buffer.get(buffer.position()) != 0) {
248
+ return loadConstant();
249
+ } else {
250
+ buffer.position(buffer.position() + 1); // continue after the 0 byte
251
+ return null;
252
+ }
253
+ }
254
+
255
+ private <%= string_type %>[] loadConstants() {
256
+ int length = loadVarUInt();
257
+ if (length == 0) {
258
+ return Nodes.EMPTY_STRING_ARRAY;
259
+ }
260
+ <%= string_type %>[] constants = new <%= string_type %>[length];
261
+ for (int i = 0; i < length; i++) {
262
+ constants[i] = constantPool.get(buffer, loadVarUInt());
263
+ }
264
+ return constants;
265
+ }
266
+
267
+ private Nodes.Location loadLocation() {
268
+ return new Nodes.Location(loadVarUInt(), loadVarUInt());
269
+ }
270
+
271
+ private Nodes.Location loadOptionalLocation() {
272
+ if (buffer.get() != 0) {
273
+ return loadLocation();
274
+ } else {
275
+ return null;
276
+ }
277
+ }
278
+
279
+ // From https://github.com/protocolbuffers/protobuf/blob/v23.1/java/core/src/main/java/com/google/protobuf/BinaryReader.java#L1507
280
+ private int loadVarUInt() {
281
+ int x;
282
+ if ((x = buffer.get()) >= 0) {
283
+ return x;
284
+ } else if ((x ^= (buffer.get() << 7)) < 0) {
285
+ x ^= (~0 << 7);
286
+ } else if ((x ^= (buffer.get() << 14)) >= 0) {
287
+ x ^= (~0 << 7) ^ (~0 << 14);
288
+ } else if ((x ^= (buffer.get() << 21)) < 0) {
289
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
290
+ } else {
291
+ x ^= buffer.get() << 28;
292
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
293
+ }
294
+ return x;
295
+ }
296
+
297
+ // From https://github.com/protocolbuffers/protobuf/blob/v25.1/java/core/src/main/java/com/google/protobuf/CodedInputStream.java#L508-L510
298
+ private int loadVarSInt() {
299
+ int x = loadVarUInt();
300
+ return (x >>> 1) ^ (-(x & 1));
301
+ }
302
+
303
+ private short loadFlags() {
304
+ int flags = loadVarUInt();
305
+ assert flags >= 0 && flags <= Short.MAX_VALUE;
306
+ return (short) flags;
307
+ }
308
+
309
+ private static final BigInteger UNSIGNED_LONG_MASK = BigInteger.ONE.shiftLeft(Long.SIZE).subtract(BigInteger.ONE);
310
+
311
+ private Object loadInteger() {
312
+ boolean negative = buffer.get() != 0;
313
+
314
+ int wordsLength = loadVarUInt();
315
+ assert wordsLength > 0;
316
+
317
+ // Load the first word. If it's the only word, then return an int if it
318
+ // fits into one and a long otherwise.
319
+ int firstWord = loadVarUInt();
320
+ if (wordsLength == 1) {
321
+ if (firstWord < 0) {
322
+ if (negative && firstWord == Integer.MIN_VALUE) {
323
+ return Integer.MIN_VALUE;
324
+ }
325
+
326
+ long words = Integer.toUnsignedLong(firstWord);
327
+ return negative ? -words : words;
328
+ }
329
+ return negative ? -firstWord : firstWord;
330
+ }
331
+
332
+ // Load the second word. If there are only two words, then return a long
333
+ // if it fits into one and a BigInteger otherwise.
334
+ int secondWord = loadVarUInt();
335
+ if (wordsLength == 2) {
336
+ long words = (((long) secondWord) << 32L) | Integer.toUnsignedLong(firstWord);
337
+ if (words < 0L) {
338
+ if (negative && words == Long.MIN_VALUE) {
339
+ return Long.MIN_VALUE;
340
+ }
341
+
342
+ BigInteger result = BigInteger.valueOf(words).and(UNSIGNED_LONG_MASK);
343
+ return negative ? result.negate() : result;
344
+ }
345
+ return negative ? -words : words;
346
+ }
347
+
348
+ // Otherwise, load the remaining words and return a BigInt.
349
+ BigInteger result = BigInteger.valueOf(Integer.toUnsignedLong(firstWord));
350
+ result = result.or(BigInteger.valueOf(Integer.toUnsignedLong(secondWord)).shiftLeft(32));
351
+
352
+ for (int wordsIndex = 2; wordsIndex < wordsLength; wordsIndex++) {
353
+ result = result.or(BigInteger.valueOf(Integer.toUnsignedLong(loadVarUInt())).shiftLeft(wordsIndex * 32));
354
+ }
355
+
356
+ return negative ? result.negate() : result;
357
+ }
358
+
359
+ private Nodes.Node loadNode() {
360
+ int type = buffer.get() & 0xFF;
361
+ <%- if Prism::Template::INCLUDE_NODE_ID -%>
362
+ int nodeId = loadVarUInt();
363
+ <%- end -%>
364
+ int startOffset = loadVarUInt();
365
+ int length = loadVarUInt();
366
+
367
+ switch (type) {
368
+ <%- array_types = [] -%>
369
+ <%- nodes.each_with_index do |node, index| -%>
370
+ case <%= index + 1 %>:
371
+ <%-
372
+ params = []
373
+ params << "nodeId" if Prism::Template::INCLUDE_NODE_ID
374
+ params << "startOffset" << "length"
375
+ params << "buffer.getInt()" if node.needs_serialized_length?
376
+ params << "loadFlags()" if node.flags
377
+ params.concat node.semantic_fields.map { |field|
378
+ case field
379
+ when Prism::Template::NodeField then "#{field.java_cast}loadNode()"
380
+ when Prism::Template::OptionalNodeField then "#{field.java_cast}loadOptionalNode()"
381
+ when Prism::Template::StringField then "loadString()"
382
+ when Prism::Template::NodeListField then
383
+ element_type = field.java_type.sub('[]', '')
384
+ array_types << element_type
385
+ "load#{element_type}s()"
386
+ when Prism::Template::ConstantField then "loadConstant()"
387
+ when Prism::Template::OptionalConstantField then "loadOptionalConstant()"
388
+ when Prism::Template::ConstantListField then "loadConstants()"
389
+ when Prism::Template::LocationField then "loadLocation()"
390
+ when Prism::Template::OptionalLocationField then "loadOptionalLocation()"
391
+ when Prism::Template::UInt8Field then "buffer.get()"
392
+ when Prism::Template::UInt32Field then "loadVarUInt()"
393
+ when Prism::Template::IntegerField then "loadInteger()"
394
+ when Prism::Template::DoubleField then "buffer.getDouble()"
395
+ else raise
396
+ end
397
+ }
398
+ -%>
399
+ return new Nodes.<%= node.name %>(<%= params.join(", ") -%>);
400
+ <%- end -%>
401
+ default:
402
+ throw new Error("Unknown node type: " + type);
403
+ }
404
+ }
405
+ <%- array_types.uniq.each do |type| -%>
406
+
407
+ private static final Nodes.<%= type %>[] EMPTY_<%= type %>_ARRAY = {};
408
+
409
+ private Nodes.<%= type %>[] load<%= type %>s() {
410
+ int length = loadVarUInt();
411
+ if (length == 0) {
412
+ return EMPTY_<%= type %>_ARRAY;
413
+ }
414
+ Nodes.<%= type %>[] nodes = new Nodes.<%= type %>[length];
415
+ for (int i = 0; i < length; i++) {
416
+ <%- if type == 'Node' -%>
417
+ nodes[i] = loadNode();
418
+ <%- else -%>
419
+ nodes[i] = (Nodes.<%= type %>) loadNode();
420
+ <%- end -%>
421
+ }
422
+ return nodes;
423
+ }
424
+ <%- end -%>
425
+
426
+ private void expect(byte value, String error) {
427
+ byte b = buffer.get();
428
+ if (b != value) {
429
+ throw new Error("Deserialization error: " + error + " (expected " + value + " but was " + b + " at position " + buffer.position() + ")");
430
+ }
431
+ }
432
+
433
+ }
434
+ // @formatter:on