Skip to documentation
SLOP

tiny.chant.parse.initializer

Reference tiny.chant parse initializer

Defined in parse.

API (2)

Actions

Public operations.

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

Source

Called byCallsNo direct callersprivate sourcelib.chant.src.parse.initializercompleteArrayTypeparse.initializercompleteType
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersparse.expressionparseAssignmentprivate sourcelib.chant.src.parse.initializerdesignatorTypeprivate sourcelib.chant.src.parse.initializerparseDesignatorparse.state.cursorconsumeparse.state.cursorexpect+2 moreparse.initializerparse
Static calls · unresolved targets: 1 · external targets: 3.

Source: lib/chant/src/parse/initializer.zig

zig
const std = @import("std");const ast = @import("../ast/root.zig");const expression = @import("expression.zig");const state = @import("state/root.zig");const cursor = state.cursor;const diagnostic = state.diagnostic;const memory = state.memory;const Error = @import("error.zig").Error;const Parser = state.Parser;pub fn parse(parser: *Parser, c_type: *const ast.Type) Error!*ast.Expr {    if (cursor.consume(parser, .lbrace)) {        var items = std.ArrayListUnmanaged(ast.expr.InitializerItem).empty;        if (!cursor.consume(parser, .rbrace)) {            while (true) {                const path = try parseDesignator(parser);                const value_type = if (path.len == 0)                    ast.types.element(c_type) orelse c_type                else blk: {                    _ = try cursor.expect(parser, .assign);                    break :blk try designatorType(parser, c_type, path);                };                try items.append(parser.arena, .{ .designator = path, .value = try parse(parser, value_type) });                if (cursor.consume(parser, .comma)) {                    if (cursor.consume(parser, .rbrace)) break;                    continue;                }                _ = try cursor.expect(parser, .rbrace);                break;            }        }        const slice = try items.toOwnedSlice(parser.arena);        if (ast.types.isArithmetic(c_type)) {            if (slice.len == 0) {                return memory.create(parser, ast.Expr, .{ .integer_literal = .{ .value = 0, .type = &ast.types.int_type } });            }            if (slice.len == 1 and slice[0].designator.len == 0) return slice[0].value;            return diagnostic.fail(parser, error.UnsupportedConstruct, "scalar initializer list has too many values");        }        return memory.create(parser, ast.Expr, .{ .initializer_list = .{ .type = c_type, .items = slice } });    }    return expression.parseAssignment(parser);}pub fn completeType(parser: *Parser, declared: *const ast.Type, initializer: ?*ast.Expr) Error!*const ast.Type {    const value = initializer orelse return declared;    const resolved = try completeArrayType(parser, declared, value);    if (value.* == .initializer_list) value.initializer_list.type = resolved;    return resolved;}fn parseDesignator(parser: *Parser) Error![]const u64 {    var designator = std.ArrayListUnmanaged(u64).empty;    while (true) {        if (cursor.consume(parser, .lbracket)) {            const index_expr = try expression.parseAssignment(parser);            const index_value = expression.evaluateIntegerConstant(parser, index_expr) orelse                return diagnostic.fail(parser, error.InvalidConstant, "array designator is not an integer constant");            const index = std.math.cast(u64, index_value) orelse                return diagnostic.fail(parser, error.InvalidConstant, "array designator is negative");            try designator.append(parser.arena, index);            _ = try cursor.expect(parser, .rbracket);            continue;        }        if (cursor.consume(parser, .dot)) {            return diagnostic.fail(parser, error.UnsupportedConstruct, "struct initializer designators are not supported");        }        break;    }    return designator.toOwnedSlice(parser.arena);}fn designatorType(parser: *Parser, c_type: *const ast.Type, path: []const u64) Error!*const ast.Type {    var current = c_type;    for (path) |index| {        if (current.kind != .array) {            return diagnostic.fail(parser, error.UnsupportedConstruct, "array designator does not name an array element");        }        if (current.array_len) |len| {            if (index >= len) return diagnostic.fail(parser, error.InvalidConstant, "array designator exceeds array bound");        }        current = current.child orelse return diagnostic.fail(parser, error.UnsupportedConstruct, "array designator names an incomplete element");    }    return current;}fn completeArrayType(parser: *Parser, declared: *const ast.Type, initializer: *ast.Expr) Error!*const ast.Type {    if (declared.kind != .array or declared.array_len != null) return declared;    const len = try inferArrayLength(parser, declared, initializer);    const type_origin = parser.nodes.typeOrigin(declared) orelse unreachable;    const resolved = try memory.createType(        parser,        declared.*,        memory.derivedType(type_origin, true),    );    resolved.array_len = len;    return resolved;}fn inferArrayLength(parser: *Parser, declared: *const ast.Type, initializer: *ast.Expr) Error!u64 {    const child = declared.child orelse return diagnostic.fail(parser, error.UnsupportedConstruct, "array initializer has no element type");    switch (initializer.*) {        .string_literal => |literal| {            if (!isCharType(child)) return diagnostic.fail(parser, error.UnsupportedConstruct, "string initializer requires a character array");            return std.math.add(u64, literal.text.len, 1) catch return diagnostic.fail(parser, error.InvalidConstant, "string initializer is too large");        },        .initializer_list => |list| {            const child_count = try staticElementCount(parser, child);            var next_scalar: u64 = 0;            var max_len: u64 = 0;            for (list.items) |item| {                if (item.designator.len == 0) {                    const consumed = try initializerScalarCount(parser, child, item.value);                    next_scalar = std.math.add(u64, next_scalar, consumed) catch return diagnostic.fail(parser, error.InvalidConstant, "array initializer is too large");                } else {                    const target = try designatorType(parser, declared, item.designator);                    const offset = try designatorOffset(parser, declared, item.designator);                    const consumed = try initializerScalarCount(parser, target, item.value);                    next_scalar = std.math.add(u64, offset, consumed) catch return diagnostic.fail(parser, error.InvalidConstant, "array initializer is too large");                }                const len = std.math.divCeil(u64, next_scalar, child_count) catch return diagnostic.fail(parser, error.InvalidConstant, "array initializer is too large");                max_len = @max(max_len, len);            }            if (max_len == 0) return diagnostic.fail(parser, error.UnsupportedConstruct, "incomplete array initializer has no size");            return max_len;        },        else => return diagnostic.fail(parser, error.UnsupportedConstruct, "array initializer does not determine array size"),    }}fn isCharType(c_type: *const ast.Type) bool {    return c_type.kind == .char_type;}fn isCharArray(c_type: *const ast.Type) bool {    if (c_type.kind != .array) return false;    var current = c_type;    while (current.kind == .array) {        current = current.child orelse return false;    }    return isCharType(current);}fn initializerScalarCount(parser: *Parser, target: *const ast.Type, initializer: *ast.Expr) Error!u64 {    switch (initializer.*) {        .initializer_list => |list| return staticElementCount(parser, list.type),        .string_literal => {            if (!isCharArray(target)) return 1;            return staticElementCount(parser, target);        },        else => return 1,    }}fn designatorOffset(parser: *Parser, c_type: *const ast.Type, path: []const u64) Error!u64 {    var current = c_type;    var offset: u64 = 0;    for (path) |index| {        if (current.kind != .array) return diagnostic.fail(parser, error.UnsupportedConstruct, "array designator does not name an array element");        if (current.array_len) |len| {            if (index >= len) return diagnostic.fail(parser, error.InvalidConstant, "array designator exceeds array bound");        }        const child = current.child orelse return diagnostic.fail(parser, error.UnsupportedConstruct, "array designator names an incomplete element");        const stride = try staticElementCount(parser, child);        const scaled = std.math.mul(u64, index, stride) catch return diagnostic.fail(parser, error.InvalidConstant, "array designator is too large");        offset = std.math.add(u64, offset, scaled) catch return diagnostic.fail(parser, error.InvalidConstant, "array designator is too large");        current = child;    }    return offset;}fn staticElementCount(parser: *Parser, c_type: *const ast.Type) Error!u64 {    if (c_type.kind != .array) return 1;    const len = c_type.array_len orelse return diagnostic.fail(parser, error.UnsupportedConstruct, "nested incomplete array initializer is unsupported");    const child = c_type.child orelse return diagnostic.fail(parser, error.UnsupportedConstruct, "array initializer has no element type");    const child_count = try staticElementCount(parser, child);    return std.math.mul(u64, len, child_count) catch return diagnostic.fail(parser, error.InvalidConstant, "array initializer is too large");}

Source: lib/chant/src/parse/root.zig:12

zig
pub const initializer = @import("initializer.zig");

Complete call list for parse.initializer.parse

7 direct calls.

Audit

Definitions3
Public names3
Members0
Version26.7.0
Revisiondaab053ee433