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...@@ -368,6 +368,7 @@ set(ZIG_STD_FILES
368 "crypto/md5.zig"368 "crypto/md5.zig"
369 "crypto/sha1.zig"369 "crypto/sha1.zig"
370 "crypto/sha2.zig"370 "crypto/sha2.zig"
371 "crypto/sha3.zig"
371 "crypto/blake2.zig"372 "crypto/blake2.zig"
372 "cstr.zig"373 "cstr.zig"
373 "debug/failing_allocator.zig"374 "debug/failing_allocator.zig"
build.zig+2-8
...@@ -15,23 +15,17 @@ pub fn build(b: &Builder) -> %void {...@@ -15,23 +15,17 @@ pub fn build(b: &Builder) -> %void {
1515
16 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");16 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);
18 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 {19 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 {
19 docgen_exe.getOutputPath(),20 docgen_exe.getOutputPath(),
21 rel_zig_exe,
20 "doc/langref.html.in",22 "doc/langref.html.in",
21 os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable,23 os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable,
22 });24 });
23 docgen_cmd.step.dependOn(&docgen_exe.step);25 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
32 const docs_step = b.step("docs", "Build documentation");27 const docs_step = b.step("docs", "Build documentation");
33 docs_step.dependOn(&docgen_cmd.step);28 docs_step.dependOn(&docgen_cmd.step);
34 docs_step.dependOn(&docgen_home_cmd.step);
3529
36 const test_step = b.step("test", "Run all the tests");30 const test_step = b.step("test", "Run all the tests");
3731
doc/docgen.zig+523-20
...@@ -1,10 +1,16 @@...@@ -1,10 +1,16 @@
1const std = @import("std");1const std = @import("std");
2const io = std.io;2const io = std.io;
3const os = std.os;3const 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
5pub fn main() -> %void {11pub fn main() -> %void {
6 // TODO use a more general purpose allocator here12 // 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);
8 defer inc_allocator.deinit();14 defer inc_allocator.deinit();
9 const allocator = &inc_allocator.allocator;15 const allocator = &inc_allocator.allocator;
1016
...@@ -12,6 +18,9 @@ pub fn main() -> %void {...@@ -12,6 +18,9 @@ pub fn main() -> %void {
1218
13 if (!args_it.skip()) @panic("expected self arg");19 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
15 const in_file_name = try (args_it.next(allocator) ?? @panic("expected input arg"));24 const in_file_name = try (args_it.next(allocator) ?? @panic("expected input arg"));
16 defer allocator.free(in_file_name);25 defer allocator.free(in_file_name);
1726
...@@ -25,39 +34,533 @@ pub fn main() -> %void {...@@ -25,39 +34,533 @@ pub fn main() -> %void {
25 defer out_file.close();34 defer out_file.close();
2635
27 var file_in_stream = io.FileInStream.init(&in_file);36 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
30 var file_out_stream = io.FileOutStream.init(&out_file);40 var file_out_stream = io.FileOutStream.init(&out_file);
31 var buffered_out_stream = io.BufferedOutStream.init(&file_out_stream.stream);41 var buffered_out_stream = io.BufferedOutStream.init(&file_out_stream.stream);
3242
33 gen(&buffered_in_stream.stream, &buffered_out_stream.stream);43 var tokenizer = Tokenizer.init(in_file_name, input_file_bytes);
34 try buffered_out_stream.flush();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();
36}48}
3749
38const State = enum {50const Token = struct {
39 Start,51 id: Id,
40 Derp,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 };
41};64};
4265
43// TODO look for code segments66const 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) {72 const State = enum {
46 var state = State.Start;73 Start,
47 while (true) {74 LBracket,
48 const byte = in.readByte() catch |err| {75 Hash,
49 if (err == error.EndOfStream) {76 TagName,
50 return;77 Eof,
51 }78 };
52 std.debug.panic("{}", err);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,
53 };94 };
54 switch (state) {95 while (self.index < self.buffer.len) : (self.index += 1) {
55 State.Start => switch (byte) {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 => {},
56 else => {164 else => {
57 out.writeByte(byte) catch unreachable;165 result.id = Token.Id.Invalid;
58 },166 },
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 }
59 },429 },
60 State.Derp => unreachable,430 else => return parseError(tokenizer, token, "invalid token"),
61 }431 }
62 }432 }
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
63}566}
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 @@...@@ -31,221 +31,10 @@
31 </head>31 </head>
32 <body>32 <body>
33 <div id="nav">33 <div id="nav">
34 <ul>34 {#nav#}
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>
246 </div>35 </div>
247 <div id="contents">36 <div id="contents">
248 <h1 id="introduction">Zig Documentation</h1>37 {#header_open|Introduction#}
249 <p>38 <p>
250 Zig is an open-source programming language designed for <strong>robustness</strong>,39 Zig is an open-source programming language designed for <strong>robustness</strong>,
251 <strong>optimality</strong>, and <strong>clarity</strong>.40 <strong>optimality</strong>, and <strong>clarity</strong>.
...@@ -264,37 +53,35 @@...@@ -264,37 +53,35 @@
264 If you search for something specific in this documentation and do not find it,53 If you search for something specific in this documentation and do not find it,
265 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>.54 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>.
266 </p>55 </p>
267 <h2 id="hello-world">Hello World</h2>56 {#header_close#}
268 <pre><code class="zig">const std = @import("std");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 {
271 // If this program is run without stdout attached, exit with an error.63 // If this program is run without stdout attached, exit with an error.
272 var stdout_file = try std.io.getStdOut();64 var stdout_file = try std.io.getStdOut();
273 // If this program encounters pipe failure when printing to stdout, exit65 // If this program encounters pipe failure when printing to stdout, exit
274 // with an error.66 // with an error.
275 try stdout_file.write("Hello, world!\n");67 try stdout_file.write("Hello, world!\n");
276}</code></pre>68}
277 <pre><code class="sh">$ zig build-exe hello.zig69 {#code_end#}
278$ ./hello
279Hello, world!</code></pre>
280 <p>70 <p>
281 Usually you don't want to write to stdout. You want to write to stderr. And you71 Usually you don't want to write to stdout. You want to write to stderr. And you
282 don't care if it fails. It's more like a <em>warning message</em> that you want72 don't care if it fails. It's more like a <em>warning message</em> that you want
283 to emit. For that you can use a simpler API:73 to emit. For that you can use a simpler API:
284 </p>74 </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 {
288 warn("Hello, world!\n");79 warn("Hello, world!\n");
289}</code></pre>80}
290 <p>See also:</p>81 {#code_end#}
291 <ul>82 {#see_also|Values|@import|Errors|Root Source File#}
292 <li><a href="#values">Values</a></li>83 {#header_close#}
293 <li><a href="#builtin-import">@import</a></li>84 {#header_open|Source Encoding#}
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>
298 <p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p>85 <p>Zig source code is encoded in UTF-8. An invalid UTF-8 byte sequence results in a compile error.</p>
299 <p>Throughout all zig source code (including in comments), some codepoints are never allowed:</p>86 <p>Throughout all zig source code (including in comments), some codepoints are never allowed:</p>
300 <ul>87 <ul>
...@@ -303,15 +90,18 @@ pub fn main() -&gt; %void {...@@ -303,15 +90,18 @@ pub fn main() -&gt; %void {
303 </ul>90 </ul>
304 <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>91 <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>
305 <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>92 <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>93 {#header_close#}
307 <pre><code class="zig">const warn = @import("std").debug.warn;94 {#header_open|Values#}
308const os = @import("std").os;95 {#code_begin|exe|values#}
309const assert = @import("std").debug.assert;96const std = @import("std");
97const warn = std.debug.warn;
98const os = std.os;
99const assert = std.debug.assert;
310100
311// error declaration, makes `error.ArgNotFound` available101// error declaration, makes `error.ArgNotFound` available
312error ArgNotFound;102error ArgNotFound;
313103
314pub fn main() -&gt; %void {104pub fn main() -> %void {
315 // integers105 // integers
316 const one_plus_one: i32 = 1 + 1;106 const one_plus_one: i32 = 1 + 1;
317 warn("1 + 1 = {}\n", one_plus_one);107 warn("1 + 1 = {}\n", one_plus_one);
...@@ -349,31 +139,9 @@ pub fn main() -&gt; %void {...@@ -349,31 +139,9 @@ pub fn main() -&gt; %void {
349139
350 warn("\nerror union 2\ntype: {}\nvalue: {}\n",140 warn("\nerror union 2\ntype: {}\nvalue: {}\n",
351 @typeName(@typeOf(number_or_error)), number_or_error);141 @typeName(@typeOf(number_or_error)), number_or_error);
352}</code></pre>142}
353 <pre><code class="sh">$ zig build-exe values.zig143 {#code_end#}
354$ ./values144 {#header_open|Primitive Types#}
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>
377 <table>145 <table>
378 <tr>146 <tr>
379 <th>147 <th>
...@@ -599,14 +367,9 @@ value: 1234</code></pre>...@@ -599,14 +367,9 @@ value: 1234</code></pre>
599 <td>an error code</td>367 <td>an error code</td>
600 </tr>368 </tr>
601 </table>369 </table>
602 <p>See also:</p>370 {#see_also|Integers|Floats|void|Errors#}
603 <ul>371 {#header_close#}
604 <li><a href="#integers">Integers</a></li>372 {#header_open|Primitive Values#}
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>
610 <table>373 <table>
611 <tr>374 <tr>
612 <th>375 <th>
...@@ -633,12 +396,9 @@ value: 1234</code></pre>...@@ -633,12 +396,9 @@ value: 1234</code></pre>
633 <td>refers to the thing in immediate scope</td>396 <td>refers to the thing in immediate scope</td>
634 </tr>397 </tr>
635 </table>398 </table>
636 <p>See also:</p>399 {#see_also|Nullables|this#}
637 <ul>400 {#header_close#}
638 <li><a href="#nullables">Nullables</a></li>401 {#header_open|String Literals#}
639 <li><a href="#this">this</a></li>
640 </ul>
641 <h3 id="string-literals">String Literals</h3>
642 <pre><code class="zig">const assert = @import("std").debug.assert;402 <pre><code class="zig">const assert = @import("std").debug.assert;
643const mem = @import("std").mem;403const mem = @import("std").mem;
644404
...@@ -658,12 +418,8 @@ test "string literals" {...@@ -658,12 +418,8 @@ test "string literals" {
658}</code></pre>418}</code></pre>
659 <pre><code class="sh">$ zig test string_literals.zig419 <pre><code class="sh">$ zig test string_literals.zig
660Test 1/1 string literals...OK</code></pre>420Test 1/1 string literals...OK</code></pre>
661 <p>See also:</p>421 {#see_also|Arrays|Zig Test#}
662 <ul>422 {#header_open|Escape Sequences#}
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>
667 <table>423 <table>
668 <tr>424 <tr>
669 <th>425 <th>
...@@ -711,7 +467,8 @@ Test 1/1 string literals...OK</code></pre>...@@ -711,7 +467,8 @@ Test 1/1 string literals...OK</code></pre>
711 </tr>467 </tr>
712 </table>468 </table>
713 <p>Note that the maximum valid Unicode point is <code>0x10ffff</code>.</p>469 <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#}
715 <p>472 <p>
716 Multiline string literals have no escapes and can span across multiple lines.473 Multiline string literals have no escapes and can span across multiple lines.
717 To start a multiline string literal, use the <code>\\</code> token. Just like a comment,474 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>...@@ -743,11 +500,10 @@ Test 1/1 string literals...OK</code></pre>
743 In this example the variable <code>c_string_literal</code> has type <code>&amp;const char</code> and500 In this example the variable <code>c_string_literal</code> has type <code>&amp;const char</code> and
744 has a terminating null byte.501 has a terminating null byte.
745 </p>502 </p>
746 <p>See also:</p>503 {#see_also|@embedFile#}
747 <ul>504 {#header_close#}
748 <li><a href="#builtin-embedFile">@embedFile</a></li>505 {#header_close#}
749 </ul>506 {#header_open|Assignment#}
750 <h3 id="values-assignment">Assignment</h3>
751 <p>Use <code>const</code> to assign a value to an identifier:</p>507 <p>Use <code>const</code> to assign a value to an identifier:</p>
752 <pre><code class="zig">const x = 1234;508 <pre><code class="zig">const x = 1234;
753509
...@@ -798,14 +554,17 @@ test "init with undefined" {...@@ -798,14 +554,17 @@ test "init with undefined" {
798}</code></pre>554}</code></pre>
799 <pre><code class="sh">$ zig test test.zig555 <pre><code class="sh">$ zig test test.zig
800Test 1/1 init with undefined...OK</code></pre>556Test 1/1 init with undefined...OK</code></pre>
801 <h2 id="integers">Integers</h2>557 {#header_close#}
802 <h3 id="integer-literals">Integer Literals</h3>558 {#header_close#}
559 {#header_open|Integers#}
560 {#header_open|Integer Literals#}
803 <pre><code class="zig">const decimal_int = 98222;561 <pre><code class="zig">const decimal_int = 98222;
804const hex_int = 0xff;562const hex_int = 0xff;
805const another_hex_int = 0xFF;563const another_hex_int = 0xFF;
806const octal_int = 0o755;564const octal_int = 0o755;
807const binary_int = 0b11110000;</code></pre>565const binary_int = 0b11110000;</code></pre>
808 <h3 id="runtime-integer-values">Runtime Integer Values</h3>566 {#header_close#}
567 {#header_open|Runtime Integer Values#}
809 <p>568 <p>
810 Integer literals have no size limitation, and if any undefined behavior occurs,569 Integer literals have no size limitation, and if any undefined behavior occurs,
811 the compiler catches it.570 the compiler catches it.
...@@ -827,14 +586,12 @@ const binary_int = 0b11110000;</code></pre>...@@ -827,14 +586,12 @@ const binary_int = 0b11110000;</code></pre>
827 integer overflow. Also available are operations such as <code>+%</code> and586 integer overflow. Also available are operations such as <code>+%</code> and
828 <code>-%</code> which are defined to have wrapping arithmetic on all targets.587 <code>-%</code> which are defined to have wrapping arithmetic on all targets.
829 </p>588 </p>
830 <p>See also:</p>589 {#see_also|Integer Overflow|Division by Zero|Wrapping Operations#}
831 <ul>590 {#header_close#}
832 <li><a href="#undef-integer-overflow">Integer Overflow</a></li>591 {#header_close#}
833 <li><a href="#undef-division-by-zero">Division By Zero</a></li>592 {#header_open|Floats#}
834 <li><a href="#undef-int-overflow-wrap">Wrapping Operations</a></li>593 {#header_close#}
835 </ul>594 {#header_open|Float Literals#}
836 <h2 id="floats">Floats</h2>
837 <h3 id="float-literals">Float Literals</h3>
838 <pre><code class="zig">const floating_point = 123.0E+77;595 <pre><code class="zig">const floating_point = 123.0E+77;
839const another_float = 123.0;596const another_float = 123.0;
840const yet_another = 123.0e+77;597const yet_another = 123.0e+77;
...@@ -842,7 +599,8 @@ const yet_another = 123.0e+77;...@@ -842,7 +599,8 @@ const yet_another = 123.0e+77;
842const hex_floating_point = 0x103.70p-5;599const hex_floating_point = 0x103.70p-5;
843const another_hex_float = 0x103.70;600const another_hex_float = 0x103.70;
844const yet_another_hex_float = 0x103.70P-5;</code></pre>601const 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#}
846 <p>By default floating point operations use <code>Optimized</code> mode,604 <p>By default floating point operations use <code>Optimized</code> mode,
847 but you can switch to <code>Strict</code> mode on a per-block basis:</p>605 but you can switch to <code>Strict</code> mode on a per-block basis:</p>
848 <p>foo.zig</p>606 <p>foo.zig</p>
...@@ -876,13 +634,10 @@ $ zig build-exe test.zig --object foo.o...@@ -876,13 +634,10 @@ $ zig build-exe test.zig --object foo.o
876$ ./test634$ ./test
877optimized = 1.0e-2635optimized = 1.0e-2
878strict = 9.765625e-3</code></pre>636strict = 9.765625e-3</code></pre>
879 <p>See also:</p>637 {#see_also|@setFloatMode|Division by Zero#}
880 <ul>638 {#header_close#}
881 <li><a href="#builtin-setFloatMode">@setFloatMode</a></li>639 {#header_open|Operators#}
882 <li><a href="#undef-division-by-zero">Division By Zero</a></li>640 {#header_open|Table of Operators#}
883 </ul>
884 <h2 id="operators">Operators</h2>
885 <h3 id="operators-table">Table of Operators</h2>
886 <table>641 <table>
887 <tr>642 <tr>
888 <th>643 <th>
...@@ -1470,7 +1225,8 @@ const ptr = &amp;x;...@@ -1470,7 +1225,8 @@ const ptr = &amp;x;
1470 </td>1225 </td>
1471 </tr>1226 </tr>
1472 </table>1227 </table>
1473 <h3 id="operators-precedence">Precedence</h3>1228 {#header_close#}
1229 {#header_open|Precedence#}
1474 <pre><code>x() x[] x.y1230 <pre><code>x() x[] x.y
1475!x -x -%x ~x *x &amp;x ?x %x %%x ??x1231!x -x -%x ~x *x &amp;x ?x %x %%x ??x
1476x{}1232x{}
...@@ -1485,7 +1241,9 @@ and...@@ -1485,7 +1241,9 @@ and
1485or1241or
1486?? catch1242?? catch
1487= *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>1243= *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>
1488 <h2 id="arrays">Arrays</h2>1244 {#header_close#}
1245 {#header_close#}
1246 {#header_open|Arrays#}
1489 <pre><code class="zig">const assert = @import("std").debug.assert;1247 <pre><code class="zig">const assert = @import("std").debug.assert;
1490const mem = @import("std").mem;1248const mem = @import("std").mem;
14911249
...@@ -1594,12 +1352,9 @@ Test 1/4 iterate over an array...OK...@@ -1594,12 +1352,9 @@ Test 1/4 iterate over an array...OK
1594Test 2/4 modify an array...OK1352Test 2/4 modify an array...OK
1595Test 3/4 compile-time array initalization...OK1353Test 3/4 compile-time array initalization...OK
1596Test 4/4 array initialization with function calls...OK</code></pre>1354Test 4/4 array initialization with function calls...OK</code></pre>
1597 <p>See also:</p>1355 {#see_also|for|Slices#}
1598 <ul>1356 {#header_close#}
1599 <li><a href="#for">for</a></li>1357 {#header_open|Pointers#}
1600 <li><a href="#slices">Slices</a></li>
1601 </ul>
1602 <h2 id="pointers">Pointers</h2>
1603 <pre><code class="zig">const assert = @import("std").debug.assert;1358 <pre><code class="zig">const assert = @import("std").debug.assert;
16041359
1605test "address of syntax" {1360test "address of syntax" {
...@@ -1737,7 +1492,7 @@ Test 5/8 volatile...OK...@@ -1737,7 +1492,7 @@ Test 5/8 volatile...OK
1737Test 6/8 nullable pointers...OK1492Test 6/8 nullable pointers...OK
1738Test 7/8 pointer casting...OK1493Test 7/8 pointer casting...OK
1739Test 8/8 pointer child type...OK</code></pre>1494Test 8/8 pointer child type...OK</code></pre>
1740 <h3 id="alignment">Alignment</h3>1495 {#header_open|Alignment#}
1741 <p>1496 <p>
1742 Each type has an <strong>alignment</strong> - a number of bytes such that,1497 Each type has an <strong>alignment</strong> - a number of bytes such that,
1743 when a value of the type is loaded from or stored to memory,1498 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...@@ -1838,7 +1593,8 @@ Test 1/1 pointer alignment safety...incorrect alignment
18381593
1839Tests failed. Use the following command to reproduce the failure:1594Tests failed. Use the following command to reproduce the failure:
1840./test</code></pre>1595./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#}
1842 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to1598 <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to
1843 perform some optimizations. This means that pointers of different types must1599 perform some optimizations. This means that pointers of different types must
1844 not alias the same memory, with the exception of <code>u8</code>. Pointers to1600 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:...@@ -1849,12 +1605,10 @@ Tests failed. Use the following command to reproduce the failure:
1849 <p>Instead, use <a href="#builtin-bitCast">@bitCast</a>:1605 <p>Instead, use <a href="#builtin-bitCast">@bitCast</a>:
1850 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>1606 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
1851 <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>1607 <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>
1852 <p>See also:</p>1608 {#see_also|Slices|Memory#}
1853 <ul>1609 {#header_close#}
1854 <li><a href="#slices">Slices</a></li>1610 {#header_close#}
1855 <li><a href="#memory">Memory</a></li>1611 {#header_open|Slices#}
1856 </ul>
1857 <h2 id="slices">Slices</h2>
1858 <pre><code class="zig">const assert = @import("std").debug.assert;1612 <pre><code class="zig">const assert = @import("std").debug.assert;
18591613
1860test "basic slices" {1614test "basic slices" {
...@@ -1948,13 +1702,9 @@ test "slice widening" {...@@ -1948,13 +1702,9 @@ test "slice widening" {
1948Test 1/3 using slices for strings...OK1702Test 1/3 using slices for strings...OK
1949Test 2/3 slice pointer...OK1703Test 2/3 slice pointer...OK
1950Test 3/3 slice widening...OK</code></pre>1704Test 3/3 slice widening...OK</code></pre>
1951 <p>See also:</p>1705 {#see_also|Pointers|for|Arrays#}
1952 <ul>1706 {#header_close#}
1953 <li><a href="#pointers">Pointers</a></li>1707 {#header_open|struct#}
1954 <li><a href="#for">for</a></li>
1955 <li><a href="#arrays">Arrays</a></li>
1956 </ul>
1957 <h2 id="struct">struct</h2>
1958 <pre><code class="zig">// Declare a struct.1708 <pre><code class="zig">// Declare a struct.
1959// Zig gives no guarantees about the order of fields and whether or1709// Zig gives no guarantees about the order of fields and whether or
1960// not there will be padding.1710// not there will be padding.
...@@ -2094,12 +1844,9 @@ Test 1/4 dot product...OK...@@ -2094,12 +1844,9 @@ Test 1/4 dot product...OK
2094Test 2/4 struct namespaced variable...OK1844Test 2/4 struct namespaced variable...OK
2095Test 3/4 field parent pointer...OK1845Test 3/4 field parent pointer...OK
2096Test 4/4 linked list...OK</code></pre>1846Test 4/4 linked list...OK</code></pre>
2097 <p>See also:</p>1847 {#see_also|comptime|@fieldParentPtr#}
2098 <ul>1848 {#header_close#}
2099 <li><a href="#comptime">comptime</a></li>1849 {#header_open|enum#}
2100 <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li>
2101 </ul>
2102 <h2 id="enum">enum</h2>
2103 <pre><code class="zig">const assert = @import("std").debug.assert;1850 <pre><code class="zig">const assert = @import("std").debug.assert;
2104const mem = @import("std").mem;1851const mem = @import("std").mem;
21051852
...@@ -2210,13 +1957,9 @@ Test 5/8 @TagType...OK...@@ -2210,13 +1957,9 @@ Test 5/8 @TagType...OK
2210Test 6/8 @memberCount...OK1957Test 6/8 @memberCount...OK
2211Test 7/8 @memberName...OK1958Test 7/8 @memberName...OK
2212Test 8/8 @tagName...OK</code></pre>1959Test 8/8 @tagName...OK</code></pre>
2213 <p>See also:</p>1960 {#see_also|@memberName|@memberCount|@tagName#}
2214 <ul>1961 {#header_close#}
2215 <li><a href="#builtin-memberName">@memberName</a></li>1962 {#header_open|union#}
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>
2220 <pre><code class="zig">const assert = @import("std").debug.assert;1963 <pre><code class="zig">const assert = @import("std").debug.assert;
2221const mem = @import("std").mem;1964const mem = @import("std").mem;
22221965
...@@ -2323,7 +2066,8 @@ Test 7/7 @tagName...OK</code></pre>...@@ -2323,7 +2066,8 @@ Test 7/7 @tagName...OK</code></pre>
2323 Unions with an enum tag are generated as a struct with a tag field and union field. Zig2066 Unions with an enum tag are generated as a struct with a tag field and union field. Zig
2324 sorts the order of the tag and union field by the largest alignment.2067 sorts the order of the tag and union field by the largest alignment.
2325 </p>2068 </p>
2326 <h2 id="switch">switch</h2>2069 {#header_close#}
2070 {#header_open|switch#}
2327 <pre><code class="zig">const assert = @import("std").debug.assert;2071 <pre><code class="zig">const assert = @import("std").debug.assert;
2328const builtin = @import("builtin");2072const builtin = @import("builtin");
23292073
...@@ -2419,14 +2163,9 @@ test "switch inside function" {...@@ -2419,14 +2163,9 @@ test "switch inside function" {
2419Test 1/2 switch simple...OK2163Test 1/2 switch simple...OK
2420Test 2/2 switch enum...OK2164Test 2/2 switch enum...OK
2421Test 3/3 switch inside function...OK</code></pre>2165Test 3/3 switch inside function...OK</code></pre>
2422 <p>See also:</p>2166 {#see_also|comptime|enum|@compileError|Compile Variables#}
2423 <ul>2167 {#header_close#}
2424 <li><a href="#comptime">comptime</a></li>2168 {#header_open|while#}
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>
2430 <pre><code class="zig">const assert = @import("std").debug.assert;2169 <pre><code class="zig">const assert = @import("std").debug.assert;
24312170
2432test "while basic" {2171test "while basic" {
...@@ -2587,15 +2326,9 @@ Test 5/8 while loop continuation expression, more complicated...OK...@@ -2587,15 +2326,9 @@ Test 5/8 while loop continuation expression, more complicated...OK
2587Test 6/8 while else...OK2326Test 6/8 while else...OK
2588Test 7/8 while null capture...OK2327Test 7/8 while null capture...OK
2589Test 8/8 inline while loop...OK</code></pre>2328Test 8/8 inline while loop...OK</code></pre>
2590 <p>See also:</p>2329 {#see_also|if|Nullables|Errors|comptime|unreachable#}
2591 <ul>2330 {#header_close#}
2592 <li><a href="#if">if</a></li>2331 {#header_open|for#}
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>
2599 <pre><code class="zig">const assert = @import("std").debug.assert;2332 <pre><code class="zig">const assert = @import("std").debug.assert;
26002333
2601test "for basics" {2334test "for basics" {
...@@ -2689,14 +2422,9 @@ Test 1/4 for basics...OK...@@ -2689,14 +2422,9 @@ Test 1/4 for basics...OK
2689Test 2/4 for reference...OK2422Test 2/4 for reference...OK
2690Test 3/4 for else...OK2423Test 3/4 for else...OK
2691Test 4/4 inline for loop...OK</code></pre>2424Test 4/4 inline for loop...OK</code></pre>
2692 <p>See also:</p>2425 {#see_also|while|comptime|Arrays|Slices#}
2693 <ul>2426 {#header_close#}
2694 <li><a href="#while">while</a></li>2427 {#header_open|if#}
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>
2700 <pre><code class="zig">// If expressions have three uses, corresponding to the three types:2428 <pre><code class="zig">// If expressions have three uses, corresponding to the three types:
2701// * bool2429// * bool
2702// * ?T2430// * ?T
...@@ -2809,28 +2537,9 @@ test "if error union" {...@@ -2809,28 +2537,9 @@ test "if error union" {
2809Test 1/3 if boolean...OK2537Test 1/3 if boolean...OK
2810Test 2/3 if nullable...OK2538Test 2/3 if nullable...OK
2811Test 3/3 if error union...OK</code></pre>2539Test 3/3 if error union...OK</code></pre>
2812 <p>See also:</p>2540 {#see_also|Nullables|Errors#}
2813 <ul>2541 {#header_close#}
2814 <li><a href="#nullables">Nullables</a></li>2542 {#header_open|defer#}
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>
2834 <pre><code class="zig">const assert = @import("std").debug.assert;2543 <pre><code class="zig">const assert = @import("std").debug.assert;
2835const printf = @import("std").io.stdout.printf;2544const printf = @import("std").io.stdout.printf;
28362545
...@@ -2916,11 +2625,9 @@ encountered an error!...@@ -2916,11 +2625,9 @@ encountered an error!
2916end of function2625end of function
2917OK2626OK
2918</code></pre>2627</code></pre>
2919 <p>See also:</p>2628 {#see_also|Errors#}
2920 <ul>2629 {#header_close#}
2921 <li><a href="#errors">Errors</a></li>2630 {#header_open|unreachable#}
2922 </ul>
2923 <h2 id="unreachable">unreachable</h2>
2924 <p>2631 <p>
2925 In <code>Debug</code> and <code>ReleaseSafe</code> mode, and when using <code>zig test</code>,2632 In <code>Debug</code> and <code>ReleaseSafe</code> mode, and when using <code>zig test</code>,
2926 <code>unreachable</code> emits a call to <code>panic</code> with the message <code>reached unreachable code</code>.2633 <code>unreachable</code> emits a call to <code>panic</code> with the message <code>reached unreachable code</code>.
...@@ -2930,7 +2637,7 @@ OK...@@ -2930,7 +2637,7 @@ OK
2930 will never be hit to perform optimizations. However, <code>zig test</code> even in <code>ReleaseFast</code> mode2637 will never be hit to perform optimizations. However, <code>zig test</code> even in <code>ReleaseFast</code> mode
2931 still emits <code>unreachable</code> as calls to <code>panic</code>.2638 still emits <code>unreachable</code> as calls to <code>panic</code>.
2932 </p>2639 </p>
2933 <h3 id="unreachable-basics">Basics</h3>2640 {#header_open|Basics#}
2934 <pre><code class="zig">// unreachable is used to assert that control flow will never happen upon a2641 <pre><code class="zig">// unreachable is used to assert that control flow will never happen upon a
2935// particular location:2642// particular location:
2936test "basic math" {2643test "basic math" {
...@@ -2974,7 +2681,8 @@ lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test)...@@ -2974,7 +2681,8 @@ lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test)
29742681
2975Tests failed. Use the following command to reproduce the failure:2682Tests failed. Use the following command to reproduce the failure:
2976./test</code></pre>2683./test</code></pre>
2977 <h3 id="unreachable-comptime">At Compile-Time</h3>2684 {#header_close#}
2685 {#header_open|At Compile-Time#}
2978 <pre><code class="zig">const assert = @import("std").debug.assert;2686 <pre><code class="zig">const assert = @import("std").debug.assert;
29792687
2980comptime {2688comptime {
...@@ -2989,13 +2697,10 @@ comptime {...@@ -2989,13 +2697,10 @@ comptime {
2989test.zig:9:12: error: unreachable code2697test.zig:9:12: error: unreachable code
2990 assert(@typeOf(unreachable) == noreturn);2698 assert(@typeOf(unreachable) == noreturn);
2991 ^</code></pre>2699 ^</code></pre>
2992 <p>See also:</p>2700 {#see_also|Zig Test|Build Mode|comptime#}
2993 <ul>2701 {#header_close#}
2994 <li><a href="#zig-test">Zig Test</a></li>2702 {#header_close#}
2995 <li><a href="#build-mode">Build Mode</a></li>2703 {#header_open|noreturn#}
2996 <li><a href="#comptime">comptime</a></li>
2997 </ul>
2998 <h2 id="noreturn">noreturn</h2>
2999 <p>2704 <p>
3000 <code>noreturn</code> is the type of:2705 <code>noreturn</code> is the type of:
3001 </p>2706 </p>
...@@ -3029,7 +2734,8 @@ fn bar() -&gt; %u32 {...@@ -3029,7 +2734,8 @@ fn bar() -&gt; %u32 {
3029}2734}
30302735
3031const assert = @import("std").debug.assert;</code></pre>2736const assert = @import("std").debug.assert;</code></pre>
3032 <h2 id="functions">Functions</h2>2737 {#header_close#}
2738 {#header_open|Functions#}
3033 <pre><code class="zig">const assert = @import("std").debug.assert;2739 <pre><code class="zig">const assert = @import("std").debug.assert;
30342740
3035// Functions are declared like this2741// Functions are declared like this
...@@ -3091,7 +2797,7 @@ comptime {...@@ -3091,7 +2797,7 @@ comptime {
30912797
3092fn foo() { }</code></pre>2798fn foo() { }</code></pre>
3093 <pre><code class="sh">$ zig build-obj test.zig</code></pre>2799 <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#}
3095 <p>2801 <p>
3096 In Zig, structs, unions, and enums with payloads cannot be passed by value2802 In Zig, structs, unions, and enums with payloads cannot be passed by value
3097 to a function.2803 to a function.
...@@ -3127,7 +2833,9 @@ export fn entry() {...@@ -3127,7 +2833,9 @@ export fn entry() {
3127 the C ABI does allow passing structs and unions by value. So functions which2833 the C ABI does allow passing structs and unions by value. So functions which
3128 use the C calling convention may pass structs and unions by value.2834 use the C calling convention may pass structs and unions by value.
3129 </p>2835 </p>
3130 <h2 id="errors">Errors</h2>2836 {#header_close#}
2837 {#header_close#}
2838 {#header_open|Errors#}
3131 <p>2839 <p>
3132 One of the distinguishing features of Zig is its exception handling strategy.2840 One of the distinguishing features of Zig is its exception handling strategy.
3133 </p>2841 </p>
...@@ -3315,13 +3023,9 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {...@@ -3315,13 +3023,9 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
3315 in other languages.3023 in other languages.
3316 </li>3024 </li>
3317 </ul>3025 </ul>
3318 <p>See also:</p>3026 {#see_also|defer|if|switch#}
3319 <ul>3027 {#header_close#}
3320 <li><a href="#defer">defer</a></li>3028 {#header_open|Nullables#}
3321 <li><a href="#if">if</a></li>
3322 <li><a href="#switch">switch</a></li>
3323 </ul>
3324 <h2 id="nullables">Nullables</h2>
3325 <p>3029 <p>
3326 One area that Zig provides safety without compromising efficiency or3030 One area that Zig provides safety without compromising efficiency or
3327 readability is with the nullable type.3031 readability is with the nullable type.
...@@ -3415,7 +3119,8 @@ fn doAThing() -&gt; ?&amp;Foo {...@@ -3415,7 +3119,8 @@ fn doAThing() -&gt; ?&amp;Foo {
3415 The optimizer can sometimes make better decisions knowing that pointer arguments3119 The optimizer can sometimes make better decisions knowing that pointer arguments
3416 cannot be null.3120 cannot be null.
3417 </p>3121 </p>
3418 <h2 id="casting">Casting</h2>3122 {#header_close#}
3123 {#header_open|Casting#}
3419 <p>TODO: explain implicit vs explicit casting</p>3124 <p>TODO: explain implicit vs explicit casting</p>
3420 <p>TODO: resolve peer types builtin</p>3125 <p>TODO: resolve peer types builtin</p>
3421 <p>TODO: truncate builtin</p>3126 <p>TODO: truncate builtin</p>
...@@ -3424,24 +3129,27 @@ fn doAThing() -&gt; ?&amp;Foo {...@@ -3424,24 +3129,27 @@ fn doAThing() -&gt; ?&amp;Foo {
3424 <p>TODO: ptr to int builtin</p>3129 <p>TODO: ptr to int builtin</p>
3425 <p>TODO: ptrcast builtin</p>3130 <p>TODO: ptrcast builtin</p>
3426 <p>TODO: explain number literals vs concrete types</p>3131 <p>TODO: explain number literals vs concrete types</p>
3427 <h2 id="void">void</h2>3132 {#header_close#}
3133 {#header_open|void#}
3428 <p>TODO: assigning void has no codegen</p>3134 <p>TODO: assigning void has no codegen</p>
3429 <p>TODO: hashmap with void becomes a set</p>3135 <p>TODO: hashmap with void becomes a set</p>
3430 <p>TODO: difference between c_void and void</p>3136 <p>TODO: difference between c_void and void</p>
3431 <p>TODO: void is the default return value of functions</p>3137 <p>TODO: void is the default return value of functions</p>
3432 <p>TODO: functions require assigning the return value</p>3138 <p>TODO: functions require assigning the return value</p>
3433 <h2 id="this">this</h2>3139 {#header_close#}
3140 {#header_open|this#}
3434 <p>TODO: example of this referring to Self struct</p>3141 <p>TODO: example of this referring to Self struct</p>
3435 <p>TODO: example of this referring to recursion function</p>3142 <p>TODO: example of this referring to recursion function</p>
3436 <p>TODO: example of this referring to basic block for @setDebugSafety</p>3143 <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#}
3438 <p>3146 <p>
3439 Zig places importance on the concept of whether an expression is known at compile-time.3147 Zig places importance on the concept of whether an expression is known at compile-time.
3440 There are a few different places this concept is used, and these building blocks are used3148 There are a few different places this concept is used, and these building blocks are used
3441 to keep the language small, readable, and powerful.3149 to keep the language small, readable, and powerful.
3442 </p>3150 </p>
3443 <h3 id="introducing-compile-time-concept">Introducing the Compile-Time Concept</h3>3151 {#header_open|Introducing the Compile-Time Concept#}
3444 <h4 id="compile-time-parameters">Compile-Time Parameters</h4>3152 {#header_open|Compile-Time Parameters#}
3445 <p>3153 <p>
3446 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.3154 Compile-time parameters is how Zig implements generics. It is compile-time duck typing.
3447 </p>3155 </p>
...@@ -3549,7 +3257,8 @@ fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool {...@@ -3549,7 +3257,8 @@ fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool {
3549 This works the same way for <code>switch</code> expressions - they are implicitly inlined3257 This works the same way for <code>switch</code> expressions - they are implicitly inlined
3550 when the target expression is compile-time known.3258 when the target expression is compile-time known.
3551 </p>3259 </p>
3552 <h4 id="compile-time-variables">Compile-Time Variables</h4>3260 {#header_close#}
3261 {#header_open|Compile-Time Variables#}
3553 <p>3262 <p>
3554 In Zig, the programmer can label variables as <code>comptime</code>. This guarantees to the compiler3263 In Zig, the programmer can label variables as <code>comptime</code>. This guarantees to the compiler
3555 that every load and store of the variable is performed at compile-time. Any violation of this results in a3264 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 {...@@ -3631,7 +3340,8 @@ fn performFn(start_value: i32) -&gt; i32 {
3631 later in this article, allows expressiveness that in other languages requires using macros,3340 later in this article, allows expressiveness that in other languages requires using macros,
3632 generated code, or a preprocessor to accomplish.3341 generated code, or a preprocessor to accomplish.
3633 </p>3342 </p>
3634 <h4 id="compile-time-expressions">Compile-Time Expressions</h4>3343 {#header_close#}
3344 {#header_open|Compile-Time Expressions#}
3635 <p>3345 <p>
3636 In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can3346 In Zig, it matters whether a given expression is known at compile-time or run-time. A programmer can
3637 use a <code>comptime</code> expression to guarantee that the expression will be evaluated at compile-time.3347 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 {...@@ -3860,7 +3570,9 @@ fn sum(numbers: []i32) -&gt; i32 {
3860 we could call the <code>sum</code> function as is with a slice of numbers whose length and values were3570 we could call the <code>sum</code> function as is with a slice of numbers whose length and values were
3861 only known at run-time.3571 only known at run-time.
3862 </p>3572 </p>
3863 <h3 id="generic-data-structures">Generic Data Structures</h3>3573 {#header_close#}
3574 {#header_close#}
3575 {#header_open|Generic Data Structures#}
3864 <p>3576 <p>
3865 Zig uses these capabilities to implement generic data structures without introducing any3577 Zig uses these capabilities to implement generic data structures without introducing any
3866 special-case syntax. If you followed along so far, you may already know how to create a3578 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 {...@@ -3895,19 +3607,21 @@ fn sum(numbers: []i32) -&gt; i32 {
3895 <code>Node</code> refers to itself as a pointer, which is not actually an infinite regression, so3607 <code>Node</code> refers to itself as a pointer, which is not actually an infinite regression, so
3896 it works fine.3608 it works fine.
3897 </p>3609 </p>
3898 <h3 id="case-study-printf">Case Study: printf in Zig</h3>3610 {#header_close#}
3611 {#header_open|Case Study: printf in Zig#}
3899 <p>3612 <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.
3901 </p>3614 </p>
3902 <pre><code class="zig">const warn = @import("std").debug.warn;3615 {#code_begin|exe|printf#}
3616const warn = @import("std").debug.warn;
39033617
3904const a_number: i32 = 1234;3618const a_number: i32 = 1234;
3905const a_string = "foobar";3619const a_string = "foobar";
39063620
3907pub fn main(args: [][]u8) -&gt; %void {3621pub fn main() {
3908 warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);3622 warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
3909}</code></pre>3623}
3910 <pre><code>here is a string: 'foobar' here is a number: 1234</code></pre>3624 {#code_end#}
39113625
3912 <p>3626 <p>
3913 Let's crack open the implementation of this and see how it works:3627 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...@@ -4027,15 +3741,17 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt
4027 Zig doesn't care whether the format argument is a string literal,3741 Zig doesn't care whether the format argument is a string literal,
4028 only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:3742 only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:
4029 </p>3743 </p>
4030 <pre><code class="zig">const warn = @import("std").debug.warn;3744 {#code_begin|exe|printf#}
3745const warn = @import("std").debug.warn;
40313746
4032const a_number: i32 = 1234;3747const a_number: i32 = 1234;
4033const a_string = "foobar";3748const a_string = "foobar";
4034const fmt = "here is a string: '{}' here is a number: {}\n";3749const fmt = "here is a string: '{}' here is a number: {}\n";
40353750
4036pub fn main(args: [][]u8) -&gt; %void {3751pub fn main() {
4037 warn(fmt, a_string, a_number);3752 warn(fmt, a_string, a_number);
4038}</code></pre>3753}
3754 {#code_end#}
4039 <p>3755 <p>
4040 This works fine.3756 This works fine.
4041 </p>3757 </p>
...@@ -4045,35 +3761,42 @@ pub fn main(args: [][]u8) -&gt; %void {...@@ -4045,35 +3761,42 @@ pub fn main(args: [][]u8) -&gt; %void {
4045 a macro language or a preprocessor language. It's Zig all the way down.3761 a macro language or a preprocessor language. It's Zig all the way down.
4046 </p>3762 </p>
4047 <p>TODO: suggestion to not use inline unless necessary</p>3763 <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#}
4049 <p>TODO: inline while</p>3767 <p>TODO: inline while</p>
4050 <p>TODO: inline for</p>3768 <p>TODO: inline for</p>
4051 <p>TODO: suggestion to not use inline unless necessary</p>3769 <p>TODO: suggestion to not use inline unless necessary</p>
4052 <h2 id="assembly">Assembly</h2>3770 {#header_close#}
3771 {#header_open|Assembly#}
4053 <p>TODO: example of inline assembly</p>3772 <p>TODO: example of inline assembly</p>
4054 <p>TODO: example of module level assembly</p>3773 <p>TODO: example of module level assembly</p>
4055 <p>TODO: example of using inline assembly return value</p>3774 <p>TODO: example of using inline assembly return value</p>
4056 <p>TODO: example of using inline assembly assigning values to variables</p>3775 <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#}
4058 <p>TODO: @fence()</p>3778 <p>TODO: @fence()</p>
4059 <p>TODO: @atomic rmw</p>3779 <p>TODO: @atomic rmw</p>
4060 <p>TODO: builtin atomic memory ordering enum</p>3780 <p>TODO: builtin atomic memory ordering enum</p>
4061 <h2 id="builtin-functions">Builtin Functions</h2>3781 {#header_close#}
3782 {#header_open|Builtin Functions#}
4062 <p>3783 <p>
4063 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.3784 Builtin functions are provided by the compiler and are prefixed with <code>@</code>.
4064 The <code>comptime</code> keyword on a parameter means that the parameter must be known3785 The <code>comptime</code> keyword on a parameter means that the parameter must be known
4065 at compile time.3786 at compile time.
4066 </p>3787 </p>
4067 <h3 id="builtin-addWithOverflow">@addWithOverflow</h3>3788 {#header_open|@addWithOverflow#}
4068 <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>3789 <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
4069 <p>3790 <p>
4070 Performs <code>*result = a + b</code>. If overflow or underflow occurs,3791 Performs <code>*result = a + b</code>. If overflow or underflow occurs,
4071 stores the overflowed bits in <code>result</code> and returns <code>true</code>.3792 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
4072 If no overflow or underflow occurs, returns <code>false</code>.3793 If no overflow or underflow occurs, returns <code>false</code>.
4073 </p>3794 </p>
4074 <h3 id="builtin-ArgType">@ArgType</h3>3795 {#header_close#}
3796 {#header_open|@ArgType#}
4075 <p>TODO</p>3797 <p>TODO</p>
4076 <h3 id="builtin-bitCast">@bitCast</h3>3798 {#header_close#}
3799 {#header_open|@bitCast#}
4077 <pre><code class="zig">@bitCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>3800 <pre><code class="zig">@bitCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
4078 <p>3801 <p>
4079 Converts a value of one type to another type.3802 Converts a value of one type to another type.
...@@ -4094,7 +3817,8 @@ pub fn main(args: [][]u8) -&gt; %void {...@@ -4094,7 +3817,8 @@ pub fn main(args: [][]u8) -&gt; %void {
4094 <p>3817 <p>
4095 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.3818 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.
4096 </p>3819 </p>
4097 <h3 id="builtin-breakpoint">@breakpoint</h3>3820 {#header_close#}
3821 {#header_open|@breakpoint#}
4098 <pre><code class="zig">@breakpoint()</code></pre>3822 <pre><code class="zig">@breakpoint()</code></pre>
4099 <p>3823 <p>
4100 This function inserts a platform-specific debug trap instruction which causes3824 This function inserts a platform-specific debug trap instruction which causes
...@@ -4104,7 +3828,8 @@ pub fn main(args: [][]u8) -&gt; %void {...@@ -4104,7 +3828,8 @@ pub fn main(args: [][]u8) -&gt; %void {
4104 This function is only valid within function scope.3828 This function is only valid within function scope.
4105 </p>3829 </p>
41063830
4107 <h3 id="builtin-alignCast">@alignCast</h3>3831 {#header_close#}
3832 {#header_open|@alignCast#}
4108 <pre><code class="zig">@alignCast(comptime alignment: u29, ptr: var) -&gt; var</code></pre>3833 <pre><code class="zig">@alignCast(comptime alignment: u29, ptr: var) -&gt; var</code></pre>
4109 <p>3834 <p>
4110 <code>ptr</code> can be <code>&amp;T</code>, <code>fn()</code>, <code>?&amp;T</code>,3835 <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 {...@@ -4114,7 +3839,8 @@ pub fn main(args: [][]u8) -&gt; %void {
4114 <p>A <a href="#undef-incorrect-pointer-alignment">pointer alignment safety check</a> is added3839 <p>A <a href="#undef-incorrect-pointer-alignment">pointer alignment safety check</a> is added
4115 to the generated code to make sure the pointer is aligned as promised.</p>3840 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#}
4118 <pre><code class="zig">@alignOf(comptime T: type) -&gt; (number literal)</code></pre>3844 <pre><code class="zig">@alignOf(comptime T: type) -&gt; (number literal)</code></pre>
4119 <p>3845 <p>
4120 This function returns the number of bytes that this type should be aligned to3846 This function returns the number of bytes that this type should be aligned to
...@@ -4129,12 +3855,9 @@ comptime {...@@ -4129,12 +3855,9 @@ comptime {
4129 The result is a target-specific compile time constant. It is guaranteed to be3855 The result is a target-specific compile time constant. It is guaranteed to be
4130 less than or equal to <a href="#builtin-sizeOf">@sizeOf(T)</a>.3856 less than or equal to <a href="#builtin-sizeOf">@sizeOf(T)</a>.
4131 </p>3857 </p>
4132 <p>See also:</p>3858 {#see_also|Alignment#}
4133 <ul>3859 {#header_close#}
4134 <li><a href="#alignment">Alignment</a></li>3860 {#header_open|@cDefine#}
4135 </ul>
4136
4137 <h3 id="builtin-cDefine">@cDefine</h3>
4138 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>3861 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>
4139 <p>3862 <p>
4140 This function can only occur inside <code>@cImport</code>.3863 This function can only occur inside <code>@cImport</code>.
...@@ -4151,15 +3874,9 @@ comptime {...@@ -4151,15 +3874,9 @@ comptime {
4151 Use the void value, like this:3874 Use the void value, like this:
4152 </p>3875 </p>
4153 <pre><code class="zig">@cDefine("_GNU_SOURCE", {})</code></pre>3876 <pre><code class="zig">@cDefine("_GNU_SOURCE", {})</code></pre>
4154 <p>See also:</p>3877 {#see_also|Import from C Header File|@cInclude|@cImport|@cUndef|void#}
4155 <ul>3878 {#header_close#}
4156 <li><a href="#c-import">Import from C Header File</a></li>3879 {#header_open|@cImport#}
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>
4163 <pre><code class="zig">@cImport(expression) -&gt; (namespace)</code></pre>3880 <pre><code class="zig">@cImport(expression) -&gt; (namespace)</code></pre>
4164 <p>3881 <p>
4165 This function parses C code and imports the functions, types, variables, and3882 This function parses C code and imports the functions, types, variables, and
...@@ -4170,14 +3887,9 @@ comptime {...@@ -4170,14 +3887,9 @@ comptime {
4170 <code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work3887 <code>@cInclude</code>, <code>@cDefine</code>, and <code>@cUndef</code> work
4171 within this expression, appending to a temporary buffer which is then parsed as C code.3888 within this expression, appending to a temporary buffer which is then parsed as C code.
4172 </p>3889 </p>
4173 <p>See also:</p>3890 {#see_also|Import from C Header File|@cInclude|@cDefine|@cUndef#}
4174 <ul>3891 {#header_close#}
4175 <li><a href="#c-import">Import from C Header File</a></li>3892 {#header_open|@cInclude#}
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>
4181 <pre><code class="zig">@cInclude(comptime path: []u8)</code></pre>3893 <pre><code class="zig">@cInclude(comptime path: []u8)</code></pre>
4182 <p>3894 <p>
4183 This function can only occur inside <code>@cImport</code>.3895 This function can only occur inside <code>@cImport</code>.
...@@ -4186,14 +3898,9 @@ comptime {...@@ -4186,14 +3898,9 @@ comptime {
4186 This appends <code>#include <$path>\n</code> to the <code>c_import</code>3898 This appends <code>#include <$path>\n</code> to the <code>c_import</code>
4187 temporary buffer.3899 temporary buffer.
4188 </p>3900 </p>
4189 <p>See also:</p>3901 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
4190 <ul>3902 {#header_close#}
4191 <li><a href="#c-import">Import from C Header File</a></li>3903 {#header_open|@cUndef#}
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>
4197 <pre><code class="zig">@cUndef(comptime name: []u8)</code></pre>3904 <pre><code class="zig">@cUndef(comptime name: []u8)</code></pre>
4198 <p>3905 <p>
4199 This function can only occur inside <code>@cImport</code>.3906 This function can only occur inside <code>@cImport</code>.
...@@ -4202,19 +3909,15 @@ comptime {...@@ -4202,19 +3909,15 @@ comptime {
4202 This appends <code>#undef $name</code> to the <code>@cImport</code>3909 This appends <code>#undef $name</code> to the <code>@cImport</code>
4203 temporary buffer.3910 temporary buffer.
4204 </p>3911 </p>
4205 <p>See also:</p>3912 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
4206 <ul>3913 {#header_close#}
4207 <li><a href="#c-import">Import from C Header File</a></li>3914 {#header_open|@canImplicitCast#}
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>
4213 <pre><code class="zig">@canImplicitCast(comptime T: type, value) -&gt; bool</code></pre>3915 <pre><code class="zig">@canImplicitCast(comptime T: type, value) -&gt; bool</code></pre>
4214 <p>3916 <p>
4215 Returns whether a value can be implicitly casted to a given type.3917 Returns whether a value can be implicitly casted to a given type.
4216 </p>3918 </p>
4217 <h3 id="builtin-clz">@clz</h3>3919 {#header_close#}
3920 {#header_open|@clz#}
4218 <pre><code class="zig">@clz(x: T) -&gt; U</code></pre>3921 <pre><code class="zig">@clz(x: T) -&gt; U</code></pre>
4219 <p>3922 <p>
4220 This function counts the number of leading zeroes in <code>x</code> which is an integer3923 This function counts the number of leading zeroes in <code>x</code> which is an integer
...@@ -4228,7 +3931,8 @@ comptime {...@@ -4228,7 +3931,8 @@ comptime {
4228 If <code>x</code> is zero, <code>@clz</code> returns <code>T.bit_count</code>.3931 If <code>x</code> is zero, <code>@clz</code> returns <code>T.bit_count</code>.
4229 </p>3932 </p>
42303933
4231 <h3 id="builtin-cmpxchg">@cmpxchg</h3>3934 {#header_close#}
3935 {#header_open|@cmpxchg#}
4232 <pre><code class="zig">@cmpxchg(ptr: &amp;T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -&gt; bool</code></pre>3936 <pre><code class="zig">@cmpxchg(ptr: &amp;T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -&gt; bool</code></pre>
4233 <p>3937 <p>
4234 This function performs an atomic compare exchange operation.3938 This function performs an atomic compare exchange operation.
...@@ -4237,12 +3941,9 @@ comptime {...@@ -4237,12 +3941,9 @@ comptime {
4237 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.3941 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.
4238 </p>3942 </p>
4239 <p><code>@typeOf(ptr).alignment</code> must be <code>&gt;= @sizeOf(T).</code></p>3943 <p><code>@typeOf(ptr).alignment</code> must be <code>&gt;= @sizeOf(T).</code></p>
4240 <p>See also:</p>3944 {#see_also|Compile Variables#}
4241 <ul>3945 {#header_close#}
4242 <li><a href="#compile-variables">Compile Variables</a></li>3946 {#header_open|@compileError#}
4243 </ul>
4244
4245 <h3 id="builtin-compileError">@compileError</h3>
4246 <pre><code class="zig">@compileError(comptime msg: []u8)</code></pre>3947 <pre><code class="zig">@compileError(comptime msg: []u8)</code></pre>
4247 <p>3948 <p>
4248 This function, when semantically analyzed, causes a compile error with the3949 This function, when semantically analyzed, causes a compile error with the
...@@ -4253,7 +3954,8 @@ comptime {...@@ -4253,7 +3954,8 @@ comptime {
4253 using <code>if</code> or <code>switch</code> with compile time constants,3954 using <code>if</code> or <code>switch</code> with compile time constants,
4254 and <code>comptime</code> functions.3955 and <code>comptime</code> functions.
4255 </p>3956 </p>
4256 <h3 id="builtin-compileLog">@compileLog</h3>3957 {#header_close#}
3958 {#header_open|@compileLog#}
4257 <pre><code class="zig">@compileLog(args: ...)</code></pre>3959 <pre><code class="zig">@compileLog(args: ...)</code></pre>
4258 <p>3960 <p>
4259 This function prints the arguments passed to it at compile-time.3961 This function prints the arguments passed to it at compile-time.
...@@ -4303,7 +4005,7 @@ test.zig:6:2: error: found compile log statement...@@ -4303,7 +4005,7 @@ test.zig:6:2: error: found compile log statement
4303 program compiles successfully and the generated executable prints:4005 program compiles successfully and the generated executable prints:
4304 </p> 4006 </p>
4305<pre><code class="sh">Runtime in main, num1 = 100.</code></pre>4007<pre><code class="sh">Runtime in main, num1 = 100.</code></pre>
4306 <h3 id="builtin-ctz">@ctz</h3>4008{{@ctheader_open:z}}
4307 <pre><code class="zig">@ctz(x: T) -&gt; U</code></pre>4009 <pre><code class="zig">@ctz(x: T) -&gt; U</code></pre>
4308 <p>4010 <p>
4309 This function counts the number of trailing zeroes in <code>x</code> which is an integer4011 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...@@ -4316,7 +4018,8 @@ test.zig:6:2: error: found compile log statement
4316 <p>4018 <p>
4317 If <code>x</code> is zero, <code>@ctz</code> returns <code>T.bit_count</code>.4019 If <code>x</code> is zero, <code>@ctz</code> returns <code>T.bit_count</code>.
4318 </p>4020 </p>
4319 <h3 id="builtin-divExact">@divExact</h3>4021 {#header_close#}
4022 {#header_open|@divExact#}
4320 <pre><code class="zig">@divExact(numerator: T, denominator: T) -&gt; T</code></pre>4023 <pre><code class="zig">@divExact(numerator: T, denominator: T) -&gt; T</code></pre>
4321 <p>4024 <p>
4322 Exact division. Caller guarantees <code>denominator != 0</code> and4025 Exact division. Caller guarantees <code>denominator != 0</code> and
...@@ -4326,13 +4029,10 @@ test.zig:6:2: error: found compile log statement...@@ -4326,13 +4029,10 @@ test.zig:6:2: error: found compile log statement
4326 <li><code>@divExact(6, 3) == 2</code></li>4029 <li><code>@divExact(6, 3) == 2</code></li>
4327 <li><code>@divExact(a, b) * b == a</code></li>4030 <li><code>@divExact(a, b) * b == a</code></li>
4328 </ul>4031 </ul>
4329 <p>See also:</p>4032 <p>For a function that returns a possible error code, use <code>@import("std").math.divExact</code>.</p>
4330 <ul>4033 {#see_also|@divTrunc|@divFloor#}
4331 <li><a href="#builtin-divTrunc">@divTrunc</a></li>4034 {#header_close#}
4332 <li><a href="#builtin-divFloor">@divFloor</a></li>4035 {#header_open|@divFloor#}
4333 <li><code>@import("std").math.divExact</code></li>
4334 </ul>
4335 <h3 id="builtin-divFloor">@divFloor</h3>
4336 <pre><code class="zig">@divFloor(numerator: T, denominator: T) -&gt; T</code></pre>4036 <pre><code class="zig">@divFloor(numerator: T, denominator: T) -&gt; T</code></pre>
4337 <p>4037 <p>
4338 Floored division. Rounds toward negative infinity. For unsigned integers it is4038 Floored division. Rounds toward negative infinity. For unsigned integers it is
...@@ -4343,13 +4043,10 @@ test.zig:6:2: error: found compile log statement...@@ -4343,13 +4043,10 @@ test.zig:6:2: error: found compile log statement
4343 <li><code>@divFloor(-5, 3) == -2</code></li>4043 <li><code>@divFloor(-5, 3) == -2</code></li>
4344 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>4044 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
4345 </ul>4045 </ul>
4346 <p>See also:</p>4046 <p>For a function that returns a possible error code, use <code>@import("std").math.divFloor</code>.</p>
4347 <ul>4047 {#see_also|@divTrunc|@divExact#}
4348 <li><a href="#builtin-divTrunc">@divTrunc</a></li>4048 {#header_close#}
4349 <li><a href="#builtin-divExact">@divExact</a></li>4049 {#header_open|@divTrunc#}
4350 <li><code>@import("std").math.divFloor</code></li>
4351 </ul>
4352 <h3 id="builtin-divTrunc">@divTrunc</h3>
4353 <pre><code class="zig">@divTrunc(numerator: T, denominator: T) -&gt; T</code></pre>4050 <pre><code class="zig">@divTrunc(numerator: T, denominator: T) -&gt; T</code></pre>
4354 <p>4051 <p>
4355 Truncated division. Rounds toward zero. For unsigned integers it is4052 Truncated division. Rounds toward zero. For unsigned integers it is
...@@ -4360,13 +4057,10 @@ test.zig:6:2: error: found compile log statement...@@ -4360,13 +4057,10 @@ test.zig:6:2: error: found compile log statement
4360 <li><code>@divTrunc(-5, 3) == -1</code></li>4057 <li><code>@divTrunc(-5, 3) == -1</code></li>
4361 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>4058 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
4362 </ul>4059 </ul>
4363 <p>See also:</p>4060 <p>For a function that returns a possible error code, use <code>@import("std").math.divTrunc</code>.</p>
4364 <ul>4061 {#see_also|@divFloor|@divExact#}
4365 <li><a href="#builtin-divFloor">@divFloor</a></li>4062 {#header_close#}
4366 <li><a href="#builtin-divExact">@divExact</a></li>4063 {#header_open|@embedFile#}
4367 <li><code>@import("std").math.divTrunc</code></li>
4368 </ul>
4369 <h3 id="builtin-embedFile">@embedFile</h3>
4370 <pre><code class="zig">@embedFile(comptime path: []const u8) -&gt; [X]u8</code></pre>4064 <pre><code class="zig">@embedFile(comptime path: []const u8) -&gt; [X]u8</code></pre>
4371 <p>4065 <p>
4372 This function returns a compile time constant fixed-size array with length4066 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...@@ -4376,21 +4070,21 @@ test.zig:6:2: error: found compile log statement
4376 <p>4070 <p>
4377 <code>path</code> is absolute or relative to the current file, just like <code>@import</code>.4071 <code>path</code> is absolute or relative to the current file, just like <code>@import</code>.
4378 </p>4072 </p>
4379 <p>See also:</p>4073 {#see_also|@import#}
4380 <ul>4074 {#header_close#}
4381 <li><a href="#builtin-import">@import</a></li>4075 {#header_open|@export#}
4382 </ul>
4383 <h3 id="builtin-export">@export</h3>
4384 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) -&gt; []const u8</code></pre>4076 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) -&gt; []const u8</code></pre>
4385 <p>4077 <p>
4386 Creates a symbol in the output object file.4078 Creates a symbol in the output object file.
4387 </p>4079 </p>
4388 <h3 id="builtin-tagName">@tagName</h3>4080 {#header_close#}
4081 {#header_open|@tagName#}
4389 <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre>4082 <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre>
4390 <p>4083 <p>
4391 Converts an enum value or union value to a slice of bytes representing the name.4084 Converts an enum value or union value to a slice of bytes representing the name.
4392 </p>4085 </p>
4393 <h3 id="builtin-TagType">@TagType</h3>4086 {#header_close#}
4087 {#header_open|@TagType#}
4394 <pre><code class="zig">@TagType(T: type) -&gt; type</code></pre>4088 <pre><code class="zig">@TagType(T: type) -&gt; type</code></pre>
4395 <p>4089 <p>
4396 For an enum, returns the integer type that is used to store the enumeration value.4090 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...@@ -4398,7 +4092,8 @@ test.zig:6:2: error: found compile log statement
4398 <p>4092 <p>
4399 For a union, returns the enum type that is used to store the tag value.4093 For a union, returns the enum type that is used to store the tag value.
4400 </p>4094 </p>
4401 <h3 id="builtin-errorName">@errorName</h3>4095 {#header_close#}
4096 {#header_open|@errorName#}
4402 <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre>4097 <pre><code class="zig">@errorName(err: error) -&gt; []u8</code></pre>
4403 <p>4098 <p>
4404 This function returns the string representation of an error. If an error4099 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...@@ -4413,14 +4108,16 @@ test.zig:6:2: error: found compile log statement
4413 or all calls have a compile-time known value for <code>err</code>, then no4108 or all calls have a compile-time known value for <code>err</code>, then no
4414 error name table will be generated.4109 error name table will be generated.
4415 </p>4110 </p>
4416 <h3 id="builtin-errorReturnTrace">@errorReturnTrace</h3>4111 {#header_close#}
4112 {#header_open|@errorReturnTrace#}
4417 <pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre>4113 <pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre>
4418 <p>4114 <p>
4419 If the binary is built with error return tracing, and this function is invoked in a4115 If the binary is built with error return tracing, and this function is invoked in a
4420 function that calls a function with an error or error union return type, returns a4116 function that calls a function with an error or error union return type, returns a
4421 stack trace object. Otherwise returns `null`.4117 stack trace object. Otherwise returns `null`.
4422 </p>4118 </p>
4423 <h3 id="builtin-fence">@fence</h3>4119 {#header_close#}
4120 {#header_open|@fence#}
4424 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>4121 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
4425 <p>4122 <p>
4426 The <code>fence</code> function is used to introduce happens-before edges between operations.4123 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...@@ -4428,17 +4125,16 @@ test.zig:6:2: error: found compile log statement
4428 <p>4125 <p>
4429 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.4126 <code>AtomicOrder</code> can be found with <code>@import("builtin").AtomicOrder</code>.
4430 </p>4127 </p>
4431 <p>See also:</p>4128 {#see_also|Compile Variables#}
4432 <ul>4129 {#header_close#}
4433 <li><a href="#compile-variables">Compile Variables</a></li>4130 {#header_open|@fieldParentPtr#}
4434 </ul>
4435 <h3 id="builtin-fieldParentPtr">@fieldParentPtr</h3>
4436 <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,4131 <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
4437 field_ptr: &amp;T) -&gt; &amp;ParentType</code></pre>4132 field_ptr: &amp;T) -&gt; &amp;ParentType</code></pre>
4438 <p>4133 <p>
4439 Given a pointer to a field, returns the base pointer of a struct.4134 Given a pointer to a field, returns the base pointer of a struct.
4440 </p>4135 </p>
4441 <h3 id="builtin-frameAddress">@frameAddress</h3>4136 {#header_close#}
4137 {#header_open|@frameAddress#}
4442 <pre><code class="zig">@frameAddress()</code></pre>4138 <pre><code class="zig">@frameAddress()</code></pre>
4443 <p>4139 <p>
4444 This function returns the base pointer of the current stack frame.4140 This function returns the base pointer of the current stack frame.
...@@ -4451,7 +4147,8 @@ test.zig:6:2: error: found compile log statement...@@ -4451,7 +4147,8 @@ test.zig:6:2: error: found compile log statement
4451 <p>4147 <p>
4452 This function is only valid within function scope.4148 This function is only valid within function scope.
4453 </p>4149 </p>
4454 <h3 id="builtin-import">@import</h3>4150 {#header_close#}
4151 {#header_open|@import#}
4455 <pre><code class="zig">@import(comptime path: []u8) -&gt; (namespace)</code></pre>4152 <pre><code class="zig">@import(comptime path: []u8) -&gt; (namespace)</code></pre>
4456 <p>4153 <p>
4457 This function finds a zig file corresponding to <code>path</code> and imports all the4154 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...@@ -4469,12 +4166,9 @@ test.zig:6:2: error: found compile log statement
4469 <li><code>@import("std")</code> - Zig Standard Library</li>4166 <li><code>@import("std")</code> - Zig Standard Library</li>
4470 <li><code>@import("builtin")</code> - Compiler-provided types and variables</li>4167 <li><code>@import("builtin")</code> - Compiler-provided types and variables</li>
4471 </ul>4168 </ul>
4472 <p>See also:</p>4169 {#see_also|Compile Variables|@embedFile#}
4473 <ul>4170 {#header_close#}
4474 <li><a href="#compile-variables">Compile Variables</a></li>4171 {#header_open|@inlineCall#}
4475 <li><a href="#builtin-embedFile">@embedFile</a></li>
4476 </ul>
4477 <h3 id="builtin-inlineCall">@inlineCall</h3>
4478 <pre><code class="zig">@inlineCall(function: X, args: ...) -&gt; Y</code></pre>4172 <pre><code class="zig">@inlineCall(function: X, args: ...) -&gt; Y</code></pre>
4479 <p>4173 <p>
4480 This calls a function, in the same way that invoking an expression with parentheses does:4174 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>...@@ -4489,21 +4183,21 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4489 Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call4183 Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call
4490 will be inlined. If the call cannot be inlined, a compile error is emitted.4184 will be inlined. If the call cannot be inlined, a compile error is emitted.
4491 </p>4185 </p>
4492 <p>See also:</p>4186 {#see_also|@noInlineCall#}
4493 <ul>4187 {#header_close#}
4494 <li><a href="#builtin-noInlineCall">@noInlineCall</a></li>4188 {#header_open|@intToPtr#}
4495 </ul>
4496 <h3 id="builtin-intToPtr">@intToPtr</h3>
4497 <pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) -&gt; DestType</code></pre>4189 <pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) -&gt; DestType</code></pre>
4498 <p>4190 <p>
4499 Converts an integer to a pointer. To convert the other way, use <a href="#builtin-ptrToInt">@ptrToInt</a>.4191 Converts an integer to a pointer. To convert the other way, use <a href="#builtin-ptrToInt">@ptrToInt</a>.
4500 </p>4192 </p>
4501 <h3 id="builtin-IntType">@IntType</h3>4193 {#header_close#}
4194 {#header_open|@IntType#}
4502 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u8) -&gt; type</code></pre>4195 <pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u8) -&gt; type</code></pre>
4503 <p>4196 <p>
4504 This function returns an integer type with the given signness and bit count.4197 This function returns an integer type with the given signness and bit count.
4505 </p>4198 </p>
4506 <h3 id="builtin-maxValue">@maxValue</h3>4199 {#header_close#}
4200 {#header_open|@maxValue#}
4507 <pre><code class="zig">@maxValue(comptime T: type) -&gt; (number literal)</code></pre>4201 <pre><code class="zig">@maxValue(comptime T: type) -&gt; (number literal)</code></pre>
4508 <p>4202 <p>
4509 This function returns the maximum value of the integer type <code>T</code>.4203 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>...@@ -4511,7 +4205,8 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4511 <p>4205 <p>
4512 The result is a compile time constant.4206 The result is a compile time constant.
4513 </p>4207 </p>
4514 <h3 id="builtin-memberCount">@memberCount</h3>4208 {#header_close#}
4209 {#header_open|@memberCount#}
4515 <pre><code class="zig">@memberCount(comptime T: type) -&gt; (number literal)</code></pre>4210 <pre><code class="zig">@memberCount(comptime T: type) -&gt; (number literal)</code></pre>
4516 <p>4211 <p>
4517 This function returns the number of enum values in an enum type.4212 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>...@@ -4519,11 +4214,14 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4519 <p>4214 <p>
4520 The result is a compile time constant.4215 The result is a compile time constant.
4521 </p>4216 </p>
4522 <h3 id="builtin-memberName">@memberName</h3>4217 {#header_close#}
4218 {#header_open|@memberName#}
4523 <p>TODO</p>4219 <p>TODO</p>
4524 <h3 id="builtin-memberType">@memberType</h3>4220 {#header_close#}
4221 {#header_open|@memberType#}
4525 <p>TODO</p>4222 <p>TODO</p>
4526 <h3 id="builtin-memcpy">@memcpy</h3>4223 {#header_close#}
4224 {#header_open|@memcpy#}
4527 <pre><code class="zig">@memcpy(noalias dest: &amp;u8, noalias source: &amp;const u8, byte_count: usize)</code></pre>4225 <pre><code class="zig">@memcpy(noalias dest: &amp;u8, noalias source: &amp;const u8, byte_count: usize)</code></pre>
4528 <p>4226 <p>
4529 This function copies bytes from one region of memory to another. <code>dest</code> and4227 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>...@@ -4540,7 +4238,8 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4540 <p>There is also a standard library function for this:</p>4238 <p>There is also a standard library function for this:</p>
4541 <pre><code class="zig">const mem = @import("std").mem;4239 <pre><code class="zig">const mem = @import("std").mem;
4542mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>4240mem.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#}
4544 <pre><code class="zig">@memset(dest: &amp;u8, c: u8, byte_count: usize)</code></pre>4243 <pre><code class="zig">@memset(dest: &amp;u8, c: u8, byte_count: usize)</code></pre>
4545 <p>4244 <p>
4546 This function sets a region of memory to <code>c</code>. <code>dest</code> is a pointer.4245 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>...@@ -4556,7 +4255,8 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
4556 <p>There is also a standard library function for this:</p>4255 <p>There is also a standard library function for this:</p>
4557 <pre><code>const mem = @import("std").mem;4256 <pre><code>const mem = @import("std").mem;
4558mem.set(u8, dest, c);</code></pre>4257mem.set(u8, dest, c);</code></pre>
4559 <h3 id="builtin-minValue">@minValue</h3>4258 {#header_close#}
4259 {#header_open|@minValue#}
4560 <pre><code class="zig">@minValue(comptime T: type) -&gt; (number literal)</code></pre>4260 <pre><code class="zig">@minValue(comptime T: type) -&gt; (number literal)</code></pre>
4561 <p>4261 <p>
4562 This function returns the minimum value of the integer type T.4262 This function returns the minimum value of the integer type T.
...@@ -4564,7 +4264,8 @@ mem.set(u8, dest, c);</code></pre>...@@ -4564,7 +4264,8 @@ mem.set(u8, dest, c);</code></pre>
4564 <p>4264 <p>
4565 The result is a compile time constant.4265 The result is a compile time constant.
4566 </p>4266 </p>
4567 <h3 id="builtin-mod">@mod</h3>4267 {#header_close#}
4268 {#header_open|@mod#}
4568 <pre><code class="zig">@mod(numerator: T, denominator: T) -&gt; T</code></pre>4269 <pre><code class="zig">@mod(numerator: T, denominator: T) -&gt; T</code></pre>
4569 <p>4270 <p>
4570 Modulus division. For unsigned integers this is the same as4271 Modulus division. For unsigned integers this is the same as
...@@ -4574,19 +4275,18 @@ mem.set(u8, dest, c);</code></pre>...@@ -4574,19 +4275,18 @@ mem.set(u8, dest, c);</code></pre>
4574 <li><code>@mod(-5, 3) == 1</code></li>4275 <li><code>@mod(-5, 3) == 1</code></li>
4575 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>4276 <li><code>@divFloor(a, b) + @mod(a, b) == a</code></li>
4576 </ul>4277 </ul>
4577 <p>See also:</p>4278 <p>For a function that returns an error code, see <code>@import("std").math.mod</code>.</p>
4578 <ul>4279 {#see_also|@rem#}
4579 <li><a href="#builtin-rem">@rem</a></li>4280 {#header_close#}
4580 <li><code>@import("std").math.mod</code></li>4281 {#header_open|@mulWithOverflow#}
4581 </ul>
4582 <h3 id="builtin-mulWithOverflow">@mulWithOverflow</h3>
4583 <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>4282 <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
4584 <p>4283 <p>
4585 Performs <code>*result = a * b</code>. If overflow or underflow occurs,4284 Performs <code>*result = a * b</code>. If overflow or underflow occurs,
4586 stores the overflowed bits in <code>result</code> and returns <code>true</code>.4285 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
4587 If no overflow or underflow occurs, returns <code>false</code>.4286 If no overflow or underflow occurs, returns <code>false</code>.
4588 </p>4287 </p>
4589 <h3 id="builtin-noInlineCall">@noInlineCall</h3>4288 {#header_close#}
4289 {#header_open|@noInlineCall#}
4590 <pre><code class="zig">@noInlineCall(function: var, args: ...) -&gt; var</code></pre>4290 <pre><code class="zig">@noInlineCall(function: var, args: ...) -&gt; var</code></pre>
4591 <p>4291 <p>
4592 This calls a function, in the same way that invoking an expression with parentheses does:4292 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>...@@ -4601,16 +4301,15 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4601 Unlike a normal function call, however, <code>@noInlineCall</code> guarantees that the call4301 Unlike a normal function call, however, <code>@noInlineCall</code> guarantees that the call
4602 will not be inlined. If the call must be inlined, a compile error is emitted.4302 will not be inlined. If the call must be inlined, a compile error is emitted.
4603 </p>4303 </p>
4604 <p>See also:</p>4304 {#see_also|@inlineCall#}
4605 <ul>4305 {#header_close#}
4606 <li><a href="#builtin-inlineCall">@inlineCall</a></li>4306 {#header_open|@offsetOf#}
4607 </ul>
4608 <h3 id="builtin-offsetOf">@offsetOf</h3>
4609 <pre><code class="zig">@offsetOf(comptime T: type, comptime field_name: [] const u8) -&gt; (number literal)</code></pre>4307 <pre><code class="zig">@offsetOf(comptime T: type, comptime field_name: [] const u8) -&gt; (number literal)</code></pre>
4610 <p>4308 <p>
4611 This function returns the byte offset of a field relative to its containing struct.4309 This function returns the byte offset of a field relative to its containing struct.
4612 </p>4310 </p>
4613 <h3 id="builtin-OpaqueType">@OpaqueType</h3>4311 {#header_close#}
4312 {#header_open|@OpaqueType#}
4614 <pre><code class="zig">@OpaqueType() -&gt; type</code></pre>4313 <pre><code class="zig">@OpaqueType() -&gt; type</code></pre>
4615 <p>4314 <p>
4616 Creates a new type with an unknown size and alignment.4315 Creates a new type with an unknown size and alignment.
...@@ -4630,7 +4329,8 @@ export fn foo(w: &amp;Wat) {...@@ -4630,7 +4329,8 @@ export fn foo(w: &amp;Wat) {
4630test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'4329test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4631 bar(w);4330 bar(w);
4632 ^</code></pre>4331 ^</code></pre>
4633 <h3 id="builtin-panic">@panic</h3>4332 {#header_close#}
4333 {#header_open|@panic#}
4634 <pre><code class="zig">@panic(message: []const u8) -&gt; noreturn</code></pre>4334 <pre><code class="zig">@panic(message: []const u8) -&gt; noreturn</code></pre>
4635 <p>4335 <p>
4636 Invokes the panic handler function. By default the panic handler function4336 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'...@@ -4644,17 +4344,15 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4644 <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li>4344 <li>From library code, calling the programmer's panic function if they exposed one in the root source file.</li>
4645 <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li>4345 <li>When mixing C and Zig code, calling the canonical panic implementation across multiple .o files.</li>
4646 </ul>4346 </ul>
4647 <p>See also:</p>4347 {#see_also|Root Source File#}
4648 <ul>4348 {#header_close#}
4649 <li><a href="#root-source-file">Root Source File</a></li>4349 {#header_open|@ptrCast#}
4650 </ul>
4651
4652 <h3 id="builtin-ptrCast">@ptrCast</h3>
4653 <pre><code class="zig">@ptrCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>4350 <pre><code class="zig">@ptrCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
4654 <p>4351 <p>
4655 Converts a pointer of one type to a pointer of another type.4352 Converts a pointer of one type to a pointer of another type.
4656 </p>4353 </p>
4657 <h3 id="builtin-ptrToInt">@ptrToInt</h3>4354 {#header_close#}
4355 {#header_open|@ptrToInt#}
4658 <pre><code class="zig">@ptrToInt(value: var) -&gt; usize</code></pre>4356 <pre><code class="zig">@ptrToInt(value: var) -&gt; usize</code></pre>
4659 <p>4357 <p>
4660 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:4358 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'...@@ -4667,7 +4365,8 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4667 </ul>4365 </ul>
4668 <p>To convert the other way, use <a href="#builtin-intToPtr">@intToPtr</a></p>4366 <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#}
4671 <pre><code class="zig">@rem(numerator: T, denominator: T) -&gt; T</code></pre>4370 <pre><code class="zig">@rem(numerator: T, denominator: T) -&gt; T</code></pre>
4672 <p>4371 <p>
4673 Remainder division. For unsigned integers this is the same as4372 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'...@@ -4677,12 +4376,10 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4677 <li><code>@rem(-5, 3) == -2</code></li>4376 <li><code>@rem(-5, 3) == -2</code></li>
4678 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>4377 <li><code>@divTrunc(a, b) + @rem(a, b) == a</code></li>
4679 </ul>4378 </ul>
4680 <p>See also:</p>4379 <p>For a function that returns an error code, see <code>@import("std").math.rem</code>.</p>
4681 <ul>4380 {#see_also|@mod#}
4682 <li><a href="#builtin-mod">@mod</a></li>4381 {#header_close#}
4683 <li><code>@import("std").math.rem</code></li>4382 {#header_open|@returnAddress#}
4684 </ul>
4685 <h3 id="builtin-returnAddress">@returnAddress</h3>
4686 <pre><code class="zig">@returnAddress()</code></pre>4383 <pre><code class="zig">@returnAddress()</code></pre>
4687 <p>4384 <p>
4688 This function returns a pointer to the return address of the current stack4385 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'...@@ -4695,14 +4392,15 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4695 <p>4392 <p>
4696 This function is only valid within function scope.4393 This function is only valid within function scope.
4697 </p>4394 </p>
46984395 {#header_close#}
4699 <h3 id="builtin-setDebugSafety">@setDebugSafety</h3>4396 {#header_open|@setDebugSafety#}
4700 <pre><code class="zig">@setDebugSafety(scope, safety_on: bool)</code></pre>4397 <pre><code class="zig">@setDebugSafety(scope, safety_on: bool)</code></pre>
4701 <p>4398 <p>
4702 Sets whether debug safety checks are on for a given scope.4399 Sets whether debug safety checks are on for a given scope.
4703 </p>4400 </p>
47044401
4705 <h3 id="builtin-setEvalBranchQuota">@setEvalBranchQuota</h3>4402 {#header_close#}
4403 {#header_open|@setEvalBranchQuota#}
4706 <pre><code class="zig">@setEvalBranchQuota(new_quota: usize)</code></pre>4404 <pre><code class="zig">@setEvalBranchQuota(new_quota: usize)</code></pre>
4707 <p>4405 <p>
4708 Changes the maximum number of backwards branches that compile-time code4406 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'...@@ -4732,12 +4430,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4732 <pre><code class="sh">$ ./zig build-obj test.zig</code></pre>4430 <pre><code class="sh">$ ./zig build-obj test.zig</code></pre>
4733 <p>(no output because it worked fine)</p>4431 <p>(no output because it worked fine)</p>
47344432
4735 <p>See also:</p>4433 {#see_also|comptime#}
4736 <ul>4434 {#header_close#}
4737 <li><a href="#comptime">comptime</a></li>4435 {#header_open|@setFloatMode#}
4738 </ul>
4739
4740 <h3 id="builtin-setFloatMode">@setFloatMode</h3>
4741 <pre><code class="zig">@setFloatMode(scope, mode: @import("builtin").FloatMode)</code></pre>4436 <pre><code class="zig">@setFloatMode(scope, mode: @import("builtin").FloatMode)</code></pre>
4742 <p>4437 <p>
4743 Sets the floating point mode for a given scope. Possible values are:4438 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'...@@ -4763,26 +4458,22 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4763 <code>Strict</code> - Floating point operations follow strict IEEE compliance.4458 <code>Strict</code> - Floating point operations follow strict IEEE compliance.
4764 </li>4459 </li>
4765 </ul>4460 </ul>
4766 <p>See also:</p>4461 {#see_also|Floating Point Operations#}
4767 <ul>4462 {#header_close#}
4768 <li><a href="#float-operations">Floating Point Operations</a></li>4463 {#header_open|@setGlobalLinkage#}
4769 </ul>
4770
4771 <h3 id="builtin-setGlobalLinkage">@setGlobalLinkage</h3>
4772 <pre><code class="zig">@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage)</code></pre>4464 <pre><code class="zig">@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage)</code></pre>
4773 <p>4465 <p>
4774 <code>GlobalLinkage</code> can be found with <code>@import("builtin").GlobalLinkage</code>.4466 <code>GlobalLinkage</code> can be found with <code>@import("builtin").GlobalLinkage</code>.
4775 </p>4467 </p>
4776 <p>See also:</p>4468 {#see_also|Compile Variables#}
4777 <ul>4469 {#header_close#}
4778 <li><a href="#compile-variables">Compile Variables</a></li>4470 {#header_open|@setGlobalSection#}
4779 </ul>
4780 <h3 id="builtin-setGlobalSection">@setGlobalSection</h3>
4781 <pre><code class="zig">@setGlobalSection(global_variable_name, comptime section_name: []const u8) -&gt; bool</code></pre>4471 <pre><code class="zig">@setGlobalSection(global_variable_name, comptime section_name: []const u8) -&gt; bool</code></pre>
4782 <p>4472 <p>
4783 Puts the global variable in the specified section.4473 Puts the global variable in the specified section.
4784 </p>4474 </p>
4785 <h3 id="builtin-shlExact">@shlExact</h3>4475 {#header_close#}
4476 {#header_open|@shlExact#}
4786 <pre><code class="zig">@shlExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>4477 <pre><code class="zig">@shlExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>
4787 <p>4478 <p>
4788 Performs the left shift operation (<code>&lt;&lt;</code>). Caller guarantees4479 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'...@@ -4792,12 +4483,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4792 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.4483 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
4793 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.4484 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
4794 </p>4485 </p>
4795 <p>See also:</p>4486 {#see_also|@shrExact|@shlWithOverflow#}
4796 <ul>4487 {#header_close#}
4797 <li><a href="#builtin-shrExact">@shrExact</a></li>4488 {#header_open|@shlWithOverflow#}
4798 <li><a href="#builtin-shlWithOverflow">@shlWithOverflow</a></li>
4799 </ul>
4800 <h3 id="builtin-shlWithOverflow">@shlWithOverflow</h3>
4801 <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &amp;T) -&gt; bool</code></pre>4489 <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &amp;T) -&gt; bool</code></pre>
4802 <p>4490 <p>
4803 Performs <code>*result = a &lt;&lt; b</code>. If overflow or underflow occurs,4491 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'...@@ -4808,12 +4496,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4808 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.4496 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
4809 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.4497 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
4810 </p>4498 </p>
4811 <p>See also:</p>4499 {#see_also|@shlExact|@shrExact#}
4812 <ul>4500 {#header_close#}
4813 <li><a href="#builtin-shlExact">@shlExact</a></li>4501 {#header_open|@shrExact#}
4814 <li><a href="#builtin-shrExact">@shrExact</a></li>
4815 </ul>
4816 <h3 id="builtin-shrExact">@shrExact</h3>
4817 <pre><code class="zig">@shrExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>4502 <pre><code class="zig">@shrExact(value: T, shift_amt: Log2T) -&gt; T</code></pre>
4818 <p>4503 <p>
4819 Performs the right shift operation (<code>&gt;&gt;</code>). Caller guarantees4504 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'...@@ -4823,11 +4508,9 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4823 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.4508 The type of <code>shift_amt</code> is an unsigned integer with <code>log2(T.bit_count)</code> bits.
4824 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.4509 This is because <code>shift_amt &gt;= T.bit_count</code> is undefined behavior.
4825 </p>4510 </p>
4826 <p>See also:</p>4511 {#see_also|@shlExact|@shlWithOverflow#}
4827 <ul>4512 {#header_close#}
4828 <li><a href="#builtin-shlExact">@shlExact</a></li>4513 {#header_open|@sizeOf#}
4829 </ul>
4830 <h3 id="builtin-sizeOf">@sizeOf</h3>
4831 <pre><code class="zig">@sizeOf(comptime T: type) -&gt; (number literal)</code></pre>4514 <pre><code class="zig">@sizeOf(comptime T: type) -&gt; (number literal)</code></pre>
4832 <p>4515 <p>
4833 This function returns the number of bytes it takes to store <code>T</code> in memory.4516 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'...@@ -4835,14 +4518,16 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat'
4835 <p>4518 <p>
4836 The result is a target-specific compile time constant.4519 The result is a target-specific compile time constant.
4837 </p>4520 </p>
4838 <h3 id="builtin-subWithOverflow">@subWithOverflow</h3>4521 {#header_close#}
4522 {#header_open|@subWithOverflow#}
4839 <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>4523 <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre>
4840 <p>4524 <p>
4841 Performs <code>*result = a - b</code>. If overflow or underflow occurs,4525 Performs <code>*result = a - b</code>. If overflow or underflow occurs,
4842 stores the overflowed bits in <code>result</code> and returns <code>true</code>.4526 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
4843 If no overflow or underflow occurs, returns <code>false</code>.4527 If no overflow or underflow occurs, returns <code>false</code>.
4844 </p>4528 </p>
4845 <h3 id="builtin-truncate">@truncate</h3>4529 {#header_close#}
4530 {#header_open|@truncate#}
4846 <pre><code class="zig">@truncate(comptime T: type, integer) -&gt; T</code></pre>4531 <pre><code class="zig">@truncate(comptime T: type, integer) -&gt; T</code></pre>
4847 <p>4532 <p>
4848 This function truncates bits from an integer type, resulting in a smaller4533 This function truncates bits from an integer type, resulting in a smaller
...@@ -4865,7 +4550,8 @@ const b: u8 = @truncate(u8, a);...@@ -4865,7 +4550,8 @@ const b: u8 = @truncate(u8, a);
4865 of endianness on the target platform.4550 of endianness on the target platform.
4866 </p>4551 </p>
48674552
4868 <h3 id="builtin-typeId">@typeId</h3>4553 {#header_close#}
4554 {#header_open|@typeId#}
4869 <pre><code class="zig">@typeId(comptime T: type) -&gt; @import("builtin").TypeId</code></pre>4555 <pre><code class="zig">@typeId(comptime T: type) -&gt; @import("builtin").TypeId</code></pre>
4870 <p>4556 <p>
4871 Returns which kind of type something is. Possible values:4557 Returns which kind of type something is. Possible values:
...@@ -4898,20 +4584,24 @@ const b: u8 = @truncate(u8, a);...@@ -4898,20 +4584,24 @@ const b: u8 = @truncate(u8, a);
4898 Opaque,4584 Opaque,
4899};</code></pre>4585};</code></pre>
49004586
4901 <h3 id="builtin-typeName">@typeName</h3>4587 {#header_close#}
4588 {#header_open|@typeName#}
4902 <pre><code class="zig">@typeName(T: type) -&gt; []u8</code></pre>4589 <pre><code class="zig">@typeName(T: type) -&gt; []u8</code></pre>
4903 <p>4590 <p>
4904 This function returns the string representation of a type.4591 This function returns the string representation of a type.
4905 </p>4592 </p>
49064593
4907 <h3 id="builtin-typeOf">@typeOf</h3>4594 {#header_close#}
4595 {#header_open|@typeOf#}
4908 <pre><code class="zig">@typeOf(expression) -&gt; type</code></pre>4596 <pre><code class="zig">@typeOf(expression) -&gt; type</code></pre>
4909 <p>4597 <p>
4910 This function returns a compile-time constant, which is the type of the4598 This function returns a compile-time constant, which is the type of the
4911 expression passed as an argument. The expression is evaluated.4599 expression passed as an argument. The expression is evaluated.
4912 </p>4600 </p>
49134601
4914 <h2 id="build-mode">Build Mode</h2>4602 {#header_close#}
4603 {#header_close#}
4604 {#header_open|Build Mode#}
4915 <p>4605 <p>
4916 Zig has three build modes:4606 Zig has three build modes:
4917 </p>4607 </p>
...@@ -4935,34 +4625,33 @@ pub fn build(b: &amp;Builder) {...@@ -4935,34 +4625,33 @@ pub fn build(b: &amp;Builder) {
4935 </p>4625 </p>
4936 <pre><code class="sh"> -Drelease-safe=(bool) optimizations on and safety on4626 <pre><code class="sh"> -Drelease-safe=(bool) optimizations on and safety on
4937 -Drelease-fast=(bool) optimizations on and safety off</code></pre>4627 -Drelease-fast=(bool) optimizations on and safety off</code></pre>
4938 <h3 id="build-mode-debug">Debug</h2>4628 {#header_open|Debug#}
4939 <pre><code class="sh">$ zig build-exe example.zig</code></pre>4629 <pre><code class="sh">$ zig build-exe example.zig</code></pre>
4940 <ul>4630 <ul>
4941 <li>Fast compilation speed</li>4631 <li>Fast compilation speed</li>
4942 <li>Safety checks enabled</li>4632 <li>Safety checks enabled</li>
4943 <li>Slow runtime performance</li>4633 <li>Slow runtime performance</li>
4944 </ul>4634 </ul>
4945 <h3 id="build-mode-release-fast">ReleaseFast</h2>4635 {#header_close#}
4636 {#header_open|ReleaseFast#}
4946 <pre><code class="sh">$ zig build-exe example.zig --release-fast</code></pre>4637 <pre><code class="sh">$ zig build-exe example.zig --release-fast</code></pre>
4947 <ul>4638 <ul>
4948 <li>Fast runtime performance</li>4639 <li>Fast runtime performance</li>
4949 <li>Safety checks disabled</li>4640 <li>Safety checks disabled</li>
4950 <li>Slow compilation speed</li>4641 <li>Slow compilation speed</li>
4951 </ul>4642 </ul>
4952 <h3 id="build-mode-release-safe">ReleaseSafe</h2>4643 {#header_close#}
4644 {#header_open|ReleaseSafe#}
4953 <pre><code class="sh">$ zig build-exe example.zig --release-safe</code></pre>4645 <pre><code class="sh">$ zig build-exe example.zig --release-safe</code></pre>
4954 <ul>4646 <ul>
4955 <li>Medium runtime performance</li>4647 <li>Medium runtime performance</li>
4956 <li>Safety checks enabled</li>4648 <li>Safety checks enabled</li>
4957 <li>Slow compilation speed</li>4649 <li>Slow compilation speed</li>
4958 </ul>4650 </ul>
4959 <p>See also:</p>4651 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
4960 <ul>4652 {#header_close#}
4961 <li><a href="#compile-variables">Compile Variables</a></li>4653 {#header_close#}
4962 <li><a href="#zig-build-system">Zig Build System</a></li>4654 {#header_open|Undefined Behavior#}
4963 <li><a href="#undefined-behavior">Undefined Behavior</a></li>
4964 </ul>
4965 <h2 id="undefined-behavior">Undefined Behavior</h2>
4966 <p>4655 <p>
4967 Zig has many instances of undefined behavior. If undefined behavior is4656 Zig has many instances of undefined behavior. If undefined behavior is
4968 detected at compile-time, Zig emits an error. Most undefined behavior that4657 detected at compile-time, Zig emits an error. Most undefined behavior that
...@@ -5000,7 +4689,7 @@ Test 1/1 safety check...reached unreachable code...@@ -5000,7 +4689,7 @@ Test 1/1 safety check...reached unreachable code
50004689
5001Tests failed. Use the following command to reproduce the failure:4690Tests failed. Use the following command to reproduce the failure:
5002./test</code></pre>4691./test</code></pre>
5003 <h3 id="undef-unreachable">Reaching Unreachable Code</h3>4692 {#header_open|Reaching Unreachable Code#}
5004 <p>At compile-time:</p>4693 <p>At compile-time:</p>
5005 <pre><code class="zig">comptime {4694 <pre><code class="zig">comptime {
5006 assert(false);4695 assert(false);
...@@ -5019,7 +4708,8 @@ fn assert(ok: bool) {...@@ -5019,7 +4708,8 @@ fn assert(ok: bool) {
5019comptime {4708comptime {
5020 ^</code></pre>4709 ^</code></pre>
5021 <p>At runtime crashes with the message <code>reached unreachable code</code> and a stack trace.</p>4710 <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#}
5023 <p>At compile-time:</p>4713 <p>At compile-time:</p>
5024 <pre><code class="zig">comptime {4714 <pre><code class="zig">comptime {
5025 const array = "hello";4715 const array = "hello";
...@@ -5030,7 +4720,8 @@ comptime {...@@ -5030,7 +4720,8 @@ comptime {
5030 const garbage = array[5];4720 const garbage = array[5];
5031 ^</code></pre>4721 ^</code></pre>
5032 <p>At runtime crashes with the message <code>index out of bounds</code> and a stack trace.</p>4722 <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#}
5034 <p>At compile-time:</p>4725 <p>At compile-time:</p>
5035 <pre><code class="zig">comptime {4726 <pre><code class="zig">comptime {
5036 const value: i32 = -1;4727 const value: i32 = -1;
...@@ -5044,7 +4735,8 @@ comptime {...@@ -5044,7 +4735,8 @@ comptime {
5044 If you are trying to obtain the maximum value of an unsigned integer, use <code>@maxValue(T)</code>,4735 If you are trying to obtain the maximum value of an unsigned integer, use <code>@maxValue(T)</code>,
5045 where <code>T</code> is the integer type, such as <code>u32</code>.4736 where <code>T</code> is the integer type, such as <code>u32</code>.
5046 </p>4737 </p>
5047 <h3 id="undef-cast-truncates-data">Cast Truncates Data</h3>4738 {#header_close#}
4739 {#header_open|Cast Truncates Data#}
5048 <p>At compile-time:</p>4740 <p>At compile-time:</p>
5049 <pre><code class="zig">comptime {4741 <pre><code class="zig">comptime {
5050 const spartan_count: u16 = 300;4742 const spartan_count: u16 = 300;
...@@ -5060,8 +4752,9 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits...@@ -5060,8 +4752,9 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
5060 where <code>T</code> is the integer type, such as <code>u32</code>, and <code>value</code>4752 where <code>T</code> is the integer type, such as <code>u32</code>, and <code>value</code>
5061 is the value you want to truncate.4753 is the value you want to truncate.
5062 </p>4754 </p>
5063 <h3 id="undef-integer-overflow">Integer Overflow</h3>4755 {#header_close#}
5064 <h4 id="undef-int-overflow-default">Default Operations</h4>4756 {#header_open|Integer Overflow#}
4757 {#header_open|Default Operations#}
5065 <p>The following operators can cause integer overflow:</p>4758 <p>The following operators can cause integer overflow:</p>
5066 <ul>4759 <ul>
5067 <li><code>+</code> (addition)</li>4760 <li><code>+</code> (addition)</li>
...@@ -5083,7 +4776,8 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits...@@ -5083,7 +4776,8 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits
5083 byte += 1;4776 byte += 1;
5084 ^</code></pre>4777 ^</code></pre>
5085 <p>At runtime crashes with the message <code>integer overflow</code> and a stack trace.</p>4778 <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#}
5087 <p>These functions provided by the standard library return possible errors.</p>4781 <p>These functions provided by the standard library return possible errors.</p>
5088 <ul>4782 <ul>
5089 <li><code>@import("std").math.add</code></li>4783 <li><code>@import("std").math.add</code></li>
...@@ -5112,7 +4806,8 @@ pub fn main() -&gt; %void {...@@ -5112,7 +4806,8 @@ pub fn main() -&gt; %void {
5112 <pre><code class="sh">$ zig build-exe test.zig4806 <pre><code class="sh">$ zig build-exe test.zig
5113$ ./test4807$ ./test
5114unable to add one: Overflow</code></pre>4808unable 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#}
5116 <p>4811 <p>
5117 These builtins return a <code>bool</code> of whether or not overflow4812 These builtins return a <code>bool</code> of whether or not overflow
5118 occurred, as well as returning the overflowed bits:4813 occurred, as well as returning the overflowed bits:
...@@ -5140,7 +4835,8 @@ pub fn main() -&gt; %void {...@@ -5140,7 +4835,8 @@ pub fn main() -&gt; %void {
5140 <pre><code class="sh">$ zig build-exe test.zig4835 <pre><code class="sh">$ zig build-exe test.zig
5141$ ./test4836$ ./test
5142overflowed result: 9</code></pre>4837overflowed result: 9</code></pre>
5143 <h4 id="undef-int-overflow-wrap">Wrapping Operations</h4>4838 {#header_close#}
4839 {#header_open|Wrapping Operations#}
5144 <p>4840 <p>
5145 These operations have guaranteed wraparound semantics.4841 These operations have guaranteed wraparound semantics.
5146 </p>4842 </p>
...@@ -5159,7 +4855,9 @@ test "wraparound addition and subtraction" {...@@ -5159,7 +4855,9 @@ test "wraparound addition and subtraction" {
5159 const max_val = min_val -% 1;4855 const max_val = min_val -% 1;
5160 assert(max_val == @maxValue(i32));4856 assert(max_val == @maxValue(i32));
5161}</code></pre>4857}</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#}
5163 <p>At compile-time:</p>4861 <p>At compile-time:</p>
5164 <pre><code class="zig">comptime {4862 <pre><code class="zig">comptime {
5165 const x = @shlExact(u8(0b01010101), 2);4863 const x = @shlExact(u8(0b01010101), 2);
...@@ -5169,7 +4867,8 @@ test "wraparound addition and subtraction" {...@@ -5169,7 +4867,8 @@ test "wraparound addition and subtraction" {
5169 const x = @shlExact(u8(0b01010101), 2);4867 const x = @shlExact(u8(0b01010101), 2);
5170 ^</code></pre>4868 ^</code></pre>
5171 <p>At runtime crashes with the message <code>left shift overflowed bits</code> and a stack trace.</p>4869 <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#}
5173 <p>At compile-time:</p>4872 <p>At compile-time:</p>
5174 <pre><code class="zig">comptime {4873 <pre><code class="zig">comptime {
5175 const x = @shrExact(u8(0b10101010), 2);4874 const x = @shrExact(u8(0b10101010), 2);
...@@ -5179,7 +4878,8 @@ test "wraparound addition and subtraction" {...@@ -5179,7 +4878,8 @@ test "wraparound addition and subtraction" {
5179 const x = @shrExact(u8(0b10101010), 2);4878 const x = @shrExact(u8(0b10101010), 2);
5180 ^</code></pre>4879 ^</code></pre>
5181 <p>At runtime crashes with the message <code>right shift overflowed bits</code> and a stack trace.</p>4880 <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#}
5183 <p>At compile-time:</p>4883 <p>At compile-time:</p>
5184 <pre><code class="zig">comptime {4884 <pre><code class="zig">comptime {
5185 const a: i32 = 1;4885 const a: i32 = 1;
...@@ -5192,7 +4892,8 @@ test "wraparound addition and subtraction" {...@@ -5192,7 +4892,8 @@ test "wraparound addition and subtraction" {
5192 ^</code></pre>4892 ^</code></pre>
5193 <p>At runtime crashes with the message <code>division by zero</code> and a stack trace.</p>4893 <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#}
5196 <p>At compile-time:</p>4897 <p>At compile-time:</p>
5197 <pre><code class="zig">comptime {4898 <pre><code class="zig">comptime {
5198 const a: i32 = 10;4899 const a: i32 = 10;
...@@ -5205,11 +4906,14 @@ test "wraparound addition and subtraction" {...@@ -5205,11 +4906,14 @@ test "wraparound addition and subtraction" {
5205 ^</code></pre>4906 ^</code></pre>
5206 <p>At runtime crashes with the message <code>remainder division by zero</code> and a stack trace.</p>4907 <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#}
5209 <p>TODO</p>4911 <p>TODO</p>
5210 <h3 id="undef-slice-widen-remainder">Slice Widen Remainder</h3>4912 {#header_close#}
4913 {#header_open|Slice Widen Remainder#}
5211 <p>TODO</p>4914 <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#}
5213 <p>At compile-time:</p>4917 <p>At compile-time:</p>
5214 <pre><code class="zig">comptime {4918 <pre><code class="zig">comptime {
5215 const nullable_number: ?i32 = null;4919 const nullable_number: ?i32 = null;
...@@ -5222,8 +4926,9 @@ test "wraparound addition and subtraction" {...@@ -5222,8 +4926,9 @@ test "wraparound addition and subtraction" {
5222 <p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>4926 <p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>
5223 <p>One way to avoid this crash is to test for null instead of assuming non-null, with4927 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
5224 the <code>if</code> expression:</p>4928 the <code>if</code> expression:</p>
5225 <pre><code class="zig">const warn = @import("std").debug.warn;4929 {#code_begin|exe|test#}
5226pub fn main() -&gt; %void {4930const warn = @import("std").debug.warn;
4931pub fn main() {
5227 const nullable_number: ?i32 = null;4932 const nullable_number: ?i32 = null;
52284933
5229 if (nullable_number) |number| {4934 if (nullable_number) |number| {
...@@ -5231,11 +4936,10 @@ pub fn main() -&gt; %void {...@@ -5231,11 +4936,10 @@ pub fn main() -&gt; %void {
5231 } else {4936 } else {
5232 warn("it's null\n");4937 warn("it's null\n");
5233 }4938 }
5234}</code></pre>4939}
5235 <pre><code class="sh">% zig build-exe test.zig4940 {#code_end#}
5236$ ./test4941 {#header_close#}
5237it's null</code></pre>4942 {#header_open|Attempt to Unwrap Error#}
5238 <h3 id="undef-attempt-unwrap-error">Attempt to Unwrap Error</h3>
5239 <p>At compile-time:</p>4943 <p>At compile-time:</p>
5240 <pre><code class="zig">comptime {4944 <pre><code class="zig">comptime {
5241 const number = %%getNumberOrFail();4945 const number = %%getNumberOrFail();
...@@ -5253,9 +4957,10 @@ fn getNumberOrFail() -&gt; %i32 {...@@ -5253,9 +4957,10 @@ fn getNumberOrFail() -&gt; %i32 {
5253 <p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p>4957 <p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p>
5254 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with4958 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
5255 the <code>if</code> expression:</p>4959 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() {
5259 const result = getNumberOrFail();4964 const result = getNumberOrFail();
52604965
5261 if (result) |number| {4966 if (result) |number| {
...@@ -5267,14 +4972,12 @@ pub fn main() -&gt; %void {...@@ -5267,14 +4972,12 @@ pub fn main() -&gt; %void {
52674972
5268error UnableToReturnNumber;4973error UnableToReturnNumber;
52694974
5270fn getNumberOrFail() -&gt; %i32 {4975fn getNumberOrFail() -> %i32 {
5271 return error.UnableToReturnNumber;4976 return error.UnableToReturnNumber;
5272}</code></pre>4977}
5273 <pre><code class="sh">$ zig build-exe test.zig4978 {#code_end#}
5274$ ./test4979 {#header_close#}
5275got error: UnableToReturnNumber</code></pre>4980 {#header_open|Invalid Error Code#}
5276
5277 <h3 id="undef-invalid-error-code">Invalid Error Code</h3>
5278 <p>At compile-time:</p>4981 <p>At compile-time:</p>
5279 <pre><code class="zig">error AnError;4982 <pre><code class="zig">error AnError;
5280comptime {4983comptime {
...@@ -5287,28 +4990,31 @@ comptime {...@@ -5287,28 +4990,31 @@ comptime {
5287 const invalid_err = error(number);4990 const invalid_err = error(number);
5288 ^</code></pre>4991 ^</code></pre>
5289 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>4992 <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#}
5291 <p>TODO</p>4995 <p>TODO</p>
52924996
5293 <h3 id="undef-incorrect-pointer-alignment">Incorrect Pointer Alignment</h3>4997 {#header_close#}
4998 {#header_open|Incorrect Pointer Alignment#}
5294 <p>TODO</p>4999 <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#}
5297 <p>TODO</p>5003 <p>TODO</p>
52985004
5299 <h2 id="memory">Memory</h2>5005 {#header_close#}
5006 {#header_close#}
5007 {#header_open|Memory#}
5300 <p>TODO: explain no default allocator in zig</p>5008 <p>TODO: explain no default allocator in zig</p>
5301 <p>TODO: show how to use the allocator interface</p>5009 <p>TODO: show how to use the allocator interface</p>
5302 <p>TODO: mention debug allocator</p>5010 <p>TODO: mention debug allocator</p>
5303 <p>TODO: importance of checking for allocation failure</p>5011 <p>TODO: importance of checking for allocation failure</p>
5304 <p>TODO: mention overcommit and the OOM Killer</p>5012 <p>TODO: mention overcommit and the OOM Killer</p>
5305 <p>TODO: mention recursion</p>5013 <p>TODO: mention recursion</p>
5306 <p>See also:</p>5014 {#see_also|Pointers#}
5307 <ul>
5308 <li><a href="#pointers">Pointers</a></li>
5309 </ul>
53105015
5311 <h2 id="compile-variables">Compile Variables</h2>5016 {#header_close#}
5017 {#header_open|Compile Variables#}
5312 <p>5018 <p>
5313 Compile variables are accessible by importing the <code>"builtin"</code> package,5019 Compile variables are accessible by importing the <code>"builtin"</code> package,
5314 which the compiler makes available to every Zig source file. It contains5020 which the compiler makes available to every Zig source file. It contains
...@@ -5474,11 +5180,9 @@ pub const object_format = ObjectFormat.elf;...@@ -5474,11 +5180,9 @@ pub const object_format = ObjectFormat.elf;
5474pub const mode = Mode.ReleaseFast;5180pub const mode = Mode.ReleaseFast;
5475pub const link_libs = [][]const u8 {5181pub const link_libs = [][]const u8 {
5476};</code></pre>5182};</code></pre>
5477 <p>See also:</p>5183 {#see_also|Build Mode#}
5478 <ul>5184 {#header_close#}
5479 <li><a href="#build-mode">Build Mode</a></li>5185 {#header_open|Root Source File#}
5480 </ul>
5481 <h2 id="root-source-file">Root Source File</h2>
5482 <p>TODO: explain how root source file finds other files</p>5186 <p>TODO: explain how root source file finds other files</p>
5483 <p>TODO: pub fn main</p>5187 <p>TODO: pub fn main</p>
5484 <p>TODO: pub fn panic</p>5188 <p>TODO: pub fn panic</p>
...@@ -5486,17 +5190,20 @@ pub const link_libs = [][]const u8 {...@@ -5486,17 +5190,20 @@ pub const link_libs = [][]const u8 {
5486 <p>TODO: order independent top level declarations</p>5190 <p>TODO: order independent top level declarations</p>
5487 <p>TODO: lazy analysis</p>5191 <p>TODO: lazy analysis</p>
5488 <p>TODO: using comptime { _ = @import() }</p>5192 <p>TODO: using comptime { _ = @import() }</p>
5489 <h2 id="zig-test">Zig Test</h2>5193 {#header_close#}
5194 {#header_open|Zig Test#}
5490 <p>TODO: basic usage</p>5195 <p>TODO: basic usage</p>
5491 <p>TODO: lazy analysis</p>5196 <p>TODO: lazy analysis</p>
5492 <p>TODO: --test-filter</p>5197 <p>TODO: --test-filter</p>
5493 <p>TODO: --test-name-prefix</p>5198 <p>TODO: --test-name-prefix</p>
5494 <p>TODO: testing in releasefast and releasesafe mode. assert still works</p>5199 <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#}
5496 <p>TODO: explain purpose, it's supposed to replace make/cmake</p>5202 <p>TODO: explain purpose, it's supposed to replace make/cmake</p>
5497 <p>TODO: example of building a zig executable</p>5203 <p>TODO: example of building a zig executable</p>
5498 <p>TODO: example of building a C library</p>5204 <p>TODO: example of building a C library</p>
5499 <h2 id="c">C</h2>5205 {#header_close#}
5206 {#header_open|C#}
5500 <p>5207 <p>
5501 Although Zig is independent of C, and, unlike most other languages, does not depend on libc,5208 Although Zig is independent of C, and, unlike most other languages, does not depend on libc,
5502 Zig acknowledges the importance of interacting with existing C code.5209 Zig acknowledges the importance of interacting with existing C code.
...@@ -5504,7 +5211,7 @@ pub const link_libs = [][]const u8 {...@@ -5504,7 +5211,7 @@ pub const link_libs = [][]const u8 {
5504 <p>5211 <p>
5505 There are a few ways that Zig facilitates C interop.5212 There are a few ways that Zig facilitates C interop.
5506 </p>5213 </p>
5507 <h3 id="c-type-primitives">C Type Primitives</h3>5214 {#header_open|C Type Primitives#}
5508 <p>5215 <p>
5509 These have guaranteed C ABI compatibility and can be used like any other type.5216 These have guaranteed C ABI compatibility and can be used like any other type.
5510 </p>5217 </p>
...@@ -5520,11 +5227,9 @@ pub const link_libs = [][]const u8 {...@@ -5520,11 +5227,9 @@ pub const link_libs = [][]const u8 {
5520 <li><code>c_longdouble</code></li>5227 <li><code>c_longdouble</code></li>
5521 <li><code>c_void</code></li>5228 <li><code>c_void</code></li>
5522 </ul>5229 </ul>
5523 <p>See also:</p>5230 {#see_also|Primitive Types#}
5524 <ul>5231 {#header_close#}
5525 <li><a href="#primitive-types">Primitive Types</a></li>5232 {#header_open|C String Literals#}
5526 </ul>
5527 <h3 id="c-string-literals">C String Literals</h3>
5528 <pre><code class="zig">extern fn puts(&amp;const u8);5233 <pre><code class="zig">extern fn puts(&amp;const u8);
55295234
5530pub fn main() -&gt; %void {5235pub fn main() -&gt; %void {
...@@ -5535,11 +5240,9 @@ pub fn main() -&gt; %void {...@@ -5535,11 +5240,9 @@ pub fn main() -&gt; %void {
5535 c\\multiline C string literal5240 c\\multiline C string literal
5536 );5241 );
5537}</code></pre>5242}</code></pre>
5538 <p>See also:</p>5243 {#see_also|String Literals#}
5539 <ul>5244 {#header_close#}
5540 <li><a href="#string-literals">String Literals</a></li>5245 {#header_open|Import from C Header File#}
5541 </ul>
5542 <h3 id="c-import">Import from C Header File</h3>
5543 <p>5246 <p>
5544 The <code>@cImport</code> builtin function can be used5247 The <code>@cImport</code> builtin function can be used
5545 to directly import symbols from .h files:5248 to directly import symbols from .h files:
...@@ -5566,19 +5269,14 @@ const c = @cImport({...@@ -5566,19 +5269,14 @@ const c = @cImport({
5566 }5269 }
5567 @cInclude("soundio.h");5270 @cInclude("soundio.h");
5568});</code></pre>5271});</code></pre>
5569 <p>See also:</p>5272 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
5570 <ul>5273 {#header_close#}
5571 <li><a href="#builtin-cImport">@cImport</a></li>5274 {#header_open|Mixing Object Files#}
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>
5578 <p>5275 <p>
5579 You can mix Zig object files with any other object files that respect the C ABI. Example:5276 You can mix Zig object files with any other object files that respect the C ABI. Example:
5580 </p>5277 </p>
5581 <h4>base64.zig</h4>5278 {#header_close#}
5279 {#header_open|base64.zig#}
5582 <pre><code class="zig">const base64 = @import("std").base64;5280 <pre><code class="zig">const base64 = @import("std").base64;
55835281
5584export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize,5282export 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,...@@ -5592,7 +5290,7 @@ export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize,
5592 return decoded_size;5290 return decoded_size;
5593}5291}
5594</code></pre>5292</code></pre>
5595 <h4>test.c</h4>5293{{teheader_open:st.c}}
5596 <pre><code class="c">// This header is generated by zig from base64.zig5294 <pre><code class="c">// This header is generated by zig from base64.zig
5597#include "base64.h"5295#include "base64.h"
55985296
...@@ -5609,7 +5307,8 @@ int main(int argc, char **argv) {...@@ -5609,7 +5307,8 @@ int main(int argc, char **argv) {
56095307
5610 return 0;5308 return 0;
5611}</code></pre>5309}</code></pre>
5612 <h4>build.zig</h4>5310 {#header_close#}
5311 {#header_open|build.zig#}
5613 <pre><code class="zig">const Builder = @import("std").build.Builder;5312 <pre><code class="zig">const Builder = @import("std").build.Builder;
56145313
5615pub fn build(b: &amp;Builder) {5314pub fn build(b: &amp;Builder) {
...@@ -5625,16 +5324,15 @@ pub fn build(b: &amp;Builder) {...@@ -5625,16 +5324,15 @@ pub fn build(b: &amp;Builder) {
56255324
5626 b.default_step.dependOn(&amp;exe.step);5325 b.default_step.dependOn(&amp;exe.step);
5627}</code></pre>5326}</code></pre>
5628 <h4>Terminal</h4>5327 {#header_close#}
5328 {#header_open|Terminal#}
5629 <pre><code class="sh">$ zig build5329 <pre><code class="sh">$ zig build
5630$ ./test5330$ ./test
5631all your base are belong to us</code></pre>5331all your base are belong to us</code></pre>
5632 <p>See also:</p>5332 {#see_also|Targets|Zig Build System#}
5633 <ul>5333 {#header_close#}
5634 <li><a href="#targets">Targets</a></li>5334 {#header_close#}
5635 <li><a href="#zig-build-system">Zig Build System</a></li>5335 {#header_open|Targets#}
5636 </ul>
5637 <h2 id="targets">Targets</h2>
5638 <p>5336 <p>
5639 Zig supports generating code for all targets that LLVM supports. Here is5337 Zig supports generating code for all targets that LLVM supports. Here is
5640 what it looks like to execute <code>zig targets</code> on a Linux x86_645338 what it looks like to execute <code>zig targets</code> on a Linux x86_64
...@@ -5760,14 +5458,15 @@ Environments:...@@ -5760,14 +5458,15 @@ Environments:
5760 Linux x86_64. Not all standard library code requires operating system abstractions, however,5458 Linux x86_64. Not all standard library code requires operating system abstractions, however,
5761 so things such as generic data structures work an all above platforms.5459 so things such as generic data structures work an all above platforms.
5762 </p>5460 </p>
5763 <h2 id="style-guide">Style Guide</h2>5461 {#header_close#}
5462 {#header_open|Style Guide#}
5764 <p>5463 <p>
5765These coding conventions are not enforced by the compiler, but they are shipped in5464These coding conventions are not enforced by the compiler, but they are shipped in
5766this documentation along with the compiler in order to provide a point of5465this documentation along with the compiler in order to provide a point of
5767reference, should anyone wish to point to an authority on agreed upon Zig5466reference, should anyone wish to point to an authority on agreed upon Zig
5768coding style.5467coding style.
5769 </p>5468 </p>
5770 <h3 id="style-guide-whitespace">Whitespace</h3>5469 {#header_open|Whitespace#}
5771 <ul>5470 <ul>
5772 <li>5471 <li>
5773 4 space indentation5472 4 space indentation
...@@ -5782,7 +5481,8 @@ coding style....@@ -5782,7 +5481,8 @@ coding style.
5782 Line length: aim for 100; use common sense.5481 Line length: aim for 100; use common sense.
5783 </li>5482 </li>
5784 </ul>5483 </ul>
5785 <h3 id="style-guide-names">Names</h3>5484 {#header_close#}
5485 {#header_open|Names#}
5786 <p>5486 <p>
5787 Roughly speaking: <code>camelCaseFunctionName</code>, <code>TitleCaseTypeName</code>,5487 Roughly speaking: <code>camelCaseFunctionName</code>, <code>TitleCaseTypeName</code>,
5788 <code>snake_case_variable_name</code>. More precisely:5488 <code>snake_case_variable_name</code>. More precisely:
...@@ -5816,7 +5516,8 @@ coding style....@@ -5816,7 +5516,8 @@ coding style.
5816 do what makes sense. For example, if there is an established convention such as5516 do what makes sense. For example, if there is an established convention such as
5817 <code>ENOENT</code>, follow the established convention.5517 <code>ENOENT</code>, follow the established convention.
5818 </p>5518 </p>
5819 <h3 id="style-guide-examples">Examples</h3>5519 {#header_close#}
5520 {#header_open|Examples#}
5820 <pre><code class="zig">const namespace_name = @import("dir_name/file_name.zig");5521 <pre><code class="zig">const namespace_name = @import("dir_name/file_name.zig");
5821var global_var: i32 = undefined;5522var global_var: i32 = undefined;
5822const const_name = 42;5523const const_name = 42;
...@@ -5858,7 +5559,9 @@ fn readU32Be() -&gt; u32 {}</code></pre>...@@ -5858,7 +5559,9 @@ fn readU32Be() -&gt; u32 {}</code></pre>
5858 <p>5559 <p>
5859 See the Zig Standard Library for more examples.5560 See the Zig Standard Library for more examples.
5860 </p>5561 </p>
5861 <h2 id="grammar">Grammar</h2>5562 {#header_close#}
5563 {#header_close#}
5564 {#header_open|Grammar#}
5862 <pre><code>Root = many(TopLevelItem) EOF5565 <pre><code>Root = many(TopLevelItem) EOF
58635566
5864TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl5567TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
...@@ -6010,7 +5713,8 @@ KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "u...@@ -6010,7 +5713,8 @@ KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "u
6010ContainerDecl = option("extern" | "packed")5713ContainerDecl = option("extern" | "packed")
6011 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))5714 ("struct" option(GroupedExpression) | "union" option("enum" option(GroupedExpression) | GroupedExpression) | ("enum" option(GroupedExpression)))
6012 "{" many(ContainerMember) "}"</code></pre>5715 "{" many(ContainerMember) "}"</code></pre>
6013 <h2 id="zen">Zen</h2>5716 {#header_close#}
5717 {#header_open|Zen#}
6014 <ul>5718 <ul>
6015 <li>Communicate intent precisely.</li>5719 <li>Communicate intent precisely.</li>
6016 <li>Edge cases matter.</li>5720 <li>Edge cases matter.</li>
...@@ -6024,8 +5728,10 @@ ContainerDecl = option("extern" | "packed")...@@ -6024,8 +5728,10 @@ ContainerDecl = option("extern" | "packed")
6024 <li>Minimize energy spent on coding style.</li>5728 <li>Minimize energy spent on coding style.</li>
6025 <li>Together we serve end users.</li>5729 <li>Together we serve end users.</li>
6026 </ul>5730 </ul>
6027 <h2>TODO</h2>5731 {#header_close#}
5732 {#header_open|TODO#}
6028 <p>TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)</p>5733 <p>TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)</p>
5734 {#header_close#}
6029 </div>5735 </div>
6030 <script src="highlight/highlight.pack.js"></script>5736 <script src="highlight/highlight.pack.js"></script>
6031 <script>hljs.initHighlightingOnLoad();</script>5737 <script>hljs.initHighlightingOnLoad();</script>
src/bigint.cpp+10-2
...@@ -1271,6 +1271,12 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {...@@ -1271,6 +1271,12 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1271}1271}
12721272
1273void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {1273void 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 }
1274 if (op1->is_negative || op2->is_negative) {1280 if (op1->is_negative || op2->is_negative) {
1275 // TODO this code path is untested1281 // TODO this code path is untested
1276 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));1282 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) {...@@ -1289,14 +1295,16 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
1289 dest->is_negative = false;1295 dest->is_negative = false;
1290 const uint64_t *op1_digits = bigint_ptr(op1);1296 const uint64_t *op1_digits = bigint_ptr(op1);
1291 const uint64_t *op2_digits = bigint_ptr(op2);1297 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];
1292 if (op1->digit_count == 1 && op2->digit_count == 1) {1301 if (op1->digit_count == 1 && op2->digit_count == 1) {
1293 dest->digit_count = 1;1302 dest->digit_count = 1;
1294 dest->data.digit = op1_digits[0] ^ op2_digits[0];1303 dest->data.digit = first_digit;
1295 bigint_normalize(dest);1304 bigint_normalize(dest);
1296 return;1305 return;
1297 }1306 }
1298 // TODO this code path is untested1307 // TODO this code path is untested
1299 uint64_t first_digit = dest->data.digit;
1300 dest->digit_count = max(op1->digit_count, op2->digit_count);1308 dest->digit_count = max(op1->digit_count, op2->digit_count);
1301 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);1309 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
1302 dest->data.digits[0] = first_digit;1310 dest->data.digits[0] = first_digit;
src/codegen.cpp+20-28
...@@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) {...@@ -921,31 +921,41 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) {
921 return g->memcpy_fn_val;921 return g->memcpy_fn_val;
922}922}
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
924static LLVMValueRef get_return_err_fn(CodeGen *g) {938static LLVMValueRef get_return_err_fn(CodeGen *g) {
925 if (g->return_err_fn != nullptr)939 if (g->return_err_fn != nullptr)
926 return g->return_err_fn;940 return g->return_err_fn;
927941
928 assert(g->err_tag_type != nullptr);942 assert(g->err_tag_type != nullptr);
929943
930 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
931
932 LLVMTypeRef arg_types[] = {944 LLVMTypeRef arg_types[] = {
933 // error return trace pointer945 // error return trace pointer
934 get_ptr_to_stack_trace_type(g)->type_ref,946 get_ptr_to_stack_trace_type(g)->type_ref,
935 // return address
936 ptr_u8,
937 };947 };
938 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false);948 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false);
939949
940 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false);950 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false);
941 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);951 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
942 addLLVMFnAttr(fn_val, "cold");953 addLLVMFnAttr(fn_val, "cold");
943 LLVMSetLinkage(fn_val, LLVMInternalLinkage);954 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
944 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));955 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
945 addLLVMFnAttr(fn_val, "nounwind");956 addLLVMFnAttr(fn_val, "nounwind");
946 add_uwtable_attr(g, fn_val);957 add_uwtable_attr(g, fn_val);
947 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");958 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
948 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
949 if (g->build_mode == BuildModeDebug) {959 if (g->build_mode == BuildModeDebug) {
950 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");960 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
951 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr);961 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr);
...@@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -983,7 +993,9 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
983 LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, "");993 LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, "");
984 LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, "");994 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
988 LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, "");1000 LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, "");
989 gen_store_untyped(g, address_value, address_slot, 0, false);1001 gen_store_untyped(g, address_value, address_slot, 0, false);
...@@ -1431,17 +1443,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns...@@ -1431,17 +1443,11 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
1431 is_err_return = true;1443 is_err_return = true;
1432 }1444 }
1433 if (is_err_return) {1445 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
1437 LLVMValueRef return_err_fn = get_return_err_fn(g);1446 LLVMValueRef return_err_fn = get_return_err_fn(g);
1438 LLVMValueRef args[] = {1447 LLVMValueRef args[] = {
1439 g->cur_err_ret_trace_val,1448 g->cur_err_ret_trace_val,
1440 block_address,
1441 };1449 };
1442 LLVMBuildBr(g->builder, return_block);1450 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 1,
1443 LLVMPositionBuilderAtEnd(g->builder, return_block);
1444 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2,
1445 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");1451 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
1446 LLVMSetTailCall(call_instruction, true);1452 LLVMSetTailCall(call_instruction, true);
1447 }1453 }
...@@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I...@@ -3291,20 +3297,6 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I
3291 return nullptr;3297 return nullptr;
3292}3298}
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
3308static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,3300static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable,
3309 IrInstructionReturnAddress *instruction)3301 IrInstructionReturnAddress *instruction)
3310{3302{
std/build.zig+1-1
...@@ -760,7 +760,7 @@ const CrossTarget = struct {...@@ -760,7 +760,7 @@ const CrossTarget = struct {
760 environ: builtin.Environ,760 environ: builtin.Environ,
761};761};
762762
763const Target = union(enum) {763pub const Target = union(enum) {
764 Native: void,764 Native: void,
765 Cross: CrossTarget,765 Cross: CrossTarget,
766766
std/crypto/blake2.zig+4
...@@ -21,6 +21,8 @@ pub const Blake2s256 = Blake2s(256);...@@ -21,6 +21,8 @@ pub const Blake2s256 = Blake2s(256);
2121
22fn Blake2s(comptime out_len: usize) -> type { return struct {22fn Blake2s(comptime out_len: usize) -> type { return struct {
23 const Self = this;23 const Self = this;
24 const block_size = 64;
25 const digest_size = out_len / 8;
2426
25 const iv = [8]u32 {27 const iv = [8]u32 {
26 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,28 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
...@@ -236,6 +238,8 @@ pub const Blake2b512 = Blake2b(512);...@@ -236,6 +238,8 @@ pub const Blake2b512 = Blake2b(512);
236238
237fn Blake2b(comptime out_len: usize) -> type { return struct {239fn Blake2b(comptime out_len: usize) -> type { return struct {
238 const Self = this;240 const Self = this;
241 const block_size = 128;
242 const digest_size = out_len / 8;
239243
240 const iv = [8]u64 {244 const iv = [8]u64 {
241 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,245 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
std/crypto/index.zig+9-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1pub const Md5 = @import("sha1.zig").Md5;1pub const Md5 = @import("md5.zig").Md5;
2pub const Sha1 = @import("md5.zig").Sha1;2pub const Sha1 = @import("sha1.zig").Sha1;
33
4const sha2 = @import("sha2.zig");4const sha2 = @import("sha2.zig");
5pub const Sha224 = sha2.Sha224;5pub const Sha224 = sha2.Sha224;
...@@ -7,6 +7,12 @@ pub const Sha256 = sha2.Sha256;...@@ -7,6 +7,12 @@ pub const Sha256 = sha2.Sha256;
7pub const Sha384 = sha2.Sha384;7pub const Sha384 = sha2.Sha384;
8pub const Sha512 = sha2.Sha512;8pub 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
10const blake2 = @import("blake2.zig");16const blake2 = @import("blake2.zig");
11pub const Blake2s224 = blake2.Blake2s224;17pub const Blake2s224 = blake2.Blake2s224;
12pub const Blake2s256 = blake2.Blake2s256;18pub const Blake2s256 = blake2.Blake2s256;
...@@ -17,5 +23,6 @@ test "crypto" {...@@ -17,5 +23,6 @@ test "crypto" {
17 _ = @import("md5.zig");23 _ = @import("md5.zig");
18 _ = @import("sha1.zig");24 _ = @import("sha1.zig");
19 _ = @import("sha2.zig");25 _ = @import("sha2.zig");
26 _ = @import("sha3.zig");
20 _ = @import("blake2.zig");27 _ = @import("blake2.zig");
21}28}
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...@@ -14,14 +14,10 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) -> Round
14 return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };14 return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t };
15}15}
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();
23pub const Md5 = struct {17pub const Md5 = struct {
24 const Self = this;18 const Self = this;
19 const block_size = 64;
20 const digest_size = 16;
2521
26 s: [4]u32,22 s: [4]u32,
27 // Streaming Cache23 // 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 {...@@ -16,6 +16,8 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) -> RoundParam {
1616
17pub const Sha1 = struct {17pub const Sha1 = struct {
18 const Self = this;18 const Self = this;
19 const block_size = 64;
20 const digest_size = 20;
1921
20 s: [5]u32,22 s: [5]u32,
21 // Streaming Cache23 // Streaming Cache
std/crypto/sha2.zig+4-1
...@@ -58,6 +58,8 @@ pub const Sha256 = Sha2_32(Sha256Params);...@@ -58,6 +58,8 @@ pub const Sha256 = Sha2_32(Sha256Params);
5858
59fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {59fn Sha2_32(comptime params: Sha2Params32) -> type { return struct {
60 const Self = this;60 const Self = this;
61 const block_size = 64;
62 const digest_size = params.out_len / 8;
6163
62 s: [8]u32,64 s: [8]u32,
63 // Streaming Cache65 // Streaming Cache
...@@ -372,7 +374,8 @@ pub const Sha512 = Sha2_64(Sha512Params);...@@ -372,7 +374,8 @@ pub const Sha512 = Sha2_64(Sha512Params);
372374
373fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {375fn Sha2_64(comptime params: Sha2Params64) -> type { return struct {
374 const Self = this;376 const Self = this;
375 const u9 = @IntType(false, 9);377 const block_size = 128;
378 const digest_size = params.out_len / 8;
376379
377 s: [8]u64,380 s: [8]u64,
378 // Streaming Cache381 // 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,...@@ -62,8 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
62 .allocator = allocator,62 .allocator = allocator,
63 .size = 0,63 .size = 0,
64 .max_distance_from_start_index = 0,64 .max_distance_from_start_index = 0,
65 // it doesn't actually matter what we set this to since we use wrapping integer arithmetic65 .modification_count = if (want_modification_safety) 0 else {},
66 .modification_count = undefined,
67 };66 };
68 }67 }
6968
...@@ -110,6 +109,10 @@ pub fn HashMap(comptime K: type, comptime V: type,...@@ -110,6 +109,10 @@ pub fn HashMap(comptime K: type, comptime V: type,
110 return hm.internalGet(key);109 return hm.internalGet(key);
111 }110 }
112111
112 pub fn contains(hm: &Self, key: K) -> bool {
113 return hm.get(key) != null;
114 }
115
113 pub fn remove(hm: &Self, key: K) -> ?&Entry {116 pub fn remove(hm: &Self, key: K) -> ?&Entry {
114 hm.incrementModificationCount();117 hm.incrementModificationCount();
115 const start_index = hm.keyToIndex(key);118 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 {...@@ -203,6 +203,20 @@ pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) -> %[]T {
203 return new_buf;203 return new_buf;
204}204}
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
206/// Linear search for the index of a scalar value inside a slice.220/// Linear search for the index of a scalar value inside a slice.
207pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) -> ?usize {221pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) -> ?usize {
208 return indexOfScalarPos(T, slice, 0, value);222 return indexOfScalarPos(T, slice, 0, value);
test/cases/math.zig+27-1
...@@ -349,6 +349,32 @@ test "big number shifting" {...@@ -349,6 +349,32 @@ test "big number shifting" {
349 }349 }
350}350}
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
352test "f128" {378test "f128" {
353 test_f128();379 test_f128();
354 comptime test_f128();380 comptime test_f128();
...@@ -368,4 +394,4 @@ fn test_f128() {...@@ -368,4 +394,4 @@ fn test_f128() {
368394
369fn should_not_be_zero(x: f128) {395fn should_not_be_zero(x: f128) {
370 assert(x != 0.0);396 assert(x != 0.0);
371}397}
\ No newline at end of file