authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-07 03:22:27-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-07 03:22:27-05:00
log4543413491078c53d24115c5229989cda05cb1a5
treef4ff1922be22c9ac8d9bf80801abeb67afdfa1af
parent634e8713c394bacfe080d03256d1dd4f9a43dd8c

std.io: introduce buffered I/O and change API

I started working on #465 and made some corresponding std.io API changes. New structs: * std.io.FileInStream * std.io.FileOutStream * std.io.BufferedOutStream * std.io.BufferedInStream Removed: * std.io.File.in_stream * std.io.File.out_stream Now instead of &file.out_stream or &file.in_stream to get access to the stream API for a file, you get it like this: var file_in_stream = io.FileInStream.init(&file); const in_stream = &file_in_stream.stream; var file_out_stream = io.FileOutStream.init(&file); const out_stream = &file_out_stream.stream; This is evidence that we might not need any OOP features - See #130.

18 files changed, 7052 insertions(+), 197 deletions(-)

build.zig+25
......@@ -1,13 +1,36 @@
11const Builder = @import("std").build.Builder;
22const tests = @import("test/tests.zig");
3const os = @import("std").os;
34
45pub fn build(b: &Builder) {
56 const mode = b.standardReleaseOptions();
67
8 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
9
10 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 {
11 docgen_exe.getOutputPath(),
12 "doc/langref.html.in",
13 %%os.path.join(b.allocator, b.cache_root, "langref.html"),
14 });
15 docgen_cmd.step.dependOn(&docgen_exe.step);
16
17 var docgen_home_cmd = b.addCommand(null, b.env_map, [][]const u8 {
18 docgen_exe.getOutputPath(),
19 "doc/home.html.in",
20 %%os.path.join(b.allocator, b.cache_root, "home.html"),
21 });
22 docgen_home_cmd.step.dependOn(&docgen_exe.step);
23
24 const docs_step = b.step("docs", "Build documentation");
25 docs_step.dependOn(&docgen_cmd.step);
26 docs_step.dependOn(&docgen_home_cmd.step);
27
728 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
829 exe.setBuildMode(mode);
930 exe.linkSystemLibrary("c");
31
1032 b.default_step.dependOn(&exe.step);
33 b.default_step.dependOn(docs_step);
1134
1235 b.installArtifact(exe);
1336
......@@ -16,6 +39,8 @@ pub fn build(b: &Builder) {
1639 const with_lldb = b.option(bool, "with-lldb", "Run tests in LLDB to get a backtrace if one fails") ?? false;
1740 const test_step = b.step("test", "Run all the tests");
1841
42 test_step.dependOn(docs_step);
43
1944 test_step.dependOn(tests.addPkgTests(b, test_filter,
2045 "test/behavior.zig", "behavior", "Run the behavior tests",
2146 with_lldb));
doc/docgen.zig created+63
......@@ -0,0 +1,63 @@
1const std = @import("std");
2const io = std.io;
3const os = std.os;
4
5pub fn main() -> %void {
6 // TODO use a more general purpose allocator here
7 var inc_allocator = %%std.heap.IncrementingAllocator.init(5 * 1024 * 1024);
8 defer inc_allocator.deinit();
9 const allocator = &inc_allocator.allocator;
10
11 var args_it = os.args();
12
13 if (!args_it.skip()) @panic("expected self arg");
14
15 const in_file_name = %%(args_it.next(allocator) ?? @panic("expected input arg"));
16 defer allocator.free(in_file_name);
17
18 const out_file_name = %%(args_it.next(allocator) ?? @panic("expected output arg"));
19 defer allocator.free(out_file_name);
20
21 var in_file = %%io.File.openRead(in_file_name, allocator);
22 defer in_file.close();
23
24 var out_file = %%io.File.openWrite(out_file_name, allocator);
25 defer out_file.close();
26
27 var file_in_stream = io.FileInStream.init(&in_file);
28 var buffered_in_stream = io.BufferedInStream.init(&file_in_stream.stream);
29
30 var file_out_stream = io.FileOutStream.init(&out_file);
31 var buffered_out_stream = io.BufferedOutStream.init(&file_out_stream.stream);
32
33 gen(&buffered_in_stream.stream, &buffered_out_stream.stream);
34 %%buffered_out_stream.flush();
35
36}
37
38const State = enum {
39 Start,
40 Derp,
41};
42
43// TODO look for code segments
44
45fn gen(in: &io.InStream, out: &const io.OutStream) {
46 var state = State.Start;
47 while (true) {
48 const byte = in.readByte() %% |err| {
49 if (err == error.EndOfStream) {
50 return;
51 }
52 std.debug.panic("{}", err)
53 };
54 switch (state) {
55 State.Start => switch (byte) {
56 else => {
57 %%out.writeByte(byte);
58 },
59 },
60 State.Derp => unreachable,
61 }
62 }
63}
doc/home.html.in created+719
......@@ -0,0 +1,719 @@
1<!doctype html>
2<html>
3 <head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
6 <title>The Zig Programming Language</title>
7 <link rel="stylesheet" type="text/css" href="highlight/styles/default.css">
8 <style type="text/css">
9 img {
10 max-width: 100%;
11 }
12 </style>
13 </head>
14 <body>
15 <img src="zig-logo.svg">
16 <p>
17 Zig is an open-source programming language designed for <strong>robustness</strong>,
18 <strong>optimality</strong>, and <strong>clarity</strong>.
19 </p>
20 <p>
21 <a href="download/">Download</a> |
22 <a href="documentation/master/">Documentation</a> |
23 <a href="https://github.com/zig-lang/zig">Source Code</a> |
24 <a href="https://github.com/zig-lang/zig/issues">Bug Tracker</a> |
25 <a href="https://webchat.freenode.net/?channels=%23zig">IRC</a> |
26 <a href="https://www.patreon.com/andrewrk">Donate $1/month</a>
27 </p>
28 <h2>Feature Highlights</h2>
29 <ul>
30 <li>Manual memory management. Memory allocation failure is handled correctly. Edge cases matter!</li>
31 <li>Zig competes with C instead of depending on it. The Zig Standard Library does not depend on libc.</li>
32 <li>Small, simple language. Focus on debugging your application rather than debugging your knowledge of your programming language.</li>
33 <li>A fresh take on error handling that resembles what well-written C error handling looks like,
34 minus the boilerplate and verbosity.</li>
35 <li>Debug mode optimizes for fast compilation time and crashing with a stack trace when undefined behavior
36 <em>would</em> happen.</li>
37 <li>ReleaseFast mode produces heavily optimized code. What other projects call
38 "Link Time Optimization" Zig does automatically.</li>
39 <li>ReleaseSafe mode produces optimized code but keeps safety checks enabled. Disable safety checks in the bottlenecks of your code.</li>
40 <li>Generic data structures and functions.</li>
41 <li>Compile-time reflection and compile-time code execution.</li>
42 <li>Import .h files and directly use C types, variables, and functions.</li>
43 <li>Export functions, variables, and types for C code to depend on. Automatically generate .h files.</li>
44 <li>Nullable type instead of null pointers.</li>
45 <li>Order independent top level declarations.</li>
46 <li>Friendly toward package maintainers. Reproducible build, bootstrapping process carefully documented. Issues filed by package maintainers are considered especially important.</li>
47 <li>Cross-compiling is a first-class use case.</li>
48 <li>No preprocessor. Instead Zig has a few carefully designed features that
49 provide a way to accomplish things you might do with a preprocessor.</li>
50 </ul>
51 <h2 id="reading-material">Reading Material</h2>
52 <ul>
53 <li>2017-10-17 - <a href="download/0.1.1/release-notes.html">Zig 0.1.1 Release Notes</a></li>
54 <li>2017-07-19 - <a href="http://tiehuis.github.io/iterative-replacement-of-c-with-zig">Iterative Replacement of C with Zig</a></li>
55 <li>2017-02-16 - <a href="http://andrewkelley.me/post/a-better-way-to-implement-bit-fields.html">A Better Way to Implement Bit-Fields</a></li>
56 <li>2017-02-13 - <a href="http://andrewkelley.me/post/zig-already-more-knowable-than-c.html">Zig: Already More Knowable Than C</a></li>
57 <li>2017-01-30 - <a href="http://andrewkelley.me/post/zig-programming-language-blurs-line-compile-time-run-time.html">Zig Programming Language Blurs the Line Between Compile-Time and Run-Time</a></li>
58 <li>2016-02-08 - <a href="http://andrewkelley.me/post/intro-to-zig.html">Introduction to the Zig Programming Language</a></li>
59 </ul>
60 <h2 id="source-examples">Source Code Examples</h2>
61 <ul>
62 <li><a href="#hello">Hello World</a></li>
63 <li><a href="#hello_libc">Hello World with libc</a></li>
64 <li><a href="#parse">Parsing Unsigned Integers</a></li>
65 <li><a href="#hashmap">HashMap with Custom Allocator</a></li>
66 <li><a href="#tetris">Tetris Clone</a></li>
67 <li><a href="#clashos">Bare Bones Operating System</a></li>
68 <li><a href="#cat">Cat Utility</a></li>
69 <li><a href="#multiline-strings">Multiline String Syntax</a></li>
70 <li><a href="#mersenne">Mersenne Twister Random Number Generator</a></li>
71 </ul>
72 <h3 id="hello">Hello World</h3>
73 <pre><code class="zig">const io = @import("std").io;
74
75pub fn main() -&gt; %void {
76 %return io.stdout.printf("Hello, world!\n");
77}</code></pre>
78 <p>Build this with:</p>
79 <pre>zig build-exe hello.zig</pre>
80 <h3 id="hello_libc">Hello World with libc</h3>
81 <pre><code class="zig">const c = @cImport({
82 // See https://github.com/zig-lang/zig/issues/515
83 @cDefine("_NO_CRT_STDIO_INLINE", "1");
84 @cInclude("stdio.h");
85 @cInclude("string.h");
86});
87
88const msg = c"Hello, world!\n";
89
90export fn main(argc: c_int, argv: &amp;&amp;u8) -&gt; c_int {
91 if (c.printf(msg) != c_int(c.strlen(msg)))
92 return -1;
93
94 return 0;
95}</code></pre>
96 <p>Build this with:</p>
97 <pre>zig build-exe hello.zig --library c</pre>
98 <h3 id="parse">Parsing Unsigned Integers</h3>
99 <pre><code class="zig">pub fn parseUnsigned(comptime T: type, buf: []u8, radix: u8) -&gt; %T {
100 var x: T = 0;
101
102 for (buf) |c| {
103 const digit = %return charToDigit(c, radix);
104 x = %return mulOverflow(T, x, radix);
105 x = %return addOverflow(T, x, digit);
106 }
107
108 return x;
109}
110
111error InvalidChar;
112
113fn charToDigit(c: u8, radix: u8) -&gt; %u8 {
114 const value = switch (c) {
115 '0' ... '9' =&gt; c - '0',
116 'A' ... 'Z' =&gt; c - 'A' + 10,
117 'a' ... 'z' =&gt; c - 'a' + 10,
118 else =&gt; return error.InvalidChar,
119 };
120
121 if (value &gt;= radix)
122 return error.InvalidChar;
123
124 return value;
125}
126
127error Overflow;
128
129pub fn mulOverflow(comptime T: type, a: T, b: T) -&gt; %T {
130 var answer: T = undefined;
131 if (@mulWithOverflow(T, a, b, &amp;answer)) error.Overflow else answer
132}
133
134pub fn addOverflow(comptime T: type, a: T, b: T) -&gt; %T {
135 var answer: T = undefined;
136 if (@addWithOverflow(T, a, b, &amp;answer)) error.Overflow else answer
137}
138
139fn getNumberWithDefault(s: []u8) -&gt; u32 {
140 parseUnsigned(u32, s, 10) %% 42
141}
142
143fn getNumberOrCrash(s: []u8) -&gt; u32 {
144 %%parseUnsigned(u32, s, 10)
145}
146
147fn addTwoTogetherOrReturnErr(a_str: []u8, b_str: []u8) -&gt; %u32 {
148 const a = parseUnsigned(u32, a_str, 10) %% |err| return err;
149 const b = parseUnsigned(u32, b_str, 10) %% |err| return err;
150 return a + b;
151}</code></pre>
152 <h3 id="hashmap">HashMap with Custom Allocator</h3>
153 <pre><code class="zig">const debug = @import(&quot;debug.zig&quot;);
154const assert = debug.assert;
155const math = @import(&quot;math.zig&quot;);
156const mem = @import(&quot;mem.zig&quot;);
157const Allocator = mem.Allocator;
158
159const want_modification_safety = !@compileVar(&quot;is_release&quot;);
160const debug_u32 = if (want_modification_safety) u32 else void;
161
162pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K)-&gt;u32,
163 comptime eql: fn(a: K, b: K)-&gt;bool) -&gt; type
164{
165 struct {
166 entries: []Entry,
167 size: usize,
168 max_distance_from_start_index: usize,
169 allocator: &amp;Allocator,
170 // this is used to detect bugs where a hashtable is edited while an iterator is running.
171 modification_count: debug_u32,
172
173 const Self = this;
174
175 pub const Entry = struct {
176 used: bool,
177 distance_from_start_index: usize,
178 key: K,
179 value: V,
180 };
181
182 pub const Iterator = struct {
183 hm: &amp;Self,
184 // how many items have we returned
185 count: usize,
186 // iterator through the entry array
187 index: usize,
188 // used to detect concurrent modification
189 initial_modification_count: debug_u32,
190
191 pub fn next(it: &amp;Iterator) -&gt; ?&amp;Entry {
192 if (want_modification_safety) {
193 assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
194 }
195 if (it.count &gt;= it.hm.size) return null;
196 while (it.index &lt; it.hm.entries.len) : (it.index += 1) {
197 const entry = &amp;it.hm.entries[it.index];
198 if (entry.used) {
199 it.index += 1;
200 it.count += 1;
201 return entry;
202 }
203 }
204 unreachable // no next item
205 }
206 };
207
208 pub fn init(hm: &amp;Self, allocator: &amp;Allocator) {
209 hm.entries = []Entry{};
210 hm.allocator = allocator;
211 hm.size = 0;
212 hm.max_distance_from_start_index = 0;
213 // it doesn't actually matter what we set this to since we use wrapping integer arithmetic
214 hm.modification_count = undefined;
215 }
216
217 pub fn deinit(hm: &amp;Self) {
218 hm.allocator.free(Entry, hm.entries);
219 }
220
221 pub fn clear(hm: &amp;Self) {
222 for (hm.entries) |*entry| {
223 entry.used = false;
224 }
225 hm.size = 0;
226 hm.max_distance_from_start_index = 0;
227 hm.incrementModificationCount();
228 }
229
230 pub fn put(hm: &amp;Self, key: K, value: V) -&gt; %void {
231 if (hm.entries.len == 0) {
232 %return hm.initCapacity(16);
233 }
234 hm.incrementModificationCount();
235
236 // if we get too full (60%), double the capacity
237 if (hm.size * 5 &gt;= hm.entries.len * 3) {
238 const old_entries = hm.entries;
239 %return hm.initCapacity(hm.entries.len * 2);
240 // dump all of the old elements into the new table
241 for (old_entries) |*old_entry| {
242 if (old_entry.used) {
243 hm.internalPut(old_entry.key, old_entry.value);
244 }
245 }
246 hm.allocator.free(Entry, old_entries);
247 }
248
249 hm.internalPut(key, value);
250 }
251
252 pub fn get(hm: &amp;Self, key: K) -&gt; ?&amp;Entry {
253 return hm.internalGet(key);
254 }
255
256 pub fn remove(hm: &amp;Self, key: K) {
257 hm.incrementModificationCount();
258 const start_index = hm.keyToIndex(key);
259 {var roll_over: usize = 0; while (roll_over &lt;= hm.max_distance_from_start_index) : (roll_over += 1) {
260 const index = (start_index + roll_over) % hm.entries.len;
261 var entry = &amp;hm.entries[index];
262
263 assert(entry.used); // key not found
264
265 if (!eql(entry.key, key)) continue;
266
267 while (roll_over &lt; hm.entries.len) : (roll_over += 1) {
268 const next_index = (start_index + roll_over + 1) % hm.entries.len;
269 const next_entry = &amp;hm.entries[next_index];
270 if (!next_entry.used or next_entry.distance_from_start_index == 0) {
271 entry.used = false;
272 hm.size -= 1;
273 return;
274 }
275 *entry = *next_entry;
276 entry.distance_from_start_index -= 1;
277 entry = next_entry;
278 }
279 unreachable // shifting everything in the table
280 }}
281 unreachable // key not found
282 }
283
284 pub fn entryIterator(hm: &amp;Self) -&gt; Iterator {
285 return Iterator {
286 .hm = hm,
287 .count = 0,
288 .index = 0,
289 .initial_modification_count = hm.modification_count,
290 };
291 }
292
293 fn initCapacity(hm: &amp;Self, capacity: usize) -&gt; %void {
294 hm.entries = %return hm.allocator.alloc(Entry, capacity);
295 hm.size = 0;
296 hm.max_distance_from_start_index = 0;
297 for (hm.entries) |*entry| {
298 entry.used = false;
299 }
300 }
301
302 fn incrementModificationCount(hm: &amp;Self) {
303 if (want_modification_safety) {
304 hm.modification_count +%= 1;
305 }
306 }
307
308 fn internalPut(hm: &amp;Self, orig_key: K, orig_value: V) {
309 var key = orig_key;
310 var value = orig_value;
311 const start_index = hm.keyToIndex(key);
312 var roll_over: usize = 0;
313 var distance_from_start_index: usize = 0;
314 while (roll_over &lt; hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1}) {
315 const index = (start_index + roll_over) % hm.entries.len;
316 const entry = &amp;hm.entries[index];
317
318 if (entry.used and !eql(entry.key, key)) {
319 if (entry.distance_from_start_index &lt; distance_from_start_index) {
320 // robin hood to the rescue
321 const tmp = *entry;
322 hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
323 distance_from_start_index);
324 *entry = Entry {
325 .used = true,
326 .distance_from_start_index = distance_from_start_index,
327 .key = key,
328 .value = value,
329 };
330 key = tmp.key;
331 value = tmp.value;
332 distance_from_start_index = tmp.distance_from_start_index;
333 }
334 continue;
335 }
336
337 if (!entry.used) {
338 // adding an entry. otherwise overwriting old value with
339 // same key
340 hm.size += 1;
341 }
342
343 hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
344 *entry = Entry {
345 .used = true,
346 .distance_from_start_index = distance_from_start_index,
347 .key = key,
348 .value = value,
349 };
350 return;
351 }
352 unreachable // put into a full map
353 }
354
355 fn internalGet(hm: &amp;Self, key: K) -&gt; ?&amp;Entry {
356 const start_index = hm.keyToIndex(key);
357 {var roll_over: usize = 0; while (roll_over &lt;= hm.max_distance_from_start_index) : (roll_over += 1) {
358 const index = (start_index + roll_over) % hm.entries.len;
359 const entry = &amp;hm.entries[index];
360
361 if (!entry.used) return null;
362 if (eql(entry.key, key)) return entry;
363 }}
364 return null;
365 }
366
367 fn keyToIndex(hm: &amp;Self, key: K) -&gt; usize {
368 return usize(hash(key)) % hm.entries.len;
369 }
370 }
371}
372
373test "basic hash map test" {
374 var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;
375 map.init(&amp;debug.global_allocator);
376 defer map.deinit();
377
378 %%map.put(1, 11);
379 %%map.put(2, 22);
380 %%map.put(3, 33);
381 %%map.put(4, 44);
382 %%map.put(5, 55);
383
384 assert((??map.get(2)).value == 22);
385 map.remove(2);
386 assert(if (const entry ?= map.get(2)) false else true);
387}
388
389fn hash_i32(x: i32) -&gt; u32 {
390 *(&amp;u32)(&amp;x)
391}
392fn eql_i32(a: i32, b: i32) -&gt; bool {
393 a == b
394}</code></pre>
395 <h3 id="tetris">Tetris Clone</h3>
396 <img src="tetris-screenshot.png">
397 <p>
398 <a href="https://github.com/andrewrk/tetris">Source Code on GitHub</a>
399 </p>
400 <h3 id="clashos">Bare Bones Operating System</h3>
401 <p>
402 <a href="https://github.com/andrewrk/clashos">Source Code on GitHub</a>
403 </p>
404 <h3 id="cat">Cat Utility</h3>
405 <pre><code class="zig">const std = @import("std");
406const io = std.io;
407const mem = std.mem;
408const os = std.os;
409
410pub fn main() -&gt; %void {
411 const exe = os.args.at(0);
412 var catted_anything = false;
413 var arg_i: usize = 1;
414 while (arg_i &lt; os.args.count()) : (arg_i += 1) {
415 const arg = os.args.at(arg_i);
416 if (mem.eql(u8, arg, "-")) {
417 catted_anything = true;
418 %return cat_stream(&amp;io.stdin);
419 } else if (arg[0] == '-') {
420 return usage(exe);
421 } else {
422 var is = io.InStream.open(arg, null) %% |err| {
423 %%io.stderr.printf("Unable to open file: {}\n", @errorName(err));
424 return err;
425 };
426 defer is.close();
427
428 catted_anything = true;
429 %return cat_stream(&amp;is);
430 }
431 }
432 if (!catted_anything) {
433 %return cat_stream(&amp;io.stdin);
434 }
435 %return io.stdout.flush();
436}
437
438fn usage(exe: []const u8) -&gt; %void {
439 %%io.stderr.printf("Usage: {} [FILE]...\n", exe);
440 return error.Invalid;
441}
442
443fn cat_stream(is: &amp;io.InStream) -&gt; %void {
444 var buf: [1024 * 4]u8 = undefined;
445
446 while (true) {
447 const bytes_read = is.read(buf[0..]) %% |err| {
448 %%io.stderr.printf("Unable to read from stream: {}\n", @errorName(err));
449 return err;
450 };
451
452 if (bytes_read == 0) {
453 break;
454 }
455
456 io.stdout.write(buf[0..bytes_read]) %% |err| {
457 %%io.stderr.printf("Unable to write to stdout: {}\n", @errorName(err));
458 return err;
459 };
460 }
461}</code></pre>
462 <h3 id="multiline-strings">Multiline String Syntax</h3>
463 <pre><code class="zig">pub fn createAllShaders() -&gt; AllShaders {
464 var as : AllShaders = undefined;
465
466 as.primitive = createShader(
467 \\#version 150 core
468 \\
469 \\in vec3 VertexPosition;
470 \\
471 \\uniform mat4 MVP;
472 \\
473 \\void main(void) {
474 \\ gl_Position = vec4(VertexPosition, 1.0) * MVP;
475 \\}
476 ,
477 \\#version 150 core
478 \\
479 \\out vec4 FragColor;
480 \\
481 \\uniform vec4 Color;
482 \\
483 \\void main(void) {
484 \\ FragColor = Color;
485 \\}
486 , null);
487
488 as.primitive_attrib_position = as.primitive.attrib_location(c&quot;VertexPosition&quot;);
489 as.primitive_uniform_mvp = as.primitive.uniform_location(c&quot;MVP&quot;);
490 as.primitive_uniform_color = as.primitive.uniform_location(c&quot;Color&quot;);
491
492
493
494 as.texture = createShader(
495 \\#version 150 core
496 \\
497 \\in vec3 VertexPosition;
498 \\in vec2 TexCoord;
499 \\
500 \\out vec2 FragTexCoord;
501 \\
502 \\uniform mat4 MVP;
503 \\
504 \\void main(void)
505 \\{
506 \\ FragTexCoord = TexCoord;
507 \\ gl_Position = vec4(VertexPosition, 1.0) * MVP;
508 \\}
509 ,
510 \\#version 150 core
511 \\
512 \\in vec2 FragTexCoord;
513 \\out vec4 FragColor;
514 \\
515 \\uniform sampler2D Tex;
516 \\
517 \\void main(void)
518 \\{
519 \\ FragColor = texture(Tex, FragTexCoord);
520 \\}
521 , null);
522
523 as.texture_attrib_tex_coord = as.texture.attrib_location(c&quot;TexCoord&quot;);
524 as.texture_attrib_position = as.texture.attrib_location(c&quot;VertexPosition&quot;);
525 as.texture_uniform_mvp = as.texture.uniform_location(c&quot;MVP&quot;);
526 as.texture_uniform_tex = as.texture.uniform_location(c&quot;Tex&quot;);
527
528 debug_gl.assert_no_error();
529
530 return as;
531}</code></pre>
532 <h3 id="mersenne">Mersenne Twister Random Number Generator</h3>
533 <pre><code class="zig">const assert = @import(&quot;debug.zig&quot;).assert;
534const rand_test = @import(&quot;rand_test.zig&quot;);
535
536pub const MT19937_32 = MersenneTwister(
537 u32, 624, 397, 31,
538 0x9908B0DF,
539 11, 0xFFFFFFFF,
540 7, 0x9D2C5680,
541 15, 0xEFC60000,
542 18, 1812433253);
543
544pub const MT19937_64 = MersenneTwister(
545 u64, 312, 156, 31,
546 0xB5026F5AA96619E9,
547 29, 0x5555555555555555,
548 17, 0x71D67FFFEDA60000,
549 37, 0xFFF7EEE000000000,
550 43, 6364136223846793005);
551
552/// Use `init` to initialize this state.
553pub const Rand = struct {
554 const Rng = if (@sizeOf(usize) &gt;= 8) MT19937_64 else MT19937_32;
555
556 rng: Rng,
557
558 /// Initialize random state with the given seed.
559 pub fn init(r: &amp;Rand, seed: usize) {
560 r.rng.init(seed);
561 }
562
563 /// Get an integer with random bits.
564 pub fn scalar(r: &amp;Rand, comptime T: type) -&gt; T {
565 if (T == usize) {
566 return r.rng.get();
567 } else {
568 var result: [@sizeOf(T)]u8 = undefined;
569 r.fillBytes(result);
570 return ([]T)(result)[0];
571 }
572 }
573
574 /// Fill `buf` with randomness.
575 pub fn fillBytes(r: &amp;Rand, buf: []u8) {
576 var bytes_left = buf.len;
577 while (bytes_left &gt;= @sizeOf(usize)) {
578 ([]usize)(buf[buf.len - bytes_left...])[0] = r.rng.get();
579 bytes_left -= @sizeOf(usize);
580 }
581 if (bytes_left &gt; 0) {
582 var rand_val_array : [@sizeOf(usize)]u8 = undefined;
583 ([]usize)(rand_val_array)[0] = r.rng.get();
584 while (bytes_left &gt; 0) {
585 buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left];
586 bytes_left -= 1;
587 }
588 }
589 }
590
591 /// Get a random unsigned integer with even distribution between `start`
592 /// inclusive and `end` exclusive.
593 // TODO support signed integers and then rename to &quot;range&quot;
594 pub fn rangeUnsigned(r: &amp;Rand, comptime T: type, start: T, end: T) -&gt; T {
595 const range = end - start;
596 const leftover = @maxValue(T) % range;
597 const upper_bound = @maxValue(T) - leftover;
598 var rand_val_array : [@sizeOf(T)]u8 = undefined;
599
600 while (true) {
601 r.fillBytes(rand_val_array);
602 const rand_val = ([]T)(rand_val_array)[0];
603 if (rand_val &lt; upper_bound) {
604 return start + (rand_val % range);
605 }
606 }
607 }
608
609 /// Get a floating point value in the range 0.0..1.0.
610 pub fn float(r: &amp;Rand, comptime T: type) -&gt; T {
611 // TODO Implement this way instead:
612 // const int = @int_type(false, @sizeOf(T) * 8);
613 // const mask = ((1 &lt;&lt; @float_mantissa_bit_count(T)) - 1);
614 // const rand_bits = r.rng.scalar(int) &amp; mask;
615 // return @float_compose(T, false, 0, rand_bits) - 1.0
616 const int_type = @intType(false, @sizeOf(T) * 8);
617 const precision = if (T == f32) {
618 16777216
619 } else if (T == f64) {
620 9007199254740992
621 } else {
622 @compileError(&quot;unknown floating point type&quot;)
623 };
624 return T(r.rangeUnsigned(int_type, 0, precision)) / T(precision);
625 }
626};
627
628fn MersenneTwister(
629 comptime int: type, comptime n: usize, comptime m: usize, comptime r: int,
630 comptime a: int,
631 comptime u: int, comptime d: int,
632 comptime s: int, comptime b: int,
633 comptime t: int, comptime c: int,
634 comptime l: int, comptime f: int) -&gt; type
635{
636 struct {
637 const Self = this;
638
639 array: [n]int,
640 index: usize,
641
642 pub fn init(mt: &amp;Self, seed: int) {
643 mt.index = n;
644
645 var prev_value = seed;
646 mt.array[0] = prev_value;
647 {var i: usize = 1; while (i &lt; n) : (i += 1) {
648 prev_value = int(i) +% f *% (prev_value ^ (prev_value &gt;&gt; (int.bit_count - 2)));
649 mt.array[i] = prev_value;
650 }};
651 }
652
653 pub fn get(mt: &amp;Self) -&gt; int {
654 const mag01 = []int{0, a};
655 const LM: int = (1 &lt;&lt; r) - 1;
656 const UM = ~LM;
657
658 if (mt.index &gt;= n) {
659 var i: usize = 0;
660
661 while (i &lt; n - m) : (i += 1) {
662 const x = (mt.array[i] &amp; UM) | (mt.array[i + 1] &amp; LM);
663 mt.array[i] = mt.array[i + m] ^ (x &gt;&gt; 1) ^ mag01[x &amp; 0x1];
664 }
665
666 while (i &lt; n - 1) : (i += 1) {
667 const x = (mt.array[i] &amp; UM) | (mt.array[i + 1] &amp; LM);
668 mt.array[i] = mt.array[i + m - n] ^ (x &gt;&gt; 1) ^ mag01[x &amp; 0x1];
669
670 }
671 const x = (mt.array[i] &amp; UM) | (mt.array[0] &amp; LM);
672 mt.array[i] = mt.array[m - 1] ^ (x &gt;&gt; 1) ^ mag01[x &amp; 0x1];
673
674 mt.index = 0;
675 }
676
677 var x = mt.array[mt.index];
678 mt.index += 1;
679
680 x ^= ((x &gt;&gt; u) &amp; d);
681 x ^= ((x &lt;&lt;% s) &amp; b);
682 x ^= ((x &lt;&lt;% t) &amp; c);
683 x ^= (x &gt;&gt; l);
684
685 return x;
686 }
687 }
688}
689
690test "float 32" {
691 var r: Rand = undefined;
692 r.init(42);
693
694 {var i: usize = 0; while (i &lt; 1000) : (i += 1) {
695 const val = r.float(f32);
696 assert(val &gt;= 0.0);
697 assert(val &lt; 1.0);
698 }}
699}
700
701test "MT19937_64" {
702 var rng: MT19937_64 = undefined;
703 rng.init(rand_test.mt64_seed);
704 for (rand_test.mt64_data) |value| {
705 assert(value == rng.get());
706 }
707}
708
709test "MT19937_32" {
710 var rng: MT19937_32 = undefined;
711 rng.init(rand_test.mt32_seed);
712 for (rand_test.mt32_data) |value| {
713 assert(value == rng.get());
714 }
715}</code></pre>
716 <script src="highlight/highlight.pack.js"></script>
717 <script>hljs.initHighlightingOnLoad();</script>
718 </body>
719</html>
doc/langref.html.in created+5851
......@@ -0,0 +1,5851 @@
1<!doctype html>
2<html>
3 <head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
6 <title>Documentation - The Zig Programming Language</title>
7 <link rel="stylesheet" type="text/css" href="highlight/styles/default.css">
8 <style type="text/css">
9 table, th, td {
10 border-collapse: collapse;
11 border: 1px solid grey;
12 }
13 th, td {
14 padding: 0.1em;
15 }
16 @media screen and (min-width: 28.75em) {
17 #nav {
18 width: 20em;
19 height: 100%;
20 overflow-y: scroll;
21 position: fixed;
22 left: 0;
23 top: 0;
24 }
25 #contents {
26 max-width: 50em;
27 padding-left: 22em;
28 }
29 }
30 </style>
31 </head>
32 <body>
33 <div id="nav">
34 <ul>
35 <li><a href="#introduction">Introduction</a></li>
36 <li><a href="#hello-world">Hello World</a></li>
37 <li><a href="#values">Values</a></li>
38 <ul>
39 <li><a href="#primitive-types">Primitive Types</a></li>
40 <li><a href="#primitive-values">Primitive Values</a></li>
41 <li><a href="#string-literals">String Literals</a>
42 <ul>
43 <li><a href="#string-literal-escapes">Escape Sequences</a></li>
44 <li><a href="#multiline-string-literals">Multiline String Literals</a></li>
45 </ul>
46 </li>
47 <li><a href="#values-assignment">Assignment</a></li>
48 </ul>
49 </li>
50 <li><a href="#integers">Integers</a>
51 <ul>
52 <li><a href="#integer-literals">Integer Literals</a></li>
53 <li><a href="#runtime-integer-values">Runtime Integer Values</a></li>
54 </ul>
55 </li>
56 <li><a href="#floats">Floats</a>
57 <ul>
58 <li><a href="#float-literals">Float Literals</a></li>
59 <li><a href="#float-operations">Floating Point Operations</a></li>
60 </ul>
61 </li>
62 <li><a href="#operators">Operators</a>
63 <ul>
64 <li><a href="#operators-table">Table of Operators</a></li>
65 <li><a href="#operators-precedence">Precedence</a></li>
66 </ul>
67 </li>
68 <li><a href="#arrays">Arrays</a></li>
69 <li><a href="#pointers">Pointers</a>
70 <ul>
71 <li><a href="#alignment">Alignment</a></li>
72 <li><a href="#type-based-alias-analysis">Type Based Alias Analysis</a></li>
73 </ul>
74 </li>
75 <li><a href="#slices">Slices</a></li>
76 <li><a href="#struct">struct</a></li>
77 <li><a href="#enum">enum</a></li>
78 <li><a href="#switch">switch</a></li>
79 <li><a href="#while">while</a></li>
80 <li><a href="#for">for</a></li>
81 <li><a href="#if">if</a></li>
82 <li><a href="#goto">goto</a></li>
83 <li><a href="#defer">defer</a></li>
84 <li><a href="#unreachable">unreachable</a>
85 <ul>
86 <li><a href="#unreachable-basics">Basics</a></li>
87 <li><a href="#unreachable-comptime">At Compile-Time</a></li>
88 </ul>
89 </li>
90 <li><a href="#noreturn">noreturn</a></li>
91 <li><a href="#functions">Functions</a>
92 <ul>
93 <li><a href="#functions-by-val-params">Pass-by-val Parameters</a>
94 </ul>
95 </li>
96 <li><a href="#errors">Errors</a></li>
97 <li><a href="#nullables">Nullables</a></li>
98 <li><a href="#casting">Casting</a></li>
99 <li><a href="#void">void</a></li>
100 <li><a href="#this">this</a></li>
101 <li><a href="#comptime">comptime</a>
102 <ul>
103 <li><a href="#introducing-compile-time-concept">Introducing the Compile-Time Concept</a></li>
104 <ul>
105 <li><a href="#compile-time-parameters">Compile-time parameters</a></li>
106 <li><a href="#compile-time-variables">Compile-time variables</a></li>
107 <li><a href="#compile-time-expressions">Compile-time expressions</a></li>
108 </ul>
109 <li><a href="#generic-data-structures">Generic Data Structures</a></li>
110 <li><a href="#case-study-printf">Case Study: printf in Zig</a></li>
111 </ul>
112 </li>
113 <li><a href="#inline">inline</a></li>
114 <li><a href="#assembly">assembly</a></li>
115 <li><a href="#atomics">Atomics</a></li>
116 <li><a href="#builtin-functions">Builtin Functions</a>
117 <ul>
118 <li><a href="#builtin-addWithOverflow">@addWithOverflow</a></li>
119 <li><a href="#builtin-alignCast">@alignCast</a></li>
120 <li><a href="#builtin-alignOf">@alignOf</a></li>
121 <li><a href="#builtin-ArgType">@ArgType</a></li>
122 <li><a href="#builtin-bitCast">@bitCast</a></li>
123 <li><a href="#builtin-breakpoint">@breakpoint</a></li>
124 <li><a href="#builtin-cDefine">@cDefine</a></li>
125 <li><a href="#builtin-cImport">@cImport</a></li>
126 <li><a href="#builtin-cInclude">@cInclude</a></li>
127 <li><a href="#builtin-cUndef">@cUndef</a></li>
128 <li><a href="#builtin-canImplicitCast">@canImplicitCast</a></li>
129 <li><a href="#builtin-clz">@clz</a></li>
130 <li><a href="#builtin-cmpxchg">@cmpxchg</a></li>
131 <li><a href="#builtin-compileError">@compileError</a></li>
132 <li><a href="#builtin-compileLog">@compileLog</a></li>
133 <li><a href="#builtin-ctz">@ctz</a></li>
134 <li><a href="#builtin-divExact">@divExact</a></li>
135 <li><a href="#builtin-divFloor">@divFloor</a></li>
136 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
137 <li><a href="#builtin-embedFile">@embedFile</a></li>
138 <li><a href="#builtin-enumTagName">@enumTagName</a></li>
139 <li><a href="#builtin-errorName">@errorName</a></li>
140 <li><a href="#builtin-fence">@fence</a></li>
141 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
142 <li><a href="#builtin-frameAddress">@frameAddress</a></li>
143 <li><a href="#builtin-import">@import</a></li>
144 <li><a href="#builtin-inlineCall">@inlineCall</a></li>
145 <li><a href="#builtin-intToPtr">@intToPtr</a></li>
146 <li><a href="#builtin-IntType">@IntType</a></li>
147 <li><a href="#builtin-maxValue">@maxValue</a></li>
148 <li><a href="#builtin-memberCount">@memberCount</a></li>
149 <li><a href="#builtin-memberName">@memberName</a></li>
150 <li><a href="#builtin-memberType">@memberType</a></li>
151 <li><a href="#builtin-memcpy">@memcpy</a></li>
152 <li><a href="#builtin-memset">@memset</a></li>
153 <li><a href="#builtin-minValue">@minValue</a></li>
154 <li><a href="#builtin-mod">@mod</a></li>
155 <li><a href="#builtin-mulWithOverflow">@mulWithOverflow</a></li>
156 <li><a href="#builtin-offsetOf">@offsetOf</a></li>
157 <li><a href="#builtin-OpaqueType">@OpaqueType</a></li>
158 <li><a href="#builtin-panic">@panic</a></li>
159 <li><a href="#builtin-ptrCast">@ptrCast</a></li>
160 <li><a href="#builtin-ptrToInt">@ptrToInt</a></li>
161 <li><a href="#builtin-rem">@rem</a></li>
162 <li><a href="#builtin-returnAddress">@returnAddress</a></li>
163 <li><a href="#builtin-setDebugSafety">@setDebugSafety</a></li>
164 <li><a href="#builtin-setEvalBranchQuota">@setEvalBranchQuota</a></li>
165 <li><a href="#builtin-setFloatMode">@setFloatMode</a></li>
166 <li><a href="#builtin-setGlobalLinkage">@setGlobalLinkage</a></li>
167 <li><a href="#builtin-setGlobalSection">@setGlobalSection</a></li>
168 <li><a href="#builtin-shlExact">@shlExact</a></li>
169 <li><a href="#builtin-shlWithOverflow">@shlWithOverflow</a></li>
170 <li><a href="#builtin-shrExact">@shrExact</a></li>
171 <li><a href="#builtin-sizeOf">@sizeOf</a></li>
172 <li><a href="#builtin-subWithOverflow">@subWithOverflow</a></li>
173 <li><a href="#builtin-truncate">@truncate</a></li>
174 <li><a href="#builtin-typeId">@typeId</a></li>
175 <li><a href="#builtin-typeName">@typeName</a></li>
176 <li><a href="#builtin-typeOf">@typeOf</a></li>
177 </ul>
178 </li>
179 <li><a href="#build-mode">Build Mode</a>
180 <ul>
181 <li><a href="#build-mode-debug">Debug</a></li>
182 <li><a href="#build-mode-release-fast">ReleaseFast</a></li>
183 <li><a href="#build-mode-release-safe">ReleaseSafe</a></li>
184 </ul>
185 </li>
186 <li><a href="#undefined-behavior">Undefined Behavior</a>
187 <ul>
188 <li><a href="#undef-unreachable">Reaching Unreachable Code</a></li>
189 <li><a href="#undef-index-out-of-bounds">Index out of Bounds</a></li>
190 <li><a href="#undef-cast-negative-unsigned">Cast Negative Number to Unsigned Integer</a></li>
191 <li><a href="#undef-cast-truncates-data">Cast Truncates Data</a></li>
192 <li><a href="#undef-integer-overflow">Integer Overflow</a>
193 <ul>
194 <li><a href="#undef-int-overflow-default">Default Operations</a></li>
195 <li><a href="#undef-int-overflow-std">Standard Library Math Functions</a></li>
196 <li><a href="#undef-int-overflow-builtin">Builtin Overflow Functions</a></li>
197 <li><a href="#undef-int-overflow-wrap">Wrapping Operations</a></li>
198
199 </ul>
200 </li>
201 <li><a href="#undef-shl-overflow">Exact Left Shift Overflow</a></li>
202 <li><a href="#undef-shr-overflow">Exact Right Shift Overflow</a></li>
203 <li><a href="#undef-division-by-zero">Division by Zero</a></li>
204 <li><a href="#undef-remainder-division-by-zero">Remainder Division by Zero</a></li>
205 <li><a href="#undef-exact-division-remainder">Exact Division Remainder</a></li>
206 <li><a href="#undef-slice-widen-remainder">Slice Widen Remainder</a></li>
207 <li><a href="#undef-attempt-unwrap-null">Attempt to Unwrap Null</a></li>
208 <li><a href="#undef-attempt-unwrap-error">Attempt to Unwrap Error</a></li>
209 <li><a href="#undef-invalid-error-code">Invalid Error Code</a></li>
210 <li><a href="#undef-invalid-enum-cast">Invalid Enum Cast</a></li>
211 <li><a href="#undef-incorrect-pointer-alignment">Incorrect Pointer Alignment</a></li>
212 </ul>
213 </li>
214 <li><a href="#memory">Memory</a></li>
215 <li><a href="#compile-variables">Compile Variables</a></li>
216 <li><a href="#root-source-file">Root Source File</a></li>
217 <li><a href="#zig-test">Zig Test</a></li>
218 <li><a href="#zig-build-system">Zig Build System</a></li>
219 <li><a href="#c">C</a>
220 <ul>
221 <li><a href="#c-type-primitives">C Type Primitives</a></li>
222 <li><a href="#c-string-literals">C String Literals</a></li>
223 <li><a href="#c-import">Import from C Header File</a></li>
224 <li><a href="#mixing-object-files">Mixing Object Files</a></li>
225 </ul>
226 </li>
227 <li><a href="#targets">Targets</a></li>
228 <li><a href="#style-guide">Style Guide</a>
229 <ul>
230 <li><a href="#style-guide-whitespace">Whitespace</a></li>
231 <li><a href="#style-guide-names">Names</a></li>
232 <li><a href="#style-guide-examples">Examples</a></li>
233 </ul>
234 </li>
235 <li><a href="#grammar">Grammar</a></li>
236 <li><a href="#zen">Zen</a></li>
237 </ul>
238 </div>
239 <div id="contents">
240 <h1 id="introduction">Zig Documentation</h1>
241 <p>
242 Zig is an open-source programming language designed for <strong>robustness</strong>,
243 <strong>optimality</strong>, and <strong>clarity</strong>.
244 </p>
245 <ul>
246 <li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li>
247 <li><strong>Optimal</strong> - write programs the best way they can behave and perform.</li>
248 <li><strong>Clear</strong> - precisely communicate your intent to the compiler and other programmers. The language imposes a low overhead to reading code.</li>
249 </ul>
250 <p>
251 Often the most efficient way to learn something new is to see examples, so
252 this documentation shows how to use each of Zig's features. It is
253 all on one page so you can search with your browser's search tool.
254 </p>
255 <p>
256 If you search for something specific in this documentation and do not find it,
257 please <a href="https://github.com/zig-lang/www.ziglang.org/issues/new?title=I%20searched%20for%20___%20in%20the%20docs%20and%20didn%27t%20find%20it">file an issue</a> or <a href="https://webchat.freenode.net/?channels=%23zig">say something on IRC</a>.
258 </p>
259 <h2 id="hello-world">Hello World</h2>
260 <pre><code class="zig">const io = @import("std").io;
261
262pub fn main() -&gt; %void {
263 // If this program is run without stdout attached, exit with an error.
264 var stdout_file = %return io.getStdOut();
265 const stdout = &amp;stdout_file.out_stream;
266 // If this program encounters pipe failure when printing to stdout, exit
267 // with an error.
268 %return stdout.print("Hello, world!\n");
269}</code></pre>
270 <pre><code class="sh">$ zig build-exe hello.zig
271$ ./hello
272Hello, world!</code></pre>
273 <p>
274 Usually you don't want to write to stdout. You want to write to stderr. And you
275 don't care if it fails. It's more like a <em>warning message</em> that you want
276 to emit. For that you can use a simpler API:
277 </p>
278 <pre><code class="zig">const warn = @import("std").debug.warn;
279
280pub fn main() -&gt; %void {
281 warn("Hello, world!\n");
282}</code></pre>
283 <p>See also:</p>
284 <ul>
285 <li><a href="#values">Values</a></li>
286 <li><a href="#builtin-import">@import</a></li>
287 <li><a href="#errors">Errors</a></li>
288 <li><a href="#root-source-file">Root Source File</a></li>
289 </ul>
290 <h2 id="values">Values</h2>
291 <pre><code class="zig">const warn = @import("std").debug.warn;
292const os = @import("std").os;
293const assert = @import("std").debug.assert;
294
295// error declaration, makes `error.ArgNotFound` available
296error ArgNotFound;
297
298pub fn main() -&gt; %void {
299 // integers
300 const one_plus_one: i32 = 1 + 1;
301 warn("1 + 1 = {}\n", one_plus_one);
302
303 // floats
304 const seven_div_three: f32 = 7.0 / 3.0;
305 warn("7.0 / 3.0 = {}\n", seven_div_three);
306
307 // boolean
308 warn("{}\n{}\n{}\n",
309 true and false,
310 true or false,
311 !true);
312
313 // nullable
314 var nullable_value: ?[]const u8 = null;
315 assert(nullable_value == null);
316
317 warn("\nnullable 1\ntype: {}\nvalue: {}\n",
318 @typeName(@typeOf(nullable_value)), nullable_value);
319
320 nullable_value = "hi";
321 assert(nullable_value != null);
322
323 warn("\nnullable 2\ntype: {}\nvalue: {}\n",
324 @typeName(@typeOf(nullable_value)), nullable_value);
325
326 // error union
327 var number_or_error: %i32 = error.ArgNotFound;
328
329 warn("\nerror union 1\ntype: {}\nvalue: {}\n",
330 @typeName(@typeOf(number_or_error)), number_or_error);
331
332 number_or_error = 1234;
333
334 warn("\nerror union 2\ntype: {}\nvalue: {}\n",
335 @typeName(@typeOf(number_or_error)), number_or_error);
336}</code></pre>
337 <pre><code class="sh">$ zig build-exe values.zig
338$ ./values
3391 + 1 = 2
3407.0 / 3.0 = 2.333333
341false
342true
343false
344
345nullable 1
346type: ?[]const u8
347value: null
348
349nullable 2
350type: ?[]const u8
351value: hi
352
353error union 1
354type: %i32
355value: error.ArgNotFound
356
357error union 2
358type: %i32
359value: 1234</code></pre>
360 <h3 id="primitive-types">Primitive Types</h2>
361 <table>
362 <tr>
363 <th>
364 Name
365 </th>
366 <th>
367 C Equivalent
368 </th>
369 <th>
370 Description
371 </th>
372 </tr>
373 <tr>
374 <td><code>i2</code></td>
375 <td><code>(none)</code></td>
376 <td>signed 2-bit integer</td>
377 </tr>
378 <tr>
379 <td><code>u2</code></td>
380 <td><code>(none)</code></td>
381 <td>unsigned 2-bit integer</td>
382 </tr>
383 <tr>
384 <td><code>i3</code></td>
385 <td><code>(none)</code></td>
386 <td>signed 3-bit integer</td>
387 </tr>
388 <tr>
389 <td><code>u3</code></td>
390 <td><code>(none)</code></td>
391 <td>unsigned 3-bit integer</td>
392 </tr>
393 <tr>
394 <td><code>i4</code></td>
395 <td><code>(none)</code></td>
396 <td>signed 4-bit integer</td>
397 </tr>
398 <tr>
399 <td><code>u4</code></td>
400 <td><code>(none)</code></td>
401 <td>unsigned 4-bit integer</td>
402 </tr>
403 <tr>
404 <td><code>i5</code></td>
405 <td><code>(none)</code></td>
406 <td>signed 5-bit integer</td>
407 </tr>
408 <tr>
409 <td><code>u5</code></td>
410 <td><code>(none)</code></td>
411 <td>unsigned 5-bit integer</td>
412 </tr>
413 <tr>
414 <td><code>i6</code></td>
415 <td><code>(none)</code></td>
416 <td>signed 6-bit integer</td>
417 </tr>
418 <tr>
419 <td><code>u6</code></td>
420 <td><code>(none)</code></td>
421 <td>unsigned 6-bit integer</td>
422 </tr>
423 <tr>
424 <td><code>i7</code></td>
425 <td><code>(none)</code></td>
426 <td>signed 7-bit integer</td>
427 </tr>
428 <tr>
429 <td><code>u7</code></td>
430 <td><code>(none)</code></td>
431 <td>unsigned 7-bit integer</td>
432 </tr>
433 <tr>
434 <td><code>i8</code></td>
435 <td><code>int8_t</code></td>
436 <td>signed 8-bit integer</td>
437 </tr>
438 <tr>
439 <td><code>u8</code></td>
440 <td><code>uint8_t</code></td>
441 <td>unsigned 8-bit integer</td>
442 </tr>
443 <tr>
444 <td><code>i16</code></td>
445 <td><code>int16_t</code></td>
446 <td>signed 16-bit integer</td>
447 </tr>
448 <tr>
449 <td><code>u16</code></td>
450 <td><code>uint16_t</code></td>
451 <td>unsigned 16-bit integer</td>
452 </tr>
453 <tr>
454 <td><code>i32</code></td>
455 <td><code>int32_t</code></td>
456 <td>signed 32-bit integer</td>
457 </tr>
458 <tr>
459 <td><code>u32</code></td>
460 <td><code>uint32_t</code></td>
461 <td>unsigned 32-bit integer</td>
462 </tr>
463 <tr>
464 <td><code>i64</code></td>
465 <td><code>int64_t</code></td>
466 <td>signed 64-bit integer</td>
467 </tr>
468 <tr>
469 <td><code>u64</code></td>
470 <td><code>uint64_t</code></td>
471 <td>unsigned 64-bit integer</td>
472 </tr>
473 <tr>
474 <td><code>i128</code></td>
475 <td><code>__int128</code></td>
476 <td>signed 128-bit integer</td>
477 </tr>
478 <tr>
479 <td><code>u128</code></td>
480 <td><code>unsigned __int128</code></td>
481 <td>unsigned 128-bit integer</td>
482 </tr>
483 <tr>
484 <td><code>isize</code></td>
485 <td><code>intptr_t</code></td>
486 <td>signed pointer sized integer</td>
487 </tr>
488 <tr>
489 <td><code>usize</code></td>
490 <td><code>uintptr_t</code></td>
491 <td>unsigned pointer sized integer</td>
492 </tr>
493
494 <tr>
495 <td><code>c_short</code></td>
496 <td><code>short</code></td>
497 <td>for ABI compatibility with C</td>
498 </tr>
499 <tr>
500 <td><code>c_ushort</code></td>
501 <td><code>unsigned short</code></td>
502 <td>for ABI compatibility with C</td>
503 </tr>
504 <tr>
505 <td><code>c_int</code></td>
506 <td><code>int</code></td>
507 <td>for ABI compatibility with C</td>
508 </tr>
509 <tr>
510 <td><code>c_uint</code></td>
511 <td><code>unsigned int</code></td>
512 <td>for ABI compatibility with C</td>
513 </tr>
514 <tr>
515 <td><code>c_long</code></td>
516 <td><code>long</code></td>
517 <td>for ABI compatibility with C</td>
518 </tr>
519 <tr>
520 <td><code>c_ulong</code></td>
521 <td><code>unsigned long</code></td>
522 <td>for ABI compatibility with C</td>
523 </tr>
524 <tr>
525 <td><code>c_longlong</code></td>
526 <td><code>long long</code></td>
527 <td>for ABI compatibility with C</td>
528 </tr>
529 <tr>
530 <td><code>c_ulonglong</code></td>
531 <td><code>unsigned long long</code></td>
532 <td>for ABI compatibility with C</td>
533 </tr>
534 <tr>
535 <td><code>c_longdouble</code></td>
536 <td><code>long double</code></td>
537 <td>for ABI compatibility with C</td>
538 </tr>
539 <tr>
540 <td><code>c_void</code></td>
541 <td><code>void</code></td>
542 <td>for ABI compatibility with C</td>
543 </tr>
544
545 <tr>
546 <td><code>f32</code></td>
547 <td><code>float</code></td>
548 <td>32-bit floating point (23-bit mantissa)</td>
549 </tr>
550 <tr>
551 <td><code>f64</code></td>
552 <td><code>double</code></td>
553 <td>64-bit floating point (52-bit mantissa)</td>
554 </tr>
555 <tr>
556 <td><code>f128</code></td>
557 <td>(none)</td>
558 <td>128-bit floating point (112-bit mantissa)</td>
559 </tr>
560 <tr>
561 <td><code>bool</code></td>
562 <td><code>bool</code></td>
563 <td><code>true</code> or <code>false</code></td>
564 </tr>
565 <tr>
566 <td><code>void</code></td>
567 <td>(none)</td>
568 <td>0 bit type</td>
569 </tr>
570 <tr>
571 <td><code>noreturn</code></td>
572 <td>(none)</td>
573 <td>the type of <code>break</code>, <code>continue</code>, <code>goto</code>, <code>return</code>, <code>unreachable</code>, and <code>while (true) {}</code></td>
574 </tr>
575 <tr>
576 <td><code>type</code></td>
577 <td>(none)</td>
578 <td>the type of types</td>
579 </tr>
580 <tr>
581 <td><code>error</code></td>
582 <td>(none)</td>
583 <td>an error code</td>
584 </tr>
585 </table>
586 <p>See also:</p>
587 <ul>
588 <li><a href="#integers">Integers</a></li>
589 <li><a href="#floats">Floats</a></li>
590 <li><a href="#void">void</a></li>
591 <li><a href="#errors">Errors</a></li>
592 </ul>
593 <h3 id="primitive-values">Primitive Values</h3>
594 <table>
595 <tr>
596 <th>
597 Name
598 </th>
599 <th>
600 Description
601 </th>
602 </tr>
603 <tr>
604 <td><code>true</code> and <code>false</code></td>
605 <td><code>bool</code> values</td>
606 </tr>
607 <tr>
608 <td><code>null</code></td>
609 <td>used to set a nullable type to <code>null</code></td>
610 </tr>
611 <tr>
612 <td><code>undefined</code></td>
613 <td>used to leave a value unspecified</td>
614 </tr>
615 <tr>
616 <td><code>this</code></td>
617 <td>refers to the thing in immediate scope</td>
618 </tr>
619 </table>
620 <p>See also:</p>
621 <ul>
622 <li><a href="#nullables">Nullables</a></li>
623 <li><a href="#this">this</a></li>
624 </ul>
625 <h3 id="string-literals">String Literals</h3>
626 <pre><code class="zig">const assert = @import("std").debug.assert;
627const mem = @import("std").mem;
628
629test "string literals" {
630 // In Zig a string literal is an array of bytes.
631 const normal_bytes = "hello";
632 assert(@typeOf(normal_bytes) == [5]u8);
633 assert(normal_bytes.len == 5);
634 assert(normal_bytes[1] == 'e');
635 assert('e' == '\x65');
636 assert(mem.eql(u8, "hello", "h\x65llo"));
637
638 // A C string literal is a null terminated pointer.
639 const null_terminated_bytes = c"hello";
640 assert(@typeOf(null_terminated_bytes) == &amp;const u8);
641 assert(null_terminated_bytes[5] == 0);
642}</code></pre>
643 <pre><code class="sh">$ zig test string_literals.zig
644Test 1/1 string literals...OK</code></pre>
645 <p>See also:</p>
646 <ul>
647 <li><a href="#arrays">Arrays</a></li>
648 <li><a href="#zig-test">Zig Test</a></li>
649 </ul>
650 <h4 id="string-literal-escapes">Escape Sequences</h4>
651 <table>
652 <tr>
653 <th>
654 Escape Sequence
655 </th>
656 <th>
657 Name
658 </th>
659 </tr>
660 <tr>
661 <td><code>\n</code></td>
662 <td>Newline</td>
663 </tr>
664 <tr>
665 <td><code>\r</code></td>
666 <td>Carriage Return</td>
667 </tr>
668 <tr>
669 <td><code>\t</code></td>
670 <td>Tab</td>
671 </tr>
672 <tr>
673 <td><code>\\</code></td>
674 <td>Backslash</td>
675 </tr>
676 <tr>
677 <td><code>\'</code></td>
678 <td>Single Quote</td>
679 </tr>
680 <tr>
681 <td><code>\"</code></td>
682 <td>Double Quote</td>
683 </tr>
684 <tr>
685 <td><code>\xNN</code></td>
686 <td>hexadecimal 8-bit character code (2 digits)</td>
687 </tr>
688 <tr>
689 <td><code>\uNNNN</code></td>
690 <td>hexadecimal 16-bit Unicode character code UTF-8 encoded (4 digits)</td>
691 </tr>
692 <tr>
693 <td><code>\UNNNNNN</code></td>
694 <td>hexadecimal 24-bit Unicode character code UTF-8 encoded (6 digits)</td>
695 </tr>
696 </table>
697 <p>Note that the maximum valid Unicode point is <code>0x10ffff</code>.</p>
698 <h4 id="multiline-string-literals">Multiline String Literals</h4>
699 <p>
700 Multiline string literals have no escapes and can span across multiple lines.
701 To start a multiline string literal, use the <code>\\</code> token. Just like a comment,
702 the string literal goes until the end of the line. The end of the line is
703 not included in the string literal.
704 However, if the next line begins with <code>\\</code> then a newline is appended and
705 the string literal continues.
706 </p>
707 <pre><code class="zig">const hello_world_in_c =
708 \\#include &lt;stdio.h&gt;
709 \\
710 \\int main(int argc, char **argv) {
711 \\ printf("hello world\n");
712 \\ return 0;
713 \\}
714;</code></pre>
715 <p>
716 For a multiline C string literal, prepend <code>c</code> to each <code>\\</code>:
717 </p>
718 <pre><code class="zig">const c_string_literal =
719 c\\#include &lt;stdio.h&gt;
720 c\\
721 c\\int main(int argc, char **argv) {
722 c\\ printf("hello world\n");
723 c\\ return 0;
724 c\\}
725;</code></pre>
726 <p>
727 In this example the variable <code>c_string_literal</code> has type <code>&amp;const char</code> and
728 has a terminating null byte.
729 </p>
730 <p>See also:</p>
731 <ul>
732 <li><a href="#builtin-embedFile">@embedFile</a></li>
733 </ul>
734 <h3 id="values-assignment">Assignment</h3>
735 <p>Use <code>const</code> to assign a value to an identifier:</p>
736 <pre><code class="zig">const x = 1234;
737
738fn foo() {
739 // It works at global scope as well as inside functions.
740 const y = 5678;
741
742 // Once assigned, an identifier cannot be changed.
743 y += 1;
744}
745
746test "assignment" {
747 foo();
748}</code></pre>
749 <pre><code class="sh">$ zig test test.zig
750test.zig:8:7: error: cannot assign to constant
751 y += 1;
752 ^</code></pre>
753 <p>If you need a variable that you can modify, use <code>var</code>:</p>
754 <pre><code class="zig">const assert = @import("std").debug.assert;
755
756test "var" {
757 var y: i32 = 5678;
758
759 y += 1;
760
761 assert(y == 5679);
762}</code></pre>
763 <pre><code class="sh">$ zig test test.zig
764Test 1/1 assignment...OK</code></pre>
765 <p>Variables must be initialized:</p>
766 <pre><code class="zig">test "initialization" {
767 var x: i32;
768
769 x = 1;
770}</code></pre>
771 <pre><code class="sh">$ zig test test.zig
772test.zig:3:5: error: variables must be initialized
773 var x: i32;
774 ^</code></pre>
775 <p>Use <code>undefined</code> to leave variables uninitialized:</p>
776 <pre><code class="zig">const assert = @import("std").debug.assert;
777
778test "init with undefined" {
779 var x: i32 = undefined;
780 x = 1;
781 assert(x == 1);
782}</code></pre>
783 <pre><code class="sh">$ zig test test.zig
784Test 1/1 init with undefined...OK</code></pre>
785 <h2 id="integers">Integers</h2>
786 <h3 id="integer-literals">Integer Literals</h3>
787 <pre><code class="zig">const decimal_int = 98222;
788const hex_int = 0xff;
789const another_hex_int = 0xFF;
790const octal_int = 0o755;
791const binary_int = 0b11110000;</code></pre>
792 <h3 id="runtime-integer-values">Runtime Integer Values</h3>
793 <p>
794 Integer literals have no size limitation, and if any undefined behavior occurs,
795 the compiler catches it.
796 </p>
797 <p>
798 However, once an integer value is no longer known at compile-time, it must have a
799 known size, and is vulnerable to undefined behavior.
800 </p>
801 <pre><code class="zig">fn divide(a: i32, b: i32) -&gt; i32 {
802 return a / b;
803}</code></pre>
804 <p>
805 In this function, values <code>a</code> and <code>b</code> are known only at runtime,
806 and thus this division operation is vulnerable to both integer overflow and
807 division by zero.
808 </p>
809 <p>
810 Operators such as <code>+</code> and <code>-</code> cause undefined behavior on
811 integer overflow. Also available are operations such as <code>+%</code> and
812 <code>-%</code> which are defined to have wrapping arithmetic on all targets.
813 </p>
814 <p>See also:</p>
815 <ul>
816 <li><a href="#undef-integer-overflow">Integer Overflow</a></li>
817 <li><a href="#undef-division-by-zero">Division By Zero</a></li>
818 <li><a href="#undef-int-overflow-wrap">Wrapping Operations</a></li>
819 </ul>
820 <h2 id="floats">Floats</h2>
821 <h3 id="float-literals">Float Literals</h3>
822 <pre><code class="zig">const floating_point = 123.0E+77;
823const another_float = 123.0;
824const yet_another = 123.0e+77;
825
826const hex_floating_point = 0x103.70p-5;
827const another_hex_float = 0x103.70;
828const yet_another_hex_float = 0x103.70P-5;</code></pre>
829 <h3 id="float-operations">Floating Point Operations</h3>
830 <p>By default floating point operations use <code>Optimized</code> mode,
831 but you can switch to <code>Strict</code> mode on a per-block basis:</p>
832 <p>foo.zig</p>
833 <pre><code class="zig">const builtin = @import("builtin");
834const big = f64(1 &lt;&lt; 40);
835
836export fn foo_strict(x: f64) -&gt; f64 {
837 @setFloatMode(this, builtin.FloatMode.Strict);
838 return x + big - big;
839}
840
841export fn foo_optimized(x: f64) -&gt; f64 {
842 return x + big - big;
843}</code></pre>
844 <p>test.zig</p>
845 <pre><code class="zig">const warn = @import("std").debug.warn;
846
847extern fn foo_strict(x: f64) -&gt; f64;
848extern fn foo_optimized(x: f64) -&gt; f64;
849
850pub fn main() -&gt; %void {
851 const x = 0.001;
852 warn("optimized = {}\n", foo_optimized(x));
853 warn("strict = {}\n", foo_strict(x));
854}</code></pre>
855 <p>For this test we have to separate code into two object files -
856 otherwise the optimizer figures out all the values at compile-time,
857 which operates in strict mode.</p>
858 <pre><code class="sh">$ zig build-obj foo.zig --release-fast
859$ zig build-exe test.zig --object foo.o
860$ ./test
861optimized = 1.0e-2
862strict = 9.765625e-3</code></pre>
863 <p>See also:</p>
864 <ul>
865 <li><a href="#builtin-setFloatMode">@setFloatMode</a></li>
866 <li><a href="#undef-division-by-zero">Division By Zero</a></li>
867 </ul>
868 <h2 id="operators">Operators</h2>
869 <h3 id="operators-table">Table of Operators</h2>
870 <table>
871 <tr>
872 <th>
873 Syntax
874 </th>
875 <th>
876 Relevant Types
877 </th>
878 <th>
879 Description
880 </th>
881 <th>
882 Example
883 </th>
884 </tr>
885 <tr>
886 <td><pre><code class="zig">a + b
887a += b</code></pre></td>
888 <td>
889 <ul>
890 <li><a href="#integers">Integers</a></li>
891 <li><a href="#floats">Floats</a></li>
892 </ul>
893 </td>
894 <td>Addition.
895 <ul>
896 <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li>
897 </ul>
898 </td>
899 <td>
900 <pre><code class="zig">2 + 5 == 7</code></pre>
901 </td>
902 </tr>
903 <tr>
904 <td><pre><code class="zig">a +% b
905a +%= b</code></pre></td>
906 <td>
907 <ul>
908 <li><a href="#integers">Integers</a></li>
909 </ul>
910 </td>
911 <td>Wrapping Addition.
912 <ul>
913 <li>Guaranteed to have twos-complement wrapping behavior.</li>
914 </ul>
915 </td>
916 <td>
917 <pre><code class="zig">u32(@maxValue(u32)) +% 1 == 0</code></pre>
918 </td>
919 </tr>
920 <tr>
921 <td><pre><code class="zig">a - b
922a -= b</code></pre></td>
923 <td>
924 <ul>
925 <li><a href="#integers">Integers</a></li>
926 <li><a href="#floats">Floats</a></li>
927 </ul>
928 </td>
929 <td>Subtraction.
930 <ul>
931 <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li>
932 </ul>
933 </td>
934 <td>
935 <pre><code class="zig">2 - 5 == -3</code></pre>
936 </td>
937 </tr>
938 <tr>
939 <td><pre><code class="zig">a -% b
940a -%= b</code></pre></td>
941 <td>
942 <ul>
943 <li><a href="#integers">Integers</a></li>
944 </ul>
945 </td>
946 <td>Wrapping Subtraction.
947 <ul>
948 <li>Guaranteed to have twos-complement wrapping behavior.</li>
949 </ul>
950 </td>
951 <td>
952 <pre><code class="zig">u32(0) -% 1 == @maxValue(u32)</code></pre>
953 </td>
954 </tr>
955 <tr>
956 <td><pre><code class="zig">-a<code></pre></td>
957 <td>
958 <ul>
959 <li><a href="#integers">Integers</a></li>
960 <li><a href="#floats">Floats</a></li>
961 </ul>
962 </td>
963 <td>
964 Negation.
965 <ul>
966 <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li>
967 </ul>
968 </td>
969 <td>
970 <pre><code class="zig">-1 == 0 - 1</code></pre>
971 </td>
972 </tr>
973 <tr>
974 <td><pre><code class="zig">-%a<code></pre></td>
975 <td>
976 <ul>
977 <li><a href="#integers">Integers</a></li>
978 </ul>
979 </td>
980 <td>
981 Wrapping Negation.
982 <ul>
983 <li>Guaranteed to have twos-complement wrapping behavior.</li>
984 </ul>
985 </td>
986 <td>
987 <pre><code class="zig">-%i32(@minValue(i32)) == @minValue(i32)</code></pre>
988 </td>
989 </tr>
990 <tr>
991 <td><pre><code class="zig">a * b
992a *= b</code></pre></td>
993 <td>
994 <ul>
995 <li><a href="#integers">Integers</a></li>
996 <li><a href="#floats">Floats</a></li>
997 </ul>
998 </td>
999 <td>Multiplication.
1000 <ul>
1001 <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li>
1002 </ul>
1003 </td>
1004 <td>
1005 <pre><code class="zig">2 * 5 == 10</code></pre>
1006 </td>
1007 </tr>
1008 <tr>
1009 <td><pre><code class="zig">a *% b
1010a *%= b</code></pre></td>
1011 <td>
1012 <ul>
1013 <li><a href="#integers">Integers</a></li>
1014 </ul>
1015 </td>
1016 <td>Wrapping Multiplication.
1017 <ul>
1018 <li>Guaranteed to have twos-complement wrapping behavior.</li>
1019 </ul>
1020 </td>
1021 <td>
1022 <pre><code class="zig">u8(200) *% 2 == 144</code></pre>
1023 </td>
1024 </tr>
1025 <tr>
1026 <td><pre><code class="zig">a / b
1027a /= b</code></pre></td>
1028 <td>
1029 <ul>
1030 <li><a href="#integers">Integers</a></li>
1031 <li><a href="#floats">Floats</a></li>
1032 </ul>
1033 </td>
1034 <td>Divison.
1035 <ul>
1036 <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li>
1037 <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for integers.</li>
1038 <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for floats in <a href="#float-operations">FloatMode.Optimized Mode</a>.</li>
1039 <li>For non-compile-time-known signed integers, must use
1040 <a href="#builtin-divTrunc">@divTrunc</a>,
1041 <a href="#builtin-divFloor">@divFloor</a>, or
1042 <a href="#builtin-divExact">@divExact</a> instead of <code>/</code>.
1043 </li>
1044 </ul>
1045 </td>
1046 <td>
1047 <pre><code class="zig">10 / 5 == 2</code></pre>
1048 </td>
1049 </tr>
1050 <tr>
1051 <td><pre><code class="zig">a % b
1052a %= b</code></pre></td>
1053 <td>
1054 <ul>
1055 <li><a href="#integers">Integers</a></li>
1056 <li><a href="#floats">Floats</a></li>
1057 </ul>
1058 </td>
1059 <td>Remainder Division.
1060 <ul>
1061 <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for integers.</li>
1062 <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for floats in <a href="#float-operations">FloatMode.Optimized Mode</a>.</li>
1063 <li>For non-compile-time-known signed integers, must use
1064 <a href="#builtin-rem">@rem</a> or
1065 <a href="#builtin-mod">@mod</a> instead of <code>%</code>.
1066 </li>
1067 </ul>
1068 </td>
1069 <td>
1070 <pre><code class="zig">10 % 3 == 1</code></pre>
1071 </td>
1072 </tr>
1073 <tr>
1074 <td><pre><code class="zig">a &lt;&lt; b
1075a &lt;&lt;= b</code></pre></td>
1076 <td>
1077 <ul>
1078 <li><a href="#integers">Integers</a></li>
1079 </ul>
1080 </td>
1081 <td>Bit Shift Left.
1082 <ul>
1083 <li>See also <a href="#builtin-shlExact">@shlExact</a>.</li>
1084 <li>See also <a href="#builtin-shlWithOverflow">@shlWithOverflow</a>.</li>
1085 </ul>
1086 </td>
1087 <td>
1088 <pre><code class="zig">1 &lt;&lt; 8 == 256</code></pre>
1089 </td>
1090 </tr>
1091 <tr>
1092 <td><pre><code class="zig">a &gt;&gt; b
1093a &gt;&gt;= b</code></pre></td>
1094 <td>
1095 <ul>
1096 <li><a href="#integers">Integers</a></li>
1097 </ul>
1098 </td>
1099 <td>Bit Shift Right.
1100 <ul>
1101 <li>See also <a href="#builtin-shrExact">@shrExact</a>.</li>
1102 </ul>
1103 </td>
1104 <td>
1105 <pre><code class="zig">10 &gt;&gt; 1 == 5</code></pre>
1106 </td>
1107 </tr>
1108 <tr>
1109 <td><pre><code class="zig">a &amp; b
1110a &amp;= b</code></pre></td>
1111 <td>
1112 <ul>
1113 <li><a href="#integers">Integers</a></li>
1114 </ul>
1115 </td>
1116 <td>Bitwise AND.
1117 </td>
1118 <td>
1119 <pre><code class="zig">0b011 &amp; 0b101 == 0b001</code></pre>
1120 </td>
1121 </tr>
1122 <tr>
1123 <td><pre><code class="zig">a | b
1124a |= b</code></pre></td>
1125 <td>
1126 <ul>
1127 <li><a href="#integers">Integers</a></li>
1128 </ul>
1129 </td>
1130 <td>Bitwise OR.
1131 </td>
1132 <td>
1133 <pre><code class="zig">0b010 | 0b100 == 0b110</code></pre>
1134 </td>
1135 </tr>
1136 <tr>
1137 <td><pre><code class="zig">a ^ b
1138a ^= b</code></pre></td>
1139 <td>
1140 <ul>
1141 <li><a href="#integers">Integers</a></li>
1142 </ul>
1143 </td>
1144 <td>Bitwise XOR.
1145 </td>
1146 <td>
1147 <pre><code class="zig">0b011 ^ 0b101 == 0b110</code></pre>
1148 </td>
1149 </tr>
1150 <tr>
1151 <td><pre><code class="zig">~a<code></pre></td>
1152 <td>
1153 <ul>
1154 <li><a href="#integers">Integers</a></li>
1155 </ul>
1156 </td>
1157 <td>
1158 Bitwise NOT.
1159 </td>
1160 <td>
1161 <pre><code class="zig">~u8(0b0101111) == 0b1010000</code></pre>
1162 </td>
1163 </tr>
1164 <tr>
1165 <td><pre><code class="zig">a ?? b</code></pre></td>
1166 <td>
1167 <ul>
1168 <li><a href="#nullables">Nullables</a></li>
1169 </ul>
1170 </td>
1171 <td>If <code>a</code> is <code>null</code>,
1172 returns <code>b</code> ("default value"),
1173 otherwise returns the unwrapped value of <code>a</code>.
1174 Note that <code>b</code> may be a value of type <a href="#noreturn">noreturn</a>.
1175 </td>
1176 <td>
1177 <pre><code class="zig">const value: ?u32 = null;
1178const unwrapped = value ?? 1234;
1179unwrapped == 1234</code></pre>
1180 </td>
1181 </tr>
1182 <tr>
1183 <td><pre><code class="zig">??a</code></pre></td>
1184 <td>
1185 <ul>
1186 <li><a href="#nullables">Nullables</a></li>
1187 </ul>
1188 </td>
1189 <td>
1190 Equivalent to:
1191 <pre><code class="zig">a ?? unreachable</code></pre>
1192 </td>
1193 <td>
1194 <pre><code class="zig">const value: ?u32 = 5678;
1195??value == 5678</code></pre>
1196 </td>
1197 </tr>
1198 <tr>
1199 <td><pre><code class="zig">a %% b
1200a %% |err| b</code></pre></td>
1201 <td>
1202 <ul>
1203 <li><a href="#errors">Error Unions</a></li>
1204 </ul>
1205 </td>
1206 <td>If <code>a</code> is an <code>error</code>,
1207 returns <code>b</code> ("default value"),
1208 otherwise returns the unwrapped value of <code>a</code>.
1209 Note that <code>b</code> may be a value of type <a href="#noreturn">noreturn</a>.
1210 <code>err</code> is the <code>error</code> and is in scope of the expression <code>b</code>.
1211 </td>
1212 <td>
1213 <pre><code class="zig">const value: %u32 = null;
1214const unwrapped = value %% 1234;
1215unwrapped == 1234</code></pre>
1216 </td>
1217 </tr>
1218 <tr>
1219 <td><pre><code class="zig">%%a</code></pre></td>
1220 <td>
1221 <ul>
1222 <li><a href="#errors">Error Unions</a></li>
1223 </ul>
1224 </td>
1225 <td>Equivalent to:
1226 <pre><code class="zig">a %% unreachable</code></pre>
1227 </td>
1228 <td>
1229 <pre><code class="zig">const value: %u32 = 5678;
1230%%value == 5678</code></pre>
1231 </td>
1232 </tr>
1233 <tr>
1234 <td><pre><code class="zig">a and b<code></pre></td>
1235 <td>
1236 <ul>
1237 <li><a href="#primitive-types">bool</a></li>
1238 </ul>
1239 </td>
1240 <td>
1241 If <code>a</code> is <code>false</code>, returns <code>false</code>
1242 without evaluating <code>b</code>. Otherwise, retuns <code>b</code>.
1243 </td>
1244 <td>
1245 <pre><code class="zig">false and true == false</code></pre>
1246 </td>
1247 </tr>
1248 <tr>
1249 <td><pre><code class="zig">a or b<code></pre></td>
1250 <td>
1251 <ul>
1252 <li><a href="#primitive-types">bool</a></li>
1253 </ul>
1254 </td>
1255 <td>
1256 If <code>a</code> is <code>true</code>, returns <code>true</code>
1257 without evaluating <code>b</code>. Otherwise, retuns <code>b</code>.
1258 </td>
1259 <td>
1260 <pre><code class="zig">false or true == true</code></pre>
1261 </td>
1262 </tr>
1263 <tr>
1264 <td><pre><code class="zig">!a<code></pre></td>
1265 <td>
1266 <ul>
1267 <li><a href="#primitive-types">bool</a></li>
1268 </ul>
1269 </td>
1270 <td>
1271 Boolean NOT.
1272 </td>
1273 <td>
1274 <pre><code class="zig">!false == true</code></pre>
1275 </td>
1276 </tr>
1277 <tr>
1278 <td><pre><code class="zig">a == b<code></pre></td>
1279 <td>
1280 <ul>
1281 <li><a href="#integers">Integers</a></li>
1282 <li><a href="#floats">Floats</a></li>
1283 <li><a href="#primitive-types">bool</a></li>
1284 <li><a href="#primitive-types">type</a></li>
1285 </ul>
1286 </td>
1287 <td>
1288 Returns <code>true</code> if a and b are equal, otherwise returns <code>false</code>.
1289 </td>
1290 <td>
1291 <pre><code class="zig">(1 == 1) == true</code></pre>
1292 </td>
1293 </tr>
1294 <tr>
1295 <td><pre><code class="zig">a == null<code></pre></td>
1296 <td>
1297 <ul>
1298 <li><a href="#nullables">Nullables</a></li>
1299 </ul>
1300 </td>
1301 <td>
1302 Returns <code>true</code> if a is <code>null</code>, otherwise returns <code>false</code>.
1303 </td>
1304 <td>
1305 <pre><code class="zig">const value: ?u32 = null;
1306value == null</code></pre>
1307 </td>
1308 </tr>
1309 <tr>
1310 <td><pre><code class="zig">a != b<code></pre></td>
1311 <td>
1312 <ul>
1313 <li><a href="#integers">Integers</a></li>
1314 <li><a href="#floats">Floats</a></li>
1315 <li><a href="#primitive-types">bool</a></li>
1316 <li><a href="#primitive-types">type</a></li>
1317 </ul>
1318 </td>
1319 <td>
1320 Returns <code>false</code> if a and b are equal, otherwise returns <code>true</code>.
1321 </td>
1322 <td>
1323 <pre><code class="zig">(1 != 1) == false</code></pre>
1324 </td>
1325 </tr>
1326 <tr>
1327 <td><pre><code class="zig">a &gt; b<code></pre></td>
1328 <td>
1329 <ul>
1330 <li><a href="#integers">Integers</a></li>
1331 <li><a href="#floats">Floats</a></li>
1332 </ul>
1333 </td>
1334 <td>
1335 Returns <code>true</code> if a is greater than b, otherwise returns <code>false</code>.
1336 </td>
1337 <td>
1338 <pre><code class="zig">(2 &gt; 1) == true</code></pre>
1339 </td>
1340 </tr>
1341 <tr>
1342 <td><pre><code class="zig">a &gt;= b<code></pre></td>
1343 <td>
1344 <ul>
1345 <li><a href="#integers">Integers</a></li>
1346 <li><a href="#floats">Floats</a></li>
1347 </ul>
1348 </td>
1349 <td>
1350 Returns <code>true</code> if a is greater than or equal to b, otherwise returns <code>false</code>.
1351 </td>
1352 <td>
1353 <pre><code class="zig">(2 &gt;= 1) == true</code></pre>
1354 </td>
1355 </tr>
1356 <tr>
1357 <td><pre><code class="zig">a &lt; b<code></pre></td>
1358 <td>
1359 <ul>
1360 <li><a href="#integers">Integers</a></li>
1361 <li><a href="#floats">Floats</a></li>
1362 </ul>
1363 </td>
1364 <td>
1365 Returns <code>true</code> if a is less than b, otherwise returns <code>false</code>.
1366 </td>
1367 <td>
1368 <pre><code class="zig">(1 &lt; 2) == true</code></pre>
1369 </td>
1370 </tr>
1371 <tr>
1372 <td><pre><code class="zig">a &lt;= b<code></pre></td>
1373 <td>
1374 <ul>
1375 <li><a href="#integers">Integers</a></li>
1376 <li><a href="#floats">Floats</a></li>
1377 </ul>
1378 </td>
1379 <td>
1380 Returns <code>true</code> if a is less than or equal to b, otherwise returns <code>false</code>.
1381 </td>
1382 <td>
1383 <pre><code class="zig">(1 &lt;= 2) == true</code></pre>
1384 </td>
1385 </tr>
1386 <tr>
1387 <td><pre><code class="zig">a ++ b<code></pre></td>
1388 <td>
1389 <ul>
1390 <li><a href="#arrays">Arrays</a></li>
1391 </ul>
1392 </td>
1393 <td>
1394 Array concatenation.
1395 <ul>
1396 <li>Only available when <code>a</code> and <code>b</code> are <a href="#comptime">compile-time known</a>.
1397 </ul>
1398 </td>
1399 <td>
1400 <pre><code class="zig">const mem = @import("std").mem;
1401const array1 = []u32{1,2};
1402const array2 = []u32{3,4};
1403const together = array1 ++ array2;
1404mem.eql(u32, together, []u32{1,2,3,4})</code></pre>
1405 </td>
1406 </tr>
1407 <tr>
1408 <td><pre><code class="zig">a ** b<code></pre></td>
1409 <td>
1410 <ul>
1411 <li><a href="#arrays">Arrays</a></li>
1412 </ul>
1413 </td>
1414 <td>
1415 Array multiplication.
1416 <ul>
1417 <li>Only available when <code>a</code> and <code>b</code> are <a href="#comptime">compile-time known</a>.
1418 </ul>
1419 </td>
1420 <td>
1421 <pre><code class="zig">const mem = @import("std").mem;
1422const pattern = "ab" ** 3;
1423mem.eql(u8, pattern, "ababab")</code></pre>
1424 </td>
1425 </tr>
1426 <tr>
1427 <td><pre><code class="zig">*a<code></pre></td>
1428 <td>
1429 <ul>
1430 <li><a href="#pointers">Pointers</a></li>
1431 </ul>
1432 </td>
1433 <td>
1434 Pointer dereference.
1435 </td>
1436 <td>
1437 <pre><code class="zig">const x: u32 = 1234;
1438const ptr = &amp;x;
1439*x == 1234</code></pre>
1440 </td>
1441 </tr>
1442 <tr>
1443 <td><pre><code class="zig">&amp;a<code></pre></td>
1444 <td>
1445 All types
1446 </td>
1447 <td>
1448 Address of.
1449 </td>
1450 <td>
1451 <pre><code class="zig">const x: u32 = 1234;
1452const ptr = &amp;x;
1453*x == 1234</code></pre>
1454 </td>
1455 </tr>
1456 </table>
1457 <h3 id="operators-precedence">Precedence</h3>
1458 <pre><code>x() x[] x.y
1459!x -x -%x ~x *x &amp;x ?x %x %%x ??x
1460x{}
1461* / % ** *%
1462+ - ++ +% -%
1463&lt;&lt; &gt;&gt;
1464&amp;
1465^
1466|
1467== != &lt; &gt; &lt;= &gt;=
1468and
1469or
1470?? %%
1471= *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>
1472 <h2 id="arrays">Arrays</h2>
1473 <pre><code class="zig">const assert = @import("std").debug.assert;
1474const mem = @import("std").mem;
1475
1476// array literal
1477const message = []u8{'h', 'e', 'l', 'l', 'o'};
1478
1479// get the size of an array
1480comptime {
1481 assert(message.len == 5);
1482}
1483
1484// a string literal is an array literal
1485const same_message = "hello";
1486
1487comptime {
1488 assert(mem.eql(u8, message, same_message));
1489 assert(@typeOf(message) == @typeOf(same_message));
1490}
1491
1492test "iterate over an array" {
1493 var sum: usize = 0;
1494 for (message) |byte| {
1495 sum += byte;
1496 }
1497 assert(sum == usize('h') + usize('e') + usize('l') * 2 + usize('o'));
1498}
1499
1500// modifiable array
1501var some_integers: [100]i32 = undefined;
1502
1503test "modify an array" {
1504 for (some_integers) |*item, i| {
1505 *item = i32(i);
1506 }
1507 assert(some_integers[10] == 10);
1508 assert(some_integers[99] == 99);
1509}
1510
1511// array concatenation works if the values are known
1512// at compile time
1513const part_one = []i32{1, 2, 3, 4};
1514const part_two = []i32{5, 6, 7, 8};
1515const all_of_it = part_one ++ part_two;
1516comptime {
1517 assert(mem.eql(i32, all_of_it, []i32{1,2,3,4,5,6,7,8}));
1518}
1519
1520// remember that string literals are arrays
1521const hello = "hello";
1522const world = "world";
1523const hello_world = hello ++ " " ++ world;
1524comptime {
1525 assert(mem.eql(u8, hello_world, "hello world"));
1526}
1527
1528// ** does repeating patterns
1529const pattern = "ab" ** 3;
1530comptime {
1531 assert(mem.eql(u8, pattern, "ababab"));
1532}
1533
1534// initialize an array to zero
1535const all_zero = []u16{0} ** 10;
1536
1537comptime {
1538 assert(all_zero.len == 10);
1539 assert(all_zero[5] == 0);
1540}
1541
1542// use compile-time code to initialize an array
1543var fancy_array = {
1544 var initial_value: [10]Point = undefined;
1545 for (initial_value) |*pt, i| {
1546 *pt = Point {
1547 .x = i32(i),
1548 .y = i32(i) * 2,
1549 };
1550 }
1551 initial_value
1552};
1553const Point = struct {
1554 x: i32,
1555 y: i32,
1556};
1557
1558test "compile-time array initalization" {
1559 assert(fancy_array[4].x == 4);
1560 assert(fancy_array[4].y == 8);
1561}
1562
1563// call a function to initialize an array
1564var more_points = []Point{makePoint(3)} ** 10;
1565fn makePoint(x: i32) -&gt; Point {
1566 Point {
1567 .x = x,
1568 .y = x * 2,
1569 }
1570}
1571test "array initialization with function calls" {
1572 assert(more_points[4].x == 3);
1573 assert(more_points[4].y == 6);
1574 assert(more_points.len == 10);
1575}</code></pre>
1576 <pre><code class="sh">$ zig test arrays.zig
1577Test 1/4 iterate over an array...OK
1578Test 2/4 modify an array...OK
1579Test 3/4 compile-time array initalization...OK
1580Test 4/4 array initialization with function calls...OK</code></pre>
1581 <p>See also:</p>
1582 <ul>
1583 <li><a href="#for">for</a></li>
1584 <li><a href="#slices">Slices</a></li>
1585 </ul>
1586 <h2 id="pointers">Pointers</h2>
1587 <pre><code class="zig">const assert = @import("std").debug.assert;
1588
1589test "address of syntax" {
1590 // Get the address of a variable:
1591 const x: i32 = 1234;
1592 const x_ptr = &x;
1593
1594 // Deference a pointer:
1595 assert(*x_ptr == 1234);
1596
1597 // When you get the address of a const variable, you get a const pointer.
1598 assert(@typeOf(x_ptr) == &amp;const i32);
1599
1600 // If you want to mutate the value, you'd need an address of a mutable variable:
1601 var y: i32 = 5678;
1602 const y_ptr = &y;
1603 assert(@typeOf(y_ptr) == &amp;i32);
1604 *y_ptr += 1;
1605 assert(*y_ptr == 5679);
1606}
1607
1608test "pointer array access" {
1609 // Pointers do not support pointer arithmetic. If you
1610 // need such a thing, use array index syntax:
1611
1612 var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1613 const ptr = &amp;array[1];
1614
1615 assert(array[2] == 3);
1616 ptr[1] += 1;
1617 assert(array[2] == 4);
1618}
1619
1620test "pointer slicing" {
1621 // In Zig, we prefer using slices over null-terminated pointers.
1622 // You can turn a pointer into a slice using slice syntax:
1623 var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1624 const ptr = &amp;array[1];
1625 const slice = ptr[1..3];
1626
1627 assert(slice.ptr == &amp;ptr[1]);
1628 assert(slice.len == 2);
1629
1630 // Slices have bounds checking and are therefore protected
1631 // against this kind of undefined behavior. This is one reason
1632 // we prefer slices to pointers.
1633 assert(array[3] == 4);
1634 slice[1] += 1;
1635 assert(array[3] == 5);
1636}
1637
1638comptime {
1639 // Pointers work at compile-time too, as long as you don't use
1640 // @ptrCast.
1641 var x: i32 = 1;
1642 const ptr = &amp;x;
1643 *ptr += 1;
1644 x += 1;
1645 assert(*ptr == 3);
1646}
1647
1648test "@ptrToInt and @intToPtr" {
1649 // To convert an integer address into a pointer, use @intToPtr:
1650 const ptr = @intToPtr(&amp;i32, 0xdeadbeef);
1651
1652 // To convert a pointer to an integer, use @ptrToInt:
1653 const addr = @ptrToInt(ptr);
1654
1655 assert(@typeOf(addr) == usize);
1656 assert(addr == 0xdeadbeef);
1657}
1658
1659comptime {
1660 // Zig is able to do this at compile-time, as long as
1661 // ptr is never dereferenced.
1662 const ptr = @intToPtr(&amp;i32, 0xdeadbeef);
1663 const addr = @ptrToInt(ptr);
1664 assert(@typeOf(addr) == usize);
1665 assert(addr == 0xdeadbeef);
1666}
1667
1668test "volatile" {
1669 // In Zig, loads and stores are assumed to not have side effects.
1670 // If a given load or store should have side effects, such as
1671 // Memory Mapped Input/Output (MMIO), use `volatile`:
1672 const mmio_ptr = @intToPtr(&amp;volatile u8, 0x12345678);
1673
1674 // Now loads and stores with mmio_ptr are guaranteed to all happen
1675 // and in the same order as in source code.
1676 assert(@typeOf(mmio_ptr) == &amp;volatile u8);
1677}
1678
1679test "nullable pointers" {
1680 // Pointers cannot be null. If you want a null pointer, use the nullable
1681 // prefix `?` to make the pointer type nullable.
1682 var ptr: ?&amp;i32 = null;
1683
1684 var x: i32 = 1;
1685 ptr = &amp;x;
1686
1687 assert(*??ptr == 1);
1688
1689 // Nullable pointers are the same size as normal pointers, because pointer
1690 // value 0 is used as the null value.
1691 assert(@sizeOf(?&amp;i32) == @sizeOf(&amp;i32));
1692}
1693
1694test "pointer casting" {
1695 // To convert one pointer type to another, use @ptrCast. This is an unsafe
1696 // operation that Zig cannot protect you against. Use @ptrCast only when other
1697 // conversions are not possible.
1698 const bytes = []u8{0x12, 0x12, 0x12, 0x12};
1699 const u32_ptr = @ptrCast(&amp;const u32, &amp;bytes[0]);
1700 assert(*u32_ptr == 0x12121212);
1701
1702 // Even this example is contrived - there are better ways to do the above than
1703 // pointer casting. For example, using a slice narrowing cast:
1704 const u32_value = ([]const u32)(bytes[0..])[0];
1705 assert(u32_value == 0x12121212);
1706
1707 // And even another way, the most straightforward way to do it:
1708 assert(@bitCast(u32, bytes) == 0x12121212);
1709}
1710
1711test "pointer child type" {
1712 // pointer types have a `child` field which tells you the type they point to.
1713 assert((&amp;u32).child == u32);
1714}</code></pre>
1715 <pre><code class="sh">$ zig test test.zig
1716Test 1/8 address of syntax...OK
1717Test 2/8 pointer array access...OK
1718Test 3/8 pointer slicing...OK
1719Test 4/8 @ptrToInt and @intToPtr...OK
1720Test 5/8 volatile...OK
1721Test 6/8 nullable pointers...OK
1722Test 7/8 pointer casting...OK
1723Test 8/8 pointer child type...OK</code></pre>
1724 <h3 id="alignment">Alignment</h3>
1725 <p>
1726 Each type has an <strong>alignment</strong> - a number of bytes such that,
1727 when a value of the type is loaded from or stored to memory,
1728 the memory address must be evenly divisible by this number. You can use
1729 <a href="#builtin-alignOf">@alignOf</a> to find out this value for any type.
1730 </p>
1731 <p>
1732 Alignment depends on the CPU architecture, but is always a power of two, and
1733 less than <code>1 &lt;&lt; 29</code>.
1734 </p>
1735 <p>
1736 In Zig, a pointer type has an alignment value. If the value is equal to the
1737 alignment of the underlying type, it can be omitted from the type:
1738 </p>
1739 <pre><code class="zig">const assert = @import("std").debug.assert;
1740const builtin = @import("builtin");
1741
1742test "variable alignment" {
1743 var x: i32 = 1234;
1744 const align_of_i32 = @alignOf(@typeOf(x));
1745 assert(@typeOf(&amp;x) == &amp;i32);
1746 assert(&amp;i32 == &amp;align(align_of_i32) i32);
1747 if (builtin.arch == builtin.Arch.x86_64) {
1748 assert((&amp;i32).alignment == 4);
1749 }
1750}</code></pre>
1751 <p>In the same way that a <code>&amp;i32</code> can be implicitly cast to a
1752 <code>&amp;const i32</code>, a pointer with a larger alignment can be implicitly
1753 cast to a pointer with a smaller alignment, but not vice versa.
1754 </p>
1755 <p>
1756 You can specify alignment on variables and functions. If you do this, then
1757 pointers to them get the specified alignment:
1758 </p>
1759 <pre><code class="zig">const assert = @import("std").debug.assert;
1760
1761var foo: u8 align(4) = 100;
1762
1763test "global variable alignment" {
1764 assert(@typeOf(&amp;foo).alignment == 4);
1765 assert(@typeOf(&amp;foo) == &amp;align(4) u8);
1766 const slice = (&amp;foo)[0..1];
1767 assert(@typeOf(slice) == []align(4) u8);
1768}
1769
1770fn derp() align(@sizeOf(usize) * 2) -&gt; i32 { 1234 }
1771fn noop1() align(1) {}
1772fn noop4() align(4) {}
1773
1774test "function alignment" {
1775 assert(derp() == 1234);
1776 assert(@typeOf(noop1) == fn() align(1));
1777 assert(@typeOf(noop4) == fn() align(4));
1778 noop1();
1779 noop4();
1780}</code></pre>
1781 <p>
1782 If you have a pointer or a slice that has a small alignment, but you know that it actually
1783 has a bigger alignment, use <a href="#builtin-alignCast">@alignCast</a> to change the
1784 pointer into a more aligned pointer. This is a no-op at runtime, but inserts a
1785 <a href="#undef-incorrect-pointer-alignment">safety check</a>:
1786 </p>
1787 <pre><code class="zig">const assert = @import("std").debug.assert;
1788
1789test "pointer alignment safety" {
1790 var array align(4) = []u32{0x11111111, 0x11111111};
1791 const bytes = ([]u8)(array[0..]);
1792 assert(foo(bytes) == 0x11111111);
1793}
1794fn foo(bytes: []u8) -&gt; u32 {
1795 const slice4 = bytes[1..5];
1796 const int_slice = ([]u32)(@alignCast(4, slice4));
1797 return int_slice[0];
1798}</code></pre>
1799 <pre><code class="sh">$ zig test test.zig
1800Test 1/1 pointer alignment safety...incorrect alignment
1801/home/andy/dev/zig/build/lib/zig/std/special/zigrt.zig:16:35: 0x0000000000203525 in ??? (test)
1802 @import("std").debug.panic("{}", message_ptr[0..message_len]);
1803 ^
1804/home/andy/dev/zig/build/test.zig:10:45: 0x00000000002035ec in ??? (test)
1805 const int_slice = ([]u32)(@alignCast(4, slice4));
1806 ^
1807/home/andy/dev/zig/build/test.zig:6:15: 0x0000000000203439 in ??? (test)
1808 assert(foo(bytes) == 0x11111111);
1809 ^
1810/home/andy/dev/zig/build/lib/zig/std/special/test_runner.zig:9:21: 0x00000000002162d8 in ??? (test)
1811 test_fn.func();
1812 ^
1813/home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:60:21: 0x0000000000216197 in ??? (test)
1814 return root.main();
1815 ^
1816/home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:47:13: 0x0000000000216050 in ??? (test)
1817 callMain(argc, argv, envp) %% std.os.posix.exit(1);
1818 ^
1819/home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000215fa0 in ??? (test)
1820 posixCallMainAndExit()
1821 ^
1822
1823Tests failed. Use the following command to reproduce the failure:
1824./test</code></pre>
1825 <h3 id="type-based-alias-analysis">Type Based Alias Analysis</h3>
1826 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
1827 perform some optimizations. This means that pointers of different types must
1828 not alias the same memory, with the exception of <code>u8</code>. Pointers to
1829 <code>u8</code> can alias any memory.
1830 </p>
1831 <p>As an example, this code produces undefined behavior:</p>
1832 <pre><code class="zig">*@ptrCast(&amp;u32, f32(12.34))</code></pre>
1833 <p>Instead, use <a href="#builtin-bitCast">@bitCast</a>:
1834 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
1835 <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>
1836 <p>See also:</p>
1837 <ul>
1838 <li><a href="#slices">Slices</a></li>
1839 <li><a href="#memory">Memory</a></li>
1840 </ul>
1841 <h2 id="slices">Slices</h2>
1842 <pre><code class="zig">const assert = @import("std").debug.assert;
1843
1844test "basic slices" {
1845 var array = []i32{1, 2, 3, 4};
1846 // A slice is a pointer and a length. The difference between an array and
1847 // a slice is that the array's length is part of the type and known at
1848 // compile-time, whereas the slice's length is known at runtime.
1849 // Both can be accessed with the `len` field.
1850 const slice = array[0..array.len];
1851 assert(slice.ptr == &amp;array[0]);
1852 assert(slice.len == array.len);
1853
1854 // Slices have array bounds checking. If you try to access something out
1855 // of bounds, you'll get a safety check failure:
1856 slice[10] += 1;
1857}</code></pre>
1858 <pre><code class="sh">$ zig test test.zig
1859Test 1/1 basic slices...index out of bounds
1860lib/zig/std/special/zigrt.zig:16:35: 0x0000000000203455 in ??? (test)
1861 @import("std").debug.panic("{}", message_ptr[0..message_len]);
1862 ^
1863test.zig:15:10: 0x0000000000203334 in ??? (test)
1864 slice[10] += 1;
1865 ^
1866lib/zig/std/special/test_runner.zig:9:21: 0x0000000000214b1a in ??? (test)
1867 test_fn.func();
1868 ^
1869lib/zig/std/special/bootstrap.zig:60:21: 0x00000000002149e7 in ??? (test)
1870 return root.main();
1871 ^
1872lib/zig/std/special/bootstrap.zig:47:13: 0x00000000002148a0 in ??? (test)
1873 callMain(argc, argv, envp) %% std.os.posix.exit(1);
1874 ^
1875lib/zig/std/special/bootstrap.zig:34:25: 0x00000000002147f0 in ??? (test)
1876 posixCallMainAndExit()
1877 ^
1878
1879Tests failed. Use the following command to reproduce the failure:
1880./test</code></pre>
1881 <p>This is one reason we prefer slices to pointers.</p>
1882 <pre><code class="zig">const assert = @import("std").debug.assert;
1883const mem = @import("std").mem;
1884const fmt = @import("std").fmt;
1885
1886test "using slices for strings" {
1887 // Zig has no concept of strings. String literals are arrays of u8, and
1888 // in general the string type is []u8 (slice of u8).
1889 // Here we implicitly cast [5]u8 to []const u8
1890 const hello: []const u8 = "hello";
1891 const world: []const u8 = "世界";
1892
1893 var all_together: [100]u8 = undefined;
1894 // You can use slice syntax on an array to convert an array into a slice.
1895 const all_together_slice = all_together[0..];
1896 // String concatenation example:
1897 const hello_world = fmt.bufPrint(all_together_slice, "{} {}", hello, world);
1898
1899 // Generally, you can use UTF-8 and not worry about whether something is a
1900 // string. If you don't need to deal with individual characters, no need
1901 // to decode.
1902 assert(mem.eql(u8, hello_world, "hello 世界"));
1903}
1904
1905test "slice pointer" {
1906 var array: [10]u8 = undefined;
1907 const ptr = &amp;array[0];
1908
1909 // You can use slicing syntax to convert a pointer into a slice:
1910 const slice = ptr[0..5];
1911 slice[2] = 3;
1912 assert(slice[2] == 3);
1913 // The slice is mutable because we sliced a mutable pointer.
1914 assert(@typeOf(slice) == []u8);
1915
1916 // You can also slice a slice:
1917 const slice2 = slice[2..3];
1918 assert(slice2.len == 1);
1919 assert(slice2[0] == 3);
1920}
1921
1922test "slice widening" {
1923 // Zig supports slice widening and slice narrowing. Cast a slice of u8
1924 // to a slice of anything else, and Zig will perform the length conversion.
1925 const array = []u8{0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13};
1926 const slice = ([]const u32)(array[0..]);
1927 assert(slice.len == 2);
1928 assert(slice[0] == 0x12121212);
1929 assert(slice[1] == 0x13131313);
1930}</code></pre>
1931 <pre><code class="sh">$ zig test test.zig
1932Test 1/3 using slices for strings...OK
1933Test 2/3 slice pointer...OK
1934Test 3/3 slice widening...OK</code></pre>
1935 <p>See also:</p>
1936 <ul>
1937 <li><a href="#pointers">Pointers</a></li>
1938 <li><a href="#for">for</a></li>
1939 <li><a href="#arrays">Arrays</a></li>
1940 </ul>
1941 <h2 id="struct">struct</h2>
1942 <pre><code class="zig">// Declare a struct.
1943// Zig gives no guarantees about the order of fields and whether or
1944// not there will be padding.
1945const Point = struct {
1946 x: f32,
1947 y: f32,
1948};
1949
1950// Maybe we want to pass it to OpenGL so we want to be particular about
1951// how the bytes are arranged.
1952const Point2 = packed struct {
1953 x: f32,
1954 y: f32,
1955};
1956
1957
1958// Declare an instance of a struct.
1959const p = Point {
1960 .x = 0.12,
1961 .y = 0.34,
1962};
1963
1964// Maybe we're not ready to fill out some of the fields.
1965var p2 = Point {
1966 .x = 0.12,
1967 .y = undefined,
1968};
1969
1970// Structs can have methods
1971// Struct methods are not special, they are only namespaced
1972// functions that you can call with dot syntax.
1973const Vec3 = struct {
1974 x: f32,
1975 y: f32,
1976 z: f32,
1977
1978 pub fn init(x: f32, y: f32, z: f32) -&gt; Vec3 {
1979 return Vec3 {
1980 .x = x,
1981 .y = y,
1982 .z = z,
1983 };
1984 }
1985
1986 pub fn dot(self: &amp;const Vec3, other: &amp;const Vec3) -&gt; f32 {
1987 return self.x * other.x + self.y * other.y + self.z * other.z;
1988 }
1989};
1990
1991const assert = @import("std").debug.assert;
1992test "dot product" {
1993 const v1 = Vec3.init(1.0, 0.0, 0.0);
1994 const v2 = Vec3.init(0.0, 1.0, 0.0);
1995 assert(v1.dot(v2) == 0.0);
1996
1997 // Other than being available to call with dot syntax, struct methods are
1998 // not special. You can reference them as any other declaration inside
1999 // the struct:
2000 assert(Vec3.dot(v1, v2) == 0.0);
2001}
2002
2003// Structs can have global declarations.
2004// Structs can have 0 fields.
2005const Empty = struct {
2006 pub const PI = 3.14;
2007};
2008test "struct namespaced variable" {
2009 assert(Empty.PI == 3.14);
2010 assert(@sizeOf(Empty) == 0);
2011
2012 // you can still instantiate an empty struct
2013 const does_nothing = Empty {};
2014}
2015
2016// struct field order is determined by the compiler for optimal performance.
2017// however, you can still calculate a struct base pointer given a field pointer:
2018fn setYBasedOnX(x: &amp;f32, y: f32) {
2019 const point = @fieldParentPtr(Point, "x", x);
2020 point.y = y;
2021}
2022test "field parent pointer" {
2023 var point = Point {
2024 .x = 0.1234,
2025 .y = 0.5678,
2026 };
2027 setYBasedOnX(&amp;point.x, 0.9);
2028 assert(point.y == 0.9);
2029}
2030
2031// You can return a struct from a function. This is how we do generics
2032// in Zig:
2033fn LinkedList(comptime T: type) -&gt; type {
2034 return struct {
2035 pub const Node = struct {
2036 prev: ?&amp;Node,
2037 next: ?&amp;Node,
2038 data: T,
2039 };
2040
2041 first: ?&amp;Node,
2042 last: ?&amp;Node,
2043 len: usize,
2044 };
2045}
2046
2047test "linked list" {
2048 // Functions called at compile-time are memoized. This means you can
2049 // do this:
2050 assert(LinkedList(i32) == LinkedList(i32));
2051
2052 var list = LinkedList(i32) {
2053 .first = null,
2054 .last = null,
2055 .len = 0,
2056 };
2057 assert(list.len == 0);
2058
2059 // Since types are first class values you can instantiate the type
2060 // by assigning it to a variable:
2061 const ListOfInts = LinkedList(i32);
2062 assert(ListOfInts == LinkedList(i32));
2063
2064 var node = ListOfInts.Node {
2065 .prev = null,
2066 .next = null,
2067 .data = 1234,
2068 };
2069 var list2 = LinkedList(i32) {
2070 .first = &amp;node,
2071 .last = &amp;node,
2072 .len = 1,
2073 };
2074 assert((??list2.first).data == 1234);
2075}</code></pre>
2076 <pre><code class="sh">$ zig test structs.zig
2077Test 1/4 dot product...OK
2078Test 2/4 struct namespaced variable...OK
2079Test 3/4 field parent pointer...OK
2080Test 4/4 linked list...OK</code></pre>
2081 <p>See also:</p>
2082 <ul>
2083 <li><a href="#comptime">comptime</a></li>
2084 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
2085 </ul>
2086 <h2 id="enum">enum</h2>
2087 <pre><code class="zig">const assert = @import("std").debug.assert;
2088const mem = @import("std").mem;
2089
2090// Declare an enum.
2091const Type = enum {
2092 Ok,
2093 NotOk,
2094};
2095
2096// Enums are sum types, and can hold more complex data of different types.
2097const ComplexType = enum {
2098 Ok: u8,
2099 NotOk: void,
2100};
2101
2102// Declare a specific instance of the enum variant.
2103const c = ComplexType.Ok { 0 };
2104
2105// The ordinal value of a simple enum with no data members can be
2106// retrieved by a simple cast.
2107// The value starts from 0, counting up for each member.
2108const Value = enum {
2109 Zero,
2110 One,
2111 Two,
2112};
2113test "enum ordinal value" {
2114 assert(usize(Value.Zero) == 0);
2115 assert(usize(Value.One) == 1);
2116 assert(usize(Value.Two) == 2);
2117}
2118
2119// Enums can have methods, the same as structs.
2120// Enum methods are not special, they are only namespaced
2121// functions that you can call with dot syntax.
2122const Suit = enum {
2123 Clubs,
2124 Spades,
2125 Diamonds,
2126 Hearts,
2127
2128 pub fn ordinal(self: &amp;const Suit) -&gt; u8 {
2129 u8(*self)
2130 }
2131};
2132test "enum method" {
2133 const p = Suit.Spades;
2134 assert(p.ordinal() == 1);
2135}
2136
2137// An enum variant of different types can be switched upon.
2138// The associated data can be retrieved using `|...|` syntax.
2139//
2140// A void type is not required on a tag-only member.
2141const Foo = enum {
2142 String: []const u8,
2143 Number: u64,
2144 None,
2145};
2146test "enum variant switch" {
2147 const p = Foo.Number { 54 };
2148 const what_is_it = switch (p) {
2149 // Capture by reference
2150 Foo.String =&gt; |*x| {
2151 "this is a string"
2152 },
2153
2154 // Capture by value
2155 Foo.Number =&gt; |x| {
2156 "this is a number"
2157 },
2158
2159 Foo.None =&gt; {
2160 "this is a none"
2161 }
2162 };
2163}
2164
2165// The @enumTagName and @memberCount builtin functions can be used to
2166// the string representation and number of members respectively.
2167const BuiltinType = enum {
2168 A: f32,
2169 B: u32,
2170 C,
2171};
2172
2173test "enum builtins" {
2174 assert(mem.eql(u8, @enumTagName(BuiltinType.A { 0 }), "A"));
2175 assert(mem.eql(u8, @enumTagName(BuiltinType.C), "C"));
2176 assert(@memberCount(BuiltinType) == 3);
2177}</code></pre>
2178 <pre><code class="sh">$ zig test enum.zig
2179Test 1/4 enum ordinal value...OK
2180Test 2/4 enum method...OK
2181Test 3/4 enum variant switch...OK
2182Test 4/4 enum builtins...OK</code></pre>
2183 <p>
2184 Enums are generated as a struct with a tag field and union field. Zig
2185 sorts the order of the tag and union field by the largest alignment.
2186 </p>
2187 <p>See also:</p>
2188 <ul>
2189 <li><a href="#builtin-enumTagName">@enumTagName</a></li>
2190 <li><a href="#builtin-memberCount">@memberCount</a></li>
2191 </ul>
2192 <h2 id="switch">switch</h2>
2193 <pre><code class="zig">const assert = @import("std").debug.assert;
2194const builtin = @import("builtin");
2195
2196test "switch simple" {
2197 const a: u64 = 10;
2198 const zz: u64 = 103;
2199
2200 // All branches of a switch expression must be able to be coerced to a
2201 // common type.
2202 //
2203 // Branches cannot fallthrough. If fallthrough behavior is desired, combine
2204 // the cases and use an if.
2205 const b = switch (a) {
2206 // Multiple cases can be combined via a ','
2207 1, 2, 3 =&gt; 0,
2208
2209 // Ranges can be specified using the ... syntax. These are inclusive
2210 // both ends.
2211 5 ... 100 =&gt; 1,
2212
2213 // Branches can be arbitrarily complex.
2214 101 =&gt; {
2215 const c: u64 = 5;
2216 c * 2 + 1
2217 },
2218
2219 // Switching on arbitrary expressions is allowed as long as the
2220 // expression is known at compile-time.
2221 zz =&gt; zz,
2222 comptime {
2223 const d: u32 = 5;
2224 const e: u32 = 100;
2225 d + e
2226 } =&gt; 107,
2227
2228 // The else branch catches everything not already captured.
2229 // Else branches are mandatory unless the entire range of values
2230 // is handled.
2231 else =&gt; 9,
2232 };
2233
2234 assert(b == 1);
2235}
2236
2237test "switch enum" {
2238 const Item = enum {
2239 A: u32,
2240 C: struct { x: u8, y: u8 },
2241 D,
2242 };
2243
2244 var a = Item.A { 3 };
2245
2246 // Switching on more complex enums is allowed.
2247 const b = switch (a) {
2248 // A capture group is allowed on a match, and will return the enum
2249 // value matched.
2250 Item.A =&gt; |item| item,
2251
2252 // A reference to the matched value can be obtained using `*` syntax.
2253 Item.C =&gt; |*item| {
2254 (*item).x += 1;
2255 6
2256 },
2257
2258 // No else is required if the types cases was exhaustively handled
2259 Item.D =&gt; 8,
2260 };
2261
2262 assert(b == 3);
2263}
2264
2265// Switch expressions can be used outside a function:
2266const os_msg = switch (builtin.os) {
2267 builtin.Os.linux =&gt; "we found a linux user",
2268 else =&gt; "not a linux user",
2269};
2270
2271// Inside a function, switch statements implicitly are compile-time
2272// evaluated if the target expression is compile-time known.
2273test "switch inside function" {
2274 switch (builtin.os) {
2275 builtin.Os.windows =&gt; {
2276 // On an OS other than windows, block is not even analyzed,
2277 // so this compile error is not triggered.
2278 // On windows this compile error would be triggered.
2279 @compileError("windows not supported");
2280 },
2281 else =&gt; {},
2282 };
2283}</code></pre>
2284 <pre><code class="sh">$ zig test switch.zig
2285Test 1/2 switch simple...OK
2286Test 2/2 switch enum...OK
2287Test 3/3 switch inside function...OK</code></pre>
2288 <p>See also:</p>
2289 <ul>
2290 <li><a href="#comptime">comptime</a></li>
2291 <li><a href="#enum">enum</a></li>
2292 <li><a href="#builtin-compileError">@compileError</a></li>
2293 <li><a href="#compile-variables">Compile Variables</a></li>
2294 </ul>
2295 <h2 id="while">while</h2>
2296 <pre><code class="zig">const assert = @import("std").debug.assert;
2297
2298test "while basic" {
2299 // A while loop is used to repeatedly execute an expression until
2300 // some condition is no longer true.
2301 var i: usize = 0;
2302 while (i &lt; 10) {
2303 i += 1;
2304 }
2305 assert(i == 10);
2306}
2307
2308test "while break" {
2309 // You can use break to exit a while loop early.
2310 var i: usize = 0;
2311 while (true) {
2312 if (i == 10)
2313 break;
2314 i += 1;
2315 }
2316 assert(i == 10);
2317}
2318
2319test "while continue" {
2320 // You can use continue to jump back to the beginning of the loop.
2321 var i: usize = 0;
2322 while (true) {
2323 i += 1;
2324 if (i &lt; 10)
2325 continue;
2326 break;
2327 }
2328 assert(i == 10);
2329}
2330
2331test "while loop continuation expression" {
2332 // You can give an expression to the while loop to execute when
2333 // the loop is continued. This is respected by the continue control flow.
2334 var i: usize = 0;
2335 while (i &lt; 10) : (i += 1) {}
2336 assert(i == 10);
2337}
2338
2339test "while loop continuation expression, more complicated" {
2340 // More complex blocks can be used as an expression in the loop continue
2341 // expression.
2342 var i1: usize = 1;
2343 var j1: usize = 1;
2344 while (i1 * j1 &lt; 2000) : ({ i1 *= 2; j1 *= 3; }) {
2345 const my_ij1 = i1 * j1;
2346 assert(my_ij1 &lt; 2000);
2347 }
2348}
2349
2350test "while else" {
2351 assert(rangeHasNumber(0, 10, 5));
2352 assert(!rangeHasNumber(0, 10, 15));
2353}
2354
2355fn rangeHasNumber(begin: usize, end: usize, number: usize) -&gt; bool {
2356 var i = begin;
2357 // While loops are expressions. The result of the expression is the
2358 // result of the else clause of a while loop, which is executed when
2359 // the condition of the while loop is tested as false.
2360 return while (i &lt; end) : (i += 1) {
2361 if (i == number) {
2362 // break expressions, like return expressions, accept a value
2363 // parameter. This is the result of the while expression.
2364 // When you break from a while loop, the else branch is not
2365 // evaluated.
2366 break true;
2367 }
2368 } else {
2369 false
2370 }
2371}
2372
2373test "while null capture" {
2374 // Just like if expressions, while loops can take a nullable as the
2375 // condition and capture the payload. When null is encountered the loop
2376 // exits.
2377 var sum1: u32 = 0;
2378 numbers_left = 3;
2379 while (eventuallyNullSequence()) |value| {
2380 sum1 += value;
2381 }
2382 assert(sum1 == 3);
2383
2384 // The else branch is allowed on nullable iteration. In this case, it will
2385 // be executed on the first null value encountered.
2386 var sum2: u32 = 0;
2387 numbers_left = 3;
2388 while (eventuallyNullSequence()) |value| {
2389 sum2 += value;
2390 } else {
2391 assert(sum1 == 3);
2392 }
2393
2394 // Just like if expressions, while loops can also take an error union as
2395 // the condition and capture the payload or the error code. When the
2396 // condition results in an error code the else branch is evaluated and
2397 // the loop is finished.
2398 var sum3: u32 = 0;
2399 numbers_left = 3;
2400 while (eventuallyErrorSequence()) |value| {
2401 sum3 += value;
2402 } else |err| {
2403 assert(err == error.ReachedZero);
2404 }
2405}
2406
2407var numbers_left: u32 = undefined;
2408fn eventuallyNullSequence() -&gt; ?u32 {
2409 return if (numbers_left == 0) {
2410 null
2411 } else {
2412 numbers_left -= 1;
2413 numbers_left
2414 }
2415}
2416error ReachedZero;
2417fn eventuallyErrorSequence() -&gt; %u32 {
2418 return if (numbers_left == 0) {
2419 error.ReachedZero
2420 } else {
2421 numbers_left -= 1;
2422 numbers_left
2423 }
2424}
2425
2426test "inline while loop" {
2427 // While loops can be inlined. This causes the loop to be unrolled, which
2428 // allows the code to do some things which only work at compile time,
2429 // such as use types as first class values.
2430 comptime var i = 0;
2431 var sum: usize = 0;
2432 inline while (i &lt; 3) : (i += 1) {
2433 const T = switch (i) {
2434 0 =&gt; f32,
2435 1 =&gt; i8,
2436 2 =&gt; bool,
2437 else =&gt; unreachable,
2438 };
2439 sum += typeNameLength(T);
2440 }
2441 assert(sum == 9);
2442}
2443
2444fn typeNameLength(comptime T: type) -&gt; usize {
2445 return @typeName(T).len;
2446}</code></pre>
2447 <pre><code class="sh">$ zig while.zig
2448Test 1/8 while basic...OK
2449Test 2/8 while break...OK
2450Test 3/8 while continue...OK
2451Test 4/8 while loop continuation expression...OK
2452Test 5/8 while loop continuation expression, more complicated...OK
2453Test 6/8 while else...OK
2454Test 7/8 while null capture...OK
2455Test 8/8 inline while loop...OK</code></pre>
2456 <p>See also:</p>
2457 <ul>
2458 <li><a href="#if">if</a></li>
2459 <li><a href="#nullables">Nullables</a></li>
2460 <li><a href="#errors">Errors</a></li>
2461 <li><a href="#comptime">comptime</a></li>
2462 <li><a href="#unreachable">unreachable</a></li>
2463 </ul>
2464 <h2 id="for">for</h2>
2465 <pre><code class="zig">const assert = @import("std").debug.assert;
2466
2467test "for basics" {
2468 const items = []i32 { 4, 5, 3, 4, 0 };
2469 var sum: i32 = 0;
2470
2471 // For loops iterate over slices and arrays.
2472 for (items) |value| {
2473 // Break and continue are supported.
2474 if (value == 0) {
2475 continue;
2476 }
2477 sum += value;
2478 }
2479 assert(sum == 16);
2480
2481 // To iterate over a portion of a slice, reslice.
2482 for (items[0..1]) |value| {
2483 sum += value;
2484 }
2485 assert(sum == 20);
2486
2487 // To access the index of iteration, specify a second capture value.
2488 // This is zero-indexed.
2489 var sum2: i32 = 0;
2490 for (items) |value, i| {
2491 assert(@typeOf(i) == usize);
2492 sum2 += i32(i);
2493 }
2494 assert(sum2 == 10);
2495}
2496
2497test "for reference" {
2498 var items = []i32 { 3, 4, 2 };
2499
2500 // Iterate over the slice by reference by
2501 // specifying that the capture value is a pointer.
2502 for (items) |*value| {
2503 *value += 1;
2504 }
2505
2506 assert(items[0] == 4);
2507 assert(items[1] == 5);
2508 assert(items[2] == 3);
2509}
2510
2511test "for else" {
2512 // For allows an else attached to it, the same as a while loop.
2513 var items = []?i32 { 3, 4, null, 5 };
2514
2515 // For loops can also be used as expressions.
2516 var sum: i32 = 0;
2517 const result = for (items) |value| {
2518 if (value == null) {
2519 break 9;
2520 } else {
2521 sum += ??value;
2522 }
2523 } else {
2524 assert(sum == 7);
2525 sum
2526 };
2527}
2528
2529
2530test "inline for loop" {
2531 const nums = []i32{2, 4, 6};
2532 // For loops can be inlined. This causes the loop to be unrolled, which
2533 // allows the code to do some things which only work at compile time,
2534 // such as use types as first class values.
2535 // The capture value and iterator value of inlined for loops are
2536 // compile-time known.
2537 var sum: usize = 0;
2538 inline for (nums) |i| {
2539 const T = switch (i) {
2540 2 =&gt; f32,
2541 4 =&gt; i8,
2542 6 =&gt; bool,
2543 else =&gt; unreachable,
2544 };
2545 sum += typeNameLength(T);
2546 }
2547 assert(sum == 9);
2548}
2549
2550fn typeNameLength(comptime T: type) -&gt; usize {
2551 return @typeName(T).len;
2552}</code></pre>
2553 <pre><code class="sh">$ zig test for.zig
2554Test 1/4 for basics...OK
2555Test 2/4 for reference...OK
2556Test 3/4 for else...OK
2557Test 4/4 inline for loop...OK</code></pre>
2558 <p>See also:</p>
2559 <ul>
2560 <li><a href="#while">while</a></li>
2561 <li><a href="#comptime">comptime</a></li>
2562 <li><a href="#arrays">Arrays</a></li>
2563 <li><a href="#slices">Slices</a></li>
2564 </ul>
2565 <h2 id="if">if</h2>
2566 <pre><code class="zig">// If expressions have three uses, corresponding to the three types:
2567// * bool
2568// * ?T
2569// * %T
2570
2571const assert = @import("std").debug.assert;
2572
2573test "if boolean" {
2574 // If expressions test boolean conditions.
2575 const a: u32 = 5;
2576 const b: u32 = 4;
2577 if (a != b) {
2578 assert(true);
2579 } else if (a == 9) {
2580 unreachable
2581 } else {
2582 unreachable
2583 }
2584
2585 // If expressions are used instead of a ternary expression.
2586 const result = if (a != b) 47 else 3089;
2587 assert(result == 47);
2588}
2589
2590test "if nullable" {
2591 // If expressions test for null.
2592
2593 const a: ?u32 = 0;
2594 if (a) |value| {
2595 assert(value == 0);
2596 } else {
2597 unreachable;
2598 }
2599
2600 const b: ?u32 = null;
2601 if (b) |value| {
2602 unreachable;
2603 } else {
2604 assert(true);
2605 }
2606
2607 // The else is not required.
2608 if (a) |value| {
2609 assert(value == 0);
2610 }
2611
2612 // To test against null only, use the binary equality operator.
2613 if (b == null) {
2614 assert(true);
2615 }
2616
2617 // Access the value by reference using a pointer capture.
2618 var c: ?u32 = 3;
2619 if (c) |*value| {
2620 *value = 2;
2621 }
2622
2623 if (c) |value| {
2624 assert(value == 2);
2625 } else {
2626 unreachable;
2627 }
2628}
2629
2630error BadValue;
2631error LessBadValue;
2632test "if error union" {
2633 // If expressions test for errors.
2634 // Note the |err| capture on the else.
2635
2636 const a: %u32 = 0;
2637 if (a) |value| {
2638 assert(value == 0);
2639 } else |err| {
2640 unreachable
2641 }
2642
2643 const b: %u32 = error.BadValue;
2644 if (b) |value| {
2645 unreachable
2646 } else |err| {
2647 assert(err == error.BadValue);
2648 }
2649
2650 // The else and |err| capture is strictly required.
2651 if (a) |value| {
2652 assert(value == 0);
2653 } else |_| {}
2654
2655 // To check only the error value, use an empty block expression.
2656 if (b) |_| {} else |err| {
2657 assert(err == error.BadValue);
2658 }
2659
2660 // Access the value by reference using a pointer capture.
2661 var c: %u32 = 3;
2662 if (c) |*value| {
2663 *value = 9;
2664 } else |err| {
2665 unreachable
2666 }
2667
2668 if (c) |value| {
2669 assert(value == 9);
2670 } else |err| {
2671 unreachable
2672 }
2673}</code></pre>
2674 <pre><code class="sh">$ zig test if.zig
2675Test 1/3 if boolean...OK
2676Test 2/3 if nullable...OK
2677Test 3/3 if error union...OK</code></pre>
2678 <p>See also:</p>
2679 <ul>
2680 <li><a href="#nullables">Nullables</a></li>
2681 <li><a href="#errors">Errors</a></li>
2682 </ul>
2683 <h2 id="goto">goto</h2>
2684 <pre><code class="zig">const assert = @import("std").debug.assert;
2685
2686test "goto" {
2687 var value = false;
2688 goto label;
2689 value = true;
2690
2691label:
2692 assert(value == false);
2693}
2694</code></pre>
2695 <pre><code class="sh">$ zig test goto.zig
2696Test 1/1 goto...OK
2697</code></pre>
2698<p>Note that there are <a href="https://github.com/zig-lang/zig/issues/346">plans to remove goto</a></p>
2699 <h2 id="defer">defer</h2>
2700 <pre><code class="zig">const assert = @import("std").debug.assert;
2701const printf = @import("std").io.stdout.printf;
2702
2703// defer will execute an expression at the end of the current scope.
2704fn deferExample() -&gt; usize {
2705 var a: usize = 1;
2706
2707 {
2708 defer a = 2;
2709 a = 1;
2710 }
2711 assert(a == 2);
2712
2713 a = 5;
2714 a
2715}
2716
2717test "defer basics" {
2718 assert(deferExample() == 5);
2719}
2720
2721// If multiple defer statements are specified, they will be executed in
2722// the reverse order they were run.
2723fn deferUnwindExample() {
2724 %%printf("\n");
2725
2726 defer {
2727 %%printf("1 ");
2728 }
2729 defer {
2730 %%printf("2 ");
2731 }
2732 if (false) {
2733 // defers are not run if they are never executed.
2734 defer {
2735 %%printf("3 ");
2736 }
2737 }
2738}
2739
2740test "defer unwinding" {
2741 deferUnwindExample()
2742}
2743
2744// The %defer keyword is similar to defer, but will only execute if the
2745// scope returns with an error.
2746//
2747// This is especially useful in allowing a function to clean up properly
2748// on error, and replaces goto error handling tactics as seen in c.
2749error DeferError;
2750fn deferErrorExample(is_error: bool) -&gt; %void {
2751 %%printf("\nstart of function\n");
2752
2753 // This will always be executed on exit
2754 defer {
2755 %%printf("end of function\n");
2756 }
2757
2758 %defer {
2759 %%printf("encountered an error!\n");
2760 }
2761
2762 if (is_error) {
2763 return error.DeferError;
2764 }
2765}
2766
2767test "%defer unwinding" {
2768 _ = deferErrorExample(false);
2769 _ = deferErrorExample(true);
2770}
2771</code></pre>
2772 <pre><code class="sh">$ zig test defer.zig
2773Test 1/3 defer basics...OK
2774Test 2/3 defer unwinding...
27752 1 OK
2776Test 3/3 %defer unwinding...
2777start of function
2778end of function
2779
2780start of function
2781encountered an error!
2782end of function
2783OK
2784</code></pre>
2785 <p>See also:</p>
2786 <ul>
2787 <li><a href="#errors">Errors</a></li>
2788 </ul>
2789 <h2 id="unreachable">unreachable</h2>
2790 <p>
2791 In <code>Debug</code> and <code>ReleaseSafe</code> mode, and when using <code>zig test</code>,
2792 <code>unreachable</code> emits a call to <code>panic</code> with the message <code>reached unreachable code</code>.
2793 </p>
2794 <p>
2795 In <code>ReleaseFast</code> mode, the optimizer uses the assumption that <code>unreachable</code> code
2796 will never be hit to perform optimizations. However, <code>zig test</code> even in <code>ReleaseFast</code> mode
2797 still emits <code>unreachable</code> as calls to <code>panic</code>.
2798 </p>
2799 <h3 id="unreachable-basics">Basics</h3>
2800 <pre><code class="zig">// unreachable is used to assert that control flow will never happen upon a
2801// particular location:
2802test "basic math" {
2803 const x = 1;
2804 const y = 2;
2805 if (x + y != 3) {
2806 unreachable;
2807 }
2808}
2809
2810// in fact, this is how assert is implemented:
2811fn assert(ok: bool) {
2812 if (!ok) unreachable; // assertion failure
2813}
2814
2815// This test will fail because we hit unreachable.
2816test "this will fail" {
2817 assert(false);
2818}</code></pre>
2819 <pre><code class="sh">$ zig test test.zig
2820Test 1/2 basic math...OK
2821Test 2/2 this will fail...reached unreachable code
2822test.zig:13:14: 0x00000000002033ac in ??? (test)
2823 if (!ok) unreachable; // assertion failure
2824 ^
2825test.zig:18:11: 0x000000000020329b in ??? (test)
2826 assert(false);
2827 ^
2828lib/zig/std/special/test_runner.zig:9:21: 0x0000000000214a7a in ??? (test)
2829 test_fn.func();
2830 ^
2831lib/zig/std/special/bootstrap.zig:60:21: 0x0000000000214947 in ??? (test)
2832 return root.main();
2833 ^
2834lib/zig/std/special/bootstrap.zig:47:13: 0x0000000000214800 in ??? (test)
2835 callMain(argc, argv, envp) %% std.os.posix.exit(1);
2836 ^
2837lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test)
2838 posixCallMainAndExit()
2839 ^
2840
2841Tests failed. Use the following command to reproduce the failure:
2842./test</code></pre>
2843 <h3 id="unreachable-comptime">At Compile-Time</h3>
2844 <pre><code class="zig">const assert = @import("std").debug.assert;
2845
2846comptime {
2847 // The type of unreachable is noreturn.
2848
2849 // However this assertion will still fail because
2850 // evaluating unreachable at compile-time is a compile error.
2851
2852 assert(@typeOf(unreachable) == noreturn);
2853}</code></pre>
2854 <pre><code class="sh">$ zig build-obj test.zig
2855test.zig:9:12: error: unreachable code
2856 assert(@typeOf(unreachable) == noreturn);
2857 ^</code></pre>
2858 <p>See also:</p>
2859 <ul>
2860 <li><a href="#zig-test">Zig Test</a></li>
2861 <li><a href="#build-mode">Build Mode</a></li>
2862 <li><a href="#comptime">comptime</a></li>
2863 </ul>
2864 <h2 id="noreturn">noreturn</h2>
2865 <p>
2866 <code>noreturn</code> is the type of:
2867 </p>
2868 <ul>
2869 <li><code>break</code></li>
2870 <li><code>continue</code></li>
2871 <li><code>goto</code></li>
2872 <li><code>return</code></li>
2873 <li><code>unreachable</code></li>
2874 <li><code>while (true) {}</code></li>
2875 </ul>
2876 <p>When resolving types together, such as <code>if</code> clauses or <code>switch</code> prongs,
2877 the <code>noreturn</code> type is compatible with every other type. Consider:
2878 </p>
2879 <pre><code class="zig">fn foo(condition: bool, b: u32) {
2880 const a = if (condition) b else return;
2881 bar(a);
2882}
2883
2884extern fn bar(value: u32);</code></pre>
2885 <p>Another use case for <code>noreturn</code> is the <code>exit</code> function:</p>
2886 <pre><code class="zig">pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) -&gt; noreturn;
2887
2888fn foo() {
2889 const value = bar() %% ExitProcess(1);
2890 assert(value == 1234);
2891}
2892
2893fn bar() -&gt; %u32 {
2894 return 1234;
2895}
2896
2897const assert = @import("std").debug.assert;</code></pre>
2898 <h2 id="functions">Functions</h2>
2899 <pre><code class="zig">const assert = @import("std").debug.assert;
2900
2901// Functions are declared like this
2902// The last expression in the function can be used as the return value.
2903fn add(a: i8, b: i8) -&gt; i8 {
2904 if (a == 0) {
2905 // You can still return manually if needed.
2906 return b;
2907 }
2908
2909 a + b
2910}
2911
2912// The export specifier makes a function externally visible in the generated
2913// object file, and makes it use the C ABI.
2914export fn sub(a: i8, b: i8) -&gt; i8 { a - b }
2915
2916// The extern specifier is used to declare a function that will be resolved
2917// at link time, when linking statically, or at runtime, when linking
2918// dynamically.
2919// The stdcallcc specifier changes the calling convention of the function.
2920extern "kernel32" stdcallcc fn ExitProcess(exit_code: u32) -&gt; noreturn;
2921extern "c" fn atan2(a: f64, b: f64) -&gt; f64;
2922
2923// coldcc makes a function use the cold calling convention.
2924coldcc fn abort() -&gt; noreturn {
2925 while (true) {}
2926}
2927
2928// nakedcc makes a function not have any function prologue or epilogue.
2929// This can be useful when integrating with assembly.
2930nakedcc fn _start() -&gt; noreturn {
2931 abort();
2932}
2933
2934// The pub specifier allows the function to be visible when importing.
2935// Another file can use @import and call sub2
2936pub fn sub2(a: i8, b: i8) -&gt; i8 { a - b }
2937
2938// Functions can be used as values and are equivalent to pointers.
2939const call2_op = fn (a: i8, b: i8) -&gt; i8;
2940fn do_op(fn_call: call2_op, op1: i8, op2: i8) -&gt; i8 {
2941 fn_call(op1, op2)
2942}
2943
2944test "function" {
2945 assert(do_op(add, 5, 6) == 11);
2946 assert(do_op(sub2, 5, 6) == -1);
2947}</code></pre>
2948 <pre><code class="sh">$ zig test function.zig
2949Test 1/1 function...OK
2950</code></pre>
2951 <p>Function values are like pointers:</p>
2952 <pre><code class="zig">const assert = @import("std").debug.assert;
2953
2954comptime {
2955 assert(@typeOf(foo) == fn());
2956 assert(@sizeOf(fn()) == @sizeOf(?fn()));
2957}
2958
2959fn foo() { }</code></pre>
2960 <pre><code class="sh">$ zig build-obj test.zig</code></pre>
2961 <h3 id="functions-by-val-params">Pass-by-value Parameters</h3>
2962 <p>
2963 In Zig, structs, unions, and enums with payloads cannot be passed by value
2964 to a function.
2965 </p>
2966 <pre><code class="zig">const Foo = struct {
2967 x: i32,
2968};
2969
2970fn bar(foo: Foo) {}
2971
2972export fn entry() {
2973 bar(Foo {.x = 12,});
2974}</code></pre>
2975 <pre><code class="sh">$ ./zig build-obj test.zig
2976/home/andy/dev/zig/build/test.zig:5:13: error: type 'Foo' is not copyable; cannot pass by value
2977fn bar(foo: Foo) {}
2978 ^</code></pre>
2979 <p>
2980 Instead, one must use <code>&amp;const</code>. Zig allows implicitly casting something
2981 to a const pointer to it:
2982 </p>
2983 <pre><code class="zig">const Foo = struct {
2984 x: i32,
2985};
2986
2987fn bar(foo: &amp;const Foo) {}
2988
2989export fn entry() {
2990 bar(Foo {.x = 12,});
2991}</code></pre>
2992 <p>
2993 However,
2994 the C ABI does allow passing structs and unions by value. So functions which
2995 use the C calling convention may pass structs and unions by value.
2996 </p>
2997 <h2 id="errors">Errors</h2>
2998 <p>
2999 One of the distinguishing features of Zig is its exception handling strategy.
3000 </p>
3001 <p>
3002 Among the top level declarations available is the error value declaration:
3003 </p>
3004 <pre><code class="zig">error FileNotFound;
3005error OutOfMemory;
3006error UnexpectedToken;</code></pre>
3007 <p>
3008 These error values are assigned an unsigned integer value greater than 0 at
3009 compile time. You are allowed to declare the same error value more than once,
3010 and if you do, it gets assigned the same integer value.
3011 </p>
3012 <p>
3013 You can refer to these error values with the error namespace such as
3014 <code>error.FileNotFound</code>.
3015 </p>
3016 <p>
3017 Each error value across the entire compilation unit gets a unique integer,
3018 and this determines the size of the pure error type.
3019 </p>
3020 <p>
3021 The pure error type is one of the error values, and in the same way that pointers
3022 cannot be null, a pure error is always an error.
3023 </p>
3024 <pre><code class="zig">const pure_error = error.FileNotFound;</code></pre>
3025 <p>
3026 Most of the time you will not find yourself using a pure error type. Instead,
3027 likely you will be using the error union type. This is when you take a normal type,
3028 and prefix it with the <code>%</code> operator.
3029 </p>
3030 <p>
3031 Here is a function to parse a string into a 64-bit integer:
3032 </p>
3033 <pre><code class="zig">error InvalidChar;
3034error Overflow;
3035
3036pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
3037 var x: u64 = 0;
3038
3039 for (buf) |c| {
3040 const digit = charToDigit(c);
3041
3042 if (digit &gt;= radix) {
3043 return error.InvalidChar;
3044 }
3045
3046 // x *= radix
3047 if (@mulWithOverflow(u64, x, radix, &amp;x)) {
3048 return error.Overflow;
3049 }
3050
3051 // x += digit
3052 if (@addWithOverflow(u64, x, digit, &amp;x)) {
3053 return error.Overflow;
3054 }
3055 }
3056
3057 return x;
3058}</code></pre>
3059 <p>
3060 Notice the return type is <code>%u64</code>. This means that the function
3061 either returns an unsigned 64 bit integer, or an error.
3062 </p>
3063 <p>
3064 Within the function definition, you can see some return statements that return
3065 a pure error, and at the bottom a return statement that returns a <code>u64</code>.
3066 Both types implicitly cast to <code>%u64</code>.
3067 </p>
3068 <p>
3069 What it looks like to use this function varies depending on what you're
3070 trying to do. One of the following:
3071 </p>
3072 <ul>
3073 <li>You want to provide a default value if it returned an error.</li>
3074 <li>If it returned an error then you want to return the same error.</li>
3075 <li>You know with complete certainty it will not return an error, so want to unconditionally unwrap it.</li>
3076 <li>You want to take a different action for each possible error.</li>
3077 </ul>
3078 <p>If you want to provide a default value, you can use the <code>%%</code> binary operator:</p>
3079 <pre><code class="zig">fn doAThing(str: []u8) {
3080 const number = parseU64(str, 10) %% 13;
3081 // ...
3082}</code></pre>
3083 <p>
3084 In this code, <code>number</code> will be equal to the successfully parsed string, or
3085 a default value of 13. The type of the right hand side of the binary <code>%%</code> operator must
3086 match the unwrapped error union type, or be of type <code>noreturn</code>.
3087 </p>
3088 <p>Let's say you wanted to return the error if you got one, otherwise continue with the
3089 function logic:</p>
3090 <pre><code class="zig">fn doAThing(str: []u8) -&gt; %void {
3091 const number = parseU64(str, 10) %% |err| return err;
3092 // ...
3093}</code></pre>
3094 <p>
3095 There is a shortcut for this. The <code>%return</code> expression:
3096 </p>
3097 <pre><code class="zig">fn doAThing(str: []u8) -&gt; %void {
3098 const number = %return parseU64(str, 10);
3099 // ...
3100}</code></pre>
3101 <p>
3102 <code>%return</code> evaluates an error union expression. If it is an error, it returns
3103 from the current function with the same error. Otherwise, the expression results in
3104 the unwrapped value.
3105 </p>
3106 <p>
3107 Maybe you know with complete certainty that an expression will never be an error.
3108 In this case you can do this:
3109 </p>
3110 <pre><code class="zig">const number = parseU64("1234", 10) %% unreachable;</code></pre>
3111 <p>
3112 Here we know for sure that "1234" will parse successfully. So we put the
3113 <code>unreachable</code> value on the right hand side. <code>unreachable</code> generates
3114 a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the
3115 application, if there <em>was</em> a surprise error here, the application would crash
3116 appropriately.
3117 </p>
3118 <p>Again there is a syntactic shortcut for this:</p>
3119 <pre><code class="zig">const number = %%parseU64("1234", 10);</code></pre>
3120 <p>
3121 The <code>%%</code> <em>prefix</em> operator is equivalent to <code class="zig">expression %% unreachable</code>. It unwraps an error union type,
3122 and panics in debug mode if the value was an error.
3123 </p>
3124 <p>
3125 Finally, you may want to take a different action for every situation. For that, we combine
3126 the <code>if</code> and <code>switch</code> expression:
3127 </p>
3128 <pre><code class="zig">fn doAThing(str: []u8) {
3129 if (parseU64(str, 10)) |number| {
3130 doSomethingWithNumber(number);
3131 } else |err| switch (err) {
3132 error.Overflow =&gt; {
3133 // handle overflow...
3134 },
3135 // we promise that InvalidChar won't happen (or crash in debug mode if it does)
3136 error.InvalidChar =&gt; unreachable,
3137 }
3138}</code></pre>
3139 <p>
3140 The other component to error handling is defer statements.
3141 In addition to an unconditional <code>defer</code>, Zig has <code>%defer</code>,
3142 which evaluates the deferred expression on block exit path if and only if
3143 the function returned with an error from the block.
3144 </p>
3145 <p>
3146 Example:
3147 </p>
3148 <pre><code class="zig">fn createFoo(param: i32) -&gt; %Foo {
3149 const foo = %return tryToAllocateFoo();
3150 // now we have allocated foo. we need to free it if the function fails.
3151 // but we want to return it if the function succeeds.
3152 %defer deallocateFoo(foo);
3153
3154 const tmp_buf = allocateTmpBuffer() ?? return error.OutOfMemory;
3155 // tmp_buf is truly a temporary resource, and we for sure want to clean it up
3156 // before this block leaves scope
3157 defer deallocateTmpBuffer(tmp_buf);
3158
3159 if (param &gt; 1337) return error.InvalidParam;
3160
3161 // here the %defer will not run since we're returning success from the function.
3162 // but the defer will run!
3163 return foo;
3164}</code></pre>
3165 <p>
3166 The neat thing about this is that you get robust error handling without
3167 the verbosity and cognitive overhead of trying to make sure every exit path
3168 is covered. The deallocation code is always directly following the allocation code.
3169 </p>
3170 <p>
3171 A couple of other tidbits about error handling:
3172 </p>
3173 <ul>
3174 <li>These primitives give enough expressiveness that it's completely practical
3175 to have failing to check for an error be a compile error. If you really want
3176 to ignore the error, you can use the <code>%%</code> prefix operator and
3177 get the added benefit of crashing in Debug and ReleaseSafe modes if your assumption was wrong.
3178 </li>
3179 <li>
3180 Since Zig understands error types, it can pre-weight branches in favor of
3181 errors not occuring. Just a small optimization benefit that is not available
3182 in other languages.
3183 </li>
3184 </ul>
3185 <p>See also:</p>
3186 <ul>
3187 <li><a href="#defer">defer</a></li>
3188 <li><a href="#if">if</a></li>
3189 <li><a href="#switch">switch</a></li>
3190 </ul>
3191 <h2 id="nullables">Nullables</h2>
3192 <p>
3193 One area that Zig provides safety without compromising efficiency or
3194 readability is with the nullable type.
3195 </p>
3196 <p>
3197 The question mark symbolizes the nullable type. You can convert a type to a nullable
3198 type by putting a question mark in front of it, like this:
3199 </p>
3200 <pre><code class="zig">// normal integer
3201const normal_int: i32 = 1234;
3202
3203// nullable integer
3204const nullable_int: ?i32 = 5678;</code></pre>
3205 <p>
3206 Now the variable <code>nullable_int</code> could be an <code>i32</code>, or <code>null</code>.
3207 </p>
3208 <p>
3209 Instead of integers, let's talk about pointers. Null references are the source of many runtime
3210 exceptions, and even stand accused of being
3211 <a href="https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/">the worst mistake of computer science</a>.
3212 </p>
3213 <p>Zig does not have them.</p>
3214 <p>
3215 Instead, you can use a nullable pointer. This secretly compiles down to a normal pointer,
3216 since we know we can use 0 as the null value for the nullable type. But the compiler
3217 can check your work and make sure you don't assign null to something that can't be null.
3218 </p>
3219 <p>
3220 Typically the downside of not having null is that it makes the code more verbose to
3221 write. But, let's compare some equivalent C code and Zig code.
3222 </p>
3223 <p>
3224 Task: call malloc, if the result is null, return null.
3225 </p>
3226 <p>C code</p>
3227 <pre><code class="c">// malloc prototype included for reference
3228void *malloc(size_t size);
3229
3230struct Foo *do_a_thing(void) {
3231 char *ptr = malloc(1234);
3232 if (!ptr) return NULL;
3233 // ...
3234}</code></pre>
3235 <p>Zig code</p>
3236 <pre><code class="zig">// malloc prototype included for reference
3237extern fn malloc(size: size_t) -&gt; ?&amp;u8;
3238
3239fn doAThing() -&gt; ?&amp;Foo {
3240 const ptr = malloc(1234) ?? return null;
3241 // ...
3242}</code></pre>
3243 <p>
3244 Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr"
3245 is <code>&amp;u8</code> <em>not</em> <code>?&amp;u8</code>. The <code>??</code> operator
3246 unwrapped the nullable type and therefore <code>ptr</code> is guaranteed to be non-null everywhere
3247 it is used in the function.
3248 </p>
3249 <p>
3250 The other form of checking against NULL you might see looks like this:
3251 </p>
3252 <pre><code class="c">void do_a_thing(struct Foo *foo) {
3253 // do some stuff
3254
3255 if (foo) {
3256 do_something_with_foo(foo);
3257 }
3258
3259 // do some stuff
3260}</code></pre>
3261 <p>
3262 In Zig you can accomplish the same thing:
3263 </p>
3264 <pre><code class="zig">fn doAThing(nullable_foo: ?&amp;Foo) {
3265 // do some stuff
3266
3267 if (const foo ?= nullable_foo) {
3268 doSomethingWithFoo(foo);
3269 }
3270
3271 // do some stuff
3272}</code></pre>
3273 <p>
3274 Once again, the notable thing here is that inside the if block,
3275 <code>foo</code> is no longer a nullable pointer, it is a pointer, which
3276 cannot be null.
3277 </p>
3278 <p>
3279 One benefit to this is that functions which take pointers as arguments can
3280 be annotated with the "nonnull" attribute - <code>__attribute__((nonnull))</code> in
3281 <a href="https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html">GCC</a>.
3282 The optimizer can sometimes make better decisions knowing that pointer arguments
3283 cannot be null.
3284 </p>
3285 <h2 id="casting">Casting</h2>
3286 <p>TODO: explain implicit vs explicit casting</p>
3287 <p>TODO: resolve peer types builtin</p>
3288 <p>TODO: truncate builtin</p>
3289 <p>TODO: bitcast builtin</p>
3290 <p>TODO: int to ptr builtin</p>
3291 <p>TODO: ptr to int builtin</p>
3292 <p>TODO: ptrcast builtin</p>
3293 <p>TODO: explain number literals vs concrete types</p>
3294 <h2 id="void">void</h2>
3295 <p>TODO: assigning void has no codegen</p>
3296 <p>TODO: hashmap with void becomes a set</p>
3297 <p>TODO: difference between c_void and void</p>
3298 <p>TODO: void is the default return value of functions</p>
3299 <p>TODO: functions require assigning the return value</p>
3300 <h2 id="this">this</h2>
3301 <p>TODO: example of this referring to Self struct</p>
3302 <p>TODO: example of this referring to recursion function</p>
3303 <p>TODO: example of this referring to basic block for @setDebugSafety</p>
3304 <h2 id="comptime">comptime</h2>
3305 <p>
3306 Zig places importance on the concept of whether an expression is known at compile-time.
3307 There are a few different places this concept is used, and these building blocks are used
3308 to keep the language small, readable, and powerful.
3309 </p>
3310 <h3 id="introducing-compile-time-concept">Introducing the Compile-Time Concept</h3>
3311 <h4 id="compile-time-parameters">Compile-Time Parameters</h4>
3312 <p>
3313 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
3314 </p>
3315 <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T {
3316 if (a &gt; b) a else b
3317}
3318fn gimmeTheBiggerFloat(a: f32, b: f32) -&gt; f32 {
3319 max(f32, a, b)
3320}
3321fn gimmeTheBiggerInteger(a: u64, b: u64) -&gt; u64 {
3322 max(u64, a, b)
3323}</code></pre>
3324 <p>
3325 In Zig, types are first-class citizens. They can be assigned to variables, passed as parameters to functions,
3326 and returned from functions. However, they can only be used in expressions which are known at <em>compile-time</em>,
3327 which is why the parameter <code>T</code> in the above snippet must be marked with <code>comptime</code>.
3328 </p>
3329 <p>
3330 A <code>comptime</code> parameter means that:
3331 </p>
3332 <ul>
3333 <li>At the callsite, the value must be known at compile-time, or it is a compile error.</li>
3334 <li>In the function definition, the value is known at compile-time.</li>
3335 </ul>
3336 <p>
3337 </p>
3338 <p>
3339 For example, if we were to introduce another function to the above snippet:
3340 </p>
3341 <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T {
3342 if (a &gt; b) a else b
3343}
3344fn letsTryToPassARuntimeType(condition: bool) {
3345 const result = max(
3346 if (condition) f32 else u64,
3347 1234,
3348 5678);
3349}</code></pre>
3350 <p>
3351 Then we get this result from the compiler:
3352 </p>
3353 <pre><code class="sh">./test.zig:6:9: error: unable to evaluate constant expression
3354 if (condition) f32 else u64,
3355 ^</code></pre>
3356 <p>
3357 This is an error because the programmer attempted to pass a value only known at run-time
3358 to a function which expects a value known at compile-time.
3359 </p>
3360 <p>
3361 Another way to get an error is if we pass a type that violates the type checker when the
3362 function is analyzed. This is what it means to have <em>compile-time duck typing</em>.
3363 </p>
3364 <p>
3365 For example:
3366 </p>
3367 <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T {
3368 if (a &gt; b) a else b
3369}
3370fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool {
3371 max(bool, a, b)
3372}</code></pre>
3373 <p>
3374 The code produces this error message:
3375 </p>
3376 <pre><code>./test.zig:2:11: error: operator not allowed for type 'bool'
3377 if (a &gt; b) a else b
3378 ^
3379./test.zig:5:8: note: called from here
3380 max(bool, a, b)
3381 ^</code></pre>
3382 <p>
3383 On the flip side, inside the function definition with the <code>comptime</code> parameter, the
3384 value is known at compile-time. This means that we actually could make this work for the bool type
3385 if we wanted to:
3386 </p>
3387 <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T {
3388 if (T == bool) {
3389 return a or b;
3390 } else if (a &gt; b) {
3391 return a;
3392 } else {
3393 return b;
3394 }
3395}
3396fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool {
3397 max(bool, a, b)
3398}</code></pre>
3399 <p>
3400 This works because Zig implicitly inlines <code>if</code> expressions when the condition
3401 is known at compile-time, and the compiler guarantees that it will skip analysis of
3402 the branch not taken.
3403 </p>
3404 <p>
3405 This means that the actual function generated for <code>max</code> in this situation looks like
3406 this:
3407 </p>
3408 <pre><code class="zig">fn max(a: bool, b: bool) -&gt; bool {
3409 return a or b;
3410}</code></pre>
3411 <p>
3412 All the code that dealt with compile-time known values is eliminated and we are left with only
3413 the necessary run-time code to accomplish the task.
3414 </p>
3415 <p>
3416 This works the same way for <code>switch</code> expressions - they are implicitly inlined
3417 when the target expression is compile-time known.
3418 </p>
3419 <h4 id="compile-time-variables">Compile-Time Variables</h4>
3420 <p>
3421 In Zig, the programmer can label variables as <code>comptime</code>. This guarantees to the compiler
3422 that every load and store of the variable is performed at compile-time. Any violation of this results in a
3423 compile error.
3424 </p>
3425 <p>
3426 This combined with the fact that we can <code>inline</code> loops allows us to write
3427 a function which is partially evaluated at compile-time and partially at run-time.
3428 </p>
3429 <p>
3430 For example:
3431 </p>
3432 <pre><code class="zig">const assert = @import("std").debug.assert;
3433
3434const CmdFn = struct {
3435 name: []const u8,
3436 func: fn(i32) -&gt; i32,
3437};
3438
3439const cmd_fns = []CmdFn{
3440 CmdFn {.name = "one", .func = one},
3441 CmdFn {.name = "two", .func = two},
3442 CmdFn {.name = "three", .func = three},
3443};
3444fn one(value: i32) -&gt; i32 { value + 1 }
3445fn two(value: i32) -&gt; i32 { value + 2 }
3446fn three(value: i32) -&gt; i32 { value + 3 }
3447
3448fn performFn(comptime prefix_char: u8, start_value: i32) -&gt; i32 {
3449 var result: i32 = start_value;
3450 comptime var i = 0;
3451 inline while (i &lt; cmd_fns.len) : (i += 1) {
3452 if (cmd_fns[i].name[0] == prefix_char) {
3453 result = cmd_fns[i].func(result);
3454 }
3455 }
3456 return result;
3457}
3458
3459test "perform fn" {
3460 assert(performFn('t', 1) == 6);
3461 assert(performFn('o', 0) == 1);
3462 assert(performFn('w', 99) == 99);
3463}</code></pre>
3464 <p>
3465 This example is a bit contrived, because the compile-time evaluation component is unnecessary;
3466 this code would work fine if it was all done at run-time. But it does end up generating
3467 different code. In this example, the function <code>performFn</code> is generated three different times,
3468 for the different values of <code>prefix_char</code> provided:
3469 </p>
3470 <pre><code class="zig">// From the line:
3471// assert(performFn('t', 1) == 6);
3472fn performFn(start_value: i32) -&gt; i32 {
3473 var result: i32 = start_value;
3474 result = two(result);
3475 result = three(result);
3476 return result;
3477}
3478
3479// From the line:
3480// assert(performFn('o', 0) == 1);
3481fn performFn(start_value: i32) -&gt; i32 {
3482 var result: i32 = start_value;
3483 result = one(result);
3484 return result;
3485}
3486
3487// From the line:
3488// assert(performFn('w', 99) == 99);
3489fn performFn(start_value: i32) -&gt; i32 {
3490 var result: i32 = start_value;
3491 return result;
3492}</code></pre>
3493 <p>
3494 Note that this happens even in a debug build; in a release build these generated functions still
3495 pass through rigorous LLVM optimizations. The important thing to note, however, is not that this
3496 is a way to write more optimized code, but that it is a way to make sure that what <em>should</em> happen
3497 at compile-time, <em>does</em> happen at compile-time. This catches more errors and as demonstrated
3498 later in this article, allows expressiveness that in other languages requires using macros,
3499 generated code, or a preprocessor to accomplish.
3500 </p>
3501 <h4 id="compile-time-expressions">Compile-Time Expressions</h4>
3502 <p>
3503 In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can
3504 use a <code>comptime</code> expression to guarantee that the expression will be evaluated at compile-time.
3505 If this cannot be accomplished, the compiler will emit an error. For example:
3506 </p>
3507 <pre><code class="zig">extern fn exit() -&gt; unreachable;
3508
3509fn foo() {
3510 comptime {
3511 exit();
3512 }
3513}</code></pre>
3514 <pre><code>./test.zig:5:9: error: unable to evaluate constant expression
3515 exit();
3516 ^</code></pre>
3517 <p>
3518 It doesn't make sense that a program could call <code>exit()</code> (or any other external function)
3519 at compile-time, so this is a compile error. However, a <code>comptime</code> expression does much
3520 more than sometimes cause a compile error.
3521 </p>
3522 <p>
3523 Within a <code>comptime</code> expression:
3524 </p>
3525 <ul>
3526 <li>All variables are <code>comptime</code> variables.</li>
3527 <li>All <code>if</code>, <code>while</code>, <code>for</code>, <code>switch</code>, and <code>goto</code>
3528 expressions are evaluated at compile-time, or emit a compile error if this is not possible.</li>
3529 <li>All function calls cause the compiler to interpret the function at compile-time, emitting a
3530 compile error if the function tries to do something that has global run-time side effects.</li>
3531 </ul>
3532 <p>
3533 This means that a programmer can create a function which is called both at compile-time and run-time, with
3534 no modification to the function required.
3535 </p>
3536 <p>
3537 Let's look at an example:
3538 </p>
3539 <pre><code class="zig">const assert = @import("std").debug.assert;
3540
3541fn fibonacci(index: u32) -&gt; u32 {
3542 if (index &lt; 2) return index;
3543 return fibonacci(index - 1) + fibonacci(index - 2);
3544}
3545
3546test "fibonacci" {
3547 // test fibonacci at run-time
3548 assert(fibonacci(7) == 13);
3549
3550 // test fibonacci at compile-time
3551 comptime {
3552 assert(fibonacci(7) == 13);
3553 }
3554}</code></pre>
3555 <pre><code>$ zig test test.zig
3556Test 1/1 testFibonacci...OK</code></pre>
3557 <p>
3558 Imagine if we had forgotten the base case of the recursive function and tried to run the tests:
3559 </p>
3560 <pre><code class="zig">const assert = @import("std").debug.assert;
3561
3562fn fibonacci(index: u32) -&gt; u32 {
3563 //if (index &lt; 2) return index;
3564 return fibonacci(index - 1) + fibonacci(index - 2);
3565}
3566
3567test "fibonacci" {
3568 comptime {
3569 assert(fibonacci(7) == 13);
3570 }
3571}</code></pre>
3572 <pre><code>$ zig test test.zig
3573./test.zig:3:28: error: operation caused overflow
3574 return fibonacci(index - 1) + fibonacci(index - 2);
3575 ^
3576./test.zig:3:21: note: called from here
3577 return fibonacci(index - 1) + fibonacci(index - 2);
3578 ^
3579./test.zig:3:21: note: called from here
3580 return fibonacci(index - 1) + fibonacci(index - 2);
3581 ^
3582./test.zig:3:21: note: called from here
3583 return fibonacci(index - 1) + fibonacci(index - 2);
3584 ^
3585./test.zig:3:21: note: called from here
3586 return fibonacci(index - 1) + fibonacci(index - 2);
3587 ^
3588./test.zig:3:21: note: called from here
3589 return fibonacci(index - 1) + fibonacci(index - 2);
3590 ^
3591./test.zig:3:21: note: called from here
3592 return fibonacci(index - 1) + fibonacci(index - 2);
3593 ^
3594./test.zig:3:21: note: called from here
3595 return fibonacci(index - 1) + fibonacci(index - 2);
3596 ^
3597./test.zig:14:25: note: called from here
3598 assert(fibonacci(7) == 13);
3599 ^</code></pre>
3600 <p>
3601 The compiler produces an error which is a stack trace from trying to evaluate the
3602 function at compile-time.
3603 </p>
3604 <p>
3605 Luckily, we used an unsigned integer, and so when we tried to subtract 1 from 0, it triggered
3606 undefined behavior, which is always a compile error if the compiler knows it happened.
3607 But what would have happened if we used a signed integer?
3608 </p>
3609 <pre><code class="zig">const assert = @import("std").debug.assert;
3610
3611fn fibonacci(index: i32) -&gt; i32 {
3612 //if (index &lt; 2) return index;
3613 return fibonacci(index - 1) + fibonacci(index - 2);
3614}
3615
3616test "fibonacci" {
3617 comptime {
3618 assert(fibonacci(7) == 13);
3619 }
3620}</code></pre>
3621 <pre><code>./test.zig:3:21: error: evaluation exceeded 1000 backwards branches
3622 return fibonacci(index - 1) + fibonacci(index - 2);
3623 ^
3624./test.zig:3:21: note: called from here
3625 return fibonacci(index - 1) + fibonacci(index - 2);
3626 ^
3627./test.zig:3:21: note: called from here
3628 return fibonacci(index - 1) + fibonacci(index - 2);
3629 ^
3630./test.zig:3:21: note: called from here
3631 return fibonacci(index - 1) + fibonacci(index - 2);
3632 ^
3633./test.zig:3:21: note: called from here
3634 return fibonacci(index - 1) + fibonacci(index - 2);
3635 ^
3636./test.zig:3:21: note: called from here
3637 return fibonacci(index - 1) + fibonacci(index - 2);
3638 ^
3639./test.zig:3:21: note: called from here
3640 return fibonacci(index - 1) + fibonacci(index - 2);
3641 ^
3642./test.zig:3:21: note: called from here
3643 return fibonacci(index - 1) + fibonacci(index - 2);
3644 ^
3645./test.zig:3:21: note: called from here
3646 return fibonacci(index - 1) + fibonacci(index - 2);
3647 ^
3648./test.zig:3:21: note: called from here
3649 return fibonacci(index - 1) + fibonacci(index - 2);
3650 ^
3651./test.zig:3:21: note: called from here
3652 return fibonacci(index - 1) + fibonacci(index - 2);
3653 ^
3654./test.zig:3:21: note: called from here
3655 return fibonacci(index - 1) + fibonacci(index - 2);
3656 ^</code></pre>
3657 <p>
3658 The compiler noticed that evaluating this function at compile-time took a long time,
3659 and thus emitted a compile error and gave up. If the programmer wants to increase
3660 the budget for compile-time computation, they can use a built-in function called
3661 <a href="#builtin-setEvalBranchQuota">@setEvalBranchQuota</a> to change the default number 1000 to something else.
3662 </p>
3663 <p>
3664 What if we fix the base case, but put the wrong value in the <code>assert</code> line?
3665 </p>
3666 <pre><code class="zig">comptime {
3667 assert(fibonacci(7) == 99999);
3668}</code></pre>
3669 <pre><code>./test.zig:15:14: error: unable to evaluate constant expression
3670 if (!ok) unreachable;
3671 ^
3672./test.zig:10:15: note: called from here
3673 assert(fibonacci(7) == 99999);
3674 ^</code></pre>
3675 <p>
3676 What happened is Zig started interpreting the <code>assert</code> function with the
3677 parameter <code>ok</code> set to <code>false</code>. When the interpreter hit
3678 <code>unreachable</code> it emitted a compile error, because reaching unreachable
3679 code is undefined behavior, and undefined behavior causes a compile error if it is detected
3680 at compile-time.
3681 </p>
3682
3683 <p>
3684 In the global scope (outside of any function), all expressions are implicitly
3685 <code>comptime</code> expressions. This means that we can use functions to
3686 initialize complex static data. For example:
3687 </p>
3688 <pre><code class="zig">const first_25_primes = firstNPrimes(25);
3689const sum_of_first_25_primes = sum(first_25_primes);
3690
3691fn firstNPrimes(comptime n: usize) -&gt; [n]i32 {
3692 var prime_list: [n]i32 = undefined;
3693 var next_index: usize = 0;
3694 var test_number: i32 = 2;
3695 while (next_index &lt; prime_list.len) : (test_number += 1) {
3696 var test_prime_index: usize = 0;
3697 var is_prime = true;
3698 while (test_prime_index &lt; next_index) : (test_prime_index += 1) {
3699 if (test_number % prime_list[test_prime_index] == 0) {
3700 is_prime = false;
3701 break;
3702 }
3703 }
3704 if (is_prime) {
3705 prime_list[next_index] = test_number;
3706 next_index += 1;
3707 }
3708 }
3709 return prime_list;
3710}
3711
3712fn sum(numbers: []i32) -&gt; i32 {
3713 var result: i32 = 0;
3714 for (numbers) |x| {
3715 result += x;
3716 }
3717 return result;
3718}</code></pre>
3719 <p>
3720 When we compile this program, Zig generates the constants
3721 with the answer pre-computed. Here are the lines from the generated LLVM IR:
3722 </p>
3723 <pre><code>@0 = internal unnamed_addr constant [25 x i32] [i32 2, i32 3, i32 5, i32 7, i32 11, i32 13, i32 17, i32 19, i32 23, i32 29, i32 31, i32 37, i32 41, i32 43, i32 47, i32 53, i32 59, i32 61, i32 67, i32 71, i32 73, i32 79, i32 83, i32 89, i32 97]
3724 @1 = internal unnamed_addr constant i32 1060</code></pre>
3725 <p>
3726 Note that we did not have to do anything special with the syntax of these functions. For example,
3727 we could call the <code>sum</code> function as is with a slice of numbers whose length and values were
3728 only known at run-time.
3729 </p>
3730 <h3 id="generic-data-structures">Generic Data Structures</h3>
3731 <p>
3732 Zig uses these capabilities to implement generic data structures without introducing any
3733 special-case syntax. If you followed along so far, you may already know how to create a
3734 generic data structure.
3735 </p>
3736 <p>
3737 Here is an example of a generic <code>List</code> data structure, that we will instantiate with
3738 the type <code>i32</code>. In Zig we refer to the type as <code>List(i32)</code>.
3739 </p>
3740 <pre><code class="zig">fn List(comptime T: type) -&gt; type {
3741 struct {
3742 items: []T,
3743 len: usize,
3744 }
3745}</code></pre>
3746 <p>
3747 That's it. It's a function that returns an anonymous <code>struct</code>. For the purposes of error messages
3748 and debugging, Zig infers the name <code>"List(i32)"</code> from the function name and parameters invoked when creating
3749 the anonymous struct.
3750 </p>
3751 <p>
3752 To keep the language small and uniform, all aggregate types in Zig are anonymous. To give a type
3753 a name, we assign it to a constant:
3754 </p>
3755 <pre><code class="zig">const Node = struct {
3756 next: &amp;Node,
3757 name: []u8,
3758};</code></pre>
3759 <p>
3760 This works because all top level declarations are order-independent, and as long as there isn't
3761 an actual infinite regression, values can refer to themselves, directly or indirectly. In this case,
3762 <code>Node</code> refers to itself as a pointer, which is not actually an infinite regression, so
3763 it works fine.
3764 </p>
3765 <h3 id="case-study-printf">Case Study: printf in Zig</h3>
3766 <p>
3767 Putting all of this together, let's seee how <code>printf</code> works in Zig.
3768 </p>
3769 <pre><code class="zig">const warn = @import("std").debug.warn;
3770
3771const a_number: i32 = 1234;
3772const a_string = "foobar";
3773
3774pub fn main(args: [][]u8) -&gt; %void {
3775 warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
3776}</code></pre>
3777 <pre><code>here is a string: 'foobar' here is a number: 1234</code></pre>
3778
3779 <p>
3780 Let's crack open the implementation of this and see how it works:
3781 </p>
3782
3783 <pre><code class="zig">/// Calls print and then flushes the buffer.
3784pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt; %void {
3785 const State = enum {
3786 Start,
3787 OpenBrace,
3788 CloseBrace,
3789 };
3790
3791 comptime var start_index: usize = 0;
3792 comptime var state = State.Start;
3793 comptime var next_arg: usize = 0;
3794
3795 inline for (format) |c, i| {
3796 switch (state) {
3797 State.Start =&gt; switch (c) {
3798 '{' =&gt; {
3799 if (start_index &lt; i) %return self.write(format[start_index...i]);
3800 state = State.OpenBrace;
3801 },
3802 '}' =&gt; {
3803 if (start_index &lt; i) %return self.write(format[start_index...i]);
3804 state = State.CloseBrace;
3805 },
3806 else =&gt; {},
3807 },
3808 State.OpenBrace =&gt; switch (c) {
3809 '{' =&gt; {
3810 state = State.Start;
3811 start_index = i;
3812 },
3813 '}' =&gt; {
3814 %return self.printValue(args[next_arg]);
3815 next_arg += 1;
3816 state = State.Start;
3817 start_index = i + 1;
3818 },
3819 else =&gt; @compileError("Unknown format character: " ++ c),
3820 },
3821 State.CloseBrace =&gt; switch (c) {
3822 '}' =&gt; {
3823 state = State.Start;
3824 start_index = i;
3825 },
3826 else =&gt; @compileError("Single '}' encountered in format string"),
3827 },
3828 }
3829 }
3830 comptime {
3831 if (args.len != next_arg) {
3832 @compileError("Unused arguments");
3833 }
3834 if (state != State.Start) {
3835 @compileError("Incomplete format string: " ++ format);
3836 }
3837 }
3838 if (start_index &lt; format.len) {
3839 %return self.write(format[start_index...format.len]);
3840 }
3841 %return self.flush();
3842}</code></pre>
3843 <p>
3844 This is a proof of concept implementation; the actual function in the standard library has more
3845 formatting capabilities.
3846 </p>
3847 <p>
3848 Note that this is not hard-coded into the Zig compiler; this is userland code in the standard library.
3849 </p>
3850 <p>
3851 When this function is analyzed from our example code above, Zig partially evaluates the function
3852 and emits a function that actually looks like this:
3853 </p>
3854 <pre><code class="zig">pub fn printf(self: &amp;OutStream, arg0: i32, arg1: []const u8) -&gt; %void {
3855 %return self.write("here is a string: '");
3856 %return self.printValue(arg0);
3857 %return self.write("' here is a number: ");
3858 %return self.printValue(arg1);
3859 %return self.write("\n");
3860 %return self.flush();
3861}</code></pre>
3862 <p>
3863 <code>printValue</code> is a function that takes a parameter of any type, and does different things depending
3864 on the type:
3865 </p>
3866 <pre><code class="zig">pub fn printValue(self: &amp;OutStream, value: var) -&gt; %void {
3867 const T = @typeOf(value);
3868 if (@isInteger(T)) {
3869 return self.printInt(T, value);
3870 } else if (@isFloat(T)) {
3871 return self.printFloat(T, value);
3872 } else if (@canImplicitCast([]const u8, value)) {
3873 const casted_value = ([]const u8)(value);
3874 return self.write(casted_value);
3875 } else {
3876 @compileError("Unable to print type '" ++ @typeName(T) ++ "'");
3877 }
3878}</code></pre>
3879 <p>
3880 And now, what happens if we give too many arguments to <code>printf</code>?
3881 </p>
3882 <pre><code class="zig">warn("here is a string: '{}' here is a number: {}\n",
3883 a_string, a_number, a_number);</code></pre>
3884 <pre><code>.../std/io.zig:147:17: error: Unused arguments
3885 @compileError("Unused arguments");
3886 ^
3887./test.zig:7:23: note: called from here
3888 warn("here is a number: {} and here is a string: {}\n",
3889 ^</code></pre>
3890 <p>
3891 Zig gives programmers the tools needed to protect themselves against their own mistakes.
3892 </p>
3893 <p>
3894 Zig doesn't care whether the format argument is a string literal,
3895 only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:
3896 </p>
3897 <pre><code class="zig">const warn = @import("std").debug.warn;
3898
3899const a_number: i32 = 1234;
3900const a_string = "foobar";
3901const fmt = "here is a string: '{}' here is a number: {}\n";
3902
3903pub fn main(args: [][]u8) -&gt; %void {
3904 warn(fmt, a_string, a_number);
3905}</code></pre>
3906 <p>
3907 This works fine.
3908 </p>
3909 <p>
3910 Zig does not special case string formatting in the compiler and instead exposes enough power to accomplish this
3911 task in userland. It does so without introducing another language on top of Zig, such as
3912 a macro language or a preprocessor language. It's Zig all the way down.
3913 </p>
3914 <p>TODO: suggestion to not use inline unless necessary</p>
3915 <h2 id="inline">inline</h2>
3916 <p>TODO: inline while</p>
3917 <p>TODO: inline for</p>
3918 <p>TODO: suggestion to not use inline unless necessary</p>
3919 <h2 id="assembly">Assembly</h2>
3920 <p>TODO: example of inline assembly</p>
3921 <p>TODO: example of module level assembly</p>
3922 <p>TODO: example of using inline assembly return value</p>
3923 <p>TODO: example of using inline assembly assigning values to variables</p>
3924 <h2 id="atomics">Atomics</h2>
3925 <p>TODO: @fence()</p>
3926 <p>TODO: @atomic rmw</p>
3927 <p>TODO: builtin atomic memory ordering enum</p>
3928 <h2 id="builtin-functions">Builtin Functions</h2>
3929 <p>
3930 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
3931 The <code>comptime</code> keyword on a parameter means that the parameter must be known
3932 at compile time.
3933 </p>
3934 <h3 id="builtin-addWithOverflow">@addWithOverflow</h3>
3935 <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
3936 <p>
3937 Performs <code>*result = a + b</code>. If overflow or underflow occurs,
3938 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
3939 If no overflow or underflow occurs, returns <code>false</code>.
3940 </p>
3941 <h3 id="builtin-ArgType">@ArgType</h3>
3942 <p>TODO</p>
3943 <h3 id="builtin-bitCast">@bitCast</h3>
3944 <pre><code class="zig">@bitCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
3945 <p>
3946 Converts a value of one type to another type.
3947 </p>
3948 <p>
3949 Asserts that <code>@sizeOf(@typeOf(value)) == @sizeOf(DestType)</code>.
3950 </p>
3951 <p>
3952 Asserts that <code>@typeId(DestType) != @import("builtin").TypeId.Pointer</code>. Use <code>@ptrCast</code> or <code>@intToPtr</code> if you need this.
3953 </p>
3954 <p>
3955 Can be used for these things for example:
3956 </p>
3957 <ul>
3958 <li>Convert <code>f32</code> to <code>u32</code> bits</li>
3959 <li>Convert <code>i32</code> to <code>u32</code> preserving twos complement</li>
3960 </ul>
3961 <p>
3962 Works at compile-time if <code>value</code> 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.
3963 </p>
3964 <h3 id="builtin-breakpoint">@breakpoint</h3>
3965 <pre><code class="zig">@breakpoint()</code></pre>
3966 <p>
3967 This function inserts a platform-specific debug trap instruction which causes
3968 debuggers to break there.
3969 </p>
3970 <p>
3971 This function is only valid within function scope.
3972 </p>
3973
3974 <h3 id="builtin-alignCast">@alignCast</h3>
3975 <pre><code class="zig">@alignCast(comptime alignment: u29, ptr: var) -&gt; var</code></pre>
3976 <p>
3977 <code>ptr</code> can be <code>&amp;T</code>, <code>fn()</code>, <code>?&amp;T</code>,
3978 <code>?fn()</code>, or <code>[]T</code>. It returns the same type as <code>ptr</code>
3979 except with the alignment adjusted to the new value.
3980 </p>
3981 <p>A <a href="#undef-incorrect-pointer-alignment">pointer alignment safety check</a> is added
3982 to the generated code to make sure the pointer is aligned as promised.</p>
3983
3984 <h3 id="builtin-alignOf">@alignOf</h3>
3985 <pre><code class="zig">@alignOf(comptime T: type) -&gt; (number literal)</code></pre>
3986 <p>
3987 This function returns the number of bytes that this type should be aligned to
3988 for the current target to match the C ABI. When the child type of a pointer has
3989 this alignment, the alignment can be omitted from the type.
3990 </p>
3991 <pre><code class="zig">const assert = @import("std").debug.assert;
3992comptime {
3993 assert(&amp;u32 == &amp;align(@alignOf(u32)) u32);
3994}</code></pre>
3995 <p>
3996 The result is a target-specific compile time constant. It is guaranteed to be
3997 less than or equal to <a href="#builtin-sizeOf">@sizeOf(T)</a>.
3998 </p>
3999 <p>See also:</p>
4000 <ul>
4001 <li><a href="#alignment">Alignment</a></li>
4002 </ul>
4003
4004 <h3 id="builtin-cDefine">@cDefine</h3>
4005 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>
4006 <p>
4007 This function can only occur inside <code>@cImport</code>.
4008 </p>
4009 <p>
4010 This appends <code>#define $name $value</code> to the <code>@cImport</code>
4011 temporary buffer.
4012 </p>
4013 <p>
4014 To define without a value, like this:
4015 </p>
4016 <pre><code class="c">#define _GNU_SOURCE</code></pre>
4017 <p>
4018 Use the void value, like this:
4019 </p>
4020 <pre><code class="zig">@cDefine("_GNU_SOURCE", {})</code></pre>
4021 <p>See also:</p>
4022 <ul>
4023 <li><a href="#c-import">Import from C Header File</a></li>
4024 <li><a href="#builtin-cInclude">@cInclude</a></li>
4025 <li><a href="#builtin-cImport">@cImport</a></li>
4026 <li><a href="#builtin-cUndef">@cUndef</a></li>
4027 <li><a href="#void">void</a></li>
4028 </ul>
4029 <h3 id="builtin-cImport">@cImport</h3>
4030 <pre><code class="zig">@cImport(expression) -&gt; (namespace)</code></pre>
4031 <p>
4032 This function parses C code and imports the functions, types, variables, and
4033 compatible macro definitions into the result namespace.
4034 </p>
4035 <p>
4036 <code>expression</code> is interpreted at compile time. The builtin functions
4037 <code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work
4038 within this expression, appending to a temporary buffer which is then parsed as C code.
4039 </p>
4040 <p>See also:</p>
4041 <ul>
4042 <li><a href="#c-import">Import from C Header File</a></li>
4043 <li><a href="#builtin-cInclude">@cInclude</a></li>
4044 <li><a href="#builtin-cDefine">@cDefine</a></li>
4045 <li><a href="#builtin-cUndef">@cUndef</a></li>
4046 </ul>
4047 <h3 id="builtin-cInclude">@cInclude</h3>
4048 <pre><code class="zig">@cInclude(comptime path: []u8)</code></pre>
4049 <p>
4050 This function can only occur inside <code>@cImport</code>.
4051 </p>
4052 <p>
4053 This appends <code>#include <$path>\n</code> to the <code>c_import</code>
4054 temporary buffer.
4055 </p>
4056 <p>See also:</p>
4057 <ul>
4058 <li><a href="#c-import">Import from C Header File</a></li>
4059 <li><a href="#builtin-cImport">@cImport</a></li>
4060 <li><a href="#builtin-cDefine">@cDefine</a></li>
4061 <li><a href="#builtin-cUndef">@cUndef</a></li>
4062 </ul>
4063 <h3 id="builtin-cUndef">@cUndef</h3>
4064 <pre><code class="zig">@cUndef(comptime name: []u8)</code></pre>
4065 <p>
4066 This function can only occur inside <code>@cImport</code>.
4067 </p>
4068 <p>
4069 This appends <code>#undef $name</code> to the <code>@cImport</code>
4070 temporary buffer.
4071 </p>
4072 <p>See also:</p>
4073 <ul>
4074 <li><a href="#c-import">Import from C Header File</a></li>
4075 <li><a href="#builtin-cImport">@cImport</a></li>
4076 <li><a href="#builtin-cDefine">@cDefine</a></li>
4077 <li><a href="#builtin-cInclude">@cInclude</a></li>
4078 </ul>
4079 <h3 id="builtin-canImplicitCast">@canImplicitCast</h3>
4080 <pre><code class="zig">@canImplicitCast(comptime T: type, value) -&gt; bool</code></pre>
4081 <p>
4082 Returns whether a value can be implicitly casted to a given type.
4083 </p>
4084 <h3 id="builtin-clz">@clz</h3>
4085 <pre><code class="zig">@clz(x: T) -&gt; U</code></pre>
4086 <p>
4087 This function counts the number of leading zeroes in <code>x</code> which is an integer
4088 type <code>T</code>.
4089 </p>
4090 <p>
4091 The return type <code>U</code> is an unsigned integer with the minimum number
4092 of bits that can represent the value <code>T.bit_count</code>.
4093 </p>
4094 <p>
4095 If <code>x</code> is zero, <code>@clz</code> returns <code>T.bit_count</code>.
4096 </p>
4097
4098 <h3 id="builtin-cmpxchg">@cmpxchg</h3>
4099 <pre><code class="zig">@cmpxchg(ptr: &amp;T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -&gt; bool</code></pre>
4100 <p>
4101 This function performs an atomic compare exchange operation.
4102 </p>
4103 <p>
4104 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.
4105 </p>
4106 <p><code>@typeOf(ptr).alignment</code> must be <code>&gt;= @sizeOf(T).</code></p>
4107 <p>See also:</p>
4108 <ul>
4109 <li><a href="#compile-variables">Compile Variables</a></li>
4110 </ul>
4111
4112 <h3 id="builtin-compileError">@compileError</h3>
4113 <pre><code class="zig">@compileError(comptime msg: []u8)</code></pre>
4114 <p>
4115 This function, when semantically analyzed, causes a compile error with the
4116 message <code>msg</code>.
4117 </p>
4118 <p>
4119 There are several ways that code avoids being semantically checked, such as
4120 using <code>if</code> or <code>switch</code> with compile time constants,
4121 and <code>comptime</code> functions.
4122 </p>
4123 <h3 id="builtin-compileLog">@compileLog</h3>
4124 <pre><code class="zig">@compileLog(args: ...)</code></pre>
4125 <p>
4126 This function prints the arguments passed to it at compile-time.
4127 </p>
4128 <p>
4129 To prevent accidentally leaving compile log statements in a codebase,
4130 a compilation error is added to the build, pointing to the compile
4131 log statement. This error prevents code from being generated, but
4132 does not otherwise interfere with analysis.
4133 </p>
4134 <p>
4135 This function can be used to do "printf debugging" on
4136 compile-time executing code.
4137 </p>
4138<pre><code class="zig">const warn = @import("std").debug.warn;
4139
4140const num1 = {
4141 var val1: i32 = 99;
4142 @compileLog("comptime val1 = ", val1);
4143 val1 = val1 + 1;
4144 val1
4145};
4146
4147pub fn main() -&gt; %void {
4148 @compileLog("comptime in main");
4149
4150 warn("Runtime in main, num1 = {}.\n", num1);
4151}</code></pre>
4152
4153 </p>
4154 <p>
4155 will ouput:
4156 </p>
4157
4158<pre><code class="sh">$ zig build-exe test.zig
4159| "comptime in main"
4160| "comptime val1 = ", 99
4161test.zig:14:5: error: found compile log statement
4162 @compileLog("comptime in main");
4163 ^
4164test.zig:6:2: error: found compile log statement
4165 @compileLog("comptime val1 = ", val1);
4166 ^</code></pre>
4167 <p>
4168 If all <code>@compileLog</code> calls are removed or
4169 not encountered by analysis, the
4170 program compiles successfully and the generated executable prints:
4171 </p>
4172<pre><code class="sh">Runtime in main, num1 = 100.</code></pre>
4173 <h3 id="builtin-ctz">@ctz</h3>
4174 <pre><code class="zig">@ctz(x: T) -&gt; U</code></pre>
4175 <p>
4176 This function counts the number of trailing zeroes in <code>x</code> which is an integer
4177 type <code>T</code>.
4178 </p>
4179 <p>
4180 The return type <code>U</code> is an unsigned integer with the minimum number
4181 of bits that can represent the value <code>T.bit_count</code>.
4182 </p>
4183 <p>
4184 If <code>x</code> is zero, <code>@ctz</code> returns <code>T.bit_count</code>.
4185 </p>
4186 <h3 id="builtin-divExact">@divExact</h3>
4187 <pre><code class="zig">@divExact(numerator: T, denominator: T) -&gt; T</code></pre>
4188 <p>
4189 Exact division. Caller guarantees <code>denominator != 0</code> and
4190 <code>@divTrunc(numerator, denominator) * denominator == numerator</code>.
4191 </p>
4192 <ul>
4193 <li><code>@divExact(6, 3) == 2</code></li>
4194 <li><code>@divExact(a, b) * b == a</code></li>
4195 </ul>
4196 <p>See also:</p>
4197 <ul>
4198 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
4199 <li><a href="#builtin-divFloor">@divFloor</a></li>
4200 <li><code>@import("std").math.divExact</code></li>
4201 </ul>
4202 <h3 id="builtin-divFloor">@divFloor</h3>
4203 <pre><code class="zig">@divFloor(numerator: T, denominator: T) -&gt; T</code></pre>
4204 <p>
4205 Floored division. Rounds toward negative infinity. For unsigned integers it is
4206 the same as <code>numerator / denominator</code>. Caller guarantees <code>denominator != 0</code> and
4207 <code>!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)</code>.
4208 </p>
4209 <ul>
4210 <li><code>@divFloor(-5, 3) == -2</code></li>
4211 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
4212 </ul>
4213 <p>See also:</p>
4214 <ul>
4215 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
4216 <li><a href="#builtin-divExact">@divExact</a></li>
4217 <li><code>@import("std").math.divFloor</code></li>
4218 </ul>
4219 <h3 id="builtin-divTrunc">@divTrunc</h3>
4220 <pre><code class="zig">@divTrunc(numerator: T, denominator: T) -&gt; T</code></pre>
4221 <p>
4222 Truncated division. Rounds toward zero. For unsigned integers it is
4223 the same as <code>numerator / denominator</code>. Caller guarantees <code>denominator != 0</code> and
4224 <code>!(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)</code>.
4225 </p>
4226 <ul>
4227 <li><code>@divTrunc(-5, 3) == -1</code></li>
4228 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
4229 </ul>
4230 <p>See also:</p>
4231 <ul>
4232 <li><a href="#builtin-divFloor">@divFloor</a></li>
4233 <li><a href="#builtin-divExact">@divExact</a></li>
4234 <li><code>@import("std").math.divTrunc</code></li>
4235 </ul>
4236 <h3 id="builtin-embedFile">@embedFile</h3>
4237 <pre><code class="zig">@embedFile(comptime path: []const u8) -&gt; [X]u8</code></pre>
4238 <p>
4239 This function returns a compile time constant fixed-size array with length
4240 equal to the byte count of the file given by <code>path</code>. The contents of the array
4241 are the contents of the file.
4242 </p>
4243 <p>
4244 <code>path</code> is absolute or relative to the current file, just like <code>@import</code>.
4245 </p>
4246 <p>See also:</p>
4247 <ul>
4248 <li><a href="#builtin-import">@import</a></li>
4249 </ul>
4250 <h3 id="builtin-enumTagName">@enumTagName</h3>
4251 <pre><code class="zig">@enumTagName(value: var) -&gt; []const u8</code></pre>
4252 <p>
4253 Converts an enum tag name to a slice of bytes.
4254 </p>
4255 <h3 id="builtin-errorName">@errorName</h3>
4256 <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre>
4257 <p>
4258 This function returns the string representation of an error. If an error
4259 declaration is:
4260 </p>
4261 <pre><code class="zig">error OutOfMem</code></pre>
4262 <p>
4263 Then the string representation is <code>"OutOfMem"</code>.
4264 </p>
4265 <p>
4266 If there are no calls to <code>@errorName</code> in an entire application,
4267 or all calls have a compile-time known value for <code>err</code>, then no
4268 error name table will be generated.
4269 </p>
4270 <h3 id="builtin-fence">@fence</h3>
4271 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
4272 <p>
4273 The <code>fence</code> function is used to introduce happens-before edges between operations.
4274 </p>
4275 <p>
4276 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.
4277 </p>
4278 <p>See also:</p>
4279 <ul>
4280 <li><a href="#compile-variables">Compile Variables</a></li>
4281 </ul>
4282 <h3 id="builtin-fieldParentPtr">@fieldParentPtr</h3>
4283 <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
4284 field_ptr: &amp;T) -&gt; &amp;ParentType</code></pre>
4285 <p>
4286 Given a pointer to a field, returns the base pointer of a struct.
4287 </p>
4288 <h3 id="builtin-frameAddress">@frameAddress</h3>
4289 <pre><code class="zig">@frameAddress()</code></pre>
4290 <p>
4291 This function returns the base pointer of the current stack frame.
4292 </p>
4293 <p>
4294 The implications of this are target specific and not consistent across all
4295 platforms. The frame address may not be available in release mode due to
4296 aggressive optimizations.
4297 </p>
4298 <p>
4299 This function is only valid within function scope.
4300 </p>
4301 <h3 id="builtin-import">@import</h3>
4302 <pre><code class="zig">@import(comptime path: []u8) -&gt; (namespace)</code></pre>
4303 <p>
4304 This function finds a zig file corresponding to <code>path</code> and imports all the
4305 public top level declarations into the resulting namespace.
4306 </p>
4307 <p>
4308 <code>path</code> can be a relative or absolute path, or it can be the name of a package.
4309 If it is a relative path, it is relative to the file that contains the <code>@import</code>
4310 function call.
4311 </p>
4312 <p>
4313 The following packages are always available:
4314 </p>
4315 <ul>
4316 <li><code>@import("std")</code> - Zig Standard Library</li>
4317 <li><code>@import("builtin")</code> - Compiler-provided types and variables</li>
4318 </ul>
4319 <p>See also:</p>
4320 <ul>
4321 <li><a href="#compile-variables">Compile Variables</a></li>
4322 <li><a href="#builtin-embedFile">@embedFile</a></li>
4323 </ul>
4324 <h3 id="builtin-inlineCall">@inlineCall</h3>
4325 <pre><code class="zig">@inlineCall(function: X, args: ...) -&gt; Y</code></pre>
4326 <p>
4327 This calls a function, in the same way that invoking an expression with parentheses does:
4328 </p>
4329 <pre><code class="zig">const assert = @import("std").debug.assert;
4330test "inline function call" {
4331 assert(@inlineCall(add, 3, 9) == 12);
4332}
4333
4334fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4335 <p>
4336 Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call
4337 will be inlined. If the call cannot be inlined, a compile error is emitted.
4338 </p>
4339 <h3 id="builtin-intToPtr">@intToPtr</h3>
4340 <pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) -&gt; DestType</code></pre>
4341 <p>
4342 Converts an integer to a pointer. To convert the other way, use <a href="#builtin-ptrToInt">@ptrToInt</a>.
4343 </p>
4344 <h3 id="builtin-IntType">@IntType</h3>
4345 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u8) -&gt; type</code></pre>
4346 <p>
4347 This function returns an integer type with the given signness and bit count.
4348 </p>
4349 <h3 id="builtin-maxValue">@maxValue</h3>
4350 <pre><code class="zig">@maxValue(comptime T: type) -&gt; (number literal)</code></pre>
4351 <p>
4352 This function returns the maximum value of the integer type <code>T</code>.
4353 </p>
4354 <p>
4355 The result is a compile time constant.
4356 </p>
4357 <h3 id="builtin-memberCount">@memberCount</h3>
4358 <pre><code class="zig">@memberCount(comptime T: type) -&gt; (number literal)</code></pre>
4359 <p>
4360 This function returns the number of enum values in an enum type.
4361 </p>
4362 <p>
4363 The result is a compile time constant.
4364 </p>
4365 <h3 id="builtin-memberName">@memberName</h3>
4366 <p>TODO</p>
4367 <h3 id="builtin-memberType">@memberType</h3>
4368 <p>TODO</p>
4369 <h3 id="builtin-memcpy">@memcpy</h3>
4370 <pre><code class="zig">@memcpy(noalias dest: &amp;u8, noalias source: &amp;const u8, byte_count: usize)</code></pre>
4371 <p>
4372 This function copies bytes from one region of memory to another. <code>dest</code> and
4373 <code>source</code> are both pointers and must not overlap.
4374 </p>
4375 <p>
4376 This function is a low level intrinsic with no safety mechanisms. Most code
4377 should not use this function, instead using something like this:
4378 </p>
4379 <pre><code class="zig">for (source[0...byte_count]) |b, i| dest[i] = b;</code></pre>
4380 <p>
4381 The optimizer is intelligent enough to turn the above snippet into a memcpy.
4382 </p>
4383 <p>There is also a standard library function for this:</p>
4384 <pre><code class="zig">const mem = @import("std").mem;
4385mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
4386 <h3 id="builtin-memset">@memset</h3>
4387 <pre><code class="zig">@memset(dest: &amp;u8, c: u8, byte_count: usize)</code></pre>
4388 <p>
4389 This function sets a region of memory to <code>c</code>. <code>dest</code> is a pointer.
4390 </p>
4391 <p>
4392 This function is a low level intrinsic with no safety mechanisms. Most
4393 code should not use this function, instead using something like this:
4394 </p>
4395 <pre><code class="zig">for (dest[0...byte_count]) |*b| *b = c;</code></pre>
4396 <p>
4397 The optimizer is intelligent enough to turn the above snippet into a memset.
4398 </p>
4399 <p>There is also a standard library function for this:</p>
4400 <pre><code>const mem = @import("std").mem;
4401mem.set(u8, dest, c);</code></pre>
4402 <h3 id="builtin-minValue">@minValue</h3>
4403 <pre><code class="zig">@minValue(comptime T: type) -&gt; (number literal)</code></pre>
4404 <p>
4405 This function returns the minimum value of the integer type T.
4406 </p>
4407 <p>
4408 The result is a compile time constant.
4409 </p>
4410 <h3 id="builtin-mod">@mod</h3>
4411 <pre><code class="zig">@mod(numerator: T, denominator: T) -&gt; T</code></pre>
4412 <p>
4413 Modulus division. For unsigned integers this is the same as
4414 <code>numerator % denominator</code>. Caller guarantees <code>denominator &gt; 0</code>.
4415 </p>
4416 <ul>
4417 <li><code>@mod(-5, 3) == 1</code></li>
4418 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
4419 </ul>
4420 <p>See also:</p>
4421 <ul>
4422 <li><a href="#builtin-rem">@rem</a></li>
4423 <li><code>@import("std").math.mod</code></li>
4424 </ul>
4425 <h3 id="builtin-mulWithOverflow">@mulWithOverflow</h3>
4426 <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
4427 <p>
4428 Performs <code>*result = a * b</code>. If overflow or underflow occurs,
4429 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
4430 If no overflow or underflow occurs, returns <code>false</code>.
4431 </p>
4432 <h3 id="builtin-offsetOf">@offsetOf</h3>
4433 <pre><code class="zig">@offsetOf(comptime T: type, comptime field_name: [] const u8) -&gt; (number literal)</code></pre>
4434 <p>
4435 This function returns the byte offset of a field relative to its containing struct.
4436 </p>
4437 <h3 id="builtin-OpaqueType">@OpaqueType</h3>
4438 <pre><code class="zig">@OpaqueType() -&gt; type</code></pre>
4439 <p>
4440 Creates a new type with an unknown size and alignment.
4441 </p>
4442 <p>
4443 This is typically used for type safety when interacting with C code that does not expose struct details.
4444 Example:
4445 </p>
4446 <pre><code class="zig">const Derp = @OpaqueType();
4447const Wat = @OpaqueType();
4448
4449extern fn bar(d: &amp;Derp);
4450export fn foo(w: &amp;Wat) {
4451 bar(w);
4452}</code></pre>
4453 <pre><code class="sh">$ ./zig build-obj test.zig
4454test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4455 bar(w);
4456 ^</code></pre>
4457 <h3 id="builtin-panic">@panic</h3>
4458 <pre><code class="zig">@panic(message: []const u8) -&gt; noreturn</code></pre>
4459 <p>
4460 Invokes the panic handler function. By default the panic handler function
4461 calls the public <code>panic</code> function exposed in the root source file, or
4462 if there is not one specified, invokes the one provided in <code>std/special/panic.zig</code>.
4463 </p>
4464 <p>Generally it is better to use <code>@import("std").debug.panic</code>.
4465 However, <code>@panic</code> can be useful for 2 scenarios:
4466 </p>
4467 <ul>
4468 <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li>
4469 <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li>
4470 </ul>
4471 <p>See also:</p>
4472 <ul>
4473 <li><a href="#root-source-file">Root Source File</a></li>
4474 </ul>
4475
4476 <h3 id="builtin-ptrCast">@ptrCast</h3>
4477 <pre><code class="zig">@ptrCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
4478 <p>
4479 Converts a pointer of one type to a pointer of another type.
4480 </p>
4481 <h3 id="builtin-ptrToInt">@ptrToInt</h3>
4482 <pre><code class="zig">@ptrToInt(value: var) -&gt; usize</code></pre>
4483 <p>
4484 Converts <code>value</code> to a <code>usize</code> which is the address of the pointer. <code>value</code> can be one of these types:
4485 </p>
4486 <ul>
4487 <li><code>&amp;T</code></li>
4488 <li><code>?&amp;T</code></li>
4489 <li><code>fn()</code></li>
4490 <li><code>?fn()</code></li>
4491 </ul>
4492 <p>To convert the other way, use <a href="#builtin-intToPtr">@intToPtr</a></p>
4493
4494 <h3 id="builtin-rem">@rem</h3>
4495 <pre><code class="zig">@rem(numerator: T, denominator: T) -&gt; T</code></pre>
4496 <p>
4497 Remainder division. For unsigned integers this is the same as
4498 <code>numerator % denominator</code>. Caller guarantees <code>denominator &gt; 0</code>.
4499 </p>
4500 <ul>
4501 <li><code>@rem(-5, 3) == -2</code></li>
4502 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
4503 </ul>
4504 <p>See also:</p>
4505 <ul>
4506 <li><a href="#builtin-mod">@mod</a></li>
4507 <li><code>@import("std").math.rem</code></li>
4508 </ul>
4509 <h3 id="builtin-returnAddress">@returnAddress</h3>
4510 <pre><code class="zig">@returnAddress()</code></pre>
4511 <p>
4512 This function returns a pointer to the return address of the current stack
4513 frame.
4514 </p>
4515 <p>
4516 The implications of this are target specific and not consistent across
4517 all platforms.
4518 </p>
4519 <p>
4520 This function is only valid within function scope.
4521 </p>
4522
4523 <h3 id="builtin-setDebugSafety">@setDebugSafety</h3>
4524 <pre><code class="zig">@setDebugSafety(scope, safety_on: bool)</code></pre>
4525 <p>
4526 Sets whether debug safety checks are on for a given scope.
4527 </p>
4528
4529 <h3 id="builtin-setEvalBranchQuota">@setEvalBranchQuota</h3>
4530 <pre><code class="zig">@setEvalBranchQuota(new_quota: usize)</code></pre>
4531 <p>
4532 Changes the maximum number of backwards branches that compile-time code
4533 execution can use before giving up and making a compile error.
4534 </p>
4535 <p>
4536 If the <code>new_quota</code> is smaller than the default quota (<code>1000</code>) or
4537 a previously explicitly set quota, it is ignored.
4538 </p>
4539 <p>
4540 Example:
4541 </p>
4542 <pre><code class="zig">comptime {
4543 var i = 0;
4544 while (i &lt; 1001) : (i += 1) {}
4545}</code></pre>
4546 <pre><code class="sh">$ ./zig build-obj test.zig
4547/home/andy/dev/zig/build/test.zig:3:5: error: evaluation exceeded 1000 backwards branches
4548 while (i &lt; 1001) : (i += 1) {}
4549 ^</code></pre>
4550 <p>Now we use <code>@setEvalBranchQuota</code>:</p>
4551 <pre><code class="zig">comptime {
4552 @setEvalBranchQuota(1001);
4553 var i = 0;
4554 while (i &lt; 1001) : (i += 1) {}
4555}</code></pre>
4556 <pre><code class="sh">$ ./zig build-obj test.zig</code></pre>
4557 <p>(no output because it worked fine)</p>
4558
4559 <p>See also:</p>
4560 <ul>
4561 <li><a href="#comptime">comptime</a></li>
4562 </ul>
4563
4564 <h3 id="builtin-setFloatMode">@setFloatMode</h3>
4565 <pre><code class="zig">@setFloatMode(scope, mode: @import("builtin").FloatMode)</code></pre>
4566 <p>
4567 Sets the floating point mode for a given scope. Possible values are:
4568 </p>
4569 <pre><code class="zig">pub const FloatMode = enum {
4570 Optimized,
4571 Strict,
4572};</code></pre>
4573 <ul>
4574 <li>
4575 <code>Optimized</code> (default) - Floating point operations may do all of the following:
4576 <ul>
4577 <li>Assume the arguments and result are not NaN. Optimizations are required to retain defined behavior over NaNs, but the value of the result is undefined.</li>
4578 <li>Assume the arguments and result are not +/-Inf. Optimizations are required to retain defined behavior over +/-Inf, but the value of the result is undefined.</li>
4579 <li>Treat the sign of a zero argument or result as insignificant.</li>
4580 <li>Use the reciprocal of an argument rather than perform division.</li>
4581 <li>Perform floating-point contraction (e.g. fusing a multiply followed by an addition into a fused multiply-and-add).</li>
4582 <li>Perform algebraically equivalent transformations that may change results in floating point (e.g. reassociate).</li>
4583 </ul>
4584 This is equivalent to <code>-ffast-math</code> in GCC.
4585 </li>
4586 <li>
4587 <code>Strict</code> - Floating point operations follow strict IEEE compliance.
4588 </li>
4589 </ul>
4590 <p>See also:</p>
4591 <ul>
4592 <li><a href="#float-operations">Floating Point Operations</a></li>
4593 </ul>
4594
4595 <h3 id="builtin-setGlobalLinkage">@setGlobalLinkage</h3>
4596 <pre><code class="zig">@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage)</code></pre>
4597 <p>
4598 <code>GlobalLinkage</code> can be found with <code>@import("builtin").GlobalLinkage</code>.
4599 </p>
4600 <p>See also:</p>
4601 <ul>
4602 <li><a href="#compile-variables">Compile Variables</a></li>
4603 </ul>
4604 <h3 id="builtin-setGlobalSection">@setGlobalSection</h3>
4605 <pre><code class="zig">@setGlobalSection(global_variable_name, comptime section_name: []const u8) -&gt; bool</code></pre>
4606 <p>
4607 Puts the global variable in the specified section.
4608 </p>
4609 <h3 id="builtin-shlExact">@shlExact</h3>
4610 <pre><code class="zig">@shlExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>
4611 <p>
4612 Performs the left shift operation (<code>&lt;&lt;</code>). Caller guarantees
4613 that the shift will not shift any 1 bits out.
4614 </p>
4615 <p>
4616 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
4617 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
4618 </p>
4619 <p>See also:</p>
4620 <ul>
4621 <li><a href="#builtin-shrExact">@shrExact</a></li>
4622 <li><a href="#builtin-shlWithOverflow">@shlWithOverflow</a></li>
4623 </ul>
4624 <h3 id="builtin-shlWithOverflow">@shlWithOverflow</h3>
4625 <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &amp;T) -&gt; bool</code></pre>
4626 <p>
4627 Performs <code>*result = a &lt;&lt; b</code>. If overflow or underflow occurs,
4628 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
4629 If no overflow or underflow occurs, returns <code>false</code>.
4630 </p>
4631 <p>
4632 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
4633 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
4634 </p>
4635 <p>See also:</p>
4636 <ul>
4637 <li><a href="#builtin-shlExact">@shlExact</a></li>
4638 <li><a href="#builtin-shrExact">@shrExact</a></li>
4639 </ul>
4640 <h3 id="builtin-shrExact">@shrExact</h3>
4641 <pre><code class="zig">@shrExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>
4642 <p>
4643 Performs the right shift operation (<code>&gt;&gt;</code>). Caller guarantees
4644 that the shift will not shift any 1 bits out.
4645 </p>
4646 <p>
4647 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
4648 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
4649 </p>
4650 <p>See also:</p>
4651 <ul>
4652 <li><a href="#builtin-shlExact">@shlExact</a></li>
4653 </ul>
4654 <h3 id="builtin-sizeOf">@sizeOf</h3>
4655 <pre><code class="zig">@sizeOf(comptime T: type) -&gt; (number literal)</code></pre>
4656 <p>
4657 This function returns the number of bytes it takes to store <code>T</code> in memory.
4658 </p>
4659 <p>
4660 The result is a target-specific compile time constant.
4661 </p>
4662 <h3 id="builtin-subWithOverflow">@subWithOverflow</h3>
4663 <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
4664 <p>
4665 Performs <code>*result = a - b</code>. If overflow or underflow occurs,
4666 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
4667 If no overflow or underflow occurs, returns <code>false</code>.
4668 </p>
4669 <h3 id="builtin-truncate">@truncate</h3>
4670 <pre><code class="zig">@truncate(comptime T: type, integer) -&gt; T</code></pre>
4671 <p>
4672 This function truncates bits from an integer type, resulting in a smaller
4673 integer type.
4674 </p>
4675 <p>
4676 The following produces a crash in debug mode and undefined behavior in
4677 release mode:
4678 </p>
4679 <pre><code class="zig">const a: u16 = 0xabcd;
4680const b: u8 = u8(a);</code></pre>
4681 <p>
4682 However this is well defined and working code:
4683 </p>
4684 <pre><code class="zig">const a: u16 = 0xabcd;
4685const b: u8 = @truncate(u8, a);
4686// b is now 0xcd</code></pre>
4687 <p>
4688 This function always truncates the significant bits of the integer, regardless
4689 of endianness on the target platform.
4690 </p>
4691
4692 <h3 id="builtin-typeId">@typeId</h3>
4693 <pre><code class="zig">@typeId(comptime T: type) -&gt; @import("builtin").TypeId</code></pre>
4694 <p>
4695 Returns which kind of type something is. Possible values:
4696 </p>
4697 <pre><code class="zig">pub const TypeId = enum {
4698 Type,
4699 Void,
4700 Bool,
4701 NoReturn,
4702 Int,
4703 Float,
4704 Pointer,
4705 Array,
4706 Struct,
4707 FloatLiteral,
4708 IntLiteral,
4709 UndefinedLiteral,
4710 NullLiteral,
4711 Nullable,
4712 ErrorUnion,
4713 Error,
4714 Enum,
4715 EnumTag,
4716 Union,
4717 Fn,
4718 Namespace,
4719 Block,
4720 BoundFn,
4721 ArgTuple,
4722 Opaque,
4723};</code></pre>
4724
4725 <h3 id="builtin-typeName">@typeName</h3>
4726 <pre><code class="zig">@typeName(T: type) -&gt; []u8</code></pre>
4727 <p>
4728 This function returns the string representation of a type.
4729 </p>
4730
4731 <h3 id="builtin-typeOf">@typeOf</h3>
4732 <pre><code class="zig">@typeOf(expression) -&gt; type</code></pre>
4733 <p>
4734 This function returns a compile-time constant, which is the type of the
4735 expression passed as an argument. The expression is evaluated.
4736 </p>
4737
4738 <h2 id="build-mode">Build Mode</h2>
4739 <p>
4740 Zig has three build modes:
4741 </p>
4742 <ul>
4743 <li><a href="#build-mode-debug">Debug</a> (default)</li>
4744 <li><a href="#build-mode-release-fast">ReleaseFast</a></li>
4745 <li><a href="#build-mode-release-safe">ReleaseSafe</a></li>
4746 </ul>
4747 <p>
4748 To add standard build options to a <code>build.zig</code> file:
4749 </p>
4750 <pre><code class="sh">const Builder = @import("std").build.Builder;
4751
4752pub fn build(b: &amp;Builder) {
4753 const exe = b.addExecutable("example", "example.zig");
4754 exe.setBuildMode(b.standardReleaseOptions());
4755 b.default_step.dependOn(&amp;exe.step);
4756}</code></pre>
4757 <p>
4758 This causes these options to be available:
4759 </p>
4760 <pre><code class="sh"> -Drelease-safe=(bool) optimizations on and safety on
4761 -Drelease-fast=(bool) optimizations on and safety off</code></pre>
4762 <h3 id="build-mode-debug">Debug</h2>
4763 <pre><code class="sh">$ zig build-exe example.zig</code></pre>
4764 <ul>
4765 <li>Fast compilation speed</li>
4766 <li>Safety checks enabled</li>
4767 <li>Slow runtime performance</li>
4768 </ul>
4769 <h3 id="build-mode-release-fast">ReleaseFast</h2>
4770 <pre><code class="sh">$ zig build-exe example.zig --release-fast</code></pre>
4771 <ul>
4772 <li>Fast runtime performance</li>
4773 <li>Safety checks disabled</li>
4774 <li>Slow compilation speed</li>
4775 </ul>
4776 <h3 id="build-mode-release-safe">ReleaseSafe</h2>
4777 <pre><code class="sh">$ zig build-exe example.zig --release-safe</code></pre>
4778 <ul>
4779 <li>Medium runtime performance</li>
4780 <li>Safety checks enabled</li>
4781 <li>Slow compilation speed</li>
4782 </ul>
4783 <p>See also:</p>
4784 <ul>
4785 <li><a href="#compile-variables">Compile Variables</a></li>
4786 <li><a href="#zig-build-system">Zig Build System</a></li>
4787 <li><a href="#undefined-behavior">Undefined Behavior</a></li>
4788 </ul>
4789 <h2 id="undefined-behavior">Undefined Behavior</h2>
4790 <p>
4791 Zig has many instances of undefined behavior. If undefined behavior is
4792 detected at compile-time, Zig emits an error. Most undefined behavior that
4793 cannot be detected at compile-time can be detected at runtime. In these cases,
4794 Zig has safety checks. Safety checks can be disabled on a per-block basis
4795 with <code>@setDebugSafety</code>. The <a href="#build-mode-release-fast">ReleaseFast</a>
4796 build mode disables all safety checks in order to facilitate optimizations.
4797 </p>
4798 <p>
4799 When a safety check fails, Zig crashes with a stack trace, like this:
4800 </p>
4801 <pre><code class="zig">test "safety check" {
4802 unreachable;
4803}</code></pre>
4804 <pre><code class="sh">$ zig test test.zig
4805Test 1/1 safety check...reached unreachable code
4806/home/andy/dev/zig/build/lib/zig/std/special/zigrt.zig:16:35: 0x000000000020331c in ??? (test)
4807 @import("std").debug.panic("{}", message_ptr[0...message_len]);
4808 ^
4809/home/andy/dev/zig/build/test.zig:2:5: 0x0000000000203297 in ??? (test)
4810 unreachable;
4811 ^
4812/home/andy/dev/zig/build/lib/zig/std/special/test_runner.zig:9:21: 0x0000000000214b0a in ??? (test)
4813 test_fn.func();
4814 ^
4815/home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:50:21: 0x0000000000214a17 in ??? (test)
4816 return root.main();
4817 ^
4818/home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:37:13: 0x00000000002148d0 in ??? (test)
4819 callMain(argc, argv, envp) %% exit(1);
4820 ^
4821/home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:30:20: 0x0000000000214820 in ??? (test)
4822 callMainAndExit()
4823 ^
4824
4825Tests failed. Use the following command to reproduce the failure:
4826./test</code></pre>
4827 <h3 id="undef-unreachable">Reaching Unreachable Code</h3>
4828 <p>At compile-time:</p>
4829 <pre><code class="zig">comptime {
4830 assert(false);
4831}
4832fn assert(ok: bool) {
4833 if (!ok) unreachable; // assertion failure
4834}</code></pre>
4835 <pre><code class="sh">$ zig build-obj test.zig
4836/home/andy/dev/zig/build/test.zig:5:14: error: unable to evaluate constant expression
4837 if (!ok) unreachable; // assertion failure
4838 ^
4839/home/andy/dev/zig/build/test.zig:2:11: note: called from here
4840 assert(false);
4841 ^
4842/home/andy/dev/zig/build/test.zig:1:10: note: called from here
4843comptime {
4844 ^</code></pre>
4845 <p>At runtime crashes with the message <code>reached unreachable code</code> and a stack trace.</p>
4846 <h3 id="undef-index-out-of-bounds">Index out of Bounds</h3>
4847 <p>At compile-time:</p>
4848 <pre><code class="zig">comptime {
4849 const array = "hello";
4850 const garbage = array[5];
4851}</code></pre>
4852 <pre><code class="sh">$ zig build-obj test.zig
4853/home/andy/dev/zig/build/test.zig:3:26: error: index 5 outside array of size 5
4854 const garbage = array[5];
4855 ^</code></pre>
4856 <p>At runtime crashes with the message <code>index out of bounds</code> and a stack trace.</p>
4857 <h3 id="undef-cast-negative-unsigned">Cast Negative Number to Unsigned Integer</h3>
4858 <p>At compile-time:</p>
4859 <pre><code class="zig">comptime {
4860 const value: i32 = -1;
4861 const unsigned = u32(value);
4862}</code></pre>
4863 <pre><code class="sh">$ zig build-obj test.zig test.zig:3:25: error: attempt to cast negative value to unsigned integer
4864 const unsigned = u32(value);
4865 ^</code></pre>
4866 <p>At runtime crashes with the message <code>attempt to cast negative value to unsigned integer</code> and a stack trace.</p>
4867 <p>
4868 If you are trying to obtain the maximum value of an unsigned integer, use <code>@maxValue(T)</code>,
4869 where <code>T</code> is the integer type, such as <code>u32</code>.
4870 </p>
4871 <h3 id="undef-cast-truncates-data">Cast Truncates Data</h3>
4872 <p>At compile-time:</p>
4873 <pre><code class="zig">comptime {
4874 const spartan_count: u16 = 300;
4875 const byte = u8(spartan_count);
4876}</code></pre>
4877 <pre><code class="sh">$ zig build-obj test.zig
4878test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
4879 const byte = u8(spartan_count);
4880 ^</code></pre>
4881 <p>At runtime crashes with the message <code>integer cast truncated bits</code> and a stack trace.</p>
4882 <p>
4883 If you are trying to truncate bits, use <code>@truncate(T, value)</code>,
4884 where <code>T</code> is the integer type, such as <code>u32</code>, and <code>value</code>
4885 is the value you want to truncate.
4886 </p>
4887 <h3 id="undef-integer-overflow">Integer Overflow</h3>
4888 <h4 id="undef-int-overflow-default">Default Operations</h4>
4889 <p>The following operators can cause integer overflow:</p>
4890 <ul>
4891 <li><code>+</code> (addition)</li>
4892 <li><code>-</code> (subtraction)</li>
4893 <li><code>-</code> (negation)</li>
4894 <li><code>*</code> (multiplication)</li>
4895 <li><code>/</code> (division)</li>
4896 <li><code>@divTrunc</code> (division)</li>
4897 <li><code>@divFloor</code> (division)</li>
4898 <li><code>@divExact</code> (division)</li>
4899 </ul>
4900 <p>Example with addition at compile-time:</p>
4901 <pre><code class="zig">comptime {
4902 var byte: u8 = 255;
4903 byte += 1;
4904}</code></pre>
4905 <pre><code class="sh">$ zig build-obj test.zig
4906/home/andy/dev/zig/build/test.zig:3:10: error: operation caused overflow
4907 byte += 1;
4908 ^</code></pre>
4909 <p>At runtime crashes with the message <code>integer overflow</code> and a stack trace.</p>
4910 <h4 id="undef-int-overflow-std">Standard Library Math Functions</h4>
4911 <p>These functions provided by the standard library return possible errors.</p>
4912 <ul>
4913 <li><code>@import("std").math.add</code></li>
4914 <li><code>@import("std").math.sub</code></li>
4915 <li><code>@import("std").math.mul</code></li>
4916 <li><code>@import("std").math.divTrunc</code></li>
4917 <li><code>@import("std").math.divFloor</code></li>
4918 <li><code>@import("std").math.divExact</code></li>
4919 <li><code>@import("std").math.shl</code></li>
4920 </ul>
4921 <p>Example of catching an overflow for addition:</p>
4922 <pre><code class="zig">const math = @import("std").math;
4923const warn = @import("std").debug.warn;
4924pub fn main() -&gt; %void {
4925 var byte: u8 = 255;
4926
4927 byte = if (math.add(u8, byte, 1)) |result| {
4928 result
4929 } else |err| {
4930 warn("unable to add one: {}\n", @errorName(err));
4931 return err;
4932 };
4933
4934 warn("result: {}\n", byte);
4935}</code></pre>
4936 <pre><code class="sh">$ zig build-exe test.zig
4937$ ./test
4938unable to add one: Overflow</code></pre>
4939 <h4 id="undef-int-overflow-builtin">Builtin Overflow Functions</h4>
4940 <p>
4941 These builtins return a <code>bool</code> of whether or not overflow
4942 occurred, as well as returning the overflowed bits:
4943 </p>
4944 <ul>
4945 <li><code>@addWithOverflow</code></li>
4946 <li><code>@subWithOverflow</code></li>
4947 <li><code>@mulWithOverflow</code></li>
4948 <li><code>@shlWithOverflow</code></li>
4949 </ul>
4950 <p>
4951 Example of <code>@addWithOverflow</code>:
4952 </p>
4953 <pre><code class="zig">const warn = @import("std").debug.warn;
4954pub fn main() -&gt; %void {
4955 var byte: u8 = 255;
4956
4957 var result: u8 = undefined;
4958 if (@addWithOverflow(u8, byte, 10, &amp;result)) {
4959 warn("overflowed result: {}\n", result);
4960 } else {
4961 warn("result: {}\n", result);
4962 }
4963}</code></pre>
4964 <pre><code class="sh">$ zig build-exe test.zig
4965$ ./test
4966overflowed result: 9</code></pre>
4967 <h4 id="undef-int-overflow-wrap">Wrapping Operations</h4>
4968 <p>
4969 These operations have guaranteed wraparound semantics.
4970 </p>
4971 <ul>
4972 <li><code>+%</code> (wraparound addition)</li>
4973 <li><code>-%</code> (wraparound subtraction)</li>
4974 <li><code>-%</code> (wraparound negation)</li>
4975 <li><code>*%</code> (wraparound multiplication)</li>
4976 </ul>
4977 <pre><code class="zig">const assert = @import("std").debug.assert;
4978
4979test "wraparound addition and subtraction" {
4980 const x: i32 = @maxValue(i32);
4981 const min_val = x +% 1;
4982 assert(min_val == @minValue(i32));
4983 const max_val = min_val -% 1;
4984 assert(max_val == @maxValue(i32));
4985}</code></pre>
4986 <h3 id="undef-shl-overflow">Exact Left Shift Overflow</h3>
4987 <p>At compile-time:</p>
4988 <pre><code class="zig">comptime {
4989 const x = @shlExact(u8(0b01010101), 2);
4990}</code></pre>
4991 <pre><code class="sh">$ zig build-obj test.zig
4992/home/andy/dev/zig/build/test.zig:2:15: error: operation caused overflow
4993 const x = @shlExact(u8(0b01010101), 2);
4994 ^</code></pre>
4995 <p>At runtime crashes with the message <code>left shift overflowed bits</code> and a stack trace.</p>
4996 <h3 id="undef-shr-overflow">Exact Right Shift Overflow</h3>
4997 <p>At compile-time:</p>
4998 <pre><code class="zig">comptime {
4999 const x = @shrExact(u8(0b10101010), 2);
5000}</code></pre>
5001 <pre><code class="sh">$ zig build-obj test.zig
5002/home/andy/dev/zig/build/test.zig:2:15: error: exact shift shifted out 1 bits
5003 const x = @shrExact(u8(0b10101010), 2);
5004 ^</code></pre>
5005 <p>At runtime crashes with the message <code>right shift overflowed bits</code> and a stack trace.</p>
5006 <h3 id="undef-division-by-zero">Division by Zero</h3>
5007 <p>At compile-time:</p>
5008 <pre><code class="zig">comptime {
5009 const a: i32 = 1;
5010 const b: i32 = 0;
5011 const c = a / b;
5012}</code></pre>
5013 <pre><code class="sh">$ zig build-obj test.zig
5014/home/andy/dev/zig/build/test.zig:4:17: error: division by zero is undefined
5015 const c = a / b;
5016 ^</code></pre>
5017 <p>At runtime crashes with the message <code>division by zero</code> and a stack trace.</p>
5018
5019 <h3 id="undef-remainder-division-by-zero">Remainder Division by Zero</h3>
5020 <p>At compile-time:</p>
5021 <pre><code class="zig">comptime {
5022 const a: i32 = 10;
5023 const b: i32 = 0;
5024 const c = a % b;
5025}</code></pre>
5026 <pre><code class="sh">$ zig build-obj test.zig
5027/home/andy/dev/zig/build/test.zig:4:17: error: division by zero is undefined
5028 const c = a % b;
5029 ^</code></pre>
5030 <p>At runtime crashes with the message <code>remainder division by zero</code> and a stack trace.</p>
5031
5032 <h3 id="undef-exact-division-remainder">Exact Division Remainder</h3>
5033 <p>TODO</p>
5034 <h3 id="undef-slice-widen-remainder">Slice Widen Remainder</h3>
5035 <p>TODO</p>
5036 <h3 id="undef-attempt-unwrap-null">Attempt to Unwrap Null</h3>
5037 <p>At compile-time:</p>
5038 <pre><code class="zig">comptime {
5039 const nullable_number: ?i32 = null;
5040 const number = ??nullable_number;
5041}</code></pre>
5042 <pre><code class="sh">$ zig build-obj test.zig
5043/home/andy/dev/zig/build/test.zig:3:20: error: unable to unwrap null
5044 const number = ??nullable_number;
5045 ^</code></pre>
5046 <p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>
5047 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
5048 the <code>if</code> expression:</p>
5049 <pre><code class="zig">const warn = @import("std").debug.warn;
5050pub fn main() -&gt; %void {
5051 const nullable_number: ?i32 = null;
5052
5053 if (nullable_number) |number| {
5054 warn("got number: {}\n", number);
5055 } else {
5056 warn("it's null\n");
5057 }
5058}</code></pre>
5059 <pre><code class="sh">% zig build-exe test.zig
5060$ ./test
5061it's null</code></pre>
5062 <h3 id="undef-attempt-unwrap-error">Attempt to Unwrap Error</h3>
5063 <p>At compile-time:</p>
5064 <pre><code class="zig">comptime {
5065 const number = %%getNumberOrFail();
5066}
5067
5068error UnableToReturnNumber;
5069
5070fn getNumberOrFail() -&gt; %i32 {
5071 return error.UnableToReturnNumber;
5072}</code></pre>
5073 <pre><code class="sh">$ zig build-obj test.zig
5074/home/andy/dev/zig/build/test.zig:2:20: error: unable to unwrap error 'UnableToReturnNumber'
5075 const number = %%getNumberOrFail();
5076 ^</code></pre>
5077 <p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p>
5078 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
5079 the <code>if</code> expression:</p>
5080 <pre><code class="zig">const warn = @import("std").debug.warn;
5081
5082pub fn main() -&gt; %void {
5083 const result = getNumberOrFail();
5084
5085 if (result) |number| {
5086 warn("got number: {}\n", number);
5087 } else |err| {
5088 warn("got error: {}\n", @errorName(err));
5089 }
5090}
5091
5092error UnableToReturnNumber;
5093
5094fn getNumberOrFail() -&gt; %i32 {
5095 return error.UnableToReturnNumber;
5096}</code></pre>
5097 <pre><code class="sh">$ zig build-exe test.zig
5098$ ./test
5099got error: UnableToReturnNumber</code></pre>
5100
5101 <h3 id="undef-invalid-error-code">Invalid Error Code</h3>
5102 <p>At compile-time:</p>
5103 <pre><code class="zig">error AnError;
5104comptime {
5105 const err = error.AnError;
5106 const number = u32(err) + 10;
5107 const invalid_err = error(number);
5108}</code></pre>
5109 <pre><code class="sh">$ zig build-obj test.zig
5110/home/andy/dev/zig/build/test.zig:5:30: error: integer value 11 represents no error
5111 const invalid_err = error(number);
5112 ^</code></pre>
5113 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>
5114 <h3 id="undef-invalid-enum-cast">Invalid Enum Cast</h3>
5115 <p>TODO</p>
5116
5117 <h3 id="undef-incorrect-pointer-alignment">Incorrect Pointer Alignment</h3>
5118 <p>TODO</p>
5119
5120 <h2 id="memory">Memory</h2>
5121 <p>TODO: explain no default allocator in zig</p>
5122 <p>TODO: show how to use the allocator interface</p>
5123 <p>TODO: mention debug allocator</p>
5124 <p>TODO: importance of checking for allocation failure</p>
5125 <p>TODO: mention overcommit and the OOM Killer</p>
5126 <p>TODO: mention recursion</p>
5127 <p>See also:</p>
5128 <ul>
5129 <li><a href="#pointers">Pointers</a></li>
5130 </ul>
5131
5132 <h2 id="compile-variables">Compile Variables</h2>
5133 <p>
5134 Compile variables are accessible by importing the <code>"builtin"</code> package,
5135 which the compiler makes available to every Zig source file. It contains
5136 compile-time constants such as the current target, endianness, and release mode.
5137 </p>
5138 <pre><code class="zig">const builtin = @import("builtin");
5139const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';</code></pre>
5140 <p>
5141 Example of what is imported with <code>@import("builtin")</code>:
5142 </p>
5143 <pre><code class="zig">pub const Os = enum {
5144 freestanding,
5145 cloudabi,
5146 darwin,
5147 dragonfly,
5148 freebsd,
5149 ios,
5150 kfreebsd,
5151 linux,
5152 lv2,
5153 macosx,
5154 netbsd,
5155 openbsd,
5156 solaris,
5157 windows,
5158 haiku,
5159 minix,
5160 rtems,
5161 nacl,
5162 cnk,
5163 bitrig,
5164 aix,
5165 cuda,
5166 nvcl,
5167 amdhsa,
5168 ps4,
5169 elfiamcu,
5170 tvos,
5171 watchos,
5172 mesa3d,
5173};
5174
5175pub const Arch = enum {
5176 armv8_2a,
5177 armv8_1a,
5178 armv8,
5179 armv8m_baseline,
5180 armv8m_mainline,
5181 armv7,
5182 armv7em,
5183 armv7m,
5184 armv7s,
5185 armv7k,
5186 armv6,
5187 armv6m,
5188 armv6k,
5189 armv6t2,
5190 armv5,
5191 armv5te,
5192 armv4t,
5193 armeb,
5194 aarch64,
5195 aarch64_be,
5196 avr,
5197 bpfel,
5198 bpfeb,
5199 hexagon,
5200 mips,
5201 mipsel,
5202 mips64,
5203 mips64el,
5204 msp430,
5205 powerpc,
5206 powerpc64,
5207 powerpc64le,
5208 r600,
5209 amdgcn,
5210 sparc,
5211 sparcv9,
5212 sparcel,
5213 s390x,
5214 tce,
5215 thumb,
5216 thumbeb,
5217 i386,
5218 x86_64,
5219 xcore,
5220 nvptx,
5221 nvptx64,
5222 le32,
5223 le64,
5224 amdil,
5225 amdil64,
5226 hsail,
5227 hsail64,
5228 spir,
5229 spir64,
5230 kalimbav3,
5231 kalimbav4,
5232 kalimbav5,
5233 shave,
5234 lanai,
5235 wasm32,
5236 wasm64,
5237 renderscript32,
5238 renderscript64,
5239};
5240pub const Environ = enum {
5241 gnu,
5242 gnuabi64,
5243 gnueabi,
5244 gnueabihf,
5245 gnux32,
5246 code16,
5247 eabi,
5248 eabihf,
5249 android,
5250 musl,
5251 musleabi,
5252 musleabihf,
5253 msvc,
5254 itanium,
5255 cygnus,
5256 amdopencl,
5257 coreclr,
5258};
5259
5260pub const ObjectFormat = enum {
5261 unknown,
5262 coff,
5263 elf,
5264 macho,
5265};
5266
5267pub const GlobalLinkage = enum {
5268 Internal,
5269 Strong,
5270 Weak,
5271 LinkOnce,
5272};
5273
5274pub const AtomicOrder = enum {
5275 Unordered,
5276 Monotonic,
5277 Acquire,
5278 Release,
5279 AcqRel,
5280 SeqCst,
5281};
5282
5283pub const Mode = enum {
5284 Debug,
5285 ReleaseSafe,
5286 ReleaseFast,
5287};
5288
5289pub const is_big_endian = false;
5290pub const is_test = false;
5291pub const os = Os.linux;
5292pub const arch = Arch.x86_64;
5293pub const environ = Environ.gnu;
5294pub const object_format = ObjectFormat.elf;
5295pub const mode = Mode.ReleaseFast;
5296pub const link_libs = [][]const u8 {
5297};</code></pre>
5298 <p>See also:</p>
5299 <ul>
5300 <li><a href="#build-mode">Build Mode</a></li>
5301 </ul>
5302 <h2 id="root-source-file">Root Source File</h2>
5303 <p>TODO: explain how root source file finds other files</p>
5304 <p>TODO: pub fn main</p>
5305 <p>TODO: pub fn panic</p>
5306 <p>TODO: if linking with libc you can use export fn main</p>
5307 <p>TODO: order independent top level declarations</p>
5308 <p>TODO: lazy analysis</p>
5309 <p>TODO: using comptime { _ = @import() }</p>
5310 <h2 id="zig-test">Zig Test</h2>
5311 <p>TODO: basic usage</p>
5312 <p>TODO: lazy analysis</p>
5313 <p>TODO: --test-filter</p>
5314 <p>TODO: --test-name-prefix</p>
5315 <p>TODO: testing in releasefast and releasesafe mode. assert still works</p>
5316 <h2 id="zig-build-system">Zig Build System</h2>
5317 <p>TODO: explain purpose, it's supposed to replace make/cmake</p>
5318 <p>TODO: example of building a zig executable</p>
5319 <p>TODO: example of building a C library</p>
5320 <h2 id="c">C</h2>
5321 <p>
5322 Although Zig is independent of C, and, unlike most other languages, does not depend on libc,
5323 Zig acknowledges the importance of interacting with existing C code.
5324 </p>
5325 <p>
5326 There are a few ways that Zig facilitates C interop.
5327 </p>
5328 <h3 id="c-type-primitives">C Type Primitives</h3>
5329 <p>
5330 These have guaranteed C ABI compatibility and can be used like any other type.
5331 </p>
5332 <ul>
5333 <li><code>c_short</code></li>
5334 <li><code>c_ushort</code></li>
5335 <li><code>c_int</code></li>
5336 <li><code>c_uint</code></li>
5337 <li><code>c_long</code></li>
5338 <li><code>c_ulong</code></li>
5339 <li><code>c_longlong</code></li>
5340 <li><code>c_ulonglong</code></li>
5341 <li><code>c_longdouble</code></li>
5342 <li><code>c_void</code></li>
5343 </ul>
5344 <p>See also:</p>
5345 <ul>
5346 <li><a href="#primitive-types">Primitive Types</a></li>
5347 </ul>
5348 <h3 id="c-string-literals">C String Literals</h3>
5349 <pre><code class="zig">extern fn puts(&amp;const u8);
5350
5351pub fn main() -&gt; %void {
5352 puts(c"this has a null terminator");
5353 puts(
5354 c\\and so
5355 c\\does this
5356 c\\multiline C string literal
5357 );
5358}</code></pre>
5359 <p>See also:</p>
5360 <ul>
5361 <li><a href="#string-literals">String Literals</a></li>
5362 </ul>
5363 <h3 id="c-import">Import from C Header File</h3>
5364 <p>
5365 The <code>@cImport</code> builtin function can be used
5366 to directly import symbols from .h files:
5367 </p>
5368 <pre><code class="zig">const c = @cImport(@cInclude("stdio.h"));
5369pub fn main() -&gt; %void {
5370 c.printf("hello\n");
5371}</code></pre>
5372 <p>
5373 The <code>@cImport</code> function takes an expression as a parameter.
5374 This expression is evaluated at compile-time and is used to control
5375 preprocessor directives and include multiple .h files:
5376 </p>
5377 <pre><code class="zig">const builtin = @import("builtin");
5378
5379const c = @cImport({
5380 @cDefine("NDEBUG", builtin.mode == builtin.Mode.ReleaseFast);
5381 if (something) {
5382 @cDefine("_GNU_SOURCE", {});
5383 }
5384 @cInclude("stdlib.h")
5385 if (something) {
5386 @cUndef("_GNU_SOURCE");
5387 }
5388 @cInclude("soundio.h");
5389});</code></pre>
5390 <p>See also:</p>
5391 <ul>
5392 <li><a href="#builtin-cImport">@cImport</a></li>
5393 <li><a href="#builtin-cInclude">@cInclude</a></li>
5394 <li><a href="#builtin-cDefine">@cDefine</a></li>
5395 <li><a href="#builtin-cUndef">@cUndef</a></li>
5396 <li><a href="#builtin-import">@import</a></li>
5397 </ul>
5398 <h3 id="mixing-object-files">Mixing Object Files</h3>
5399 <p>
5400 You can mix Zig object files with any other object files that respect the C ABI. Example:
5401 </p>
5402 <h4>base64.zig</h4>
5403 <pre><code class="zig">const base64 = @import("std").base64;
5404
5405export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize,
5406 source_ptr: &amp;const u8, source_len: usize) -&gt; usize
5407{
5408 const src = source_ptr[0...source_len];
5409 const dest = dest_ptr[0...dest_len];
5410 return base64.decode(dest, src).len;
5411}</code></pre>
5412 <h4>test.c</h4>
5413 <pre><code class="c">// This header is generated by zig from base64.zig
5414#include "base64.h"
5415
5416#include &lt;string.h&gt;
5417#include &lt;stdio.h&gt;
5418
5419int main(int argc, char **argv) {
5420 const char *encoded = "YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz";
5421 char buf[200];
5422
5423 size_t len = decode_base_64(buf, 200, encoded, strlen(encoded));
5424 buf[len] = 0;
5425 puts(buf);
5426
5427 return 0;
5428}</code></pre>
5429 <h4>build.zig</h4>
5430 <pre><code class="zig">const Builder = @import("std").build.Builder;
5431
5432pub fn build(b: &amp;Builder) {
5433 const obj = b.addObject("base64", "base64.zig");
5434
5435 const exe = b.addCExecutable("test");
5436 exe.addCompileFlags([][]const u8 {
5437 "-std=c99",
5438 });
5439 exe.addSourceFile("test.c");
5440 exe.addObject(obj);
5441 exe.setOutputPath(".");
5442
5443 b.default_step.dependOn(&amp;exe.step);
5444}</code></pre>
5445 <h4>Terminal</h4>
5446 <pre><code class="sh">$ zig build
5447$ ./test
5448all your base are belong to us</code></pre>
5449 <p>See also:</p>
5450 <ul>
5451 <li><a href="#targets">Targets</a></li>
5452 <li><a href="#zig-build-system">Zig Build System</a></li>
5453 </ul>
5454 <h2 id="targets">Targets</h2>
5455 <p>
5456 Zig supports generating code for all targets that LLVM supports. Here is
5457 what it looks like to execute <code>zig targets</code> on a Linux x86_64
5458 computer:
5459 </p>
5460 <pre><code class="sh">$ zig targets
5461Architectures:
5462 armv8_2a
5463 armv8_1a
5464 armv8
5465 armv8m_baseline
5466 armv8m_mainline
5467 armv7
5468 armv7em
5469 armv7m
5470 armv7s
5471 armv7k
5472 armv6
5473 armv6m
5474 armv6k
5475 armv6t2
5476 armv5
5477 armv5te
5478 armv4t
5479 armeb
5480 aarch64
5481 aarch64_be
5482 avr
5483 bpfel
5484 bpfeb
5485 hexagon
5486 mips
5487 mipsel
5488 mips64
5489 mips64el
5490 msp430
5491 powerpc
5492 powerpc64
5493 powerpc64le
5494 r600
5495 amdgcn
5496 sparc
5497 sparcv9
5498 sparcel
5499 s390x
5500 tce
5501 thumb
5502 thumbeb
5503 i386
5504 x86_64 (native)
5505 xcore
5506 nvptx
5507 nvptx64
5508 le32
5509 le64
5510 amdil
5511 amdil64
5512 hsail
5513 hsail64
5514 spir64
5515 kalimbav3
5516 kalimbav4
5517 kalimbav5
5518 shave
5519 lanai
5520 wasm32
5521 wasm64
5522 renderscript32
5523 renderscript64
5524
5525Operating Systems:
5526 freestanding
5527 cloudabi
5528 darwin
5529 dragonfly
5530 freebsd
5531 ios
5532 kfreebsd
5533 linux (native)
5534 lv2
5535 macosx
5536 netbsd
5537 openbsd
5538 solaris
5539 windows
5540 haiku
5541 minix
5542 rtems
5543 nacl
5544 cnk
5545 bitrig
5546 aix
5547 cuda
5548 nvcl
5549 amdhsa
5550 ps4
5551 elfiamcu
5552 tvos
5553 watchos
5554 mesa3d
5555
5556Environments:
5557 gnu (native)
5558 gnuabi64
5559 gnueabi
5560 gnueabihf
5561 gnux32
5562 code16
5563 eabi
5564 eabihf
5565 android
5566 musl
5567 musleabi
5568 musleabihf
5569 msvc
5570 itanium
5571 cygnus
5572 amdopencl
5573 coreclr</code></pre>
5574 <p>
5575 The Zig Standard Library (<code>@import("std")</code>) has architecture, environment, and operating sytsem
5576 abstractions, and thus takes additional work to support more platforms. It currently supports
5577 Linux x86_64. Not all standard library code requires operating system abstractions, however,
5578 so things such as generic data structures work an all above platforms.
5579 </p>
5580 <h2 id="style-guide">Style Guide</h2>
5581 <p>
5582These coding conventions are not enforced by the compiler, but they are shipped in
5583this documentation along with the compiler in order to provide a point of
5584reference, should anyone wish to point to an authority on agreed upon Zig
5585coding style.
5586 </p>
5587 <h3 id="style-guide-whitespace">Whitespace</h3>
5588 <ul>
5589 <li>
5590 4 space indentation
5591 </li>
5592 <li>
5593 Open braces on same line, unless you need to wrap.
5594 </li>
5595 <li>If a list of things is longer than 2, put each item on its own line and
5596 exercise the abilty to put an extra comma at the end.
5597 </li>
5598 <li>
5599 Line length: aim for 100; use common sense.
5600 </li>
5601 </ul>
5602 <h3 id="style-guide-names">Names</h3>
5603 <p>
5604 Roughly speaking: <code>camelCaseFunctionName</code>, <code>TitleCaseTypeName</code>,
5605 <code>snake_case_variable_name</code>. More precisely:
5606 </p>
5607 <ul>
5608 <li>
5609 If <code>x</code> is a <code>struct</code> (or an alias of a <code>struct</code>),
5610 then <code>x</code> should be <code>TitleCase</code>.
5611 </li>
5612 <li>
5613 If <code>x</code> otherwise identifies a type, <code>x</code> should have <code>snake_case</code>.
5614 </li>
5615 <li>
5616 If <code>x</code> is callable, and <code>x</code>'s return type is <code>type</code>, then <code>x</code> should be <code>TitleCase</code>.
5617 </li>
5618 <li>
5619 If <code>x</code> is otherwise callable, then <code>x</code> should be <code>camelCase</code>.
5620 </li>
5621 <li>
5622 Otherwise, <code>x</code> should be <code>snake_case</code>.
5623 </li>
5624 </ul>
5625 <p>
5626 Acronyms, initialisms, proper nouns, or any other word that has capitalization
5627 rules in written English are subject to naming conventions just like any other
5628 word. Even acronyms that are only 2 letters long are subject to these
5629 conventions.
5630 </p>
5631 <p>
5632 These are general rules of thumb; if it makes sense to do something different,
5633 do what makes sense. For example, if there is an established convention such as
5634 <code>ENOENT</code>, follow the established convention.
5635 </p>
5636 <h3 id="style-guide-examples">Examples</h3>
5637 <pre><code class="zig">const namespace_name = @import("dir_name/file_name.zig");
5638var global_var: i32 = undefined;
5639const const_name = 42;
5640const primitive_type_alias = f32;
5641const string_alias = []u8;
5642
5643const StructName = struct {};
5644const StructAlias = StructName;
5645
5646fn functionName(param_name: TypeName) {
5647 var functionPointer = functionName;
5648 functionPointer();
5649 functionPointer = otherFunction;
5650 functionPointer();
5651}
5652const functionAlias = functionName;
5653
5654fn ListTemplateFunction(comptime ChildType: type, comptime fixed_size: usize) -&gt; type {
5655 return List(ChildType, fixed_size);
5656}
5657
5658fn ShortList(comptime T: type, comptime n: usize) -&gt; type {
5659 struct {
5660 field_name: [n]T,
5661 fn methodName() {}
5662 }
5663}
5664
5665// The word XML loses its casing when used in Zig identifiers.
5666const xml_document =
5667 \\&lt;?xml version="1.0" encoding="UTF-8"?&gt;
5668 \\&lt;document&gt;
5669 \\&lt;/document&gt;
5670;
5671const XmlParser = struct {};
5672
5673// The initials BE (Big Endian) are just another word in Zig identifier names.
5674fn readU32Be() -&gt; u32 {}</code></pre>
5675 <p>
5676 See the Zig Standard Library for more examples.
5677 </p>
5678 <h2 id="grammar">Grammar</h2>
5679 <pre><code>Root = many(TopLevelItem) EOF
5680
5681TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
5682
5683TestDecl = "test" String Block
5684
5685TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
5686
5687ErrorValueDecl = "error" Symbol ";"
5688
5689GlobalVarDecl = VariableDeclaration ";"
5690
5691VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression
5692
5693ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
5694
5695ContainerField = Symbol option(":" Expression) ","
5696
5697UseDecl = "use" Expression ";"
5698
5699ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
5700
5701FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("-&gt;" TypeExpr)
5702
5703VisibleMod = "pub" | "export"
5704
5705FnDef = option("inline" | "extern") FnProto Block
5706
5707ParamDeclList = "(" list(ParamDecl, ",") ")"
5708
5709ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...")
5710
5711Block = "{" many(Statement) option(Expression) "}"
5712
5713Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";"
5714
5715Label = Symbol ":"
5716
5717TypeExpr = PrefixOpExpression | "var"
5718
5719BlockOrExpression = Block | Expression
5720
5721Expression = ReturnExpression | BreakExpression | AssignmentExpression
5722
5723AsmExpression = "asm" option("volatile") "(" String option(AsmOutput) ")"
5724
5725AsmOutput = ":" list(AsmOutputItem, ",") option(AsmInput)
5726
5727AsmInput = ":" list(AsmInputItem, ",") option(AsmClobbers)
5728
5729AsmOutputItem = "[" Symbol "]" String "(" (Symbol | "-&gt;" TypeExpr) ")"
5730
5731AsmInputItem = "[" Symbol "]" String "(" Expression ")"
5732
5733AsmClobbers= ":" list(String, ",")
5734
5735UnwrapExpression = BoolOrExpression (UnwrapNullable | UnwrapError) | BoolOrExpression
5736
5737UnwrapNullable = "??" Expression
5738
5739UnwrapError = "%%" option("|" Symbol "|") Expression
5740
5741AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
5742
5743AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&lt;&lt;=" | "&gt;&gt;=" | "&amp;=" | "^=" | "|=" | "*%=" | "+%=" | "-%="
5744
5745BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
5746
5747CompTimeExpression(body) = "comptime" body
5748
5749SwitchExpression = "switch" "(" Expression ")" "{" many(SwitchProng) "}"
5750
5751SwitchProng = (list(SwitchItem, ",") | "else") "=&gt;" option("|" option("*") Symbol "|") Expression ","
5752
5753SwitchItem = Expression | (Expression "..." Expression)
5754
5755ForExpression(body) = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") body option("else" BlockExpression(body))
5756
5757BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
5758
5759ReturnExpression = option("%") "return" option(Expression)
5760
5761BreakExpression = "break" option(Expression)
5762
5763Defer(body) = option("%") "defer" body
5764
5765IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
5766
5767TryExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body "else" "|" Symbol "|" BlockExpression(body)
5768
5769TestExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" BlockExpression(body))
5770
5771WhileExpression(body) = option("inline") "while" "(" Expression ")" option("|" option("*") Symbol "|") option(":" "(" Expression ")") body option("else" option("|" Symbol "|") BlockExpression(body))
5772
5773BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
5774
5775ComparisonExpression = BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression
5776
5777ComparisonOperator = "==" | "!=" | "&lt;" | "&gt;" | "&lt;=" | "&gt;="
5778
5779BinaryOrExpression = BinaryXorExpression "|" BinaryOrExpression | BinaryXorExpression
5780
5781BinaryXorExpression = BinaryAndExpression "^" BinaryXorExpression | BinaryAndExpression
5782
5783BinaryAndExpression = BitShiftExpression "&amp;" BinaryAndExpression | BitShiftExpression
5784
5785BitShiftExpression = AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression
5786
5787BitShiftOperator = "&lt;&lt;" | "&gt;&gt;" | "&lt;&lt;"
5788
5789AdditionExpression = MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression
5790
5791AdditionOperator = "+" | "-" | "++" | "+%" | "-%"
5792
5793MultiplyExpression = CurlySuffixExpression MultiplyOperator MultiplyExpression | CurlySuffixExpression
5794
5795CurlySuffixExpression = TypeExpr option(ContainerInitExpression)
5796
5797MultiplyOperator = "*" | "/" | "%" | "**" | "*%"
5798
5799PrefixOpExpression = PrefixOp PrefixOpExpression | SuffixOpExpression
5800
5801SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
5802
5803FieldAccessExpression = "." Symbol
5804
5805FnCallExpression = "(" list(Expression, ",") ")"
5806
5807ArrayAccessExpression = "[" Expression "]"
5808
5809SliceExpression = "[" Expression ".." option(Expression) "]"
5810
5811ContainerInitExpression = "{" ContainerInitBody "}"
5812
5813ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
5814
5815StructLiteralField = "." Symbol "=" Expression
5816
5817PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
5818
5819PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
5820
5821ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr
5822
5823GotoExpression = "goto" Symbol
5824
5825GroupedExpression = "(" Expression ")"
5826
5827KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
5828
5829ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"</code></pre>
5830 <h2 id="zen">Zen</h2>
5831 <ul>
5832 <li>Communicate intent precisely.</li>
5833 <li>Edge cases matter.</li>
5834 <li>Favor reading code over writing code.</li>
5835 <li>Only one obvious way to do things.</li>
5836 <li>Runtime crashes are better than bugs.</li>
5837 <li>Compile errors are better than runtime crashes.</li>
5838 <li>Incremental improvements.</li>
5839 <li>Avoid local maximums.</li>
5840 <li>Reduce the amount one must remember.</li>
5841 <li>Minimize energy spent on coding style.</li>
5842 <li>Together we serve end users.</li>
5843 </ul>
5844 <h2>TODO</h2>
5845 <p>TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)</p>
5846 </div>
5847 <script src="highlight/highlight.pack.js"></script>
5848 <script>hljs.initHighlightingOnLoad();</script>
5849 </body>
5850</html>
5851
example/cat/main.zig+5-6
......@@ -10,14 +10,13 @@ pub fn main() -> %void {
1010 const exe = %return unwrapArg(??args_it.next(allocator));
1111 var catted_anything = false;
1212 var stdout_file = %return io.getStdOut();
13 const stdout = &stdout_file.out_stream;
1413
1514 while (args_it.next(allocator)) |arg_or_err| {
1615 const arg = %return unwrapArg(arg_or_err);
1716 if (mem.eql(u8, arg, "-")) {
1817 catted_anything = true;
1918 var stdin_file = %return io.getStdIn();
20 %return cat_stream(stdout, &stdin_file.in_stream);
19 %return cat_file(&stdout_file, &stdin_file);
2120 } else if (arg[0] == '-') {
2221 return usage(exe);
2322 } else {
......@@ -28,12 +27,12 @@ pub fn main() -> %void {
2827 defer file.close();
2928
3029 catted_anything = true;
31 %return cat_stream(stdout, &file.in_stream);
30 %return cat_file(&stdout_file, &file);
3231 }
3332 }
3433 if (!catted_anything) {
3534 var stdin_file = %return io.getStdIn();
36 %return cat_stream(stdout, &stdin_file.in_stream);
35 %return cat_file(&stdout_file, &stdin_file);
3736 }
3837}
3938
......@@ -42,11 +41,11 @@ fn usage(exe: []const u8) -> %void {
4241 return error.Invalid;
4342}
4443
45fn cat_stream(stdout: &io.OutStream, is: &io.InStream) -> %void {
44fn cat_file(stdout: &io.File, file: &io.File) -> %void {
4645 var buf: [1024 * 4]u8 = undefined;
4746
4847 while (true) {
49 const bytes_read = is.read(buf[0..]) %% |err| {
48 const bytes_read = file.read(buf[0..]) %% |err| {
5049 warn("Unable to read from stream: {}\n", @errorName(err));
5150 return err;
5251 };
example/guess_number/main.zig+3-3
......@@ -6,10 +6,10 @@ const os = std.os;
66
77pub fn main() -> %void {
88 var stdout_file = %return io.getStdOut();
9 const stdout = &stdout_file.out_stream;
9 var stdout_file_stream = io.FileOutStream.init(&stdout_file);
10 const stdout = &stdout_file_stream.stream;
1011
1112 var stdin_file = %return io.getStdIn();
12 const stdin = &stdin_file.in_stream;
1313
1414 %return stdout.print("Welcome to the Guess Number Game in Zig.\n");
1515
......@@ -24,7 +24,7 @@ pub fn main() -> %void {
2424 %return stdout.print("\nGuess a number between 1 and 100: ");
2525 var line_buf : [20]u8 = undefined;
2626
27 const line_len = stdin.read(line_buf[0..]) %% |err| {
27 const line_len = stdin_file.read(line_buf[0..]) %% |err| {
2828 %return stdout.print("Unable to read from stdin: {}\n", @errorName(err));
2929 return err;
3030 };
example/hello_world/hello.zig+1-2
......@@ -3,8 +3,7 @@ const std = @import("std");
33pub fn main() -> %void {
44 // If this program is run without stdout attached, exit with an error.
55 var stdout_file = %return std.io.getStdOut();
6 const stdout = &stdout_file.out_stream;
76 // If this program encounters pipe failure when printing to stdout, exit
87 // with an error.
9 %return stdout.print("Hello, world!\n");
8 %return stdout_file.write("Hello, world!\n");
109}
src-self-hosted/main.zig+1-1
......@@ -1,7 +1,7 @@
11const builtin = @import("builtin");
22const io = @import("std").io;
33const os = @import("std").os;
4const heap = @import("std").mem;
4const heap = @import("std").heap;
55
66// TODO: sync up CLI with c++ code
77// TODO: concurrency
src/ir.cpp+1
......@@ -12823,6 +12823,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1282312823 case TypeTableEntryIdEnum:
1282412824 {
1282512825 TypeTableEntry *tag_type = target_type->data.enumeration.tag_type;
12826 assert(tag_type != nullptr);
1282612827 if (pointee_val) {
1282712828 ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base);
1282812829 bigint_init_unsigned(&out_val->data.x_bigint, pointee_val->data.x_enum.tag);
src/main.cpp+55-53
......@@ -20,70 +20,70 @@ static int usage(const char *arg0) {
2020 fprintf(stderr, "Usage: %s [command] [options]\n"
2121 "Commands:\n"
2222 " build build project from build.zig\n"
23 " build-exe $source create executable from source or object files\n"
24 " build-lib $source create library from source or object files\n"
25 " build-obj $source create object from source or assembly\n"
26 " parsec $source convert c code to zig code\n"
23 " build-exe [source] create executable from source or object files\n"
24 " build-lib [source] create library from source or object files\n"
25 " build-obj [source] create object from source or assembly\n"
26 " parsec [source] convert c code to zig code\n"
2727 " targets list available compilation targets\n"
28 " test $source create and run a test build\n"
28 " test [source] create and run a test build\n"
2929 " version print version number and exit\n"
3030 " zen print zen of zig and exit\n"
3131 "Compile Options:\n"
32 " --assembly $source add assembly file to build\n"
33 " --cache-dir $path override the cache directory\n"
34 " --color $auto|off|on enable or disable colored error messages\n"
35 " --emit $filetype emit a specific file format as compilation output\n"
32 " --assembly [source] add assembly file to build\n"
33 " --cache-dir [path] override the cache directory\n"
34 " --color [auto|off|on] enable or disable colored error messages\n"
35 " --emit [filetype] emit a specific file format as compilation output\n"
3636 " --enable-timing-info print timing diagnostics\n"
37 " --libc-include-dir $path directory where libc stdlib.h resides\n"
38 " --name $name override output name\n"
39 " --output $file override destination path\n"
40 " --output-h $file override generated header file path\n"
41 " --pkg-begin $name $path make package available to import and push current pkg\n"
37 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
38 " --name [name] override output name\n"
39 " --output [file] override destination path\n"
40 " --output-h [file] override generated header file path\n"
41 " --pkg-begin [name] [path] make package available to import and push current pkg\n"
4242 " --pkg-end pop current pkg\n"
4343 " --release-fast build with optimizations on and safety off\n"
4444 " --release-safe build with optimizations on and safety on\n"
4545 " --static output will be statically linked\n"
4646 " --strip exclude debug symbols\n"
47 " --target-arch $name specify target architecture\n"
48 " --target-environ $name specify target environment\n"
49 " --target-os $name specify target operating system\n"
47 " --target-arch [name] specify target architecture\n"
48 " --target-environ [name] specify target environment\n"
49 " --target-os [name] specify target operating system\n"
5050 " --verbose-tokenize turn on compiler debug output for tokenization\n"
5151 " --verbose-ast turn on compiler debug output for parsing into an AST\n"
5252 " --verbose-link turn on compiler debug output for linking\n"
5353 " --verbose-ir turn on compiler debug output for Zig IR\n"
5454 " --verbose-llvm-ir turn on compiler debug output for LLVM IR\n"
5555 " --verbose-cimport turn on compiler debug output for C imports\n"
56 " --zig-install-prefix $path override directory where zig thinks it is installed\n"
57 " -dirafter $dir same as -isystem but do it last\n"
58 " -isystem $dir add additional search path for other .h files\n"
59 " -mllvm $arg additional arguments to forward to LLVM's option processing\n"
56 " --zig-install-prefix [path] override directory where zig thinks it is installed\n"
57 " -dirafter [dir] same as -isystem but do it last\n"
58 " -isystem [dir] add additional search path for other .h files\n"
59 " -mllvm [arg] additional arguments to forward to LLVM's option processing\n"
6060 "Link Options:\n"
61 " --ar-path $path set the path to ar\n"
62 " --dynamic-linker $path set the path to ld.so\n"
61 " --ar-path [path] set the path to ar\n"
62 " --dynamic-linker [path] set the path to ld.so\n"
6363 " --each-lib-rpath add rpath for each used dynamic library\n"
64 " --libc-lib-dir $path directory where libc crt1.o resides\n"
65 " --libc-static-lib-dir $path directory where libc crtbegin.o resides\n"
66 " --msvc-lib-dir $path (windows) directory where vcruntime.lib resides\n"
67 " --kernel32-lib-dir $path (windows) directory where kernel32.lib resides\n"
68 " --library $lib link against lib\n"
69 " --library-path $dir add a directory to the library search path\n"
70 " --linker-script $path use a custom linker script\n"
71 " --object $obj add object file to build\n"
72 " -L$dir alias for --library-path\n"
64 " --libc-lib-dir [path] directory where libc crt1.o resides\n"
65 " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
66 " --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides\n"
67 " --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides\n"
68 " --library [lib] link against lib\n"
69 " --library-path [dir] add a directory to the library search path\n"
70 " --linker-script [path] use a custom linker script\n"
71 " --object [obj] add object file to build\n"
72 " -L[dir] alias for --library-path\n"
7373 " -rdynamic add all symbols to the dynamic symbol table\n"
74 " -rpath $path add directory to the runtime library search path\n"
74 " -rpath [path] add directory to the runtime library search path\n"
7575 " -mconsole (windows) --subsystem console to the linker\n"
7676 " -mwindows (windows) --subsystem windows to the linker\n"
77 " -framework $name (darwin) link against framework\n"
78 " -mios-version-min $ver (darwin) set iOS deployment target\n"
79 " -mmacosx-version-min $ver (darwin) set Mac OS X deployment target\n"
80 " --ver-major $ver dynamic library semver major version\n"
81 " --ver-minor $ver dynamic library semver minor version\n"
82 " --ver-patch $ver dynamic library semver patch version\n"
77 " -framework [name] (darwin) link against framework\n"
78 " -mios-version-min [ver] (darwin) set iOS deployment target\n"
79 " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
80 " --ver-major [ver] dynamic library semver major version\n"
81 " --ver-minor [ver] dynamic library semver minor version\n"
82 " --ver-patch [ver] dynamic library semver patch version\n"
8383 "Test Options:\n"
84 " --test-filter $text skip tests that do not match filter\n"
85 " --test-name-prefix $text add prefix to all tests\n"
86 " --test-cmd $arg specify test execution command one arg at a time\n"
84 " --test-filter [text] skip tests that do not match filter\n"
85 " --test-name-prefix [text] add prefix to all tests\n"
86 " --test-cmd [arg] specify test execution command one arg at a time\n"
8787 " --test-cmd-bin appends test binary path to test cmd args\n"
8888 , arg0);
8989 return EXIT_FAILURE;
......@@ -401,8 +401,8 @@ int main(int argc, char **argv) {
401401 "\n"
402402 "General Options:\n"
403403 " --help Print this help and exit\n"
404 " --build-file $file Override path to build.zig\n"
405 " --cache-dir $path Override path to cache directory\n"
404 " --build-file [file] Override path to build.zig\n"
405 " --cache-dir [path] Override path to cache directory\n"
406406 " --verbose Print commands before executing them\n"
407407 " --verbose-tokenize Enable compiler debug output for tokenization\n"
408408 " --verbose-ast Enable compiler debug output for parsing into an AST\n"
......@@ -410,14 +410,14 @@ int main(int argc, char **argv) {
410410 " --verbose-ir Enable compiler debug output for Zig IR\n"
411411 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
412412 " --verbose-cimport Enable compiler debug output for C imports\n"
413 " --prefix $path Override default install prefix\n"
413 " --prefix [path] Override default install prefix\n"
414414 "\n"
415415 "Project-specific options become available when the build file is found.\n"
416416 "Run this command with no options to generate a build.zig template.\n"
417417 "\n"
418418 "Advanced Options:\n"
419 " --build-file $file Override path to build.zig\n"
420 " --cache-dir $path Override path to cache directory\n"
419 " --build-file [file] Override path to build.zig\n"
420 " --cache-dir [path] Override path to cache directory\n"
421421 " --verbose-tokenize Enable compiler debug output for tokenization\n"
422422 " --verbose-ast Enable compiler debug output for parsing into an AST\n"
423423 " --verbose-link Enable compiler debug output for linking\n"
......@@ -853,20 +853,22 @@ int main(int argc, char **argv) {
853853
854854 ZigTarget *non_null_target = target ? target : &native;
855855
856 Buf *test_exe_name = buf_sprintf("." OS_SEP "test%s", target_exe_file_ext(non_null_target));
856 Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target));
857 Buf *test_exe_path = buf_alloc();
858 os_path_join(full_cache_dir, test_exe_name, test_exe_path);
857859
858860 for (size_t i = 0; i < test_exec_args.length; i += 1) {
859861 if (test_exec_args.items[i] == nullptr) {
860 test_exec_args.items[i] = buf_ptr(test_exe_name);
862 test_exec_args.items[i] = buf_ptr(test_exe_path);
861863 }
862864 }
863865
864866 codegen_build(g);
865 codegen_link(g, buf_ptr(test_exe_name));
867 codegen_link(g, buf_ptr(test_exe_path));
866868
867869 if (!target_can_exec(&native, target)) {
868870 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
869 buf_ptr(test_exe_name));
871 buf_ptr(test_exe_path));
870872 return 0;
871873 }
872874
......@@ -879,12 +881,12 @@ int main(int argc, char **argv) {
879881 os_spawn_process(test_exec_args.items[0], rest_args, &term);
880882 } else {
881883 ZigList<const char *> no_args = {0};
882 os_spawn_process(buf_ptr(test_exe_name), no_args, &term);
884 os_spawn_process(buf_ptr(test_exe_path), no_args, &term);
883885 }
884886
885887 if (term.how != TerminationIdClean || term.code != 0) {
886888 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
887 fprintf(stderr, "%s\n", buf_ptr(test_exe_name));
889 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));
888890 } else if (timing_info) {
889891 codegen_print_timing_report(g, stdout);
890892 }
std/build.zig+1-1
......@@ -1706,7 +1706,7 @@ pub const CommandStep = struct {
17061706 fn make(step: &Step) -> %void {
17071707 const self = @fieldParentPtr(CommandStep, "step", step);
17081708
1709 const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else null;
1709 const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root;
17101710 return self.builder.spawnChildEnvMap(cwd, self.env_map, self.argv);
17111711 }
17121712};
std/debug.zig+50-35
......@@ -17,6 +17,7 @@ error UnsupportedDebugInfo;
1717/// Does not append a newline.
1818/// TODO atomic/multithread support
1919var stderr_file: io.File = undefined;
20var stderr_file_out_stream: io.FileOutStream = undefined;
2021var stderr_stream: ?&io.OutStream = null;
2122pub fn warn(comptime fmt: []const u8, args: ...) {
2223 const stderr = getStderrStream() %% return;
......@@ -27,7 +28,8 @@ fn getStderrStream() -> %&io.OutStream {
2728 return st;
2829 } else {
2930 stderr_file = %return io.getStdErr();
30 const st = &stderr_file.out_stream;
31 stderr_file_out_stream = io.FileOutStream.init(&stderr_file);
32 const st = &stderr_file_out_stream.stream;
3133 stderr_stream = st;
3234 return st;
3335 };
......@@ -201,7 +203,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_
201203 var column: usize = 1;
202204 var abs_index: usize = 0;
203205 while (true) {
204 const amt_read = %return f.in_stream.read(buf[0..]);
206 const amt_read = %return f.read(buf[0..]);
205207 const slice = buf[0..amt_read];
206208
207209 for (slice) |byte| {
......@@ -239,7 +241,9 @@ const ElfStackTrace = struct {
239241 }
240242
241243 pub fn readString(self: &ElfStackTrace) -> %[]u8 {
242 return readStringRaw(self.allocator(), &self.self_exe_file.in_stream);
244 var in_file_stream = io.FileInStream.init(&self.self_exe_file);
245 const in_stream = &in_file_stream.stream;
246 return readStringRaw(self.allocator(), in_stream);
243247 }
244248};
245249
......@@ -567,7 +571,9 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u
567571}
568572
569573fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable {
570 const in_stream = &st.self_exe_file.in_stream;
574 const in_file = &st.self_exe_file;
575 var in_file_stream = io.FileInStream.init(in_file);
576 const in_stream = &in_file_stream.stream;
571577 var result = AbbrevTable.init(st.allocator());
572578 while (true) {
573579 const abbrev_code = %return readULeb128(in_stream);
......@@ -620,7 +626,9 @@ fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?&
620626
621627fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -> %Die {
622628 const in_file = &st.self_exe_file;
623 const abbrev_code = %return readULeb128(&in_file.in_stream);
629 var in_file_stream = io.FileInStream.init(in_file);
630 const in_stream = &in_file_stream.stream;
631 const abbrev_code = %return readULeb128(in_stream);
624632 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo;
625633
626634 var result = Die {
......@@ -632,7 +640,7 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -
632640 for (table_entry.attrs.toSliceConst()) |attr, i| {
633641 result.attrs.items[i] = Die.Attr {
634642 .id = attr.attr_id,
635 .value = %return parseFormValue(st.allocator(), &st.self_exe_file.in_stream, attr.form_id, is_64),
643 .value = %return parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),
636644 };
637645 }
638646 return result;
......@@ -646,11 +654,14 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
646654 var this_offset = st.debug_line.offset;
647655 var this_index: usize = 0;
648656
657 var in_file_stream = io.FileInStream.init(in_file);
658 const in_stream = &in_file_stream.stream;
659
649660 while (this_offset < debug_line_end) : (this_index += 1) {
650661 %return in_file.seekTo(this_offset);
651662
652663 var is_64: bool = undefined;
653 const unit_length = %return readInitialLength(&in_file.in_stream, &is_64);
664 const unit_length = %return readInitialLength(in_stream, &is_64);
654665 if (unit_length == 0)
655666 return error.MissingDebugInfo;
656667 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
......@@ -660,28 +671,28 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
660671 continue;
661672 }
662673
663 const version = %return in_file.in_stream.readInt(st.elf.is_big_endian, u16);
674 const version = %return in_stream.readInt(st.elf.is_big_endian, u16);
664675 if (version != 2) return error.InvalidDebugInfo;
665676
666 const prologue_length = %return in_file.in_stream.readInt(st.elf.is_big_endian, u32);
677 const prologue_length = %return in_stream.readInt(st.elf.is_big_endian, u32);
667678 const prog_start_offset = (%return in_file.getPos()) + prologue_length;
668679
669 const minimum_instruction_length = %return in_file.in_stream.readByte();
680 const minimum_instruction_length = %return in_stream.readByte();
670681 if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
671682
672 const default_is_stmt = (%return in_file.in_stream.readByte()) != 0;
673 const line_base = %return in_file.in_stream.readByteSigned();
683 const default_is_stmt = (%return in_stream.readByte()) != 0;
684 const line_base = %return in_stream.readByteSigned();
674685
675 const line_range = %return in_file.in_stream.readByte();
686 const line_range = %return in_stream.readByte();
676687 if (line_range == 0)
677688 return error.InvalidDebugInfo;
678689
679 const opcode_base = %return in_file.in_stream.readByte();
690 const opcode_base = %return in_stream.readByte();
680691
681692 const standard_opcode_lengths = %return st.allocator().alloc(u8, opcode_base - 1);
682693
683694 {var i: usize = 0; while (i < opcode_base - 1) : (i += 1) {
684 standard_opcode_lengths[i] = %return in_file.in_stream.readByte();
695 standard_opcode_lengths[i] = %return in_stream.readByte();
685696 }}
686697
687698 var include_directories = ArrayList([]u8).init(st.allocator());
......@@ -701,9 +712,9 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
701712 const file_name = %return st.readString();
702713 if (file_name.len == 0)
703714 break;
704 const dir_index = %return readULeb128(&in_file.in_stream);
705 const mtime = %return readULeb128(&in_file.in_stream);
706 const len_bytes = %return readULeb128(&in_file.in_stream);
715 const dir_index = %return readULeb128(in_stream);
716 const mtime = %return readULeb128(in_stream);
717 const len_bytes = %return readULeb128(in_stream);
707718 %return file_entries.append(FileEntry {
708719 .file_name = file_name,
709720 .dir_index = dir_index,
......@@ -715,14 +726,14 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
715726 %return in_file.seekTo(prog_start_offset);
716727
717728 while (true) {
718 const opcode = %return in_file.in_stream.readByte();
729 const opcode = %return in_stream.readByte();
719730
720731 var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash
721732 if (opcode == DW.LNS_extended_op) {
722 const op_size = %return readULeb128(&in_file.in_stream);
733 const op_size = %return readULeb128(in_stream);
723734 if (op_size < 1)
724735 return error.InvalidDebugInfo;
725 sub_op = %return in_file.in_stream.readByte();
736 sub_op = %return in_stream.readByte();
726737 switch (sub_op) {
727738 DW.LNE_end_sequence => {
728739 prog.end_sequence = true;
......@@ -730,14 +741,14 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
730741 return error.MissingDebugInfo;
731742 },
732743 DW.LNE_set_address => {
733 const addr = %return in_file.in_stream.readInt(st.elf.is_big_endian, usize);
744 const addr = %return in_stream.readInt(st.elf.is_big_endian, usize);
734745 prog.address = addr;
735746 },
736747 DW.LNE_define_file => {
737748 const file_name = %return st.readString();
738 const dir_index = %return readULeb128(&in_file.in_stream);
739 const mtime = %return readULeb128(&in_file.in_stream);
740 const len_bytes = %return readULeb128(&in_file.in_stream);
749 const dir_index = %return readULeb128(in_stream);
750 const mtime = %return readULeb128(in_stream);
751 const len_bytes = %return readULeb128(in_stream);
741752 %return file_entries.append(FileEntry {
742753 .file_name = file_name,
743754 .dir_index = dir_index,
......@@ -766,19 +777,19 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
766777 prog.basic_block = false;
767778 },
768779 DW.LNS_advance_pc => {
769 const arg = %return readULeb128(&in_file.in_stream);
780 const arg = %return readULeb128(in_stream);
770781 prog.address += arg * minimum_instruction_length;
771782 },
772783 DW.LNS_advance_line => {
773 const arg = %return readILeb128(&in_file.in_stream);
784 const arg = %return readILeb128(in_stream);
774785 prog.line += arg;
775786 },
776787 DW.LNS_set_file => {
777 const arg = %return readULeb128(&in_file.in_stream);
788 const arg = %return readULeb128(in_stream);
778789 prog.file = arg;
779790 },
780791 DW.LNS_set_column => {
781 const arg = %return readULeb128(&in_file.in_stream);
792 const arg = %return readULeb128(in_stream);
782793 prog.column = arg;
783794 },
784795 DW.LNS_negate_stmt => {
......@@ -792,7 +803,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
792803 prog.address += inc_addr;
793804 },
794805 DW.LNS_fixed_advance_pc => {
795 const arg = %return in_file.in_stream.readInt(st.elf.is_big_endian, u16);
806 const arg = %return in_stream.readInt(st.elf.is_big_endian, u16);
796807 prog.address += arg;
797808 },
798809 DW.LNS_set_prologue_end => {
......@@ -817,25 +828,29 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
817828 const debug_info_end = st.debug_info.offset + st.debug_info.size;
818829 var this_unit_offset = st.debug_info.offset;
819830 var cu_index: usize = 0;
831
832 var in_file_stream = io.FileInStream.init(&st.self_exe_file);
833 const in_stream = &in_file_stream.stream;
834
820835 while (this_unit_offset < debug_info_end) {
821836 %return st.self_exe_file.seekTo(this_unit_offset);
822837
823838 var is_64: bool = undefined;
824 const unit_length = %return readInitialLength(&st.self_exe_file.in_stream, &is_64);
839 const unit_length = %return readInitialLength(in_stream, &is_64);
825840 if (unit_length == 0)
826841 return;
827842 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
828843
829 const version = %return st.self_exe_file.in_stream.readInt(st.elf.is_big_endian, u16);
844 const version = %return in_stream.readInt(st.elf.is_big_endian, u16);
830845 if (version < 2 or version > 5) return error.InvalidDebugInfo;
831846
832847 const debug_abbrev_offset = if (is_64) {
833 %return st.self_exe_file.in_stream.readInt(st.elf.is_big_endian, u64)
848 %return in_stream.readInt(st.elf.is_big_endian, u64)
834849 } else {
835 %return st.self_exe_file.in_stream.readInt(st.elf.is_big_endian, u32)
850 %return in_stream.readInt(st.elf.is_big_endian, u32)
836851 };
837852
838 const address_size = %return st.self_exe_file.in_stream.readByte();
853 const address_size = %return in_stream.readByte();
839854 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
840855
841856 const compile_unit_pos = %return st.self_exe_file.getPos();
std/elf.zig+47-41
......@@ -92,29 +92,32 @@ pub const Elf = struct {
9292 elf.in_file = file;
9393 elf.auto_close_stream = false;
9494
95 var file_stream = io.FileInStream.init(elf.in_file);
96 const in = &file_stream.stream;
97
9598 var magic: [4]u8 = undefined;
96 %return elf.in_file.in_stream.readNoEof(magic[0..]);
99 %return in.readNoEof(magic[0..]);
97100 if (!mem.eql(u8, magic, "\x7fELF")) return error.InvalidFormat;
98101
99 elf.is_64 = switch (%return elf.in_file.in_stream.readByte()) {
102 elf.is_64 = switch (%return in.readByte()) {
100103 1 => false,
101104 2 => true,
102105 else => return error.InvalidFormat,
103106 };
104107
105 elf.is_big_endian = switch (%return elf.in_file.in_stream.readByte()) {
108 elf.is_big_endian = switch (%return in.readByte()) {
106109 1 => false,
107110 2 => true,
108111 else => return error.InvalidFormat,
109112 };
110113
111 const version_byte = %return elf.in_file.in_stream.readByte();
114 const version_byte = %return in.readByte();
112115 if (version_byte != 1) return error.InvalidFormat;
113116
114117 // skip over padding
115118 %return elf.in_file.seekForward(9);
116119
117 elf.file_type = switch (%return elf.in_file.in_stream.readInt(elf.is_big_endian, u16)) {
120 elf.file_type = switch (%return in.readInt(elf.is_big_endian, u16)) {
118121 1 => FileType.Relocatable,
119122 2 => FileType.Executable,
120123 3 => FileType.Shared,
......@@ -122,7 +125,7 @@ pub const Elf = struct {
122125 else => return error.InvalidFormat,
123126 };
124127
125 elf.arch = switch (%return elf.in_file.in_stream.readInt(elf.is_big_endian, u16)) {
128 elf.arch = switch (%return in.readInt(elf.is_big_endian, u16)) {
126129 0x02 => Arch.Sparc,
127130 0x03 => Arch.x86,
128131 0x08 => Arch.Mips,
......@@ -135,34 +138,34 @@ pub const Elf = struct {
135138 else => return error.InvalidFormat,
136139 };
137140
138 const elf_version = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
141 const elf_version = %return in.readInt(elf.is_big_endian, u32);
139142 if (elf_version != 1) return error.InvalidFormat;
140143
141144 if (elf.is_64) {
142 elf.entry_addr = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
143 elf.program_header_offset = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
144 elf.section_header_offset = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
145 elf.entry_addr = %return in.readInt(elf.is_big_endian, u64);
146 elf.program_header_offset = %return in.readInt(elf.is_big_endian, u64);
147 elf.section_header_offset = %return in.readInt(elf.is_big_endian, u64);
145148 } else {
146 elf.entry_addr = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
147 elf.program_header_offset = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
148 elf.section_header_offset = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
149 elf.entry_addr = u64(%return in.readInt(elf.is_big_endian, u32));
150 elf.program_header_offset = u64(%return in.readInt(elf.is_big_endian, u32));
151 elf.section_header_offset = u64(%return in.readInt(elf.is_big_endian, u32));
149152 }
150153
151154 // skip over flags
152155 %return elf.in_file.seekForward(4);
153156
154 const header_size = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u16);
157 const header_size = %return in.readInt(elf.is_big_endian, u16);
155158 if ((elf.is_64 and header_size != 64) or
156159 (!elf.is_64 and header_size != 52))
157160 {
158161 return error.InvalidFormat;
159162 }
160163
161 const ph_entry_size = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u16);
162 const ph_entry_count = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u16);
163 const sh_entry_size = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u16);
164 const sh_entry_count = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u16);
165 elf.string_section_index = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u16));
164 const ph_entry_size = %return in.readInt(elf.is_big_endian, u16);
165 const ph_entry_count = %return in.readInt(elf.is_big_endian, u16);
166 const sh_entry_size = %return in.readInt(elf.is_big_endian, u16);
167 const sh_entry_count = %return in.readInt(elf.is_big_endian, u16);
168 elf.string_section_index = u64(%return in.readInt(elf.is_big_endian, u16));
166169
167170 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
168171
......@@ -185,32 +188,32 @@ pub const Elf = struct {
185188 if (sh_entry_size != 64) return error.InvalidFormat;
186189
187190 for (elf.section_headers) |*section| {
188 section.name = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
189 section.sh_type = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
190 section.flags = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
191 section.addr = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
192 section.offset = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
193 section.size = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
194 section.link = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
195 section.info = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
196 section.addr_align = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
197 section.ent_size = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u64);
191 section.name = %return in.readInt(elf.is_big_endian, u32);
192 section.sh_type = %return in.readInt(elf.is_big_endian, u32);
193 section.flags = %return in.readInt(elf.is_big_endian, u64);
194 section.addr = %return in.readInt(elf.is_big_endian, u64);
195 section.offset = %return in.readInt(elf.is_big_endian, u64);
196 section.size = %return in.readInt(elf.is_big_endian, u64);
197 section.link = %return in.readInt(elf.is_big_endian, u32);
198 section.info = %return in.readInt(elf.is_big_endian, u32);
199 section.addr_align = %return in.readInt(elf.is_big_endian, u64);
200 section.ent_size = %return in.readInt(elf.is_big_endian, u64);
198201 }
199202 } else {
200203 if (sh_entry_size != 40) return error.InvalidFormat;
201204
202205 for (elf.section_headers) |*section| {
203206 // TODO (multiple occurences) allow implicit cast from %u32 -> %u64 ?
204 section.name = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
205 section.sh_type = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
206 section.flags = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
207 section.addr = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
208 section.offset = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
209 section.size = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
210 section.link = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
211 section.info = %return elf.in_file.in_stream.readInt(elf.is_big_endian, u32);
212 section.addr_align = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
213 section.ent_size = u64(%return elf.in_file.in_stream.readInt(elf.is_big_endian, u32));
207 section.name = %return in.readInt(elf.is_big_endian, u32);
208 section.sh_type = %return in.readInt(elf.is_big_endian, u32);
209 section.flags = u64(%return in.readInt(elf.is_big_endian, u32));
210 section.addr = u64(%return in.readInt(elf.is_big_endian, u32));
211 section.offset = u64(%return in.readInt(elf.is_big_endian, u32));
212 section.size = u64(%return in.readInt(elf.is_big_endian, u32));
213 section.link = %return in.readInt(elf.is_big_endian, u32);
214 section.info = %return in.readInt(elf.is_big_endian, u32);
215 section.addr_align = u64(%return in.readInt(elf.is_big_endian, u32));
216 section.ent_size = u64(%return in.readInt(elf.is_big_endian, u32));
214217 }
215218 }
216219
......@@ -236,6 +239,9 @@ pub const Elf = struct {
236239 }
237240
238241 pub fn findSection(elf: &Elf, name: []const u8) -> %?&SectionHeader {
242 var file_stream = io.FileInStream.init(elf.in_file);
243 const in = &file_stream.stream;
244
239245 for (elf.section_headers) |*section| {
240246 if (section.sh_type == SHT_NULL) continue;
241247
......@@ -243,12 +249,12 @@ pub const Elf = struct {
243249 %return elf.in_file.seekTo(name_offset);
244250
245251 for (name) |expected_c| {
246 const target_c = %return elf.in_file.in_stream.readByte();
252 const target_c = %return in.readByte();
247253 if (target_c == 0 or expected_c != target_c) goto next_section;
248254 }
249255
250256 {
251 const null_byte = %return elf.in_file.in_stream.readByte();
257 const null_byte = %return in.readByte();
252258 if (null_byte == 0) return section;
253259 }
254260
std/io.zig+179-27
......@@ -76,16 +76,50 @@ pub fn getStdIn() -> %File {
7676 return File.openHandle(handle);
7777}
7878
79/// Implementation of InStream trait for File
80pub const FileInStream = struct {
81 file: &File,
82 stream: InStream,
83
84 pub fn init(file: &File) -> FileInStream {
85 return FileInStream {
86 .file = file,
87 .stream = InStream {
88 .readFn = readFn,
89 },
90 };
91 }
92
93 fn readFn(in_stream: &InStream, buffer: []u8) -> %usize {
94 const self = @fieldParentPtr(FileInStream, "stream", in_stream);
95 return self.file.read(buffer);
96 }
97};
98
99/// Implementation of OutStream trait for File
100pub const FileOutStream = struct {
101 file: &File,
102 stream: OutStream,
103
104 pub fn init(file: &File) -> FileOutStream {
105 return FileOutStream {
106 .file = file,
107 .stream = OutStream {
108 .writeFn = writeFn,
109 },
110 };
111 }
112
113 fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void {
114 const self = @fieldParentPtr(FileOutStream, "stream", out_stream);
115 return self.file.write(bytes);
116 }
117};
118
79119pub const File = struct {
80120 /// The OS-specific file descriptor or file handle.
81121 handle: os.FileHandle,
82122
83 /// A file has the `InStream` trait
84 in_stream: InStream,
85
86 /// A file has the `OutStream` trait
87 out_stream: OutStream,
88
89123 /// `path` may need to be copied in memory to add a null terminating byte. In this case
90124 /// a fixed size buffer of size std.os.max_noalloc_path_len is an attempted solution. If the fixed
91125 /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned.
......@@ -135,12 +169,6 @@ pub const File = struct {
135169 pub fn openHandle(handle: os.FileHandle) -> File {
136170 return File {
137171 .handle = handle,
138 .out_stream = OutStream {
139 .writeFn = writeFn,
140 },
141 .in_stream = InStream {
142 .readFn = readFn,
143 },
144172 };
145173 }
146174
......@@ -232,8 +260,7 @@ pub const File = struct {
232260 return usize(stat.size);
233261 }
234262
235 fn readFn(in_stream: &InStream, buffer: []u8) -> %usize {
236 const self = @fieldParentPtr(File, "in_stream", in_stream);
263 pub fn read(self: &File, buffer: []u8) -> %usize {
237264 if (is_posix) {
238265 var index: usize = 0;
239266 while (index < buffer.len) {
......@@ -275,8 +302,7 @@ pub const File = struct {
275302 }
276303 }
277304
278 fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void {
279 const self = @fieldParentPtr(File, "out_stream", out_stream);
305 fn write(self: &File, bytes: []const u8) -> %void {
280306 if (is_posix) {
281307 %return os.posixWrite(self.handle, bytes);
282308 } else if (is_windows) {
......@@ -285,19 +311,8 @@ pub const File = struct {
285311 @compileError("Unsupported OS");
286312 }
287313 }
288
289314};
290315
291/// `path` may need to be copied in memory to add a null terminating byte. In this case
292/// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed
293/// size buffer is too small, and the provided allocator is null, `error.NameTooLong` is returned.
294/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
295pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) -> %void {
296 var file = %return File.openWrite(path, allocator);
297 defer file.close();
298 %return file.out_stream.write(data);
299}
300
301316error StreamTooLong;
302317error EndOfStream;
303318
......@@ -446,3 +461,140 @@ pub const OutStream = struct {
446461 return self.writeFn(self, slice);
447462 }
448463};
464
465/// `path` may need to be copied in memory to add a null terminating byte. In this case
466/// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed
467/// size buffer is too small, and the provided allocator is null, `error.NameTooLong` is returned.
468/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
469pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) -> %void {
470 var file = %return File.openWrite(path, allocator);
471 defer file.close();
472 %return file.write(data);
473}
474
475pub const BufferedInStream = BufferedInStreamCustom(os.page_size);
476
477pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type {
478 return struct {
479 const Self = this;
480
481 pub stream: InStream,
482
483 unbuffered_in_stream: &InStream,
484
485 buffer: [buffer_size]u8,
486 start_index: usize,
487 end_index: usize,
488
489 pub fn init(unbuffered_in_stream: &InStream) -> Self {
490 return Self {
491 .unbuffered_in_stream = unbuffered_in_stream,
492 .buffer = undefined,
493
494 // Initialize these two fields to buffer_size so that
495 // in `readFn` we treat the state as being able to read
496 // more from the unbuffered stream. If we set them to 0
497 // and 0, the code would think we already hit EOF.
498 .start_index = buffer_size,
499 .end_index = buffer_size,
500
501 .stream = InStream {
502 .readFn = readFn,
503 },
504 };
505 }
506
507 fn readFn(in_stream: &InStream, dest: []u8) -> %usize {
508 const self = @fieldParentPtr(Self, "stream", in_stream);
509
510 var dest_index: usize = 0;
511 while (true) {
512 const dest_space = dest.len - dest_index;
513 if (dest_space == 0) {
514 return dest_index;
515 }
516 const amt_buffered = self.end_index - self.start_index;
517 if (amt_buffered == 0) {
518 assert(self.end_index <= buffer_size);
519 if (self.end_index == buffer_size) {
520 // we can read more data from the unbuffered stream
521 if (dest_space < buffer_size) {
522 self.start_index = 0;
523 self.end_index = %return self.unbuffered_in_stream.read(self.buffer[0..]);
524 } else {
525 // asking for so much data that buffering is actually less efficient.
526 // forward the request directly to the unbuffered stream
527 const amt_read = %return self.unbuffered_in_stream.read(dest[dest_index..]);
528 return dest_index + amt_read;
529 }
530 } else {
531 // reading from the unbuffered stream returned less than we asked for
532 // so we cannot read any more data.
533 return dest_index;
534 }
535 }
536 const copy_amount = math.min(dest_space, amt_buffered);
537 const copy_end_index = self.start_index + copy_amount;
538 mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);
539 self.start_index = copy_end_index;
540 dest_index += copy_amount;
541 }
542 }
543 };
544}
545
546pub const BufferedOutStream = BufferedOutStreamCustom(os.page_size);
547
548pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type {
549 return struct {
550 const Self = this;
551
552 pub stream: OutStream,
553
554 unbuffered_out_stream: &OutStream,
555
556 buffer: [buffer_size]u8,
557 index: usize,
558
559 pub fn init(unbuffered_out_stream: &OutStream) -> Self {
560 return Self {
561 .unbuffered_out_stream = unbuffered_out_stream,
562 .buffer = undefined,
563 .index = 0,
564 .stream = OutStream {
565 .writeFn = writeFn,
566 },
567 };
568 }
569
570 pub fn flush(self: &Self) -> %void {
571 if (self.index == 0)
572 return;
573
574 %return self.unbuffered_out_stream.write(self.buffer[0..self.index]);
575 self.index = 0;
576 }
577
578 fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void {
579 const self = @fieldParentPtr(Self, "stream", out_stream);
580
581 if (bytes.len >= self.buffer.len) {
582 %return self.flush();
583 return self.unbuffered_out_stream.write(bytes);
584 }
585 var src_index: usize = 0;
586
587 while (src_index < bytes.len) {
588 const dest_space_left = self.buffer.len - self.index;
589 const copy_amt = math.min(dest_space_left, bytes.len - src_index);
590 mem.copy(u8, self.buffer[self.index..], bytes[src_index..src_index + copy_amt]);
591 self.index += copy_amt;
592 assert(self.index <= self.buffer.len);
593 if (self.index == self.buffer.len) {
594 %return self.flush();
595 }
596 src_index += copy_amt;
597 }
598 }
599 };
600}
std/os/index.zig+2-2
......@@ -730,8 +730,8 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [
730730
731731 var buf: [page_size]u8 = undefined;
732732 while (true) {
733 const amt = %return in_file.in_stream.read(buf[0..]);
734 %return out_file.out_stream.write(buf[0..amt]);
733 const amt = %return in_file.read(buf[0..]);
734 %return out_file.write(buf[0..amt]);
735735 if (amt != buf.len)
736736 return rename(allocator, tmp_path, dest_path);
737737 }
std/special/build_runner.zig+19-6
......@@ -44,9 +44,22 @@ pub fn main() -> %void {
4444 var prefix: ?[]const u8 = null;
4545
4646 var stderr_file = io.getStdErr();
47 var stderr_stream: %&io.OutStream = if (stderr_file) |*f| &f.out_stream else |err| err;
47 var stderr_file_stream: io.FileOutStream = undefined;
48 var stderr_stream: %&io.OutStream = if (stderr_file) |*f| {
49 stderr_file_stream = io.FileOutStream.init(f);
50 &stderr_file_stream.stream
51 } else |err| {
52 err
53 };
54
4855 var stdout_file = io.getStdOut();
49 var stdout_stream: %&io.OutStream = if (stdout_file) |*f| &f.out_stream else |err| err;
56 var stdout_file_stream: io.FileOutStream = undefined;
57 var stdout_stream: %&io.OutStream = if (stdout_file) |*f| {
58 stdout_file_stream = io.FileOutStream.init(f);
59 &stdout_file_stream.stream
60 } else |err| {
61 err
62 };
5063
5164 while (arg_it.next(allocator)) |err_or_arg| {
5265 const arg = %return unwrapArg(err_or_arg);
......@@ -135,7 +148,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
135148 \\General Options:
136149 \\ --help Print this help and exit
137150 \\ --verbose Print commands before executing them
138 \\ --prefix $path Override default install prefix
151 \\ --prefix [path] Override default install prefix
139152 \\
140153 \\Project-Specific Options:
141154 \\
......@@ -146,7 +159,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
146159 } else {
147160 for (builder.available_options_list.toSliceConst()) |option| {
148161 const name = %return fmt.allocPrint(allocator,
149 " -D{}=${}", option.name, Builder.typeIdName(option.type_id));
162 " -D{}=[{}]", option.name, Builder.typeIdName(option.type_id));
150163 defer allocator.free(name);
151164 %return out_stream.print("{s24} {}\n", name, option.description);
152165 }
......@@ -155,8 +168,8 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
155168 %return out_stream.write(
156169 \\
157170 \\Advanced Options:
158 \\ --build-file $file Override path to build.zig
159 \\ --cache-dir $path Override path to zig cache directory
171 \\ --build-file [file] Override path to build.zig
172 \\ --cache-dir [path] Override path to zig cache directory
160173 \\ --verbose-tokenize Enable compiler debug output for tokenization
161174 \\ --verbose-ast Enable compiler debug output for parsing into an AST
162175 \\ --verbose-link Enable compiler debug output for linking
test/compare_output.zig+13-13
......@@ -17,7 +17,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
1717 \\
1818 \\pub fn main() -> %void {
1919 \\ privateFunction();
20 \\ const stdout = &(%%getStdOut()).out_stream;
20 \\ const stdout = &(FileOutStream.init(&%%getStdOut()).stream);
2121 \\ %%stdout.print("OK 2\n");
2222 \\}
2323 \\
......@@ -32,7 +32,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
3232 \\// purposefully conflicting function with main.zig
3333 \\// but it's private so it should be OK
3434 \\fn privateFunction() {
35 \\ const stdout = &(%%getStdOut()).out_stream;
35 \\ const stdout = &(FileOutStream.init(&%%getStdOut()).stream);
3636 \\ %%stdout.print("OK 1\n");
3737 \\}
3838 \\
......@@ -58,7 +58,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
5858 tc.addSourceFile("foo.zig",
5959 \\use @import("std").io;
6060 \\pub fn foo_function() {
61 \\ const stdout = &(%%getStdOut()).out_stream;
61 \\ const stdout = &(FileOutStream.init(&%%getStdOut()).stream);
6262 \\ %%stdout.print("OK\n");
6363 \\}
6464 );
......@@ -69,7 +69,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
6969 \\
7070 \\pub fn bar_function() {
7171 \\ if (foo_function()) {
72 \\ const stdout = &(%%getStdOut()).out_stream;
72 \\ const stdout = &(FileOutStream.init(&%%getStdOut()).stream);
7373 \\ %%stdout.print("OK\n");
7474 \\ }
7575 \\}
......@@ -101,7 +101,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
101101 \\pub const a_text = "OK\n";
102102 \\
103103 \\pub fn ok() {
104 \\ const stdout = &(%%io.getStdOut()).out_stream;
104 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
105105 \\ %%stdout.print(b_text);
106106 \\}
107107 );
......@@ -119,7 +119,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
119119 \\const io = @import("std").io;
120120 \\
121121 \\pub fn main() -> %void {
122 \\ const stdout = &(%%io.getStdOut()).out_stream;
122 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
123123 \\ %%stdout.print("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a'));
124124 \\}
125125 , "Hello, world!\n0012 012 a\n");
......@@ -272,7 +272,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
272272 \\ var x_local : i32 = print_ok(x);
273273 \\}
274274 \\fn print_ok(val: @typeOf(x)) -> @typeOf(foo) {
275 \\ const stdout = &(%%io.getStdOut()).out_stream;
275 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
276276 \\ %%stdout.print("OK\n");
277277 \\ return 0;
278278 \\}
......@@ -354,7 +354,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
354354 \\pub fn main() -> %void {
355355 \\ const bar = Bar {.field2 = 13,};
356356 \\ const foo = Foo {.field1 = bar,};
357 \\ const stdout = &(%%io.getStdOut()).out_stream;
357 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
358358 \\ if (!foo.method()) {
359359 \\ %%stdout.print("BAD\n");
360360 \\ }
......@@ -368,7 +368,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
368368 cases.add("defer with only fallthrough",
369369 \\const io = @import("std").io;
370370 \\pub fn main() -> %void {
371 \\ const stdout = &(%%io.getStdOut()).out_stream;
371 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
372372 \\ %%stdout.print("before\n");
373373 \\ defer %%stdout.print("defer1\n");
374374 \\ defer %%stdout.print("defer2\n");
......@@ -381,7 +381,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
381381 \\const io = @import("std").io;
382382 \\const os = @import("std").os;
383383 \\pub fn main() -> %void {
384 \\ const stdout = &(%%io.getStdOut()).out_stream;
384 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
385385 \\ %%stdout.print("before\n");
386386 \\ defer %%stdout.print("defer1\n");
387387 \\ defer %%stdout.print("defer2\n");
......@@ -398,7 +398,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
398398 \\ do_test() %% return;
399399 \\}
400400 \\fn do_test() -> %void {
401 \\ const stdout = &(%%io.getStdOut()).out_stream;
401 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
402402 \\ %%stdout.print("before\n");
403403 \\ defer %%stdout.print("defer1\n");
404404 \\ %defer %%stdout.print("deferErr\n");
......@@ -418,7 +418,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
418418 \\ do_test() %% return;
419419 \\}
420420 \\fn do_test() -> %void {
421 \\ const stdout = &(%%io.getStdOut()).out_stream;
421 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
422422 \\ %%stdout.print("before\n");
423423 \\ defer %%stdout.print("defer1\n");
424424 \\ %defer %%stdout.print("deferErr\n");
......@@ -435,7 +435,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
435435 \\const io = @import("std").io;
436436 \\
437437 \\pub fn main() -> %void {
438 \\ const stdout = &(%%io.getStdOut()).out_stream;
438 \\ const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
439439 \\ %%stdout.print(foo_txt);
440440 \\}
441441 , "1234\nabcd\n");
test/tests.zig+17-7
......@@ -249,8 +249,11 @@ pub const CompareOutputContext = struct {
249249 var stdout = Buffer.initNull(b.allocator);
250250 var stderr = Buffer.initNull(b.allocator);
251251
252 %%(??child.stdout).in_stream.readAllBuffer(&stdout, max_stdout_size);
253 %%(??child.stderr).in_stream.readAllBuffer(&stderr, max_stdout_size);
252 var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
253 var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
254
255 %%stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size);
256 %%stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size);
254257
255258 const term = child.wait() %% |err| {
256259 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
......@@ -576,8 +579,11 @@ pub const CompileErrorContext = struct {
576579 var stdout_buf = Buffer.initNull(b.allocator);
577580 var stderr_buf = Buffer.initNull(b.allocator);
578581
579 %%(??child.stdout).in_stream.readAllBuffer(&stdout_buf, max_stdout_size);
580 %%(??child.stderr).in_stream.readAllBuffer(&stderr_buf, max_stdout_size);
582 var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
583 var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
584
585 %%stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size);
586 %%stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size);
581587
582588 const term = child.wait() %% |err| {
583589 debug.panic("Unable to spawn {}: {}\n", zig_args.items[0], @errorName(err));
......@@ -718,7 +724,8 @@ pub const BuildExamplesContext = struct {
718724 }
719725
720726 var zig_args = ArrayList([]const u8).init(b.allocator);
721 %%zig_args.append(b.zig_exe);
727 const rel_zig_exe = %%os.path.relative(b.allocator, b.build_root, b.zig_exe);
728 %%zig_args.append(rel_zig_exe);
722729 %%zig_args.append("build");
723730
724731 %%zig_args.append("--build-file");
......@@ -844,8 +851,11 @@ pub const ParseCContext = struct {
844851 var stdout_buf = Buffer.initNull(b.allocator);
845852 var stderr_buf = Buffer.initNull(b.allocator);
846853
847 %%(??child.stdout).in_stream.readAllBuffer(&stdout_buf, max_stdout_size);
848 %%(??child.stderr).in_stream.readAllBuffer(&stderr_buf, max_stdout_size);
854 var stdout_file_in_stream = io.FileInStream.init(&??child.stdout);
855 var stderr_file_in_stream = io.FileInStream.init(&??child.stderr);
856
857 %%stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size);
858 %%stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size);
849859
850860 const term = child.wait() %% |err| {
851861 debug.panic("Unable to spawn {}: {}\n", zig_args.toSliceConst()[0], @errorName(err));