Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

compile

compile.compile
pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void

File

Code

pub fn compile(allocator: Allocator, io: Io, source: []const u8, writer: *std.Io.Writer, options: CompileOptions) !void {
    var lexer = lex.Lexer.init(source, .{
        .default_code_page = options.default_code_page,
        .source_mappings = options.source_mappings,
        .max_string_literal_codepoints = options.max_string_literal_codepoints,
    });
    var parser = Parser.init(&lexer, .{
        .warn_instead_of_error_on_invalid_code_page = options.warn_instead_of_error_on_invalid_code_page,
        .disjoint_code_page = options.disjoint_code_page,
    });
    var tree = try parser.parse(allocator, options.diagnostics);
    defer tree.deinit();

    var search_dirs: std.ArrayList(SearchDir) = .empty;
    defer {
        for (search_dirs.items) |*search_dir| {
            search_dir.deinit(allocator, io);
        }
        search_dirs.deinit(allocator);
    }

    if (options.source_mappings) |source_mappings| {
        const root_path = source_mappings.files.get(source_mappings.root_filename_offset);
        // If dirname returns null, then the root path will be the same as
        // the cwd so we don't need to add it as a distinct search path.
        if (std.fs.path.dirname(root_path)) |root_dir_path| {
            var root_dir = try options.cwd.openDir(io, root_dir_path, .{});
            errdefer root_dir.close(io);
            try search_dirs.append(allocator, .{ .dir = root_dir, .path = try allocator.dupe(u8, root_dir_path) });
        }
    }
    // Re-open the passed in cwd since we want to be able to close it (Io.Dir.cwd() shouldn't be closed)
    const cwd_dir = options.cwd.openDir(io, ".", .{}) catch |err| {
        try options.diagnostics.append(.{
            .err = .failed_to_open_cwd,
            .token = .{
                .id = .invalid,
                .start = 0,
                .end = 0,
                .line_number = 1,
            },
            .code_page = .utf8,
            .print_source_line = false,
            .extra = .{ .file_open_error = .{
                .err = ErrorDetails.FileOpenError.enumFromError(err),
                .filename_string_index = undefined,
            } },
        });
        return error.CompileError;
    };
    try search_dirs.append(allocator, .{ .dir = cwd_dir, .path = null });
    for (options.extra_include_paths) |extra_include_path| {
        var dir = openSearchPathDir(options.cwd, io, extra_include_path) catch {
            // TODO: maybe a warning that the search path is skipped?
            continue;
        };
        errdefer dir.close(io);
        try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, extra_include_path) });
    }
    for (options.system_include_paths) |system_include_path| {
        var dir = openSearchPathDir(options.cwd, io, system_include_path) catch {
            // TODO: maybe a warning that the search path is skipped?
            continue;
        };
        errdefer dir.close(io);
        try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, system_include_path) });
    }
    if (!options.ignore_include_env_var) {
        const INCLUDE = options.include_env_value orelse "";

        // The only precedence here is llvm-rc which also uses the platform-specific
        // delimiter. There's no precedence set by `rc.exe` since it's Windows-only.
        const delimiter = switch (builtin.os.tag) {
            .windows => ';',
            else => ':',
        };
        var it = std.mem.tokenizeScalar(u8, INCLUDE, delimiter);
        while (it.next()) |search_path| {
            var dir = openSearchPathDir(options.cwd, io, search_path) catch continue;
            errdefer dir.close(io);
            try search_dirs.append(allocator, .{ .dir = dir, .path = try allocator.dupe(u8, search_path) });
        }
    }

    var arena_allocator = std.heap.ArenaAllocator.init(allocator);
    defer arena_allocator.deinit();
    const arena = arena_allocator.allocator();

    var compiler: Compiler = .{
        .source = source,
        .arena = arena,
        .allocator = allocator,
        .io = io,
        .cwd = options.cwd,
        .diagnostics = options.diagnostics,
        .dependencies = options.dependencies,
        .input_code_pages = &tree.input_code_pages,
        .output_code_pages = &tree.output_code_pages,
        // This is only safe because we know search_dirs won't be modified past this point
        .search_dirs = search_dirs.items,
        .null_terminate_string_table_strings = options.null_terminate_string_table_strings,
        .silent_duplicate_control_ids = options.silent_duplicate_control_ids,
    };
    if (options.default_language_id) |default_language_id| {
        compiler.state.language = res.Language.fromInt(default_language_id);
    }

    try compiler.writeRoot(tree.root(), writer);
}