authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-17 03:24:03-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-17 03:24:49-05:00
log2e6125bc66bd717838fb107107564cdd66112613
tree10563f692587b10ddc723328300fb58f24142f8f
parent7a3fd89d253993cbb73c6890974aa6d3f1f01f22

ziglang.org home page no longer in this repo

update docs examples which use build-exe to be tested See #465

3 files changed, 30 insertions(+), 783 deletions(-)

build.zig-9
......@@ -24,17 +24,8 @@ pub fn build(b: &Builder) -> %void {
2424 });
2525 docgen_cmd.step.dependOn(&docgen_exe.step);
2626
27 var docgen_home_cmd = b.addCommand(null, b.env_map, [][]const u8 {
28 docgen_exe.getOutputPath(),
29 rel_zig_exe,
30 "doc/home.html.in",
31 os.path.join(b.allocator, b.cache_root, "home.html") catch unreachable,
32 });
33 docgen_home_cmd.step.dependOn(&docgen_exe.step);
34
3527 const docs_step = b.step("docs", "Build documentation");
3628 docs_step.dependOn(&docgen_cmd.step);
37 docs_step.dependOn(&docgen_home_cmd.step);
3829
3930 const test_step = b.step("test", "Run all the tests");
4031
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+30-50
......@@ -92,14 +92,16 @@ pub fn main() -> %void {
9292 <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>
9393 {#header_close#}
9494 {#header_open|Values#}
95 <pre><code class="zig">const warn = @import("std").debug.warn;
96const os = @import("std").os;
97const assert = @import("std").debug.assert;
95 {#code_begin|exe|values#}
96const std = @import("std");
97const warn = std.debug.warn;
98const os = std.os;
99const assert = std.debug.assert;
98100
99101// error declaration, makes `error.ArgNotFound` available
100102error ArgNotFound;
101103
102pub fn main() -&gt; %void {
104pub fn main() -> %void {
103105 // integers
104106 const one_plus_one: i32 = 1 + 1;
105107 warn("1 + 1 = {}\n", one_plus_one);
......@@ -137,30 +139,8 @@ pub fn main() -&gt; %void {
137139
138140 warn("\nerror union 2\ntype: {}\nvalue: {}\n",
139141 @typeName(@typeOf(number_or_error)), number_or_error);
140}</code></pre>
141 <pre><code class="sh">$ zig build-exe values.zig
142$ ./values
1431 + 1 = 2
1447.0 / 3.0 = 2.333333
145false
146true
147false
148
149nullable 1
150type: ?[]const u8
151value: null
152
153nullable 2
154type: ?[]const u8
155value: hi
156
157error union 1
158type: %i32
159value: error.ArgNotFound
160
161error union 2
162type: %i32
163value: 1234</code></pre>
142}
143 {#code_end#}
164144 {#header_open|Primitive Types#}
165145 <table>
166146 <tr>
......@@ -3630,17 +3610,18 @@ fn sum(numbers: []i32) -&gt; i32 {
36303610 {#header_close#}
36313611 {#header_open|Case Study: printf in Zig#}
36323612 <p>
3633 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.
36343614 </p>
3635 <pre><code class="zig">const warn = @import("std").debug.warn;
3615 {#code_begin|exe|printf#}
3616const warn = @import("std").debug.warn;
36363617
36373618const a_number: i32 = 1234;
36383619const a_string = "foobar";
36393620
3640pub fn main(args: [][]u8) -&gt; %void {
3621pub fn main() {
36413622 warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
3642}</code></pre>
3643 <pre><code>here is a string: 'foobar' here is a number: 1234</code></pre>
3623}
3624 {#code_end#}
36443625
36453626 <p>
36463627 Let's crack open the implementation of this and see how it works:
......@@ -3760,15 +3741,17 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt
37603741 Zig doesn't care whether the format argument is a string literal,
37613742 only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:
37623743 </p>
3763 <pre><code class="zig">const warn = @import("std").debug.warn;
3744 {#code_begin|exe|printf#}
3745const warn = @import("std").debug.warn;
37643746
37653747const a_number: i32 = 1234;
37663748const a_string = "foobar";
37673749const fmt = "here is a string: '{}' here is a number: {}\n";
37683750
3769pub fn main(args: [][]u8) -&gt; %void {
3751pub fn main() {
37703752 warn(fmt, a_string, a_number);
3771}</code></pre>
3753}
3754 {#code_end#}
37723755 <p>
37733756 This works fine.
37743757 </p>
......@@ -4943,8 +4926,9 @@ test "wraparound addition and subtraction" {
49434926 <p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>
49444927 <p>One way to avoid this crash is to test for null instead of assuming non-null, with
49454928 the <code>if</code> expression:</p>
4946 <pre><code class="zig">const warn = @import("std").debug.warn;
4947pub fn main() -&gt; %void {
4929 {#code_begin|exe|test#}
4930const warn = @import("std").debug.warn;
4931pub fn main() {
49484932 const nullable_number: ?i32 = null;
49494933
49504934 if (nullable_number) |number| {
......@@ -4952,10 +4936,8 @@ pub fn main() -&gt; %void {
49524936 } else {
49534937 warn("it's null\n");
49544938 }
4955}</code></pre>
4956 <pre><code class="sh">% zig build-exe test.zig
4957$ ./test
4958it's null</code></pre>
4939}
4940 {#code_end#}
49594941 {#header_close#}
49604942 {#header_open|Attempt to Unwrap Error#}
49614943 <p>At compile-time:</p>
......@@ -4975,9 +4957,10 @@ fn getNumberOrFail() -&gt; %i32 {
49754957 <p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p>
49764958 <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
49774959 the <code>if</code> expression:</p>
4978 <pre><code class="zig">const warn = @import("std").debug.warn;
4960 {#code_begin|exe|test#}
4961const warn = @import("std").debug.warn;
49794962
4980pub fn main() -&gt; %void {
4963pub fn main() {
49814964 const result = getNumberOrFail();
49824965
49834966 if (result) |number| {
......@@ -4989,13 +4972,10 @@ pub fn main() -&gt; %void {
49894972
49904973error UnableToReturnNumber;
49914974
4992fn getNumberOrFail() -&gt; %i32 {
4975fn getNumberOrFail() -> %i32 {
49934976 return error.UnableToReturnNumber;
4994}</code></pre>
4995 <pre><code class="sh">$ zig build-exe test.zig
4996$ ./test
4997got error: UnableToReturnNumber</code></pre>
4998
4977}
4978 {#code_end#}
49994979 {#header_close#}
50004980 {#header_open|Invalid Error Code#}
50014981 <p>At compile-time:</p>