Commit 2e6125bc66
Changed files (3)
doc/home.html.in
@@ -1,724 +0,0 @@
-<!doctype html>
-<html>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
- <title>The Zig Programming Language</title>
- <link rel="stylesheet" type="text/css" href="highlight/styles/default.css">
- <style type="text/css">
- img {
- max-width: 100%;
- }
- </style>
- </head>
- <body>
- <img src="zig-logo.svg">
- <p>
- Zig is an open-source programming language designed for <strong>robustness</strong>,
- <strong>optimality</strong>, and <strong>clarity</strong>.
- </p>
- <p>
- <a href="download/">Download</a> |
- <a href="documentation/master/">Documentation</a> |
- <a href="https://github.com/zig-lang/zig">Source Code</a> |
- <a href="https://github.com/zig-lang/zig/issues">Bug Tracker</a> |
- <a href="https://webchat.freenode.net/?channels=%23zig">IRC</a> |
- <a href="https://www.patreon.com/andrewrk">Donate $1/month</a>
- </p>
- <h2>Feature Highlights</h2>
- <ul>
- <li>Manual memory management. Memory allocation failure is handled correctly. Edge cases matter!</li>
- <li>Zig competes with C instead of depending on it. The Zig Standard Library does not depend on libc.</li>
- <li>Small, simple language. Focus on debugging your application rather than debugging your knowledge of your programming language.</li>
- <li>A fresh take on error handling that resembles what well-written C error handling looks like,
- minus the boilerplate and verbosity.</li>
- <li>Debug mode optimizes for fast compilation time and crashing with a stack trace when undefined behavior
- <em>would</em> happen.</li>
- <li>ReleaseFast mode produces heavily optimized code. What other projects call
- "Link Time Optimization" Zig does automatically.</li>
- <li>ReleaseSafe mode produces optimized code but keeps safety checks enabled. Disable safety checks in the bottlenecks of your code.</li>
- <li>Generic data structures and functions.</li>
- <li>Compile-time reflection and compile-time code execution.</li>
- <li>Import .h files and directly use C types, variables, and functions.</li>
- <li>Export functions, variables, and types for C code to depend on. Automatically generate .h files.</li>
- <li>Nullable type instead of null pointers.</li>
- <li>Order independent top level declarations.</li>
- <li>Friendly toward package maintainers. Reproducible build, bootstrapping process carefully documented. Issues filed by package maintainers are considered especially important.</li>
- <li>Cross-compiling is a first-class use case.</li>
- <li>No preprocessor. Instead Zig has a few carefully designed features that
- provide a way to accomplish things you might do with a preprocessor.</li>
- </ul>
- <h2 id="reading-material">Reading Material</h2>
- <ul>
- <li>2018-01-03 - <a href="http://andrewkelley.me/post/zig-december-2017-in-review.html">December 2017 in Review</a></li>
- <li>2017-10-17 - <a href="download/0.1.1/release-notes.html">Zig 0.1.1 Release Notes</a></li>
- <li>2017-07-19 - <a href="http://tiehuis.github.io/iterative-replacement-of-c-with-zig">Iterative Replacement of C with Zig</a></li>
- <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>
- <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>
- <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>
- <li>2016-02-08 - <a href="http://andrewkelley.me/post/intro-to-zig.html">Introduction to the Zig Programming Language</a></li>
- </ul>
- <h2 id="source-examples">Source Code Examples</h2>
- <ul>
- <li><a href="#hello">Hello World</a></li>
- <li><a href="#hello_libc">Hello World with libc</a></li>
- <li><a href="#parse">Parsing Unsigned Integers</a></li>
- <li><a href="#hashmap">HashMap with Custom Allocator</a></li>
- <li><a href="#tetris">Tetris Clone</a></li>
- <li><a href="#clashos">Bare Bones Operating System</a></li>
- <li><a href="#cat">Cat Utility</a></li>
- <li><a href="#multiline-strings">Multiline String Syntax</a></li>
- <li><a href="#mersenne">Mersenne Twister Random Number Generator</a></li>
- </ul>
- <h3 id="hello">Hello World</h3>
- <pre><code class="zig">const std = @import("std");
-
-pub fn main() -> %void {
- // If this program is run without stdout attached, exit with an error.
- var stdout_file = try std.io.getStdOut();
- // If this program encounters pipe failure when printing to stdout, exit
- // with an error.
- try stdout_file.write("Hello, world!\n");
-}</code></pre>
- <p>Build this with:</p>
- <pre>zig build-exe hello.zig</pre>
- <h3 id="hello_libc">Hello World with libc</h3>
- <pre><code class="zig">const c = @cImport({
- // See https://github.com/zig-lang/zig/issues/515
- @cDefine("_NO_CRT_STDIO_INLINE", "1");
- @cInclude("stdio.h");
- @cInclude("string.h");
-});
-
-const msg = c"Hello, world!\n";
-
-export fn main(argc: c_int, argv: &&u8) -> c_int {
- if (c.printf(msg) != c_int(c.strlen(msg)))
- return -1;
-
- return 0;
-}</code></pre>
- <p>Build this with:</p>
- <pre>zig build-exe hello.zig --library c</pre>
- <h3 id="parse">Parsing Unsigned Integers</h3>
- <pre><code class="zig">pub fn parseUnsigned(comptime T: type, buf: []u8, radix: u8) -> %T {
- var x: T = 0;
-
- for (buf) |c| {
- const digit = try charToDigit(c, radix);
- x = try mulOverflow(T, x, radix);
- x = try addOverflow(T, x, digit);
- }
-
- return x;
-}
-
-error InvalidChar;
-
-fn charToDigit(c: u8, radix: u8) -> %u8 {
- const value = switch (c) {
- '0' ... '9' => c - '0',
- 'A' ... 'Z' => c - 'A' + 10,
- 'a' ... 'z' => c - 'a' + 10,
- else => return error.InvalidChar,
- };
-
- if (value >= radix)
- return error.InvalidChar;
-
- return value;
-}
-
-error Overflow;
-
-pub fn mulOverflow(comptime T: type, a: T, b: T) -> %T {
- var answer: T = undefined;
- if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer
-}
-
-pub fn addOverflow(comptime T: type, a: T, b: T) -> %T {
- var answer: T = undefined;
- if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer
-}
-
-fn getNumberWithDefault(s: []u8) -> u32 {
- parseUnsigned(u32, s, 10) catch 42
-}
-
-fn getNumberOrCrash(s: []u8) -> u32 {
- %%parseUnsigned(u32, s, 10)
-}
-
-fn addTwoTogetherOrReturnErr(a_str: []u8, b_str: []u8) -> %u32 {
- const a = parseUnsigned(u32, a_str, 10) catch |err| return err;
- const b = parseUnsigned(u32, b_str, 10) catch |err| return err;
- return a + b;
-}</code></pre>
- <h3 id="hashmap">HashMap with Custom Allocator</h3>
- <pre><code class="zig">const debug = @import("debug.zig");
-const assert = debug.assert;
-const math = @import("math.zig");
-const mem = @import("mem.zig");
-const Allocator = mem.Allocator;
-
-const want_modification_safety = !@compileVar("is_release");
-const debug_u32 = if (want_modification_safety) u32 else void;
-
-pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K)->u32,
- comptime eql: fn(a: K, b: K)->bool) -> type
-{
- struct {
- entries: []Entry,
- size: usize,
- max_distance_from_start_index: usize,
- allocator: &Allocator,
- // this is used to detect bugs where a hashtable is edited while an iterator is running.
- modification_count: debug_u32,
-
- const Self = this;
-
- pub const Entry = struct {
- used: bool,
- distance_from_start_index: usize,
- key: K,
- value: V,
- };
-
- pub const Iterator = struct {
- hm: &Self,
- // how many items have we returned
- count: usize,
- // iterator through the entry array
- index: usize,
- // used to detect concurrent modification
- initial_modification_count: debug_u32,
-
- pub fn next(it: &Iterator) -> ?&Entry {
- if (want_modification_safety) {
- assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
- }
- if (it.count >= it.hm.size) return null;
- while (it.index < it.hm.entries.len) : (it.index += 1) {
- const entry = &it.hm.entries[it.index];
- if (entry.used) {
- it.index += 1;
- it.count += 1;
- return entry;
- }
- }
- unreachable // no next item
- }
- };
-
- pub fn init(hm: &Self, allocator: &Allocator) {
- hm.entries = []Entry{};
- hm.allocator = allocator;
- hm.size = 0;
- hm.max_distance_from_start_index = 0;
- // it doesn't actually matter what we set this to since we use wrapping integer arithmetic
- hm.modification_count = undefined;
- }
-
- pub fn deinit(hm: &Self) {
- hm.allocator.free(Entry, hm.entries);
- }
-
- pub fn clear(hm: &Self) {
- for (hm.entries) |*entry| {
- entry.used = false;
- }
- hm.size = 0;
- hm.max_distance_from_start_index = 0;
- hm.incrementModificationCount();
- }
-
- pub fn put(hm: &Self, key: K, value: V) -> %void {
- if (hm.entries.len == 0) {
- try hm.initCapacity(16);
- }
- hm.incrementModificationCount();
-
- // if we get too full (60%), double the capacity
- if (hm.size * 5 >= hm.entries.len * 3) {
- const old_entries = hm.entries;
- try hm.initCapacity(hm.entries.len * 2);
- // dump all of the old elements into the new table
- for (old_entries) |*old_entry| {
- if (old_entry.used) {
- hm.internalPut(old_entry.key, old_entry.value);
- }
- }
- hm.allocator.free(Entry, old_entries);
- }
-
- hm.internalPut(key, value);
- }
-
- pub fn get(hm: &Self, key: K) -> ?&Entry {
- return hm.internalGet(key);
- }
-
- pub fn remove(hm: &Self, key: K) {
- hm.incrementModificationCount();
- const start_index = hm.keyToIndex(key);
- {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
- const index = (start_index + roll_over) % hm.entries.len;
- var entry = &hm.entries[index];
-
- assert(entry.used); // key not found
-
- if (!eql(entry.key, key)) continue;
-
- while (roll_over < hm.entries.len) : (roll_over += 1) {
- const next_index = (start_index + roll_over + 1) % hm.entries.len;
- const next_entry = &hm.entries[next_index];
- if (!next_entry.used or next_entry.distance_from_start_index == 0) {
- entry.used = false;
- hm.size -= 1;
- return;
- }
- *entry = *next_entry;
- entry.distance_from_start_index -= 1;
- entry = next_entry;
- }
- unreachable // shifting everything in the table
- }}
- unreachable // key not found
- }
-
- pub fn entryIterator(hm: &Self) -> Iterator {
- return Iterator {
- .hm = hm,
- .count = 0,
- .index = 0,
- .initial_modification_count = hm.modification_count,
- };
- }
-
- fn initCapacity(hm: &Self, capacity: usize) -> %void {
- hm.entries = try hm.allocator.alloc(Entry, capacity);
- hm.size = 0;
- hm.max_distance_from_start_index = 0;
- for (hm.entries) |*entry| {
- entry.used = false;
- }
- }
-
- fn incrementModificationCount(hm: &Self) {
- if (want_modification_safety) {
- hm.modification_count +%= 1;
- }
- }
-
- fn internalPut(hm: &Self, orig_key: K, orig_value: V) {
- var key = orig_key;
- var value = orig_value;
- const start_index = hm.keyToIndex(key);
- var roll_over: usize = 0;
- var distance_from_start_index: usize = 0;
- while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1}) {
- const index = (start_index + roll_over) % hm.entries.len;
- const entry = &hm.entries[index];
-
- if (entry.used and !eql(entry.key, key)) {
- if (entry.distance_from_start_index < distance_from_start_index) {
- // robin hood to the rescue
- const tmp = *entry;
- hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
- distance_from_start_index);
- *entry = Entry {
- .used = true,
- .distance_from_start_index = distance_from_start_index,
- .key = key,
- .value = value,
- };
- key = tmp.key;
- value = tmp.value;
- distance_from_start_index = tmp.distance_from_start_index;
- }
- continue;
- }
-
- if (!entry.used) {
- // adding an entry. otherwise overwriting old value with
- // same key
- hm.size += 1;
- }
-
- hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
- *entry = Entry {
- .used = true,
- .distance_from_start_index = distance_from_start_index,
- .key = key,
- .value = value,
- };
- return;
- }
- unreachable // put into a full map
- }
-
- fn internalGet(hm: &Self, key: K) -> ?&Entry {
- const start_index = hm.keyToIndex(key);
- {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
- const index = (start_index + roll_over) % hm.entries.len;
- const entry = &hm.entries[index];
-
- if (!entry.used) return null;
- if (eql(entry.key, key)) return entry;
- }}
- return null;
- }
-
- fn keyToIndex(hm: &Self, key: K) -> usize {
- return usize(hash(key)) % hm.entries.len;
- }
- }
-}
-
-test "basic hash map test" {
- var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined;
- map.init(&debug.global_allocator);
- defer map.deinit();
-
- %%map.put(1, 11);
- %%map.put(2, 22);
- %%map.put(3, 33);
- %%map.put(4, 44);
- %%map.put(5, 55);
-
- assert((??map.get(2)).value == 22);
- map.remove(2);
- assert(if (const entry ?= map.get(2)) false else true);
-}
-
-fn hash_i32(x: i32) -> u32 {
- *(&u32)(&x)
-}
-fn eql_i32(a: i32, b: i32) -> bool {
- a == b
-}</code></pre>
- <h3 id="tetris">Tetris Clone</h3>
- <img src="tetris-screenshot.png">
- <p>
- <a href="https://github.com/andrewrk/tetris">Source Code on GitHub</a>
- </p>
- <h3 id="clashos">Bare Bones Operating System</h3>
- <p>
- <a href="https://github.com/andrewrk/clashos">Source Code on GitHub</a>
- </p>
- <h3 id="cat">Cat Utility</h3>
- <pre><code class="zig">const std = @import("std");
-const io = std.io;
-const mem = std.mem;
-const os = std.os;
-
-pub fn main() -> %void {
- const exe = os.args.at(0);
- var catted_anything = false;
- var arg_i: usize = 1;
- while (arg_i < os.args.count()) : (arg_i += 1) {
- const arg = os.args.at(arg_i);
- if (mem.eql(u8, arg, "-")) {
- catted_anything = true;
- try cat_stream(&io.stdin);
- } else if (arg[0] == '-') {
- return usage(exe);
- } else {
- var is = io.InStream.open(arg, null) catch |err| {
- %%io.stderr.printf("Unable to open file: {}\n", @errorName(err));
- return err;
- };
- defer is.close();
-
- catted_anything = true;
- try cat_stream(&is);
- }
- }
- if (!catted_anything) {
- try cat_stream(&io.stdin);
- }
- try io.stdout.flush();
-}
-
-fn usage(exe: []const u8) -> %void {
- %%io.stderr.printf("Usage: {} [FILE]...\n", exe);
- return error.Invalid;
-}
-
-fn cat_stream(is: &io.InStream) -> %void {
- var buf: [1024 * 4]u8 = undefined;
-
- while (true) {
- const bytes_read = is.read(buf[0..]) catch |err| {
- %%io.stderr.printf("Unable to read from stream: {}\n", @errorName(err));
- return err;
- };
-
- if (bytes_read == 0) {
- break;
- }
-
- io.stdout.write(buf[0..bytes_read]) catch |err| {
- %%io.stderr.printf("Unable to write to stdout: {}\n", @errorName(err));
- return err;
- };
- }
-}</code></pre>
- <h3 id="multiline-strings">Multiline String Syntax</h3>
- <pre><code class="zig">pub fn createAllShaders() -> AllShaders {
- var as : AllShaders = undefined;
-
- as.primitive = createShader(
- \\#version 150 core
- \\
- \\in vec3 VertexPosition;
- \\
- \\uniform mat4 MVP;
- \\
- \\void main(void) {
- \\ gl_Position = vec4(VertexPosition, 1.0) * MVP;
- \\}
- ,
- \\#version 150 core
- \\
- \\out vec4 FragColor;
- \\
- \\uniform vec4 Color;
- \\
- \\void main(void) {
- \\ FragColor = Color;
- \\}
- , null);
-
- as.primitive_attrib_position = as.primitive.attrib_location(c"VertexPosition");
- as.primitive_uniform_mvp = as.primitive.uniform_location(c"MVP");
- as.primitive_uniform_color = as.primitive.uniform_location(c"Color");
-
-
-
- as.texture = createShader(
- \\#version 150 core
- \\
- \\in vec3 VertexPosition;
- \\in vec2 TexCoord;
- \\
- \\out vec2 FragTexCoord;
- \\
- \\uniform mat4 MVP;
- \\
- \\void main(void)
- \\{
- \\ FragTexCoord = TexCoord;
- \\ gl_Position = vec4(VertexPosition, 1.0) * MVP;
- \\}
- ,
- \\#version 150 core
- \\
- \\in vec2 FragTexCoord;
- \\out vec4 FragColor;
- \\
- \\uniform sampler2D Tex;
- \\
- \\void main(void)
- \\{
- \\ FragColor = texture(Tex, FragTexCoord);
- \\}
- , null);
-
- as.texture_attrib_tex_coord = as.texture.attrib_location(c"TexCoord");
- as.texture_attrib_position = as.texture.attrib_location(c"VertexPosition");
- as.texture_uniform_mvp = as.texture.uniform_location(c"MVP");
- as.texture_uniform_tex = as.texture.uniform_location(c"Tex");
-
- debug_gl.assert_no_error();
-
- return as;
-}</code></pre>
- <h3 id="mersenne">Mersenne Twister Random Number Generator</h3>
- <pre><code class="zig">const assert = @import("debug.zig").assert;
-const rand_test = @import("rand_test.zig");
-
-pub const MT19937_32 = MersenneTwister(
- u32, 624, 397, 31,
- 0x9908B0DF,
- 11, 0xFFFFFFFF,
- 7, 0x9D2C5680,
- 15, 0xEFC60000,
- 18, 1812433253);
-
-pub const MT19937_64 = MersenneTwister(
- u64, 312, 156, 31,
- 0xB5026F5AA96619E9,
- 29, 0x5555555555555555,
- 17, 0x71D67FFFEDA60000,
- 37, 0xFFF7EEE000000000,
- 43, 6364136223846793005);
-
-/// Use `init` to initialize this state.
-pub const Rand = struct {
- const Rng = if (@sizeOf(usize) >= 8) MT19937_64 else MT19937_32;
-
- rng: Rng,
-
- /// Initialize random state with the given seed.
- pub fn init(r: &Rand, seed: usize) {
- r.rng.init(seed);
- }
-
- /// Get an integer with random bits.
- pub fn scalar(r: &Rand, comptime T: type) -> T {
- if (T == usize) {
- return r.rng.get();
- } else {
- var result: [@sizeOf(T)]u8 = undefined;
- r.fillBytes(result);
- return ([]T)(result)[0];
- }
- }
-
- /// Fill `buf` with randomness.
- pub fn fillBytes(r: &Rand, buf: []u8) {
- var bytes_left = buf.len;
- while (bytes_left >= @sizeOf(usize)) {
- ([]usize)(buf[buf.len - bytes_left...])[0] = r.rng.get();
- bytes_left -= @sizeOf(usize);
- }
- if (bytes_left > 0) {
- var rand_val_array : [@sizeOf(usize)]u8 = undefined;
- ([]usize)(rand_val_array)[0] = r.rng.get();
- while (bytes_left > 0) {
- buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left];
- bytes_left -= 1;
- }
- }
- }
-
- /// Get a random unsigned integer with even distribution between `start`
- /// inclusive and `end` exclusive.
- // TODO support signed integers and then rename to "range"
- pub fn rangeUnsigned(r: &Rand, comptime T: type, start: T, end: T) -> T {
- const range = end - start;
- const leftover = @maxValue(T) % range;
- const upper_bound = @maxValue(T) - leftover;
- var rand_val_array : [@sizeOf(T)]u8 = undefined;
-
- while (true) {
- r.fillBytes(rand_val_array);
- const rand_val = ([]T)(rand_val_array)[0];
- if (rand_val < upper_bound) {
- return start + (rand_val % range);
- }
- }
- }
-
- /// Get a floating point value in the range 0.0..1.0.
- pub fn float(r: &Rand, comptime T: type) -> T {
- // TODO Implement this way instead:
- // const int = @int_type(false, @sizeOf(T) * 8);
- // const mask = ((1 << @float_mantissa_bit_count(T)) - 1);
- // const rand_bits = r.rng.scalar(int) & mask;
- // return @float_compose(T, false, 0, rand_bits) - 1.0
- const int_type = @intType(false, @sizeOf(T) * 8);
- const precision = if (T == f32) {
- 16777216
- } else if (T == f64) {
- 9007199254740992
- } else {
- @compileError("unknown floating point type")
- };
- return T(r.rangeUnsigned(int_type, 0, precision)) / T(precision);
- }
-};
-
-fn MersenneTwister(
- comptime int: type, comptime n: usize, comptime m: usize, comptime r: int,
- comptime a: int,
- comptime u: int, comptime d: int,
- comptime s: int, comptime b: int,
- comptime t: int, comptime c: int,
- comptime l: int, comptime f: int) -> type
-{
- struct {
- const Self = this;
-
- array: [n]int,
- index: usize,
-
- pub fn init(mt: &Self, seed: int) {
- mt.index = n;
-
- var prev_value = seed;
- mt.array[0] = prev_value;
- {var i: usize = 1; while (i < n) : (i += 1) {
- prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2)));
- mt.array[i] = prev_value;
- }};
- }
-
- pub fn get(mt: &Self) -> int {
- const mag01 = []int{0, a};
- const LM: int = (1 << r) - 1;
- const UM = ~LM;
-
- if (mt.index >= n) {
- var i: usize = 0;
-
- while (i < n - m) : (i += 1) {
- const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM);
- mt.array[i] = mt.array[i + m] ^ (x >> 1) ^ mag01[x & 0x1];
- }
-
- while (i < n - 1) : (i += 1) {
- const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM);
- mt.array[i] = mt.array[i + m - n] ^ (x >> 1) ^ mag01[x & 0x1];
-
- }
- const x = (mt.array[i] & UM) | (mt.array[0] & LM);
- mt.array[i] = mt.array[m - 1] ^ (x >> 1) ^ mag01[x & 0x1];
-
- mt.index = 0;
- }
-
- var x = mt.array[mt.index];
- mt.index += 1;
-
- x ^= ((x >> u) & d);
- x ^= ((x <<% s) & b);
- x ^= ((x <<% t) & c);
- x ^= (x >> l);
-
- return x;
- }
- }
-}
-
-test "float 32" {
- var r: Rand = undefined;
- r.init(42);
-
- {var i: usize = 0; while (i < 1000) : (i += 1) {
- const val = r.float(f32);
- assert(val >= 0.0);
- assert(val < 1.0);
- }}
-}
-
-test "MT19937_64" {
- var rng: MT19937_64 = undefined;
- rng.init(rand_test.mt64_seed);
- for (rand_test.mt64_data) |value| {
- assert(value == rng.get());
- }
-}
-
-test "MT19937_32" {
- var rng: MT19937_32 = undefined;
- rng.init(rand_test.mt32_seed);
- for (rand_test.mt32_data) |value| {
- assert(value == rng.get());
- }
-}</code></pre>
- <script src="highlight/highlight.pack.js"></script>
- <script>hljs.initHighlightingOnLoad();</script>
- </body>
-</html>
doc/langref.html.in
@@ -92,14 +92,16 @@ pub fn main() -> %void {
<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>
{#header_close#}
{#header_open|Values#}
- <pre><code class="zig">const warn = @import("std").debug.warn;
-const os = @import("std").os;
-const assert = @import("std").debug.assert;
+ {#code_begin|exe|values#}
+const std = @import("std");
+const warn = std.debug.warn;
+const os = std.os;
+const assert = std.debug.assert;
// error declaration, makes `error.ArgNotFound` available
error ArgNotFound;
-pub fn main() -> %void {
+pub fn main() -> %void {
// integers
const one_plus_one: i32 = 1 + 1;
warn("1 + 1 = {}\n", one_plus_one);
@@ -137,30 +139,8 @@ pub fn main() -> %void {
warn("\nerror union 2\ntype: {}\nvalue: {}\n",
@typeName(@typeOf(number_or_error)), number_or_error);
-}</code></pre>
- <pre><code class="sh">$ zig build-exe values.zig
-$ ./values
-1 + 1 = 2
-7.0 / 3.0 = 2.333333
-false
-true
-false
-
-nullable 1
-type: ?[]const u8
-value: null
-
-nullable 2
-type: ?[]const u8
-value: hi
-
-error union 1
-type: %i32
-value: error.ArgNotFound
-
-error union 2
-type: %i32
-value: 1234</code></pre>
+}
+ {#code_end#}
{#header_open|Primitive Types#}
<table>
<tr>
@@ -3630,17 +3610,18 @@ fn sum(numbers: []i32) -> i32 {
{#header_close#}
{#header_open|Case Study: printf in Zig#}
<p>
- Putting all of this together, let's seee how <code>printf</code> works in Zig.
+ Putting all of this together, let's see how <code>printf</code> works in Zig.
</p>
- <pre><code class="zig">const warn = @import("std").debug.warn;
+ {#code_begin|exe|printf#}
+const warn = @import("std").debug.warn;
const a_number: i32 = 1234;
const a_string = "foobar";
-pub fn main(args: [][]u8) -> %void {
+pub fn main() {
warn("here is a string: '{}' here is a number: {}\n", a_string, a_number);
-}</code></pre>
- <pre><code>here is a string: 'foobar' here is a number: 1234</code></pre>
+}
+ {#code_end#}
<p>
Let's crack open the implementation of this and see how it works:
@@ -3760,15 +3741,17 @@ pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) ->
Zig doesn't care whether the format argument is a string literal,
only that it is a compile-time known value that is implicitly castable to a <code>[]const u8</code>:
</p>
- <pre><code class="zig">const warn = @import("std").debug.warn;
+ {#code_begin|exe|printf#}
+const warn = @import("std").debug.warn;
const a_number: i32 = 1234;
const a_string = "foobar";
const fmt = "here is a string: '{}' here is a number: {}\n";
-pub fn main(args: [][]u8) -> %void {
+pub fn main() {
warn(fmt, a_string, a_number);
-}</code></pre>
+}
+ {#code_end#}
<p>
This works fine.
</p>
@@ -4943,8 +4926,9 @@ test "wraparound addition and subtraction" {
<p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p>
<p>One way to avoid this crash is to test for null instead of assuming non-null, with
the <code>if</code> expression:</p>
- <pre><code class="zig">const warn = @import("std").debug.warn;
-pub fn main() -> %void {
+ {#code_begin|exe|test#}
+const warn = @import("std").debug.warn;
+pub fn main() {
const nullable_number: ?i32 = null;
if (nullable_number) |number| {
@@ -4952,10 +4936,8 @@ pub fn main() -> %void {
} else {
warn("it's null\n");
}
-}</code></pre>
- <pre><code class="sh">% zig build-exe test.zig
-$ ./test
-it's null</code></pre>
+}
+ {#code_end#}
{#header_close#}
{#header_open|Attempt to Unwrap Error#}
<p>At compile-time:</p>
@@ -4975,9 +4957,10 @@ fn getNumberOrFail() -> %i32 {
<p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p>
<p>One way to avoid this crash is to test for an error instead of assuming a successful result, with
the <code>if</code> expression:</p>
- <pre><code class="zig">const warn = @import("std").debug.warn;
+ {#code_begin|exe|test#}
+const warn = @import("std").debug.warn;
-pub fn main() -> %void {
+pub fn main() {
const result = getNumberOrFail();
if (result) |number| {
@@ -4989,13 +4972,10 @@ pub fn main() -> %void {
error UnableToReturnNumber;
-fn getNumberOrFail() -> %i32 {
+fn getNumberOrFail() -> %i32 {
return error.UnableToReturnNumber;
-}</code></pre>
- <pre><code class="sh">$ zig build-exe test.zig
-$ ./test
-got error: UnableToReturnNumber</code></pre>
-
+}
+ {#code_end#}
{#header_close#}
{#header_open|Invalid Error Code#}
<p>At compile-time:</p>
build.zig
@@ -24,17 +24,8 @@ pub fn build(b: &Builder) -> %void {
});
docgen_cmd.step.dependOn(&docgen_exe.step);
- var docgen_home_cmd = b.addCommand(null, b.env_map, [][]const u8 {
- docgen_exe.getOutputPath(),
- rel_zig_exe,
- "doc/home.html.in",
- os.path.join(b.allocator, b.cache_root, "home.html") catch unreachable,
- });
- docgen_home_cmd.step.dependOn(&docgen_exe.step);
-
const docs_step = b.step("docs", "Build documentation");
docs_step.dependOn(&docgen_cmd.step);
- docs_step.dependOn(&docgen_home_cmd.step);
const test_step = b.step("test", "Run all the tests");