authorgravatar for mrpaul@aestheticwisdom.comMr. Paul <mrpaul@aestheticwisdom.com> 2021-09-20 15:32:34+07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-20 19:54:57-04:00
log380ca2685548ac916c825842033671ac8a97f577
tree0678aff3d664557bdb5ee2c4fbe9b840de55c529
parentabc30f79489b68f6dc0ee4b408c63a8e783215d1

docgen: re-enable syntax checking for code blocks

In a previous commit (f4d3d29), syntax checking for code blocks with the `syntax` type was disabled due to a change in astgen now checking the existence of identifiers. The change in astgen caused some code samples in the language reference to cause compilation errors. This commit updates the code samples in the language reference and re-enables syntax checking. Some code samples have been changed to unchecked syntax blocks using `{#syntax_block#}` when suitable.

2 files changed, 149 insertions(+), 105 deletions(-)

doc/docgen.zig+1-3
...@@ -1222,9 +1222,7 @@ fn genHtml(...@@ -1222,9 +1222,7 @@ fn genHtml(
12221222
1223 try printSourceBlock(allocator, tokenizer, out, syntax_block);1223 try printSourceBlock(allocator, tokenizer, out, syntax_block);
12241224
1225 // TODO: remove code.just_check_syntax after updating code samples1225 if (!do_code_tests) {
1226 // that have stopped working due to a change in the compiler.
1227 if (!do_code_tests or code.just_check_syntax) {
1228 continue;1226 continue;
1229 }1227 }
12301228
doc/langref.html.in+148-102
...@@ -4771,6 +4771,8 @@ test "parse u64" {...@@ -4771,6 +4771,8 @@ test "parse u64" {
4771 {#header_open|catch#}4771 {#header_open|catch#}
4772 <p>If you want to provide a default value, you can use the {#syntax#}catch{#endsyntax#} binary operator:</p>4772 <p>If you want to provide a default value, you can use the {#syntax#}catch{#endsyntax#} binary operator:</p>
4773 {#code_begin|syntax#}4773 {#code_begin|syntax#}
4774const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
4775
4774fn doAThing(str: []u8) void {4776fn doAThing(str: []u8) void {
4775 const number = parseU64(str, 10) catch 13;4777 const number = parseU64(str, 10) catch 13;
4776 _ = number; // ...4778 _ = number; // ...
...@@ -4786,6 +4788,8 @@ fn doAThing(str: []u8) void {...@@ -4786,6 +4788,8 @@ fn doAThing(str: []u8) void {
4786 <p>Let's say you wanted to return the error if you got one, otherwise continue with the4788 <p>Let's say you wanted to return the error if you got one, otherwise continue with the
4787 function logic:</p>4789 function logic:</p>
4788 {#code_begin|syntax#}4790 {#code_begin|syntax#}
4791const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
4792
4789fn doAThing(str: []u8) !void {4793fn doAThing(str: []u8) !void {
4790 const number = parseU64(str, 10) catch |err| return err;4794 const number = parseU64(str, 10) catch |err| return err;
4791 _ = number; // ...4795 _ = number; // ...
...@@ -4795,6 +4799,8 @@ fn doAThing(str: []u8) !void {...@@ -4795,6 +4799,8 @@ fn doAThing(str: []u8) !void {
4795 There is a shortcut for this. The {#syntax#}try{#endsyntax#} expression:4799 There is a shortcut for this. The {#syntax#}try{#endsyntax#} expression:
4796 </p>4800 </p>
4797 {#code_begin|syntax#}4801 {#code_begin|syntax#}
4802const parseU64 = @import("error_union_parsing_u64.zig").parseU64;
4803
4798fn doAThing(str: []u8) !void {4804fn doAThing(str: []u8) !void {
4799 const number = try parseU64(str, 10);4805 const number = try parseU64(str, 10);
4800 _ = number; // ...4806 _ = number; // ...
...@@ -4810,7 +4816,7 @@ fn doAThing(str: []u8) !void {...@@ -4810,7 +4816,7 @@ fn doAThing(str: []u8) !void {
4810 Maybe you know with complete certainty that an expression will never be an error.4816 Maybe you know with complete certainty that an expression will never be an error.
4811 In this case you can do this:4817 In this case you can do this:
4812 </p>4818 </p>
4813 {#code_begin|syntax#}const number = parseU64("1234", 10) catch unreachable;{#code_end#}4819 {#syntax#}const number = parseU64("1234", 10) catch unreachable;{#endsyntax#}
4814 <p>4820 <p>
4815 Here we know for sure that "1234" will parse successfully. So we put the4821 Here we know for sure that "1234" will parse successfully. So we put the
4816 {#syntax#}unreachable{#endsyntax#} value on the right hand side. {#syntax#}unreachable{#endsyntax#} generates4822 {#syntax#}unreachable{#endsyntax#} value on the right hand side. {#syntax#}unreachable{#endsyntax#} generates
...@@ -4822,7 +4828,7 @@ fn doAThing(str: []u8) !void {...@@ -4822,7 +4828,7 @@ fn doAThing(str: []u8) !void {
4822 Finally, you may want to take a different action for every situation. For that, we combine4828 Finally, you may want to take a different action for every situation. For that, we combine
4823 the {#link|if#} and {#link|switch#} expression:4829 the {#link|if#} and {#link|switch#} expression:
4824 </p>4830 </p>
4825 {#code_begin|syntax#}4831 {#syntax_block|zig|handle_all_error_scenarios.zig#}
4826fn doAThing(str: []u8) void {4832fn doAThing(str: []u8) void {
4827 if (parseU64(str, 10)) |number| {4833 if (parseU64(str, 10)) |number| {
4828 doSomethingWithNumber(number);4834 doSomethingWithNumber(number);
...@@ -4834,7 +4840,7 @@ fn doAThing(str: []u8) void {...@@ -4834,7 +4840,7 @@ fn doAThing(str: []u8) void {
4834 error.InvalidChar => unreachable,4840 error.InvalidChar => unreachable,
4835 }4841 }
4836}4842}
4837 {#code_end#}4843 {#end_syntax_block#}
4838 {#header_open|errdefer#}4844 {#header_open|errdefer#}
4839 <p>4845 <p>
4840 The other component to error handling is defer statements.4846 The other component to error handling is defer statements.
...@@ -4845,7 +4851,7 @@ fn doAThing(str: []u8) void {...@@ -4845,7 +4851,7 @@ fn doAThing(str: []u8) void {
4845 <p>4851 <p>
4846 Example:4852 Example:
4847 </p>4853 </p>
4848 {#code_begin|syntax#}4854 {#syntax_block|zig|errdefer_example.zig#}
4849fn createFoo(param: i32) !Foo {4855fn createFoo(param: i32) !Foo {
4850 const foo = try tryToAllocateFoo();4856 const foo = try tryToAllocateFoo();
4851 // now we have allocated foo. we need to free it if the function fails.4857 // now we have allocated foo. we need to free it if the function fails.
...@@ -4863,7 +4869,7 @@ fn createFoo(param: i32) !Foo {...@@ -4863,7 +4869,7 @@ fn createFoo(param: i32) !Foo {
4863 // but the defer will run!4869 // but the defer will run!
4864 return foo;4870 return foo;
4865}4871}
4866 {#code_end#}4872 {#end_syntax_block#}
4867 <p>4873 <p>
4868 The neat thing about this is that you get robust error handling without4874 The neat thing about this is that you get robust error handling without
4869 the verbosity and cognitive overhead of trying to make sure every exit path4875 the verbosity and cognitive overhead of trying to make sure every exit path
...@@ -5132,12 +5138,12 @@ fn bang2() void {...@@ -5132,12 +5138,12 @@ fn bang2() void {
5132 For the case when no errors are returned, the cost is a single memory write operation, only in the first non-failable function in the call graph that calls a failable function, i.e. when a function returning {#syntax#}void{#endsyntax#} calls a function returning {#syntax#}error{#endsyntax#}.5138 For the case when no errors are returned, the cost is a single memory write operation, only in the first non-failable function in the call graph that calls a failable function, i.e. when a function returning {#syntax#}void{#endsyntax#} calls a function returning {#syntax#}error{#endsyntax#}.
5133 This is to initialize this struct in the stack memory:5139 This is to initialize this struct in the stack memory:
5134 </p>5140 </p>
5135 {#code_begin|syntax#}5141 {#syntax_block|zig|stack_trace_struct.zig#}
5136pub const StackTrace = struct {5142pub const StackTrace = struct {
5137 index: usize,5143 index: usize,
5138 instruction_addresses: [N]usize,5144 instruction_addresses: [N]usize,
5139};5145};
5140 {#code_end#}5146 {#end_syntax_block#}
5141 <p>5147 <p>
5142 Here, N is the maximum function call depth as determined by call graph analysis. Recursion is ignored and counts for 2.5148 Here, N is the maximum function call depth as determined by call graph analysis. Recursion is ignored and counts for 2.
5143 </p>5149 </p>
...@@ -5150,13 +5156,13 @@ pub const StackTrace = struct {...@@ -5150,13 +5156,13 @@ pub const StackTrace = struct {
5150 <p>5156 <p>
5151 When generating the code for a function that returns an error, just before the {#syntax#}return{#endsyntax#} statement (only for the {#syntax#}return{#endsyntax#} statements that return errors), Zig generates a call to this function:5157 When generating the code for a function that returns an error, just before the {#syntax#}return{#endsyntax#} statement (only for the {#syntax#}return{#endsyntax#} statements that return errors), Zig generates a call to this function:
5152 </p>5158 </p>
5153 {#code_begin|syntax#}5159 {#syntax_block|zig|zig_return_error_fn.zig#}
5154// marked as "no-inline" in LLVM IR5160// marked as "no-inline" in LLVM IR
5155fn __zig_return_error(stack_trace: *StackTrace) void {5161fn __zig_return_error(stack_trace: *StackTrace) void {
5156 stack_trace.instruction_addresses[stack_trace.index] = @returnAddress();5162 stack_trace.instruction_addresses[stack_trace.index] = @returnAddress();
5157 stack_trace.index = (stack_trace.index + 1) % N;5163 stack_trace.index = (stack_trace.index + 1) % N;
5158}5164}
5159 {#code_end#}5165 {#end_syntax_block#}
5160 <p>5166 <p>
5161 The cost is 2 math operations plus some memory reads and writes. The memory accessed is constrained and should remain cached for the duration of the error return bubbling.5167 The cost is 2 math operations plus some memory reads and writes. The memory accessed is constrained and should remain cached for the duration of the error return bubbling.
5162 </p>5168 </p>
...@@ -5206,16 +5212,16 @@ const optional_int: ?i32 = 5678;...@@ -5206,16 +5212,16 @@ const optional_int: ?i32 = 5678;
5206 Task: call malloc, if the result is null, return null.5212 Task: call malloc, if the result is null, return null.
5207 </p>5213 </p>
5208 <p>C code</p>5214 <p>C code</p>
5209 <pre><code class="cpp">// malloc prototype included for reference5215 {#syntax_block|c|call_malloc_in_c.c#}// malloc prototype included for reference
5210void *malloc(size_t size);5216void *malloc(size_t size);
52115217
5212struct Foo *do_a_thing(void) {5218struct Foo *do_a_thing(void) {
5213 char *ptr = malloc(1234);5219 char *ptr = malloc(1234);
5214 if (!ptr) return NULL;5220 if (!ptr) return NULL;
5215 // ...5221 // ...
5216}</code></pre>5222}{#end_syntax_block#}
5217 <p>Zig code</p>5223 <p>Zig code</p>
5218 {#code_begin|syntax#}5224 {#syntax_block|zig|call_malloc_from_zig.zig#}
5219// malloc prototype included for reference5225// malloc prototype included for reference
5220extern fn malloc(size: size_t) ?*u8;5226extern fn malloc(size: size_t) ?*u8;
52215227
...@@ -5223,7 +5229,7 @@ fn doAThing() ?*Foo {...@@ -5223,7 +5229,7 @@ fn doAThing() ?*Foo {
5223 const ptr = malloc(1234) orelse return null;5229 const ptr = malloc(1234) orelse return null;
5224 _ = ptr; // ...5230 _ = ptr; // ...
5225}5231}
5226 {#code_end#}5232 {#end_syntax_block#}
5227 <p>5233 <p>
5228 Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr"5234 Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr"
5229 is {#syntax#}*u8{#endsyntax#} <em>not</em> {#syntax#}?*u8{#endsyntax#}. The {#syntax#}orelse{#endsyntax#} keyword5235 is {#syntax#}*u8{#endsyntax#} <em>not</em> {#syntax#}?*u8{#endsyntax#}. The {#syntax#}orelse{#endsyntax#} keyword
...@@ -5233,7 +5239,7 @@ fn doAThing() ?*Foo {...@@ -5233,7 +5239,7 @@ fn doAThing() ?*Foo {
5233 <p>5239 <p>
5234 The other form of checking against NULL you might see looks like this:5240 The other form of checking against NULL you might see looks like this:
5235 </p>5241 </p>
5236 <pre><code class="cpp">void do_a_thing(struct Foo *foo) {5242 {#syntax_block|c|checking_null_in_c.c#}void do_a_thing(struct Foo *foo) {
5237 // do some stuff5243 // do some stuff
52385244
5239 if (foo) {5245 if (foo) {
...@@ -5241,11 +5247,14 @@ fn doAThing() ?*Foo {...@@ -5241,11 +5247,14 @@ fn doAThing() ?*Foo {
5241 }5247 }
52425248
5243 // do some stuff5249 // do some stuff
5244}</code></pre>5250}{#end_syntax_block#}
5245 <p>5251 <p>
5246 In Zig you can accomplish the same thing:5252 In Zig you can accomplish the same thing:
5247 </p>5253 </p>
5248 {#code_begin|syntax#}5254 {#code_begin|syntax|checking_null_in_zig#}
5255const Foo = struct{};
5256fn doSomethingWithFoo(foo: *Foo) void { _ = foo; }
5257
5249fn doAThing(optional_foo: ?*Foo) void {5258fn doAThing(optional_foo: ?*Foo) void {
5250 // do some stuff5259 // do some stuff
52515260
...@@ -6111,7 +6120,7 @@ test "perform fn" {...@@ -6111,7 +6120,7 @@ test "perform fn" {
6111 different code. In this example, the function {#syntax#}performFn{#endsyntax#} is generated three different times,6120 different code. In this example, the function {#syntax#}performFn{#endsyntax#} is generated three different times,
6112 for the different values of {#syntax#}prefix_char{#endsyntax#} provided:6121 for the different values of {#syntax#}prefix_char{#endsyntax#} provided:
6113 </p>6122 </p>
6114 {#code_begin|syntax#}6123 {#syntax_block|zig|performFn_1#}
6115// From the line:6124// From the line:
6116// expect(performFn('t', 1) == 6);6125// expect(performFn('t', 1) == 6);
6117fn performFn(start_value: i32) i32 {6126fn performFn(start_value: i32) i32 {
...@@ -6120,8 +6129,8 @@ fn performFn(start_value: i32) i32 {...@@ -6120,8 +6129,8 @@ fn performFn(start_value: i32) i32 {
6120 result = three(result);6129 result = three(result);
6121 return result;6130 return result;
6122}6131}
6123 {#code_end#}6132 {#end_syntax_block#}
6124 {#code_begin|syntax#}6133 {#syntax_block|zig|performFn_2#}
6125// From the line:6134// From the line:
6126// expect(performFn('o', 0) == 1);6135// expect(performFn('o', 0) == 1);
6127fn performFn(start_value: i32) i32 {6136fn performFn(start_value: i32) i32 {
...@@ -6129,15 +6138,15 @@ fn performFn(start_value: i32) i32 {...@@ -6129,15 +6138,15 @@ fn performFn(start_value: i32) i32 {
6129 result = one(result);6138 result = one(result);
6130 return result;6139 return result;
6131}6140}
6132 {#code_end#}6141 {#end_syntax_block#}
6133 {#code_begin|syntax#}6142 {#syntax_block|zig|performFn_3#}
6134// From the line:6143// From the line:
6135// expect(performFn('w', 99) == 99);6144// expect(performFn('w', 99) == 99);
6136fn performFn(start_value: i32) i32 {6145fn performFn(start_value: i32) i32 {
6137 var result: i32 = start_value;6146 var result: i32 = start_value;
6138 return result;6147 return result;
6139}6148}
6140 {#code_end#}6149 {#end_syntax_block#}
6141 <p>6150 <p>
6142 Note that this happens even in a debug build; in a release build these generated functions still6151 Note that this happens even in a debug build; in a release build these generated functions still
6143 pass through rigorous LLVM optimizations. The important thing to note, however, is not that this6152 pass through rigorous LLVM optimizations. The important thing to note, however, is not that this
...@@ -6367,11 +6376,11 @@ const Node = struct {...@@ -6367,11 +6376,11 @@ const Node = struct {
6367 it works fine.6376 it works fine.
6368 </p>6377 </p>
6369 {#header_close#}6378 {#header_close#}
6370 {#header_open|Case Study: printf in Zig#}6379 {#header_open|Case Study: print in Zig#}
6371 <p>6380 <p>
6372 Putting all of this together, let's see how {#syntax#}printf{#endsyntax#} works in Zig.6381 Putting all of this together, let's see how {#syntax#}print{#endsyntax#} works in Zig.
6373 </p>6382 </p>
6374 {#code_begin|exe|printf#}6383 {#code_begin|exe|print#}
6375const print = @import("std").debug.print;6384const print = @import("std").debug.print;
63766385
6377const a_number: i32 = 1234;6386const a_number: i32 = 1234;
...@@ -6386,67 +6395,84 @@ pub fn main() void {...@@ -6386,67 +6395,84 @@ pub fn main() void {
6386 Let's crack open the implementation of this and see how it works:6395 Let's crack open the implementation of this and see how it works:
6387 </p>6396 </p>
63886397
6389 {#code_begin|syntax#}6398 {#code_begin|syntax|poc_print_fn#}
6390/// Calls print and then flushes the buffer.6399const Writer = struct {
6391pub fn printf(self: *Writer, comptime format: []const u8, args: anytype) anyerror!void {6400 /// Calls print and then flushes the buffer.
6392 const State = enum {6401 pub fn print(self: *Writer, comptime format: []const u8, args: anytype) anyerror!void {
6393 start,6402 const State = enum {
6394 open_brace,6403 start,
6395 close_brace,6404 open_brace,
6396 };6405 close_brace,
63976406 };
6398 comptime var start_index: usize = 0;
6399 comptime var state = State.start;
6400 comptime var next_arg: usize = 0;
64016407
6402 inline for (format) |c, i| {6408 comptime var start_index: usize = 0;
6403 switch (state) {6409 comptime var state = State.start;
6404 State.start => switch (c) {6410 comptime var next_arg: usize = 0;
6405 '{' => {6411
6406 if (start_index < i) try self.write(format[start_index..i]);6412 inline for (format) |c, i| {
6407 state = State.open_brace;6413 switch (state) {
6408 },6414 State.start => switch (c) {
6409 '}' => {6415 '{' => {
6410 if (start_index < i) try self.write(format[start_index..i]);6416 if (start_index < i) try self.write(format[start_index..i]);
6411 state = State.close_brace;6417 state = State.open_brace;
6412 },6418 },
6413 else => {},6419 '}' => {
6414 },6420 if (start_index < i) try self.write(format[start_index..i]);
6415 State.open_brace => switch (c) {6421 state = State.close_brace;
6416 '{' => {6422 },
6417 state = State.start;6423 else => {},
6418 start_index = i;
6419 },6424 },
6420 '}' => {6425 State.open_brace => switch (c) {
6421 try self.printValue(args[next_arg]);6426 '{' => {
6422 next_arg += 1;6427 state = State.start;
6423 state = State.start;6428 start_index = i;
6424 start_index = i + 1;6429 },
6430 '}' => {
6431 try self.printValue(args[next_arg]);
6432 next_arg += 1;
6433 state = State.start;
6434 start_index = i + 1;
6435 },
6436 's' => {
6437 continue;
6438 },
6439 else => @compileError("Unknown format character: " ++ [1]u8{c}),
6425 },6440 },
6426 else => @compileError("Unknown format character: " ++ c),6441 State.close_brace => switch (c) {
6427 },6442 '}' => {
6428 State.close_brace => switch (c) {6443 state = State.start;
6429 '}' => {6444 start_index = i;
6430 state = State.start;6445 },
6431 start_index = i;6446 else => @compileError("Single '}' encountered in format string"),
6432 },6447 },
6433 else => @compileError("Single '}' encountered in format string"),6448 }
6434 },
6435 }6449 }
6436 }6450 comptime {
6437 comptime {6451 if (args.len != next_arg) {
6438 if (args.len != next_arg) {6452 @compileError("Unused arguments");
6439 @compileError("Unused arguments");6453 }
6454 if (state != State.start) {
6455 @compileError("Incomplete format string: " ++ format);
6456 }
6440 }6457 }
6441 if (state != State.Start) {6458 if (start_index < format.len) {
6442 @compileError("Incomplete format string: " ++ format);6459 try self.write(format[start_index..format.len]);
6443 }6460 }
6461 try self.flush();
6444 }6462 }
6445 if (start_index < format.len) {6463
6446 try self.write(format[start_index..format.len]);6464 fn write(self: *Writer, value: []const u8) !void {
6465 _ = self;
6466 _ = value;
6447 }6467 }
6448 try self.flush();6468 pub fn printValue(self: *Writer, value: anytype) !void {
6449}6469 _ = self;
6470 _ = value;
6471 }
6472 fn flush(self: *Writer) !void {
6473 _ = self;
6474 }
6475};
6450 {#code_end#}6476 {#code_end#}
6451 <p>6477 <p>
6452 This is a proof of concept implementation; the actual function in the standard library has more6478 This is a proof of concept implementation; the actual function in the standard library has more
...@@ -6459,8 +6485,8 @@ pub fn printf(self: *Writer, comptime format: []const u8, args: anytype) anyerro...@@ -6459,8 +6485,8 @@ pub fn printf(self: *Writer, comptime format: []const u8, args: anytype) anyerro
6459 When this function is analyzed from our example code above, Zig partially evaluates the function6485 When this function is analyzed from our example code above, Zig partially evaluates the function
6460 and emits a function that actually looks like this:6486 and emits a function that actually looks like this:
6461 </p>6487 </p>
6462 {#code_begin|syntax#}6488 {#syntax_block|zig|Emitted print Function#}
6463pub fn printf(self: *Writer, arg0: i32, arg1: []const u8) !void {6489pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void {
6464 try self.write("here is a string: '");6490 try self.write("here is a string: '");
6465 try self.printValue(arg0);6491 try self.printValue(arg0);
6466 try self.write("' here is a number: ");6492 try self.write("' here is a number: ");
...@@ -6468,28 +6494,46 @@ pub fn printf(self: *Writer, arg0: i32, arg1: []const u8) !void {...@@ -6468,28 +6494,46 @@ pub fn printf(self: *Writer, arg0: i32, arg1: []const u8) !void {
6468 try self.write("\n");6494 try self.write("\n");
6469 try self.flush();6495 try self.flush();
6470}6496}
6471 {#code_end#}6497 {#end_syntax_block#}
6472 <p>6498 <p>
6473 {#syntax#}printValue{#endsyntax#} is a function that takes a parameter of any type, and does different things depending6499 {#syntax#}printValue{#endsyntax#} is a function that takes a parameter of any type, and does different things depending
6474 on the type:6500 on the type:
6475 </p>6501 </p>
6476 {#code_begin|syntax#}6502 {#code_begin|syntax|poc_printValue_fn#}
6477pub fn printValue(self: *Writer, value: anytype) !void {6503 const Writer = struct {
6478 switch (@typeInfo(@TypeOf(value))) {6504 pub fn printValue(self: *Writer, value: anytype) !void {
6479 .Int => {6505 switch (@typeInfo(@TypeOf(value))) {
6480 return self.printInt(T, value);6506 .Int => {
6481 },6507 return self.writeInt(value);
6482 .Float => {6508 },
6483 return self.printFloat(T, value);6509 .Float => {
6484 },6510 return self.writeFloat(value);
6485 else => {6511 },
6486 @compileError("Unable to print type '" ++ @typeName(T) ++ "'");6512 .Pointer => {
6487 },6513 return self.write(value);
6514 },
6515 else => {
6516 @compileError("Unable to print type '" ++ @typeName(@TypeOf(value)) ++ "'");
6517 },
6518 }
6488 }6519 }
6489}6520
6521 fn write(self: *Writer, value: []const u8) !void {
6522 _ = self;
6523 _ = value;
6524 }
6525 fn writeInt(self: *Writer, value: anytype) !void {
6526 _ = self;
6527 _ = value;
6528 }
6529 fn writeFloat(self: *Writer, value: anytype) !void {
6530 _ = self;
6531 _ = value;
6532 }
6533};
6490 {#code_end#}6534 {#code_end#}
6491 <p>6535 <p>
6492 And now, what happens if we give too many arguments to {#syntax#}printf{#endsyntax#}?6536 And now, what happens if we give too many arguments to {#syntax#}print{#endsyntax#}?
6493 </p>6537 </p>
6494 {#code_begin|test_err|Unused argument in 'here is a string: '{s}' here is a number: {}#}6538 {#code_begin|test_err|Unused argument in 'here is a string: '{s}' here is a number: {}#}
6495const print = @import("std").debug.print;6539const print = @import("std").debug.print;
...@@ -6497,7 +6541,7 @@ const print = @import("std").debug.print;...@@ -6497,7 +6541,7 @@ const print = @import("std").debug.print;
6497const a_number: i32 = 1234;6541const a_number: i32 = 1234;
6498const a_string = "foobar";6542const a_string = "foobar";
64996543
6500test "printf too many arguments" {6544test "print too many arguments" {
6501 print("here is a string: '{s}' here is a number: {}\n", .{6545 print("here is a string: '{s}' here is a number: {}\n", .{
6502 a_string,6546 a_string,
6503 a_number,6547 a_number,
...@@ -6512,7 +6556,7 @@ test "printf too many arguments" {...@@ -6512,7 +6556,7 @@ test "printf too many arguments" {
6512 Zig doesn't care whether the format argument is a string literal,6556 Zig doesn't care whether the format argument is a string literal,
6513 only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:6557 only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}:
6514 </p>6558 </p>
6515 {#code_begin|exe|printf#}6559 {#code_begin|exe|print#}
6516const print = @import("std").debug.print;6560const print = @import("std").debug.print;
65176561
6518const a_number: i32 = 1234;6562const a_number: i32 = 1234;
...@@ -7401,9 +7445,11 @@ fn add(a: i32, b: i32) i32 {...@@ -7401,9 +7445,11 @@ fn add(a: i32, b: i32) i32 {
7401 {#syntax#}@call{#endsyntax#} allows more flexibility than normal function call syntax does. The7445 {#syntax#}@call{#endsyntax#} allows more flexibility than normal function call syntax does. The
7402 {#syntax#}CallOptions{#endsyntax#} struct is reproduced here:7446 {#syntax#}CallOptions{#endsyntax#} struct is reproduced here:
7403 </p>7447 </p>
7404 {#code_begin|syntax#}7448 {#syntax_block|zig|builtin.CallOptions struct#}
7405pub const CallOptions = struct {7449pub const CallOptions = struct {
7406 modifier: Modifier = .auto,7450 modifier: Modifier = .auto,
7451
7452 /// Only valid when `Modifier` is `Modifier.async_kw`.
7407 stack: ?[]align(std.Target.stack_align) u8 = null,7453 stack: ?[]align(std.Target.stack_align) u8 = null,
74087454
7409 pub const Modifier = enum {7455 pub const Modifier = enum {
...@@ -7440,7 +7486,7 @@ pub const CallOptions = struct {...@@ -7440,7 +7486,7 @@ pub const CallOptions = struct {
7440 compile_time,7486 compile_time,
7441 };7487 };
7442};7488};
7443 {#code_end#}7489 {#end_syntax_block#}
7444 {#header_close#}7490 {#header_close#}
74457491
7446 {#header_open|@cDefine#}7492 {#header_open|@cDefine#}
...@@ -7554,7 +7600,7 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v...@@ -7554,7 +7600,7 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v
7554 This function performs a weak atomic compare exchange operation. It's the equivalent of this code,7600 This function performs a weak atomic compare exchange operation. It's the equivalent of this code,
7555 except atomic:7601 except atomic:
7556 </p>7602 </p>
7557 {#code_begin|syntax#}7603 {#syntax_block|zig|cmpxchgWeakButNotAtomic#}
7558fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {7604fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {
7559 const old_value = ptr.*;7605 const old_value = ptr.*;
7560 if (old_value == expected_value and usuallyTrueButSometimesFalse()) {7606 if (old_value == expected_value and usuallyTrueButSometimesFalse()) {
...@@ -7564,7 +7610,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -7564,7 +7610,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
7564 return old_value;7610 return old_value;
7565 }7611 }
7566}7612}
7567 {#code_end#}7613 {#end_syntax_block#}
7568 <p>7614 <p>
7569 If you are using cmpxchg in a loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#}7615 If you are using cmpxchg in a loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#}
7570 is the better choice, because it can be implemented more efficiently in machine instructions.7616 is the better choice, because it can be implemented more efficiently in machine instructions.
...@@ -10159,7 +10205,7 @@ pub fn main() void {...@@ -10159,7 +10205,7 @@ pub fn main() void {
10159 This expression is evaluated at compile-time and is used to control10205 This expression is evaluated at compile-time and is used to control
10160 preprocessor directives and include multiple <code class="file">.h</code> files:10206 preprocessor directives and include multiple <code class="file">.h</code> files:
10161 </p>10207 </p>
10162 {#code_begin|syntax#}10208 {#syntax_block|zig|@cImport Expression#}
10163const builtin = @import("builtin");10209const builtin = @import("builtin");
1016410210
10165const c = @cImport({10211const c = @cImport({
...@@ -10173,7 +10219,7 @@ const c = @cImport({...@@ -10173,7 +10219,7 @@ const c = @cImport({
10173 }10219 }
10174 @cInclude("soundio.h");10220 @cInclude("soundio.h");
10175});10221});
10176 {#code_end#}10222 {#end_syntax_block#}
10177 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}10223 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
10178 {#header_close#}10224 {#header_close#}
1017910225