herb 0.11.0-x86-linux-gnu → 0.11.1-x86-linux-gnu
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/config.yml +3 -0
- data/ext/herb/nodes.c +34 -17
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/ast/nodes.rb +32 -6
- data/lib/herb/bootstrap.rb +6 -2
- data/lib/herb/dev/runner.rb +6 -1
- data/lib/herb/engine/compiler.rb +47 -11
- data/lib/herb/engine/slots/dynamics_compiler.rb +10 -0
- data/lib/herb/engine/slots/markers.rb +24 -0
- data/lib/herb/engine/slots/state_compiler.rb +1 -2
- data/lib/herb/engine/slots/visitor.rb +39 -28
- data/lib/herb/engine.rb +0 -2
- data/lib/herb/version.rb +1 -1
- data/sig/herb/ast/nodes.rbs +10 -4
- data/sig/herb/bootstrap.rbs +2 -0
- data/sig/herb/dev/runner.rbs +3 -0
- data/sig/herb/engine/compiler.rbs +14 -3
- data/sig/herb/engine/slots/dynamics_compiler.rbs +3 -0
- data/sig/herb/engine/slots/markers.rbs +14 -0
- data/sig/herb/engine/slots/visitor.rbs +17 -13
- data/sig/serialized_ast_nodes.rbs +1 -0
- data/src/analyze/action_view/tag_helper_node_builders.c +6 -3
- data/src/analyze/action_view/tag_helpers.c +76 -20
- data/src/analyze/analyze.c +5 -25
- data/src/analyze/analyze_helpers.c +94 -232
- data/src/analyze/analyzed_ruby.c +2 -0
- data/src/analyze/builders.c +1 -0
- data/src/analyze/control_type.c +17 -7
- data/src/analyze/prism_annotate.c +32 -9
- data/src/ast/ast_nodes.c +3 -1
- data/src/ast/ast_pretty_print.c +5 -1
- data/src/extract.c +204 -143
- data/src/include/analyze/analyze.h +0 -22
- data/src/include/analyze/analyzed_ruby.h +25 -0
- data/src/include/analyze/helpers.h +2 -22
- data/src/include/ast/ast_nodes.h +2 -1
- data/src/include/lexer/lexer.h +1 -0
- data/src/include/prism/herb_prism_node.h +6 -1
- data/src/include/version.h +1 -1
- data/src/lexer.c +32 -0
- data/src/prism/prism_helpers.c +91 -0
- data/templates/ext/herb/nodes.c.erb +1 -1
- data/templates/java/nodes.c.erb +1 -1
- data/templates/javascript/packages/core/src/nodes.ts.erb +21 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +1 -1
- data/templates/rust/src/ast/nodes.rs.erb +1 -4
- data/templates/wasm/nodes.cpp.erb +5 -15
- metadata +1 -1
data/src/prism/prism_helpers.c
CHANGED
|
@@ -244,3 +244,94 @@ location_T* get_then_keyword_location_elsif_wrapped(const char* source, hb_alloc
|
|
|
244
244
|
|
|
245
245
|
return location;
|
|
246
246
|
}
|
|
247
|
+
|
|
248
|
+
static size_t newline_index_for_offset(const pm_newline_list_t* newlines, size_t offset) {
|
|
249
|
+
size_t low = 0;
|
|
250
|
+
size_t high = newlines->size;
|
|
251
|
+
|
|
252
|
+
while (low < high) {
|
|
253
|
+
size_t middle = low + (high - low) / 2;
|
|
254
|
+
|
|
255
|
+
if (newlines->offsets[middle] <= offset) {
|
|
256
|
+
low = middle + 1;
|
|
257
|
+
} else {
|
|
258
|
+
high = middle;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return low > 0 ? low - 1 : 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
void herb_prism_node_serialize(herb_prism_node_T prism_node, pm_buffer_t* buffer) {
|
|
266
|
+
if (!prism_node.node || !prism_node.parser) { return; }
|
|
267
|
+
|
|
268
|
+
pm_parser_t* parser = prism_node.parser;
|
|
269
|
+
|
|
270
|
+
if (prism_node.source_end == 0 || parser->newline_list.size == 0) {
|
|
271
|
+
pm_serialize(parser, prism_node.node, buffer);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const pm_newline_list_t* newlines = &parser->newline_list;
|
|
276
|
+
size_t first_line = newline_index_for_offset(newlines, prism_node.source_start);
|
|
277
|
+
size_t last_line = newline_index_for_offset(newlines, prism_node.source_end);
|
|
278
|
+
size_t line_count = last_line - first_line + 1;
|
|
279
|
+
|
|
280
|
+
if (last_line + 1 < newlines->size) { line_count++; }
|
|
281
|
+
|
|
282
|
+
pm_parser_t view = *parser;
|
|
283
|
+
|
|
284
|
+
view.newline_list.offsets = newlines->offsets + first_line;
|
|
285
|
+
view.newline_list.size = line_count;
|
|
286
|
+
view.newline_list.capacity = line_count;
|
|
287
|
+
view.start_line = parser->start_line + (int32_t) first_line;
|
|
288
|
+
|
|
289
|
+
memset(&view.magic_comment_list, 0, sizeof(pm_list_t));
|
|
290
|
+
memset(&view.error_list, 0, sizeof(pm_list_t));
|
|
291
|
+
memset(&view.warning_list, 0, sizeof(pm_list_t));
|
|
292
|
+
memset(&view.comment_list, 0, sizeof(pm_list_t));
|
|
293
|
+
|
|
294
|
+
size_t comment_count = 0;
|
|
295
|
+
|
|
296
|
+
for (pm_list_node_t* entry = parser->comment_list.head; entry; entry = entry->next) {
|
|
297
|
+
pm_comment_t* comment = (pm_comment_t*) entry;
|
|
298
|
+
size_t start = (size_t) (comment->location.start - parser->start);
|
|
299
|
+
|
|
300
|
+
if (start >= prism_node.source_start && start < prism_node.source_end) { comment_count++; }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
pm_comment_t* comments = NULL;
|
|
304
|
+
|
|
305
|
+
if (comment_count > 0) {
|
|
306
|
+
comments = malloc(comment_count * sizeof(pm_comment_t));
|
|
307
|
+
|
|
308
|
+
if (!comments) {
|
|
309
|
+
pm_serialize(parser, prism_node.node, buffer);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
size_t index = 0;
|
|
314
|
+
|
|
315
|
+
for (pm_list_node_t* entry = parser->comment_list.head; entry; entry = entry->next) {
|
|
316
|
+
pm_comment_t* comment = (pm_comment_t*) entry;
|
|
317
|
+
size_t start = (size_t) (comment->location.start - parser->start);
|
|
318
|
+
|
|
319
|
+
if (start < prism_node.source_start || start >= prism_node.source_end) { continue; }
|
|
320
|
+
|
|
321
|
+
comments[index] = *comment;
|
|
322
|
+
comments[index].node.next = NULL;
|
|
323
|
+
|
|
324
|
+
if (index > 0) { comments[index - 1].node.next = &comments[index].node; }
|
|
325
|
+
|
|
326
|
+
index++;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
view.comment_list.size = comment_count;
|
|
330
|
+
view.comment_list.head = &comments[0].node;
|
|
331
|
+
view.comment_list.tail = &comments[comment_count - 1].node;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
pm_serialize(&view, prism_node.node, buffer);
|
|
335
|
+
|
|
336
|
+
free(comments);
|
|
337
|
+
}
|
|
@@ -70,7 +70,7 @@ static VALUE rb_<%= node.human %>_from_c_struct(<%= node.struct_type %>* <%= nod
|
|
|
70
70
|
VALUE <%= node.human %>_<%= field.name %>;
|
|
71
71
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
72
72
|
pm_buffer_t pm_buffer = { 0 };
|
|
73
|
-
|
|
73
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &pm_buffer);
|
|
74
74
|
|
|
75
75
|
if (pm_buffer.length > 0) {
|
|
76
76
|
<%= node.human %>_<%= field.name %> = rb_str_new(pm_buffer.value, pm_buffer.length);
|
data/templates/java/nodes.c.erb
CHANGED
|
@@ -50,7 +50,7 @@ jobject <%= node.name %>FromCStruct(JNIEnv* env, <%= node.struct_type %>* <%= no
|
|
|
50
50
|
jbyteArray <%= field.name %>;
|
|
51
51
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
52
52
|
pm_buffer_t pm_buffer = { 0 };
|
|
53
|
-
|
|
53
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &pm_buffer);
|
|
54
54
|
if (pm_buffer.length > 0) {
|
|
55
55
|
<%= field.name %> = (*env)->NewByteArray(env, (jsize)pm_buffer.length);
|
|
56
56
|
(*env)->SetByteArrayRegion(env, <%= field.name %>, 0, (jsize)pm_buffer.length, (const jbyte*)pm_buffer.value);
|
|
@@ -13,6 +13,26 @@ import type { LocateResult } from "./locate.js"
|
|
|
13
13
|
|
|
14
14
|
export type SerializedNodeType = string
|
|
15
15
|
|
|
16
|
+
type PrismNodeCacheEntry = {
|
|
17
|
+
bytes: Uint8Array
|
|
18
|
+
source: string
|
|
19
|
+
node: PrismNode | null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const prismNodeCache = new WeakMap<Node, PrismNodeCacheEntry>()
|
|
23
|
+
|
|
24
|
+
function cachedPrismNode(owner: Node, bytes: Uint8Array, source: string): PrismNode | null {
|
|
25
|
+
const cached = prismNodeCache.get(owner)
|
|
26
|
+
|
|
27
|
+
if (cached && cached.bytes === bytes && cached.source === source) return cached.node
|
|
28
|
+
|
|
29
|
+
const node = deserializePrismNode(bytes, source)
|
|
30
|
+
|
|
31
|
+
prismNodeCache.set(owner, { bytes, source, node })
|
|
32
|
+
|
|
33
|
+
return node
|
|
34
|
+
}
|
|
35
|
+
|
|
16
36
|
export interface SerializedNode {
|
|
17
37
|
type: SerializedNodeType
|
|
18
38
|
location: SerializedLocation
|
|
@@ -388,7 +408,7 @@ export class <%= node.name %> extends Node {
|
|
|
388
408
|
<%- prism_field = node.fields.find { |f| f.is_a?(Herb::Template::PrismSerializedField) || f.is_a?(Herb::Template::PrismNodeField) } -%>
|
|
389
409
|
get prismNode(): PrismNode | null {
|
|
390
410
|
if (!this.<%= prism_field.name %> || !this.source) return null;
|
|
391
|
-
return
|
|
411
|
+
return cachedPrismNode(this, this.<%= prism_field.name %>, this.source);
|
|
392
412
|
}
|
|
393
413
|
<%- end -%>
|
|
394
414
|
|
|
@@ -90,7 +90,7 @@ napi_value <%= node.human %>NodeFromCStruct(napi_env env, <%= node.struct_type %
|
|
|
90
90
|
napi_value <%= field.name %>;
|
|
91
91
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
92
92
|
pm_buffer_t pm_buffer = { 0 };
|
|
93
|
-
|
|
93
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &pm_buffer);
|
|
94
94
|
|
|
95
95
|
if (pm_buffer.length > 0) {
|
|
96
96
|
void* buffer_data;
|
|
@@ -233,10 +233,7 @@ pub(crate) unsafe fn convert_node(node_pointer: *const c_void, source: &std::syn
|
|
|
233
233
|
Some(std::slice::from_raw_parts((*c_node_pointer).<%= field.name %>.data, (*c_node_pointer).<%= field.name %>.length).to_vec())
|
|
234
234
|
},
|
|
235
235
|
<%- when Herb::Template::PrismNodeField -%>
|
|
236
|
-
<%= field.name %>: crate::prism::serialize(
|
|
237
|
-
(*c_node_pointer).<%= field.name %>.node,
|
|
238
|
-
(*c_node_pointer).<%= field.name %>.parser,
|
|
239
|
-
),
|
|
236
|
+
<%= field.name %>: crate::prism::serialize((*c_node_pointer).<%= field.name %>),
|
|
240
237
|
source: Some(std::sync::Arc::clone(source)),
|
|
241
238
|
#[cfg(feature = "prism")]
|
|
242
239
|
prism_cache: std::sync::OnceLock::new(),
|
|
@@ -47,29 +47,19 @@ val <%= node.name %>FromCStruct(<%= node.struct_type %>* <%= node.human %>, cons
|
|
|
47
47
|
}
|
|
48
48
|
<%- when Herb::Template::PrismSerializedField -%>
|
|
49
49
|
if (<%= node.human %>-><%= field.name %>.data != NULL && <%= node.human %>-><%= field.name %>.length > 0) {
|
|
50
|
-
val
|
|
51
|
-
|
|
52
|
-
for (size_t i = 0; i < <%= node.human %>-><%= field.name %>.length; i++) {
|
|
53
|
-
jsArray.call<void>("push", (int)<%= node.human %>-><%= field.name %>.data[i]);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
result.set("<%= field.name %>", jsArray);
|
|
50
|
+
val view = val(typed_memory_view(<%= node.human %>-><%= field.name %>.length, (const uint8_t*) <%= node.human %>-><%= field.name %>.data));
|
|
51
|
+
result.set("<%= field.name %>", val::global("Uint8Array").new_(view));
|
|
57
52
|
} else {
|
|
58
53
|
result.set("<%= field.name %>", val::null());
|
|
59
54
|
}
|
|
60
55
|
<%- when Herb::Template::PrismNodeField -%>
|
|
61
56
|
if (<%= node.human %>-><%= field.name %>.node != NULL && <%= node.human %>-><%= field.name %>.parser != NULL) {
|
|
62
57
|
pm_buffer_t pm_buffer = { 0 };
|
|
63
|
-
|
|
58
|
+
herb_prism_node_serialize(<%= node.human %>-><%= field.name %>, &pm_buffer);
|
|
64
59
|
|
|
65
60
|
if (pm_buffer.length > 0) {
|
|
66
|
-
val
|
|
67
|
-
|
|
68
|
-
for (size_t i = 0; i < pm_buffer.length; i++) {
|
|
69
|
-
jsArray.call<void>("push", (int)((uint8_t*)pm_buffer.value)[i]);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
result.set("<%= field.name %>", jsArray);
|
|
61
|
+
val view = val(typed_memory_view(pm_buffer.length, (const uint8_t*) pm_buffer.value));
|
|
62
|
+
result.set("<%= field.name %>", val::global("Uint8Array").new_(view));
|
|
73
63
|
} else {
|
|
74
64
|
result.set("<%= field.name %>", val::null());
|
|
75
65
|
}
|