tiny.smg.tree.runtime.node
Defined in tree.runtime.
API (16)
Actions
Public operations.
Node.emptyNode.initchildchildByFieldchildCountendByteendLinefieldNameForChildisNamedkindnamedChildnamedChildCountslicestartBytestartLine
Types and contracts
Public types and contracts.
Source
Source: tools/smg/src/tree/runtime/node.zig
zig
const std = @import("std");const runtime = @import("root.zig");const abi = runtime.abi;const subtree = runtime.subtree;pub const Node = struct { tree: ?*const subtree.Tree, value: ?*const subtree.Subtree, alias_symbol: abi.Symbol = 0, pub fn init(tree: *const subtree.Tree, value: *const subtree.Subtree) Node { return .{ .tree = tree, .value = value }; } pub fn empty() Node { return .{ .tree = null, .value = null }; }};pub fn kind(node: Node) []const u8 { const tree = node.tree orelse return ""; const value = node.value orelse return ""; const symbol = if (node.alias_symbol == 0) value.symbol else node.alias_symbol; return tree.language.symbolName(symbol);}pub fn childCount(node: Node) u32 { return relevantCount(node, true);}pub fn namedChildCount(node: Node) u32 { return relevantCount(node, false);}pub fn child(node: Node, index: u32) Node { return childAt(node, index, true);}pub fn namedChild(node: Node, index: u32) Node { return childAt(node, index, false);}pub fn childByField(node: Node, comptime field: []const u8) ?Node { const tree = node.tree orelse return null; const field_id = tree.language.fieldId(field); if (field_id == 0) return null; return childByFieldId(node, field_id);}pub fn fieldNameForChild(initial: Node, requested: u32) ?[]const u8 { var node = initial; var target = requested; var inherited: ?[]const u8 = null; while (true) { const tree = node.tree orelse return null; const value = node.value orelse return null; var visible_index: u32 = 0; var structural_index: u32 = 0; var descend: ?Node = null; for (value.children) |child_value| { const child_structural_index = structural_index; const alias_symbol = aliasFor(node, child_value, structural_index); if (!child_value.extra) structural_index += 1; const direct = Node{ .tree = tree, .value = child_value, .alias_symbol = alias_symbol }; if (isRelevant(direct, true)) { if (visible_index == target) { if (child_value.extra) return null; return directFieldName(node, child_structural_index) orelse inherited; } visible_index += 1; continue; } const count = relevantCount(direct, true); if (target >= visible_index and target - visible_index < count) { if (!child_value.extra) inherited = directFieldName(node, child_structural_index) orelse inherited; target -= visible_index; descend = direct; break; } visible_index += count; } node = descend orelse return null; }}pub fn isNamed(node: Node) bool { const tree = node.tree orelse return false; const value = node.value orelse return false; if (node.alias_symbol != 0) return tree.language.symbolMetadata(node.alias_symbol).named; return value.named;}pub fn startLine(node: Node) i64 { const value = node.value orelse return 0; return @intCast(value.start.point.row + 1);}pub fn endLine(node: Node) i64 { const value = node.value orelse return 0; return @intCast(value.end.point.row + 1);}pub fn startByte(node: Node) u32 { return (node.value orelse return 0).start.byte;}pub fn endByte(node: Node) u32 { return (node.value orelse return 0).end.byte;}pub fn slice(source: []const u8, node: Node) []const u8 { const start = @min(@as(usize, startByte(node)), source.len); const end = @min(@as(usize, endByte(node)), source.len); return source[start..@max(start, end)];}fn childByFieldId(initial: Node, field_id: abi.Field) ?Node { var node = initial; while (true) { const tree = node.tree orelse return null; const value = node.value orelse return null; if (value.children.len == 0) return null; const fields = tree.language.fieldMap(value.production_id); if (fields.len == 0) return null; var start: usize = 0; while (start < fields.len and fields[start].field_id < field_id) : (start += 1) {} if (start == fields.len or fields[start].field_id != field_id) return null; var end = start + 1; while (end < fields.len and fields[end].field_id == field_id) : (end += 1) {} var field_index = start; var structural_index: u32 = 0; var inherited: ?Node = null; for (value.children) |child_value| { const alias_symbol = aliasFor(node, child_value, structural_index); const direct = Node{ .tree = tree, .value = child_value, .alias_symbol = alias_symbol }; if (child_value.extra) continue; const current_index = structural_index; structural_index += 1; if (current_index < fields[field_index].child_index) continue; if (current_index > fields[field_index].child_index) return null; if (fields[field_index].inherited) { if (field_index + 1 == end) { inherited = direct; break; } if (childByFieldId(direct, field_id)) |result| return result; field_index += 1; if (field_index == end) return null; } else if (isRelevant(direct, true)) { return direct; } else { const result = childAt(direct, 0, true); if (result.value != null) return result; field_index += 1; if (field_index == end) return null; } } node = inherited orelse return null; }}fn childAt(initial: Node, requested: u32, include_anonymous: bool) Node { var node = initial; var target = requested; while (true) { const tree = node.tree orelse return Node.empty(); const value = node.value orelse return Node.empty(); var visible_index: u32 = 0; var structural_index: u32 = 0; var descend: ?Node = null; for (value.children) |child_value| { const alias_symbol = aliasFor(node, child_value, structural_index); if (!child_value.extra) structural_index += 1; const direct = Node{ .tree = tree, .value = child_value, .alias_symbol = alias_symbol }; if (isRelevant(direct, include_anonymous)) { if (visible_index == target) return direct; visible_index += 1; continue; } const count = relevantCount(direct, include_anonymous); if (target >= visible_index and target - visible_index < count) { target -= visible_index; descend = direct; break; } visible_index += count; } node = descend orelse return Node.empty(); }}fn relevantCount(node: Node, include_anonymous: bool) u32 { const value = node.value orelse return 0; return if (include_anonymous) value.visible_descendant_count else value.named_descendant_count;}fn isRelevant(node: Node, include_anonymous: bool) bool { const tree = node.tree orelse return false; const value = node.value orelse return false; if (node.alias_symbol != 0) { const metadata = tree.language.symbolMetadata(node.alias_symbol); return if (include_anonymous) metadata.visible else metadata.named; } return value.visible and (include_anonymous or value.named);}fn aliasFor(parent: Node, child_value: *const subtree.Subtree, structural_index: u32) abi.Symbol { if (child_value.extra) return 0; const tree = parent.tree orelse return 0; const value = parent.value orelse return 0; const aliases = tree.language.aliases(value.production_id); if (structural_index >= aliases.len) return 0; return aliases[structural_index];}fn directFieldName(parent: Node, structural_index: u32) ?[]const u8 { const tree = parent.tree orelse return null; const value = parent.value orelse return null; for (tree.language.fieldMap(value.production_id)) |field| { if (!field.inherited and field.child_index == structural_index) { const pointer = tree.language.raw.field_names.?[field.field_id]; if (@intFromPtr(pointer) == 0) return null; return std.mem.span(@as([*:0]const u8, @ptrCast(pointer))); } } return null;}Source: tools/smg/src/tree/runtime/root.zig:4
zig
pub const node = @import("node.zig");Audit
| Definitions | 17 |
|---|---|
| Public names | 32 |
| Members | 3 |
| Version | 26.7.0 |
| Revision | daab053ee433 |