diff --git a/doc/docgen.zig b/doc/docgen.zig index f3bb7df6b1..d21ed78cb0 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -1,10 +1,14 @@ const std = @import("std"); const io = std.io; const os = std.os; +const warn = std.debug.warn; +const mem = std.mem; + +pub const max_doc_file_size = 10 * 1024 * 1024; pub fn main() -> %void { // TODO use a more general purpose allocator here - var inc_allocator = try std.heap.IncrementingAllocator.init(5 * 1024 * 1024); + var inc_allocator = try std.heap.IncrementingAllocator.init(max_doc_file_size); defer inc_allocator.deinit(); const allocator = &inc_allocator.allocator; @@ -25,39 +29,383 @@ pub fn main() -> %void { defer out_file.close(); var file_in_stream = io.FileInStream.init(&in_file); - var buffered_in_stream = io.BufferedInStream.init(&file_in_stream.stream); + + const input_file_bytes = try file_in_stream.stream.readAllAlloc(allocator, max_doc_file_size); var file_out_stream = io.FileOutStream.init(&out_file); var buffered_out_stream = io.BufferedOutStream.init(&file_out_stream.stream); - gen(&buffered_in_stream.stream, &buffered_out_stream.stream); - try buffered_out_stream.flush(); + const toc = try genToc(allocator, in_file_name, input_file_bytes); + try genHtml(allocator, toc, &buffered_out_stream.stream); + try buffered_out_stream.flush(); } -const State = enum { - Start, - Derp, +const Token = struct { + id: Id, + start: usize, + end: usize, + + const Id = enum { + Invalid, + Content, + BracketOpen, + TagContent, + Separator, + BracketClose, + Eof, + }; }; -// TODO look for code segments +const Tokenizer = struct { + buffer: []const u8, + index: usize, + state: State, + source_file_name: []const u8, -fn gen(in: &io.InStream, out: &io.OutStream) { - var state = State.Start; - while (true) { - const byte = in.readByte() catch |err| { - if (err == error.EndOfStream) { - return; - } - std.debug.panic("{}", err); + const State = enum { + Start, + LBracket, + Hash, + TagName, + Eof, + }; + + fn init(source_file_name: []const u8, buffer: []const u8) -> Tokenizer { + return Tokenizer { + .buffer = buffer, + .index = 0, + .state = State.Start, + .source_file_name = source_file_name, }; - switch (state) { - State.Start => switch (byte) { - else => { - out.writeByte(byte) catch unreachable; + } + + fn next(self: &Tokenizer) -> Token { + var result = Token { + .id = Token.Id.Eof, + .start = self.index, + .end = undefined, + }; + while (self.index < self.buffer.len) : (self.index += 1) { + const c = self.buffer[self.index]; + switch (self.state) { + State.Start => switch (c) { + '{' => { + self.state = State.LBracket; + }, + else => { + result.id = Token.Id.Content; + }, }, - }, - State.Derp => unreachable, + State.LBracket => switch (c) { + '#' => { + if (result.id != Token.Id.Eof) { + self.index -= 1; + self.state = State.Start; + break; + } else { + result.id = Token.Id.BracketOpen; + self.index += 1; + self.state = State.TagName; + break; + } + }, + else => { + result.id = Token.Id.Content; + self.state = State.Start; + }, + }, + State.TagName => switch (c) { + '|' => { + if (result.id != Token.Id.Eof) { + break; + } else { + result.id = Token.Id.Separator; + self.index += 1; + break; + } + }, + '#' => { + self.state = State.Hash; + }, + else => { + result.id = Token.Id.TagContent; + }, + }, + State.Hash => switch (c) { + '}' => { + if (result.id != Token.Id.Eof) { + self.index -= 1; + self.state = State.TagName; + break; + } else { + result.id = Token.Id.BracketClose; + self.index += 1; + self.state = State.Start; + break; + } + }, + else => { + result.id = Token.Id.TagContent; + self.state = State.TagName; + }, + }, + State.Eof => unreachable, + } + } else { + switch (self.state) { + State.Start, State.LBracket, State.Eof => {}, + else => { + result.id = Token.Id.Invalid; + }, + } + self.state = State.Eof; } + result.end = self.index; + return result; + } + + const Location = struct { + line: usize, + column: usize, + line_start: usize, + line_end: usize, + }; + + fn getTokenLocation(self: &Tokenizer, token: &const Token) -> Location { + var loc = Location { + .line = 0, + .column = 0, + .line_start = 0, + .line_end = 0, + }; + for (self.buffer) |c, i| { + if (i == token.start) { + loc.line_end = i; + while (loc.line_end < self.buffer.len and self.buffer[loc.line_end] != '\n') : (loc.line_end += 1) {} + return loc; + } + if (c == '\n') { + loc.line += 1; + loc.column = 0; + loc.line_start = i + 1; + } else { + loc.column += 1; + } + } + return loc; + } +}; + +error ParseError; + +fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const u8, args: ...) -> error { + const loc = tokenizer.getTokenLocation(token); + warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args); + if (loc.line_start <= loc.line_end) { + warn("{}\n", tokenizer.buffer[loc.line_start..loc.line_end]); + { + var i: usize = 0; + while (i < loc.column) : (i += 1) { + warn(" "); + } + } + { + const caret_count = token.end - token.start; + var i: usize = 0; + while (i < caret_count) : (i += 1) { + warn("~"); + } + } + warn("\n"); + } + return error.ParseError; +} + +fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) -> %void { + if (token.id != id) { + return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id)); } } + +fn eatToken(tokenizer: &Tokenizer, id: Token.Id) -> %Token { + const token = tokenizer.next(); + try assertToken(tokenizer, token, id); + return token; +} + +const HeaderOpen = struct { + name: []const u8, + url: []const u8, + n: usize, +}; + +const Tag = enum { + Nav, + HeaderOpen, + HeaderClose, +}; + +const Node = union(enum) { + Content: []const u8, + Nav, + HeaderOpen: HeaderOpen, +}; + +const Toc = struct { + nodes: []Node, + toc: []u8, +}; + +const Action = enum { + Open, + Close, +}; + +fn genToc(allocator: &mem.Allocator, source_file_name: []const u8, input_file_bytes: []const u8) -> %Toc { + var tokenizer = Tokenizer.init(source_file_name, input_file_bytes); + + var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator); + defer urls.deinit(); + + var header_stack_size: usize = 0; + var last_action = Action.Open; + + var toc_buf = try std.Buffer.initSize(allocator, 0); + defer toc_buf.deinit(); + + var toc_buf_adapter = io.BufferOutStream.init(&toc_buf); + var toc = &toc_buf_adapter.stream; + + var nodes = std.ArrayList(Node).init(allocator); + defer nodes.deinit(); + + try toc.writeByte('\n'); + + while (true) { + const token = tokenizer.next(); + switch (token.id) { + Token.Id.Eof => { + if (header_stack_size != 0) { + return parseError(&tokenizer, token, "unbalanced headers"); + } + try toc.write(" \n"); + break; + }, + Token.Id.Content => { + try nodes.append(Node {.Content = input_file_bytes[token.start..token.end] }); + }, + Token.Id.BracketOpen => { + const tag_token = try eatToken(&tokenizer, Token.Id.TagContent); + const tag_name = input_file_bytes[tag_token.start..tag_token.end]; + + var tag: Tag = undefined; + if (mem.eql(u8, tag_name, "nav")) { + tag = Tag.Nav; + } else if (mem.eql(u8, tag_name, "header_open")) { + tag = Tag.HeaderOpen; + header_stack_size += 1; + } else if (mem.eql(u8, tag_name, "header_close")) { + if (header_stack_size == 0) { + return parseError(&tokenizer, tag_token, "unbalanced close header"); + } + header_stack_size -= 1; + tag = Tag.HeaderClose; + } else { + return parseError(&tokenizer, tag_token, "unrecognized tag name: {}", tag_name); + } + + var tag_content: ?[]const u8 = null; + const maybe_sep = tokenizer.next(); + if (maybe_sep.id == Token.Id.Separator) { + const content_token = try eatToken(&tokenizer, Token.Id.TagContent); + tag_content = input_file_bytes[content_token.start..content_token.end]; + _ = eatToken(&tokenizer, Token.Id.BracketClose); + } else { + try assertToken(&tokenizer, maybe_sep, Token.Id.BracketClose); + } + + switch (tag) { + Tag.HeaderOpen => { + const content = tag_content ?? return parseError(&tokenizer, tag_token, "expected header content"); + const urlized = try urlize(allocator, content); + try nodes.append(Node{.HeaderOpen = HeaderOpen { + .name = content, + .url = urlized, + .n = header_stack_size, + }}); + if (try urls.put(urlized, tag_token)) |other_tag_token| { + parseError(&tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {}; + parseError(&tokenizer, other_tag_token, "other tag here") catch {}; + return error.ParseError; + } + if (last_action == Action.Open) { + try toc.writeByte('\n'); + try toc.writeByteNTimes(' ', header_stack_size * 4); + try toc.write("
Zig is an open-source programming language designed for robustness, optimality, and clarity. @@ -264,7 +53,8 @@ If you search for something specific in this documentation and do not find it, please file an issue or say something on IRC.
-const std = @import("std");
pub fn main() -> %void {
@@ -294,7 +84,8 @@ pub fn main() -> %void {
Errors
Root Source File
- Source Encoding
+ {#header_close#}
+ {#header_open|Source Encoding#}
Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.
Throughout all zig source code (including in comments), some codepoints are never allowed:
@@ -303,7 +94,8 @@ pub fn main() -> %void {
The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).
For some discussion on the rationale behind these design decisions, see issue #663
- Values
+ {#header_close#}
+ {#header_open|Values#}
const warn = @import("std").debug.warn;
const os = @import("std").os;
const assert = @import("std").debug.assert;
@@ -373,7 +165,7 @@ value: error.ArgNotFound
error union 2
type: %i32
value: 1234
- Primitive Types
+ {#header_open|Primitive Types#}
@@ -606,7 +398,8 @@ value: 1234
void
Errors
- Primitive Values
+ {#header_close#}
+ {#header_open|Primitive Values#}
@@ -638,7 +431,8 @@ value: 1234
Nullables
this
- String Literals
+ {#header_close#}
+ {#header_open|String Literals#}
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
@@ -663,7 +457,7 @@ Test 1/1 string literals...OK
Arrays
Zig Test
- Escape Sequences
+ {#header_open|Escape Sequences#}
@@ -711,7 +505,8 @@ Test 1/1 string literals...OK
Note that the maximum valid Unicode point is 0x10ffff.
- Multiline String Literals
+ {#header_close#}
+ {#header_open|Multiline String Literals#}
Multiline string literals have no escapes and can span across multiple lines.
To start a multiline string literal, use the \\ token. Just like a comment,
@@ -747,7 +542,9 @@ Test 1/1 string literals...OK
- Assignment
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Assignment#}
Use const to assign a value to an identifier:
const x = 1234;
@@ -798,14 +595,17 @@ test "init with undefined" {
}
$ zig test test.zig
Test 1/1 init with undefined...OK
- Integers
- Integer Literals
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Integers#}
+ {#header_open|Integer Literals#}
const decimal_int = 98222;
const hex_int = 0xff;
const another_hex_int = 0xFF;
const octal_int = 0o755;
const binary_int = 0b11110000;
- Runtime Integer Values
+ {#header_close#}
+ {#header_open|Runtime Integer Values#}
Integer literals have no size limitation, and if any undefined behavior occurs,
the compiler catches it.
@@ -833,8 +633,11 @@ const binary_int = 0b11110000;
Division By Zero
Wrapping Operations
- Floats
- Float Literals
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Floats#}
+ {#header_close#}
+ {#header_open|Float Literals#}
const floating_point = 123.0E+77;
const another_float = 123.0;
const yet_another = 123.0e+77;
@@ -842,7 +645,8 @@ const yet_another = 123.0e+77;
const hex_floating_point = 0x103.70p-5;
const another_hex_float = 0x103.70;
const yet_another_hex_float = 0x103.70P-5;
- Floating Point Operations
+ {#header_close#}
+ {#header_open|Floating Point Operations#}
By default floating point operations use Optimized mode,
but you can switch to Strict mode on a per-block basis:
foo.zig
@@ -881,8 +685,9 @@ strict = 9.765625e-3
@setFloatMode
Division By Zero
- Operators
- Table of Operators
+ {#header_close#}
+ {#header_open|Operators#}
+ {#header_open|Table of Operators#}
@@ -1470,7 +1275,8 @@ const ptr = &x;
- Precedence
+ {#header_close#}
+ {#header_open|Precedence#}
x() x[] x.y
!x -x -%x ~x *x &x ?x %x %%x ??x
x{}
@@ -1485,7 +1291,9 @@ and
or
?? catch
= *= /= %= += -= <<= >>= &= ^= |=
- Arrays
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Arrays#}
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
@@ -1599,7 +1407,8 @@ Test 4/4 array initialization with function calls...OK
for
Slices
- Pointers
+ {#header_close#}
+ {#header_open|Pointers#}
const assert = @import("std").debug.assert;
test "address of syntax" {
@@ -1737,7 +1546,7 @@ Test 5/8 volatile...OK
Test 6/8 nullable pointers...OK
Test 7/8 pointer casting...OK
Test 8/8 pointer child type...OK
- Alignment
+ {#header_open|Alignment#}
Each type has an alignment - a number of bytes such that,
when a value of the type is loaded from or stored to memory,
@@ -1838,7 +1647,8 @@ Test 1/1 pointer alignment safety...incorrect alignment
Tests failed. Use the following command to reproduce the failure:
./test
-
Type Based Alias Analysis
+ {#header_close#}
+ {#header_open|Type Based Alias Analysis#}
Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
perform some optimizations. This means that pointers of different types must
not alias the same memory, with the exception of u8. Pointers to
@@ -1854,7 +1664,9 @@ Tests failed. Use the following command to reproduce the failure:
Slices
Memory
- Slices
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Slices#}
const assert = @import("std").debug.assert;
test "basic slices" {
@@ -1954,7 +1766,8 @@ Test 3/3 slice widening...OK
for
Arrays
- struct
+ {#header_close#}
+ {#header_open|struct#}
// Declare a struct.
// Zig gives no guarantees about the order of fields and whether or
// not there will be padding.
@@ -2099,7 +1912,8 @@ Test 4/4 linked list...OK
comptime
@fieldParentPtr
- enum
+ {#header_close#}
+ {#header_open|enum#}
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
@@ -2216,7 +2030,8 @@ Test 8/8 @tagName...OK
@memberCount
@tagName
- union
+ {#header_close#}
+ {#header_open|union#}
const assert = @import("std").debug.assert;
const mem = @import("std").mem;
@@ -2323,7 +2138,8 @@ Test 7/7 @tagName...OK
Unions with an enum tag are generated as a struct with a tag field and union field. Zig
sorts the order of the tag and union field by the largest alignment.
- switch
+ {#header_close#}
+ {#header_open|switch#}
const assert = @import("std").debug.assert;
const builtin = @import("builtin");
@@ -2426,7 +2242,8 @@ Test 3/3 switch inside function...OK
@compileError
Compile Variables
- while
+ {#header_close#}
+ {#header_open|while#}
const assert = @import("std").debug.assert;
test "while basic" {
@@ -2595,7 +2412,8 @@ Test 8/8 inline while loop...OK
comptime
unreachable
- for
+ {#header_close#}
+ {#header_open|for#}
const assert = @import("std").debug.assert;
test "for basics" {
@@ -2696,7 +2514,8 @@ Test 4/4 inline for loop...OK
Arrays
Slices
- if
+ {#header_close#}
+ {#header_open|if#}
// If expressions have three uses, corresponding to the three types:
// * bool
// * ?T
@@ -2814,7 +2633,8 @@ Test 3/3 if error union...OK
Nullables
Errors
- goto
+ {#header_close#}
+ {#header_open|goto#}
const assert = @import("std").debug.assert;
test "goto" {
@@ -2830,7 +2650,7 @@ label:
Test 1/1 goto...OK
Note that there are plans to remove goto
- defer
+{{deheader_open:fer}}
const assert = @import("std").debug.assert;
const printf = @import("std").io.stdout.printf;
@@ -2920,7 +2740,8 @@ OK
- unreachable
+ {#header_close#}
+ {#header_open|unreachable#}
In Debug and ReleaseSafe mode, and when using zig test,
unreachable emits a call to panic with the message reached unreachable code.
@@ -2930,7 +2751,7 @@ OK
will never be hit to perform optimizations. However, zig test even in ReleaseFast mode
still emits unreachable as calls to panic.
- Basics
+ {#header_open|Basics#}
// unreachable is used to assert that control flow will never happen upon a
// particular location:
test "basic math" {
@@ -2974,7 +2795,8 @@ lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test)
Tests failed. Use the following command to reproduce the failure:
./test
- At Compile-Time
+ {#header_close#}
+ {#header_open|At Compile-Time#}
const assert = @import("std").debug.assert;
comptime {
@@ -2995,7 +2817,9 @@ test.zig:9:12: error: unreachable code
Build Mode
comptime
- noreturn
+ {#header_close#}
+ {#header_close#}
+ {#header_open|noreturn#}
noreturn is the type of:
@@ -3029,7 +2853,8 @@ fn bar() -> %u32 {
}
const assert = @import("std").debug.assert;
- Functions
+ {#header_close#}
+ {#header_open|Functions#}
const assert = @import("std").debug.assert;
// Functions are declared like this
@@ -3091,7 +2916,7 @@ comptime {
fn foo() { }
$ zig build-obj test.zig
- Pass-by-value Parameters
+ {#header_open|Pass-by-value Parameters#}
In Zig, structs, unions, and enums with payloads cannot be passed by value
to a function.
@@ -3127,7 +2952,9 @@ export fn entry() {
the C ABI does allow passing structs and unions by value. So functions which
use the C calling convention may pass structs and unions by value.
- Errors
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Errors#}
One of the distinguishing features of Zig is its exception handling strategy.
@@ -3321,7 +3148,8 @@ pub fn parseU64(buf: []const u8, radix: u8) -> %u64 {
if
switch
- Nullables
+ {#header_close#}
+ {#header_open|Nullables#}
One area that Zig provides safety without compromising efficiency or
readability is with the nullable type.
@@ -3415,7 +3243,8 @@ fn doAThing() -> ?&Foo {
The optimizer can sometimes make better decisions knowing that pointer arguments
cannot be null.
- Casting
+ {#header_close#}
+ {#header_open|Casting#}
TODO: explain implicit vs explicit casting
TODO: resolve peer types builtin
TODO: truncate builtin
@@ -3424,24 +3253,27 @@ fn doAThing() -> ?&Foo {
TODO: ptr to int builtin
TODO: ptrcast builtin
TODO: explain number literals vs concrete types
- void
+ {#header_close#}
+ {#header_open|void#}
TODO: assigning void has no codegen
TODO: hashmap with void becomes a set
TODO: difference between c_void and void
TODO: void is the default return value of functions
TODO: functions require assigning the return value
- this
+ {#header_close#}
+ {#header_open|this#}
TODO: example of this referring to Self struct
TODO: example of this referring to recursion function
TODO: example of this referring to basic block for @setDebugSafety
- comptime
+ {#header_close#}
+ {#header_open|comptime#}
Zig places importance on the concept of whether an expression is known at compile-time.
There are a few different places this concept is used, and these building blocks are used
to keep the language small, readable, and powerful.
- Introducing the Compile-Time Concept
- Compile-Time Parameters
+ {#header_open|Introducing the Compile-Time Concept#}
+ {#header_open|Compile-Time Parameters#}
Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
@@ -3549,7 +3381,8 @@ fn letsTryToCompareBools(a: bool, b: bool) -> bool {
This works the same way for switch expressions - they are implicitly inlined
when the target expression is compile-time known.
- Compile-Time Variables
+ {#header_close#}
+ {#header_open|Compile-Time Variables#}
In Zig, the programmer can label variables as comptime. This guarantees to the compiler
that every load and store of the variable is performed at compile-time. Any violation of this results in a
@@ -3631,7 +3464,8 @@ fn performFn(start_value: i32) -> i32 {
later in this article, allows expressiveness that in other languages requires using macros,
generated code, or a preprocessor to accomplish.
- Compile-Time Expressions
+ {#header_close#}
+ {#header_open|Compile-Time Expressions#}
In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can
use a comptime expression to guarantee that the expression will be evaluated at compile-time.
@@ -3860,7 +3694,9 @@ fn sum(numbers: []i32) -> i32 {
we could call the sum function as is with a slice of numbers whose length and values were
only known at run-time.
- Generic Data Structures
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Generic Data Structures#}
Zig uses these capabilities to implement generic data structures without introducing any
special-case syntax. If you followed along so far, you may already know how to create a
@@ -3895,7 +3731,8 @@ fn sum(numbers: []i32) -> i32 {
Node refers to itself as a pointer, which is not actually an infinite regression, so
it works fine.
- Case Study: printf in Zig
+ {#header_close#}
+ {#header_open|Case Study: printf in Zig#}
Putting all of this together, let's seee how printf works in Zig.
@@ -4045,35 +3882,42 @@ pub fn main(args: [][]u8) -> %void {
a macro language or a preprocessor language. It's Zig all the way down.
TODO: suggestion to not use inline unless necessary
- inline
+ {#header_close#}
+ {#header_close#}
+ {#header_open|inline#}
TODO: inline while
TODO: inline for
TODO: suggestion to not use inline unless necessary
- Assembly
+ {#header_close#}
+ {#header_open|Assembly#}
TODO: example of inline assembly
TODO: example of module level assembly
TODO: example of using inline assembly return value
TODO: example of using inline assembly assigning values to variables
- Atomics
+ {#header_close#}
+ {#header_open|Atomics#}
TODO: @fence()
TODO: @atomic rmw
TODO: builtin atomic memory ordering enum
- Builtin Functions
+ {#header_close#}
+ {#header_open|Builtin Functions#}
Builtin functions are provided by the compiler and are prefixed with @.
The comptime keyword on a parameter means that the parameter must be known
at compile time.
- @addWithOverflow
+ {#header_open|@addWithOverflow#}
@addWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool
Performs *result = a + b. If overflow or underflow occurs,
stores the overflowed bits in result and returns true.
If no overflow or underflow occurs, returns false.
- @ArgType
+ {#header_close#}
+ {#header_open|@ArgType#}
TODO
- @bitCast
+ {#header_close#}
+ {#header_open|@bitCast#}
@bitCast(comptime DestType: type, value: var) -> DestType
Converts a value of one type to another type.
@@ -4094,7 +3938,8 @@ pub fn main(args: [][]u8) -> %void {
Works at compile-time if value is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.
- @breakpoint
+ {#header_close#}
+ {#header_open|@breakpoint#}
@breakpoint()
This function inserts a platform-specific debug trap instruction which causes
@@ -4104,7 +3949,8 @@ pub fn main(args: [][]u8) -> %void {
This function is only valid within function scope.
- @alignCast
+ {#header_close#}
+ {#header_open|@alignCast#}
@alignCast(comptime alignment: u29, ptr: var) -> var
ptr can be &T, fn(), ?&T,
@@ -4114,7 +3960,8 @@ pub fn main(args: [][]u8) -> %void {
A pointer alignment safety check is added
to the generated code to make sure the pointer is aligned as promised.
- @alignOf
+ {#header_close#}
+ {#header_open|@alignOf#}
@alignOf(comptime T: type) -> (number literal)
This function returns the number of bytes that this type should be aligned to
@@ -4134,7 +3981,8 @@ comptime {
Alignment
- @cDefine
+ {#header_close#}
+ {#header_open|@cDefine#}
@cDefine(comptime name: []u8, value)
This function can only occur inside @cImport.
@@ -4159,7 +4007,8 @@ comptime {
@cUndef
void
- @cImport
+ {#header_close#}
+ {#header_open|@cImport#}
@cImport(expression) -> (namespace)
This function parses C code and imports the functions, types, variables, and
@@ -4177,7 +4026,8 @@ comptime {
@cDefine
@cUndef
- @cInclude
+ {#header_close#}
+ {#header_open|@cInclude#}
@cInclude(comptime path: []u8)
This function can only occur inside @cImport.
@@ -4193,7 +4043,8 @@ comptime {
@cDefine
@cUndef
- @cUndef
+ {#header_close#}
+ {#header_open|@cUndef#}
@cUndef(comptime name: []u8)
This function can only occur inside @cImport.
@@ -4209,12 +4060,14 @@ comptime {
@cDefine
@cInclude
- @canImplicitCast
+ {#header_close#}
+ {#header_open|@canImplicitCast#}
@canImplicitCast(comptime T: type, value) -> bool
Returns whether a value can be implicitly casted to a given type.
- @clz
+ {#header_close#}
+ {#header_open|@clz#}
@clz(x: T) -> U
This function counts the number of leading zeroes in x which is an integer
@@ -4228,7 +4081,8 @@ comptime {
If x is zero, @clz returns T.bit_count.
- @cmpxchg
+ {#header_close#}
+ {#header_open|@cmpxchg#}
@cmpxchg(ptr: &T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -> bool
This function performs an atomic compare exchange operation.
@@ -4242,7 +4096,8 @@ comptime {
Compile Variables
- @compileError
+ {#header_close#}
+ {#header_open|@compileError#}
@compileError(comptime msg: []u8)
This function, when semantically analyzed, causes a compile error with the
@@ -4253,7 +4108,8 @@ comptime {
using if or switch with compile time constants,
and comptime functions.
- @compileLog
+ {#header_close#}
+ {#header_open|@compileLog#}
@compileLog(args: ...)
This function prints the arguments passed to it at compile-time.
@@ -4303,7 +4159,7 @@ test.zig:6:2: error: found compile log statement
program compiles successfully and the generated executable prints:
Runtime in main, num1 = 100.
- @ctz
+{{@ctheader_open:z}}
@ctz(x: T) -> U
This function counts the number of trailing zeroes in x which is an integer
@@ -4316,7 +4172,8 @@ test.zig:6:2: error: found compile log statement
If x is zero, @ctz returns T.bit_count.
- @divExact
+ {#header_close#}
+ {#header_open|@divExact#}
@divExact(numerator: T, denominator: T) -> T
Exact division. Caller guarantees denominator != 0 and
@@ -4332,7 +4189,8 @@ test.zig:6:2: error: found compile log statement
@divFloor
@import("std").math.divExact
- @divFloor
+ {#header_close#}
+ {#header_open|@divFloor#}
@divFloor(numerator: T, denominator: T) -> T
Floored division. Rounds toward negative infinity. For unsigned integers it is
@@ -4349,7 +4207,8 @@ test.zig:6:2: error: found compile log statement
@divExact
@import("std").math.divFloor
- @divTrunc
+ {#header_close#}
+ {#header_open|@divTrunc#}
@divTrunc(numerator: T, denominator: T) -> T
Truncated division. Rounds toward zero. For unsigned integers it is
@@ -4366,7 +4225,8 @@ test.zig:6:2: error: found compile log statement
@divExact
@import("std").math.divTrunc
- @embedFile
+ {#header_close#}
+ {#header_open|@embedFile#}
@embedFile(comptime path: []const u8) -> [X]u8
This function returns a compile time constant fixed-size array with length
@@ -4380,17 +4240,20 @@ test.zig:6:2: error: found compile log statement
- @export
+ {#header_close#}
+ {#header_open|@export#}
@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) -> []const u8
Creates a symbol in the output object file.
- @tagName
+ {#header_close#}
+ {#header_open|@tagName#}
@tagName(value: var) -> []const u8
Converts an enum value or union value to a slice of bytes representing the name.
- @TagType
+ {#header_close#}
+ {#header_open|@TagType#}
@TagType(T: type) -> type
For an enum, returns the integer type that is used to store the enumeration value.
@@ -4398,7 +4261,8 @@ test.zig:6:2: error: found compile log statement
For a union, returns the enum type that is used to store the tag value.
- @errorName
+ {#header_close#}
+ {#header_open|@errorName#}
@errorName(err: error) -> []u8
This function returns the string representation of an error. If an error
@@ -4413,14 +4277,16 @@ test.zig:6:2: error: found compile log statement
or all calls have a compile-time known value for err, then no
error name table will be generated.
- @errorReturnTrace
+ {#header_close#}
+ {#header_open|@errorReturnTrace#}
@errorReturnTrace() -> ?&builtin.StackTrace
If the binary is built with error return tracing, and this function is invoked in a
function that calls a function with an error or error union return type, returns a
stack trace object. Otherwise returns `null`.
- @fence
+ {#header_close#}
+ {#header_open|@fence#}
@fence(order: AtomicOrder)
The fence function is used to introduce happens-before edges between operations.
@@ -4432,13 +4298,15 @@ test.zig:6:2: error: found compile log statement
- @fieldParentPtr
+ {#header_close#}
+ {#header_open|@fieldParentPtr#}
@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
field_ptr: &T) -> &ParentType
Given a pointer to a field, returns the base pointer of a struct.
- @frameAddress
+ {#header_close#}
+ {#header_open|@frameAddress#}
@frameAddress()
This function returns the base pointer of the current stack frame.
@@ -4451,7 +4319,8 @@ test.zig:6:2: error: found compile log statement
This function is only valid within function scope.
- @import
+ {#header_close#}
+ {#header_open|@import#}
@import(comptime path: []u8) -> (namespace)
This function finds a zig file corresponding to path and imports all the
@@ -4474,7 +4343,8 @@ test.zig:6:2: error: found compile log statement
Compile Variables
@embedFile
- @inlineCall
+ {#header_close#}
+ {#header_open|@inlineCall#}
@inlineCall(function: X, args: ...) -> Y
This calls a function, in the same way that invoking an expression with parentheses does:
@@ -4493,17 +4363,20 @@ fn add(a: i32, b: i32) -> i32 { a + b }
- @intToPtr
+ {#header_close#}
+ {#header_open|@intToPtr#}
@intToPtr(comptime DestType: type, int: usize) -> DestType
Converts an integer to a pointer. To convert the other way, use @ptrToInt.
- @IntType
+ {#header_close#}
+ {#header_open|@IntType#}
@IntType(comptime is_signed: bool, comptime bit_count: u8) -> type
This function returns an integer type with the given signness and bit count.
- @maxValue
+ {#header_close#}
+ {#header_open|@maxValue#}
@maxValue(comptime T: type) -> (number literal)
This function returns the maximum value of the integer type T.
@@ -4511,7 +4384,8 @@ fn add(a: i32, b: i32) -> i32 { a + b }
The result is a compile time constant.
- @memberCount
+ {#header_close#}
+ {#header_open|@memberCount#}
@memberCount(comptime T: type) -> (number literal)
This function returns the number of enum values in an enum type.
@@ -4519,11 +4393,14 @@ fn add(a: i32, b: i32) -> i32 { a + b }
The result is a compile time constant.
- @memberName
+ {#header_close#}
+ {#header_open|@memberName#}
TODO
- @memberType
+ {#header_close#}
+ {#header_open|@memberType#}
TODO
- @memcpy
+ {#header_close#}
+ {#header_open|@memcpy#}
@memcpy(noalias dest: &u8, noalias source: &const u8, byte_count: usize)
This function copies bytes from one region of memory to another. dest and
@@ -4540,7 +4417,8 @@ fn add(a: i32, b: i32) -> i32 { a + b }
There is also a standard library function for this:
const mem = @import("std").mem;
mem.copy(u8, dest[0...byte_count], source[0...byte_count]);
- @memset
+ {#header_close#}
+ {#header_open|@memset#}
@memset(dest: &u8, c: u8, byte_count: usize)
This function sets a region of memory to c. dest is a pointer.
@@ -4556,7 +4434,8 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);
There is also a standard library function for this:
const mem = @import("std").mem;
mem.set(u8, dest, c);
- @minValue
+ {#header_close#}
+ {#header_open|@minValue#}
@minValue(comptime T: type) -> (number literal)
This function returns the minimum value of the integer type T.
@@ -4564,7 +4443,8 @@ mem.set(u8, dest, c);
The result is a compile time constant.
- @mod
+ {#header_close#}
+ {#header_open|@mod#}
@mod(numerator: T, denominator: T) -> T
Modulus division. For unsigned integers this is the same as
@@ -4579,14 +4459,16 @@ mem.set(u8, dest, c);
@rem
@import("std").math.mod
- @mulWithOverflow
+ {#header_close#}
+ {#header_open|@mulWithOverflow#}
@mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool
Performs *result = a * b. If overflow or underflow occurs,
stores the overflowed bits in result and returns true.
If no overflow or underflow occurs, returns false.
- @noInlineCall
+ {#header_close#}
+ {#header_open|@noInlineCall#}
@noInlineCall(function: var, args: ...) -> var
This calls a function, in the same way that invoking an expression with parentheses does:
@@ -4605,12 +4487,14 @@ fn add(a: i32, b: i32) -> i32 { a + b }
- @offsetOf
+ {#header_close#}
+ {#header_open|@offsetOf#}
@offsetOf(comptime T: type, comptime field_name: [] const u8) -> (number literal)
This function returns the byte offset of a field relative to its containing struct.
- @OpaqueType
+ {#header_close#}
+ {#header_open|@OpaqueType#}
@OpaqueType() -> type
Creates a new type with an unknown size and alignment.
@@ -4630,7 +4514,8 @@ export fn foo(w: &Wat) {
test.zig:5:9: error: expected type '&Derp', found '&Wat'
bar(w);
^
-
@panic
+ {#header_close#}
+ {#header_open|@panic#}
@panic(message: []const u8) -> noreturn
Invokes the panic handler function. By default the panic handler function
@@ -4649,12 +4534,14 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
Root Source File
- @ptrCast
+ {#header_close#}
+ {#header_open|@ptrCast#}
@ptrCast(comptime DestType: type, value: var) -> DestType
Converts a pointer of one type to a pointer of another type.
- @ptrToInt
+ {#header_close#}
+ {#header_open|@ptrToInt#}
@ptrToInt(value: var) -> usize
Converts value to a usize which is the address of the pointer. value can be one of these types:
@@ -4667,7 +4554,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
To convert the other way, use @intToPtr
- @rem
+ {#header_close#}
+ {#header_open|@rem#}
@rem(numerator: T, denominator: T) -> T
Remainder division. For unsigned integers this is the same as
@@ -4682,7 +4570,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
@mod
@import("std").math.rem
- @returnAddress
+ {#header_close#}
+ {#header_open|@returnAddress#}
@returnAddress()
This function returns a pointer to the return address of the current stack
@@ -4696,13 +4585,15 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
This function is only valid within function scope.
- @setDebugSafety
+ {#header_close#}
+ {#header_open|@setDebugSafety#}
@setDebugSafety(scope, safety_on: bool)
Sets whether debug safety checks are on for a given scope.
- @setEvalBranchQuota
+ {#header_close#}
+ {#header_open|@setEvalBranchQuota#}
@setEvalBranchQuota(new_quota: usize)
Changes the maximum number of backwards branches that compile-time code
@@ -4737,7 +4628,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
comptime
- @setFloatMode
+ {#header_close#}
+ {#header_open|@setFloatMode#}
@setFloatMode(scope, mode: @import("builtin").FloatMode)
Sets the floating point mode for a given scope. Possible values are:
@@ -4768,7 +4660,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
Floating Point Operations
- @setGlobalLinkage
+ {#header_close#}
+ {#header_open|@setGlobalLinkage#}
@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage)
GlobalLinkage can be found with @import("builtin").GlobalLinkage.
@@ -4777,12 +4670,14 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
- @setGlobalSection
+ {#header_close#}
+ {#header_open|@setGlobalSection#}
@setGlobalSection(global_variable_name, comptime section_name: []const u8) -> bool
Puts the global variable in the specified section.
- @shlExact
+ {#header_close#}
+ {#header_open|@shlExact#}
@shlExact(value: T, shift_amt: Log2T) -> T
Performs the left shift operation (<<). Caller guarantees
@@ -4797,7 +4692,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
@shrExact
@shlWithOverflow
- @shlWithOverflow
+ {#header_close#}
+ {#header_open|@shlWithOverflow#}
@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -> bool
Performs *result = a << b. If overflow or underflow occurs,
@@ -4813,7 +4709,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
@shlExact
@shrExact
- @shrExact
+ {#header_close#}
+ {#header_open|@shrExact#}
@shrExact(value: T, shift_amt: Log2T) -> T
Performs the right shift operation (>>). Caller guarantees
@@ -4827,7 +4724,8 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
- @sizeOf
+ {#header_close#}
+ {#header_open|@sizeOf#}
@sizeOf(comptime T: type) -> (number literal)
This function returns the number of bytes it takes to store T in memory.
@@ -4835,14 +4733,16 @@ test.zig:5:9: error: expected type '&Derp', found '&Wat'
The result is a target-specific compile time constant.
- @subWithOverflow
+ {#header_close#}
+ {#header_open|@subWithOverflow#}
@subWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool
Performs *result = a - b. If overflow or underflow occurs,
stores the overflowed bits in result and returns true.
If no overflow or underflow occurs, returns false.
- @truncate
+ {#header_close#}
+ {#header_open|@truncate#}
@truncate(comptime T: type, integer) -> T
This function truncates bits from an integer type, resulting in a smaller
@@ -4865,7 +4765,8 @@ const b: u8 = @truncate(u8, a);
of endianness on the target platform.
- @typeId
+ {#header_close#}
+ {#header_open|@typeId#}
@typeId(comptime T: type) -> @import("builtin").TypeId
Returns which kind of type something is. Possible values:
@@ -4898,20 +4799,24 @@ const b: u8 = @truncate(u8, a);
Opaque,
};
-
@typeName
+ {#header_close#}
+ {#header_open|@typeName#}
@typeName(T: type) -> []u8
This function returns the string representation of a type.
- @typeOf
+ {#header_close#}
+ {#header_open|@typeOf#}
@typeOf(expression) -> type
This function returns a compile-time constant, which is the type of the
expression passed as an argument. The expression is evaluated.
- Build Mode
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Build Mode#}
Zig has three build modes:
@@ -4935,21 +4840,23 @@ pub fn build(b: &Builder) {
-Drelease-safe=(bool) optimizations on and safety on
-Drelease-fast=(bool) optimizations on and safety off
- Debug
+ {#header_open|Debug#}
$ zig build-exe example.zig
- Fast compilation speed
- Safety checks enabled
- Slow runtime performance
- ReleaseFast
+ {#header_close#}
+ {#header_open|ReleaseFast#}
$ zig build-exe example.zig --release-fast
- Fast runtime performance
- Safety checks disabled
- Slow compilation speed
- ReleaseSafe
+ {#header_close#}
+ {#header_open|ReleaseSafe#}
$ zig build-exe example.zig --release-safe
- Medium runtime performance
@@ -4962,7 +4869,9 @@ pub fn build(b: &Builder) {
- Zig Build System
- Undefined Behavior
- Undefined Behavior
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Undefined Behavior#}
Zig has many instances of undefined behavior. If undefined behavior is
detected at compile-time, Zig emits an error. Most undefined behavior that
@@ -5000,7 +4909,7 @@ Test 1/1 safety check...reached unreachable code
Tests failed. Use the following command to reproduce the failure:
./test
-
Reaching Unreachable Code
+ {#header_open|Reaching Unreachable Code#}
At compile-time:
comptime {
assert(false);
@@ -5019,7 +4928,8 @@ fn assert(ok: bool) {
comptime {
^
At runtime crashes with the message reached unreachable code and a stack trace.
- Index out of Bounds
+ {#header_close#}
+ {#header_open|Index out of Bounds#}
At compile-time:
comptime {
const array = "hello";
@@ -5030,7 +4940,8 @@ comptime {
const garbage = array[5];
^
At runtime crashes with the message index out of bounds and a stack trace.
- Cast Negative Number to Unsigned Integer
+ {#header_close#}
+ {#header_open|Cast Negative Number to Unsigned Integer#}
At compile-time:
comptime {
const value: i32 = -1;
@@ -5044,7 +4955,8 @@ comptime {
If you are trying to obtain the maximum value of an unsigned integer, use @maxValue(T),
where T is the integer type, such as u32.
- Cast Truncates Data
+ {#header_close#}
+ {#header_open|Cast Truncates Data#}
At compile-time:
comptime {
const spartan_count: u16 = 300;
@@ -5060,8 +4972,9 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
where T is the integer type, such as u32, and value
is the value you want to truncate.
- Integer Overflow
- Default Operations
+ {#header_close#}
+ {#header_open|Integer Overflow#}
+ {#header_open|Default Operations#}
The following operators can cause integer overflow:
+ (addition)
@@ -5083,7 +4996,8 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
byte += 1;
^
At runtime crashes with the message integer overflow and a stack trace.
- Standard Library Math Functions
+ {#header_close#}
+ {#header_open|Standard Library Math Functions#}
These functions provided by the standard library return possible errors.
@import("std").math.add
@@ -5112,7 +5026,8 @@ pub fn main() -> %void {
$ zig build-exe test.zig
$ ./test
unable to add one: Overflow
- Builtin Overflow Functions
+ {#header_close#}
+ {#header_open|Builtin Overflow Functions#}
These builtins return a bool of whether or not overflow
occurred, as well as returning the overflowed bits:
@@ -5140,7 +5055,8 @@ pub fn main() -> %void {
$ zig build-exe test.zig
$ ./test
overflowed result: 9
- Wrapping Operations
+ {#header_close#}
+ {#header_open|Wrapping Operations#}
These operations have guaranteed wraparound semantics.
@@ -5159,7 +5075,9 @@ test "wraparound addition and subtraction" {
const max_val = min_val -% 1;
assert(max_val == @maxValue(i32));
}
- Exact Left Shift Overflow
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Exact Left Shift Overflow#}
At compile-time:
comptime {
const x = @shlExact(u8(0b01010101), 2);
@@ -5169,7 +5087,8 @@ test "wraparound addition and subtraction" {
const x = @shlExact(u8(0b01010101), 2);
^
At runtime crashes with the message left shift overflowed bits and a stack trace.
- Exact Right Shift Overflow
+ {#header_close#}
+ {#header_open|Exact Right Shift Overflow#}
At compile-time:
comptime {
const x = @shrExact(u8(0b10101010), 2);
@@ -5179,7 +5098,8 @@ test "wraparound addition and subtraction" {
const x = @shrExact(u8(0b10101010), 2);
^
At runtime crashes with the message right shift overflowed bits and a stack trace.
- Division by Zero
+ {#header_close#}
+ {#header_open|Division by Zero#}
At compile-time:
comptime {
const a: i32 = 1;
@@ -5192,7 +5112,8 @@ test "wraparound addition and subtraction" {
^
At runtime crashes with the message division by zero and a stack trace.
- Remainder Division by Zero
+ {#header_close#}
+ {#header_open|Remainder Division by Zero#}
At compile-time:
comptime {
const a: i32 = 10;
@@ -5205,11 +5126,14 @@ test "wraparound addition and subtraction" {
^
At runtime crashes with the message remainder division by zero and a stack trace.
- Exact Division Remainder
+ {#header_close#}
+ {#header_open|Exact Division Remainder#}
TODO
- Slice Widen Remainder
+ {#header_close#}
+ {#header_open|Slice Widen Remainder#}
TODO
- Attempt to Unwrap Null
+ {#header_close#}
+ {#header_open|Attempt to Unwrap Null#}
At compile-time:
comptime {
const nullable_number: ?i32 = null;
@@ -5235,7 +5159,8 @@ pub fn main() -> %void {
% zig build-exe test.zig
$ ./test
it's null
- Attempt to Unwrap Error
+ {#header_close#}
+ {#header_open|Attempt to Unwrap Error#}
At compile-time:
comptime {
const number = %%getNumberOrFail();
@@ -5274,7 +5199,8 @@ fn getNumberOrFail() -> %i32 {
$ ./test
got error: UnableToReturnNumber
- Invalid Error Code
+ {#header_close#}
+ {#header_open|Invalid Error Code#}
At compile-time:
error AnError;
comptime {
@@ -5287,16 +5213,21 @@ comptime {
const invalid_err = error(number);
^
At runtime crashes with the message invalid error code and a stack trace.
- Invalid Enum Cast
+ {#header_close#}
+ {#header_open|Invalid Enum Cast#}
TODO
- Incorrect Pointer Alignment
+ {#header_close#}
+ {#header_open|Incorrect Pointer Alignment#}
TODO
- Wrong Union Field Access
+ {#header_close#}
+ {#header_open|Wrong Union Field Access#}
TODO
- Memory
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Memory#}
TODO: explain no default allocator in zig
TODO: show how to use the allocator interface
TODO: mention debug allocator
@@ -5308,7 +5239,8 @@ comptime {
Pointers
- Compile Variables
+ {#header_close#}
+ {#header_open|Compile Variables#}
Compile variables are accessible by importing the "builtin" package,
which the compiler makes available to every Zig source file. It contains
@@ -5478,7 +5410,8 @@ pub const link_libs = [][]const u8 {
- Root Source File
+ {#header_close#}
+ {#header_open|Root Source File#}
TODO: explain how root source file finds other files
TODO: pub fn main
TODO: pub fn panic
@@ -5486,17 +5419,20 @@ pub const link_libs = [][]const u8 {
TODO: order independent top level declarations
TODO: lazy analysis
TODO: using comptime { _ = @import() }
- Zig Test
+ {#header_close#}
+ {#header_open|Zig Test#}
TODO: basic usage
TODO: lazy analysis
TODO: --test-filter
TODO: --test-name-prefix
TODO: testing in releasefast and releasesafe mode. assert still works
- Zig Build System
+ {#header_close#}
+ {#header_open|Zig Build System#}
TODO: explain purpose, it's supposed to replace make/cmake
TODO: example of building a zig executable
TODO: example of building a C library
- C
+ {#header_close#}
+ {#header_open|C#}
Although Zig is independent of C, and, unlike most other languages, does not depend on libc,
Zig acknowledges the importance of interacting with existing C code.
@@ -5504,7 +5440,7 @@ pub const link_libs = [][]const u8 {
There are a few ways that Zig facilitates C interop.
- C Type Primitives
+ {#header_open|C Type Primitives#}
These have guaranteed C ABI compatibility and can be used like any other type.
@@ -5524,7 +5460,8 @@ pub const link_libs = [][]const u8 {
- C String Literals
+ {#header_close#}
+ {#header_open|C String Literals#}
extern fn puts(&const u8);
pub fn main() -> %void {
@@ -5539,7 +5476,8 @@ pub fn main() -> %void {
- Import from C Header File
+ {#header_close#}
+ {#header_open|Import from C Header File#}
The @cImport builtin function can be used
to directly import symbols from .h files:
@@ -5574,11 +5512,13 @@ const c = @cImport({
@cUndef
@import
- Mixing Object Files
+ {#header_close#}
+ {#header_open|Mixing Object Files#}
You can mix Zig object files with any other object files that respect the C ABI. Example:
- base64.zig
+ {#header_close#}
+ {#header_open|base64.zig#}
const base64 = @import("std").base64;
export fn decode_base_64(dest_ptr: &u8, dest_len: usize,
@@ -5592,7 +5532,7 @@ export fn decode_base_64(dest_ptr: &u8, dest_len: usize,
return decoded_size;
}
- test.c
+{{teheader_open:st.c}}
// This header is generated by zig from base64.zig
#include "base64.h"
@@ -5609,7 +5549,8 @@ int main(int argc, char **argv) {
return 0;
}
- build.zig
+ {#header_close#}
+ {#header_open|build.zig#}
const Builder = @import("std").build.Builder;
pub fn build(b: &Builder) {
@@ -5625,7 +5566,8 @@ pub fn build(b: &Builder) {
b.default_step.dependOn(&exe.step);
}
- Terminal
+ {#header_close#}
+ {#header_open|Terminal#}
$ zig build
$ ./test
all your base are belong to us
@@ -5634,7 +5576,9 @@ all your base are belong to us
Targets
Zig Build System
- Targets
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Targets#}
Zig supports generating code for all targets that LLVM supports. Here is
what it looks like to execute zig targets on a Linux x86_64
@@ -5760,14 +5704,15 @@ Environments:
Linux x86_64. Not all standard library code requires operating system abstractions, however,
so things such as generic data structures work an all above platforms.
- Style Guide
+ {#header_close#}
+ {#header_open|Style Guide#}
These coding conventions are not enforced by the compiler, but they are shipped in
this documentation along with the compiler in order to provide a point of
reference, should anyone wish to point to an authority on agreed upon Zig
coding style.
- Whitespace
+ {#header_open|Whitespace#}
-
4 space indentation
@@ -5782,7 +5727,8 @@ coding style.
Line length: aim for 100; use common sense.
- Names
+ {#header_close#}
+ {#header_open|Names#}
Roughly speaking: camelCaseFunctionName, TitleCaseTypeName,
snake_case_variable_name. More precisely:
@@ -5816,7 +5762,8 @@ coding style.
do what makes sense. For example, if there is an established convention such as
ENOENT, follow the established convention.
- Examples
+ {#header_close#}
+ {#header_open|Examples#}
const namespace_name = @import("dir_name/file_name.zig");
var global_var: i32 = undefined;
const const_name = 42;
@@ -5858,7 +5805,9 @@ fn readU32Be() -> u32 {}
See the Zig Standard Library for more examples.
- Grammar
+ {#header_close#}
+ {#header_close#}
+ {#header_open|Grammar#}
Root = many(TopLevelItem) EOF
TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
@@ -6010,7 +5959,8 @@ KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "u
ContainerDecl = option("extern" | "packed")
("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
"{" many(ContainerMember) "}"
- Zen
+ {#header_close#}
+ {#header_open|Zen#}
- Communicate intent precisely.
- Edge cases matter.
@@ -6024,8 +5974,10 @@ ContainerDecl = option("extern" | "packed")
- Minimize energy spent on coding style.
- Together we serve end users.
- TODO
+ {#header_close#}
+ {#header_open|TODO#}
TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)
+ {#header_close#}
diff --git a/std/hash_map.zig b/std/hash_map.zig
index f91e4b31ba..e3c968146e 100644
--- a/std/hash_map.zig
+++ b/std/hash_map.zig
@@ -62,8 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
.allocator = allocator,
.size = 0,
.max_distance_from_start_index = 0,
- // it doesn't actually matter what we set this to since we use wrapping integer arithmetic
- .modification_count = undefined,
+ .modification_count = if (want_modification_safety) 0 else {},
};
}