| ... | @@ -2523,19 +2523,28 @@ test "multidimensional arrays" { | ... | @@ -2523,19 +2523,28 @@ test "multidimensional arrays" { |
| 2523 | {#header_open|Sentinel-Terminated Arrays#} | 2523 | {#header_open|Sentinel-Terminated Arrays#} |
| 2524 | <p> | 2524 | <p> |
| 2525 | The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the | 2525 | The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element of value {#syntax#}x{#endsyntax#} at the |
| 2526 | index corresponding to {#syntax#}len{#endsyntax#}. | 2526 | index corresponding to the length {#syntax#}N{#endsyntax#}. |
| 2527 | </p> | 2527 | </p> |
| 2528 | {#code_begin|test|test_null_terminated_array#} | 2528 | {#code_begin|test|test_null_terminated_array#} |
| 2529 | const std = @import("std"); | 2529 | const std = @import("std"); |
| 2530 | const expect = std.testing.expect; | 2530 | const expect = std.testing.expect; |
| 2531 | | 2531 | |
| 2532 | test "null terminated array" { | 2532 | test "0-terminated sentinel array" { |
| 2533 | const array = [_:0]u8 {1, 2, 3, 4}; | 2533 | const array = [_:0]u8 {1, 2, 3, 4}; |
| 2534 | | 2534 | |
| 2535 | try expect(@TypeOf(array) == [4:0]u8); | 2535 | try expect(@TypeOf(array) == [4:0]u8); |
| 2536 | try expect(array.len == 4); | 2536 | try expect(array.len == 4); |
| 2537 | try expect(array[4] == 0); | 2537 | try expect(array[4] == 0); |
| 2538 | } | 2538 | } |
| | 2539 | |
| | 2540 | test "extra 0s in 0-terminated sentinel array" { |
| | 2541 | // The sentinel value may appear earlier, but does not influence the compile-time 'len'. |
| | 2542 | const array = [_:0]u8 {1, 0, 0, 4}; |
| | 2543 | |
| | 2544 | try expect(@TypeOf(array) == [4:0]u8); |
| | 2545 | try expect(array.len == 4); |
| | 2546 | try expect(array[4] == 0); |
| | 2547 | } |
| 2539 | {#code_end#} | 2548 | {#code_end#} |
| 2540 | {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#} | 2549 | {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#} |
| 2541 | {#header_close#} | 2550 | {#header_close#} |
| ... | @@ -3052,8 +3061,6 @@ test "using slices for strings" { | ... | @@ -3052,8 +3061,6 @@ test "using slices for strings" { |
| 3052 | } | 3061 | } |
| 3053 | | 3062 | |
| 3054 | test "slice pointer" { | 3063 | test "slice pointer" { |
| 3055 | var a: []u8 = undefined; | | |
| 3056 | try expect(@TypeOf(a) == []u8); | | |
| 3057 | var array: [10]u8 = undefined; | 3064 | var array: [10]u8 = undefined; |
| 3058 | const ptr = &array; | 3065 | const ptr = &array; |
| 3059 | try expect(@TypeOf(ptr) == *[10]u8); | 3066 | try expect(@TypeOf(ptr) == *[10]u8); |
| ... | @@ -3062,10 +3069,10 @@ test "slice pointer" { | ... | @@ -3062,10 +3069,10 @@ test "slice pointer" { |
| 3062 | var start: usize = 0; | 3069 | var start: usize = 0; |
| 3063 | var end: usize = 5; | 3070 | var end: usize = 5; |
| 3064 | const slice = ptr[start..end]; | 3071 | const slice = ptr[start..end]; |
| 3065 | slice[2] = 3; | | |
| 3066 | try expect(slice[2] == 3); | | |
| 3067 | // The slice is mutable because we sliced a mutable pointer. | 3072 | // The slice is mutable because we sliced a mutable pointer. |
| 3068 | try expect(@TypeOf(slice) == []u8); | 3073 | try expect(@TypeOf(slice) == []u8); |
| | 3074 | slice[2] = 3; |
| | 3075 | try expect(array[2] == 3); |
| 3069 | | 3076 | |
| 3070 | // Again, slicing with comptime-known indexes will produce another pointer | 3077 | // Again, slicing with comptime-known indexes will produce another pointer |
| 3071 | // to an array: | 3078 | // to an array: |
| ... | @@ -3088,7 +3095,7 @@ test "slice pointer" { | ... | @@ -3088,7 +3095,7 @@ test "slice pointer" { |
| 3088 | const std = @import("std"); | 3095 | const std = @import("std"); |
| 3089 | const expect = std.testing.expect; | 3096 | const expect = std.testing.expect; |
| 3090 | | 3097 | |
| 3091 | test "null terminated slice" { | 3098 | test "0-terminated slice" { |
| 3092 | const slice: [:0]const u8 = "hello"; | 3099 | const slice: [:0]const u8 = "hello"; |
| 3093 | | 3100 | |
| 3094 | try expect(slice.len == 5); | 3101 | try expect(slice.len == 5); |
| ... | @@ -3104,7 +3111,7 @@ test "null terminated slice" { | ... | @@ -3104,7 +3111,7 @@ test "null terminated slice" { |
| 3104 | const std = @import("std"); | 3111 | const std = @import("std"); |
| 3105 | const expect = std.testing.expect; | 3112 | const expect = std.testing.expect; |
| 3106 | | 3113 | |
| 3107 | test "null terminated slicing" { | 3114 | test "0-terminated slicing" { |
| 3108 | var array = [_]u8{ 3, 2, 1, 0, 3, 2, 1, 0 }; | 3115 | var array = [_]u8{ 3, 2, 1, 0, 3, 2, 1, 0 }; |
| 3109 | var runtime_length: usize = 3; | 3116 | var runtime_length: usize = 3; |
| 3110 | const slice = array[0..runtime_length :0]; | 3117 | const slice = array[0..runtime_length :0]; |
| ... | @@ -3590,7 +3597,7 @@ const std = @import("std"); | ... | @@ -3590,7 +3597,7 @@ const std = @import("std"); |
| 3590 | const expect = std.testing.expect; | 3597 | const expect = std.testing.expect; |
| 3591 | | 3598 | |
| 3592 | test "fully anonymous struct" { | 3599 | test "fully anonymous struct" { |
| 3593 | try dump(.{ | 3600 | try check(.{ |
| 3594 | .int = @as(u32, 1234), | 3601 | .int = @as(u32, 1234), |
| 3595 | .float = @as(f64, 12.34), | 3602 | .float = @as(f64, 12.34), |
| 3596 | .b = true, | 3603 | .b = true, |
| ... | @@ -3598,7 +3605,7 @@ test "fully anonymous struct" { | ... | @@ -3598,7 +3605,7 @@ test "fully anonymous struct" { |
| 3598 | }); | 3605 | }); |
| 3599 | } | 3606 | } |
| 3600 | | 3607 | |
| 3601 | fn dump(args: anytype) !void { | 3608 | fn check(args: anytype) !void { |
| 3602 | try expect(args.int == 1234); | 3609 | try expect(args.int == 1234); |
| 3603 | try expect(args.float == 12.34); | 3610 | try expect(args.float == 12.34); |
| 3604 | try expect(args.b); | 3611 | try expect(args.b); |
| ... | @@ -3813,8 +3820,8 @@ test "switch using enum literals" { | ... | @@ -3813,8 +3820,8 @@ test "switch using enum literals" { |
| 3813 | | 3820 | |
| 3814 | {#header_open|Non-exhaustive enum#} | 3821 | {#header_open|Non-exhaustive enum#} |
| 3815 | <p> | 3822 | <p> |
| 3816 | A Non-exhaustive enum can be created by adding a trailing '_' field. | 3823 | A non-exhaustive enum can be created by adding a trailing {#syntax#}_{#endsyntax#} field. |
| 3817 | It must specify a tag type and cannot consume every enumeration value. | 3824 | The enum must specify a tag type and cannot consume every enumeration value. |
| 3818 | </p> | 3825 | </p> |
| 3819 | <p> | 3826 | <p> |
| 3820 | {#link|@enumFromInt#} on a non-exhaustive enum involves the safety semantics | 3827 | {#link|@enumFromInt#} on a non-exhaustive enum involves the safety semantics |
| ... | @@ -3822,8 +3829,8 @@ test "switch using enum literals" { | ... | @@ -3822,8 +3829,8 @@ test "switch using enum literals" { |
| 3822 | a well-defined enum value. | 3829 | a well-defined enum value. |
| 3823 | </p> | 3830 | </p> |
| 3824 | <p> | 3831 | <p> |
| 3825 | A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong | 3832 | A switch on a non-exhaustive enum can include a {#syntax#}_{#endsyntax#} prong as an alternative to an {#syntax#}else{#endsyntax#} prong. |
| 3826 | with the difference being that it makes it a compile error if all the known tag names are not handled by the switch. | 3833 | With a {#syntax#}_{#endsyntax#} prong the compiler errors if all the known tag names are not handled by the switch. |
| 3827 | </p> | 3834 | </p> |
| 3828 | {#code_begin|test|test_switch_non-exhaustive#} | 3835 | {#code_begin|test|test_switch_non-exhaustive#} |
| 3829 | const std = @import("std"); | 3836 | const std = @import("std"); |
| ... | @@ -5268,14 +5275,14 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 { | ... | @@ -5268,14 +5275,14 @@ fn shiftLeftOne(a: u32) callconv(.Inline) u32 { |
| 5268 | pub fn sub2(a: i8, b: i8) i8 { return a - b; } | 5275 | pub fn sub2(a: i8, b: i8) i8 { return a - b; } |
| 5269 | | 5276 | |
| 5270 | // Function pointers are prefixed with `*const `. | 5277 | // Function pointers are prefixed with `*const `. |
| 5271 | const call2_op = *const fn (a: i8, b: i8) i8; | 5278 | const Call2Op = *const fn (a: i8, b: i8) i8; |
| 5272 | fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 { | 5279 | fn doOp(fnCall: Call2Op, op1: i8, op2: i8) i8 { |
| 5273 | return fn_call(op1, op2); | 5280 | return fnCall(op1, op2); |
| 5274 | } | 5281 | } |
| 5275 | | 5282 | |
| 5276 | test "function" { | 5283 | test "function" { |
| 5277 | try expect(do_op(add, 5, 6) == 11); | 5284 | try expect(doOp(add, 5, 6) == 11); |
| 5278 | try expect(do_op(sub2, 5, 6) == -1); | 5285 | try expect(doOp(sub2, 5, 6) == -1); |
| 5279 | } | 5286 | } |
| 5280 | {#code_end#} | 5287 | {#code_end#} |
| 5281 | <p>There is a difference between a function <em>body</em> and a function <em>pointer</em>. | 5288 | <p>There is a difference between a function <em>body</em> and a function <em>pointer</em>. |
| ... | @@ -6515,7 +6522,7 @@ test "coerce to optionals" { | ... | @@ -6515,7 +6522,7 @@ test "coerce to optionals" { |
| 6515 | try expect(y == null); | 6522 | try expect(y == null); |
| 6516 | } | 6523 | } |
| 6517 | {#code_end#} | 6524 | {#code_end#} |
| 6518 | <p>It works nested inside the {#link|Error Union Type#}, too:</p> | 6525 | <p>Optionals work nested inside the {#link|Error Union Type#}, too:</p> |
| 6519 | {#code_begin|test|test_coerce_optional_wrapped_error_union#} | 6526 | {#code_begin|test|test_coerce_optional_wrapped_error_union#} |
| 6520 | const std = @import("std"); | 6527 | const std = @import("std"); |
| 6521 | const expect = std.testing.expect; | 6528 | const expect = std.testing.expect; |
| ... | @@ -6841,7 +6848,8 @@ test "turn HashMap into a set with void" { | ... | @@ -6841,7 +6848,8 @@ test "turn HashMap into a set with void" { |
| 6841 | {#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}anyopaque{#endsyntax#} has an unknown, but non-zero, size. | 6848 | {#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}anyopaque{#endsyntax#} has an unknown, but non-zero, size. |
| 6842 | </p> | 6849 | </p> |
| 6843 | <p> | 6850 | <p> |
| 6844 | Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example: | 6851 | Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example, ignoring |
| | 6852 | a non-{#syntax#}void{#endsyntax#} expression is a compile error: |
| 6845 | </p> | 6853 | </p> |
| 6846 | {#code_begin|test_err|test_expression_ignored|ignored#} | 6854 | {#code_begin|test_err|test_expression_ignored|ignored#} |
| 6847 | test "ignoring expression value" { | 6855 | test "ignoring expression value" { |
| ... | @@ -6852,7 +6860,7 @@ fn foo() i32 { | ... | @@ -6852,7 +6860,7 @@ fn foo() i32 { |
| 6852 | return 1234; | 6860 | return 1234; |
| 6853 | } | 6861 | } |
| 6854 | {#code_end#} | 6862 | {#code_end#} |
| 6855 | <p>However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Function return values can also be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}. </p> | 6863 | <p>However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Expression results can be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}. </p> |
| 6856 | {#code_begin|test|test_void_ignored#} | 6864 | {#code_begin|test|test_void_ignored#} |
| 6857 | test "void is ignored" { | 6865 | test "void is ignored" { |
| 6858 | returnsVoid(); | 6866 | returnsVoid(); |
| ... | @@ -7110,12 +7118,10 @@ fn performFn(start_value: i32) i32 { | ... | @@ -7110,12 +7118,10 @@ fn performFn(start_value: i32) i32 { |
| 7110 | } | 7118 | } |
| 7111 | {#end_syntax_block#} | 7119 | {#end_syntax_block#} |
| 7112 | <p> | 7120 | <p> |
| 7113 | Note that this happens even in a debug build; in a release build these generated functions still | 7121 | Note that this happens even in a debug build. |
| 7114 | pass through rigorous LLVM optimizations. The important thing to note, however, is not that this | 7122 | This is not a way to write more optimized code, but it is a way to make sure that what <em>should</em> happen |
| 7115 | is a way to write more optimized code, but that it is a way to make sure that what <em>should</em> happen | 7123 | at compile-time, <em>does</em> happen at compile-time. This catches more errors and allows expressiveness |
| 7116 | at compile-time, <em>does</em> happen at compile-time. This catches more errors and as demonstrated | 7124 | that in other languages requires using macros, generated code, or a preprocessor to accomplish. |
| 7117 | later in this article, allows expressiveness that in other languages requires using macros, | | |
| 7118 | generated code, or a preprocessor to accomplish. | | |
| 7119 | </p> | 7125 | </p> |
| 7120 | {#header_close#} | 7126 | {#header_close#} |
| 7121 | {#header_open|Compile-Time Expressions#} | 7127 | {#header_open|Compile-Time Expressions#} |
| ... | @@ -7297,9 +7303,8 @@ test "variable values" { | ... | @@ -7297,9 +7303,8 @@ test "variable values" { |
| 7297 | {#header_close#} | 7303 | {#header_close#} |
| 7298 | {#header_open|Generic Data Structures#} | 7304 | {#header_open|Generic Data Structures#} |
| 7299 | <p> | 7305 | <p> |
| 7300 | Zig uses these capabilities to implement generic data structures without introducing any | 7306 | Zig uses comptime capabilities to implement generic data structures without introducing any |
| 7301 | special-case syntax. If you followed along so far, you may already know how to create a | 7307 | special-case syntax. |
| 7302 | generic data structure. | | |
| 7303 | </p> | 7308 | </p> |
| 7304 | <p> | 7309 | <p> |
| 7305 | 			Here is an example of a generic {#syntax#}List{#endsyntax#} data structure. | 7310 | 			Here is an example of a generic {#syntax#}List{#endsyntax#} data structure. |
| ... | @@ -7321,7 +7326,6 @@ var list = List(i32){ | ... | @@ -7321,7 +7326,6 @@ var list = List(i32){ |
| 7321 | {#code_end#} | 7326 | {#code_end#} |
| 7322 | <p> | 7327 | <p> |
| 7323 | That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}. | 7328 | That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}. |
| 7324 | To keep the language small and uniform, all aggregate types in Zig are anonymous. | | |
| 7325 | For the purposes of error messages and debugging, Zig infers the name | 7329 | For the purposes of error messages and debugging, Zig infers the name |
| 7326 | {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating | 7330 | {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating |
| 7327 | the anonymous struct. | 7331 | the anonymous struct. |
| ... | @@ -7754,6 +7758,9 @@ test "global assembly" { | ... | @@ -7754,6 +7758,9 @@ test "global assembly" { |
| 7754 | <p>TODO: @fence()</p> | 7758 | <p>TODO: @fence()</p> |
| 7755 | <p>TODO: @atomic rmw</p> | 7759 | <p>TODO: @atomic rmw</p> |
| 7756 | <p>TODO: builtin atomic memory ordering enum</p> | 7760 | <p>TODO: builtin atomic memory ordering enum</p> |
| | 7761 | |
| | 7762 | {#see_also|@atomicLoad|@atomicStore|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} |
| | 7763 | |
| 7757 | {#header_close#} | 7764 | {#header_close#} |
| 7758 | | 7765 | |
| 7759 | {#header_open|Async Functions#} | 7766 | {#header_open|Async Functions#} |
| ... | @@ -7824,7 +7831,7 @@ comptime { | ... | @@ -7824,7 +7831,7 @@ comptime { |
| 7824 | {#header_open|@atomicLoad#} | 7831 | {#header_open|@atomicLoad#} |
| 7825 | <pre>{#syntax#}@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}</pre> | 7832 | <pre>{#syntax#}@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}</pre> |
| 7826 | <p> | 7833 | <p> |
| 7827 | This builtin function atomically dereferences a pointer and returns the value. | 7834 | This builtin function atomically dereferences a pointer to a {#syntax#}T{#endsyntax#} and returns the value. |
| 7828 | </p> | 7835 | </p> |
| 7829 | <p> | 7836 | <p> |
| 7830 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 7837 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, |
| ... | @@ -7836,14 +7843,15 @@ comptime { | ... | @@ -7836,14 +7843,15 @@ comptime { |
| 7836 | {#header_open|@atomicRmw#} | 7843 | {#header_open|@atomicRmw#} |
| 7837 | <pre>{#syntax#}@atomicRmw(comptime T: type, ptr: *T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}</pre> | 7844 | <pre>{#syntax#}@atomicRmw(comptime T: type, ptr: *T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T{#endsyntax#}</pre> |
| 7838 | <p> | 7845 | <p> |
| 7839 | This builtin function atomically modifies memory and then returns the previous value. | 7846 | This builtin function dereferences a pointer to a {#syntax#}T{#endsyntax#} and atomically |
| | 7847 | modifies the value and returns the previous value. |
| 7840 | </p> | 7848 | </p> |
| 7841 | <p> | 7849 | <p> |
| 7842 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 7850 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, |
| 7843 | an integer or an enum. | 7851 | an integer or an enum. |
| 7844 | </p> | 7852 | </p> |
| 7845 | <p> | 7853 | <p> |
| 7846 | Supported operations: | 7854 | Supported values for the {#syntax#}op{#endsyntax#} parameter: |
| 7847 | </p> | 7855 | </p> |
| 7848 | <ul> | 7856 | <ul> |
| 7849 | <li>{#syntax#}.Xchg{#endsyntax#} - stores the operand unmodified. Supports enums, integers and floats.</li> | 7857 | <li>{#syntax#}.Xchg{#endsyntax#} - stores the operand unmodified. Supports enums, integers and floats.</li> |
| ... | @@ -7864,7 +7872,7 @@ comptime { | ... | @@ -7864,7 +7872,7 @@ comptime { |
| 7864 | {#header_open|@atomicStore#} | 7872 | {#header_open|@atomicStore#} |
| 7865 | <pre>{#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}</pre> | 7873 | <pre>{#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}</pre> |
| 7866 | <p> | 7874 | <p> |
| 7867 | This builtin function atomically stores a value. | 7875 | This builtin function dereferences a pointer to a {#syntax#}T{#endsyntax#} and atomically stores the given value. |
| 7868 | </p> | 7876 | </p> |
| 7869 | <p> | 7877 | <p> |
| 7870 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, | 7878 | {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float, |
| ... | @@ -8122,7 +8130,8 @@ pub const CallModifier = enum { | ... | @@ -8122,7 +8130,8 @@ pub const CallModifier = enum { |
| 8122 | {#header_open|@cmpxchgStrong#} | 8130 | {#header_open|@cmpxchgStrong#} |
| 8123 | <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> | 8131 | <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> |
| 8124 | <p> | 8132 | <p> |
| 8125 | This function performs a strong atomic compare exchange operation. It's the equivalent of this code, | 8133 | This function performs a strong atomic compare-and-exchange operation, returning {#syntax#}null{#endsyntax#} |
| | 8134 | if the current value is not the given expected value. It's the equivalent of this code, |
| 8126 | except atomic: | 8135 | except atomic: |
| 8127 | </p> | 8136 | </p> |
| 8128 | {#code_begin|syntax|not_atomic_cmpxchgStrong#} | 8137 | {#code_begin|syntax|not_atomic_cmpxchgStrong#} |
| ... | @@ -8137,7 +8146,7 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v | ... | @@ -8137,7 +8146,7 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v |
| 8137 | } | 8146 | } |
| 8138 | {#code_end#} | 8147 | {#code_end#} |
| 8139 | <p> | 8148 | <p> |
| 8140 | If you are using cmpxchg in a loop, {#link|@cmpxchgWeak#} is the better choice, because it can be implemented | 8149 | If you are using cmpxchg in a retry loop, {#link|@cmpxchgWeak#} is the better choice, because it can be implemented |
| 8141 | more efficiently in machine instructions. | 8150 | more efficiently in machine instructions. |
| 8142 | </p> | 8151 | </p> |
| 8143 | <p> | 8152 | <p> |
| ... | @@ -8151,7 +8160,8 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v | ... | @@ -8151,7 +8160,8 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v |
| 8151 | {#header_open|@cmpxchgWeak#} | 8160 | {#header_open|@cmpxchgWeak#} |
| 8152 | <pre>{#syntax#}@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> | 8161 | <pre>{#syntax#}@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre> |
| 8153 | <p> | 8162 | <p> |
| 8154 | This function performs a weak atomic compare exchange operation. It's the equivalent of this code, | 8163 | This function performs a weak atomic compare-and-exchange operation, returning {#syntax#}null{#endsyntax#} |
| | 8164 | if the current value is not the given expected value. It's the equivalent of this code, |
| 8155 | except atomic: | 8165 | except atomic: |
| 8156 | </p> | 8166 | </p> |
| 8157 | {#syntax_block|zig|cmpxchgWeakButNotAtomic#} | 8167 | {#syntax_block|zig|cmpxchgWeakButNotAtomic#} |
| ... | @@ -8166,7 +8176,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val | ... | @@ -8166,7 +8176,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 8166 | } | 8176 | } |
| 8167 | {#end_syntax_block#} | 8177 | {#end_syntax_block#} |
| 8168 | <p> | 8178 | <p> |
| 8169 | If you are using cmpxchg in a loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#} | 8179 | If you are using cmpxchg in a retry loop, the sporadic failure will be no problem, and {#syntax#}cmpxchgWeak{#endsyntax#} |
| 8170 | is the better choice, because it can be implemented more efficiently in machine instructions. | 8180 | is the better choice, because it can be implemented more efficiently in machine instructions. |
| 8171 | However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}. | 8181 | However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}. |
| 8172 | </p> | 8182 | </p> |
| ... | @@ -8219,24 +8229,6 @@ const num1 = blk: { | ... | @@ -8219,24 +8229,6 @@ const num1 = blk: { |
| 8219 | test "main" { | 8229 | test "main" { |
| 8220 | @compileLog("comptime in main"); | 8230 | @compileLog("comptime in main"); |
| 8221 | | 8231 | |
| 8222 | print("Runtime in main, num1 = {}.\n", .{num1}); | | |
| 8223 | } | | |
| 8224 | {#code_end#} | | |
| 8225 | <p> | | |
| 8226 | If all {#syntax#}@compileLog{#endsyntax#} calls are removed or | | |
| 8227 | not encountered by analysis, the | | |
| 8228 | program compiles successfully and the generated executable prints: | | |
| 8229 | </p> | | |
| 8230 | {#code_begin|test|test_without_compileLog_builtin#} | | |
| 8231 | const print = @import("std").debug.print; | | |
| 8232 | | | |
| 8233 | const num1 = blk: { | | |
| 8234 | var val1: i32 = 99; | | |
| 8235 | val1 = val1 + 1; | | |
| 8236 | break :blk val1; | | |
| 8237 | }; | | |
| 8238 | | | |
| 8239 | test "main" { | | |
| 8240 | print("Runtime in main, num1 = {}.\n", .{num1}); | 8232 | print("Runtime in main, num1 = {}.\n", .{num1}); |
| 8241 | } | 8233 | } |
| 8242 | {#code_end#} | 8234 | {#code_end#} |
| ... | @@ -9020,14 +9012,16 @@ pub const PrefetchOptions = struct { | ... | @@ -9020,14 +9012,16 @@ pub const PrefetchOptions = struct { |
| 9020 | {#header_open|@setCold#} | 9012 | {#header_open|@setCold#} |
| 9021 | <pre>{#syntax#}@setCold(comptime is_cold: bool) void{#endsyntax#}</pre> | 9013 | <pre>{#syntax#}@setCold(comptime is_cold: bool) void{#endsyntax#}</pre> |
| 9022 | <p> | 9014 | <p> |
| 9023 | Tells the optimizer that a function is rarely called. | 9015 | Tells the optimizer that the current function is (or is not) rarely called. |
| | 9016 | |
| | 9017 | This function is only valid within function scope. |
| 9024 | </p> | 9018 | </p> |
| 9025 | {#header_close#} | 9019 | {#header_close#} |
| 9026 | | 9020 | |
| 9027 | {#header_open|@setEvalBranchQuota#} | 9021 | {#header_open|@setEvalBranchQuota#} |
| 9028 | <pre>{#syntax#}@setEvalBranchQuota(comptime new_quota: u32) void{#endsyntax#}</pre> | 9022 | <pre>{#syntax#}@setEvalBranchQuota(comptime new_quota: u32) void{#endsyntax#}</pre> |
| 9029 | <p> | 9023 | <p> |
| 9030 | Changes the maximum number of backwards branches that compile-time code | 9024 | Increase the maximum number of backwards branches that compile-time code |
| 9031 | execution can use before giving up and making a compile error. | 9025 | execution can use before giving up and making a compile error. |
| 9032 | </p> | 9026 | </p> |
| 9033 | <p> | 9027 | <p> |
| ... | @@ -9232,7 +9226,7 @@ test "vector @shuffle" { | ... | @@ -9232,7 +9226,7 @@ test "vector @shuffle" { |
| 9232 | The result is a target-specific compile time constant. | 9226 | The result is a target-specific compile time constant. |
| 9233 | </p> | 9227 | </p> |
| 9234 | <p> | 9228 | <p> |
| 9235 | This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset | 9229 | This size may contain padding bytes. If there were two consecutive T in memory, the padding would be the offset |
| 9236 | in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#}, | 9230 | in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#}, |
| 9237 | consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or | 9231 | consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or |
| 9238 | {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}. | 9232 | {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}. |
| ... | @@ -9247,7 +9241,7 @@ test "vector @shuffle" { | ... | @@ -9247,7 +9241,7 @@ test "vector @shuffle" { |
| 9247 | {#header_open|@splat#} | 9241 | {#header_open|@splat#} |
| 9248 | <pre>{#syntax#}@splat(scalar: anytype) anytype{#endsyntax#}</pre> | 9242 | <pre>{#syntax#}@splat(scalar: anytype) anytype{#endsyntax#}</pre> |
| 9249 | <p> | 9243 | <p> |
| 9250 | Produces a vector where each element is the value {#syntax#}scalar{#endsyntax#}. | 9244 | Produces a vector where each element is the value {#syntax#}scalar{#endsyntax#}. |
| 9251 | The return type and thus the length of the vector is inferred. | 9245 | The return type and thus the length of the vector is inferred. |
| 9252 | </p> | 9246 | </p> |
| 9253 | {#code_begin|test|test_splat_builtin#} | 9247 | {#code_begin|test|test_splat_builtin#} |