authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-17 13:11:21-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-17 13:11:21-05:00
log48cd808185f54e935714539d101585a9a0a41673
tree3817592ec8e324e54debddf93d968847294cf8f6
parentb897e98d30b7e471cdabf6b8f0baab44998265cd
parenta4e8e55908eb406f4713c22a6721d6d73f6951a5

Merge remote-tracking branch 'origin/master' into llvm6


18 files changed, 1372 insertions(+), 1513 deletions(-)

CMakeLists.txt+1
......@@ -368,6 +368,7 @@ set(ZIG_STD_FILES
368368 "crypto/md5.zig"
369369 "crypto/sha1.zig"
370370 "crypto/sha2.zig"
371 "crypto/sha3.zig"
371372 "crypto/blake2.zig"
372373 "cstr.zig"
373374 "debug/failing_allocator.zig"
build.zig+2-8
......@@ -15,23 +15,17 @@ pub fn build(b: &Builder) -> %void {
1515
1616 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
1717
18 const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
1819 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 {
1920 docgen_exe.getOutputPath(),
21 rel_zig_exe,
2022 "doc/langref.html.in",
2123 os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable,
2224 });
2325 docgen_cmd.step.dependOn(&docgen_exe.step);
2426
25 var docgen_home_cmd = b.addCommand(null, b.env_map, [][]const u8 {
26 docgen_exe.getOutputPath(),
27 "doc/home.html.in",
28 os.path.join(b.allocator, b.cache_root, "home.html") catch unreachable,
29 });
30 docgen_home_cmd.step.dependOn(&docgen_exe.step);
31
3227 const docs_step = b.step("docs", "Build documentation");
3328 docs_step.dependOn(&docgen_cmd.step);
34 docs_step.dependOn(&docgen_home_cmd.step);
3529
3630 const test_step = b.step("test", "Run all the tests");
3731
doc/docgen.zig+523-20
......@@ -1,10 +1,16 @@
11const std = @import("std");
22const io = std.io;
33const os = std.os;
4const warn = std.debug.warn;
5const mem = std.mem;
6
7const max_doc_file_size = 10 * 1024 * 1024;
8
9const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt();
410
511pub fn main() -> %void {
612 // TODO use a more general purpose allocator here
7 var inc_allocator = try std.heap.IncrementingAllocator.init(5 * 1024 * 1024);
13 var inc_allocator = try std.heap.IncrementingAllocator.init(max_doc_file_size);
814 defer inc_allocator.deinit();
915 const allocator = &inc_allocator.allocator;
1016
......@@ -12,6 +18,9 @@ pub fn main() -> %void {
1218
1319 if (!args_it.skip()) @panic("expected self arg");
1420
21 const zig_exe = try (args_it.next(allocator) ?? @panic("expected zig exe arg"));
22 defer allocator.free(zig_exe);
23
1524 const in_file_name = try (args_it.next(allocator) ?? @panic("expected input arg"));
1625 defer allocator.free(in_file_name);
1726
......@@ -25,39 +34,533 @@ pub fn main() -> %void {
2534 defer out_file.close();
2635
2736 var file_in_stream = io.FileInStream.init(&in_file);
28 var buffered_in_stream = io.BufferedInStream.init(&file_in_stream.stream);
37
38 const input_file_bytes = try file_in_stream.stream.readAllAlloc(allocator, max_doc_file_size);
2939
3040 var file_out_stream = io.FileOutStream.init(&out_file);
3141 var buffered_out_stream = io.BufferedOutStream.init(&file_out_stream.stream);
3242
33 gen(&buffered_in_stream.stream, &buffered_out_stream.stream);
34 try buffered_out_stream.flush();
43 var tokenizer = Tokenizer.init(in_file_name, input_file_bytes);
44 var toc = try genToc(allocator, &tokenizer);
3545
46 try genHtml(allocator, &tokenizer, &toc, &buffered_out_stream.stream, zig_exe);
47 try buffered_out_stream.flush();
3648}
3749
38const State = enum {
39 Start,
40 Derp,
50const Token = struct {
51 id: Id,
52 start: usize,
53 end: usize,
54
55 const Id = enum {
56 Invalid,
57 Content,
58 BracketOpen,
59 TagContent,
60 Separator,
61 BracketClose,
62 Eof,
63 };
4164};
4265
43// TODO look for code segments
66const Tokenizer = struct {
67 buffer: []const u8,
68 index: usize,
69 state: State,
70 source_file_name: []const u8,
4471
45fn gen(in: &io.InStream, out: &io.OutStream) {
46 var state = State.Start;
47 while (true) {
48 const byte = in.readByte() catch |err| {
49 if (err == error.EndOfStream) {
50 return;
51 }
52 std.debug.panic("{}", err);
72 const State = enum {
73 Start,
74 LBracket,
75 Hash,
76 TagName,
77 Eof,
78 };
79
80 fn init(source_file_name: []const u8, buffer: []const u8) -> Tokenizer {
81 return Tokenizer {
82 .buffer = buffer,
83 .index = 0,
84 .state = State.Start,
85 .source_file_name = source_file_name,
86 };
87 }
88
89 fn next(self: &Tokenizer) -> Token {
90 var result = Token {
91 .id = Token.Id.Eof,
92 .start = self.index,
93 .end = undefined,
5394 };
54 switch (state) {
55 State.Start => switch (byte) {
95 while (self.index < self.buffer.len) : (self.index += 1) {
96 const c = self.buffer[self.index];
97 switch (self.state) {
98 State.Start => switch (c) {
99 '{' => {
100 self.state = State.LBracket;
101 },
102 else => {
103 result.id = Token.Id.Content;
104 },
105 },
106 State.LBracket => switch (c) {
107 '#' => {
108 if (result.id != Token.Id.Eof) {
109 self.index -= 1;
110 self.state = State.Start;
111 break;
112 } else {
113 result.id = Token.Id.BracketOpen;
114 self.index += 1;
115 self.state = State.TagName;
116 break;
117 }
118 },
119 else => {
120 result.id = Token.Id.Content;
121 self.state = State.Start;
122 },
123 },
124 State.TagName => switch (c) {
125 '|' => {
126 if (result.id != Token.Id.Eof) {
127 break;
128 } else {
129 result.id = Token.Id.Separator;
130 self.index += 1;
131 break;
132 }
133 },
134 '#' => {
135 self.state = State.Hash;
136 },
137 else => {
138 result.id = Token.Id.TagContent;
139 },
140 },
141 State.Hash => switch (c) {
142 '}' => {
143 if (result.id != Token.Id.Eof) {
144 self.index -= 1;
145 self.state = State.TagName;
146 break;
147 } else {
148 result.id = Token.Id.BracketClose;
149 self.index += 1;
150 self.state = State.Start;
151 break;
152 }
153 },
154 else => {
155 result.id = Token.Id.TagContent;
156 self.state = State.TagName;
157 },
158 },
159 State.Eof => unreachable,
160 }
161 } else {
162 switch (self.state) {
163 State.Start, State.LBracket, State.Eof => {},
56164 else => {
57 out.writeByte(byte) catch unreachable;
165 result.id = Token.Id.Invalid;
58166 },
167 }
168 self.state = State.Eof;
169 }
170 result.end = self.index;
171 return result;
172 }
173
174 const Location = struct {
175 line: usize,
176 column: usize,
177 line_start: usize,
178 line_end: usize,
179 };
180
181 fn getTokenLocation(self: &Tokenizer, token: &const Token) -> Location {
182 var loc = Location {
183 .line = 0,
184 .column = 0,
185 .line_start = 0,
186 .line_end = 0,
187 };
188 for (self.buffer) |c, i| {
189 if (i == token.start) {
190 loc.line_end = i;
191 while (loc.line_end < self.buffer.len and self.buffer[loc.line_end] != '\n') : (loc.line_end += 1) {}
192 return loc;
193 }
194 if (c == '\n') {
195 loc.line += 1;
196 loc.column = 0;
197 loc.line_start = i + 1;
198 } else {
199 loc.column += 1;
200 }
201 }
202 return loc;
203 }
204};
205
206error ParseError;
207
208fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const u8, args: ...) -> error {
209 const loc = tokenizer.getTokenLocation(token);
210 warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args);
211 if (loc.line_start <= loc.line_end) {
212 warn("{}\n", tokenizer.buffer[loc.line_start..loc.line_end]);
213 {
214 var i: usize = 0;
215 while (i < loc.column) : (i += 1) {
216 warn(" ");
217 }
218 }
219 {
220 const caret_count = token.end - token.start;
221 var i: usize = 0;
222 while (i < caret_count) : (i += 1) {
223 warn("~");
224 }
225 }
226 warn("\n");
227 }
228 return error.ParseError;
229}
230
231fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) -> %void {
232 if (token.id != id) {
233 return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
234 }
235}
236
237fn eatToken(tokenizer: &Tokenizer, id: Token.Id) -> %Token {
238 const token = tokenizer.next();
239 try assertToken(tokenizer, token, id);
240 return token;
241}
242
243const HeaderOpen = struct {
244 name: []const u8,
245 url: []const u8,
246 n: usize,
247};
248
249const SeeAlsoItem = struct {
250 name: []const u8,
251 token: Token,
252};
253
254const Code = struct {
255 id: Id,
256 name: []const u8,
257 source_token: Token,
258
259 const Id = enum {
260 Test,
261 Exe,
262 Error,
263 };
264};
265
266const Node = union(enum) {
267 Content: []const u8,
268 Nav,
269 HeaderOpen: HeaderOpen,
270 SeeAlso: []const SeeAlsoItem,
271 Code: Code,
272};
273
274const Toc = struct {
275 nodes: []Node,
276 toc: []u8,
277 urls: std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8),
278};
279
280const Action = enum {
281 Open,
282 Close,
283};
284
285fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc {
286 var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);
287 %defer urls.deinit();
288
289 var header_stack_size: usize = 0;
290 var last_action = Action.Open;
291
292 var toc_buf = try std.Buffer.initSize(allocator, 0);
293 defer toc_buf.deinit();
294
295 var toc_buf_adapter = io.BufferOutStream.init(&toc_buf);
296 var toc = &toc_buf_adapter.stream;
297
298 var nodes = std.ArrayList(Node).init(allocator);
299 defer nodes.deinit();
300
301 try toc.writeByte('\n');
302
303 while (true) {
304 const token = tokenizer.next();
305 switch (token.id) {
306 Token.Id.Eof => {
307 if (header_stack_size != 0) {
308 return parseError(tokenizer, token, "unbalanced headers");
309 }
310 try toc.write(" </ul>\n");
311 break;
312 },
313 Token.Id.Content => {
314 try nodes.append(Node {.Content = tokenizer.buffer[token.start..token.end] });
315 },
316 Token.Id.BracketOpen => {
317 const tag_token = try eatToken(tokenizer, Token.Id.TagContent);
318 const tag_name = tokenizer.buffer[tag_token.start..tag_token.end];
319
320 if (mem.eql(u8, tag_name, "nav")) {
321 _ = try eatToken(tokenizer, Token.Id.BracketClose);
322
323 try nodes.append(Node.Nav);
324 } else if (mem.eql(u8, tag_name, "header_open")) {
325 _ = try eatToken(tokenizer, Token.Id.Separator);
326 const content_token = try eatToken(tokenizer, Token.Id.TagContent);
327 const content = tokenizer.buffer[content_token.start..content_token.end];
328 _ = try eatToken(tokenizer, Token.Id.BracketClose);
329
330 header_stack_size += 1;
331
332 const urlized = try urlize(allocator, content);
333 try nodes.append(Node{.HeaderOpen = HeaderOpen {
334 .name = content,
335 .url = urlized,
336 .n = header_stack_size,
337 }});
338 if (try urls.put(urlized, tag_token)) |other_tag_token| {
339 parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {};
340 parseError(tokenizer, other_tag_token, "other tag here") catch {};
341 return error.ParseError;
342 }
343 if (last_action == Action.Open) {
344 try toc.writeByte('\n');
345 try toc.writeByteNTimes(' ', header_stack_size * 4);
346 try toc.write("<ul>\n");
347 } else {
348 last_action = Action.Open;
349 }
350 try toc.writeByteNTimes(' ', 4 + header_stack_size * 4);
351 try toc.print("<li><a href=\"#{}\">{}</a>", urlized, content);
352 } else if (mem.eql(u8, tag_name, "header_close")) {
353 if (header_stack_size == 0) {
354 return parseError(tokenizer, tag_token, "unbalanced close header");
355 }
356 header_stack_size -= 1;
357 _ = try eatToken(tokenizer, Token.Id.BracketClose);
358
359 if (last_action == Action.Close) {
360 try toc.writeByteNTimes(' ', 8 + header_stack_size * 4);
361 try toc.write("</ul></li>\n");
362 } else {
363 try toc.write("</li>\n");
364 last_action = Action.Close;
365 }
366 } else if (mem.eql(u8, tag_name, "see_also")) {
367 var list = std.ArrayList(SeeAlsoItem).init(allocator);
368 %defer list.deinit();
369
370 while (true) {
371 const see_also_tok = tokenizer.next();
372 switch (see_also_tok.id) {
373 Token.Id.TagContent => {
374 const content = tokenizer.buffer[see_also_tok.start..see_also_tok.end];
375 try list.append(SeeAlsoItem {
376 .name = content,
377 .token = see_also_tok,
378 });
379 },
380 Token.Id.Separator => {},
381 Token.Id.BracketClose => {
382 try nodes.append(Node {.SeeAlso = list.toOwnedSlice() } );
383 break;
384 },
385 else => return parseError(tokenizer, see_also_tok, "invalid see_also token"),
386 }
387 }
388 } else if (mem.eql(u8, tag_name, "code_begin")) {
389 _ = try eatToken(tokenizer, Token.Id.Separator);
390 const code_kind_tok = try eatToken(tokenizer, Token.Id.TagContent);
391 var name: []const u8 = "test";
392 const maybe_sep = tokenizer.next();
393 switch (maybe_sep.id) {
394 Token.Id.Separator => {
395 const name_tok = try eatToken(tokenizer, Token.Id.TagContent);
396 name = tokenizer.buffer[name_tok.start..name_tok.end];
397 _ = try eatToken(tokenizer, Token.Id.BracketClose);
398 },
399 Token.Id.BracketClose => {},
400 else => return parseError(tokenizer, token, "invalid token"),
401 }
402 const code_kind_str = tokenizer.buffer[code_kind_tok.start..code_kind_tok.end];
403 var code_kind_id: Code.Id = undefined;
404 if (mem.eql(u8, code_kind_str, "exe")) {
405 code_kind_id = Code.Id.Exe;
406 } else if (mem.eql(u8, code_kind_str, "test")) {
407 code_kind_id = Code.Id.Test;
408 } else if (mem.eql(u8, code_kind_str, "error")) {
409 code_kind_id = Code.Id.Error;
410 } else {
411 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str);
412 }
413 const source_token = try eatToken(tokenizer, Token.Id.Content);
414 _ = try eatToken(tokenizer, Token.Id.BracketOpen);
415 const end_code_tag = try eatToken(tokenizer, Token.Id.TagContent);
416 const end_tag_name = tokenizer.buffer[end_code_tag.start..end_code_tag.end];
417 if (!mem.eql(u8, end_tag_name, "code_end")) {
418 return parseError(tokenizer, end_code_tag, "expected code_end token");
419 }
420 _ = try eatToken(tokenizer, Token.Id.BracketClose);
421 try nodes.append(Node {.Code = Code{
422 .id = code_kind_id,
423 .name = name,
424 .source_token = source_token,
425 }});
426 } else {
427 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
428 }
59429 },
60 State.Derp => unreachable,
430 else => return parseError(tokenizer, token, "invalid token"),
61431 }
62432 }
433
434 return Toc {
435 .nodes = nodes.toOwnedSlice(),
436 .toc = toc_buf.toOwnedSlice(),
437 .urls = urls,
438 };
439}
440
441fn urlize(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
442 var buf = try std.Buffer.initSize(allocator, 0);
443 defer buf.deinit();
444
445 var buf_adapter = io.BufferOutStream.init(&buf);
446 var out = &buf_adapter.stream;
447 for (input) |c| {
448 switch (c) {
449 'a'...'z', 'A'...'Z', '_', '-' => {
450 try out.writeByte(c);
451 },
452 ' ' => {
453 try out.writeByte('-');
454 },
455 else => {},
456 }
457 }
458 return buf.toOwnedSlice();
459}
460
461fn escapeHtml(allocator: &mem.Allocator, input: []const u8) -> %[]u8 {
462 var buf = try std.Buffer.initSize(allocator, 0);
463 defer buf.deinit();
464
465 var buf_adapter = io.BufferOutStream.init(&buf);
466 var out = &buf_adapter.stream;
467 for (input) |c| {
468 try switch (c) {
469 '&' => out.write("&amp;"),
470 '<' => out.write("&lt;"),
471 '>' => out.write("&gt;"),
472 '"' => out.write("&quot;"),
473 else => out.writeByte(c),
474 };
475 }
476 return buf.toOwnedSlice();
477}
478
479error ExampleFailedToCompile;
480
481fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) -> %void {
482 for (toc.nodes) |node| {
483 switch (node) {
484 Node.Content => |data| {
485 try out.write(data);
486 },
487 Node.Nav => {
488 try out.write(toc.toc);
489 },
490 Node.HeaderOpen => |info| {
491 try out.print("<h{} id=\"{}\">{}</h{}>\n", info.n, info.url, info.name, info.n);
492 },
493 Node.SeeAlso => |items| {
494 try out.write("<p>See also:</p><ul>\n");
495 for (items) |item| {
496 const url = try urlize(allocator, item.name);
497 if (!toc.urls.contains(url)) {
498 return parseError(tokenizer, item.token, "url not found: {}", url);
499 }
500 try out.print("<li><a href=\"#{}\">{}</a></li>\n", url, item.name);
501 }
502 try out.write("</ul>\n");
503 },
504 Node.Code => |code| {
505 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
506 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
507 const escaped_source = try escapeHtml(allocator, trimmed_raw_source);
508 try out.print("<pre><code class=\"zig\">{}</code></pre>", escaped_source);
509 const tmp_dir_name = "docgen_tmp";
510 try os.makePath(allocator, tmp_dir_name);
511 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
512 const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
513 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
514 const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);
515 try io.writeFile(tmp_source_file_name, trimmed_raw_source, null);
516
517 switch (code.id) {
518 Code.Id.Exe => {
519 {
520 const args = [][]const u8 {zig_exe, "build-exe", tmp_source_file_name, "--output", tmp_bin_file_name};
521 const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
522 switch (result.term) {
523 os.ChildProcess.Term.Exited => |exit_code| {
524 if (exit_code != 0) {
525 warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code);
526 for (args) |arg| warn("{} ", arg) else warn("\n");
527 return parseError(tokenizer, code.source_token, "example failed to compile");
528 }
529 },
530 else => {
531 warn("{}\nThe following command crashed:\n", result.stderr);
532 for (args) |arg| warn("{} ", arg) else warn("\n");
533 return parseError(tokenizer, code.source_token, "example failed to compile");
534 },
535 }
536 }
537 const args = [][]const u8 {tmp_bin_file_name};
538 const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size);
539 switch (result.term) {
540 os.ChildProcess.Term.Exited => |exit_code| {
541 if (exit_code != 0) {
542 warn("The following command exited with code {}:\n", exit_code);
543 for (args) |arg| warn("{} ", arg) else warn("\n");
544 return parseError(tokenizer, code.source_token, "example exited with code {}", exit_code);
545 }
546 },
547 else => {
548 warn("The following command crashed:\n");
549 for (args) |arg| warn("{} ", arg) else warn("\n");
550 return parseError(tokenizer, code.source_token, "example crashed");
551 },
552 }
553 try out.print("<pre><code class=\"sh\">$ zig build-exe {}.zig\n$ ./{}\n{}{}</code></pre>\n", code.name, code.name, result.stderr, result.stdout);
554 },
555 Code.Id.Test => {
556 @panic("TODO");
557 },
558 Code.Id.Error => {
559 @panic("TODO");
560 },
561 }
562 },
563 }
564 }
565
63566}
doc/home.html.in deleted-724
......@@ -1,724 +0,0 @@
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>2018-01-03 - <a href="http://andrewkelley.me/post/zig-december-2017-in-review.html">December 2017 in Review</a></li>
54 <li>2017-10-17 - <a href="download/0.1.1/release-notes.html">Zig 0.1.1 Release Notes</a></li>
55 <li>2017-07-19 - <a href="http://tiehuis.github.io/iterative-replacement-of-c-with-zig">Iterative Replacement of C with Zig</a></li>
56 <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>
57 <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>
58 <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>
59 <li>2016-02-08 - <a href="http://andrewkelley.me/post/intro-to-zig.html">Introduction to the Zig Programming Language</a></li>
60 </ul>
61 <h2 id="source-examples">Source Code Examples</h2>
62 <ul>
63 <li><a href="#hello">Hello World</a></li>
64 <li><a href="#hello_libc">Hello World with libc</a></li>
65 <li><a href="#parse">Parsing Unsigned Integers</a></li>
66 <li><a href="#hashmap">HashMap with Custom Allocator</a></li>
67 <li><a href="#tetris">Tetris Clone</a></li>
68 <li><a href="#clashos">Bare Bones Operating System</a></li>
69 <li><a href="#cat">Cat Utility</a></li>
70 <li><a href="#multiline-strings">Multiline String Syntax</a></li>
71 <li><a href="#mersenne">Mersenne Twister Random Number Generator</a></li>
72 </ul>
73 <h3 id="hello">Hello World</h3>
74 <pre><code class="zig">const std = @import("std");
75
76pub fn main() -&gt; %void {
77 // If this program is run without stdout attached, exit with an error.
78 var stdout_file = try std.io.getStdOut();
79 // If this program encounters pipe failure when printing to stdout, exit
80 // with an error.
81 try stdout_file.write("Hello, world!\n");
82}</code></pre>
83 <p>Build this with:</p>
84 <pre>zig build-exe hello.zig</pre>
85 <h3 id="hello_libc">Hello World with libc</h3>
86 <pre><code class="zig">const c = @cImport({
87 // See https://github.com/zig-lang/zig/issues/515
88 @cDefine("_NO_CRT_STDIO_INLINE", "1");
89 @cInclude("stdio.h");
90 @cInclude("string.h");
91});
92
93const msg = c"Hello, world!\n";
94
95export fn main(argc: c_int, argv: &amp;&amp;u8) -&gt; c_int {
96 if (c.printf(msg) != c_int(c.strlen(msg)))
97 return -1;
98
99 return 0;
100}</code></pre>
101 <p>Build this with:</p>
102 <pre>zig build-exe hello.zig --library c</pre>
103 <h3 id="parse">Parsing Unsigned Integers</h3>
104 <pre><code class="zig">pub fn parseUnsigned(comptime T: type, buf: []u8, radix: u8) -&gt; %T {
105 var x: T = 0;
106
107 for (buf) |c| {
108 const digit = try charToDigit(c, radix);
109 x = try mulOverflow(T, x, radix);
110 x = try addOverflow(T, x, digit);
111 }
112
113 return x;
114}
115
116error InvalidChar;
117
118fn charToDigit(c: u8, radix: u8) -&gt; %u8 {
119 const value = switch (c) {
120 '0' ... '9' =&gt; c - '0',
121 'A' ... 'Z' =&gt; c - 'A' + 10,
122 'a' ... 'z' =&gt; c - 'a' + 10,
123 else =&gt; return error.InvalidChar,
124 };
125
126 if (value &gt;= radix)
127 return error.InvalidChar;
128
129 return value;
130}
131
132error Overflow;
133
134pub fn mulOverflow(comptime T: type, a: T, b: T) -&gt; %T {
135 var answer: T = undefined;
136 if (@mulWithOverflow(T, a, b, &amp;answer)) error.Overflow else answer
137}
138
139pub fn addOverflow(comptime T: type, a: T, b: T) -&gt; %T {
140 var answer: T = undefined;
141 if (@addWithOverflow(T, a, b, &amp;answer)) error.Overflow else answer
142}
143
144fn getNumberWithDefault(s: []u8) -&gt; u32 {
145 parseUnsigned(u32, s, 10) catch 42
146}
147
148fn getNumberOrCrash(s: []u8) -&gt; u32 {
149 %%parseUnsigned(u32, s, 10)
150}
151
152fn addTwoTogetherOrReturnErr(a_str: []u8, b_str: []u8) -&gt; %u32 {
153 const a = parseUnsigned(u32, a_str, 10) catch |err| return err;
154 const b = parseUnsigned(u32, b_str, 10) catch |err| return err;
155 return a + b;
156}</code></pre>
157 <h3 id="hashmap">HashMap with Custom Allocator</h3>
158 <pre><code class="zig">const debug = @import(&quot;debug.zig&quot;);
159const assert = debug.assert;
160const math = @import(&quot;math.zig&quot;);
161const mem = @import(&quot;mem.zig&quot;);
162const Allocator = mem.Allocator;
163
164const want_modification_safety = !@compileVar(&quot;is_release&quot;);
165const debug_u32 = if (want_modification_safety) u32 else void;
166
167pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K)-&gt;u32,
168 comptime eql: fn(a: K, b: K)-&gt;bool) -&gt; type
169{
170 struct {
171 entries: []Entry,
172 size: usize,
173 max_distance_from_start_index: usize,
174 allocator: &amp;Allocator,
175 // this is used to detect bugs where a hashtable is edited while an iterator is running.
176 modification_count: debug_u32,
177
178 const Self = this;
179
180 pub const Entry = struct {
181 used: bool,
182 distance_from_start_index: usize,
183 key: K,
184 value: V,
185 };
186
187 pub const Iterator = struct {
188 hm: &amp;Self,
189 // how many items have we returned
190 count: usize,
191 // iterator through the entry array
192 index: usize,
193 // used to detect concurrent modification
194 initial_modification_count: debug_u32,
195
196 pub fn next(it: &amp;Iterator) -&gt; ?&amp;Entry {
197 if (want_modification_safety) {
198 assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
199 }
200 if (it.count &gt;= it.hm.size) return null;
201 while (it.index &lt; it.hm.entries.len) : (it.index += 1) {
202 const entry = &amp;it.hm.entries[it.index];
203 if (entry.used) {
204 it.index += 1;
205 it.count += 1;
206 return entry;
207 }
208 }
209 unreachable // no next item
210 }
211 };
212
213 pub fn init(hm: &amp;Self, allocator: &amp;Allocator) {
214 hm.entries = []Entry{};
215 hm.allocator = allocator;
216 hm.size = 0;
217 hm.max_distance_from_start_index = 0;
218 // it doesn't actually matter what we set this to since we use wrapping integer arithmetic
219 hm.modification_count = undefined;
220 }
221
222 pub fn deinit(hm: &amp;Self) {
223 hm.allocator.free(Entry, hm.entries);
224 }
225
226 pub fn clear(hm: &amp;Self) {
227 for (hm.entries) |*entry| {
228 entry.used = false;
229 }
230 hm.size = 0;
231 hm.max_distance_from_start_index = 0;
232 hm.incrementModificationCount();
233 }
234
235 pub fn put(hm: &amp;Self, key: K, value: V) -&gt; %void {
236 if (hm.entries.len == 0) {
237 try hm.initCapacity(16);
238 }
239 hm.incrementModificationCount();
240
241 // if we get too full (60%), double the capacity
242 if (hm.size * 5 &gt;= hm.entries.len * 3) {
243 const old_entries = hm.entries;
244 try hm.initCapacity(hm.entries.len * 2);
245 // dump all of the old elements into the new table
246 for (old_entries) |*old_entry| {
247 if (old_entry.used) {
248 hm.internalPut(old_entry.key, old_entry.value);
249 }
250 }
251 hm.allocator.free(Entry, old_entries);
252 }
253
254 hm.internalPut(key, value);
255 }
256
257 pub fn get(hm: &amp;Self, key: K) -&gt; ?&amp;Entry {
258 return hm.internalGet(key);
259 }
260
261 pub fn remove(hm: &amp;Self, key: K) {
262 hm.incrementModificationCount();
263 const start_index = hm.keyToIndex(key);
264 {var roll_over: usize = 0; while (roll_over &lt;= hm.max_distance_from_start_index) : (roll_over += 1) {
265 const index = (start_index + roll_over) % hm.entries.len;
266 var entry = &amp;hm.entries[index];
267
268 assert(entry.used); // key not found
269
270 if (!eql(entry.key, key)) continue;
271
272 while (roll_over &lt; hm.entries.len) : (roll_over += 1) {
273 const next_index = (start_index + roll_over + 1) % hm.entries.len;
274 const next_entry = &amp;hm.entries[next_index];
275 if (!next_entry.used or next_entry.distance_from_start_index == 0) {
276 entry.used = false;
277 hm.size -= 1;
278 return;
279 }
280 *entry = *next_entry;
281 entry.distance_from_start_index -= 1;
282 entry = next_entry;
283 }
284 unreachable // shifting everything in the table
285 }}
286 unreachable // key not found
287 }
288
289 pub fn entryIterator(hm: &amp;Self) -&gt; Iterator {
290 return Iterator {
291 .hm = hm,
292 .count = 0,
293 .index = 0,
294 .initial_modification_count = hm.modification_count,
295 };
296 }
297
298 fn initCapacity(hm: &amp;Self, capacity: usize) -&gt; %void {
299 hm.entries = try hm.allocator.alloc(Entry, capacity);
300 hm.size = 0;
301 hm.max_distance_from_start_index = 0;
302 for (hm.entries) |*entry| {
303 entry.used = false;
304 }
305 }
306
307 fn incrementModificationCount(hm: &amp;Self) {
308 if (want_modification_safety) {
309 hm.modification_count +%= 1;
310 }
311 }
312
313 fn internalPut(hm: &amp;Self, orig_key: K, orig_value: V) {
314 var key = orig_key;
315 var value = orig_value;
316 const start_index = hm.keyToIndex(key);
317 var roll_over: usize = 0;
318 var distance_from_start_index: usize = 0;
319 while (roll_over &lt; hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1}) {
320 const index = (start_index + roll_over) % hm.entries.len;
321 const entry = &amp;hm.entries[index];
322
323 if (entry.used and !eql(entry.key, key)) {
324 if (entry.distance_from_start_index &lt; distance_from_start_index) {
325 // robin hood to the rescue
326 const tmp = *entry;
327 hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
328 distance_from_start_index);
329 *entry = Entry {
330 .used = true,
331 .distance_from_start_index = distance_from_start_index,
332 .key = key,
333 .value = value,
334 };
335 key = tmp.key;
336 value = tmp.value;
337 distance_from_start_index = tmp.distance_from_start_index;
338 }
339 continue;
340 }
341
342 if (!entry.used) {
343 // adding an entry. otherwise overwriting old value with
344 // same key
345 hm.size += 1;
346 }
347
348 hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
349 *entry = Entry {
350 .used = true,
351 .distance_from_start_index = distance_from_start_index,
352 .key = key,
353 .value = value,
354 };
355 return;
356 }
357 unreachable // put into a full map
358 }
359
360 fn internalGet(hm: &amp;Self, key: K) -&gt; ?&amp;Entry {
361 const start_index = hm.keyToIndex(key);
362 {var roll_over: usize = 0; while (roll_over &lt;= hm.max_distance_from_start_index) : (roll_over += 1) {
363 const index = (start_index + roll_over) % hm.entries.len;
364 const entry = &amp;hm.entries[index];
365
366 if (!entry.used) return null;
367 if (eql(entry.key, key)) return entry;
368 }}
369 return null;
370 }
371
372 fn keyToIndex(hm: &amp;Self, key: K) -&gt; usize {
373 return usize(hash(key)) % hm.entries.len;
374 }
375 }
376}
377
378test "basic hash map test" {
379 var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;
380 map.init(&amp;debug.global_allocator);
381 defer map.deinit();
382
383 %%map.put(1, 11);
384 %%map.put(2, 22);
385 %%map.put(3, 33);
386 %%map.put(4, 44);
387 %%map.put(5, 55);
388
389 assert((??map.get(2)).value == 22);
390 map.remove(2);
391 assert(if (const entry ?= map.get(2)) false else true);
392}
393
394fn hash_i32(x: i32) -&gt; u32 {
395 *(&amp;u32)(&amp;x)
396}
397fn eql_i32(a: i32, b: i32) -&gt; bool {
398 a == b
399}</code></pre>
400 <h3 id="tetris">Tetris Clone</h3>
401 <img src="tetris-screenshot.png">
402 <p>
403 <a href="https://github.com/andrewrk/tetris">Source Code on GitHub</a>
404 </p>
405 <h3 id="clashos">Bare Bones Operating System</h3>
406 <p>
407 <a href="https://github.com/andrewrk/clashos">Source Code on GitHub</a>
408 </p>
409 <h3 id="cat">Cat Utility</h3>
410 <pre><code class="zig">const std = @import("std");
411const io = std.io;
412const mem = std.mem;
413const os = std.os;
414
415pub fn main() -&gt; %void {
416 const exe = os.args.at(0);
417 var catted_anything = false;
418 var arg_i: usize = 1;
419 while (arg_i &lt; os.args.count()) : (arg_i += 1) {
420 const arg = os.args.at(arg_i);
421 if (mem.eql(u8, arg, "-")) {
422 catted_anything = true;
423 try cat_stream(&amp;io.stdin);
424 } else if (arg[0] == '-') {
425 return usage(exe);
426 } else {
427 var is = io.InStream.open(arg, null) catch |err| {
428 %%io.stderr.printf("Unable to open file: {}\n", @errorName(err));
429 return err;
430 };
431 defer is.close();
432
433 catted_anything = true;
434 try cat_stream(&amp;is);
435 }
436 }
437 if (!catted_anything) {
438 try cat_stream(&amp;io.stdin);
439 }
440 try io.stdout.flush();
441}
442
443fn usage(exe: []const u8) -&gt; %void {
444 %%io.stderr.printf("Usage: {} [FILE]...\n", exe);
445 return error.Invalid;
446}
447
448fn cat_stream(is: &amp;io.InStream) -&gt; %void {
449 var buf: [1024 * 4]u8 = undefined;
450
451 while (true) {
452 const bytes_read = is.read(buf[0..]) catch |err| {
453 %%io.stderr.printf("Unable to read from stream: {}\n", @errorName(err));
454 return err;
455 };
456
457 if (bytes_read == 0) {
458 break;
459 }
460
461 io.stdout.write(buf[0..bytes_read]) catch |err| {
462 %%io.stderr.printf("Unable to write to stdout: {}\n", @errorName(err));
463 return err;
464 };
465 }
466}</code></pre>
467 <h3 id="multiline-strings">Multiline String Syntax</h3>
468 <pre><code class="zig">pub fn createAllShaders() -&gt; AllShaders {
469 var as : AllShaders = undefined;
470
471 as.primitive = createShader(
472 \\#version 150 core
473 \\
474 \\in vec3 VertexPosition;
475 \\
476 \\uniform mat4 MVP;
477 \\
478 \\void main(void) {
479 \\ gl_Position = vec4(VertexPosition, 1.0) * MVP;
480 \\}
481 ,
482 \\#version 150 core
483 \\
484 \\out vec4 FragColor;
485 \\
486 \\uniform vec4 Color;
487 \\
488 \\void main(void) {
489 \\ FragColor = Color;
490 \\}
491 , null);
492
493 as.primitive_attrib_position = as.primitive.attrib_location(c&quot;VertexPosition&quot;);
494 as.primitive_uniform_mvp = as.primitive.uniform_location(c&quot;MVP&quot;);
495 as.primitive_uniform_color = as.primitive.uniform_location(c&quot;Color&quot;);
496
497
498
499 as.texture = createShader(
500 \\#version 150 core
501 \\
502 \\in vec3 VertexPosition;
503 \\in vec2 TexCoord;
504 \\
505 \\out vec2 FragTexCoord;
506 \\
507 \\uniform mat4 MVP;
508 \\
509 \\void main(void)
510 \\{
511 \\ FragTexCoord = TexCoord;
512 \\ gl_Position = vec4(VertexPosition, 1.0) * MVP;
513 \\}
514 ,
515 \\#version 150 core
516 \\
517 \\in vec2 FragTexCoord;
518 \\out vec4 FragColor;
519 \\
520 \\uniform sampler2D Tex;
521 \\
522 \\void main(void)
523 \\{
524 \\ FragColor = texture(Tex, FragTexCoord);
525 \\}
526 , null);
527
528 as.texture_attrib_tex_coord = as.texture.attrib_location(c&quot;TexCoord&quot;);
529 as.texture_attrib_position = as.texture.attrib_location(c&quot;VertexPosition&quot;);
530 as.texture_uniform_mvp = as.texture.uniform_location(c&quot;MVP&quot;);
531 as.texture_uniform_tex = as.texture.uniform_location(c&quot;Tex&quot;);
532
533 debug_gl.assert_no_error();
534
535 return as;
536}</code></pre>
537 <h3 id="mersenne">Mersenne Twister Random Number Generator</h3>
538 <pre><code class="zig">const assert = @import(&quot;debug.zig&quot;).assert;
539const rand_test = @import(&quot;rand_test.zig&quot;);
540
541pub const MT19937_32 = MersenneTwister(
542 u32, 624, 397, 31,
543 0x9908B0DF,
544 11, 0xFFFFFFFF,
545 7, 0x9D2C5680,
546 15, 0xEFC60000,
547 18, 1812433253);
548
549pub const MT19937_64 = MersenneTwister(
550 u64, 312, 156, 31,
551 0xB5026F5AA96619E9,
552 29, 0x5555555555555555,
553 17, 0x71D67FFFEDA60000,
554 37, 0xFFF7EEE000000000,
555 43, 6364136223846793005);
556
557/// Use `init` to initialize this state.
558pub const Rand = struct {
559 const Rng = if (@sizeOf(usize) &gt;= 8) MT19937_64 else MT19937_32;
560
561 rng: Rng,
562
563 /// Initialize random state with the given seed.
564 pub fn init(r: &amp;Rand, seed: usize) {
565 r.rng.init(seed);
566 }
567
568 /// Get an integer with random bits.
569 pub fn scalar(r: &amp;Rand, comptime T: type) -&gt; T {
570 if (T == usize) {
571 return r.rng.get();
572 } else {
573 var result: [@sizeOf(T)]u8 = undefined;
574 r.fillBytes(result);
575 return ([]T)(result)[0];
576 }
577 }
578
579 /// Fill `buf` with randomness.
580 pub fn fillBytes(r: &amp;Rand, buf: []u8) {
581 var bytes_left = buf.len;
582 while (bytes_left &gt;= @sizeOf(usize)) {
583 ([]usize)(buf[buf.len - bytes_left...])[0] = r.rng.get();
584 bytes_left -= @sizeOf(usize);
585 }
586 if (bytes_left &gt; 0) {
587 var rand_val_array : [@sizeOf(usize)]u8 = undefined;
588 ([]usize)(rand_val_array)[0] = r.rng.get();
589 while (bytes_left &gt; 0) {
590 buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left];
591 bytes_left -= 1;
592 }
593 }
594 }
595
596 /// Get a random unsigned integer with even distribution between `start`
597 /// inclusive and `end` exclusive.
598 // TODO support signed integers and then rename to &quot;range&quot;
599 pub fn rangeUnsigned(r: &amp;Rand, comptime T: type, start: T, end: T) -&gt; T {
600 const range = end - start;
601 const leftover = @maxValue(T) % range;
602 const upper_bound = @maxValue(T) - leftover;
603 var rand_val_array : [@sizeOf(T)]u8 = undefined;
604
605 while (true) {
606 r.fillBytes(rand_val_array);
607 const rand_val = ([]T)(rand_val_array)[0];
608 if (rand_val &lt; upper_bound) {
609 return start + (rand_val % range);
610 }
611 }
612 }
613
614 /// Get a floating point value in the range 0.0..1.0.
615 pub fn float(r: &amp;Rand, comptime T: type) -&gt; T {
616 // TODO Implement this way instead:
617 // const int = @int_type(false, @sizeOf(T) * 8);
618 // const mask = ((1 &lt;&lt; @float_mantissa_bit_count(T)) - 1);
619 // const rand_bits = r.rng.scalar(int) &amp; mask;
620 // return @float_compose(T, false, 0, rand_bits) - 1.0
621 const int_type = @intType(false, @sizeOf(T) * 8);
622 const precision = if (T == f32) {
623 16777216
624 } else if (T == f64) {
625 9007199254740992
626 } else {
627 @compileError(&quot;unknown floating point type&quot;)
628 };
629 return T(r.rangeUnsigned(int_type, 0, precision)) / T(precision);
630 }
631};
632
633fn MersenneTwister(
634 comptime int: type, comptime n: usize, comptime m: usize, comptime r: int,
635 comptime a: int,
636 comptime u: int, comptime d: int,
637 comptime s: int, comptime b: int,
638 comptime t: int, comptime c: int,
639 comptime l: int, comptime f: int) -&gt; type
640{
641 struct {
642 const Self = this;
643
644 array: [n]int,
645 index: usize,
646
647 pub fn init(mt: &amp;Self, seed: int) {
648 mt.index = n;
649
650 var prev_value = seed;
651 mt.array[0] = prev_value;
652 {var i: usize = 1; while (i &lt; n) : (i += 1) {
653 prev_value = int(i) +% f *% (prev_value ^ (prev_value &gt;&gt; (int.bit_count - 2)));
654 mt.array[i] = prev_value;
655 }};
656 }
657
658 pub fn get(mt: &amp;Self) -&gt; int {
659 const mag01 = []int{0, a};
660 const LM: int = (1 &lt;&lt; r) - 1;
661 const UM = ~LM;
662
663 if (mt.index &gt;= n) {
664 var i: usize = 0;
665
666 while (i &lt; n - m) : (i += 1) {
667 const x = (mt.array[i] &amp; UM) | (mt.array[i + 1] &amp; LM);
668 mt.array[i] = mt.array[i + m] ^ (x &gt;&gt; 1) ^ mag01[x &amp; 0x1];
669 }
670
671 while (i &lt; n - 1) : (i += 1) {
672 const x = (mt.array[i] &amp; UM) | (mt.array[i + 1] &amp; LM);
673 mt.array[i] = mt.array[i + m - n] ^ (x &gt;&gt; 1) ^ mag01[x &amp; 0x1];
674
675 }
676 const x = (mt.array[i] &amp; UM) | (mt.array[0] &amp; LM);
677 mt.array[i] = mt.array[m - 1] ^ (x &gt;&gt; 1) ^ mag01[x &amp; 0x1];
678
679 mt.index = 0;
680 }
681
682 var x = mt.array[mt.index];
683 mt.index += 1;
684
685 x ^= ((x &gt;&gt; u) &amp; d);
686 x ^= ((x &lt;&lt;% s) &amp; b);
687 x ^= ((x &lt;&lt;% t) &amp; c);
688 x ^= (x &gt;&gt; l);
689
690 return x;
691 }
692 }
693}
694
695test "float 32" {
696 var r: Rand = undefined;
697 r.init(42);
698
699 {var i: usize = 0; while (i &lt; 1000) : (i += 1) {
700 const val = r.float(f32);
701 assert(val &gt;= 0.0);
702 assert(val &lt; 1.0);
703 }}
704}
705
706test "MT19937_64" {
707 var rng: MT19937_64 = undefined;
708 rng.init(rand_test.mt64_seed);
709 for (rand_test.mt64_data) |value| {
710 assert(value == rng.get());
711 }
712}
713
714test "MT19937_32" {
715 var rng: MT19937_32 = undefined;
716 rng.init(rand_test.mt32_seed);
717 for (rand_test.mt32_data) |value| {
718 assert(value == rng.get());
719 }
720}</code></pre>
721 <script src="highlight/highlight.pack.js"></script>
722 <script>hljs.initHighlightingOnLoad();</script>
723 </body>
724</html>
doc/langref.html.in+424-718
......@@ -31,221 +31,10 @@
3131 </head>
3232 <body>
3333 <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="#source-encoding">Source Encoding</a></li>
38 <li><a href="#values">Values</a></li>
39 <ul>
40 <li><a href="#primitive-types">Primitive Types</a></li>
41 <li><a href="#primitive-values">Primitive Values</a></li>
42 <li><a href="#string-literals">String Literals</a>
43 <ul>
44 <li><a href="#string-literal-escapes">Escape Sequences</a></li>
45 <li><a href="#multiline-string-literals">Multiline String Literals</a></li>
46 </ul>
47 </li>
48 <li><a href="#values-assignment">Assignment</a></li>
49 </ul>
50 </li>
51 <li><a href="#integers">Integers</a>
52 <ul>
53 <li><a href="#integer-literals">Integer Literals</a></li>
54 <li><a href="#runtime-integer-values">Runtime Integer Values</a></li>
55 </ul>
56 </li>
57 <li><a href="#floats">Floats</a>
58 <ul>
59 <li><a href="#float-literals">Float Literals</a></li>
60 <li><a href="#float-operations">Floating Point Operations</a></li>
61 </ul>
62 </li>
63 <li><a href="#operators">Operators</a>
64 <ul>
65 <li><a href="#operators-table">Table of Operators</a></li>
66 <li><a href="#operators-precedence">Precedence</a></li>
67 </ul>
68 </li>
69 <li><a href="#arrays">Arrays</a></li>
70 <li><a href="#pointers">Pointers</a>
71 <ul>
72 <li><a href="#alignment">Alignment</a></li>
73 <li><a href="#type-based-alias-analysis">Type Based Alias Analysis</a></li>
74 </ul>
75 </li>
76 <li><a href="#slices">Slices</a></li>
77 <li><a href="#struct">struct</a></li>
78 <li><a href="#enum">enum</a></li>
79 <li><a href="#union">union</a></li>
80 <li><a href="#switch">switch</a></li>
81 <li><a href="#while">while</a></li>
82 <li><a href="#for">for</a></li>
83 <li><a href="#if">if</a></li>
84 <li><a href="#goto">goto</a></li>
85 <li><a href="#defer">defer</a></li>
86 <li><a href="#unreachable">unreachable</a>
87 <ul>
88 <li><a href="#unreachable-basics">Basics</a></li>
89 <li><a href="#unreachable-comptime">At Compile-Time</a></li>
90 </ul>
91 </li>
92 <li><a href="#noreturn">noreturn</a></li>
93 <li><a href="#functions">Functions</a>
94 <ul>
95 <li><a href="#functions-by-val-params">Pass-by-val Parameters</a>
96 </ul>
97 </li>
98 <li><a href="#errors">Errors</a></li>
99 <li><a href="#nullables">Nullables</a></li>
100 <li><a href="#casting">Casting</a></li>
101 <li><a href="#void">void</a></li>
102 <li><a href="#this">this</a></li>
103 <li><a href="#comptime">comptime</a>
104 <ul>
105 <li><a href="#introducing-compile-time-concept">Introducing the Compile-Time Concept</a></li>
106 <ul>
107 <li><a href="#compile-time-parameters">Compile-time parameters</a></li>
108 <li><a href="#compile-time-variables">Compile-time variables</a></li>
109 <li><a href="#compile-time-expressions">Compile-time expressions</a></li>
110 </ul>
111 <li><a href="#generic-data-structures">Generic Data Structures</a></li>
112 <li><a href="#case-study-printf">Case Study: printf in Zig</a></li>
113 </ul>
114 </li>
115 <li><a href="#inline">inline</a></li>
116 <li><a href="#assembly">assembly</a></li>
117 <li><a href="#atomics">Atomics</a></li>
118 <li><a href="#builtin-functions">Builtin Functions</a>
119 <ul>
120 <li><a href="#builtin-addWithOverflow">@addWithOverflow</a></li>
121 <li><a href="#builtin-alignCast">@alignCast</a></li>
122 <li><a href="#builtin-alignOf">@alignOf</a></li>
123 <li><a href="#builtin-ArgType">@ArgType</a></li>
124 <li><a href="#builtin-bitCast">@bitCast</a></li>
125 <li><a href="#builtin-breakpoint">@breakpoint</a></li>
126 <li><a href="#builtin-cDefine">@cDefine</a></li>
127 <li><a href="#builtin-cImport">@cImport</a></li>
128 <li><a href="#builtin-cInclude">@cInclude</a></li>
129 <li><a href="#builtin-cUndef">@cUndef</a></li>
130 <li><a href="#builtin-canImplicitCast">@canImplicitCast</a></li>
131 <li><a href="#builtin-clz">@clz</a></li>
132 <li><a href="#builtin-cmpxchg">@cmpxchg</a></li>
133 <li><a href="#builtin-compileError">@compileError</a></li>
134 <li><a href="#builtin-compileLog">@compileLog</a></li>
135 <li><a href="#builtin-ctz">@ctz</a></li>
136 <li><a href="#builtin-divExact">@divExact</a></li>
137 <li><a href="#builtin-divFloor">@divFloor</a></li>
138 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
139 <li><a href="#builtin-embedFile">@embedFile</a></li>
140 <li><a href="#builtin-export">@export</a></li>
141 <li><a href="#builtin-tagName">@tagName</a></li>
142 <li><a href="#builtin-TagType">@TagType</a></li>
143 <li><a href="#builtin-EnumTagType">@EnumTagType</a></li>
144 <li><a href="#builtin-errorName">@errorName</a></li>
145 <li><a href="#builtin-errorReturnTrace">@errorReturnTrace</a></li>
146 <li><a href="#builtin-fence">@fence</a></li>
147 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
148 <li><a href="#builtin-frameAddress">@frameAddress</a></li>
149 <li><a href="#builtin-import">@import</a></li>
150 <li><a href="#builtin-inlineCall">@inlineCall</a></li>
151 <li><a href="#builtin-intToPtr">@intToPtr</a></li>
152 <li><a href="#builtin-IntType">@IntType</a></li>
153 <li><a href="#builtin-maxValue">@maxValue</a></li>
154 <li><a href="#builtin-memberCount">@memberCount</a></li>
155 <li><a href="#builtin-memberName">@memberName</a></li>
156 <li><a href="#builtin-memberType">@memberType</a></li>
157 <li><a href="#builtin-memcpy">@memcpy</a></li>
158 <li><a href="#builtin-memset">@memset</a></li>
159 <li><a href="#builtin-minValue">@minValue</a></li>
160 <li><a href="#builtin-mod">@mod</a></li>
161 <li><a href="#builtin-mulWithOverflow">@mulWithOverflow</a></li>
162 <li><a href="#builtin-noInlineCall">@noInlineCall</a></li>
163 <li><a href="#builtin-offsetOf">@offsetOf</a></li>
164 <li><a href="#builtin-OpaqueType">@OpaqueType</a></li>
165 <li><a href="#builtin-panic">@panic</a></li>
166 <li><a href="#builtin-ptrCast">@ptrCast</a></li>
167 <li><a href="#builtin-ptrToInt">@ptrToInt</a></li>
168 <li><a href="#builtin-rem">@rem</a></li>
169 <li><a href="#builtin-returnAddress">@returnAddress</a></li>
170 <li><a href="#builtin-setDebugSafety">@setDebugSafety</a></li>
171 <li><a href="#builtin-setEvalBranchQuota">@setEvalBranchQuota</a></li>
172 <li><a href="#builtin-setFloatMode">@setFloatMode</a></li>
173 <li><a href="#builtin-setGlobalLinkage">@setGlobalLinkage</a></li>
174 <li><a href="#builtin-setGlobalSection">@setGlobalSection</a></li>
175 <li><a href="#builtin-shlExact">@shlExact</a></li>
176 <li><a href="#builtin-shlWithOverflow">@shlWithOverflow</a></li>
177 <li><a href="#builtin-shrExact">@shrExact</a></li>
178 <li><a href="#builtin-sizeOf">@sizeOf</a></li>
179 <li><a href="#builtin-subWithOverflow">@subWithOverflow</a></li>
180 <li><a href="#builtin-truncate">@truncate</a></li>
181 <li><a href="#builtin-typeId">@typeId</a></li>
182 <li><a href="#builtin-typeName">@typeName</a></li>
183 <li><a href="#builtin-typeOf">@typeOf</a></li>
184 </ul>
185 </li>
186 <li><a href="#build-mode">Build Mode</a>
187 <ul>
188 <li><a href="#build-mode-debug">Debug</a></li>
189 <li><a href="#build-mode-release-fast">ReleaseFast</a></li>
190 <li><a href="#build-mode-release-safe">ReleaseSafe</a></li>
191 </ul>
192 </li>
193 <li><a href="#undefined-behavior">Undefined Behavior</a>
194 <ul>
195 <li><a href="#undef-unreachable">Reaching Unreachable Code</a></li>
196 <li><a href="#undef-index-out-of-bounds">Index out of Bounds</a></li>
197 <li><a href="#undef-cast-negative-unsigned">Cast Negative Number to Unsigned Integer</a></li>
198 <li><a href="#undef-cast-truncates-data">Cast Truncates Data</a></li>
199 <li><a href="#undef-integer-overflow">Integer Overflow</a>
200 <ul>
201 <li><a href="#undef-int-overflow-default">Default Operations</a></li>
202 <li><a href="#undef-int-overflow-std">Standard Library Math Functions</a></li>
203 <li><a href="#undef-int-overflow-builtin">Builtin Overflow Functions</a></li>
204 <li><a href="#undef-int-overflow-wrap">Wrapping Operations</a></li>
205
206 </ul>
207 </li>
208 <li><a href="#undef-shl-overflow">Exact Left Shift Overflow</a></li>
209 <li><a href="#undef-shr-overflow">Exact Right Shift Overflow</a></li>
210 <li><a href="#undef-division-by-zero">Division by Zero</a></li>
211 <li><a href="#undef-remainder-division-by-zero">Remainder Division by Zero</a></li>
212 <li><a href="#undef-exact-division-remainder">Exact Division Remainder</a></li>
213 <li><a href="#undef-slice-widen-remainder">Slice Widen Remainder</a></li>
214 <li><a href="#undef-attempt-unwrap-null">Attempt to Unwrap Null</a></li>
215 <li><a href="#undef-attempt-unwrap-error">Attempt to Unwrap Error</a></li>
216 <li><a href="#undef-invalid-error-code">Invalid Error Code</a></li>
217 <li><a href="#undef-invalid-enum-cast">Invalid Enum Cast</a></li>
218 <li><a href="#undef-incorrect-pointer-alignment">Incorrect Pointer Alignment</a></li>
219 <li><a href="#undef-bad-union-field">Wrong Union Field Access</a></li>
220 </ul>
221 </li>
222 <li><a href="#memory">Memory</a></li>
223 <li><a href="#compile-variables">Compile Variables</a></li>
224 <li><a href="#root-source-file">Root Source File</a></li>
225 <li><a href="#zig-test">Zig Test</a></li>
226 <li><a href="#zig-build-system">Zig Build System</a></li>
227 <li><a href="#c">C</a>
228 <ul>
229 <li><a href="#c-type-primitives">C Type Primitives</a></li>
230 <li><a href="#c-string-literals">C String Literals</a></li>
231 <li><a href="#c-import">Import from C Header File</a></li>
232 <li><a href="#mixing-object-files">Mixing Object Files</a></li>
233 </ul>
234 </li>
235 <li><a href="#targets">Targets</a></li>
236 <li><a href="#style-guide">Style Guide</a>
237 <ul>
238 <li><a href="#style-guide-whitespace">Whitespace</a></li>
239 <li><a href="#style-guide-names">Names</a></li>
240 <li><a href="#style-guide-examples">Examples</a></li>
241 </ul>
242 </li>
243 <li><a href="#grammar">Grammar</a></li>
244 <li><a href="#zen">Zen</a></li>
245 </ul>
34 {#nav#}
24635 </div>
24736 <div id="contents">
248 <h1 id="introduction">Zig Documentation</h1>
37 {#header_open|Introduction#}
24938 <p>
25039 Zig is an open-source programming language designed for <strong>robustness</strong>,
25140 <strong>optimality</strong>, and <strong>clarity</strong>.
......@@ -264,37 +53,35 @@
26453 If you search for something specific in this documentation and do not find it,
26554 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>.
26655 </p>
267 <h2 id="hello-world">Hello World</h2>
268 <pre><code class="zig">const std = @import("std");
56 {#header_close#}
57 {#header_open|Hello World#}
26958
270pub fn main() -&gt; %void {
59 {#code_begin|exe|hello#}
60const std = @import("std");
61
62pub fn main() -> %void {
27163 // If this program is run without stdout attached, exit with an error.
27264 var stdout_file = try std.io.getStdOut();
27365 // If this program encounters pipe failure when printing to stdout, exit
27466 // with an error.
27567 try stdout_file.write("Hello, world!\n");
276}</code></pre>
277 <pre><code class="sh">$ zig build-exe hello.zig
278$ ./hello
279Hello, world!</code></pre>
68}
69 {#code_end#}
28070 <p>
28171 Usually you don't want to write to stdout. You want to write to stderr. And you
28272 don't care if it fails. It's more like a <em>warning message</em> that you want
28373 to emit. For that you can use a simpler API:
28474 </p>
285 <pre><code class="zig">const warn = @import("std").debug.warn;
75 {#code_begin|exe|hello#}
76const warn = @import("std").debug.warn;
28677
287pub fn main() -&gt; %void {
78pub fn main() -> %void {
28879 warn("Hello, world!\n");
289}</code></pre>
290 <p>See also:</p>
291 <ul>
292 <li><a href="#values">Values</a></li>
293 <li><a href="#builtin-import">@import</a></li>
294 <li><a href="#errors">Errors</a></li>
295 <li><a href="#root-source-file">Root Source File</a></li>
296 </ul>
297 <h2 id="source-encoding">Source Encoding</h2>
80}
81 {#code_end#}
82 {#see_also|Values|@import|Errors|Root Source File#}
83 {#header_close#}
84 {#header_open|Source Encoding#}
29885 <p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p>
29986 <p>Throughout all zig source code (including in comments), some codepoints are never allowed:</p>
30087 <ul>
......@@ -303,15 +90,18 @@ pub fn main() -&gt; %void {
30390 </ul>
30491 <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
30592 <p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/zig-lang/zig/issues/663">issue #663</a></p>
306 <h2 id="values">Values</h2>
307 <pre><code class="zig">const warn = @import("std").debug.warn;
308const os = @import("std").os;
309const assert = @import("std").debug.assert;
93 {#header_close#}
94 {#header_open|Values#}
95 {#code_begin|exe|values#}
96const std = @import("std");
97const warn = std.debug.warn;
98const os = std.os;
99const assert = std.debug.assert;
310100
311101// error declaration, makes `error.ArgNotFound` available
312102error ArgNotFound;
313103
314pub fn main() -&gt; %void {
104pub fn main() -> %void {
315105 // integers
316106 const one_plus_one: i32 = 1 + 1;
317107 warn("1 + 1 = {}\n", one_plus_one);
......@@ -349,31 +139,9 @@ pub fn main() -&gt; %void {
349139
350140 warn("\nerror union 2\ntype: {}\nvalue: {}\n",
351141 @typeName(@typeOf(number_or_error)), number_or_error);
352}</code></pre>
353 <pre><code class="sh">$ zig build-exe values.zig
354$ ./values
3551 + 1 = 2
3567.0 / 3.0 = 2.333333
357false
358true
359false
360
361nullable 1
362type: ?[]const u8
363value: null
364
365nullable 2
366type: ?[]const u8
367value: hi
368
369error union 1
370type: %i32
371value: error.ArgNotFound
372
373error union 2
374type: %i32
375value: 1234</code></pre>
376 <h3 id="primitive-types">Primitive Types</h2>
142}
143 {#code_end#}
144 {#header_open|Primitive Types#}
377145 <table>
378146 <tr>
379147 <th>
......@@ -599,14 +367,9 @@ value: 1234</code></pre>
599367 <td>an error code</td>
600368 </tr>
601369 </table>
602 <p>See also:</p>
603 <ul>
604 <li><a href="#integers">Integers</a></li>
605 <li><a href="#floats">Floats</a></li>
606 <li><a href="#void">void</a></li>
607 <li><a href="#errors">Errors</a></li>
608 </ul>
609 <h3 id="primitive-values">Primitive Values</h3>
370 {#see_also|Integers|Floats|void|Errors#}
371 {#header_close#}
372 {#header_open|Primitive Values#}
610373 <table>
611374 <tr>
612375 <th>
......@@ -633,12 +396,9 @@ value: 1234</code></pre>
633396 <td>refers to the thing in immediate scope</td>
634397 </tr>
635398 </table>
636 <p>See also:</p>
637 <ul>
638 <li><a href="#nullables">Nullables</a></li>
639 <li><a href="#this">this</a></li>
640 </ul>
641 <h3 id="string-literals">String Literals</h3>
399 {#see_also|Nullables|this#}
400 {#header_close#}
401 {#header_open|String Literals#}
642402 <pre><code class="zig">const assert = @import("std").debug.assert;
643403const mem = @import("std").mem;
644404
......@@ -658,12 +418,8 @@ test "string literals" {
658418}</code></pre>
659419 <pre><code class="sh">$ zig test string_literals.zig
660420Test 1/1 string literals...OK</code></pre>
661 <p>See also:</p>
662 <ul>
663 <li><a href="#arrays">Arrays</a></li>
664 <li><a href="#zig-test">Zig Test</a></li>
665 </ul>
666 <h4 id="string-literal-escapes">Escape Sequences</h4>
421 {#see_also|Arrays|Zig Test#}
422 {#header_open|Escape Sequences#}
667423 <table>
668424 <tr>
669425 <th>
......@@ -711,7 +467,8 @@ Test 1/1 string literals...OK</code></pre>
711467 </tr>
712468 </table>
713469 <p>Note that the maximum valid Unicode point is <code>0x10ffff</code>.</p>
714 <h4 id="multiline-string-literals">Multiline String Literals</h4>
470 {#header_close#}
471 {#header_open|Multiline String Literals#}
715472 <p>
716473 Multiline string literals have no escapes and can span across multiple lines.
717474 To start a multiline string literal, use the <code>\\</code> token. Just like a comment,
......@@ -743,11 +500,10 @@ Test 1/1 string literals...OK</code></pre>
743500 In this example the variable <code>c_string_literal</code> has type <code>&amp;const char</code> and
744501 has a terminating null byte.
745502 </p>
746 <p>See also:</p>
747 <ul>
748 <li><a href="#builtin-embedFile">@embedFile</a></li>
749 </ul>
750 <h3 id="values-assignment">Assignment</h3>
503 {#see_also|@embedFile#}
504 {#header_close#}
505 {#header_close#}
506 {#header_open|Assignment#}
751507 <p>Use <code>const</code> to assign a value to an identifier:</p>
752508 <pre><code class="zig">const x = 1234;
753509
......@@ -798,14 +554,17 @@ test "init with undefined" {
798554}</code></pre>
799555 <pre><code class="sh">$ zig test test.zig
800556Test 1/1 init with undefined...OK</code></pre>
801 <h2 id="integers">Integers</h2>
802 <h3 id="integer-literals">Integer Literals</h3>
557 {#header_close#}
558 {#header_close#}
559 {#header_open|Integers#}
560 {#header_open|Integer Literals#}
803561 <pre><code class="zig">const decimal_int = 98222;
804562const hex_int = 0xff;
805563const another_hex_int = 0xFF;
806564const octal_int = 0o755;
807565const binary_int = 0b11110000;</code></pre>
808 <h3 id="runtime-integer-values">Runtime Integer Values</h3>
566 {#header_close#}
567 {#header_open|Runtime Integer Values#}
809568 <p>
810569 Integer literals have no size limitation, and if any undefined behavior occurs,
811570 the compiler catches it.
......@@ -827,14 +586,12 @@ const binary_int = 0b11110000;</code></pre>
827586 integer overflow. Also available are operations such as <code>+%</code> and
828587 <code>-%</code> which are defined to have wrapping arithmetic on all targets.
829588 </p>
830 <p>See also:</p>
831 <ul>
832 <li><a href="#undef-integer-overflow">Integer Overflow</a></li>
833 <li><a href="#undef-division-by-zero">Division By Zero</a></li>
834 <li><a href="#undef-int-overflow-wrap">Wrapping Operations</a></li>
835 </ul>
836 <h2 id="floats">Floats</h2>
837 <h3 id="float-literals">Float Literals</h3>
589 {#see_also|Integer Overflow|Division by Zero|Wrapping Operations#}
590 {#header_close#}
591 {#header_close#}
592 {#header_open|Floats#}
593 {#header_close#}
594 {#header_open|Float Literals#}
838595 <pre><code class="zig">const floating_point = 123.0E+77;
839596const another_float = 123.0;
840597const yet_another = 123.0e+77;
......@@ -842,7 +599,8 @@ const yet_another = 123.0e+77;
842599const hex_floating_point = 0x103.70p-5;
843600const another_hex_float = 0x103.70;
844601const yet_another_hex_float = 0x103.70P-5;</code></pre>
845 <h3 id="float-operations">Floating Point Operations</h3>
602 {#header_close#}
603 {#header_open|Floating Point Operations#}
846604 <p>By default floating point operations use <code>Optimized</code> mode,
847605 but you can switch to <code>Strict</code> mode on a per-block basis:</p>
848606 <p>foo.zig</p>
......@@ -876,13 +634,10 @@ $ zig build-exe test.zig --object foo.o
876634$ ./test
877635optimized = 1.0e-2
878636strict = 9.765625e-3</code></pre>
879 <p>See also:</p>
880 <ul>
881 <li><a href="#builtin-setFloatMode">@setFloatMode</a></li>
882 <li><a href="#undef-division-by-zero">Division By Zero</a></li>
883 </ul>
884 <h2 id="operators">Operators</h2>
885 <h3 id="operators-table">Table of Operators</h2>
637 {#see_also|@setFloatMode|Division by Zero#}
638 {#header_close#}
639 {#header_open|Operators#}
640 {#header_open|Table of Operators#}
886641 <table>
887642 <tr>
888643 <th>
......@@ -1470,7 +1225,8 @@ const ptr = &amp;x;
14701225 </td>
14711226 </tr>
14721227 </table>
1473 <h3 id="operators-precedence">Precedence</h3>
1228 {#header_close#}
1229 {#header_open|Precedence#}
14741230 <pre><code>x() x[] x.y
14751231!x -x -%x ~x *x &amp;x ?x %x %%x ??x
14761232x{}
......@@ -1485,7 +1241,9 @@ and
14851241or
14861242?? catch
14871243= *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>
1488 <h2 id="arrays">Arrays</h2>
1244 {#header_close#}
1245 {#header_close#}
1246 {#header_open|Arrays#}
14891247 <pre><code class="zig">const assert = @import("std").debug.assert;
14901248const mem = @import("std").mem;
14911249
......@@ -1594,12 +1352,9 @@ Test 1/4 iterate over an array...OK
15941352Test 2/4 modify an array...OK
15951353Test 3/4 compile-time array initalization...OK
15961354Test 4/4 array initialization with function calls...OK</code></pre>
1597 <p>See also:</p>
1598 <ul>
1599 <li><a href="#for">for</a></li>
1600 <li><a href="#slices">Slices</a></li>
1601 </ul>
1602 <h2 id="pointers">Pointers</h2>
1355 {#see_also|for|Slices#}
1356 {#header_close#}
1357 {#header_open|Pointers#}
16031358 <pre><code class="zig">const assert = @import("std").debug.assert;
16041359
16051360test "address of syntax" {
......@@ -1737,7 +1492,7 @@ Test 5/8 volatile...OK
17371492Test 6/8 nullable pointers...OK
17381493Test 7/8 pointer casting...OK
17391494Test 8/8 pointer child type...OK</code></pre>
1740 <h3 id="alignment">Alignment</h3>
1495 {#header_open|Alignment#}
17411496 <p>
17421497 Each type has an <strong>alignment</strong> - a number of bytes such that,
17431498 when a value of the type is loaded from or stored to memory,
......@@ -1838,7 +1593,8 @@ Test 1/1 pointer alignment safety...incorrect alignment
18381593
18391594Tests failed. Use the following command to reproduce the failure:
18401595./test</code></pre>
1841 <h3 id="type-based-alias-analysis">Type Based Alias Analysis</h3>
1596 {#header_close#}
1597 {#header_open|Type Based Alias Analysis#}
18421598 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
18431599 perform some optimizations. This means that pointers of different types must
18441600 not alias the same memory, with the exception of <code>u8</code>. Pointers to
......@@ -1849,12 +1605,10 @@ Tests failed. Use the following command to reproduce the failure:
18491605 <p>Instead, use <a href="#builtin-bitCast">@bitCast</a>:
18501606 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
18511607 <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>
1852 <p>See also:</p>
1853 <ul>
1854 <li><a href="#slices">Slices</a></li>
1855 <li><a href="#memory">Memory</a></li>
1856 </ul>
1857 <h2 id="slices">Slices</h2>
1608 {#see_also|Slices|Memory#}
1609 {#header_close#}
1610 {#header_close#}
1611 {#header_open|Slices#}
18581612 <pre><code class="zig">const assert = @import("std").debug.assert;
18591613
18601614test "basic slices" {
......@@ -1948,13 +1702,9 @@ test "slice widening" {
19481702Test 1/3 using slices for strings...OK
19491703Test 2/3 slice pointer...OK
19501704Test 3/3 slice widening...OK</code></pre>
1951 <p>See also:</p>
1952 <ul>
1953 <li><a href="#pointers">Pointers</a></li>
1954 <li><a href="#for">for</a></li>
1955 <li><a href="#arrays">Arrays</a></li>
1956 </ul>
1957 <h2 id="struct">struct</h2>
1705 {#see_also|Pointers|for|Arrays#}
1706 {#header_close#}
1707 {#header_open|struct#}
19581708 <pre><code class="zig">// Declare a struct.
19591709// Zig gives no guarantees about the order of fields and whether or
19601710// not there will be padding.
......@@ -2094,12 +1844,9 @@ Test 1/4 dot product...OK
20941844Test 2/4 struct namespaced variable...OK
20951845Test 3/4 field parent pointer...OK
20961846Test 4/4 linked list...OK</code></pre>
2097 <p>See also:</p>
2098 <ul>
2099 <li><a href="#comptime">comptime</a></li>
2100 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
2101 </ul>
2102 <h2 id="enum">enum</h2>
1847 {#see_also|comptime|@fieldParentPtr#}
1848 {#header_close#}
1849 {#header_open|enum#}
21031850 <pre><code class="zig">const assert = @import("std").debug.assert;
21041851const mem = @import("std").mem;
21051852
......@@ -2210,13 +1957,9 @@ Test 5/8 @TagType...OK
22101957Test 6/8 @memberCount...OK
22111958Test 7/8 @memberName...OK
22121959Test 8/8 @tagName...OK</code></pre>
2213 <p>See also:</p>
2214 <ul>
2215 <li><a href="#builtin-memberName">@memberName</a></li>
2216 <li><a href="#builtin-memberCount">@memberCount</a></li>
2217 <li><a href="#builtin-tagName">@tagName</a></li>
2218 </ul>
2219 <h2 id="union">union</h2>
1960 {#see_also|@memberName|@memberCount|@tagName#}
1961 {#header_close#}
1962 {#header_open|union#}
22201963 <pre><code class="zig">const assert = @import("std").debug.assert;
22211964const mem = @import("std").mem;
22221965
......@@ -2323,7 +2066,8 @@ Test 7/7 @tagName...OK</code></pre>
23232066 Unions with an enum tag are generated as a struct with a tag field and union field. Zig
23242067 sorts the order of the tag and union field by the largest alignment.
23252068 </p>
2326 <h2 id="switch">switch</h2>
2069 {#header_close#}
2070 {#header_open|switch#}
23272071 <pre><code class="zig">const assert = @import("std").debug.assert;
23282072const builtin = @import("builtin");
23292073
......@@ -2419,14 +2163,9 @@ test "switch inside function" {
24192163Test 1/2 switch simple...OK
24202164Test 2/2 switch enum...OK
24212165Test 3/3 switch inside function...OK</code></pre>
2422 <p>See also:</p>
2423 <ul>
2424 <li><a href="#comptime">comptime</a></li>
2425 <li><a href="#enum">enum</a></li>
2426 <li><a href="#builtin-compileError">@compileError</a></li>
2427 <li><a href="#compile-variables">Compile Variables</a></li>
2428 </ul>
2429 <h2 id="while">while</h2>
2166 {#see_also|comptime|enum|@compileError|Compile Variables#}
2167 {#header_close#}
2168 {#header_open|while#}
24302169 <pre><code class="zig">const assert = @import("std").debug.assert;
24312170
24322171test "while basic" {
......@@ -2587,15 +2326,9 @@ Test 5/8 while loop continuation expression, more complicated...OK
25872326Test 6/8 while else...OK
25882327Test 7/8 while null capture...OK
25892328Test 8/8 inline while loop...OK</code></pre>
2590 <p>See also:</p>
2591 <ul>
2592 <li><a href="#if">if</a></li>
2593 <li><a href="#nullables">Nullables</a></li>
2594 <li><a href="#errors">Errors</a></li>
2595 <li><a href="#comptime">comptime</a></li>
2596 <li><a href="#unreachable">unreachable</a></li>
2597 </ul>
2598 <h2 id="for">for</h2>
2329 {#see_also|if|Nullables|Errors|comptime|unreachable#}
2330 {#header_close#}
2331 {#header_open|for#}
25992332 <pre><code class="zig">const assert = @import("std").debug.assert;
26002333
26012334test "for basics" {
......@@ -2689,14 +2422,9 @@ Test 1/4 for basics...OK
26892422Test 2/4 for reference...OK
26902423Test 3/4 for else...OK
26912424Test 4/4 inline for loop...OK</code></pre>
2692 <p>See also:</p>
2693 <ul>
2694 <li><a href="#while">while</a></li>
2695 <li><a href="#comptime">comptime</a></li>
2696 <li><a href="#arrays">Arrays</a></li>
2697 <li><a href="#slices">Slices</a></li>
2698 </ul>
2699 <h2 id="if">if</h2>
2425 {#see_also|while|comptime|Arrays|Slices#}
2426 {#header_close#}
2427 {#header_open|if#}
27002428 <pre><code class="zig">// If expressions have three uses, corresponding to the three types:
27012429// * bool
27022430// * ?T
......@@ -2809,28 +2537,9 @@ test "if error union" {
28092537Test 1/3 if boolean...OK
28102538Test 2/3 if nullable...OK
28112539Test 3/3 if error union...OK</code></pre>
2812 <p>See also:</p>
2813 <ul>
2814 <li><a href="#nullables">Nullables</a></li>
2815 <li><a href="#errors">Errors</a></li>
2816 </ul>
2817 <h2 id="goto">goto</h2>
2818 <pre><code class="zig">const assert = @import("std").debug.assert;
2819
2820test "goto" {
2821 var value = false;
2822 goto label;
2823 value = true;
2824
2825label:
2826 assert(value == false);
2827}
2828</code></pre>
2829 <pre><code class="sh">$ zig test goto.zig
2830Test 1/1 goto...OK
2831</code></pre>
2832<p>Note that there are <a href="https://github.com/zig-lang/zig/issues/346">plans to remove goto</a></p>
2833 <h2 id="defer">defer</h2>
2540 {#see_also|Nullables|Errors#}
2541 {#header_close#}
2542 {#header_open|defer#}
28342543 <pre><code class="zig">const assert = @import("std").debug.assert;
28352544const printf = @import("std").io.stdout.printf;
28362545
......@@ -2916,11 +2625,9 @@ encountered an error!
29162625end of function
29172626OK
29182627</code></pre>
2919 <p>See also:</p>
2920 <ul>
2921 <li><a href="#errors">Errors</a></li>
2922 </ul>
2923 <h2 id="unreachable">unreachable</h2>
2628 {#see_also|Errors#}
2629 {#header_close#}
2630 {#header_open|unreachable#}
29242631 <p>
29252632 In <code>Debug</code> and <code>ReleaseSafe</code> mode, and when using <code>zig test</code>,
29262633 <code>unreachable</code> emits a call to <code>panic</code> with the message <code>reached unreachable code</code>.
......@@ -2930,7 +2637,7 @@ OK
29302637 will never be hit to perform optimizations. However, <code>zig test</code> even in <code>ReleaseFast</code> mode
29312638 still emits <code>unreachable</code> as calls to <code>panic</code>.
29322639 </p>
2933 <h3 id="unreachable-basics">Basics</h3>
2640 {#header_open|Basics#}
29342641 <pre><code class="zig">// unreachable is used to assert that control flow will never happen upon a
29352642// particular location:
29362643test "basic math" {
......@@ -2974,7 +2681,8 @@ lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test)
29742681
29752682Tests failed. Use the following command to reproduce the failure:
29762683./test</code></pre>
2977 <h3 id="unreachable-comptime">At Compile-Time</h3>
2684 {#header_close#}
2685 {#header_open|At Compile-Time#}
29782686 <pre><code class="zig">const assert = @import("std").debug.assert;
29792687
29802688comptime {
......@@ -2989,13 +2697,10 @@ comptime {
29892697test.zig:9:12: error: unreachable code
29902698 assert(@typeOf(unreachable) == noreturn);
29912699 ^</code></pre>
2992 <p>See also:</p>
2993 <ul>
2994 <li><a href="#zig-test">Zig Test</a></li>
2995 <li><a href="#build-mode">Build Mode</a></li>
2996 <li><a href="#comptime">comptime</a></li>
2997 </ul>
2998 <h2 id="noreturn">noreturn</h2>
2700 {#see_also|Zig Test|Build Mode|comptime#}
2701 {#header_close#}
2702 {#header_close#}
2703 {#header_open|noreturn#}
29992704 <p>
30002705 <code>noreturn</code> is the type of:
30012706 </p>
......@@ -3029,7 +2734,8 @@ fn bar() -&gt; %u32 {
30292734}
30302735
30312736const assert = @import("std").debug.assert;</code></pre>
3032 <h2 id="functions">Functions</h2>
2737 {#header_close#}
2738 {#header_open|Functions#}
30332739 <pre><code class="zig">const assert = @import("std").debug.assert;
30342740
30352741// Functions are declared like this
......@@ -3091,7 +2797,7 @@ comptime {
30912797
30922798fn foo() { }</code></pre>
30932799 <pre><code class="sh">$ zig build-obj test.zig</code></pre>
3094 <h3 id="functions-by-val-params">Pass-by-value Parameters</h3>
2800 {#header_open|Pass-by-value Parameters#}
30952801 <p>
30962802 In Zig, structs, unions, and enums with payloads cannot be passed by value
30972803 to a function.
......@@ -3127,7 +2833,9 @@ export fn entry() {
31272833 the C ABI does allow passing structs and unions by value. So functions which
31282834 use the C calling convention may pass structs and unions by value.
31292835 </p>
3130 <h2 id="errors">Errors</h2>
2836 {#header_close#}
2837 {#header_close#}
2838 {#header_open|Errors#}
31312839 <p>
31322840 One of the distinguishing features of Zig is its exception handling strategy.
31332841 </p>
......@@ -3315,13 +3023,9 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
33153023 in other languages.
33163024 </li>
33173025 </ul>
3318 <p>See also:</p>
3319 <ul>
3320 <li><a href="#defer">defer</a></li>
3321 <li><a href="#if">if</a></li>
3322 <li><a href="#switch">switch</a></li>
3323 </ul>
3324 <h2 id="nullables">Nullables</h2>
3026 {#see_also|defer|if|switch#}
3027 {#header_close#}
3028 {#header_open|Nullables#}
33253029 <p>
33263030 One area that Zig provides safety without compromising efficiency or
33273031 readability is with the nullable type.
......@@ -3415,7 +3119,8 @@ fn doAThing() -&gt; ?&amp;Foo {
34153119 The optimizer can sometimes make better decisions knowing that pointer arguments
34163120 cannot be null.
34173121 </p>
3418 <h2 id="casting">Casting</h2>
3122 {#header_close#}
3123 {#header_open|Casting#}
34193124 <p>TODO: explain implicit vs explicit casting</p>
34203125 <p>TODO: resolve peer types builtin</p>
34213126 <p>TODO: truncate builtin</p>
......@@ -3424,24 +3129,27 @@ fn doAThing() -&gt; ?&amp;Foo {
34243129 <p>TODO: ptr to int builtin</p>
34253130 <p>TODO: ptrcast builtin</p>
34263131 <p>TODO: explain number literals vs concrete types</p>
3427 <h2 id="void">void</h2>
3132 {#header_close#}
3133 {#header_open|void#}
34283134 <p>TODO: assigning void has no codegen</p>
34293135 <p>TODO: hashmap with void becomes a set</p>
34303136 <p>TODO: difference between c_void and void</p>
34313137 <p>TODO: void is the default return value of functions</p>
34323138 <p>TODO: functions require assigning the return value</p>
3433 <h2 id="this">this</h2>
3139 {#header_close#}
3140 {#header_open|this#}
34343141 <p>TODO: example of this referring to Self struct</p>
34353142 <p>TODO: example of this referring to recursion function</p>
34363143 <p>TODO: example of this referring to basic block for @setDebugSafety</p>
3437 <h2 id="comptime">comptime</h2>
3144 {#header_close#}
3145 {#header_open|comptime#}
34383146 <p>
34393147 Zig places importance on the concept of whether an expression is known at compile-time.
34403148 There are a few different places this concept is used, and these building blocks are used
34413149 to keep the language small, readable, and powerful.
34423150 </p>
3443 <h3 id="introducing-compile-time-concept">Introducing the Compile-Time Concept</h3>
3444 <h4 id="compile-time-parameters">Compile-Time Parameters</h4>
3151 {#header_open|Introducing the Compile-Time Concept#}
3152 {#header_open|Compile-Time Parameters#}
34453153 <p>
34463154 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
34473155 </p>
......@@ -3549,7 +3257,8 @@ fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool {
35493257 This works the same way for <code>switch</code> expressions - they are implicitly inlined
35503258 when the target expression is compile-time known.
35513259 </p>
3552 <h4 id="compile-time-variables">Compile-Time Variables</h4>
3260 {#header_close#}
3261 {#header_open|Compile-Time Variables#}
35533262 <p>
35543263 In Zig, the programmer can label variables as <code>comptime</code>. This guarantees to the compiler
35553264 that every load and store of the variable is performed at compile-time. Any violation of this results in a
......@@ -3631,7 +3340,8 @@ fn performFn(start_value: i32) -&gt; i32 {
36313340 later in this article, allows expressiveness that in other languages requires using macros,
36323341 generated code, or a preprocessor to accomplish.
36333342 </p>
3634 <h4 id="compile-time-expressions">Compile-Time Expressions</h4>
3343 {#header_close#}
3344 {#header_open|Compile-Time Expressions#}
36353345 <p>
36363346 In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can
36373347 use a <code>comptime</code> expression to guarantee that the expression will be evaluated at compile-time.
......@@ -3860,7 +3570,9 @@ fn sum(numbers: []i32) -&gt; i32 {
38603570 we could call the <code>sum</code> function as is with a slice of numbers whose length and values were
38613571 only known at run-time.
38623572 </p>
3863 <h3 id="generic-data-structures">Generic Data Structures</h3>
3573 {#header_close#}
3574 {#header_close#}
3575 {#header_open|Generic Data Structures#}
38643576 <p>
38653577 Zig uses these capabilities to implement generic data structures without introducing any
38663578 special-case syntax. If you followed along so far, you may already know how to create a
......@@ -3895,19 +3607,21 @@ fn sum(numbers: []i32) -&gt; i32 {
38953607 <code>Node</code> refers to itself as a pointer, which is not actually an infinite regression, so
38963608 it works fine.
38973609 </p>
3898 <h3 id="case-study-printf">Case Study: printf in Zig</h3>
3610 {#header_close#}
3611 {#header_open|Case Study: printf in Zig#}
38993612 <p>
3900 Putting all of this together, let's seee how <code>printf</code> works in Zig.
3613 Putting all of this together, let's see how <code>printf</code> works in Zig.
39013614 </p>
3902 <pre><code class="zig">const warn = @import("std").debug.warn;
3615 {#code_begin|exe|printf#}
3616const warn = @import("std").debug.warn;
39033617
39043618const a_number: i32 = 1234;
39053619const a_string = "foobar";
39063620
3907pub fn main(args: [][]u8) -&gt; %void {
3621pub fn main() {
39083622 warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
3909}</code></pre>
3910 <pre><code>here is a string: 'foobar' here is a number: 1234</code></pre>
3623}
3624 {#code_end#}
39113625
39123626 <p>
39133627 Let's crack open the implementation of this and see how it works:
......@@ -4027,15 +3741,17 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt
40273741 Zig doesn't care whether the format argument is a string literal,
40283742 only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:
40293743 </p>
4030 <pre><code class="zig">const warn = @import("std").debug.warn;
3744 {#code_begin|exe|printf#}
3745const warn = @import("std").debug.warn;
40313746
40323747const a_number: i32 = 1234;
40333748const a_string = "foobar";
40343749const fmt = "here is a string: '{}' here is a number: {}\n";
40353750
4036pub fn main(args: [][]u8) -&gt; %void {
3751pub fn main() {
40373752 warn(fmt, a_string, a_number);
4038}</code></pre>
3753}
3754 {#code_end#}
40393755 <p>
40403756 This works fine.
40413757 </p>
......@@ -4045,35 +3761,42 @@ pub fn main(args: [][]u8) -&gt; %void {
40453761 a macro language or a preprocessor language. It's Zig all the way down.
40463762 </p>
40473763 <p>TODO: suggestion to not use inline unless necessary</p>
4048 <h2 id="inline">inline</h2>
3764 {#header_close#}
3765 {#header_close#}
3766 {#header_open|inline#}
40493767 <p>TODO: inline while</p>
40503768 <p>TODO: inline for</p>
40513769 <p>TODO: suggestion to not use inline unless necessary</p>
4052 <h2 id="assembly">Assembly</h2>
3770 {#header_close#}
3771 {#header_open|Assembly#}
40533772 <p>TODO: example of inline assembly</p>
40543773 <p>TODO: example of module level assembly</p>
40553774 <p>TODO: example of using inline assembly return value</p>
40563775 <p>TODO: example of using inline assembly assigning values to variables</p>
4057 <h2 id="atomics">Atomics</h2>
3776 {#header_close#}
3777 {#header_open|Atomics#}
40583778 <p>TODO: @fence()</p>
40593779 <p>TODO: @atomic rmw</p>
40603780 <p>TODO: builtin atomic memory ordering enum</p>
4061 <h2 id="builtin-functions">Builtin Functions</h2>
3781 {#header_close#}
3782 {#header_open|Builtin Functions#}
40623783 <p>
40633784 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
40643785 The <code>comptime</code> keyword on a parameter means that the parameter must be known
40653786 at compile time.
40663787 </p>
4067 <h3 id="builtin-addWithOverflow">@addWithOverflow</h3>
3788 {#header_open|@addWithOverflow#}
40683789 <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
40693790 <p>
40703791 Performs <code>*result = a + b</code>. If overflow or underflow occurs,
40713792 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
40723793 If no overflow or underflow occurs, returns <code>false</code>.
40733794 </p>
4074 <h3 id="builtin-ArgType">@ArgType</h3>
3795 {#header_close#}
3796 {#header_open|@ArgType#}
40753797 <p>TODO</p>
4076 <h3 id="builtin-bitCast">@bitCast</h3>
3798 {#header_close#}
3799 {#header_open|@bitCast#}
40773800 <pre><code class="zig">@bitCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
40783801 <p>
40793802 Converts a value of one type to another type.
......@@ -4094,7 +3817,8 @@ pub fn main(args: [][]u8) -&gt; %void {
40943817 <p>
40953818 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.
40963819 </p>
4097 <h3 id="builtin-breakpoint">@breakpoint</h3>
3820 {#header_close#}
3821 {#header_open|@breakpoint#}
40983822 <pre><code class="zig">@breakpoint()</code></pre>
40993823 <p>
41003824 This function inserts a platform-specific debug trap instruction which causes
......@@ -4104,7 +3828,8 @@ pub fn main(args: [][]u8) -&gt; %void {
41043828 This function is only valid within function scope.
41053829 </p>
41063830
4107 <h3 id="builtin-alignCast">@alignCast</h3>
3831 {#header_close#}
3832 {#header_open|@alignCast#}
41083833 <pre><code class="zig">@alignCast(comptime alignment: u29, ptr: var) -&gt; var</code></pre>
41093834 <p>
41103835 <code>ptr</code> can be <code>&amp;T</code>, <code>fn()</code>, <code>?&amp;T</code>,
......@@ -4114,7 +3839,8 @@ pub fn main(args: [][]u8) -&gt; %void {
41143839 <p>A <a href="#undef-incorrect-pointer-alignment">pointer alignment safety check</a> is added
41153840 to the generated code to make sure the pointer is aligned as promised.</p>
41163841
4117 <h3 id="builtin-alignOf">@alignOf</h3>
3842 {#header_close#}
3843 {#header_open|@alignOf#}
41183844 <pre><code class="zig">@alignOf(comptime T: type) -&gt; (number literal)</code></pre>
41193845 <p>
41203846 This function returns the number of bytes that this type should be aligned to
......@@ -4129,12 +3855,9 @@ comptime {
41293855 The result is a target-specific compile time constant. It is guaranteed to be
41303856 less than or equal to <a href="#builtin-sizeOf">@sizeOf(T)</a>.
41313857 </p>
4132 <p>See also:</p>
4133 <ul>
4134 <li><a href="#alignment">Alignment</a></li>
4135 </ul>
4136
4137 <h3 id="builtin-cDefine">@cDefine</h3>
3858 {#see_also|Alignment#}
3859 {#header_close#}
3860 {#header_open|@cDefine#}
41383861 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>
41393862 <p>
41403863 This function can only occur inside <code>@cImport</code>.
......@@ -4151,15 +3874,9 @@ comptime {
41513874 Use the void value, like this:
41523875 </p>
41533876 <pre><code class="zig">@cDefine("_GNU_SOURCE", {})</code></pre>
4154 <p>See also:</p>
4155 <ul>
4156 <li><a href="#c-import">Import from C Header File</a></li>
4157 <li><a href="#builtin-cInclude">@cInclude</a></li>
4158 <li><a href="#builtin-cImport">@cImport</a></li>
4159 <li><a href="#builtin-cUndef">@cUndef</a></li>
4160 <li><a href="#void">void</a></li>
4161 </ul>
4162 <h3 id="builtin-cImport">@cImport</h3>
3877 {#see_also|Import from C Header File|@cInclude|@cImport|@cUndef|void#}
3878 {#header_close#}
3879 {#header_open|@cImport#}
41633880 <pre><code class="zig">@cImport(expression) -&gt; (namespace)</code></pre>
41643881 <p>
41653882 This function parses C code and imports the functions, types, variables, and
......@@ -4170,14 +3887,9 @@ comptime {
41703887 <code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work
41713888 within this expression, appending to a temporary buffer which is then parsed as C code.
41723889 </p>
4173 <p>See also:</p>
4174 <ul>
4175 <li><a href="#c-import">Import from C Header File</a></li>
4176 <li><a href="#builtin-cInclude">@cInclude</a></li>
4177 <li><a href="#builtin-cDefine">@cDefine</a></li>
4178 <li><a href="#builtin-cUndef">@cUndef</a></li>
4179 </ul>
4180 <h3 id="builtin-cInclude">@cInclude</h3>
3890 {#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}
3891 {#header_close#}
3892 {#header_open|@cInclude#}
41813893 <pre><code class="zig">@cInclude(comptime path: []u8)</code></pre>
41823894 <p>
41833895 This function can only occur inside <code>@cImport</code>.
......@@ -4186,14 +3898,9 @@ comptime {
41863898 This appends <code>#include <$path>\n</code> to the <code>c_import</code>
41873899 temporary buffer.
41883900 </p>
4189 <p>See also:</p>
4190 <ul>
4191 <li><a href="#c-import">Import from C Header File</a></li>
4192 <li><a href="#builtin-cImport">@cImport</a></li>
4193 <li><a href="#builtin-cDefine">@cDefine</a></li>
4194 <li><a href="#builtin-cUndef">@cUndef</a></li>
4195 </ul>
4196 <h3 id="builtin-cUndef">@cUndef</h3>
3901 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
3902 {#header_close#}
3903 {#header_open|@cUndef#}
41973904 <pre><code class="zig">@cUndef(comptime name: []u8)</code></pre>
41983905 <p>
41993906 This function can only occur inside <code>@cImport</code>.
......@@ -4202,19 +3909,15 @@ comptime {
42023909 This appends <code>#undef $name</code> to the <code>@cImport</code>
42033910 temporary buffer.
42043911 </p>
4205 <p>See also:</p>
4206 <ul>
4207 <li><a href="#c-import">Import from C Header File</a></li>
4208 <li><a href="#builtin-cImport">@cImport</a></li>
4209 <li><a href="#builtin-cDefine">@cDefine</a></li>
4210 <li><a href="#builtin-cInclude">@cInclude</a></li>
4211 </ul>
4212 <h3 id="builtin-canImplicitCast">@canImplicitCast</h3>
3912 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
3913 {#header_close#}
3914 {#header_open|@canImplicitCast#}
42133915 <pre><code class="zig">@canImplicitCast(comptime T: type, value) -&gt; bool</code></pre>
42143916 <p>
42153917 Returns whether a value can be implicitly casted to a given type.
42163918 </p>
4217 <h3 id="builtin-clz">@clz</h3>
3919 {#header_close#}
3920 {#header_open|@clz#}
42183921 <pre><code class="zig">@clz(x: T) -&gt; U</code></pre>
42193922 <p>
42203923 This function counts the number of leading zeroes in <code>x</code> which is an integer
......@@ -4228,7 +3931,8 @@ comptime {
42283931 If <code>x</code> is zero, <code>@clz</code> returns <code>T.bit_count</code>.
42293932 </p>
42303933
4231 <h3 id="builtin-cmpxchg">@cmpxchg</h3>
3934 {#header_close#}
3935 {#header_open|@cmpxchg#}
42323936 <pre><code class="zig">@cmpxchg(ptr: &amp;T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -&gt; bool</code></pre>
42333937 <p>
42343938 This function performs an atomic compare exchange operation.
......@@ -4237,12 +3941,9 @@ comptime {
42373941 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.
42383942 </p>
42393943 <p><code>@typeOf(ptr).alignment</code> must be <code>&gt;= @sizeOf(T).</code></p>
4240 <p>See also:</p>
4241 <ul>
4242 <li><a href="#compile-variables">Compile Variables</a></li>
4243 </ul>
4244
4245 <h3 id="builtin-compileError">@compileError</h3>
3944 {#see_also|Compile Variables#}
3945 {#header_close#}
3946 {#header_open|@compileError#}
42463947 <pre><code class="zig">@compileError(comptime msg: []u8)</code></pre>
42473948 <p>
42483949 This function, when semantically analyzed, causes a compile error with the
......@@ -4253,7 +3954,8 @@ comptime {
42533954 using <code>if</code> or <code>switch</code> with compile time constants,
42543955 and <code>comptime</code> functions.
42553956 </p>
4256 <h3 id="builtin-compileLog">@compileLog</h3>
3957 {#header_close#}
3958 {#header_open|@compileLog#}
42573959 <pre><code class="zig">@compileLog(args: ...)</code></pre>
42583960 <p>
42593961 This function prints the arguments passed to it at compile-time.
......@@ -4303,7 +4005,7 @@ test.zig:6:2: error: found compile log statement
43034005 program compiles successfully and the generated executable prints:
43044006 </p>
43054007<pre><code class="sh">Runtime in main, num1 = 100.</code></pre>
4306 <h3 id="builtin-ctz">@ctz</h3>
4008{{@ctheader_open:z}}
43074009 <pre><code class="zig">@ctz(x: T) -&gt; U</code></pre>
43084010 <p>
43094011 This function counts the number of trailing zeroes in <code>x</code> which is an integer
......@@ -4316,7 +4018,8 @@ test.zig:6:2: error: found compile log statement
43164018 <p>
43174019 If <code>x</code> is zero, <code>@ctz</code> returns <code>T.bit_count</code>.
43184020 </p>
4319 <h3 id="builtin-divExact">@divExact</h3>
4021 {#header_close#}
4022 {#header_open|@divExact#}
43204023 <pre><code class="zig">@divExact(numerator: T, denominator: T) -&gt; T</code></pre>
43214024 <p>
43224025 Exact division. Caller guarantees <code>denominator != 0</code> and
......@@ -4326,13 +4029,10 @@ test.zig:6:2: error: found compile log statement
43264029 <li><code>@divExact(6, 3) == 2</code></li>
43274030 <li><code>@divExact(a, b) * b == a</code></li>
43284031 </ul>
4329 <p>See also:</p>
4330 <ul>
4331 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
4332 <li><a href="#builtin-divFloor">@divFloor</a></li>
4333 <li><code>@import("std").math.divExact</code></li>
4334 </ul>
4335 <h3 id="builtin-divFloor">@divFloor</h3>
4032 <p>For a function that returns a possible error code, use <code>@import("std").math.divExact</code>.</p>
4033 {#see_also|@divTrunc|@divFloor#}
4034 {#header_close#}
4035 {#header_open|@divFloor#}
43364036 <pre><code class="zig">@divFloor(numerator: T, denominator: T) -&gt; T</code></pre>
43374037 <p>
43384038 Floored division. Rounds toward negative infinity. For unsigned integers it is
......@@ -4343,13 +4043,10 @@ test.zig:6:2: error: found compile log statement
43434043 <li><code>@divFloor(-5, 3) == -2</code></li>
43444044 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
43454045 </ul>
4346 <p>See also:</p>
4347 <ul>
4348 <li><a href="#builtin-divTrunc">@divTrunc</a></li>
4349 <li><a href="#builtin-divExact">@divExact</a></li>
4350 <li><code>@import("std").math.divFloor</code></li>
4351 </ul>
4352 <h3 id="builtin-divTrunc">@divTrunc</h3>
4046 <p>For a function that returns a possible error code, use <code>@import("std").math.divFloor</code>.</p>
4047 {#see_also|@divTrunc|@divExact#}
4048 {#header_close#}
4049 {#header_open|@divTrunc#}
43534050 <pre><code class="zig">@divTrunc(numerator: T, denominator: T) -&gt; T</code></pre>
43544051 <p>
43554052 Truncated division. Rounds toward zero. For unsigned integers it is
......@@ -4360,13 +4057,10 @@ test.zig:6:2: error: found compile log statement
43604057 <li><code>@divTrunc(-5, 3) == -1</code></li>
43614058 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
43624059 </ul>
4363 <p>See also:</p>
4364 <ul>
4365 <li><a href="#builtin-divFloor">@divFloor</a></li>
4366 <li><a href="#builtin-divExact">@divExact</a></li>
4367 <li><code>@import("std").math.divTrunc</code></li>
4368 </ul>
4369 <h3 id="builtin-embedFile">@embedFile</h3>
4060 <p>For a function that returns a possible error code, use <code>@import("std").math.divTrunc</code>.</p>
4061 {#see_also|@divFloor|@divExact#}
4062 {#header_close#}
4063 {#header_open|@embedFile#}
43704064 <pre><code class="zig">@embedFile(comptime path: []const u8) -&gt; [X]u8</code></pre>
43714065 <p>
43724066 This function returns a compile time constant fixed-size array with length
......@@ -4376,21 +4070,21 @@ test.zig:6:2: error: found compile log statement
43764070 <p>
43774071 <code>path</code> is absolute or relative to the current file, just like <code>@import</code>.
43784072 </p>
4379 <p>See also:</p>
4380 <ul>
4381 <li><a href="#builtin-import">@import</a></li>
4382 </ul>
4383 <h3 id="builtin-export">@export</h3>
4073 {#see_also|@import#}
4074 {#header_close#}
4075 {#header_open|@export#}
43844076 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) -&gt; []const u8</code></pre>
43854077 <p>
43864078 Creates a symbol in the output object file.
43874079 </p>
4388 <h3 id="builtin-tagName">@tagName</h3>
4080 {#header_close#}
4081 {#header_open|@tagName#}
43894082 <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre>
43904083 <p>
43914084 Converts an enum value or union value to a slice of bytes representing the name.
43924085 </p>
4393 <h3 id="builtin-TagType">@TagType</h3>
4086 {#header_close#}
4087 {#header_open|@TagType#}
43944088 <pre><code class="zig">@TagType(T: type) -&gt; type</code></pre>
43954089 <p>
43964090 For an enum, returns the integer type that is used to store the enumeration value.
......@@ -4398,7 +4092,8 @@ test.zig:6:2: error: found compile log statement
43984092 <p>
43994093 For a union, returns the enum type that is used to store the tag value.
44004094 </p>
4401 <h3 id="builtin-errorName">@errorName</h3>
4095 {#header_close#}
4096 {#header_open|@errorName#}
44024097 <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre>
44034098 <p>
44044099 This function returns the string representation of an error. If an error
......@@ -4413,14 +4108,16 @@ test.zig:6:2: error: found compile log statement
44134108 or all calls have a compile-time known value for <code>err</code>, then no
44144109 error name table will be generated.
44154110 </p>
4416 <h3 id="builtin-errorReturnTrace">@errorReturnTrace</h3>
4111 {#header_close#}
4112 {#header_open|@errorReturnTrace#}
44174113 <pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre>
44184114 <p>
44194115 If the binary is built with error return tracing, and this function is invoked in a
44204116 function that calls a function with an error or error union return type, returns a
44214117 stack trace object. Otherwise returns `null`.
44224118 </p>
4423 <h3 id="builtin-fence">@fence</h3>
4119 {#header_close#}
4120 {#header_open|@fence#}
44244121 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
44254122 <p>
44264123 The <code>fence</code> function is used to introduce happens-before edges between operations.
......@@ -4428,17 +4125,16 @@ test.zig:6:2: error: found compile log statement
44284125 <p>
44294126 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.
44304127 </p>
4431 <p>See also:</p>
4432 <ul>
4433 <li><a href="#compile-variables">Compile Variables</a></li>
4434 </ul>
4435 <h3 id="builtin-fieldParentPtr">@fieldParentPtr</h3>
4128 {#see_also|Compile Variables#}
4129 {#header_close#}
4130 {#header_open|@fieldParentPtr#}
44364131 <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
44374132 field_ptr: &amp;T) -&gt; &amp;ParentType</code></pre>
44384133 <p>
44394134 Given a pointer to a field, returns the base pointer of a struct.
44404135 </p>
4441 <h3 id="builtin-frameAddress">@frameAddress</h3>
4136 {#header_close#}
4137 {#header_open|@frameAddress#}
44424138 <pre><code class="zig">@frameAddress()</code></pre>
44434139 <p>
44444140 This function returns the base pointer of the current stack frame.
......@@ -4451,7 +4147,8 @@ test.zig:6:2: error: found compile log statement
44514147 <p>
44524148 This function is only valid within function scope.
44534149 </p>
4454 <h3 id="builtin-import">@import</h3>
4150 {#header_close#}
4151 {#header_open|@import#}
44554152 <pre><code class="zig">@import(comptime path: []u8) -&gt; (namespace)</code></pre>
44564153 <p>
44574154 This function finds a zig file corresponding to <code>path</code> and imports all the
......@@ -4469,12 +4166,9 @@ test.zig:6:2: error: found compile log statement
44694166 <li><code>@import("std")</code> - Zig Standard Library</li>
44704167 <li><code>@import("builtin")</code> - Compiler-provided types and variables</li>
44714168 </ul>
4472 <p>See also:</p>
4473 <ul>
4474 <li><a href="#compile-variables">Compile Variables</a></li>
4475 <li><a href="#builtin-embedFile">@embedFile</a></li>
4476 </ul>
4477 <h3 id="builtin-inlineCall">@inlineCall</h3>
4169 {#see_also|Compile Variables|@embedFile#}
4170 {#header_close#}
4171 {#header_open|@inlineCall#}
44784172 <pre><code class="zig">@inlineCall(function: X, args: ...) -&gt; Y</code></pre>
44794173 <p>
44804174 This calls a function, in the same way that invoking an expression with parentheses does:
......@@ -4489,21 +4183,21 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
44894183 Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call
44904184 will be inlined. If the call cannot be inlined, a compile error is emitted.
44914185 </p>
4492 <p>See also:</p>
4493 <ul>
4494 <li><a href="#builtin-noInlineCall">@noInlineCall</a></li>
4495 </ul>
4496 <h3 id="builtin-intToPtr">@intToPtr</h3>
4186 {#see_also|@noInlineCall#}
4187 {#header_close#}
4188 {#header_open|@intToPtr#}
44974189 <pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) -&gt; DestType</code></pre>
44984190 <p>
44994191 Converts an integer to a pointer. To convert the other way, use <a href="#builtin-ptrToInt">@ptrToInt</a>.
45004192 </p>
4501 <h3 id="builtin-IntType">@IntType</h3>
4193 {#header_close#}
4194 {#header_open|@IntType#}
45024195 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u8) -&gt; type</code></pre>
45034196 <p>
45044197 This function returns an integer type with the given signness and bit count.
45054198 </p>
4506 <h3 id="builtin-maxValue">@maxValue</h3>
4199 {#header_close#}
4200 {#header_open|@maxValue#}
45074201 <pre><code class="zig">@maxValue(comptime T: type) -&gt; (number literal)</code></pre>
45084202 <p>
45094203 This function returns the maximum value of the integer type <code>T</code>.
......@@ -4511,7 +4205,8 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
45114205 <p>
45124206 The result is a compile time constant.
45134207 </p>
4514 <h3 id="builtin-memberCount">@memberCount</h3>
4208 {#header_close#}
4209 {#header_open|@memberCount#}
45154210 <pre><code class="zig">@memberCount(comptime T: type) -&gt; (number literal)</code></pre>
45164211 <p>
45174212 This function returns the number of enum values in an enum type.
......@@ -4519,11 +4214,14 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
45194214 <p>
45204215 The result is a compile time constant.
45214216 </p>
4522 <h3 id="builtin-memberName">@memberName</h3>
4217 {#header_close#}
4218 {#header_open|@memberName#}
45234219 <p>TODO</p>
4524 <h3 id="builtin-memberType">@memberType</h3>
4220 {#header_close#}
4221 {#header_open|@memberType#}
45254222 <p>TODO</p>
4526 <h3 id="builtin-memcpy">@memcpy</h3>
4223 {#header_close#}
4224 {#header_open|@memcpy#}
45274225 <pre><code class="zig">@memcpy(noalias dest: &amp;u8, noalias source: &amp;const u8, byte_count: usize)</code></pre>
45284226 <p>
45294227 This function copies bytes from one region of memory to another. <code>dest</code> and
......@@ -4540,7 +4238,8 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
45404238 <p>There is also a standard library function for this:</p>
45414239 <pre><code class="zig">const mem = @import("std").mem;
45424240mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
4543 <h3 id="builtin-memset">@memset</h3>
4241 {#header_close#}
4242 {#header_open|@memset#}
45444243 <pre><code class="zig">@memset(dest: &amp;u8, c: u8, byte_count: usize)</code></pre>
45454244 <p>
45464245 This function sets a region of memory to <code>c</code>. <code>dest</code> is a pointer.
......@@ -4556,7 +4255,8 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
45564255 <p>There is also a standard library function for this:</p>
45574256 <pre><code>const mem = @import("std").mem;
45584257mem.set(u8, dest, c);</code></pre>
4559 <h3 id="builtin-minValue">@minValue</h3>
4258 {#header_close#}
4259 {#header_open|@minValue#}
45604260 <pre><code class="zig">@minValue(comptime T: type) -&gt; (number literal)</code></pre>
45614261 <p>
45624262 This function returns the minimum value of the integer type T.
......@@ -4564,7 +4264,8 @@ mem.set(u8, dest, c);</code></pre>
45644264 <p>
45654265 The result is a compile time constant.
45664266 </p>
4567 <h3 id="builtin-mod">@mod</h3>
4267 {#header_close#}
4268 {#header_open|@mod#}
45684269 <pre><code class="zig">@mod(numerator: T, denominator: T) -&gt; T</code></pre>
45694270 <p>
45704271 Modulus division. For unsigned integers this is the same as
......@@ -4574,19 +4275,18 @@ mem.set(u8, dest, c);</code></pre>
45744275 <li><code>@mod(-5, 3) == 1</code></li>
45754276 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
45764277 </ul>
4577 <p>See also:</p>
4578 <ul>
4579 <li><a href="#builtin-rem">@rem</a></li>
4580 <li><code>@import("std").math.mod</code></li>
4581 </ul>
4582 <h3 id="builtin-mulWithOverflow">@mulWithOverflow</h3>
4278 <p>For a function that returns an error code, see <code>@import("std").math.mod</code>.</p>
4279 {#see_also|@rem#}
4280 {#header_close#}
4281 {#header_open|@mulWithOverflow#}
45834282 <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
45844283 <p>
45854284 Performs <code>*result = a * b</code>. If overflow or underflow occurs,
45864285 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
45874286 If no overflow or underflow occurs, returns <code>false</code>.
45884287 </p>
4589 <h3 id="builtin-noInlineCall">@noInlineCall</h3>
4288 {#header_close#}
4289 {#header_open|@noInlineCall#}
45904290 <pre><code class="zig">@noInlineCall(function: var, args: ...) -&gt; var</code></pre>
45914291 <p>
45924292 This calls a function, in the same way that invoking an expression with parentheses does:
......@@ -4601,16 +4301,15 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
46014301 Unlike a normal function call, however, <code>@noInlineCall</code> guarantees that the call
46024302 will not be inlined. If the call must be inlined, a compile error is emitted.
46034303 </p>
4604 <p>See also:</p>
4605 <ul>
4606 <li><a href="#builtin-inlineCall">@inlineCall</a></li>
4607 </ul>
4608 <h3 id="builtin-offsetOf">@offsetOf</h3>
4304 {#see_also|@inlineCall#}
4305 {#header_close#}
4306 {#header_open|@offsetOf#}
46094307 <pre><code class="zig">@offsetOf(comptime T: type, comptime field_name: [] const u8) -&gt; (number literal)</code></pre>
46104308 <p>
46114309 This function returns the byte offset of a field relative to its containing struct.
46124310 </p>
4613 <h3 id="builtin-OpaqueType">@OpaqueType</h3>
4311 {#header_close#}
4312 {#header_open|@OpaqueType#}
46144313 <pre><code class="zig">@OpaqueType() -&gt; type</code></pre>
46154314 <p>
46164315 Creates a new type with an unknown size and alignment.
......@@ -4630,7 +4329,8 @@ export fn foo(w: &amp;Wat) {
46304329test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
46314330 bar(w);
46324331 ^</code></pre>
4633 <h3 id="builtin-panic">@panic</h3>
4332 {#header_close#}
4333 {#header_open|@panic#}
46344334 <pre><code class="zig">@panic(message: []const u8) -&gt; noreturn</code></pre>
46354335 <p>
46364336 Invokes the panic handler function. By default the panic handler function
......@@ -4644,17 +4344,15 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
46444344 <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li>
46454345 <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li>
46464346 </ul>
4647 <p>See also:</p>
4648 <ul>
4649 <li><a href="#root-source-file">Root Source File</a></li>
4650 </ul>
4651
4652 <h3 id="builtin-ptrCast">@ptrCast</h3>
4347 {#see_also|Root Source File#}
4348 {#header_close#}
4349 {#header_open|@ptrCast#}
46534350 <pre><code class="zig">@ptrCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
46544351 <p>
46554352 Converts a pointer of one type to a pointer of another type.
46564353 </p>
4657 <h3 id="builtin-ptrToInt">@ptrToInt</h3>
4354 {#header_close#}
4355 {#header_open|@ptrToInt#}
46584356 <pre><code class="zig">@ptrToInt(value: var) -&gt; usize</code></pre>
46594357 <p>
46604358 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:
......@@ -4667,7 +4365,8 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
46674365 </ul>
46684366 <p>To convert the other way, use <a href="#builtin-intToPtr">@intToPtr</a></p>
46694367
4670 <h3 id="builtin-rem">@rem</h3>
4368 {#header_close#}
4369 {#header_open|@rem#}
46714370 <pre><code class="zig">@rem(numerator: T, denominator: T) -&gt; T</code></pre>
46724371 <p>
46734372 Remainder division. For unsigned integers this is the same as
......@@ -4677,12 +4376,10 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
46774376 <li><code>@rem(-5, 3) == -2</code></li>
46784377 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
46794378 </ul>
4680 <p>See also:</p>
4681 <ul>
4682 <li><a href="#builtin-mod">@mod</a></li>
4683 <li><code>@import("std").math.rem</code></li>
4684 </ul>
4685 <h3 id="builtin-returnAddress">@returnAddress</h3>
4379 <p>For a function that returns an error code, see <code>@import("std").math.rem</code>.</p>
4380 {#see_also|@mod#}
4381 {#header_close#}
4382 {#header_open|@returnAddress#}
46864383 <pre><code class="zig">@returnAddress()</code></pre>
46874384 <p>
46884385 This function returns a pointer to the return address of the current stack
......@@ -4695,14 +4392,15 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
46954392 <p>
46964393 This function is only valid within function scope.
46974394 </p>
4698
4699 <h3 id="builtin-setDebugSafety">@setDebugSafety</h3>
4395 {#header_close#}
4396 {#header_open|@setDebugSafety#}
47004397 <pre><code class="zig">@setDebugSafety(scope, safety_on: bool)</code></pre>
47014398 <p>
47024399 Sets whether debug safety checks are on for a given scope.
47034400 </p>
47044401
4705 <h3 id="builtin-setEvalBranchQuota">@setEvalBranchQuota</h3>
4402 {#header_close#}
4403 {#header_open|@setEvalBranchQuota#}
47064404 <pre><code class="zig">@setEvalBranchQuota(new_quota: usize)</code></pre>
47074405 <p>
47084406 Changes the maximum number of backwards branches that compile-time code
......@@ -4732,12 +4430,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
47324430 <pre><code class="sh">$ ./zig build-obj test.zig</code></pre>
47334431 <p>(no output because it worked fine)</p>
47344432
4735 <p>See also:</p>
4736 <ul>
4737 <li><a href="#comptime">comptime</a></li>
4738 </ul>
4739
4740 <h3 id="builtin-setFloatMode">@setFloatMode</h3>
4433 {#see_also|comptime#}
4434 {#header_close#}
4435 {#header_open|@setFloatMode#}
47414436 <pre><code class="zig">@setFloatMode(scope, mode: @import("builtin").FloatMode)</code></pre>
47424437 <p>
47434438 Sets the floating point mode for a given scope. Possible values are:
......@@ -4763,26 +4458,22 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
47634458 <code>Strict</code> - Floating point operations follow strict IEEE compliance.
47644459 </li>
47654460 </ul>
4766 <p>See also:</p>
4767 <ul>
4768 <li><a href="#float-operations">Floating Point Operations</a></li>
4769 </ul>
4770
4771 <h3 id="builtin-setGlobalLinkage">@setGlobalLinkage</h3>
4461 {#see_also|Floating Point Operations#}
4462 {#header_close#}
4463 {#header_open|@setGlobalLinkage#}
47724464 <pre><code class="zig">@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage)</code></pre>
47734465 <p>
47744466 <code>GlobalLinkage</code> can be found with <code>@import("builtin").GlobalLinkage</code>.
47754467 </p>
4776 <p>See also:</p>
4777 <ul>
4778 <li><a href="#compile-variables">Compile Variables</a></li>
4779 </ul>
4780 <h3 id="builtin-setGlobalSection">@setGlobalSection</h3>
4468 {#see_also|Compile Variables#}
4469 {#header_close#}
4470 {#header_open|@setGlobalSection#}
47814471 <pre><code class="zig">@setGlobalSection(global_variable_name, comptime section_name: []const u8) -&gt; bool</code></pre>
47824472 <p>
47834473 Puts the global variable in the specified section.
47844474 </p>
4785 <h3 id="builtin-shlExact">@shlExact</h3>
4475 {#header_close#}
4476 {#header_open|@shlExact#}
47864477 <pre><code class="zig">@shlExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>
47874478 <p>
47884479 Performs the left shift operation (<code>&lt;&lt;</code>). Caller guarantees
......@@ -4792,12 +4483,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
47924483 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
47934484 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
47944485 </p>
4795 <p>See also:</p>
4796 <ul>
4797 <li><a href="#builtin-shrExact">@shrExact</a></li>
4798 <li><a href="#builtin-shlWithOverflow">@shlWithOverflow</a></li>
4799 </ul>
4800 <h3 id="builtin-shlWithOverflow">@shlWithOverflow</h3>
4486 {#see_also|@shrExact|@shlWithOverflow#}
4487 {#header_close#}
4488 {#header_open|@shlWithOverflow#}
48014489 <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &amp;T) -&gt; bool</code></pre>
48024490 <p>
48034491 Performs <code>*result = a &lt;&lt; b</code>. If overflow or underflow occurs,
......@@ -4808,12 +4496,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
48084496 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
48094497 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
48104498 </p>
4811 <p>See also:</p>
4812 <ul>
4813 <li><a href="#builtin-shlExact">@shlExact</a></li>
4814 <li><a href="#builtin-shrExact">@shrExact</a></li>
4815 </ul>
4816 <h3 id="builtin-shrExact">@shrExact</h3>
4499 {#see_also|@shlExact|@shrExact#}
4500 {#header_close#}
4501 {#header_open|@shrExact#}
48174502 <pre><code class="zig">@shrExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>
48184503 <p>
48194504 Performs the right shift operation (<code>&gt;&gt;</code>). Caller guarantees
......@@ -4823,11 +4508,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
48234508 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
48244509 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
48254510 </p>
4826 <p>See also:</p>
4827 <ul>
4828 <li><a href="#builtin-shlExact">@shlExact</a></li>
4829 </ul>
4830 <h3 id="builtin-sizeOf">@sizeOf</h3>
4511 {#see_also|@shlExact|@shlWithOverflow#}
4512 {#header_close#}
4513 {#header_open|@sizeOf#}
48314514 <pre><code class="zig">@sizeOf(comptime T: type) -&gt; (number literal)</code></pre>
48324515 <p>
48334516 This function returns the number of bytes it takes to store <code>T</code> in memory.
......@@ -4835,14 +4518,16 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
48354518 <p>
48364519 The result is a target-specific compile time constant.
48374520 </p>
4838 <h3 id="builtin-subWithOverflow">@subWithOverflow</h3>
4521 {#header_close#}
4522 {#header_open|@subWithOverflow#}
48394523 <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
48404524 <p>
48414525 Performs <code>*result = a - b</code>. If overflow or underflow occurs,
48424526 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
48434527 If no overflow or underflow occurs, returns <code>false</code>.
48444528 </p>
4845 <h3 id="builtin-truncate">@truncate</h3>
4529 {#header_close#}
4530 {#header_open|@truncate#}
48464531 <pre><code class="zig">@truncate(comptime T: type, integer) -&gt; T</code></pre>
48474532 <p>
48484533 This function truncates bits from an integer type, resulting in a smaller
......@@ -4865,7 +4550,8 @@ const b: u8 = @truncate(u8, a);
48654550 of endianness on the target platform.
48664551 </p>
48674552
4868 <h3 id="builtin-typeId">@typeId</h3>
4553 {#header_close#}
4554 {#header_open|@typeId#}
48694555 <pre><code class="zig">@typeId(comptime T: type) -&gt; @import("builtin").TypeId</code></pre>
48704556 <p>
48714557 Returns which kind of type something is. Possible values:
......@@ -4898,20 +4584,24 @@ const b: u8 = @truncate(u8, a);
48984584 Opaque,
48994585};</code></pre>
49004586
4901 <h3 id="builtin-typeName">@typeName</h3>
4587 {#header_close#}
4588 {#header_open|@typeName#}
49024589 <pre><code class="zig">@typeName(T: type) -&gt; []u8</code></pre>
49034590 <p>
49044591 This function returns the string representation of a type.
49054592 </p>
49064593
4907 <h3 id="builtin-typeOf">@typeOf</h3>
4594 {#header_close#}
4595 {#header_open|@typeOf#}
49084596 <pre><code class="zig">@typeOf(expression) -&gt; type</code></pre>
49094597 <p>
49104598 This function returns a compile-time constant, which is the type of the
49114599 expression passed as an argument. The expression is evaluated.
49124600 </p>
49134601
4914 <h2 id="build-mode">Build Mode</h2>
4602 {#header_close#}
4603 {#header_close#}
4604 {#header_open|Build Mode#}
49154605 <p>
49164606 Zig has three build modes:
49174607 </p>
......@@ -4935,34 +4625,33 @@ pub fn build(b: &amp;Builder) {
49354625 </p>
49364626 <pre><code class="sh"> -Drelease-safe=(bool) optimizations on and safety on
49374627 -Drelease-fast=(bool) optimizations on and safety off</code></pre>
4938 <h3 id="build-mode-debug">Debug</h2>
4628 {#header_open|Debug#}
49394629 <pre><code class="sh">$ zig build-exe example.zig</code></pre>
49404630 <ul>
49414631 <li>Fast compilation speed</li>
49424632 <li>Safety checks enabled</li>
49434633 <li>Slow runtime performance</li>
49444634 </ul>
4945 <h3 id="build-mode-release-fast">ReleaseFast</h2>
4635 {#header_close#}
4636 {#header_open|ReleaseFast#}
49464637 <pre><code class="sh">$ zig build-exe example.zig --release-fast</code></pre>
49474638 <ul>
49484639 <li>Fast runtime performance</li>
49494640 <li>Safety checks disabled</li>
49504641 <li>Slow compilation speed</li>
49514642 </ul>
4952 <h3 id="build-mode-release-safe">ReleaseSafe</h2>
4643 {#header_close#}
4644 {#header_open|ReleaseSafe#}
49534645 <pre><code class="sh">$ zig build-exe example.zig --release-safe</code></pre>
49544646 <ul>
49554647 <li>Medium runtime performance</li>
49564648 <li>Safety checks enabled</li>
49574649 <li>Slow compilation speed</li>
49584650 </ul>
4959 <p>See also:</p>
4960 <ul>
4961 <li><a href="#compile-variables">Compile Variables</a></li>
4962 <li><a href="#zig-build-system">Zig Build System</a></li>
4963 <li><a href="#undefined-behavior">Undefined Behavior</a></li>
4964 </ul>
4965 <h2 id="undefined-behavior">Undefined Behavior</h2>
4651 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
4652 {#header_close#}
4653 {#header_close#}
4654 {#header_open|Undefined Behavior#}
49664655 <p>
49674656 Zig has many instances of undefined behavior. If undefined behavior is
49684657 detected at compile-time, Zig emits an error. Most undefined behavior that
......@@ -5000,7 +4689,7 @@ Test 1/1 safety check...reached unreachable code
50004689
50014690Tests failed. Use the following command to reproduce the failure:
50024691./test</code></pre>
5003 <h3 id="undef-unreachable">Reaching Unreachable Code</h3>
4692 {#header_open|Reaching Unreachable Code#}
50044693 <p>At compile-time:</p>
50054694 <pre><code class="zig">comptime {
50064695 assert(false);
......@@ -5019,7 +4708,8 @@ fn assert(ok: bool) {
50194708comptime {
50204709 ^</code></pre>
50214710 <p>At runtime crashes with the message <code>reached unreachable code</code> and a stack trace.</p>
5022 <h3 id="undef-index-out-of-bounds">Index out of Bounds</h3>
4711 {#header_close#}
4712 {#header_open|Index out of Bounds#}
50234713 <p>At compile-time:</p>
50244714 <pre><code class="zig">comptime {
50254715 const array = "hello";
......@@ -5030,7 +4720,8 @@ comptime {
50304720 const garbage = array[5];
50314721 ^</code></pre>
50324722 <p>At runtime crashes with the message <code>index out of bounds</code> and a stack trace.</p>
5033 <h3 id="undef-cast-negative-unsigned">Cast Negative Number to Unsigned Integer</h3>
4723 {#header_close#}
4724 {#header_open|Cast Negative Number to Unsigned Integer#}
50344725 <p>At compile-time:</p>
50354726 <pre><code class="zig">comptime {
50364727 const value: i32 = -1;
......@@ -5044,7 +4735,8 @@ comptime {
50444735 If you are trying to obtain the maximum value of an unsigned integer, use <code>@maxValue(T)</code>,
50454736 where <code>T</code> is the integer type, such as <code>u32</code>.
50464737 </p>
5047 <h3 id="undef-cast-truncates-data">Cast Truncates Data</h3>
4738 {#header_close#}
4739 {#header_open|Cast Truncates Data#}
50484740 <p>At compile-time:</p>
50494741 <pre><code class="zig">comptime {
50504742 const spartan_count: u16 = 300;
......@@ -5060,8 +4752,9 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
50604752 where <code>T</code> is the integer type, such as <code>u32</code>, and <code>value</code>
50614753 is the value you want to truncate.
50624754 </p>
5063 <h3 id="undef-integer-overflow">Integer Overflow</h3>
5064 <h4 id="undef-int-overflow-default">Default Operations</h4>
4755 {#header_close#}
4756 {#header_open|Integer Overflow#}
4757 {#header_open|Default Operations#}
50654758 <p>The following operators can cause integer overflow:</p>
50664759 <ul>
50674760 <li><code>+</code> (addition)</li>
......@@ -5083,7 +4776,8 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
50834776 byte += 1;
50844777 ^</code></pre>
50854778 <p>At runtime crashes with the message <code>integer overflow</code> and a stack trace.</p>
5086 <h4 id="undef-int-overflow-std">Standard Library Math Functions</h4>
4779 {#header_close#}
4780 {#header_open|Standard Library Math Functions#}
50874781 <p>These functions provided by the standard library return possible errors.</p>
50884782 <ul>
50894783 <li><code>@import("std").math.add</code></li>
......@@ -5112,7 +4806,8 @@ pub fn main() -&gt; %void {
51124806 <pre><code class="sh">$ zig build-exe test.zig
51134807$ ./test
51144808unable to add one: Overflow</code></pre>
5115 <h4 id="undef-int-overflow-builtin">Builtin Overflow Functions</h4>
4809 {#header_close#}
4810 {#header_open|Builtin Overflow Functions#}
51164811 <p>
51174812 These builtins return a <code>bool</code> of whether or not overflow
51184813 occurred, as well as returning the overflowed bits:
......@@ -5140,7 +4835,8 @@ pub fn main() -&gt; %void {
51404835 <pre><code class="sh">$ zig build-exe test.zig
51414836$ ./test
51424837overflowed result: 9</code></pre>
5143 <h4 id="undef-int-overflow-wrap">Wrapping Operations</h4>
4838 {#header_close#}
4839 {#header_open|Wrapping Operations#}
51444840 <p>
51454841 These operations have guaranteed wraparound semantics.
51464842 </p>
......@@ -5159,7 +4855,9 @@ test "wraparound addition and subtraction" {
51594855 const max_val = min_val -% 1;
51604856 assert(max_val == @maxValue(i32));
51614857}</code></pre>
5162 <h3 id="undef-shl-overflow">Exact Left Shift Overflow</h3>
4858 {#header_close#}
4859 {#header_close#}
4860 {#header_open|Exact Left Shift Overflow#}
51634861 <p>At compile-time:</p>
51644862 <pre><code class="zig">comptime {
51654863 const x = @shlExact(u8(0b01010101), 2);
......@@ -5169,7 +4867,8 @@ test "wraparound addition and subtraction" {
51694867 const x = @shlExact(u8(0b01010101), 2);
51704868 ^</code></pre>
51714869 <p>At runtime crashes with the message <code>left shift overflowed bits</code> and a stack trace.</p>
5172 <h3 id="undef-shr-overflow">Exact Right Shift Overflow</h3>
4870 {#header_close#}
4871 {#header_open|Exact Right Shift Overflow#}
51734872 <p>At compile-time:</p>
51744873 <pre><code class="zig">comptime {
51754874 const x = @shrExact(u8(0b10101010), 2);
......@@ -5179,7 +4878,8 @@ test "wraparound addition and subtraction" {
51794878 const x = @shrExact(u8(0b10101010), 2);
51804879 ^</code></pre>
51814880 <p>At runtime crashes with the message <code>right shift overflowed bits</code> and a stack trace.</p>
5182 <h3 id="undef-division-by-zero">Division by Zero</h3>
4881 {#header_close#}
4882 {#header_open|Division by Zero#}
51834883 <p>At compile-time:</p>
51844884 <pre><code class="zig">comptime {
51854885 const a: i32 = 1;
......@@ -5192,7 +4892,8 @@ test "wraparound addition and subtraction" {
51924892 ^</code></pre>
51934893 <p>At runtime crashes with the message <code>division by zero</code> and a stack trace.</p>
51944894
5195 <h3 id="undef-remainder-division-by-zero">Remainder Division by Zero</h3>
4895 {#header_close#}
4896 {#header_open|Remainder Division by Zero#}
51964897 <p>At compile-time:</p>
51974898 <pre><code class="zig">comptime {
51984899 const a: i32 = 10;
......@@ -5205,11 +4906,14 @@ test "wraparound addition and subtraction" {
52054906 ^</code></pre>
52064907 <p>At runtime crashes with the message <code>remainder division by zero</code> and a stack trace.</p>
52074908
5208 <h3 id="undef-exact-division-remainder">Exact Division Remainder</h3>
4909 {#header_close#}
4910 {#header_open|Exact Division Remainder#}
52094911 <p>TODO</p>
5210 <h3 id="undef-slice-widen-remainder">Slice Widen Remainder</h3>
4912 {#header_close#}
4913 {#header_open|Slice Widen Remainder#}
52114914 <p>TODO</p>
5212 <h3 id="undef-attempt-unwrap-null">Attempt to Unwrap Null</h3>
4915 {#header_close#}
4916 {#header_open|Attempt to Unwrap Null#}
52134917 <p>At compile-time:</p>
52144918 <pre><code class="zig">comptime {
52154919 const nullable_number: ?i32 = null;
......@@ -5222,8 +4926,9 @@ test "wraparound addition and subtraction" {
52224926 <p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>
52234927 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
52244928 the <code>if</code> expression:</p>
5225 <pre><code class="zig">const warn = @import("std").debug.warn;
5226pub fn main() -&gt; %void {
4929 {#code_begin|exe|test#}
4930const warn = @import("std").debug.warn;
4931pub fn main() {
52274932 const nullable_number: ?i32 = null;
52284933
52294934 if (nullable_number) |number| {
......@@ -5231,11 +4936,10 @@ pub fn main() -&gt; %void {
52314936 } else {
52324937 warn("it's null\n");
52334938 }
5234}</code></pre>
5235 <pre><code class="sh">% zig build-exe test.zig
5236$ ./test
5237it's null</code></pre>
5238 <h3 id="undef-attempt-unwrap-error">Attempt to Unwrap Error</h3>
4939}
4940 {#code_end#}
4941 {#header_close#}
4942 {#header_open|Attempt to Unwrap Error#}
52394943 <p>At compile-time:</p>
52404944 <pre><code class="zig">comptime {
52414945 const number = %%getNumberOrFail();
......@@ -5253,9 +4957,10 @@ fn getNumberOrFail() -&gt; %i32 {
52534957 <p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p>
52544958 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
52554959 the <code>if</code> expression:</p>
5256 <pre><code class="zig">const warn = @import("std").debug.warn;
4960 {#code_begin|exe|test#}
4961const warn = @import("std").debug.warn;
52574962
5258pub fn main() -&gt; %void {
4963pub fn main() {
52594964 const result = getNumberOrFail();
52604965
52614966 if (result) |number| {
......@@ -5267,14 +4972,12 @@ pub fn main() -&gt; %void {
52674972
52684973error UnableToReturnNumber;
52694974
5270fn getNumberOrFail() -&gt; %i32 {
4975fn getNumberOrFail() -> %i32 {
52714976 return error.UnableToReturnNumber;
5272}</code></pre>
5273 <pre><code class="sh">$ zig build-exe test.zig
5274$ ./test
5275got error: UnableToReturnNumber</code></pre>
5276
5277 <h3 id="undef-invalid-error-code">Invalid Error Code</h3>
4977}
4978 {#code_end#}
4979 {#header_close#}
4980 {#header_open|Invalid Error Code#}
52784981 <p>At compile-time:</p>
52794982 <pre><code class="zig">error AnError;
52804983comptime {
......@@ -5287,28 +4990,31 @@ comptime {
52874990 const invalid_err = error(number);
52884991 ^</code></pre>
52894992 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>
5290 <h3 id="undef-invalid-enum-cast">Invalid Enum Cast</h3>
4993 {#header_close#}
4994 {#header_open|Invalid Enum Cast#}
52914995 <p>TODO</p>
52924996
5293 <h3 id="undef-incorrect-pointer-alignment">Incorrect Pointer Alignment</h3>
4997 {#header_close#}
4998 {#header_open|Incorrect Pointer Alignment#}
52944999 <p>TODO</p>
52955000
5296 <h3 id="undef-bad-union-field">Wrong Union Field Access</h3>
5001 {#header_close#}
5002 {#header_open|Wrong Union Field Access#}
52975003 <p>TODO</p>
52985004
5299 <h2 id="memory">Memory</h2>
5005 {#header_close#}
5006 {#header_close#}
5007 {#header_open|Memory#}
53005008 <p>TODO: explain no default allocator in zig</p>
53015009 <p>TODO: show how to use the allocator interface</p>
53025010 <p>TODO: mention debug allocator</p>
53035011 <p>TODO: importance of checking for allocation failure</p>
53045012 <p>TODO: mention overcommit and the OOM Killer</p>
53055013 <p>TODO: mention recursion</p>
5306 <p>See also:</p>
5307 <ul>
5308 <li><a href="#pointers">Pointers</a></li>
5309 </ul>
5014 {#see_also|Pointers#}
53105015
5311 <h2 id="compile-variables">Compile Variables</h2>
5016 {#header_close#}
5017 {#header_open|Compile Variables#}
53125018 <p>
53135019 Compile variables are accessible by importing the <code>"builtin"</code> package,
53145020 which the compiler makes available to every Zig source file. It contains
......@@ -5474,11 +5180,9 @@ pub const object_format = ObjectFormat.elf;
54745180pub const mode = Mode.ReleaseFast;
54755181pub const link_libs = [][]const u8 {
54765182};</code></pre>
5477 <p>See also:</p>
5478 <ul>
5479 <li><a href="#build-mode">Build Mode</a></li>
5480 </ul>
5481 <h2 id="root-source-file">Root Source File</h2>
5183 {#see_also|Build Mode#}
5184 {#header_close#}
5185 {#header_open|Root Source File#}
54825186 <p>TODO: explain how root source file finds other files</p>
54835187 <p>TODO: pub fn main</p>
54845188 <p>TODO: pub fn panic</p>
......@@ -5486,17 +5190,20 @@ pub const link_libs = [][]const u8 {
54865190 <p>TODO: order independent top level declarations</p>
54875191 <p>TODO: lazy analysis</p>
54885192 <p>TODO: using comptime { _ = @import() }</p>
5489 <h2 id="zig-test">Zig Test</h2>
5193 {#header_close#}
5194 {#header_open|Zig Test#}
54905195 <p>TODO: basic usage</p>
54915196 <p>TODO: lazy analysis</p>
54925197 <p>TODO: --test-filter</p>
54935198 <p>TODO: --test-name-prefix</p>
54945199 <p>TODO: testing in releasefast and releasesafe mode. assert still works</p>
5495 <h2 id="zig-build-system">Zig Build System</h2>
5200 {#header_close#}
5201 {#header_open|Zig Build System#}
54965202 <p>TODO: explain purpose, it's supposed to replace make/cmake</p>
54975203 <p>TODO: example of building a zig executable</p>
54985204 <p>TODO: example of building a C library</p>
5499 <h2 id="c">C</h2>
5205 {#header_close#}
5206 {#header_open|C#}
55005207 <p>
55015208 Although Zig is independent of C, and, unlike most other languages, does not depend on libc,
55025209 Zig acknowledges the importance of interacting with existing C code.
......@@ -5504,7 +5211,7 @@ pub const link_libs = [][]const u8 {
55045211 <p>
55055212 There are a few ways that Zig facilitates C interop.
55065213 </p>
5507 <h3 id="c-type-primitives">C Type Primitives</h3>
5214 {#header_open|C Type Primitives#}
55085215 <p>
55095216 These have guaranteed C ABI compatibility and can be used like any other type.
55105217 </p>
......@@ -5520,11 +5227,9 @@ pub const link_libs = [][]const u8 {
55205227 <li><code>c_longdouble</code></li>
55215228 <li><code>c_void</code></li>
55225229 </ul>
5523 <p>See also:</p>
5524 <ul>
5525 <li><a href="#primitive-types">Primitive Types</a></li>
5526 </ul>
5527 <h3 id="c-string-literals">C String Literals</h3>
5230 {#see_also|Primitive Types#}
5231 {#header_close#}
5232 {#header_open|C String Literals#}
55285233 <pre><code class="zig">extern fn puts(&amp;const u8);
55295234
55305235pub fn main() -&gt; %void {
......@@ -5535,11 +5240,9 @@ pub fn main() -&gt; %void {
55355240 c\\multiline C string literal
55365241 );
55375242}</code></pre>
5538 <p>See also:</p>
5539 <ul>
5540 <li><a href="#string-literals">String Literals</a></li>
5541 </ul>
5542 <h3 id="c-import">Import from C Header File</h3>
5243 {#see_also|String Literals#}
5244 {#header_close#}
5245 {#header_open|Import from C Header File#}
55435246 <p>
55445247 The <code>@cImport</code> builtin function can be used
55455248 to directly import symbols from .h files:
......@@ -5566,19 +5269,14 @@ const c = @cImport({
55665269 }
55675270 @cInclude("soundio.h");
55685271});</code></pre>
5569 <p>See also:</p>
5570 <ul>
5571 <li><a href="#builtin-cImport">@cImport</a></li>
5572 <li><a href="#builtin-cInclude">@cInclude</a></li>
5573 <li><a href="#builtin-cDefine">@cDefine</a></li>
5574 <li><a href="#builtin-cUndef">@cUndef</a></li>
5575 <li><a href="#builtin-import">@import</a></li>
5576 </ul>
5577 <h3 id="mixing-object-files">Mixing Object Files</h3>
5272 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
5273 {#header_close#}
5274 {#header_open|Mixing Object Files#}
55785275 <p>
55795276 You can mix Zig object files with any other object files that respect the C ABI. Example:
55805277 </p>
5581 <h4>base64.zig</h4>
5278 {#header_close#}
5279 {#header_open|base64.zig#}
55825280 <pre><code class="zig">const base64 = @import("std").base64;
55835281
55845282export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize,
......@@ -5592,7 +5290,7 @@ export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize,
55925290 return decoded_size;
55935291}
55945292</code></pre>
5595 <h4>test.c</h4>
5293{{teheader_open:st.c}}
55965294 <pre><code class="c">// This header is generated by zig from base64.zig
55975295#include "base64.h"
55985296
......@@ -5609,7 +5307,8 @@ int main(int argc, char **argv) {
56095307
56105308 return 0;
56115309}</code></pre>
5612 <h4>build.zig</h4>
5310 {#header_close#}
5311 {#header_open|build.zig#}
56135312 <pre><code class="zig">const Builder = @import("std").build.Builder;
56145313
56155314pub fn build(b: &amp;Builder) {
......@@ -5625,16 +5324,15 @@ pub fn build(b: &amp;Builder) {
56255324
56265325 b.default_step.dependOn(&amp;exe.step);
56275326}</code></pre>
5628 <h4>Terminal</h4>
5327 {#header_close#}
5328 {#header_open|Terminal#}
56295329 <pre><code class="sh">$ zig build
56305330$ ./test
56315331all your base are belong to us</code></pre>
5632 <p>See also:</p>
5633 <ul>
5634 <li><a href="#targets">Targets</a></li>
5635 <li><a href="#zig-build-system">Zig Build System</a></li>
5636 </ul>
5637 <h2 id="targets">Targets</h2>
5332 {#see_also|Targets|Zig Build System#}
5333 {#header_close#}
5334 {#header_close#}
5335 {#header_open|Targets#}
56385336 <p>
56395337 Zig supports generating code for all targets that LLVM supports. Here is
56405338 what it looks like to execute <code>zig targets</code> on a Linux x86_64
......@@ -5760,14 +5458,15 @@ Environments:
57605458 Linux x86_64. Not all standard library code requires operating system abstractions, however,
57615459 so things such as generic data structures work an all above platforms.
57625460 </p>
5763 <h2 id="style-guide">Style Guide</h2>
5461 {#header_close#}
5462 {#header_open|Style Guide#}
57645463 <p>
57655464These coding conventions are not enforced by the compiler, but they are shipped in
57665465this documentation along with the compiler in order to provide a point of
57675466reference, should anyone wish to point to an authority on agreed upon Zig
57685467coding style.
57695468 </p>
5770 <h3 id="style-guide-whitespace">Whitespace</h3>
5469 {#header_open|Whitespace#}
57715470 <ul>
57725471 <li>
57735472 4 space indentation
......@@ -5782,7 +5481,8 @@ coding style.
57825481 Line length: aim for 100; use common sense.
57835482 </li>
57845483 </ul>
5785 <h3 id="style-guide-names">Names</h3>
5484 {#header_close#}
5485 {#header_open|Names#}
57865486 <p>
57875487 Roughly speaking: <code>camelCaseFunctionName</code>, <code>TitleCaseTypeName</code>,
57885488 <code>snake_case_variable_name</code>. More precisely:
......@@ -5816,7 +5516,8 @@ coding style.
58165516 do what makes sense. For example, if there is an established convention such as
58175517 <code>ENOENT</code>, follow the established convention.
58185518 </p>
5819 <h3 id="style-guide-examples">Examples</h3>
5519 {#header_close#}
5520 {#header_open|Examples#}
58205521 <pre><code class="zig">const namespace_name = @import("dir_name/file_name.zig");
58215522var global_var: i32 = undefined;
58225523const const_name = 42;
......@@ -5858,7 +5559,9 @@ fn readU32Be() -&gt; u32 {}</code></pre>
58585559 <p>
58595560 See the Zig Standard Library for more examples.
58605561 </p>
5861 <h2 id="grammar">Grammar</h2>
5562 {#header_close#}
5563 {#header_close#}
5564 {#header_open|Grammar#}
58625565 <pre><code>Root = many(TopLevelItem) EOF
58635566
58645567TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
......@@ -6010,7 +5713,8 @@ KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "u
60105713ContainerDecl = option("extern" | "packed")
60115714 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
60125715 "{" many(ContainerMember) "}"</code></pre>
6013 <h2 id="zen">Zen</h2>
5716 {#header_close#}
5717 {#header_open|Zen#}
60145718 <ul>
60155719 <li>Communicate intent precisely.</li>
60165720 <li>Edge cases matter.</li>
......@@ -6024,8 +5728,10 @@ ContainerDecl = option("extern" | "packed")
60245728 <li>Minimize energy spent on coding style.</li>
60255729 <li>Together we serve end users.</li>
60265730 </ul>
6027 <h2>TODO</h2>
5731 {#header_close#}
5732 {#header_open|TODO#}
60285733 <p>TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)</p>
5734 {#header_close#}
60295735 </div>
60305736 <script src="highlight/highlight.pack.js"></script>
60315737 <script>hljs.initHighlightingOnLoad();</script>
src/bigint.cpp+10-2
......@@ -1271,6 +1271,12 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
12711271}
12721272
12731273void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1274 if (op1->digit_count == 0) {
1275 return bigint_init_bigint(dest, op2);
1276 }
1277 if (op2->digit_count == 0) {
1278 return bigint_init_bigint(dest, op1);
1279 }
12741280 if (op1->is_negative || op2->is_negative) {
12751281 // TODO this code path is untested
12761282 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
......@@ -1289,14 +1295,16 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
12891295 dest->is_negative = false;
12901296 const uint64_t *op1_digits = bigint_ptr(op1);
12911297 const uint64_t *op2_digits = bigint_ptr(op2);
1298
1299 assert(op1->digit_count > 0 && op2->digit_count > 0);
1300 uint64_t first_digit = op1_digits[0] ^ op2_digits[0];
12921301 if (op1->digit_count == 1 && op2->digit_count == 1) {
12931302 dest->digit_count = 1;
1294 dest->data.digit = op1_digits[0] ^ op2_digits[0];
1303 dest->data.digit = first_digit;
12951304 bigint_normalize(dest);
12961305 return;
12971306 }
12981307 // TODO this code path is untested
1299 uint64_t first_digit = dest->data.digit;
13001308 dest->digit_count = max(op1->digit_count, op2->digit_count);
13011309 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
13021310 dest->data.digits[0] = first_digit;
src/codegen.cpp+20-28
......@@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) {
921921 return g->memcpy_fn_val;
922922}
923923
924static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
925 if (g->return_address_fn_val)
926 return g->return_address_fn_val;
927
928 TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
929
930 LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref,
931 &g->builtin_types.entry_i32->type_ref, 1, false);
932 g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
933 assert(LLVMGetIntrinsicID(g->return_address_fn_val));
934
935 return g->return_address_fn_val;
936}
937
924938static LLVMValueRef get_return_err_fn(CodeGen *g) {
925939 if (g->return_err_fn != nullptr)
926940 return g->return_err_fn;
927941
928942 assert(g->err_tag_type != nullptr);
929943
930 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
931
932944 LLVMTypeRef arg_types[] = {
933945 // error return trace pointer
934946 get_ptr_to_stack_trace_type(g)->type_ref,
935 // return address
936 ptr_u8,
937947 };
938 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);
948 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
939949
940950 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false);
941951 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
952 addLLVMFnAttr(fn_val, "noinline"); // so that we can look at return address
942953 addLLVMFnAttr(fn_val, "cold");
943954 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
944955 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
945956 addLLVMFnAttr(fn_val, "nounwind");
946957 add_uwtable_attr(g, fn_val);
947958 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
948 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
949959 if (g->build_mode == BuildModeDebug) {
950960 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
951961 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr);
......@@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
983993 LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, "");
984994 LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, "");
985995
986 LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, LLVMGetParam(fn_val, 1), usize_type_ref, "");
996 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
997 LLVMValueRef return_address_ptr = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, "");
998 LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, "");
987999
9881000 LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, "");
9891001 gen_store_untyped(g, address_value, address_slot, 0, false);
......@@ -1431,17 +1443,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
14311443 is_err_return = true;
14321444 }
14331445 if (is_err_return) {
1434 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError");
1435 LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block);
1436
14371446 LLVMValueRef return_err_fn = get_return_err_fn(g);
14381447 LLVMValueRef args[] = {
14391448 g->cur_err_ret_trace_val,
1440 block_address,
14411449 };
1442 LLVMBuildBr(g->builder, return_block);
1443 LLVMPositionBuilderAtEnd(g->builder, return_block);
1444 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2,
1450 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,
14451451 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
14461452 LLVMSetTailCall(call_instruction, true);
14471453 }
......@@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I
32913297 return nullptr;
32923298}
32933299
3294static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
3295 if (g->return_address_fn_val)
3296 return g->return_address_fn_val;
3297
3298 TypeTableEntry *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
3299
3300 LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref,
3301 &g->builtin_types.entry_i32->type_ref, 1, false);
3302 g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type);
3303 assert(LLVMGetIntrinsicID(g->return_address_fn_val));
3304
3305 return g->return_address_fn_val;
3306}
3307
33083300static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,
33093301 IrInstructionReturnAddress *instruction)
33103302{
std/build.zig+1-1
......@@ -760,7 +760,7 @@ const CrossTarget = struct {
760760 environ: builtin.Environ,
761761};
762762
763const Target = union(enum) {
763pub const Target = union(enum) {
764764 Native: void,
765765 Cross: CrossTarget,
766766
std/crypto/blake2.zig+4
......@@ -21,6 +21,8 @@ pub const Blake2s256 = Blake2s(256);
2121
2222fn Blake2s(comptime out_len: usize) -> type { return struct {
2323 const Self = this;
24 const block_size = 64;
25 const digest_size = out_len / 8;
2426
2527 const iv = [8]u32 {
2628 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
......@@ -236,6 +238,8 @@ pub const Blake2b512 = Blake2b(512);
236238
237239fn Blake2b(comptime out_len: usize) -> type { return struct {
238240 const Self = this;
241 const block_size = 128;
242 const digest_size = out_len / 8;
239243
240244 const iv = [8]u64 {
241245 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
std/crypto/index.zig+9-2
......@@ -1,5 +1,5 @@
1pub const Md5 = @import("sha1.zig").Md5;
2pub const Sha1 = @import("md5.zig").Sha1;
1pub const Md5 = @import("md5.zig").Md5;
2pub const Sha1 = @import("sha1.zig").Sha1;
33
44const sha2 = @import("sha2.zig");
55pub const Sha224 = sha2.Sha224;
......@@ -7,6 +7,12 @@ pub const Sha256 = sha2.Sha256;
77pub const Sha384 = sha2.Sha384;
88pub const Sha512 = sha2.Sha512;
99
10const sha3 = @import("sha3.zig");
11pub const Sha3_224 = sha3.Sha3_224;
12pub const Sha3_256 = sha3.Sha3_256;
13pub const Sha3_384 = sha3.Sha3_384;
14pub const Sha3_512 = sha3.Sha3_512;
15
1016const blake2 = @import("blake2.zig");
1117pub const Blake2s224 = blake2.Blake2s224;
1218pub const Blake2s256 = blake2.Blake2s256;
......@@ -17,5 +23,6 @@ test "crypto" {
1723 _ = @import("md5.zig");
1824 _ = @import("sha1.zig");
1925 _ = @import("sha2.zig");
26 _ = @import("sha3.zig");
2027 _ = @import("blake2.zig");
2128}
std/crypto/md5.zig+2-6
......@@ -14,14 +14,10 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) -> Round
1414 return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };
1515}
1616
17/// const hash1 = Md5.hash("my input");
18///
19/// const hasher = Md5.init();
20/// hasher.update("my ");
21/// hasher.update("input");
22/// const hash2 = hasher.final();
2317pub const Md5 = struct {
2418 const Self = this;
19 const block_size = 64;
20 const digest_size = 16;
2521
2622 s: [4]u32,
2723 // Streaming Cache
std/crypto/sha1.zig+2
......@@ -16,6 +16,8 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) -> RoundParam {
1616
1717pub const Sha1 = struct {
1818 const Self = this;
19 const block_size = 64;
20 const digest_size = 20;
1921
2022 s: [5]u32,
2123 // Streaming Cache
std/crypto/sha2.zig+4-1
......@@ -58,6 +58,8 @@ pub const Sha256 = Sha2_32(Sha256Params);
5858
5959fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
6060 const Self = this;
61 const block_size = 64;
62 const digest_size = params.out_len / 8;
6163
6264 s: [8]u32,
6365 // Streaming Cache
......@@ -372,7 +374,8 @@ pub const Sha512 = Sha2_64(Sha512Params);
372374
373375fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
374376 const Self = this;
375 const u9 = @IntType(false, 9);
377 const block_size = 128;
378 const digest_size = params.out_len / 8;
376379
377380 s: [8]u64,
378381 // Streaming Cache
std/crypto/sha3.zig created+281
......@@ -0,0 +1,281 @@
1const mem = @import("../mem.zig");
2const math = @import("../math/index.zig");
3const endian = @import("../endian.zig");
4const debug = @import("../debug/index.zig");
5const builtin = @import("builtin");
6const htest = @import("test.zig");
7
8pub const Sha3_224 = Keccak(224, 0x06);
9pub const Sha3_256 = Keccak(256, 0x06);
10pub const Sha3_384 = Keccak(384, 0x06);
11pub const Sha3_512 = Keccak(512, 0x06);
12
13fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct {
14 const Self = this;
15 const block_size = 200;
16 const digest_size = bits / 8;
17
18 s: [200]u8,
19 offset: usize,
20 rate: usize,
21
22 pub fn init() -> Self {
23 var d: Self = undefined;
24 d.reset();
25 return d;
26 }
27
28 pub fn reset(d: &Self) {
29 mem.set(u8, d.s[0..], 0);
30 d.offset = 0;
31 d.rate = 200 - (bits / 4);
32 }
33
34 pub fn hash(b: []const u8, out: []u8) {
35 var d = Self.init();
36 d.update(b);
37 d.final(out);
38 }
39
40 pub fn update(d: &Self, b: []const u8) {
41 var ip: usize = 0;
42 var len = b.len;
43 var rate = d.rate - d.offset;
44 var offset = d.offset;
45
46 // absorb
47 while (len >= rate) {
48 for (d.s[offset .. offset + rate]) |*r, i|
49 *r ^= b[ip..][i];
50
51 keccak_f(1600, d.s[0..]);
52
53 ip += rate;
54 len -= rate;
55 rate = d.rate;
56 offset = 0;
57 }
58
59 for (d.s[offset .. offset + len]) |*r, i|
60 *r ^= b[ip..][i];
61
62 d.offset = offset + len;
63 }
64
65 pub fn final(d: &Self, out: []u8) {
66 // padding
67 d.s[d.offset] ^= delim;
68 d.s[d.rate - 1] ^= 0x80;
69
70 keccak_f(1600, d.s[0..]);
71
72 // squeeze
73 var op: usize = 0;
74 var len: usize = bits / 8;
75
76 while (len >= d.rate) {
77 mem.copy(u8, out[op..], d.s[0..d.rate]);
78 keccak_f(1600, d.s[0..]);
79 op += d.rate;
80 len -= d.rate;
81 }
82
83 mem.copy(u8, out[op..], d.s[0..len]);
84 }
85};}
86
87const RC = []const u64 {
88 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
89 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
90 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
91 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
92 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
93 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
94};
95
96const ROTC = []const usize {
97 1, 3, 6, 10, 15, 21, 28, 36,
98 45, 55, 2, 14, 27, 41, 56, 8,
99 25, 43, 62, 18, 39, 61, 20, 44
100};
101
102const PIL = []const usize {
103 10, 7, 11, 17, 18, 3, 5, 16,
104 8, 21, 24, 4, 15, 23, 19, 13,
105 12, 2, 20, 14, 22, 9, 6, 1
106};
107
108const M5 = []const usize {
109 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
110};
111
112fn keccak_f(comptime F: usize, d: []u8) {
113 debug.assert(d.len == F / 8);
114
115 const B = F / 25;
116 const no_rounds = comptime x: { break :x 12 + 2 * math.log2(B); };
117
118 var s = []const u64 {0} ** 25;
119 var t = []const u64 {0} ** 1;
120 var c = []const u64 {0} ** 5;
121
122 for (s) |*r, i| {
123 *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]);
124 }
125
126 var x: usize = 0;
127 var y: usize = 0;
128 // TODO: Cannot unroll all loops here due to comptime differences.
129 inline for (RC[0..no_rounds]) |round| {
130 // theta
131 x = 0; while (x < 5) : (x += 1) {
132 c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20];
133 }
134 x = 0; while (x < 5) : (x += 1) {
135 t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1));
136 y = 0; while (y < 5) : (y += 1) {
137 s[x + y*5] ^= t[0];
138 }
139 }
140
141 // rho+pi
142 t[0] = s[1];
143 x = 0; while (x < 24) : (x += 1) {
144 c[0] = s[PIL[x]];
145 s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]);
146 t[0] = c[0];
147 }
148
149 // chi
150 y = 0; while (y < 5) : (y += 1) {
151 x = 0; while (x < 5) : (x += 1) {
152 c[x] = s[x + y*5];
153 }
154 x = 0; while (x < 5) : (x += 1) {
155 s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]);
156 }
157 }
158
159 // iota
160 s[0] ^= round;
161 }
162
163 for (s) |r, i| {
164 mem.writeInt(d[8*i .. 8*i + 8], r, builtin.Endian.Little);
165 }
166}
167
168
169test "sha3-224 single" {
170 htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", "");
171 htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc");
172 htest.assertEqualHash(Sha3_224, "543e6868e1666c1a643630df77367ae5a62a85070a51c14cbf665cbc", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
173}
174
175test "sha3-224 streaming" {
176 var h = Sha3_224.init();
177 var out: [28]u8 = undefined;
178
179 h.final(out[0..]);
180 htest.assertEqual("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", out[0..]);
181
182 h.reset();
183 h.update("abc");
184 h.final(out[0..]);
185 htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]);
186
187 h.reset();
188 h.update("a");
189 h.update("b");
190 h.update("c");
191 h.final(out[0..]);
192 htest.assertEqual("e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", out[0..]);
193}
194
195test "sha3-256 single" {
196 htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , "");
197 htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc");
198 htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
199}
200
201test "sha3-256 streaming" {
202 var h = Sha3_256.init();
203 var out: [32]u8 = undefined;
204
205 h.final(out[0..]);
206 htest.assertEqual("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", out[0..]);
207
208 h.reset();
209 h.update("abc");
210 h.final(out[0..]);
211 htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]);
212
213 h.reset();
214 h.update("a");
215 h.update("b");
216 h.update("c");
217 h.final(out[0..]);
218 htest.assertEqual("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", out[0..]);
219}
220
221test "sha3-384 single" {
222 const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";
223 htest.assertEqualHash(Sha3_384, h1 , "");
224 const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";
225 htest.assertEqualHash(Sha3_384, h2, "abc");
226 const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7";
227 htest.assertEqualHash(Sha3_384, h3, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
228}
229
230test "sha3-384 streaming" {
231 var h = Sha3_384.init();
232 var out: [48]u8 = undefined;
233
234 const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";
235 h.final(out[0..]);
236 htest.assertEqual(h1, out[0..]);
237
238 const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";
239 h.reset();
240 h.update("abc");
241 h.final(out[0..]);
242 htest.assertEqual(h2, out[0..]);
243
244 h.reset();
245 h.update("a");
246 h.update("b");
247 h.update("c");
248 h.final(out[0..]);
249 htest.assertEqual(h2, out[0..]);
250}
251
252test "sha3-512 single" {
253 const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";
254 htest.assertEqualHash(Sha3_512, h1 , "");
255 const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";
256 htest.assertEqualHash(Sha3_512, h2, "abc");
257 const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185";
258 htest.assertEqualHash(Sha3_512, h3, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
259}
260
261test "sha3-512 streaming" {
262 var h = Sha3_512.init();
263 var out: [64]u8 = undefined;
264
265 const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";
266 h.final(out[0..]);
267 htest.assertEqual(h1, out[0..]);
268
269 const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";
270 h.reset();
271 h.update("abc");
272 h.final(out[0..]);
273 htest.assertEqual(h2, out[0..]);
274
275 h.reset();
276 h.update("a");
277 h.update("b");
278 h.update("c");
279 h.final(out[0..]);
280 htest.assertEqual(h2, out[0..]);
281}
std/crypto/throughput_test.zig created+43
......@@ -0,0 +1,43 @@
1// Modify the HashFunction variable to the one wanted to test.
2//
3// NOTE: The throughput measurement may be slightly lower than other measurements since we run
4// through our block alignment functions as well. Be aware when comparing against other tests.
5//
6// ```
7// zig build-exe --release-fast --library c throughput_test.zig
8// ./throughput_test
9// ```
10const HashFunction = @import("md5.zig").Md5;
11const BytesToHash = 1024 * Mb;
12
13const std = @import("std");
14
15const c = @cImport({
16 @cInclude("time.h");
17});
18
19const Mb = 1024 * 1024;
20
21pub fn main() -> %void {
22 var stdout_file = try std.io.getStdOut();
23 var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
24 const stdout = &stdout_out_stream.stream;
25
26 var block: [HashFunction.block_size]u8 = undefined;
27 std.mem.set(u8, block[0..], 0);
28
29 var h = HashFunction.init();
30 var offset: usize = 0;
31
32 const start = c.clock();
33 while (offset < BytesToHash) : (offset += block.len) {
34 h.update(block[0..]);
35 }
36 const end = c.clock();
37
38 const elapsed_s = f64((end - start) * c.CLOCKS_PER_SEC) / 1000000;
39 const throughput = u64(BytesToHash / elapsed_s);
40
41 try stdout.print("{}: ", @typeName(HashFunction));
42 try stdout.print("{} Mb/s\n", throughput);
43}
std/hash_map.zig+5-2
......@@ -62,8 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
6262 .allocator = allocator,
6363 .size = 0,
6464 .max_distance_from_start_index = 0,
65 // it doesn't actually matter what we set this to since we use wrapping integer arithmetic
66 .modification_count = undefined,
65 .modification_count = if (want_modification_safety) 0 else {},
6766 };
6867 }
6968
......@@ -110,6 +109,10 @@ pub fn HashMap(comptime K: type, comptime V: type,
110109 return hm.internalGet(key);
111110 }
112111
112 pub fn contains(hm: &Self, key: K) -> bool {
113 return hm.get(key) != null;
114 }
115
113116 pub fn remove(hm: &Self, key: K) -> ?&Entry {
114117 hm.incrementModificationCount();
115118 const start_index = hm.keyToIndex(key);
std/mem.zig+14
......@@ -203,6 +203,20 @@ pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) -> %[]T {
203203 return new_buf;
204204}
205205
206/// Remove values from the beginning and end of a slice.
207pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) -> []const T {
208 var begin: usize = 0;
209 var end: usize = slice.len;
210 while (begin < end and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {}
211 while (end > begin and indexOfScalar(T, values_to_strip, slice[end - 1]) != null) : (end -= 1) {}
212 return slice[begin..end];
213}
214
215test "mem.trim" {
216 assert(eql(u8, trim(u8, " foo\n ", " \n"), "foo"));
217 assert(eql(u8, trim(u8, "foo", " \n"), "foo"));
218}
219
206220/// Linear search for the index of a scalar value inside a slice.
207221pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) -> ?usize {
208222 return indexOfScalarPos(T, slice, 0, value);
test/cases/math.zig+27-1
......@@ -349,6 +349,32 @@ test "big number shifting" {
349349 }
350350}
351351
352test "xor" {
353 test_xor();
354 comptime test_xor();
355}
356
357fn test_xor() {
358 assert(0xFF ^ 0x00 == 0xFF);
359 assert(0xF0 ^ 0x0F == 0xFF);
360 assert(0xFF ^ 0xF0 == 0x0F);
361 assert(0xFF ^ 0x0F == 0xF0);
362 assert(0xFF ^ 0xFF == 0x00);
363}
364
365test "big number xor" {
366 comptime {
367 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
368 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
369 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
370 assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
371 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
372 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
373 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
374 assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
375 }
376}
377
352378test "f128" {
353379 test_f128();
354380 comptime test_f128();
......@@ -368,4 +394,4 @@ fn test_f128() {
368394
369395fn should_not_be_zero(x: f128) {
370396 assert(x != 0.0);
371}
397}
\ No newline at end of file