Skip to documentation
SLOP

tiny.chant.ParserNodeStorage

Reference tiny.chant ParserNodeStorage

Defined in tiny.chant.

The storage divides one buffer the caller supplies into slots for up to two expression nodes, one statement node and two type nodes per admitted token, along with the source token and cached inferred type of each node.

API (36)

Actions

Public operations.

Types and contracts

Public types and contracts.

Fields and members

Public fields and members.

No direct callersNo direct callstiny.chantParserNodeStorage
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/chant/src/parse/state/storage.zig:43

zig
/// The storage divides one buffer the caller supplies into slots for up to two/// expression nodes, one statement node and two type nodes per admitted token,/// along with the source token and cached inferred type of each node. A caller/// allocates one aligned buffer of `Capacity.storage_bytes`, hands it to/// `init`, activates it, and passes it to `parse`, and every node of the/// resulting syntax tree (the parsed translation unit) lives here. The buffer/// belongs to the caller, and `deinit` hands it back. Each parse starts by/// clearing the node counts, so a second parse into the same storage/// invalidates every node pointer from the first, and `deinit` invalidates them/// as well. A request for a node when its slots are full returns/// `error.NodeCapacityExceeded` before anything is written. The order of use is/// `init`, `activate`, any number of parses, then `deinit`.pub const Storage = struct {    phase: alloc_phase.capacity.Phase,    capacity: capacity_mod.Capacity,    storage: @This().Storage,    expressions: []ast.Expr,    statements: []ast.Stmt,    types: []ast.Type,    type_origins: []origin.TypeOrigin,    expression_origins: []usize,    expression_types: []?*const ast.Type,    type_charges: []u8,    admitted_tokens_len: usize,    expression_count: usize,    statement_count: usize,    type_count: usize,    pub const storage_alignment: usize = capacity_mod.storage_alignment;    pub const Storage = []align(storage_alignment) u8;    pub const Limits: type = capacity_mod.Limits;    pub const Capacity: type = capacity_mod.Capacity;    pub const Exhaustion: type = NodeExhaustion;    pub const InitError = capacity_mod.DeriveError || error{StorageTooShort};    pub const work_limits: alloc_phase.capacity.WorkLimits = .{        .transition_steps_max = std.math.maxInt(usize),        .cleanup_steps_per_call_max = 0,        .cleanup_calls_at_capacity_max = 0,    };    pub const claim: alloc_phase.capacity.Declaration = .{        .source = .{            .id = "chant.parser_node_storage",            .kind = .phase_static,            .limit_source = .caller,            .storage = .{                .covered = &.{                    .{                        .id = "at_most_two_expression_nodes_per_lexed_token",                        .lifetime = .steady,                        .detail = "at most two expression nodes per lexed token",                    },                    .{                        .id = "at_most_one_statement_node_per_lexed_token",                        .lifetime = .steady,                        .detail = "at most one statement node per lexed token",                    },                    .{                        .id = "at_most_two_dynamic_type_nodes_per_lexed_token",                        .lifetime = .steady,                        .detail = "at most two dynamic type nodes per lexed token",                    },                    .{                        .id = "node_origin_inferred_type_cache_and_two_charge_toke_1bf7f8a5a1ad",                        .lifetime = .steady,                        .detail = "node origin, inferred-type cache, and two-charge token ledger metadata",                    },                },                .excluded = &.{                    "list and map backing bytes plus their container metadata",                    "object bindings, scopes, and decoded token-text bytes",                    "caller-owned lexed tokens and their borrowed source and file bytes",                    "allocator metadata for caller acquisition and excluded parser allocations",                    "Choir context and lowered IR storage",                },            },            .capacity = .{                .inputs = &.{                    alloc_phase.capacity.bindInput(capacity_mod.Limits, "tokens", "tokens"),                },                .type_selectors = &.{                    alloc_phase.capacity.bindType(ast.Expr, "expr"),                    alloc_phase.capacity.bindType(ast.Stmt, "stmt"),                    alloc_phase.capacity.bindType(ast.Type, "type"),                    alloc_phase.capacity.bindType(origin.TypeOrigin, "typeorigin"),                    alloc_phase.capacity.bindType(usize, "usize"),                    alloc_phase.capacity.bindType(?*const ast.Type, "type_type"),                    alloc_phase.capacity.bindType(u8, "u8"),                },                .nodes = &.{                    .{ .input = 0 },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 2 } } },                    .{ .scale = .{ .node = 1, .coefficient = .{ .size_of_concrete_type = 0 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 1 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 2 } } },                    .{ .scale = .{ .node = 4, .coefficient = .{ .size_of_concrete_type = 2 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 2 } } },                    .{ .scale = .{ .node = 6, .coefficient = .{ .size_of_concrete_type = 3 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 2 } } },                    .{ .scale = .{ .node = 8, .coefficient = .{ .size_of_concrete_type = 4 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .literal = 2 } } },                    .{ .scale = .{ .node = 10, .coefficient = .{ .size_of_concrete_type = 5 } } },                    .{ .scale = .{ .node = 0, .coefficient = .{ .size_of_concrete_type = 6 } } },                    .{ .constant = 0 },                    .{ .alignment = .{ .node = 13, .alignment = .{ .concrete_type = 0 } } },                    .{ .add = .{ .left = 14, .right = 2 } },                    .{ .alignment = .{ .node = 15, .alignment = .{ .concrete_type = 1 } } },                    .{ .add = .{ .left = 16, .right = 3 } },                    .{ .alignment = .{ .node = 17, .alignment = .{ .concrete_type = 2 } } },                    .{ .add = .{ .left = 18, .right = 5 } },                    .{ .alignment = .{ .node = 19, .alignment = .{ .concrete_type = 3 } } },                    .{ .add = .{ .left = 20, .right = 7 } },                    .{ .alignment = .{ .node = 21, .alignment = .{ .concrete_type = 4 } } },                    .{ .add = .{ .left = 22, .right = 9 } },                    .{ .alignment = .{ .node = 23, .alignment = .{ .concrete_type = 5 } } },                    .{ .add = .{ .left = 24, .right = 11 } },                    .{ .alignment = .{ .node = 25, .alignment = .{ .concrete_type = 6 } } },                    .{ .add = .{ .left = 26, .right = 12 } },                    .{ .alignment = .{ .node = 27, .alignment = .{ .literal = 1 } } },                },                .assertions = &.{.{                    .scope = .closure_total,                    .measure = .retained,                    .relation = .exact,                    .expression = 28,                }},            },            .overload = .{                .kind = .reject_before_mutation,                .detail = "short regions and mismatched or over-limit token surveys reject before node placement",            },            .risks = .{                .transitive = .{                    .status = .witnessed,                    .detail = "all parser node creation dispatches exhaustively into the three typed slices",                },                .foreign = .{                    .status = .excluded,                    .detail = "node placement reads borrowed memory and crosses no foreign boundary",                },            },            .work = .{ .equation = "each node placement is one checked slice write bounded by lexed tokens" },            .dependencies = &.{"chant.lexed_token_storage"},            .obligations = &.{                .{ .key = "chant_parser_nodes_capacity", .role = .capacity_model },                .{ .key = "chant_parser_nodes_boundary", .role = .overload },                .{ .key = "chant_parser_nodes_oom", .role = .custom },                .{ .key = "chant_parser_nodes_identity", .role = .overload },                .{ .key = "chant_parser_nodes_prepublication", .role = .overload },                .{ .key = "chant_parser_nodes_sealed_transitive_risk", .role = .transitive_risk },                .{ .key = "chant_parser_nodes_sealed_foreign_risk", .role = .foreign_risk },                .{ .key = "chant_parser_nodes_sealed_work_bound", .role = .work_bound },                .{ .key = "chant_parser_nodes_differential", .role = .transitive_risk },                .{ .key = "chant_parser_nodes_adversarial", .role = .transitive_risk },                .{ .key = "chant_parser_type_charge", .role = .transitive_risk },                .{ .key = "chant_parser_type_cache", .role = .transitive_risk },            },        },        .bindings = .{            .owner = @This(),            .seal = .{                .family = alloc_phase.capacity.selector(@This().activate),                .premise = .{                    .class = .checked_semantic_fact,                    .authority = .checker,                },            },            .teardown = .{                .family = alloc_phase.capacity.selector(@This().deinit),                .premise = .{                    .class = .checked_semantic_fact,                    .authority = .checker,                },            },        },    };    pub const Status = struct {        expressions: usize,        statements: usize,        types: usize,    };    pub fn init(        storage: @This().Storage,        limits: capacity_mod.Limits,    ) InitError!@This() {        const capacity = try capacity_mod.Capacity.derive(limits);        if (storage.len < capacity.storage_bytes) return error.StorageTooShort;        const owned = storage[0..capacity.storage_bytes];        return .{            .phase = .initialization,            .capacity = capacity,            .storage = owned,            .expressions = typedSlice(                ast.Expr,                owned,                capacity.expressions_offset,                capacity.expressions,            ),            .statements = typedSlice(                ast.Stmt,                owned,                capacity.statements_offset,                capacity.statements,            ),            .types = typedSlice(                ast.Type,                owned,                capacity.types_offset,                capacity.types,            ),            .type_origins = typedSlice(                origin.TypeOrigin,                owned,                capacity.type_origins_offset,                capacity.types,            ),            .expression_origins = typedSlice(                usize,                owned,                capacity.expression_origins_offset,                capacity.expressions,            ),            .expression_types = typedSlice(                ?*const ast.Type,                owned,                capacity.expression_types_offset,                capacity.expressions,            ),            .type_charges = typedSlice(                u8,                owned,                capacity.type_charges_offset,                capacity.limits.tokens,            ),            .admitted_tokens_len = 0,            .expression_count = 0,            .statement_count = 0,            .type_count = 0,        };    }    pub fn activate(self: *@This()) void {        std.debug.assert(self.phase == .initialization);        self.assertStorage();        self.phase = .steady;    }    pub fn admit(        self: *@This(),        token_survey: Survey,        tokens: []const Token,    ) NodeExhaustion!void {        std.debug.assert(self.phase == .steady);        try requireIdentity(token_survey, tokens);        if (token_survey.limits.tokens > self.capacity.limits.tokens) {            return error.NodeCapacityExceeded;        }        @memset(self.type_charges, 0);        self.admitted_tokens_len = tokens.len;        self.expression_count = 0;        self.statement_count = 0;        self.type_count = 0;    }    pub fn createExpr(self: *@This(), value: ast.Expr) PlacementExhaustion!*ast.Expr {        return self.createExprAt(value, null);    }    pub fn createExprAt(        self: *@This(),        value: ast.Expr,        token_index: ?usize,    ) PlacementExhaustion!*ast.Expr {        std.debug.assert(self.phase == .steady);        if (self.expression_count >= self.expressions.len) {            return error.NodeCapacityExceeded;        }        if (token_index) |index| {            if (index >= self.admitted_tokens_len) {                return error.NodeCapacityExceeded;            }        }        const result = &self.expressions[self.expression_count];        self.expression_origins[self.expression_count] = token_index orelse            origin.no_token;        self.expression_types[self.expression_count] = null;        self.expression_count += 1;        result.* = value;        return result;    }    pub fn createStmt(self: *@This(), value: ast.Stmt) PlacementExhaustion!*ast.Stmt {        std.debug.assert(self.phase == .steady);        if (self.statement_count >= self.statements.len) {            return error.NodeCapacityExceeded;        }        const result = &self.statements[self.statement_count];        self.statement_count += 1;        result.* = value;        return result;    }    pub fn createType(        self: *@This(),        value: ast.Type,        placement: origin.TypePlacement,    ) PlacementExhaustion!*ast.Type {        std.debug.assert(self.phase == .steady);        if (self.type_count >= self.types.len) return error.NodeCapacityExceeded;        if (!self.validTypePlacement(placement)) {            return error.NodeCapacityExceeded;        }        if (self.type_charges[placement.charged] >= 2) {            return error.NodeCapacityExceeded;        }        const result = &self.types[self.type_count];        self.type_charges[placement.charged] += 1;        self.type_origins[self.type_count] = placement.origin;        self.type_count += 1;        result.* = value;        return result;    }    pub fn typeOrigin(        self: *const @This(),        value: *const ast.Type,    ) ?origin.TypeOrigin {        const index = pointerIndex(ast.Type, self.types, value) orelse return null;        std.debug.assert(index < self.type_count);        return self.type_origins[index];    }    pub fn expressionOrigin(        self: *const @This(),        value: *const ast.Expr,    ) usize {        const index = pointerIndex(ast.Expr, self.expressions, value) orelse            unreachable;        std.debug.assert(index < self.expression_count);        const token_index = self.expression_origins[index];        std.debug.assert(token_index != origin.no_token);        return token_index;    }    pub fn inferredType(        self: *const @This(),        value: *const ast.Expr,    ) ?*const ast.Type {        const index = pointerIndex(ast.Expr, self.expressions, value) orelse            unreachable;        std.debug.assert(index < self.expression_count);        return self.expression_types[index];    }    pub fn setInferredType(        self: *@This(),        value: *const ast.Expr,        inferred: *const ast.Type,    ) void {        const index = pointerIndex(ast.Expr, self.expressions, value) orelse            unreachable;        std.debug.assert(index < self.expression_count);        std.debug.assert(self.expression_types[index] == null);        self.expression_types[index] = inferred;    }    pub fn status(self: *const @This()) Status {        std.debug.assert(self.phase == .steady);        return .{            .expressions = self.expression_count,            .statements = self.statement_count,            .types = self.type_count,        };    }    pub fn deinit(self: *@This()) @This().Storage {        std.debug.assert(self.phase == .steady);        self.phase = .teardown;        const storage = self.storage;        self.* = undefined;        return storage;    }    fn assertStorage(self: *const @This()) void {        const expected = capacity_mod.Capacity.derive(            self.capacity.limits,        ) catch unreachable;        std.debug.assert(std.meta.eql(expected, self.capacity));        std.debug.assert(self.storage.len == self.capacity.storage_bytes);        std.debug.assert(self.expressions.len == self.capacity.expressions);        std.debug.assert(self.statements.len == self.capacity.statements);        std.debug.assert(self.types.len == self.capacity.types);        std.debug.assert(self.type_origins.len == self.capacity.types);        std.debug.assert(self.expression_origins.len == self.capacity.expressions);        std.debug.assert(self.expression_types.len == self.capacity.expressions);        std.debug.assert(self.type_charges.len == self.capacity.limits.tokens);    }    fn validTypePlacement(        self: *const @This(),        placement: origin.TypePlacement,    ) bool {        if (placement.charged >= self.admitted_tokens_len) return false;        if (placement.origin.primary >= self.admitted_tokens_len) return false;        if (placement.origin.secondary != origin.no_token and            placement.origin.secondary >= self.admitted_tokens_len)        {            return false;        }        return placement.charged == placement.origin.primary or            placement.charged == placement.origin.secondary;    }};

Source: lib/chant/src/root.zig:79

zig
pub const ParserNodeStorage = parse.Storage;
Called byCallsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser node storage requires th...test sourcelib.chant.src.parse.state.storagetest: parser type origins enforce two...private sourcelib.chant.src.parse.state.storage.StorageassertStorageParserNodeStorageactivate
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser node storage requires th...test sourcelib.chant.src.parse.state.storagetest: parser type origins enforce two...private sourcelib.chant.src.parse.state.storagerequireIdentityParserNodeStorageadmit
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...parse.StoragecreateExprAtParserNodeStoragecreateExpr
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsparse.StoragecreateExprParserNodeStoragecreateExprAt
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser node storage requires th...ParserNodeStoragecreateStmt
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser type origins enforce two...private sourcelib.chant.src.parse.state.storage.StoragevalidTypePlacementParserNodeStoragecreateType
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser node storage requires th...test sourcelib.chant.src.parse.state.storagetest: parser type origins enforce two...ParserNodeStoragedeinit
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.chant.src.parse.state.storagepointerIndexParserNodeStorageexpressionOrigin
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.chant.src.parse.state.storagepointerIndexParserNodeStorageinferredType
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.chant.src.parse.state.storageinitFailurestest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser node storage requires th...test sourcelib.chant.src.parse.state.storagetest: parser type origins enforce two...private sourcelib.chant.src.parse.state.storagetypedSliceParserNodeStorageinit
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersprivate sourcelib.chant.src.parse.state.storagepointerIndexParserNodeStoragesetInferredType
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.chant.src.parse.state.storagetest: parser node storage admits exac...test sourcelib.chant.src.parse.state.storagetest: parser node storage requires th...test sourcelib.chant.src.parse.state.storagetest: parser type origins enforce two...ParserNodeStoragestatus
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.chant.src.parse.state.storagepointerIndexParserNodeStoragetypeOrigin
Static calls · unresolved targets: 0 · external targets: 0.

Also reachable as

parse.Storage, parse.state.Storage.

Audit

Definitions23
Public names69
Members17
Version26.7.0
Revisiondaab053ee433