herb 0.7.2-aarch64-linux-musl → 0.7.3-aarch64-linux-musl

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 (130) 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/extconf.rb +2 -1
  7. data/ext/herb/nodes.c +1 -1
  8. data/herb.gemspec +3 -0
  9. data/lib/herb/3.0/herb.so +0 -0
  10. data/lib/herb/3.1/herb.so +0 -0
  11. data/lib/herb/3.2/herb.so +0 -0
  12. data/lib/herb/3.3/herb.so +0 -0
  13. data/lib/herb/3.4/herb.so +0 -0
  14. data/lib/herb/version.rb +1 -1
  15. data/src/analyze.c +5 -9
  16. data/src/analyze_helpers.c +17 -6
  17. data/src/include/pretty_print.h +1 -1
  18. data/src/include/version.h +1 -1
  19. data/src/parser.c +1 -0
  20. data/src/pretty_print.c +1 -1
  21. data/templates/ext/herb/error_helpers.c.erb +85 -0
  22. data/templates/ext/herb/error_helpers.h.erb +12 -0
  23. data/templates/ext/herb/nodes.c.erb +90 -0
  24. data/templates/ext/herb/nodes.h.erb +9 -0
  25. data/templates/javascript/packages/core/src/errors.ts.erb +193 -0
  26. data/templates/javascript/packages/core/src/node-type-guards.ts.erb +325 -0
  27. data/templates/javascript/packages/core/src/nodes.ts.erb +414 -0
  28. data/templates/javascript/packages/core/src/visitor.ts.erb +29 -0
  29. data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +113 -0
  30. data/templates/javascript/packages/node/extension/error_helpers.h.erb +17 -0
  31. data/templates/javascript/packages/node/extension/nodes.cpp.erb +111 -0
  32. data/templates/javascript/packages/node/extension/nodes.h.erb +17 -0
  33. data/templates/lib/herb/ast/nodes.rb.erb +117 -0
  34. data/templates/lib/herb/errors.rb.erb +106 -0
  35. data/templates/lib/herb/visitor.rb.erb +28 -0
  36. data/templates/sig/serialized_ast_errors.rbs.erb +10 -0
  37. data/templates/sig/serialized_ast_nodes.rbs.erb +10 -0
  38. data/templates/src/ast_nodes.c.erb +145 -0
  39. data/templates/src/ast_pretty_print.c.erb +97 -0
  40. data/templates/src/errors.c.erb +245 -0
  41. data/templates/src/include/ast_nodes.h.erb +46 -0
  42. data/templates/src/include/ast_pretty_print.h.erb +14 -0
  43. data/templates/src/include/errors.h.erb +58 -0
  44. data/templates/src/visitor.c.erb +47 -0
  45. data/templates/template.rb +406 -0
  46. data/templates/wasm/error_helpers.cpp.erb +93 -0
  47. data/templates/wasm/error_helpers.h.erb +15 -0
  48. data/templates/wasm/nodes.cpp.erb +79 -0
  49. data/templates/wasm/nodes.h.erb +15 -0
  50. data/vendor/prism/Rakefile +75 -0
  51. data/vendor/prism/config.yml +4713 -0
  52. data/vendor/prism/include/prism/ast.h +8190 -0
  53. data/vendor/prism/include/prism/defines.h +260 -0
  54. data/vendor/prism/include/prism/diagnostic.h +455 -0
  55. data/vendor/prism/include/prism/encoding.h +283 -0
  56. data/vendor/prism/include/prism/node.h +129 -0
  57. data/vendor/prism/include/prism/options.h +482 -0
  58. data/vendor/prism/include/prism/pack.h +163 -0
  59. data/vendor/prism/include/prism/parser.h +933 -0
  60. data/vendor/prism/include/prism/prettyprint.h +34 -0
  61. data/vendor/prism/include/prism/regexp.h +43 -0
  62. data/vendor/prism/include/prism/static_literals.h +121 -0
  63. data/vendor/prism/include/prism/util/pm_buffer.h +236 -0
  64. data/vendor/prism/include/prism/util/pm_char.h +204 -0
  65. data/vendor/prism/include/prism/util/pm_constant_pool.h +218 -0
  66. data/vendor/prism/include/prism/util/pm_integer.h +130 -0
  67. data/vendor/prism/include/prism/util/pm_list.h +103 -0
  68. data/vendor/prism/include/prism/util/pm_memchr.h +29 -0
  69. data/vendor/prism/include/prism/util/pm_newline_list.h +113 -0
  70. data/vendor/prism/include/prism/util/pm_string.h +200 -0
  71. data/vendor/prism/include/prism/util/pm_strncasecmp.h +32 -0
  72. data/vendor/prism/include/prism/util/pm_strpbrk.h +46 -0
  73. data/vendor/prism/include/prism/version.h +29 -0
  74. data/vendor/prism/include/prism.h +408 -0
  75. data/vendor/prism/src/diagnostic.c +848 -0
  76. data/vendor/prism/src/encoding.c +5235 -0
  77. data/vendor/prism/src/node.c +8676 -0
  78. data/vendor/prism/src/options.c +328 -0
  79. data/vendor/prism/src/pack.c +509 -0
  80. data/vendor/prism/src/prettyprint.c +8941 -0
  81. data/vendor/prism/src/prism.c +23302 -0
  82. data/vendor/prism/src/regexp.c +790 -0
  83. data/vendor/prism/src/serialize.c +2268 -0
  84. data/vendor/prism/src/static_literals.c +617 -0
  85. data/vendor/prism/src/token_type.c +703 -0
  86. data/vendor/prism/src/util/pm_buffer.c +357 -0
  87. data/vendor/prism/src/util/pm_char.c +318 -0
  88. data/vendor/prism/src/util/pm_constant_pool.c +342 -0
  89. data/vendor/prism/src/util/pm_integer.c +670 -0
  90. data/vendor/prism/src/util/pm_list.c +49 -0
  91. data/vendor/prism/src/util/pm_memchr.c +35 -0
  92. data/vendor/prism/src/util/pm_newline_list.c +125 -0
  93. data/vendor/prism/src/util/pm_string.c +383 -0
  94. data/vendor/prism/src/util/pm_strncasecmp.c +36 -0
  95. data/vendor/prism/src/util/pm_strpbrk.c +206 -0
  96. data/vendor/prism/templates/ext/prism/api_node.c.erb +282 -0
  97. data/vendor/prism/templates/include/prism/ast.h.erb +226 -0
  98. data/vendor/prism/templates/include/prism/diagnostic.h.erb +130 -0
  99. data/vendor/prism/templates/java/org/prism/AbstractNodeVisitor.java.erb +22 -0
  100. data/vendor/prism/templates/java/org/prism/Loader.java.erb +434 -0
  101. data/vendor/prism/templates/java/org/prism/Nodes.java.erb +403 -0
  102. data/vendor/prism/templates/javascript/src/deserialize.js.erb +448 -0
  103. data/vendor/prism/templates/javascript/src/nodes.js.erb +197 -0
  104. data/vendor/prism/templates/javascript/src/visitor.js.erb +78 -0
  105. data/vendor/prism/templates/lib/prism/compiler.rb.erb +43 -0
  106. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +103 -0
  107. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +189 -0
  108. data/vendor/prism/templates/lib/prism/dsl.rb.erb +133 -0
  109. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +131 -0
  110. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +19 -0
  111. data/vendor/prism/templates/lib/prism/node.rb.erb +515 -0
  112. data/vendor/prism/templates/lib/prism/reflection.rb.erb +136 -0
  113. data/vendor/prism/templates/lib/prism/serialize.rb.erb +602 -0
  114. data/vendor/prism/templates/lib/prism/visitor.rb.erb +55 -0
  115. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +68 -0
  116. data/vendor/prism/templates/rbi/prism/node.rbi.erb +164 -0
  117. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +18 -0
  118. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +45 -0
  119. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +31 -0
  120. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +7 -0
  121. data/vendor/prism/templates/sig/prism/node.rbs.erb +132 -0
  122. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +17 -0
  123. data/vendor/prism/templates/sig/prism.rbs.erb +89 -0
  124. data/vendor/prism/templates/src/diagnostic.c.erb +523 -0
  125. data/vendor/prism/templates/src/node.c.erb +333 -0
  126. data/vendor/prism/templates/src/prettyprint.c.erb +166 -0
  127. data/vendor/prism/templates/src/serialize.c.erb +406 -0
  128. data/vendor/prism/templates/src/token_type.c.erb +369 -0
  129. data/vendor/prism/templates/template.rb +689 -0
  130. metadata +112 -2
@@ -0,0 +1,206 @@
1
+ #include "prism/util/pm_strpbrk.h"
2
+
3
+ /**
4
+ * Add an invalid multibyte character error to the parser.
5
+ */
6
+ static inline void
7
+ pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
8
+ pm_diagnostic_list_append_format(&parser->error_list, start, end, PM_ERR_INVALID_MULTIBYTE_CHARACTER, *start);
9
+ }
10
+
11
+ /**
12
+ * Set the explicit encoding for the parser to the current encoding.
13
+ */
14
+ static inline void
15
+ pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, const uint8_t *source, size_t width) {
16
+ if (parser->explicit_encoding != NULL) {
17
+ if (parser->explicit_encoding == parser->encoding) {
18
+ // Okay, we already locked to this encoding.
19
+ } else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) {
20
+ // Not okay, we already found a Unicode escape sequence and this
21
+ // conflicts.
22
+ pm_diagnostic_list_append_format(&parser->error_list, source, source + width, PM_ERR_MIXED_ENCODING, parser->encoding->name);
23
+ } else {
24
+ // Should not be anything else.
25
+ assert(false && "unreachable");
26
+ }
27
+ }
28
+
29
+ parser->explicit_encoding = parser->encoding;
30
+ }
31
+
32
+ /**
33
+ * This is the default path.
34
+ */
35
+ static inline const uint8_t *
36
+ pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
37
+ size_t index = 0;
38
+
39
+ while (index < maximum) {
40
+ if (strchr((const char *) charset, source[index]) != NULL) {
41
+ return source + index;
42
+ }
43
+
44
+ if (source[index] < 0x80) {
45
+ index++;
46
+ } else {
47
+ size_t width = pm_encoding_utf_8_char_width(source + index, (ptrdiff_t) (maximum - index));
48
+
49
+ if (width > 0) {
50
+ index += width;
51
+ } else if (!validate) {
52
+ index++;
53
+ } else {
54
+ // At this point we know we have an invalid multibyte character.
55
+ // We'll walk forward as far as we can until we find the next
56
+ // valid character so that we don't spam the user with a ton of
57
+ // the same kind of error.
58
+ const size_t start = index;
59
+
60
+ do {
61
+ index++;
62
+ } while (index < maximum && pm_encoding_utf_8_char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
63
+
64
+ pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
65
+ }
66
+ }
67
+ }
68
+
69
+ return NULL;
70
+ }
71
+
72
+ /**
73
+ * This is the path when the encoding is ASCII-8BIT.
74
+ */
75
+ static inline const uint8_t *
76
+ pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
77
+ size_t index = 0;
78
+
79
+ while (index < maximum) {
80
+ if (strchr((const char *) charset, source[index]) != NULL) {
81
+ return source + index;
82
+ }
83
+
84
+ if (validate && source[index] >= 0x80) pm_strpbrk_explicit_encoding_set(parser, source, 1);
85
+ index++;
86
+ }
87
+
88
+ return NULL;
89
+ }
90
+
91
+ /**
92
+ * This is the slow path that does care about the encoding.
93
+ */
94
+ static inline const uint8_t *
95
+ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
96
+ size_t index = 0;
97
+ const pm_encoding_t *encoding = parser->encoding;
98
+
99
+ while (index < maximum) {
100
+ if (strchr((const char *) charset, source[index]) != NULL) {
101
+ return source + index;
102
+ }
103
+
104
+ if (source[index] < 0x80) {
105
+ index++;
106
+ } else {
107
+ size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
108
+ if (validate) pm_strpbrk_explicit_encoding_set(parser, source, width);
109
+
110
+ if (width > 0) {
111
+ index += width;
112
+ } else if (!validate) {
113
+ index++;
114
+ } else {
115
+ // At this point we know we have an invalid multibyte character.
116
+ // We'll walk forward as far as we can until we find the next
117
+ // valid character so that we don't spam the user with a ton of
118
+ // the same kind of error.
119
+ const size_t start = index;
120
+
121
+ do {
122
+ index++;
123
+ } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
124
+
125
+ pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
126
+ }
127
+ }
128
+ }
129
+
130
+ return NULL;
131
+ }
132
+
133
+ /**
134
+ * This is the fast path that does not care about the encoding because we know
135
+ * the encoding only supports single-byte characters.
136
+ */
137
+ static inline const uint8_t *
138
+ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) {
139
+ size_t index = 0;
140
+ const pm_encoding_t *encoding = parser->encoding;
141
+
142
+ while (index < maximum) {
143
+ if (strchr((const char *) charset, source[index]) != NULL) {
144
+ return source + index;
145
+ }
146
+
147
+ if (source[index] < 0x80 || !validate) {
148
+ index++;
149
+ } else {
150
+ size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index));
151
+ pm_strpbrk_explicit_encoding_set(parser, source, width);
152
+
153
+ if (width > 0) {
154
+ index += width;
155
+ } else {
156
+ // At this point we know we have an invalid multibyte character.
157
+ // We'll walk forward as far as we can until we find the next
158
+ // valid character so that we don't spam the user with a ton of
159
+ // the same kind of error.
160
+ const size_t start = index;
161
+
162
+ do {
163
+ index++;
164
+ } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0);
165
+
166
+ pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index);
167
+ }
168
+ }
169
+ }
170
+
171
+ return NULL;
172
+ }
173
+
174
+ /**
175
+ * Here we have rolled our own version of strpbrk. The standard library strpbrk
176
+ * has undefined behavior when the source string is not null-terminated. We want
177
+ * to support strings that are not null-terminated because pm_parse does not
178
+ * have the contract that the string is null-terminated. (This is desirable
179
+ * because it means the extension can call pm_parse with the result of a call to
180
+ * mmap).
181
+ *
182
+ * The standard library strpbrk also does not support passing a maximum length
183
+ * to search. We want to support this for the reason mentioned above, but we
184
+ * also don't want it to stop on null bytes. Ruby actually allows null bytes
185
+ * within strings, comments, regular expressions, etc. So we need to be able to
186
+ * skip past them.
187
+ *
188
+ * Finally, we want to support encodings wherein the charset could contain
189
+ * characters that are trailing bytes of multi-byte characters. For example, in
190
+ * Shift_JIS, the backslash character can be a trailing byte. In that case we
191
+ * need to take a slower path and iterate one multi-byte character at a time.
192
+ */
193
+ const uint8_t *
194
+ pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, ptrdiff_t length, bool validate) {
195
+ if (length <= 0) {
196
+ return NULL;
197
+ } else if (!parser->encoding_changed) {
198
+ return pm_strpbrk_utf8(parser, source, charset, (size_t) length, validate);
199
+ } else if (parser->encoding == PM_ENCODING_ASCII_8BIT_ENTRY) {
200
+ return pm_strpbrk_ascii_8bit(parser, source, charset, (size_t) length, validate);
201
+ } else if (parser->encoding->multibyte) {
202
+ return pm_strpbrk_multi_byte(parser, source, charset, (size_t) length, validate);
203
+ } else {
204
+ return pm_strpbrk_single_byte(parser, source, charset, (size_t) length, validate);
205
+ }
206
+ }
@@ -0,0 +1,282 @@
1
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
2
+ #include "prism/extension.h"
3
+
4
+ extern VALUE rb_cPrism;
5
+ extern VALUE rb_cPrismNode;
6
+ extern VALUE rb_cPrismSource;
7
+ extern VALUE rb_cPrismToken;
8
+ extern VALUE rb_cPrismLocation;
9
+
10
+ <%- nodes.each do |node| -%>
11
+ static VALUE rb_cPrism<%= node.name %>;
12
+ <%- end -%>
13
+
14
+ static VALUE
15
+ pm_location_new(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end, VALUE source, bool freeze) {
16
+ if (freeze) {
17
+ VALUE location_argv[] = {
18
+ source,
19
+ LONG2FIX(start - parser->start),
20
+ LONG2FIX(end - start)
21
+ };
22
+
23
+ return rb_obj_freeze(rb_class_new_instance(3, location_argv, rb_cPrismLocation));
24
+ } else {
25
+ uint64_t value = ((((uint64_t) (start - parser->start)) << 32) | ((uint32_t) (end - start)));
26
+ return ULL2NUM(value);
27
+ }
28
+ }
29
+
30
+ VALUE
31
+ pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze) {
32
+ ID type = rb_intern(pm_token_type_name(token->type));
33
+ VALUE location = pm_location_new(parser, token->start, token->end, source, freeze);
34
+
35
+ VALUE slice = rb_enc_str_new((const char *) token->start, token->end - token->start, encoding);
36
+ if (freeze) rb_obj_freeze(slice);
37
+
38
+ VALUE argv[] = { source, ID2SYM(type), slice, location };
39
+ VALUE value = rb_class_new_instance(4, argv, rb_cPrismToken);
40
+ if (freeze) rb_obj_freeze(value);
41
+
42
+ return value;
43
+ }
44
+
45
+ static VALUE
46
+ pm_string_new(const pm_string_t *string, rb_encoding *encoding) {
47
+ return rb_obj_freeze(rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding));
48
+ }
49
+
50
+ VALUE
51
+ pm_integer_new(const pm_integer_t *integer) {
52
+ VALUE result;
53
+ if (integer->values == NULL) {
54
+ result = UINT2NUM(integer->value);
55
+ } else {
56
+ VALUE string = rb_str_new(NULL, integer->length * 8);
57
+ unsigned char *bytes = (unsigned char *) RSTRING_PTR(string);
58
+
59
+ size_t offset = integer->length * 8;
60
+ for (size_t value_index = 0; value_index < integer->length; value_index++) {
61
+ uint32_t value = integer->values[value_index];
62
+
63
+ for (int index = 0; index < 8; index++) {
64
+ int byte = (value >> (4 * index)) & 0xf;
65
+ bytes[--offset] = byte < 10 ? byte + '0' : byte - 10 + 'a';
66
+ }
67
+ }
68
+
69
+ result = rb_funcall(string, rb_intern("to_i"), 1, UINT2NUM(16));
70
+ }
71
+
72
+ if (integer->negative) {
73
+ result = rb_funcall(result, rb_intern("-@"), 0);
74
+ }
75
+
76
+ return result;
77
+ }
78
+
79
+ // Create a Prism::Source object from the given parser, after pm_parse() was called.
80
+ VALUE
81
+ pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) {
82
+ VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding);
83
+
84
+ VALUE offsets = rb_ary_new_capa(parser->newline_list.size);
85
+ for (size_t index = 0; index < parser->newline_list.size; index++) {
86
+ rb_ary_push(offsets, ULONG2NUM(parser->newline_list.offsets[index]));
87
+ }
88
+
89
+ if (freeze) {
90
+ rb_obj_freeze(source_string);
91
+ rb_obj_freeze(offsets);
92
+ }
93
+
94
+ VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(parser->start_line), offsets);
95
+ if (freeze) rb_obj_freeze(source);
96
+
97
+ return source;
98
+ }
99
+
100
+ typedef struct pm_node_stack_node {
101
+ struct pm_node_stack_node *prev;
102
+ const pm_node_t *visit;
103
+ bool visited;
104
+ } pm_node_stack_node_t;
105
+
106
+ static void
107
+ pm_node_stack_push(pm_node_stack_node_t **stack, const pm_node_t *visit) {
108
+ pm_node_stack_node_t *node = xmalloc(sizeof(pm_node_stack_node_t));
109
+ node->prev = *stack;
110
+ node->visit = visit;
111
+ node->visited = false;
112
+ *stack = node;
113
+ }
114
+
115
+ static const pm_node_t *
116
+ pm_node_stack_pop(pm_node_stack_node_t **stack) {
117
+ pm_node_stack_node_t *current = *stack;
118
+ const pm_node_t *visit = current->visit;
119
+
120
+ *stack = current->prev;
121
+ xfree(current);
122
+
123
+ return visit;
124
+ }
125
+
126
+ VALUE
127
+ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) {
128
+ VALUE constants = rb_ary_new_capa(parser->constant_pool.size);
129
+
130
+ for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
131
+ pm_constant_t *constant = &parser->constant_pool.constants[index];
132
+ int state = 0;
133
+
134
+ VALUE string = rb_enc_str_new((const char *) constant->start, constant->length, encoding);
135
+ VALUE value = rb_protect(rb_str_intern, string, &state);
136
+
137
+ if (state != 0) {
138
+ value = ID2SYM(rb_intern_const("?"));
139
+ rb_set_errinfo(Qnil);
140
+ }
141
+
142
+ rb_ary_push(constants, value);
143
+ }
144
+
145
+ pm_node_stack_node_t *node_stack = NULL;
146
+ pm_node_stack_push(&node_stack, node);
147
+ VALUE value_stack = rb_ary_new();
148
+
149
+ while (node_stack != NULL) {
150
+ if (!node_stack->visited) {
151
+ if (node_stack->visit == NULL) {
152
+ pm_node_stack_pop(&node_stack);
153
+ rb_ary_push(value_stack, Qnil);
154
+ continue;
155
+ }
156
+
157
+ const pm_node_t *node = node_stack->visit;
158
+ node_stack->visited = true;
159
+
160
+ switch (PM_NODE_TYPE(node)) {
161
+ <%- nodes.each do |node| -%>
162
+ <%- if node.fields.any? { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%>
163
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
164
+ case <%= node.type %>: {
165
+ pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
166
+ <%- node.fields.each do |field| -%>
167
+ <%- case field -%>
168
+ <%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
169
+ pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>);
170
+ <%- when Prism::Template::NodeListField -%>
171
+ for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
172
+ pm_node_stack_push(&node_stack, (pm_node_t *) cast-><%= field.name %>.nodes[index]);
173
+ }
174
+ <%- end -%>
175
+ <%- end -%>
176
+ break;
177
+ }
178
+ <%- end -%>
179
+ <%- end -%>
180
+ default:
181
+ break;
182
+ }
183
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
184
+ } else {
185
+ const pm_node_t *node = pm_node_stack_pop(&node_stack);
186
+
187
+ switch (PM_NODE_TYPE(node)) {
188
+ <%- nodes.each do |node| -%>
189
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
190
+ case <%= node.type %>: {
191
+ <%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField].include?(field.class) } -%>
192
+ pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
193
+ <%- end -%>
194
+ VALUE argv[<%= node.fields.length + 4 %>];
195
+
196
+ // source
197
+ argv[0] = source;
198
+
199
+ // node_id
200
+ argv[1] = ULONG2NUM(node->node_id);
201
+
202
+ // location
203
+ argv[2] = pm_location_new(parser, node->location.start, node->location.end, source, freeze);
204
+
205
+ // flags
206
+ argv[3] = ULONG2NUM(node->flags);
207
+ <%- node.fields.each.with_index(4) do |field, index| -%>
208
+
209
+ // <%= field.name %>
210
+ <%- case field -%>
211
+ <%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
212
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
213
+ argv[<%= index %>] = rb_ary_pop(value_stack);
214
+ <%- when Prism::Template::NodeListField -%>
215
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
216
+ argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
217
+ for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
218
+ rb_ary_push(argv[<%= index %>], rb_ary_pop(value_stack));
219
+ }
220
+ if (freeze) rb_obj_freeze(argv[<%= index %>]);
221
+ <%- when Prism::Template::StringField -%>
222
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
223
+ argv[<%= index %>] = pm_string_new(&cast-><%= field.name %>, encoding);
224
+ <%- when Prism::Template::ConstantField -%>
225
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
226
+ assert(cast-><%= field.name %> != 0);
227
+ argv[<%= index %>] = RARRAY_AREF(constants, cast-><%= field.name %> - 1);
228
+ <%- when Prism::Template::OptionalConstantField -%>
229
+ argv[<%= index %>] = cast-><%= field.name %> == 0 ? Qnil : RARRAY_AREF(constants, cast-><%= field.name %> - 1);
230
+ <%- when Prism::Template::ConstantListField -%>
231
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
232
+ argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
233
+ for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
234
+ assert(cast-><%= field.name %>.ids[index] != 0);
235
+ rb_ary_push(argv[<%= index %>], RARRAY_AREF(constants, cast-><%= field.name %>.ids[index] - 1));
236
+ }
237
+ if (freeze) rb_obj_freeze(argv[<%= index %>]);
238
+ <%- when Prism::Template::LocationField -%>
239
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
240
+ argv[<%= index %>] = pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
241
+ <%- when Prism::Template::OptionalLocationField -%>
242
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
243
+ argv[<%= index %>] = cast-><%= field.name %>.start == NULL ? Qnil : pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
244
+ <%- when Prism::Template::UInt8Field -%>
245
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
246
+ argv[<%= index %>] = UINT2NUM(cast-><%= field.name %>);
247
+ <%- when Prism::Template::UInt32Field -%>
248
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
249
+ argv[<%= index %>] = ULONG2NUM(cast-><%= field.name %>);
250
+ <%- when Prism::Template::IntegerField -%>
251
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
252
+ argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>);
253
+ <%- when Prism::Template::DoubleField -%>
254
+ #line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
255
+ argv[<%= index %>] = DBL2NUM(cast-><%= field.name %>);
256
+ <%- else -%>
257
+ <%- raise -%>
258
+ <%- end -%>
259
+ <%- end -%>
260
+
261
+ VALUE value = rb_class_new_instance(<%= node.fields.length + 4 %>, argv, rb_cPrism<%= node.name %>);
262
+ if (freeze) rb_obj_freeze(value);
263
+
264
+ rb_ary_push(value_stack, value);
265
+ break;
266
+ }
267
+ <%- end -%>
268
+ default:
269
+ rb_raise(rb_eRuntimeError, "unknown node type: %d", PM_NODE_TYPE(node));
270
+ }
271
+ }
272
+ }
273
+
274
+ return rb_ary_pop(value_stack);
275
+ }
276
+
277
+ void
278
+ Init_prism_api_node(void) {
279
+ <%- nodes.each do |node| -%>
280
+ rb_cPrism<%= node.name %> = rb_define_class_under(rb_cPrism, "<%= node.name %>", rb_cPrismNode);
281
+ <%- end -%>
282
+ }