authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-26 12:06:08-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-26 12:06:08-04:00
log1f96a866769423e363f1c48654c0f51ecf75db58
tree504b4913f00bd6a32f097ea6061d5fa211d2c940
parent284ab109c4b83f7bb9a832f284f706e641b002fd
parentc029f4bfc47b5d6d825f7ae7a3f224e9e9d6ce0b

Merge remote-tracking branch 'origin/master' into llvm7


134 files changed, 8980 insertions(+), 6179 deletions(-)

CMakeLists.txt+1-1
......@@ -196,7 +196,7 @@ else()
196196 if(MSVC)
197197 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
198198 else()
199 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
199 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment -Wno-class-memaccess -Wno-unknown-warning-option")
200200 endif()
201201 set_target_properties(embedded_lld_lib PROPERTIES
202202 COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
README.md+7-4
......@@ -1,9 +1,9 @@
1![ZIG](http://ziglang.org/zig-logo.svg)
1![ZIG](https://ziglang.org/zig-logo.svg)
22
33A programming language designed for robustness, optimality, and
44clarity.
55
6[ziglang.org](http://ziglang.org)
6[ziglang.org](https://ziglang.org)
77
88## Feature Highlights
99
......@@ -114,7 +114,7 @@ libc. Create demo games using Zig.
114114
115115## Building
116116
117[![Build Status](https://travis-ci.org/zig-lang/zig.svg?branch=master)](https://travis-ci.org/zig-lang/zig)
117[![Build Status](https://travis-ci.org/ziglang/zig.svg?branch=master)](https://travis-ci.org/ziglang/zig)
118118[![Build status](https://ci.appveyor.com/api/projects/status/4t80mk2dmucrc38i/branch/master?svg=true)](https://ci.appveyor.com/project/andrewrk/zig-d3l86/branch/master)
119119
120120### Stage 1: Build Zig from C++ Source Code
......@@ -161,7 +161,7 @@ bin/zig build --build-file ../build.zig test
161161
162162##### Windows
163163
164See https://github.com/zig-lang/zig/wiki/Building-Zig-on-Windows
164See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
165165
166166### Stage 2: Build Self-Hosted Zig from Zig Source Code
167167
......@@ -182,6 +182,9 @@ binary.
182182
183183This is the actual compiler binary that we will install to the system.
184184
185*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
186not yet supported.*
187
185188#### Debug / Development Build
186189
187190```
build.zig+34-25
......@@ -16,7 +16,7 @@ pub fn build(b: &Builder) !void {
1616 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
1717
1818 const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
19 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 {
19 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
2020 docgen_exe.getOutputPath(),
2121 rel_zig_exe,
2222 "doc/langref.html.in",
......@@ -30,7 +30,10 @@ pub fn build(b: &Builder) !void {
3030 const test_step = b.step("test", "Run all the tests");
3131
3232 // find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
33 const build_info = try b.exec([][]const u8{b.zig_exe, "BUILD_INFO"});
33 const build_info = try b.exec([][]const u8{
34 b.zig_exe,
35 "BUILD_INFO",
36 });
3437 var index: usize = 0;
3538 const cmake_binary_dir = nextValue(&index, build_info);
3639 const cxx_compiler = nextValue(&index, build_info);
......@@ -67,7 +70,10 @@ pub fn build(b: &Builder) !void {
6770 dependOnLib(exe, llvm);
6871
6972 if (exe.target.getOs() == builtin.Os.linux) {
70 const libstdcxx_path_padded = try b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"});
73 const libstdcxx_path_padded = try b.exec([][]const u8{
74 cxx_compiler,
75 "-print-file-name=libstdc++.a",
76 });
7177 const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next();
7278 if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
7379 warn(
......@@ -111,17 +117,11 @@ pub fn build(b: &Builder) !void {
111117
112118 test_step.dependOn(docs_step);
113119
114 test_step.dependOn(tests.addPkgTests(b, test_filter,
115 "test/behavior.zig", "behavior", "Run the behavior tests",
116 with_lldb));
120 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", with_lldb));
117121
118 test_step.dependOn(tests.addPkgTests(b, test_filter,
119 "std/index.zig", "std", "Run the standard library tests",
120 with_lldb));
122 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", with_lldb));
121123
122 test_step.dependOn(tests.addPkgTests(b, test_filter,
123 "std/special/compiler_rt/index.zig", "compiler-rt", "Run the compiler_rt tests",
124 with_lldb));
124 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt/index.zig", "compiler-rt", "Run the compiler_rt tests", with_lldb));
125125
126126 test_step.dependOn(tests.addCompareOutputTests(b, test_filter));
127127 test_step.dependOn(tests.addBuildExampleTests(b, test_filter));
......@@ -149,8 +149,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) vo
149149
150150fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void {
151151 const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
152 lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp",
153 b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
152 lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
154153}
155154
156155const LibraryDep = struct {
......@@ -161,11 +160,21 @@ const LibraryDep = struct {
161160};
162161
163162fn findLLVM(b: &Builder, llvm_config_exe: []const u8) !LibraryDep {
164 const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
165 const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"});
166 const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"});
163 const libs_output = try b.exec([][]const u8{
164 llvm_config_exe,
165 "--libs",
166 "--system-libs",
167 });
168 const includes_output = try b.exec([][]const u8{
169 llvm_config_exe,
170 "--includedir",
171 });
172 const libdir_output = try b.exec([][]const u8{
173 llvm_config_exe,
174 "--libdir",
175 });
167176
168 var result = LibraryDep {
177 var result = LibraryDep{
169178 .libs = ArrayList([]const u8).init(b.allocator),
170179 .system_libs = ArrayList([]const u8).init(b.allocator),
171180 .includes = ArrayList([]const u8).init(b.allocator),
......@@ -227,17 +236,17 @@ pub fn installCHeaders(b: &Builder, c_header_files: []const u8) void {
227236}
228237
229238fn nextValue(index: &usize, build_info: []const u8) []const u8 {
230 const start = *index;
231 while (true) : (*index += 1) {
232 switch (build_info[*index]) {
239 const start = index.*;
240 while (true) : (index.* += 1) {
241 switch (build_info[index.*]) {
233242 '\n' => {
234 const result = build_info[start..*index];
235 *index += 1;
243 const result = build_info[start..index.*];
244 index.* += 1;
236245 return result;
237246 },
238247 '\r' => {
239 const result = build_info[start..*index];
240 *index += 2;
248 const result = build_info[start..index.*];
249 index.* += 2;
241250 return result;
242251 },
243252 else => continue,
doc/langref.html.in+133-40
......@@ -96,7 +96,7 @@
9696 </p>
9797 <p>
9898 If you search for something specific in this documentation and do not find it,
99 please <a href="https://github.com/zig-lang/www.ziglang.org/issues/new?title=I%20searched%20for%20___%20in%20the%20docs%20and%20didn%27t%20find%20it">file an issue</a> or <a href="https://webchat.freenode.net/?channels=%23zig">say something on IRC</a>.
99 please <a href="https://github.com/ziglang/www.ziglang.org/issues/new?title=I%20searched%20for%20___%20in%20the%20docs%20and%20didn%27t%20find%20it">file an issue</a> or <a href="https://webchat.freenode.net/?channels=%23zig">say something on IRC</a>.
100100 </p>
101101 <p>
102102 The code samples in this document are compiled and tested as part of the main test suite of Zig.
......@@ -1232,7 +1232,7 @@ mem.eql(u8, pattern, "ababab")</code></pre>
12321232 </td>
12331233 </tr>
12341234 <tr>
1235 <td><pre><code class="zig">*a<code></pre></td>
1235 <td><pre><code class="zig">a.*<code></pre></td>
12361236 <td>
12371237 <ul>
12381238 <li>{#link|Pointers#}</li>
......@@ -1244,7 +1244,7 @@ mem.eql(u8, pattern, "ababab")</code></pre>
12441244 <td>
12451245 <pre><code class="zig">const x: u32 = 1234;
12461246const ptr = &amp;x;
1247*x == 1234</code></pre>
1247x.* == 1234</code></pre>
12481248 </td>
12491249 </tr>
12501250 <tr>
......@@ -1258,7 +1258,7 @@ const ptr = &amp;x;
12581258 <td>
12591259 <pre><code class="zig">const x: u32 = 1234;
12601260const ptr = &amp;x;
1261*x == 1234</code></pre>
1261x.* == 1234</code></pre>
12621262 </td>
12631263 </tr>
12641264 </table>
......@@ -1267,8 +1267,8 @@ const ptr = &amp;x;
12671267 {#header_open|Precedence#}
12681268 <pre><code>x() x[] x.y
12691269a!b
1270!x -x -%x ~x *x &amp;x ?x ??x
1271x{}
1270!x -x -%x ~x &amp;x ?x ??x
1271x{} x.*
12721272! * / % ** *%
12731273+ - ++ +% -%
12741274&lt;&lt; &gt;&gt;
......@@ -1316,7 +1316,7 @@ var some_integers: [100]i32 = undefined;
13161316
13171317test "modify an array" {
13181318 for (some_integers) |*item, i| {
1319 *item = i32(i);
1319 item.* = i32(i);
13201320 }
13211321 assert(some_integers[10] == 10);
13221322 assert(some_integers[99] == 99);
......@@ -1357,7 +1357,7 @@ comptime {
13571357var fancy_array = init: {
13581358 var initial_value: [10]Point = undefined;
13591359 for (initial_value) |*pt, i| {
1360 *pt = Point {
1360 pt.* = Point {
13611361 .x = i32(i),
13621362 .y = i32(i) * 2,
13631363 };
......@@ -1400,7 +1400,7 @@ test "address of syntax" {
14001400 const x_ptr = &x;
14011401
14021402 // Deference a pointer:
1403 assert(*x_ptr == 1234);
1403 assert(x_ptr.* == 1234);
14041404
14051405 // When you get the address of a const variable, you get a const pointer.
14061406 assert(@typeOf(x_ptr) == &const i32);
......@@ -1409,8 +1409,8 @@ test "address of syntax" {
14091409 var y: i32 = 5678;
14101410 const y_ptr = &y;
14111411 assert(@typeOf(y_ptr) == &i32);
1412 *y_ptr += 1;
1413 assert(*y_ptr == 5679);
1412 y_ptr.* += 1;
1413 assert(y_ptr.* == 5679);
14141414}
14151415
14161416test "pointer array access" {
......@@ -1448,9 +1448,9 @@ comptime {
14481448 // @ptrCast.
14491449 var x: i32 = 1;
14501450 const ptr = &x;
1451 *ptr += 1;
1451 ptr.* += 1;
14521452 x += 1;
1453 assert(*ptr == 3);
1453 assert(ptr.* == 3);
14541454}
14551455
14561456test "@ptrToInt and @intToPtr" {
......@@ -1492,7 +1492,7 @@ test "nullable pointers" {
14921492 var x: i32 = 1;
14931493 ptr = &x;
14941494
1495 assert(*??ptr == 1);
1495 assert((??ptr).* == 1);
14961496
14971497 // Nullable pointers are the same size as normal pointers, because pointer
14981498 // value 0 is used as the null value.
......@@ -1505,7 +1505,7 @@ test "pointer casting" {
15051505 // conversions are not possible.
15061506 const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12};
15071507 const u32_ptr = @ptrCast(&const u32, &bytes[0]);
1508 assert(*u32_ptr == 0x12121212);
1508 assert(u32_ptr.* == 0x12121212);
15091509
15101510 // Even this example is contrived - there are better ways to do the above than
15111511 // pointer casting. For example, using a slice narrowing cast:
......@@ -1610,7 +1610,7 @@ fn foo(bytes: []u8) u32 {
16101610 <code>u8</code> can alias any memory.
16111611 </p>
16121612 <p>As an example, this code produces undefined behavior:</p>
1613 <pre><code class="zig">*@ptrCast(&amp;u32, f32(12.34))</code></pre>
1613 <pre><code class="zig">@ptrCast(&amp;u32, f32(12.34)).*</code></pre>
16141614 <p>Instead, use {#link|@bitCast#}:
16151615 <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
16161616 <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>
......@@ -2040,7 +2040,7 @@ const Variant = union(enum) {
20402040 Bool: bool,
20412041
20422042 fn truthy(self: &const Variant) bool {
2043 return switch (*self) {
2043 return switch (self.*) {
20442044 Variant.Int => |x_int| x_int != 0,
20452045 Variant.Bool => |x_bool| x_bool,
20462046 };
......@@ -2151,7 +2151,7 @@ test "switch enum" {
21512151
21522152 // A reference to the matched value can be obtained using `*` syntax.
21532153 Item.C => |*item| blk: {
2154 (*item).x += 1;
2154 item.*.x += 1;
21552155 break :blk 6;
21562156 },
21572157
......@@ -2374,7 +2374,7 @@ test "for reference" {
23742374 // Iterate over the slice by reference by
23752375 // specifying that the capture value is a pointer.
23762376 for (items) |*value| {
2377 *value += 1;
2377 value.* += 1;
23782378 }
23792379
23802380 assert(items[0] == 4);
......@@ -2483,7 +2483,7 @@ test "if nullable" {
24832483 // Access the value by reference using a pointer capture.
24842484 var c: ?u32 = 3;
24852485 if (c) |*value| {
2486 *value = 2;
2486 value.* = 2;
24872487 }
24882488
24892489 if (c) |value| {
......@@ -2524,7 +2524,7 @@ test "if error union" {
25242524 // Access the value by reference using a pointer capture.
25252525 var c: error!u32 = 3;
25262526 if (c) |*value| {
2527 *value = 9;
2527 value.* = 9;
25282528 } else |err| {
25292529 unreachable;
25302530 }
......@@ -2827,7 +2827,7 @@ test "fn reflection" {
28272827 </p>
28282828 <p>
28292829 The number of unique error values across the entire compilation should determine the size of the error set type.
2830 However right now it is hard coded to be a <code>u16</code>. See <a href="https://github.com/zig-lang/zig/issues/786">#768</a>.
2830 However right now it is hard coded to be a <code>u16</code>. See <a href="https://github.com/ziglang/zig/issues/786">#768</a>.
28312831 </p>
28322832 <p>
28332833 You can implicitly cast an error from a subset to its superset:
......@@ -3111,7 +3111,48 @@ test "error union" {
31113111 {#code_end#}
31123112 <p>TODO the <code>||</code> operator for error sets</p>
31133113 {#header_open|Inferred Error Sets#}
3114 <p>TODO</p>
3114 <p>
3115 Because many functions in Zig return a possible error, Zig supports inferring the error set.
3116 To infer the error set for a function, use this syntax:
3117 </p>
3118{#code_begin|test#}
3119// With an inferred error set
3120pub fn add_inferred(comptime T: type, a: T, b: T) !T {
3121 var answer: T = undefined;
3122 return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
3123}
3124
3125// With an explicit error set
3126pub fn add_explicit(comptime T: type, a: T, b: T) Error!T {
3127 var answer: T = undefined;
3128 return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer;
3129}
3130
3131const Error = error {
3132 Overflow,
3133};
3134
3135const std = @import("std");
3136
3137test "inferred error set" {
3138 if (add_inferred(u8, 255, 1)) |_| unreachable else |err| switch (err) {
3139 error.Overflow => {}, // ok
3140 }
3141}
3142{#code_end#}
3143 <p>
3144 When a function has an inferred error set, that function becomes generic and thus it becomes
3145 trickier to do certain things with it, such as obtain a function pointer, or have an error
3146 set that is consistent across different build targets. Additionally, inferred error sets
3147 are incompatible with recursion.
3148 </p>
3149 <p>
3150 In these situations, it is recommended to use an explicit error set. You can generally start
3151 with an empty error set and let compile errors guide you toward completing the set.
3152 </p>
3153 <p>
3154 These limitations may be overcome in a future version of Zig.
3155 </p>
31153156 {#header_close#}
31163157 {#header_close#}
31173158 {#header_open|Error Return Traces#}
......@@ -3872,13 +3913,22 @@ pub fn main() void {
38723913 {#header_open|@addWithOverflow#}
38733914 <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre>
38743915 <p>
3875 Performs <code>*result = a + b</code>. If overflow or underflow occurs,
3916 Performs <code>result.* = a + b</code>. If overflow or underflow occurs,
38763917 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
38773918 If no overflow or underflow occurs, returns <code>false</code>.
38783919 </p>
38793920 {#header_close#}
38803921 {#header_open|@ArgType#}
3881 <p>TODO</p>
3922 <pre><code class="zig">@ArgType(comptime T: type, comptime n: usize) -&gt; type</code></pre>
3923 <p>
3924 This builtin function takes a function type and returns the type of the parameter at index <code>n</code>.
3925 </p>
3926 <p>
3927 <code>T</code> must be a function type.
3928 </p>
3929 <p>
3930 Note: This function is deprecated. Use {#link|@typeInfo#} instead.
3931 </p>
38823932 {#header_close#}
38833933 {#header_open|@atomicLoad#}
38843934 <pre><code class="zig">@atomicLoad(comptime T: type, ptr: &amp;const T, comptime ordering: builtin.AtomicOrder) -&gt; T</code></pre>
......@@ -4073,9 +4123,9 @@ comptime {
40734123 </p>
40744124 {#code_begin|syntax#}
40754125fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T {
4076 const old_value = *ptr;
4126 const old_value = ptr.*;
40774127 if (old_value == expected_value) {
4078 *ptr = new_value;
4128 ptr.* = new_value;
40794129 return null;
40804130 } else {
40814131 return old_value;
......@@ -4100,9 +4150,9 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_v
41004150 </p>
41014151 {#code_begin|syntax#}
41024152fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T {
4103 const old_value = *ptr;
4153 const old_value = ptr.*;
41044154 if (old_value == expected_value and usuallyTrueButSometimesFalse()) {
4105 *ptr = new_value;
4155 ptr.* = new_value;
41064156 return null;
41074157 } else {
41084158 return old_value;
......@@ -4447,7 +4497,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
44474497 This function is a low level intrinsic with no safety mechanisms. Most
44484498 code should not use this function, instead using something like this:
44494499 </p>
4450 <pre><code class="zig">for (dest[0...byte_count]) |*b| *b = c;</code></pre>
4500 <pre><code class="zig">for (dest[0...byte_count]) |*b| b.* = c;</code></pre>
44514501 <p>
44524502 The optimizer is intelligent enough to turn the above snippet into a memset.
44534503 </p>
......@@ -4480,22 +4530,63 @@ mem.set(u8, dest, c);</code></pre>
44804530 {#header_open|@mulWithOverflow#}
44814531 <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre>
44824532 <p>
4483 Performs <code>*result = a * b</code>. If overflow or underflow occurs,
4533 Performs <code>result.* = a * b</code>. If overflow or underflow occurs,
44844534 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
44854535 If no overflow or underflow occurs, returns <code>false</code>.
44864536 </p>
44874537 {#header_close#}
4538 {#header_open|@newStackCall#}
4539 <pre><code class="zig">@newStackCall(new_stack: []u8, function: var, args: ...) -&gt; var</code></pre>
4540 <p>
4541 This calls a function, in the same way that invoking an expression with parentheses does. However,
4542 instead of using the same stack as the caller, the function uses the stack provided in the <code>new_stack</code>
4543 parameter.
4544 </p>
4545 {#code_begin|test#}
4546const std = @import("std");
4547const assert = std.debug.assert;
4548
4549var new_stack_bytes: [1024]u8 = undefined;
4550
4551test "calling a function with a new stack" {
4552 const arg = 1234;
4553
4554 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
4555 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
4556 _ = targetFunction(arg);
4557
4558 assert(arg == 1234);
4559 assert(a < b);
4560}
4561
4562fn targetFunction(x: i32) usize {
4563 assert(x == 1234);
4564
4565 var local_variable: i32 = 42;
4566 const ptr = &local_variable;
4567 ptr.* += 1;
4568
4569 assert(local_variable == 43);
4570 return @ptrToInt(ptr);
4571}
4572 {#code_end#}
4573 {#header_close#}
44884574 {#header_open|@noInlineCall#}
44894575 <pre><code class="zig">@noInlineCall(function: var, args: ...) -&gt; var</code></pre>
44904576 <p>
44914577 This calls a function, in the same way that invoking an expression with parentheses does:
44924578 </p>
4493 <pre><code class="zig">const assert = @import("std").debug.assert;
4579 {#code_begin|test#}
4580const assert = @import("std").debug.assert;
4581
44944582test "noinline function call" {
44954583 assert(@noInlineCall(add, 3, 9) == 12);
44964584}
44974585
4498fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre>
4586fn add(a: i32, b: i32) i32 {
4587 return a + b;
4588}
4589 {#code_end#}
44994590 <p>
45004591 Unlike a normal function call, however, <code>@noInlineCall</code> guarantees that the call
45014592 will not be inlined. If the call must be inlined, a compile error is emitted.
......@@ -4705,7 +4796,7 @@ pub const FloatMode = enum {
47054796 {#header_open|@shlWithOverflow#}
47064797 <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -&gt; bool</code></pre>
47074798 <p>
4708 Performs <code>*result = a &lt;&lt; b</code>. If overflow or underflow occurs,
4799 Performs <code>result.* = a &lt;&lt; b</code>. If overflow or underflow occurs,
47094800 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
47104801 If no overflow or underflow occurs, returns <code>false</code>.
47114802 </p>
......@@ -4749,7 +4840,7 @@ pub const FloatMode = enum {
47494840 {#header_open|@subWithOverflow#}
47504841 <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre>
47514842 <p>
4752 Performs <code>*result = a - b</code>. If overflow or underflow occurs,
4843 Performs <code>result.* = a - b</code>. If overflow or underflow occurs,
47534844 stores the overflowed bits in <code>result</code> and returns <code>true</code>.
47544845 If no overflow or underflow occurs, returns <code>false</code>.
47554846 </p>
......@@ -5867,7 +5958,7 @@ pub fn main() void {
58675958 {#code_begin|exe#}
58685959 {#link_libc#}
58695960const c = @cImport({
5870 // See https://github.com/zig-lang/zig/issues/515
5961 // See https://github.com/ziglang/zig/issues/515
58715962 @cDefine("_NO_CRT_STDIO_INLINE", "1");
58725963 @cInclude("stdio.h");
58735964});
......@@ -6210,7 +6301,7 @@ fn readU32Be() u32 {}
62106301 <li>Non-Ascii Unicode line endings: U+0085 (NEL), U+2028 (LS), U+2029 (PS).</li>
62116302 </ul>
62126303 <p>The codepoint U+000a (LF) (which is encoded as the single-byte value 0x0a) is the line terminator character. This character always terminates a line of zig source code (except possbly the last line of the file).</p>
6213 <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>
6304 <p>For some discussion on the rationale behind these design decisions, see <a href="https://github.com/ziglang/zig/issues/663">issue #663</a></p>
62146305 {#header_close#}
62156306 {#header_open|Grammar#}
62166307 <pre><code class="nohighlight">Root = many(TopLevelItem) EOF
......@@ -6341,10 +6432,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
63416432
63426433PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression
63436434
6344SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
6435SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression)
63456436
63466437FieldAccessExpression = "." Symbol
63476438
6439PtrDerefExpression = ".*"
6440
63486441FnCallExpression = "(" list(Expression, ",") ")"
63496442
63506443ArrayAccessExpression = "[" Expression "]"
......@@ -6357,7 +6450,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
63576450
63586451StructLiteralField = "." Symbol "=" Expression
63596452
6360PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
6453PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
63616454
63626455PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
63636456
......@@ -6451,7 +6544,7 @@ hljs.registerLanguage("zig", function(t) {
64516544 a = t.IR + "\\s*\\(",
64526545 c = {
64536546 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",
6454 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo",
6547 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo newStackCall",
64556548 literal: "true false null undefined"
64566549 },
64576550 n = [e, t.CLCM, t.CBCM, s, r];
example/hello_world/hello_libc.zig+1-1
......@@ -1,5 +1,5 @@
11const c = @cImport({
2 // See https://github.com/zig-lang/zig/issues/515
2 // See https://github.com/ziglang/zig/issues/515
33 @cDefine("_NO_CRT_STDIO_INLINE", "1");
44 @cInclude("stdio.h");
55 @cInclude("string.h");
src-self-hosted/arg.zig+41-33
......@@ -30,24 +30,22 @@ fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool {
3030}
3131
3232// Modifies the current argument index during iteration
33fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize,
34 allowed_set: ?[]const []const u8, index: &usize) !FlagArg {
35
33fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: &usize) !FlagArg {
3634 switch (required) {
37 0 => return FlagArg { .None = undefined }, // TODO: Required to force non-tag but value?
35 0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value?
3836 1 => {
39 if (*index + 1 >= args.len) {
37 if (index.* + 1 >= args.len) {
4038 return error.MissingFlagArguments;
4139 }
4240
43 *index += 1;
44 const arg = args[*index];
41 index.* += 1;
42 const arg = args[index.*];
4543
4644 if (!argInAllowedSet(allowed_set, arg)) {
4745 return error.ArgumentNotInAllowedSet;
4846 }
4947
50 return FlagArg { .Single = arg };
48 return FlagArg{ .Single = arg };
5149 },
5250 else => |needed| {
5351 var extra = ArrayList([]const u8).init(allocator);
......@@ -55,12 +53,12 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required:
5553
5654 var j: usize = 0;
5755 while (j < needed) : (j += 1) {
58 if (*index + 1 >= args.len) {
56 if (index.* + 1 >= args.len) {
5957 return error.MissingFlagArguments;
6058 }
6159
62 *index += 1;
63 const arg = args[*index];
60 index.* += 1;
61 const arg = args[index.*];
6462
6563 if (!argInAllowedSet(allowed_set, arg)) {
6664 return error.ArgumentNotInAllowedSet;
......@@ -69,7 +67,7 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required:
6967 try extra.append(arg);
7068 }
7169
72 return FlagArg { .Many = extra };
70 return FlagArg{ .Many = extra };
7371 },
7472 }
7573}
......@@ -82,7 +80,7 @@ pub const Args = struct {
8280 positionals: ArrayList([]const u8),
8381
8482 pub fn parse(allocator: &Allocator, comptime spec: []const Flag, args: []const []const u8) !Args {
85 var parsed = Args {
83 var parsed = Args{
8684 .flags = HashMapFlags.init(allocator),
8785 .positionals = ArrayList([]const u8).init(allocator),
8886 };
......@@ -116,11 +114,7 @@ pub const Args = struct {
116114 };
117115
118116 if (flag.mergable) {
119 var prev =
120 if (parsed.flags.get(flag_name_trimmed)) |entry|
121 entry.value.Many
122 else
123 ArrayList([]const u8).init(allocator);
117 var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator);
124118
125119 // MergeN creation disallows 0 length flag entry (doesn't make sense)
126120 switch (flag_args) {
......@@ -129,7 +123,7 @@ pub const Args = struct {
129123 FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()),
130124 }
131125
132 _ = try parsed.flags.put(flag_name_trimmed, FlagArg { .Many = prev });
126 _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
133127 } else {
134128 _ = try parsed.flags.put(flag_name_trimmed, flag_args);
135129 }
......@@ -163,7 +157,9 @@ pub const Args = struct {
163157 pub fn single(self: &Args, name: []const u8) ?[]const u8 {
164158 if (self.flags.get(name)) |entry| {
165159 switch (entry.value) {
166 FlagArg.Single => |inner| { return inner; },
160 FlagArg.Single => |inner| {
161 return inner;
162 },
167163 else => @panic("attempted to retrieve flag with wrong type"),
168164 }
169165 } else {
......@@ -175,7 +171,9 @@ pub const Args = struct {
175171 pub fn many(self: &Args, name: []const u8) ?[]const []const u8 {
176172 if (self.flags.get(name)) |entry| {
177173 switch (entry.value) {
178 FlagArg.Many => |inner| { return inner.toSliceConst(); },
174 FlagArg.Many => |inner| {
175 return inner.toSliceConst();
176 },
179177 else => @panic("attempted to retrieve flag with wrong type"),
180178 }
181179 } else {
......@@ -207,7 +205,7 @@ pub const Flag = struct {
207205 }
208206
209207 pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag {
210 return Flag {
208 return Flag{
211209 .name = name,
212210 .required = n,
213211 .mergable = false,
......@@ -220,7 +218,7 @@ pub const Flag = struct {
220218 @compileError("n must be greater than 0");
221219 }
222220
223 return Flag {
221 return Flag{
224222 .name = name,
225223 .required = n,
226224 .mergable = true,
......@@ -229,7 +227,7 @@ pub const Flag = struct {
229227 }
230228
231229 pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag {
232 return Flag {
230 return Flag{
233231 .name = name,
234232 .required = 1,
235233 .mergable = false,
......@@ -239,26 +237,36 @@ pub const Flag = struct {
239237};
240238
241239test "parse arguments" {
242 const spec1 = comptime []const Flag {
240 const spec1 = comptime []const Flag{
243241 Flag.Bool("--help"),
244242 Flag.Bool("--init"),
245243 Flag.Arg1("--build-file"),
246 Flag.Option("--color", []const []const u8 { "on", "off", "auto" }),
244 Flag.Option("--color", []const []const u8{
245 "on",
246 "off",
247 "auto",
248 }),
247249 Flag.ArgN("--pkg-begin", 2),
248250 Flag.ArgMergeN("--object", 1),
249251 Flag.ArgN("--library", 1),
250252 };
251253
252 const cliargs = []const []const u8 {
254 const cliargs = []const []const u8{
253255 "build",
254256 "--help",
255257 "pos1",
256 "--build-file", "build.zig",
257 "--object", "obj1",
258 "--object", "obj2",
259 "--library", "lib1",
260 "--library", "lib2",
261 "--color", "on",
258 "--build-file",
259 "build.zig",
260 "--object",
261 "obj1",
262 "--object",
263 "obj2",
264 "--library",
265 "lib1",
266 "--library",
267 "lib2",
268 "--color",
269 "on",
262270 "pos2",
263271 };
264272
src-self-hosted/main.zig-2
......@@ -637,14 +637,12 @@ const usage_fmt =
637637 \\
638638 \\Options:
639639 \\ --help Print this help and exit
640 \\ --keep-backups Retain backup entries for every file
641640 \\
642641 \\
643642 ;
644643
645644const args_fmt_spec = []Flag {
646645 Flag.Bool("--help"),
647 Flag.Bool("--keep-backups"),
648646};
649647
650648fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {
src-self-hosted/module.zig+9-9
......@@ -96,6 +96,7 @@ pub const Module = struct {
9696 pub const LinkLib = struct {
9797 name: []const u8,
9898 path: ?[]const u8,
99
99100 /// the list of symbols we depend on from this lib
100101 symbols: ArrayList([]u8),
101102 provided_explicitly: bool,
......@@ -130,9 +131,7 @@ pub const Module = struct {
130131 }
131132 };
132133
133 pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target,
134 kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) !&Module
135 {
134 pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target, kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) !&Module {
136135 var name_buffer = try Buffer.init(allocator, name);
137136 errdefer name_buffer.deinit();
138137
......@@ -148,14 +147,14 @@ pub const Module = struct {
148147 const module_ptr = try allocator.create(Module);
149148 errdefer allocator.destroy(module_ptr);
150149
151 *module_ptr = Module {
150 module_ptr.* = Module{
152151 .allocator = allocator,
153152 .name = name_buffer,
154153 .root_src_path = root_src_path,
155154 .module = module,
156155 .context = context,
157156 .builder = builder,
158 .target = *target,
157 .target = target.*,
159158 .kind = kind,
160159 .build_mode = build_mode,
161160 .zig_lib_dir = zig_lib_dir,
......@@ -221,8 +220,10 @@ pub const Module = struct {
221220
222221 pub fn build(self: &Module) !void {
223222 if (self.llvm_argv.len != 0) {
224 var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator,
225 [][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, });
223 var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator, [][]const []const u8{
224 [][]const u8{"zig (LLVM option parsing)"},
225 self.llvm_argv,
226 });
226227 defer c_compatible_args.deinit();
227228 c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
228229 }
......@@ -261,7 +262,6 @@ pub const Module = struct {
261262
262263 warn("====llvm ir:====\n");
263264 self.dump();
264
265265 }
266266
267267 pub fn link(self: &Module, out_file: ?[]const u8) !void {
......@@ -285,7 +285,7 @@ pub const Module = struct {
285285 }
286286
287287 const link_lib = try self.allocator.create(LinkLib);
288 *link_lib = LinkLib {
288 link_lib.* = LinkLib{
289289 .name = name,
290290 .path = null,
291291 .provided_explicitly = provided_explicitly,
src-self-hosted/target.zig+4-3
......@@ -12,7 +12,7 @@ pub const Target = union(enum) {
1212 Cross: CrossTarget,
1313
1414 pub fn oFileExt(self: &const Target) []const u8 {
15 const environ = switch (*self) {
15 const environ = switch (self.*) {
1616 Target.Native => builtin.environ,
1717 Target.Cross => |t| t.environ,
1818 };
......@@ -30,7 +30,7 @@ pub const Target = union(enum) {
3030 }
3131
3232 pub fn getOs(self: &const Target) builtin.Os {
33 return switch (*self) {
33 return switch (self.*) {
3434 Target.Native => builtin.os,
3535 Target.Cross => |t| t.os,
3636 };
......@@ -38,7 +38,8 @@ pub const Target = union(enum) {
3838
3939 pub fn isDarwin(self: &const Target) bool {
4040 return switch (self.getOs()) {
41 builtin.Os.ios, builtin.Os.macosx => true,
41 builtin.Os.ios,
42 builtin.Os.macosx => true,
4243 else => false,
4344 };
4445 }
src/all_types.hpp+13-1
......@@ -379,6 +379,7 @@ enum NodeType {
379379 NodeTypeArrayAccessExpr,
380380 NodeTypeSliceExpr,
381381 NodeTypeFieldAccessExpr,
382 NodeTypePtrDeref,
382383 NodeTypeUse,
383384 NodeTypeBoolLiteral,
384385 NodeTypeNullLiteral,
......@@ -603,13 +604,16 @@ struct AstNodeFieldAccessExpr {
603604 Buf *field_name;
604605};
605606
607struct AstNodePtrDerefExpr {
608 AstNode *target;
609};
610
606611enum PrefixOp {
607612 PrefixOpInvalid,
608613 PrefixOpBoolNot,
609614 PrefixOpBinNot,
610615 PrefixOpNegation,
611616 PrefixOpNegationWrap,
612 PrefixOpDereference,
613617 PrefixOpMaybe,
614618 PrefixOpUnwrapMaybe,
615619};
......@@ -911,6 +915,7 @@ struct AstNode {
911915 AstNodeCompTime comptime_expr;
912916 AstNodeAsmExpr asm_expr;
913917 AstNodeFieldAccessExpr field_access_expr;
918 AstNodePtrDerefExpr ptr_deref_expr;
914919 AstNodeContainerDecl container_decl;
915920 AstNodeStructField struct_field;
916921 AstNodeStringLiteral string_literal;
......@@ -1340,6 +1345,7 @@ enum BuiltinFnId {
13401345 BuiltinFnIdOffsetOf,
13411346 BuiltinFnIdInlineCall,
13421347 BuiltinFnIdNoInlineCall,
1348 BuiltinFnIdNewStackCall,
13431349 BuiltinFnIdTypeId,
13441350 BuiltinFnIdShlExact,
13451351 BuiltinFnIdShrExact,
......@@ -1654,8 +1660,13 @@ struct CodeGen {
16541660 LLVMValueRef coro_alloc_helper_fn_val;
16551661 LLVMValueRef merge_err_ret_traces_fn_val;
16561662 LLVMValueRef add_error_return_trace_addr_fn_val;
1663 LLVMValueRef stacksave_fn_val;
1664 LLVMValueRef stackrestore_fn_val;
1665 LLVMValueRef write_register_fn_val;
16571666 bool error_during_imports;
16581667
1668 LLVMValueRef sp_md_node;
1669
16591670 const char **clang_argv;
16601671 size_t clang_argv_len;
16611672 ZigList<const char *> lib_dirs;
......@@ -2278,6 +2289,7 @@ struct IrInstructionCall {
22782289 bool is_async;
22792290
22802291 IrInstruction *async_allocator;
2292 IrInstruction *new_stack;
22812293};
22822294
22832295struct IrInstructionConst {
src/analyze.cpp+3-2
......@@ -1007,7 +1007,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
10071007 if (fn_type_id->return_type != nullptr) {
10081008 ensure_complete_type(g, fn_type_id->return_type);
10091009 } else {
1010 zig_panic("TODO implement inferred return types https://github.com/zig-lang/zig/issues/447");
1010 zig_panic("TODO implement inferred return types https://github.com/ziglang/zig/issues/447");
10111011 }
10121012
10131013 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
......@@ -1556,7 +1556,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
15561556 return g->builtin_types.entry_invalid;
15571557 }
15581558 add_node_error(g, proto_node,
1559 buf_sprintf("TODO implement inferred return types https://github.com/zig-lang/zig/issues/447"));
1559 buf_sprintf("TODO implement inferred return types https://github.com/ziglang/zig/issues/447"));
15601560 return g->builtin_types.entry_invalid;
15611561 //return get_generic_fn_type(g, &fn_type_id);
15621562 }
......@@ -3281,6 +3281,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
32813281 case NodeTypeUnreachable:
32823282 case NodeTypeAsmExpr:
32833283 case NodeTypeFieldAccessExpr:
3284 case NodeTypePtrDeref:
32843285 case NodeTypeStructField:
32853286 case NodeTypeContainerInitExpr:
32863287 case NodeTypeStructValueField:
src/ast_render.cpp+9-1
......@@ -66,7 +66,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
6666 case PrefixOpNegationWrap: return "-%";
6767 case PrefixOpBoolNot: return "!";
6868 case PrefixOpBinNot: return "~";
69 case PrefixOpDereference: return "*";
7069 case PrefixOpMaybe: return "?";
7170 case PrefixOpUnwrapMaybe: return "??";
7271 }
......@@ -222,6 +221,8 @@ static const char *node_type_str(NodeType node_type) {
222221 return "AsmExpr";
223222 case NodeTypeFieldAccessExpr:
224223 return "FieldAccessExpr";
224 case NodeTypePtrDeref:
225 return "PtrDerefExpr";
225226 case NodeTypeContainerDecl:
226227 return "ContainerDecl";
227228 case NodeTypeStructField:
......@@ -696,6 +697,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
696697 print_symbol(ar, rhs);
697698 break;
698699 }
700 case NodeTypePtrDeref:
701 {
702 AstNode *lhs = node->data.ptr_deref_expr.target;
703 render_node_ungrouped(ar, lhs);
704 fprintf(ar->f, ".*");
705 break;
706 }
699707 case NodeTypeUndefinedLiteral:
700708 fprintf(ar->f, "undefined");
701709 break;
src/codegen.cpp+100-5
......@@ -586,7 +586,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
586586 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "nonnull");
587587 }
588588 // Note: byval is disabled on windows due to an LLVM bug:
589 // https://github.com/zig-lang/zig/issues/536
589 // https://github.com/ziglang/zig/issues/536
590590 if (is_byval && g->zig_target.os != OsWindows) {
591591 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)gen_index, "byval");
592592 }
......@@ -923,6 +923,53 @@ static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) {
923923 gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr);
924924}
925925
926static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
927 if (g->stacksave_fn_val)
928 return g->stacksave_fn_val;
929
930 // declare i8* @llvm.stacksave()
931
932 LLVMTypeRef fn_type = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), nullptr, 0, false);
933 g->stacksave_fn_val = LLVMAddFunction(g->module, "llvm.stacksave", fn_type);
934 assert(LLVMGetIntrinsicID(g->stacksave_fn_val));
935
936 return g->stacksave_fn_val;
937}
938
939static LLVMValueRef get_stackrestore_fn_val(CodeGen *g) {
940 if (g->stackrestore_fn_val)
941 return g->stackrestore_fn_val;
942
943 // declare void @llvm.stackrestore(i8* %ptr)
944
945 LLVMTypeRef param_type = LLVMPointerType(LLVMInt8Type(), 0);
946 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), &param_type, 1, false);
947 g->stackrestore_fn_val = LLVMAddFunction(g->module, "llvm.stackrestore", fn_type);
948 assert(LLVMGetIntrinsicID(g->stackrestore_fn_val));
949
950 return g->stackrestore_fn_val;
951}
952
953static LLVMValueRef get_write_register_fn_val(CodeGen *g) {
954 if (g->write_register_fn_val)
955 return g->write_register_fn_val;
956
957 // declare void @llvm.write_register.i64(metadata, i64 @value)
958 // !0 = !{!"sp\00"}
959
960 LLVMTypeRef param_types[] = {
961 LLVMMetadataTypeInContext(LLVMGetGlobalContext()),
962 LLVMIntType(g->pointer_size_bytes * 8),
963 };
964
965 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 2, false);
966 Buf *name = buf_sprintf("llvm.write_register.i%d", g->pointer_size_bytes * 8);
967 g->write_register_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
968 assert(LLVMGetIntrinsicID(g->write_register_fn_val));
969
970 return g->write_register_fn_val;
971}
972
926973static LLVMValueRef get_coro_destroy_fn_val(CodeGen *g) {
927974 if (g->coro_destroy_fn_val)
928975 return g->coro_destroy_fn_val;
......@@ -2840,6 +2887,38 @@ static size_t get_async_err_code_arg_index(CodeGen *g, FnTypeId *fn_type_id) {
28402887 return 1 + get_async_allocator_arg_index(g, fn_type_id);
28412888}
28422889
2890
2891static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) {
2892 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, "");
2893 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_len_index, "");
2894
2895 LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, "");
2896 LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, "");
2897
2898 LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), "");
2899 LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, "");
2900 LLVMValueRef align_amt = LLVMConstInt(LLVMTypeOf(end_addr), get_abi_alignment(g, g->builtin_types.entry_usize), false);
2901 LLVMValueRef align_adj = LLVMBuildURem(g->builder, end_addr, align_amt, "");
2902 return LLVMBuildNUWSub(g->builder, end_addr, align_adj, "");
2903}
2904
2905static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) {
2906 LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);
2907
2908 if (g->sp_md_node == nullptr) {
2909 Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target.arch));
2910 LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);
2911 g->sp_md_node = LLVMMDNode(&str_node, 1);
2912 }
2913
2914 LLVMValueRef params[] = {
2915 g->sp_md_node,
2916 aligned_end_addr,
2917 };
2918
2919 LLVMBuildCall(g->builder, write_register_fn_val, params, 2, "");
2920}
2921
28432922static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
28442923 LLVMValueRef fn_val;
28452924 TypeTableEntry *fn_type;
......@@ -2906,13 +2985,28 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
29062985 }
29072986
29082987 LLVMCallConv llvm_cc = get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc);
2909 LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
2910 gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, "");
2988 LLVMValueRef result;
2989
2990 if (instruction->new_stack == nullptr) {
2991 result = ZigLLVMBuildCall(g->builder, fn_val,
2992 gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, "");
2993 } else {
2994 LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g);
2995 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);
2996
2997 LLVMValueRef new_stack_addr = get_new_stack_addr(g, ir_llvm_value(g, instruction->new_stack));
2998 LLVMValueRef old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, "");
2999 gen_set_stack_pointer(g, new_stack_addr);
3000 result = ZigLLVMBuildCall(g->builder, fn_val,
3001 gen_param_values, (unsigned)gen_param_index, llvm_cc, fn_inline, "");
3002 LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, "");
3003 }
3004
29113005
29123006 for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
29133007 FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
29143008 // Note: byval is disabled on windows due to an LLVM bug:
2915 // https://github.com/zig-lang/zig/issues/536
3009 // https://github.com/ziglang/zig/issues/536
29163010 if (gen_info->is_byval && g->zig_target.os != OsWindows) {
29173011 addLLVMCallsiteAttr(result, (unsigned)gen_info->gen_index, "byval");
29183012 }
......@@ -6086,6 +6180,7 @@ static void define_builtin_fns(CodeGen *g) {
60866180 create_builtin_fn(g, BuiltinFnIdSqrt, "sqrt", 2);
60876181 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
60886182 create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
6183 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
60896184 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
60906185 create_builtin_fn(g, BuiltinFnIdShlExact, "shlExact", 2);
60916186 create_builtin_fn(g, BuiltinFnIdShrExact, "shrExact", 2);
......@@ -6550,7 +6645,7 @@ static void init(CodeGen *g) {
65506645 const char *target_specific_features;
65516646 if (g->is_native_target) {
65526647 // LLVM creates invalid binaries on Windows sometimes.
6553 // See https://github.com/zig-lang/zig/issues/508
6648 // See https://github.com/ziglang/zig/issues/508
65546649 // As a workaround we do not use target native features on Windows.
65556650 if (g->zig_target.os == OsWindows) {
65566651 target_specific_cpu_args = "";
src/ir.cpp+83-19
......@@ -1102,7 +1102,8 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio
11021102
11031103static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
11041104 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1105 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator)
1105 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
1106 IrInstruction *new_stack)
11061107{
11071108 IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node);
11081109 call_instruction->fn_entry = fn_entry;
......@@ -1113,6 +1114,7 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
11131114 call_instruction->arg_count = arg_count;
11141115 call_instruction->is_async = is_async;
11151116 call_instruction->async_allocator = async_allocator;
1117 call_instruction->new_stack = new_stack;
11161118
11171119 if (fn_ref)
11181120 ir_ref_instruction(fn_ref, irb->current_basic_block);
......@@ -1120,16 +1122,19 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
11201122 ir_ref_instruction(args[i], irb->current_basic_block);
11211123 if (async_allocator)
11221124 ir_ref_instruction(async_allocator, irb->current_basic_block);
1125 if (new_stack != nullptr)
1126 ir_ref_instruction(new_stack, irb->current_basic_block);
11231127
11241128 return &call_instruction->base;
11251129}
11261130
11271131static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction,
11281132 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1129 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator)
1133 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator,
1134 IrInstruction *new_stack)
11301135{
11311136 IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope,
1132 old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator);
1137 old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator, new_stack);
11331138 ir_link_new_instruction(new_instruction, old_instruction);
11341139 return new_instruction;
11351140}
......@@ -4303,7 +4308,37 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
43034308 }
43044309 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
43054310
4306 IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr);
4311 IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr, nullptr);
4312 return ir_lval_wrap(irb, scope, call, lval);
4313 }
4314 case BuiltinFnIdNewStackCall:
4315 {
4316 if (node->data.fn_call_expr.params.length == 0) {
4317 add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0"));
4318 return irb->codegen->invalid_instruction;
4319 }
4320
4321 AstNode *new_stack_node = node->data.fn_call_expr.params.at(0);
4322 IrInstruction *new_stack = ir_gen_node(irb, new_stack_node, scope);
4323 if (new_stack == irb->codegen->invalid_instruction)
4324 return new_stack;
4325
4326 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1);
4327 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
4328 if (fn_ref == irb->codegen->invalid_instruction)
4329 return fn_ref;
4330
4331 size_t arg_count = node->data.fn_call_expr.params.length - 2;
4332
4333 IrInstruction **args = allocate<IrInstruction*>(arg_count);
4334 for (size_t i = 0; i < arg_count; i += 1) {
4335 AstNode *arg_node = node->data.fn_call_expr.params.at(i + 2);
4336 args[i] = ir_gen_node(irb, arg_node, scope);
4337 if (args[i] == irb->codegen->invalid_instruction)
4338 return args[i];
4339 }
4340
4341 IrInstruction *call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, false, nullptr, new_stack);
43074342 return ir_lval_wrap(irb, scope, call, lval);
43084343 }
43094344 case BuiltinFnIdTypeId:
......@@ -4513,7 +4548,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
45134548 }
45144549 }
45154550
4516 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator);
4551 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr);
45174552 return ir_lval_wrap(irb, scope, fn_call, lval);
45184553}
45194554
......@@ -4574,8 +4609,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
45744609}
45754610
45764611static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) {
4577 assert(node->type == NodeTypePrefixOpExpr);
4578 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
4612 AstNode *expr_node;
4613 if (node->type == NodeTypePrefixOpExpr) {
4614 expr_node = node->data.prefix_op_expr.primary_expr;
4615 } else if (node->type == NodeTypePtrDeref) {
4616 expr_node = node->data.ptr_deref_expr.target;
4617 } else {
4618 zig_unreachable();
4619 }
45794620
45804621 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval);
45814622 if (value == irb->codegen->invalid_instruction)
......@@ -4716,8 +4757,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
47164757 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
47174758 case PrefixOpNegationWrap:
47184759 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
4719 case PrefixOpDereference:
4720 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
47214760 case PrefixOpMaybe:
47224761 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
47234762 case PrefixOpUnwrapMaybe:
......@@ -6553,6 +6592,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
65536592
65546593 return ir_build_load_ptr(irb, scope, node, ptr_instruction);
65556594 }
6595 case NodeTypePtrDeref:
6596 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
65566597 case NodeTypeThisLiteral:
65576598 return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval);
65586599 case NodeTypeBoolLiteral:
......@@ -6825,7 +6866,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
68256866 IrInstruction **args = allocate<IrInstruction *>(arg_count);
68266867 args[0] = implicit_allocator_ptr; // self
68276868 args[1] = mem_slice; // old_mem
6828 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
6869 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr, nullptr);
68296870
68306871 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
68316872 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
......@@ -8686,6 +8727,10 @@ static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_
86868727 *dest = *src;
86878728 if (!same_global_refs) {
86888729 dest->global_refs = global_refs;
8730 if (dest->type->id == TypeTableEntryIdStruct) {
8731 dest->data.x_struct.fields = allocate_nonzero<ConstExprValue>(dest->type->data.structure.src_field_count);
8732 memcpy(dest->data.x_struct.fields, src->data.x_struct.fields, sizeof(ConstExprValue) * dest->type->data.structure.src_field_count);
8733 }
86898734 }
86908735}
86918736
......@@ -11670,7 +11715,8 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
1167011715 if (var->mem_slot_index != SIZE_MAX) {
1167111716 assert(var->mem_slot_index < ira->exec_context.mem_slot_count);
1167211717 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
11673 *mem_slot = casted_init_value->value;
11718 copy_const_val(mem_slot, &casted_init_value->value,
11719 !is_comptime_var || var->gen_is_const);
1167411720
1167511721 if (is_comptime_var || (var_class_requires_const && var->gen_is_const)) {
1167611722 ir_build_const_from(ira, &decl_var_instruction->base);
......@@ -11987,7 +12033,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *c
1198712033 TypeTableEntry *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
1198812034
1198912035 IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,
11990 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst);
12036 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst, nullptr);
1199112037 result->value.type = async_return_type;
1199212038 return result;
1199312039}
......@@ -12084,7 +12130,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
1208412130 casted_arg->value.type->id == TypeTableEntryIdNumLitFloat)
1208512131 {
1208612132 ir_add_error(ira, casted_arg,
12087 buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/zig-lang/zig/issues/557"));
12133 buf_sprintf("compiler bug: integer and float literals in var args function must be casted. https://github.com/ziglang/zig/issues/557"));
1208812134 return false;
1208912135 }
1209012136
......@@ -12285,7 +12331,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1228512331
1228612332 if (fn_proto_node->data.fn_proto.is_var_args) {
1228712333 ir_add_error(ira, &call_instruction->base,
12288 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/zig-lang/zig/issues/313"));
12334 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));
1228912335 return ira->codegen->builtin_types.entry_invalid;
1229012336 }
1229112337
......@@ -12357,6 +12403,19 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1235712403 return ir_finish_anal(ira, return_type);
1235812404 }
1235912405
12406 IrInstruction *casted_new_stack = nullptr;
12407 if (call_instruction->new_stack != nullptr) {
12408 TypeTableEntry *u8_ptr = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
12409 TypeTableEntry *u8_slice = get_slice_type(ira->codegen, u8_ptr);
12410 IrInstruction *new_stack = call_instruction->new_stack->other;
12411 if (type_is_invalid(new_stack->value.type))
12412 return ira->codegen->builtin_types.entry_invalid;
12413
12414 casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
12415 if (type_is_invalid(casted_new_stack->value.type))
12416 return ira->codegen->builtin_types.entry_invalid;
12417 }
12418
1236012419 if (fn_type->data.fn.is_generic) {
1236112420 if (!fn_entry) {
1236212421 ir_add_error(ira, call_instruction->fn_ref,
......@@ -12365,7 +12424,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1236512424 }
1236612425 if (call_instruction->is_async && fn_type_id->is_var_args) {
1236712426 ir_add_error(ira, call_instruction->fn_ref,
12368 buf_sprintf("compiler bug: TODO: implement var args async functions. https://github.com/zig-lang/zig/issues/557"));
12427 buf_sprintf("compiler bug: TODO: implement var args async functions. https://github.com/ziglang/zig/issues/557"));
1236912428 return ira->codegen->builtin_types.entry_invalid;
1237012429 }
1237112430
......@@ -12448,7 +12507,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1244812507 VariableTableEntry *arg_var = get_fn_var_by_index(parent_fn_entry, arg_tuple_i);
1244912508 if (arg_var == nullptr) {
1245012509 ir_add_error(ira, arg,
12451 buf_sprintf("compiler bug: var args can't handle void. https://github.com/zig-lang/zig/issues/557"));
12510 buf_sprintf("compiler bug: var args can't handle void. https://github.com/ziglang/zig/issues/557"));
1245212511 return ira->codegen->builtin_types.entry_invalid;
1245312512 }
1245412513 IrInstruction *arg_var_ptr_inst = ir_get_var_ptr(ira, arg, arg_var, true, false);
......@@ -12583,7 +12642,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1258312642 assert(async_allocator_inst == nullptr);
1258412643 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
1258512644 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
12586 call_instruction->is_async, nullptr);
12645 call_instruction->is_async, nullptr, casted_new_stack);
1258712646
1258812647 ir_add_alloca(ira, new_call_instruction, return_type);
1258912648
......@@ -12674,7 +12733,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1267412733
1267512734
1267612735 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
12677 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr);
12736 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr, casted_new_stack);
1267812737
1267912738 ir_add_alloca(ira, new_call_instruction, return_type);
1268012739 return ir_finish_anal(ira, return_type);
......@@ -16496,6 +16555,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
1649616555 {
1649716556 size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index);
1649816557 inner_fields[1].data.x_maybe = create_const_vals(1);
16558 inner_fields[1].data.x_maybe->special = ConstValSpecialStatic;
1649916559 inner_fields[1].data.x_maybe->type = ira->codegen->builtin_types.entry_usize;
1650016560 bigint_init_unsigned(&inner_fields[1].data.x_maybe->data.x_bigint, byte_offset);
1650116561 }
......@@ -18030,7 +18090,11 @@ static TypeTableEntry *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira
1803018090 if (type_is_invalid(end_value->value.type))
1803118091 return ira->codegen->builtin_types.entry_invalid;
1803218092
18033 assert(start_value->value.type->id == TypeTableEntryIdEnum);
18093 if (start_value->value.type->id != TypeTableEntryIdEnum) {
18094 ir_add_error(ira, range->start, buf_sprintf("not an enum type"));
18095 return ira->codegen->builtin_types.entry_invalid;
18096 }
18097
1803418098 BigInt start_index;
1803518099 bigint_init_bigint(&start_index, &start_value->value.data.x_enum_tag);
1803618100
src/parser.cpp+25-18
......@@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index
10461046}
10471047
10481048/*
1049SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
1049SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression)
10501050FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
10511051ArrayAccessExpression : token(LBracket) Expression token(RBracket)
10521052SliceExpression = "[" Expression ".." option(Expression) "]"
10531053FieldAccessExpression : token(Dot) token(Symbol)
1054PtrDerefExpression = ".*"
10541055StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
10551056*/
10561057static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
......@@ -1131,13 +1132,27 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index,
11311132 } else if (first_token->id == TokenIdDot) {
11321133 *token_index += 1;
11331134
1134 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1135 Token *token = &pc->tokens->at(*token_index);
1136
1137 if (token->id == TokenIdSymbol) {
1138 *token_index += 1;
11351139
1136 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
1137 node->data.field_access_expr.struct_expr = primary_expr;
1138 node->data.field_access_expr.field_name = token_buf(name_token);
1140 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
1141 node->data.field_access_expr.struct_expr = primary_expr;
1142 node->data.field_access_expr.field_name = token_buf(token);
1143
1144 primary_expr = node;
1145 } else if (token->id == TokenIdStar) {
1146 *token_index += 1;
1147
1148 AstNode *node = ast_create_node(pc, NodeTypePtrDeref, first_token);
1149 node->data.ptr_deref_expr.target = primary_expr;
1150
1151 primary_expr = node;
1152 } else {
1153 ast_invalid_token_error(pc, token);
1154 }
11391155
1140 primary_expr = node;
11411156 } else {
11421157 return primary_expr;
11431158 }
......@@ -1150,10 +1165,8 @@ static PrefixOp tok_to_prefix_op(Token *token) {
11501165 case TokenIdDash: return PrefixOpNegation;
11511166 case TokenIdMinusPercent: return PrefixOpNegationWrap;
11521167 case TokenIdTilde: return PrefixOpBinNot;
1153 case TokenIdStar: return PrefixOpDereference;
11541168 case TokenIdMaybe: return PrefixOpMaybe;
11551169 case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
1156 case TokenIdStarStar: return PrefixOpDereference;
11571170 default: return PrefixOpInvalid;
11581171 }
11591172}
......@@ -1199,7 +1212,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
11991212
12001213/*
12011214PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression
1202PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
1215PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
12031216*/
12041217static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
12051218 Token *token = &pc->tokens->at(*token_index);
......@@ -1222,15 +1235,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
12221235
12231236 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
12241237 AstNode *parent_node = node;
1225 if (token->id == TokenIdStarStar) {
1226 // pretend that we got 2 star tokens
1227
1228 parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
1229 parent_node->data.prefix_op_expr.primary_expr = node;
1230 parent_node->data.prefix_op_expr.prefix_op = PrefixOpDereference;
1231
1232 node->column += 1;
1233 }
12341238
12351239 AstNode *prefix_op_expr = ast_parse_error_set_expr(pc, token_index, true);
12361240 node->data.prefix_op_expr.primary_expr = prefix_op_expr;
......@@ -3012,6 +3016,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30123016 case NodeTypeFieldAccessExpr:
30133017 visit_field(&node->data.field_access_expr.struct_expr, visit, context);
30143018 break;
3019 case NodeTypePtrDeref:
3020 visit_field(&node->data.ptr_deref_expr.target, visit, context);
3021 break;
30153022 case NodeTypeUse:
30163023 visit_field(&node->data.use.expr, visit, context);
30173024 break;
src/target.cpp+63-1
......@@ -701,6 +701,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
701701 case OsLinux:
702702 case OsMacOSX:
703703 case OsZen:
704 case OsOpenBSD:
704705 switch (id) {
705706 case CIntTypeShort:
706707 case CIntTypeUShort:
......@@ -741,7 +742,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
741742 case OsKFreeBSD:
742743 case OsLv2:
743744 case OsNetBSD:
744 case OsOpenBSD:
745745 case OsSolaris:
746746 case OsHaiku:
747747 case OsMinix:
......@@ -895,3 +895,65 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
895895
896896 return false;
897897}
898
899const char *arch_stack_pointer_register_name(const ArchType *arch) {
900 switch (arch->arch) {
901 case ZigLLVM_UnknownArch:
902 zig_unreachable();
903 case ZigLLVM_x86:
904 return "sp";
905 case ZigLLVM_x86_64:
906 return "rsp";
907
908 case ZigLLVM_aarch64:
909 case ZigLLVM_arm:
910 case ZigLLVM_thumb:
911 case ZigLLVM_aarch64_be:
912 case ZigLLVM_amdgcn:
913 case ZigLLVM_amdil:
914 case ZigLLVM_amdil64:
915 case ZigLLVM_armeb:
916 case ZigLLVM_arc:
917 case ZigLLVM_avr:
918 case ZigLLVM_bpfeb:
919 case ZigLLVM_bpfel:
920 case ZigLLVM_hexagon:
921 case ZigLLVM_lanai:
922 case ZigLLVM_hsail:
923 case ZigLLVM_hsail64:
924 case ZigLLVM_kalimba:
925 case ZigLLVM_le32:
926 case ZigLLVM_le64:
927 case ZigLLVM_mips:
928 case ZigLLVM_mips64:
929 case ZigLLVM_mips64el:
930 case ZigLLVM_mipsel:
931 case ZigLLVM_msp430:
932 case ZigLLVM_nios2:
933 case ZigLLVM_nvptx:
934 case ZigLLVM_nvptx64:
935 case ZigLLVM_ppc64le:
936 case ZigLLVM_r600:
937 case ZigLLVM_renderscript32:
938 case ZigLLVM_renderscript64:
939 case ZigLLVM_riscv32:
940 case ZigLLVM_riscv64:
941 case ZigLLVM_shave:
942 case ZigLLVM_sparc:
943 case ZigLLVM_sparcel:
944 case ZigLLVM_sparcv9:
945 case ZigLLVM_spir:
946 case ZigLLVM_spir64:
947 case ZigLLVM_systemz:
948 case ZigLLVM_tce:
949 case ZigLLVM_tcele:
950 case ZigLLVM_thumbeb:
951 case ZigLLVM_wasm32:
952 case ZigLLVM_wasm64:
953 case ZigLLVM_xcore:
954 case ZigLLVM_ppc:
955 case ZigLLVM_ppc64:
956 zig_panic("TODO populate this table with stack pointer register name for this CPU architecture");
957 }
958 zig_unreachable();
959}
src/target.hpp+2
......@@ -78,6 +78,8 @@ size_t target_arch_count(void);
7878const ArchType *get_target_arch(size_t index);
7979void get_arch_name(char *out_str, const ArchType *arch);
8080
81const char *arch_stack_pointer_register_name(const ArchType *arch);
82
8183size_t target_vendor_count(void);
8284ZigLLVM_VendorType get_target_vendor(size_t index);
8385
src/translate_c.cpp+53-30
......@@ -247,6 +247,12 @@ static AstNode *trans_create_node_field_access_str(Context *c, AstNode *containe
247247 return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
248248}
249249
250static AstNode *trans_create_node_ptr_deref(Context *c, AstNode *child_node) {
251 AstNode *node = trans_create_node(c, NodeTypePtrDeref);
252 node->data.ptr_deref_expr.target = child_node;
253 return node;
254}
255
250256static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
251257 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
252258 node->data.prefix_op_expr.prefix_op = op;
......@@ -1413,8 +1419,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
14131419 AstNode *operation_type_cast = trans_c_cast(c, rhs_location,
14141420 stmt->getComputationLHSType(),
14151421 stmt->getLHS()->getType(),
1416 trans_create_node_prefix_op(c, PrefixOpDereference,
1417 trans_create_node_symbol(c, tmp_var_name)));
1422 trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)));
14181423
14191424 // result_type(... >> u5(rhs))
14201425 AstNode *result_type_cast = trans_c_cast(c, rhs_location,
......@@ -1427,7 +1432,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
14271432
14281433 // *_ref = ...
14291434 AstNode *assign_statement = trans_create_node_bin_op(c,
1430 trans_create_node_prefix_op(c, PrefixOpDereference,
1435 trans_create_node_ptr_deref(c,
14311436 trans_create_node_symbol(c, tmp_var_name)),
14321437 BinOpTypeAssign, result_type_cast);
14331438
......@@ -1437,7 +1442,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
14371442 // break :x *_ref
14381443 child_scope->node->data.block.statements.append(
14391444 trans_create_node_break(c, label_name,
1440 trans_create_node_prefix_op(c, PrefixOpDereference,
1445 trans_create_node_ptr_deref(c,
14411446 trans_create_node_symbol(c, tmp_var_name))));
14421447 }
14431448
......@@ -1484,11 +1489,11 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
14841489 if (rhs == nullptr) return nullptr;
14851490
14861491 AstNode *assign_statement = trans_create_node_bin_op(c,
1487 trans_create_node_prefix_op(c, PrefixOpDereference,
1492 trans_create_node_ptr_deref(c,
14881493 trans_create_node_symbol(c, tmp_var_name)),
14891494 BinOpTypeAssign,
14901495 trans_create_node_bin_op(c,
1491 trans_create_node_prefix_op(c, PrefixOpDereference,
1496 trans_create_node_ptr_deref(c,
14921497 trans_create_node_symbol(c, tmp_var_name)),
14931498 bin_op,
14941499 rhs));
......@@ -1497,7 +1502,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
14971502 // break :x *_ref
14981503 child_scope->node->data.block.statements.append(
14991504 trans_create_node_break(c, label_name,
1500 trans_create_node_prefix_op(c, PrefixOpDereference,
1505 trans_create_node_ptr_deref(c,
15011506 trans_create_node_symbol(c, tmp_var_name))));
15021507
15031508 return child_scope->node;
......@@ -1818,13 +1823,13 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
18181823 // const _tmp = *_ref;
18191824 Buf* tmp_var_name = buf_create_from_str("_tmp");
18201825 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr,
1821 trans_create_node_prefix_op(c, PrefixOpDereference,
1826 trans_create_node_ptr_deref(c,
18221827 trans_create_node_symbol(c, ref_var_name)));
18231828 child_scope->node->data.block.statements.append(tmp_var_decl);
18241829
18251830 // *_ref += 1;
18261831 AstNode *assign_statement = trans_create_node_bin_op(c,
1827 trans_create_node_prefix_op(c, PrefixOpDereference,
1832 trans_create_node_ptr_deref(c,
18281833 trans_create_node_symbol(c, ref_var_name)),
18291834 assign_op,
18301835 trans_create_node_unsigned(c, 1));
......@@ -1872,14 +1877,14 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
18721877
18731878 // *_ref += 1;
18741879 AstNode *assign_statement = trans_create_node_bin_op(c,
1875 trans_create_node_prefix_op(c, PrefixOpDereference,
1880 trans_create_node_ptr_deref(c,
18761881 trans_create_node_symbol(c, ref_var_name)),
18771882 assign_op,
18781883 trans_create_node_unsigned(c, 1));
18791884 child_scope->node->data.block.statements.append(assign_statement);
18801885
18811886 // break :x *_ref
1882 AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference,
1887 AstNode *deref_expr = trans_create_node_ptr_deref(c,
18831888 trans_create_node_symbol(c, ref_var_name));
18841889 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, deref_expr));
18851890
......@@ -1924,7 +1929,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
19241929 if (is_fn_ptr)
19251930 return value_node;
19261931 AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
1927 return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped);
1932 return trans_create_node_ptr_deref(c, unwrapped);
19281933 }
19291934 case UO_Plus:
19301935 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");
......@@ -4445,27 +4450,45 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
44454450 }
44464451}
44474452
4448static PrefixOp ctok_to_prefix_op(CTok *token) {
4449 switch (token->id) {
4450 case CTokIdBang: return PrefixOpBoolNot;
4451 case CTokIdMinus: return PrefixOpNegation;
4452 case CTokIdTilde: return PrefixOpBinNot;
4453 case CTokIdAsterisk: return PrefixOpDereference;
4454 default: return PrefixOpInvalid;
4455 }
4456}
44574453static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
44584454 CTok *op_tok = &ctok->tokens.at(*tok_i);
4459 PrefixOp prefix_op = ctok_to_prefix_op(op_tok);
4460 if (prefix_op == PrefixOpInvalid) {
4461 return parse_ctok_suffix_op_expr(c, ctok, tok_i);
4462 }
4463 *tok_i += 1;
44644455
4465 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
4466 if (prefix_op_expr == nullptr)
4467 return nullptr;
4468 return trans_create_node_prefix_op(c, prefix_op, prefix_op_expr);
4456 switch (op_tok->id) {
4457 case CTokIdBang:
4458 {
4459 *tok_i += 1;
4460 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
4461 if (prefix_op_expr == nullptr)
4462 return nullptr;
4463 return trans_create_node_prefix_op(c, PrefixOpBoolNot, prefix_op_expr);
4464 }
4465 case CTokIdMinus:
4466 {
4467 *tok_i += 1;
4468 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
4469 if (prefix_op_expr == nullptr)
4470 return nullptr;
4471 return trans_create_node_prefix_op(c, PrefixOpNegation, prefix_op_expr);
4472 }
4473 case CTokIdTilde:
4474 {
4475 *tok_i += 1;
4476 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
4477 if (prefix_op_expr == nullptr)
4478 return nullptr;
4479 return trans_create_node_prefix_op(c, PrefixOpBinNot, prefix_op_expr);
4480 }
4481 case CTokIdAsterisk:
4482 {
4483 *tok_i += 1;
4484 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
4485 if (prefix_op_expr == nullptr)
4486 return nullptr;
4487 return trans_create_node_ptr_deref(c, prefix_op_expr);
4488 }
4489 default:
4490 return parse_ctok_suffix_op_expr(c, ctok, tok_i);
4491 }
44694492}
44704493
44714494static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
std/array_list.zig+33-21
......@@ -8,7 +8,7 @@ pub fn ArrayList(comptime T: type) type {
88 return AlignedArrayList(T, @alignOf(T));
99}
1010
11pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
11pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
1212 return struct {
1313 const Self = this;
1414
......@@ -21,7 +21,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
2121
2222 /// Deinitialize with `deinit` or use `toOwnedSlice`.
2323 pub fn init(allocator: &Allocator) Self {
24 return Self {
24 return Self{
2525 .items = []align(A) T{},
2626 .len = 0,
2727 .allocator = allocator,
......@@ -52,7 +52,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
5252 /// allocated with `allocator`.
5353 /// Deinitialize with `deinit` or use `toOwnedSlice`.
5454 pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) Self {
55 return Self {
55 return Self{
5656 .items = slice,
5757 .len = slice.len,
5858 .allocator = allocator,
......@@ -63,7 +63,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
6363 pub fn toOwnedSlice(self: &Self) []align(A) T {
6464 const allocator = self.allocator;
6565 const result = allocator.alignedShrink(T, A, self.items, self.len);
66 *self = init(allocator);
66 self.* = init(allocator);
6767 return result;
6868 }
6969
......@@ -71,21 +71,21 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
7171 try l.ensureCapacity(l.len + 1);
7272 l.len += 1;
7373
74 mem.copy(T, l.items[n+1..l.len], l.items[n..l.len-1]);
75 l.items[n] = *item;
74 mem.copy(T, l.items[n + 1..l.len], l.items[n..l.len - 1]);
75 l.items[n] = item.*;
7676 }
7777
7878 pub fn insertSlice(l: &Self, n: usize, items: []align(A) const T) !void {
7979 try l.ensureCapacity(l.len + items.len);
8080 l.len += items.len;
8181
82 mem.copy(T, l.items[n+items.len..l.len], l.items[n..l.len-items.len]);
83 mem.copy(T, l.items[n..n+items.len], items);
82 mem.copy(T, l.items[n + items.len..l.len], l.items[n..l.len - items.len]);
83 mem.copy(T, l.items[n..n + items.len], items);
8484 }
8585
8686 pub fn append(l: &Self, item: &const T) !void {
8787 const new_item_ptr = try l.addOne();
88 *new_item_ptr = *item;
88 new_item_ptr.* = item.*;
8989 }
9090
9191 pub fn appendSlice(l: &Self, items: []align(A) const T) !void {
......@@ -128,8 +128,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{
128128 }
129129
130130 pub fn popOrNull(self: &Self) ?T {
131 if (self.len == 0)
132 return null;
131 if (self.len == 0) return null;
133132 return self.pop();
134133 }
135134
......@@ -160,13 +159,19 @@ test "basic ArrayList test" {
160159 var list = ArrayList(i32).init(debug.global_allocator);
161160 defer list.deinit();
162161
163 {var i: usize = 0; while (i < 10) : (i += 1) {
164 list.append(i32(i + 1)) catch unreachable;
165 }}
162 {
163 var i: usize = 0;
164 while (i < 10) : (i += 1) {
165 list.append(i32(i + 1)) catch unreachable;
166 }
167 }
166168
167 {var i: usize = 0; while (i < 10) : (i += 1) {
168 assert(list.items[i] == i32(i + 1));
169 }}
169 {
170 var i: usize = 0;
171 while (i < 10) : (i += 1) {
172 assert(list.items[i] == i32(i + 1));
173 }
174 }
170175
171176 for (list.toSlice()) |v, i| {
172177 assert(v == i32(i + 1));
......@@ -179,14 +184,18 @@ test "basic ArrayList test" {
179184 assert(list.pop() == 10);
180185 assert(list.len == 9);
181186
182 list.appendSlice([]const i32 { 1, 2, 3 }) catch unreachable;
187 list.appendSlice([]const i32{
188 1,
189 2,
190 3,
191 }) catch unreachable;
183192 assert(list.len == 12);
184193 assert(list.pop() == 3);
185194 assert(list.pop() == 2);
186195 assert(list.pop() == 1);
187196 assert(list.len == 9);
188197
189 list.appendSlice([]const i32 {}) catch unreachable;
198 list.appendSlice([]const i32{}) catch unreachable;
190199 assert(list.len == 9);
191200}
192201
......@@ -228,12 +237,15 @@ test "insert ArrayList test" {
228237 assert(list.items[0] == 5);
229238 assert(list.items[1] == 1);
230239
231 try list.insertSlice(1, []const i32 { 9, 8 });
240 try list.insertSlice(1, []const i32{
241 9,
242 8,
243 });
232244 assert(list.items[0] == 5);
233245 assert(list.items[1] == 9);
234246 assert(list.items[2] == 8);
235247
236 const items = []const i32 { 1 };
248 const items = []const i32{1};
237249 try list.insertSlice(0, items[0..0]);
238250 assert(list.items[0] == 5);
239251}
std/atomic/queue.zig+8-6
......@@ -16,7 +16,7 @@ pub fn Queue(comptime T: type) type {
1616 data: T,
1717 };
1818
19 // TODO: well defined copy elision: https://github.com/zig-lang/zig/issues/287
19 // TODO: well defined copy elision: https://github.com/ziglang/zig/issues/287
2020 pub fn init(self: &Self) void {
2121 self.root.next = null;
2222 self.head = &self.root;
......@@ -70,7 +70,7 @@ test "std.atomic.queue" {
7070
7171 var queue: Queue(i32) = undefined;
7272 queue.init();
73 var context = Context {
73 var context = Context{
7474 .allocator = a,
7575 .queue = &queue,
7676 .put_sum = 0,
......@@ -81,16 +81,18 @@ test "std.atomic.queue" {
8181
8282 var putters: [put_thread_count]&std.os.Thread = undefined;
8383 for (putters) |*t| {
84 *t = try std.os.spawnThread(&context, startPuts);
84 t.* = try std.os.spawnThread(&context, startPuts);
8585 }
8686 var getters: [put_thread_count]&std.os.Thread = undefined;
8787 for (getters) |*t| {
88 *t = try std.os.spawnThread(&context, startGets);
88 t.* = try std.os.spawnThread(&context, startGets);
8989 }
9090
91 for (putters) |t| t.wait();
91 for (putters) |t|
92 t.wait();
9293 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
93 for (getters) |t| t.wait();
94 for (getters) |t|
95 t.wait();
9496
9597 std.debug.assert(context.put_sum == context.get_sum);
9698 std.debug.assert(context.get_count == puts_per_thread * put_thread_count);
std/atomic/stack.zig+8-8
......@@ -14,9 +14,7 @@ pub fn Stack(comptime T: type) type {
1414 };
1515
1616 pub fn init() Self {
17 return Self {
18 .root = null,
19 };
17 return Self{ .root = null };
2018 }
2119
2220 /// push operation, but only if you are the first item in the stack. if you did not succeed in
......@@ -75,7 +73,7 @@ test "std.atomic.stack" {
7573 var a = &fixed_buffer_allocator.allocator;
7674
7775 var stack = Stack(i32).init();
78 var context = Context {
76 var context = Context{
7977 .allocator = a,
8078 .stack = &stack,
8179 .put_sum = 0,
......@@ -86,16 +84,18 @@ test "std.atomic.stack" {
8684
8785 var putters: [put_thread_count]&std.os.Thread = undefined;
8886 for (putters) |*t| {
89 *t = try std.os.spawnThread(&context, startPuts);
87 t.* = try std.os.spawnThread(&context, startPuts);
9088 }
9189 var getters: [put_thread_count]&std.os.Thread = undefined;
9290 for (getters) |*t| {
93 *t = try std.os.spawnThread(&context, startGets);
91 t.* = try std.os.spawnThread(&context, startGets);
9492 }
9593
96 for (putters) |t| t.wait();
94 for (putters) |t|
95 t.wait();
9796 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
98 for (getters) |t| t.wait();
97 for (getters) |t|
98 t.wait();
9999
100100 std.debug.assert(context.put_sum == context.get_sum);
101101 std.debug.assert(context.get_count == puts_per_thread * put_thread_count);
std/buffer.zig+7-28
......@@ -31,9 +31,7 @@ pub const Buffer = struct {
3131 /// * ::replaceContentsBuffer
3232 /// * ::resize
3333 pub fn initNull(allocator: &Allocator) Buffer {
34 return Buffer {
35 .list = ArrayList(u8).init(allocator),
36 };
34 return Buffer{ .list = ArrayList(u8).init(allocator) };
3735 }
3836
3937 /// Must deinitialize with deinit.
......@@ -45,9 +43,7 @@ pub const Buffer = struct {
4543 /// allocated with `allocator`.
4644 /// Must deinitialize with deinit.
4745 pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) Buffer {
48 var self = Buffer {
49 .list = ArrayList(u8).fromOwnedSlice(allocator, slice),
50 };
46 var self = Buffer{ .list = ArrayList(u8).fromOwnedSlice(allocator, slice) };
5147 self.list.append(0);
5248 return self;
5349 }
......@@ -57,11 +53,10 @@ pub const Buffer = struct {
5753 pub fn toOwnedSlice(self: &Buffer) []u8 {
5854 const allocator = self.list.allocator;
5955 const result = allocator.shrink(u8, self.list.items, self.len());
60 *self = initNull(allocator);
56 self.* = initNull(allocator);
6157 return result;
6258 }
6359
64
6560 pub fn deinit(self: &Buffer) void {
6661 self.list.deinit();
6762 }
......@@ -99,26 +94,10 @@ pub const Buffer = struct {
9994 mem.copy(u8, self.list.toSlice()[old_len..], m);
10095 }
10196
102 // TODO: remove, use OutStream for this
103 pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) !void {
104 return fmt.format(self, append, format, args);
105 }
106
107 // TODO: remove, use OutStream for this
10897 pub fn appendByte(self: &Buffer, byte: u8) !void {
109 return self.appendByteNTimes(byte, 1);
110 }
111
112 // TODO: remove, use OutStream for this
113 pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) !void {
114 var prev_size: usize = self.len();
115 const new_size = prev_size + count;
116 try self.resize(new_size);
117
118 var i: usize = prev_size;
119 while (i < new_size) : (i += 1) {
120 self.list.items[i] = byte;
121 }
98 const old_len = self.len();
99 try self.resize(old_len + 1);
100 self.list.toSlice()[old_len] = byte;
122101 }
123102
124103 pub fn eql(self: &const Buffer, m: []const u8) bool {
......@@ -154,7 +133,7 @@ test "simple Buffer" {
154133 var buf = try Buffer.init(debug.global_allocator, "");
155134 assert(buf.len() == 0);
156135 try buf.append("hello");
157 try buf.appendByte(' ');
136 try buf.append(" ");
158137 try buf.append("world");
159138 assert(buf.eql("hello world"));
160139 assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
std/build.zig+86-121
......@@ -82,10 +82,8 @@ pub const Builder = struct {
8282 description: []const u8,
8383 };
8484
85 pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8,
86 cache_root: []const u8) Builder
87 {
88 var self = Builder {
85 pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
86 var self = Builder{
8987 .zig_exe = zig_exe,
9088 .build_root = build_root,
9189 .cache_root = os.path.relative(allocator, build_root, cache_root) catch unreachable,
......@@ -112,12 +110,12 @@ pub const Builder = struct {
112110 .lib_dir = undefined,
113111 .exe_dir = undefined,
114112 .installed_files = ArrayList([]const u8).init(allocator),
115 .uninstall_tls = TopLevelStep {
113 .uninstall_tls = TopLevelStep{
116114 .step = Step.init("uninstall", allocator, makeUninstall),
117115 .description = "Remove build artifacts from prefix path",
118116 },
119117 .have_uninstall_step = false,
120 .install_tls = TopLevelStep {
118 .install_tls = TopLevelStep{
121119 .step = Step.initNoOp("install", allocator),
122120 .description = "Copy build artifacts to prefix path",
123121 },
......@@ -151,9 +149,7 @@ pub const Builder = struct {
151149 return LibExeObjStep.createObject(self, name, root_src);
152150 }
153151
154 pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8,
155 ver: &const Version) &LibExeObjStep
156 {
152 pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep {
157153 return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
158154 }
159155
......@@ -163,7 +159,7 @@ pub const Builder = struct {
163159
164160 pub fn addTest(self: &Builder, root_src: []const u8) &TestStep {
165161 const test_step = self.allocator.create(TestStep) catch unreachable;
166 *test_step = TestStep.init(self, root_src);
162 test_step.* = TestStep.init(self, root_src);
167163 return test_step;
168164 }
169165
......@@ -190,33 +186,31 @@ pub const Builder = struct {
190186 }
191187
192188 /// ::argv is copied.
193 pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
194 argv: []const []const u8) &CommandStep
195 {
189 pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep {
196190 return CommandStep.create(self, cwd, env_map, argv);
197191 }
198192
199193 pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep {
200194 const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
201 *write_file_step = WriteFileStep.init(self, file_path, data);
195 write_file_step.* = WriteFileStep.init(self, file_path, data);
202196 return write_file_step;
203197 }
204198
205199 pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep {
206200 const data = self.fmt(format, args);
207201 const log_step = self.allocator.create(LogStep) catch unreachable;
208 *log_step = LogStep.init(self, data);
202 log_step.* = LogStep.init(self, data);
209203 return log_step;
210204 }
211205
212206 pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep {
213207 const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
214 *remove_dir_step = RemoveDirStep.init(self, dir_path);
208 remove_dir_step.* = RemoveDirStep.init(self, dir_path);
215209 return remove_dir_step;
216210 }
217211
218212 pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version {
219 return Version {
213 return Version{
220214 .major = major,
221215 .minor = minor,
222216 .patch = patch,
......@@ -254,8 +248,7 @@ pub const Builder = struct {
254248 }
255249
256250 pub fn getInstallStep(self: &Builder) &Step {
257 if (self.have_install_step)
258 return &self.install_tls.step;
251 if (self.have_install_step) return &self.install_tls.step;
259252
260253 self.top_level_steps.append(&self.install_tls) catch unreachable;
261254 self.have_install_step = true;
......@@ -263,8 +256,7 @@ pub const Builder = struct {
263256 }
264257
265258 pub fn getUninstallStep(self: &Builder) &Step {
266 if (self.have_uninstall_step)
267 return &self.uninstall_tls.step;
259 if (self.have_uninstall_step) return &self.uninstall_tls.step;
268260
269261 self.top_level_steps.append(&self.uninstall_tls) catch unreachable;
270262 self.have_uninstall_step = true;
......@@ -360,7 +352,7 @@ pub const Builder = struct {
360352
361353 pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T {
362354 const type_id = comptime typeToEnum(T);
363 const available_option = AvailableOption {
355 const available_option = AvailableOption{
364356 .name = name,
365357 .type_id = type_id,
366358 .description = description,
......@@ -413,7 +405,7 @@ pub const Builder = struct {
413405
414406 pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step {
415407 const step_info = self.allocator.create(TopLevelStep) catch unreachable;
416 *step_info = TopLevelStep {
408 step_info.* = TopLevelStep{
417409 .step = Step.initNoOp(name, self.allocator),
418410 .description = description,
419411 };
......@@ -446,9 +438,9 @@ pub const Builder = struct {
446438 }
447439
448440 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) bool {
449 if (self.user_input_options.put(name, UserInputOption {
441 if (self.user_input_options.put(name, UserInputOption{
450442 .name = name,
451 .value = UserValue { .Scalar = value },
443 .value = UserValue{ .Scalar = value },
452444 .used = false,
453445 }) catch unreachable) |*prev_value| {
454446 // option already exists
......@@ -458,18 +450,18 @@ pub const Builder = struct {
458450 var list = ArrayList([]const u8).init(self.allocator);
459451 list.append(s) catch unreachable;
460452 list.append(value) catch unreachable;
461 _ = self.user_input_options.put(name, UserInputOption {
453 _ = self.user_input_options.put(name, UserInputOption{
462454 .name = name,
463 .value = UserValue { .List = list },
455 .value = UserValue{ .List = list },
464456 .used = false,
465457 }) catch unreachable;
466458 },
467459 UserValue.List => |*list| {
468460 // append to the list
469461 list.append(value) catch unreachable;
470 _ = self.user_input_options.put(name, UserInputOption {
462 _ = self.user_input_options.put(name, UserInputOption{
471463 .name = name,
472 .value = UserValue { .List = *list },
464 .value = UserValue{ .List = list.* },
473465 .used = false,
474466 }) catch unreachable;
475467 },
......@@ -483,9 +475,9 @@ pub const Builder = struct {
483475 }
484476
485477 pub fn addUserInputFlag(self: &Builder, name: []const u8) bool {
486 if (self.user_input_options.put(name, UserInputOption {
478 if (self.user_input_options.put(name, UserInputOption{
487479 .name = name,
488 .value = UserValue {.Flag = {} },
480 .value = UserValue{ .Flag = {} },
489481 .used = false,
490482 }) catch unreachable) |*prev_value| {
491483 switch (prev_value.value) {
......@@ -556,9 +548,7 @@ pub const Builder = struct {
556548 warn("\n");
557549 }
558550
559 fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
560 argv: []const []const u8) !void
561 {
551 fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) !void {
562552 if (self.verbose) {
563553 printCmd(cwd, argv);
564554 }
......@@ -617,7 +607,7 @@ pub const Builder = struct {
617607 self.pushInstalledFile(full_dest_path);
618608
619609 const install_step = self.allocator.create(InstallFileStep) catch unreachable;
620 *install_step = InstallFileStep.init(self, src_path, full_dest_path);
610 install_step.* = InstallFileStep.init(self, src_path, full_dest_path);
621611 return install_step;
622612 }
623613
......@@ -659,25 +649,23 @@ pub const Builder = struct {
659649 if (builtin.environ == builtin.Environ.msvc) {
660650 return "cl.exe";
661651 } else {
662 return os.getEnvVarOwned(self.allocator, "CC") catch |err|
652 return os.getEnvVarOwned(self.allocator, "CC") catch |err|
663653 if (err == error.EnvironmentVariableNotFound)
664654 ([]const u8)("cc")
665655 else
666 debug.panic("Unable to get environment variable: {}", err)
667 ;
656 debug.panic("Unable to get environment variable: {}", err);
668657 }
669658 }
670659
671660 pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
672661 // TODO report error for ambiguous situations
673 const exe_extension = (Target { .Native = {}}).exeFileExt();
662 const exe_extension = (Target{ .Native = {} }).exeFileExt();
674663 for (self.search_prefixes.toSliceConst()) |search_prefix| {
675664 for (names) |name| {
676665 if (os.path.isAbsolute(name)) {
677666 return name;
678667 }
679 const full_path = try os.path.join(self.allocator, search_prefix, "bin",
680 self.fmt("{}{}", name, exe_extension));
668 const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension));
681669 if (os.path.real(self.allocator, full_path)) |real_path| {
682670 return real_path;
683671 } else |_| {
......@@ -761,7 +749,7 @@ pub const Target = union(enum) {
761749 Cross: CrossTarget,
762750
763751 pub fn oFileExt(self: &const Target) []const u8 {
764 const environ = switch (*self) {
752 const environ = switch (self.*) {
765753 Target.Native => builtin.environ,
766754 Target.Cross => |t| t.environ,
767755 };
......@@ -786,7 +774,7 @@ pub const Target = union(enum) {
786774 }
787775
788776 pub fn getOs(self: &const Target) builtin.Os {
789 return switch (*self) {
777 return switch (self.*) {
790778 Target.Native => builtin.os,
791779 Target.Cross => |t| t.os,
792780 };
......@@ -794,7 +782,8 @@ pub const Target = union(enum) {
794782
795783 pub fn isDarwin(self: &const Target) bool {
796784 return switch (self.getOs()) {
797 builtin.Os.ios, builtin.Os.macosx => true,
785 builtin.Os.ios,
786 builtin.Os.macosx => true,
798787 else => false,
799788 };
800789 }
......@@ -860,61 +849,57 @@ pub const LibExeObjStep = struct {
860849 Obj,
861850 };
862851
863 pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8,
864 ver: &const Version) &LibExeObjStep
865 {
852 pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, ver: &const Version) &LibExeObjStep {
866853 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
867 *self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
854 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
868855 return self;
869856 }
870857
871858 pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep {
872859 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
873 *self = initC(builder, name, Kind.Lib, version, false);
860 self.* = initC(builder, name, Kind.Lib, version, false);
874861 return self;
875862 }
876863
877864 pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
878865 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
879 *self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
866 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
880867 return self;
881868 }
882869
883870 pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep {
884871 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
885 *self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
872 self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
886873 return self;
887874 }
888875
889876 pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep {
890877 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
891 *self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
878 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
892879 return self;
893880 }
894881
895882 pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep {
896883 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
897 *self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
884 self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
898885 self.object_src = src;
899886 return self;
900887 }
901888
902889 pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep {
903890 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
904 *self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
891 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));
905892 return self;
906893 }
907894
908895 pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep {
909896 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
910 *self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
897 self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
911898 return self;
912899 }
913900
914 fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind,
915 static: bool, ver: &const Version) LibExeObjStep
916 {
917 var self = LibExeObjStep {
901 fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, static: bool, ver: &const Version) LibExeObjStep {
902 var self = LibExeObjStep{
918903 .strip = false,
919904 .builder = builder,
920905 .verbose_link = false,
......@@ -930,7 +915,7 @@ pub const LibExeObjStep = struct {
930915 .step = Step.init(name, builder.allocator, make),
931916 .output_path = null,
932917 .output_h_path = null,
933 .version = *ver,
918 .version = ver.*,
934919 .out_filename = undefined,
935920 .out_h_filename = builder.fmt("{}.h", name),
936921 .major_only_filename = undefined,
......@@ -953,11 +938,11 @@ pub const LibExeObjStep = struct {
953938 }
954939
955940 fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep {
956 var self = LibExeObjStep {
941 var self = LibExeObjStep{
957942 .builder = builder,
958943 .name = name,
959944 .kind = kind,
960 .version = *version,
945 .version = version.*,
961946 .static = static,
962947 .target = Target.Native,
963948 .cflags = ArrayList([]const u8).init(builder.allocator),
......@@ -1005,9 +990,9 @@ pub const LibExeObjStep = struct {
1005990 self.out_filename = self.builder.fmt("lib{}.a", self.name);
1006991 } else {
1007992 switch (self.target.getOs()) {
1008 builtin.Os.ios, builtin.Os.macosx => {
1009 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib",
1010 self.name, self.version.major, self.version.minor, self.version.patch);
993 builtin.Os.ios,
994 builtin.Os.macosx => {
995 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);
1011996 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);
1012997 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
1013998 },
......@@ -1015,8 +1000,7 @@ pub const LibExeObjStep = struct {
10151000 self.out_filename = self.builder.fmt("{}.dll", self.name);
10161001 },
10171002 else => {
1018 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}",
1019 self.name, self.version.major, self.version.minor, self.version.patch);
1003 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", self.name, self.version.major, self.version.minor, self.version.patch);
10201004 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);
10211005 self.name_only_filename = self.builder.fmt("lib{}.so", self.name);
10221006 },
......@@ -1026,16 +1010,12 @@ pub const LibExeObjStep = struct {
10261010 }
10271011 }
10281012
1029 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os,
1030 target_environ: builtin.Environ) void
1031 {
1032 self.target = Target {
1033 .Cross = CrossTarget {
1034 .arch = target_arch,
1035 .os = target_os,
1036 .environ = target_environ,
1037 }
1038 };
1013 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
1014 self.target = Target{ .Cross = CrossTarget{
1015 .arch = target_arch,
1016 .os = target_os,
1017 .environ = target_environ,
1018 } };
10391019 self.computeOutFileNames();
10401020 }
10411021
......@@ -1159,7 +1139,7 @@ pub const LibExeObjStep = struct {
11591139 pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
11601140 assert(self.is_zig);
11611141
1162 self.packages.append(Pkg {
1142 self.packages.append(Pkg{
11631143 .name = name,
11641144 .path = pkg_index_path,
11651145 }) catch unreachable;
......@@ -1343,8 +1323,7 @@ pub const LibExeObjStep = struct {
13431323 try builder.spawnChild(zig_args.toSliceConst());
13441324
13451325 if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) {
1346 try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
1347 self.name_only_filename);
1326 try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename);
13481327 }
13491328 }
13501329
......@@ -1373,7 +1352,8 @@ pub const LibExeObjStep = struct {
13731352 args.append("ssp-buffer-size=4") catch unreachable;
13741353 }
13751354 },
1376 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {
1355 builtin.Mode.ReleaseFast,
1356 builtin.Mode.ReleaseSmall => {
13771357 args.append("-O2") catch unreachable;
13781358 args.append("-fno-stack-protector") catch unreachable;
13791359 },
......@@ -1505,8 +1485,7 @@ pub const LibExeObjStep = struct {
15051485 }
15061486
15071487 if (!is_darwin) {
1508 const rpath_arg = builder.fmt("-Wl,-rpath,{}",
1509 os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
1488 const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
15101489 defer builder.allocator.free(rpath_arg);
15111490 cc_args.append(rpath_arg) catch unreachable;
15121491
......@@ -1535,8 +1514,7 @@ pub const LibExeObjStep = struct {
15351514 try builder.spawnChild(cc_args.toSliceConst());
15361515
15371516 if (self.target.wantSharedLibSymLinks()) {
1538 try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
1539 self.name_only_filename);
1517 try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename);
15401518 }
15411519 }
15421520 },
......@@ -1581,8 +1559,7 @@ pub const LibExeObjStep = struct {
15811559 cc_args.append("-o") catch unreachable;
15821560 cc_args.append(output_path) catch unreachable;
15831561
1584 const rpath_arg = builder.fmt("-Wl,-rpath,{}",
1585 os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
1562 const rpath_arg = builder.fmt("-Wl,-rpath,{}", os.path.real(builder.allocator, builder.pathFromRoot(builder.cache_root)) catch unreachable);
15861563 defer builder.allocator.free(rpath_arg);
15871564 cc_args.append(rpath_arg) catch unreachable;
15881565
......@@ -1635,7 +1612,7 @@ pub const TestStep = struct {
16351612
16361613 pub fn init(builder: &Builder, root_src: []const u8) TestStep {
16371614 const step_name = builder.fmt("test {}", root_src);
1638 return TestStep {
1615 return TestStep{
16391616 .step = Step.init(step_name, builder.allocator, make),
16401617 .builder = builder,
16411618 .root_src = root_src,
......@@ -1644,7 +1621,7 @@ pub const TestStep = struct {
16441621 .name_prefix = "",
16451622 .filter = null,
16461623 .link_libs = BufSet.init(builder.allocator),
1647 .target = Target { .Native = {} },
1624 .target = Target{ .Native = {} },
16481625 .exec_cmd_args = null,
16491626 .include_dirs = ArrayList([]const u8).init(builder.allocator),
16501627 };
......@@ -1674,16 +1651,12 @@ pub const TestStep = struct {
16741651 self.filter = text;
16751652 }
16761653
1677 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os,
1678 target_environ: builtin.Environ) void
1679 {
1680 self.target = Target {
1681 .Cross = CrossTarget {
1682 .arch = target_arch,
1683 .os = target_os,
1684 .environ = target_environ,
1685 }
1686 };
1654 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
1655 self.target = Target{ .Cross = CrossTarget{
1656 .arch = target_arch,
1657 .os = target_os,
1658 .environ = target_environ,
1659 } };
16871660 }
16881661
16891662 pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void {
......@@ -1789,11 +1762,9 @@ pub const CommandStep = struct {
17891762 env_map: &const BufMap,
17901763
17911764 /// ::argv is copied.
1792 pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
1793 argv: []const []const u8) &CommandStep
1794 {
1765 pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, argv: []const []const u8) &CommandStep {
17951766 const self = builder.allocator.create(CommandStep) catch unreachable;
1796 *self = CommandStep {
1767 self.* = CommandStep{
17971768 .builder = builder,
17981769 .step = Step.init(argv[0], builder.allocator, make),
17991770 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
......@@ -1828,7 +1799,7 @@ const InstallArtifactStep = struct {
18281799 LibExeObjStep.Kind.Exe => builder.exe_dir,
18291800 LibExeObjStep.Kind.Lib => builder.lib_dir,
18301801 };
1831 *self = Self {
1802 self.* = Self{
18321803 .builder = builder,
18331804 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
18341805 .artifact = artifact,
......@@ -1837,10 +1808,8 @@ const InstallArtifactStep = struct {
18371808 self.step.dependOn(&artifact.step);
18381809 builder.pushInstalledFile(self.dest_file);
18391810 if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
1840 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir,
1841 artifact.major_only_filename) catch unreachable);
1842 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir,
1843 artifact.name_only_filename) catch unreachable);
1811 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable);
1812 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable);
18441813 }
18451814 return self;
18461815 }
......@@ -1859,8 +1828,7 @@ const InstallArtifactStep = struct {
18591828 };
18601829 try builder.copyFileMode(self.artifact.getOutputPath(), self.dest_file, mode);
18611830 if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
1862 try doAtomicSymLinks(builder.allocator, self.dest_file,
1863 self.artifact.major_only_filename, self.artifact.name_only_filename);
1831 try doAtomicSymLinks(builder.allocator, self.dest_file, self.artifact.major_only_filename, self.artifact.name_only_filename);
18641832 }
18651833 }
18661834};
......@@ -1872,7 +1840,7 @@ pub const InstallFileStep = struct {
18721840 dest_path: []const u8,
18731841
18741842 pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep {
1875 return InstallFileStep {
1843 return InstallFileStep{
18761844 .builder = builder,
18771845 .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make),
18781846 .src_path = src_path,
......@@ -1893,7 +1861,7 @@ pub const WriteFileStep = struct {
18931861 data: []const u8,
18941862
18951863 pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep {
1896 return WriteFileStep {
1864 return WriteFileStep{
18971865 .builder = builder,
18981866 .step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make),
18991867 .file_path = file_path,
......@@ -1922,7 +1890,7 @@ pub const LogStep = struct {
19221890 data: []const u8,
19231891
19241892 pub fn init(builder: &Builder, data: []const u8) LogStep {
1925 return LogStep {
1893 return LogStep{
19261894 .builder = builder,
19271895 .step = Step.init(builder.fmt("log {}", data), builder.allocator, make),
19281896 .data = data,
......@@ -1941,7 +1909,7 @@ pub const RemoveDirStep = struct {
19411909 dir_path: []const u8,
19421910
19431911 pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep {
1944 return RemoveDirStep {
1912 return RemoveDirStep{
19451913 .builder = builder,
19461914 .step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make),
19471915 .dir_path = dir_path,
......@@ -1966,8 +1934,8 @@ pub const Step = struct {
19661934 loop_flag: bool,
19671935 done_flag: bool,
19681936
1969 pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step {
1970 return Step {
1937 pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn(&Step) error!void) Step {
1938 return Step{
19711939 .name = name,
19721940 .makeFn = makeFn,
19731941 .dependencies = ArrayList(&Step).init(allocator),
......@@ -1980,8 +1948,7 @@ pub const Step = struct {
19801948 }
19811949
19821950 pub fn make(self: &Step) !void {
1983 if (self.done_flag)
1984 return;
1951 if (self.done_flag) return;
19851952
19861953 try self.makeFn(self);
19871954 self.done_flag = true;
......@@ -1994,9 +1961,7 @@ pub const Step = struct {
19941961 fn makeNoOp(self: &Step) error!void {}
19951962};
19961963
1997fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
1998 filename_name_only: []const u8) !void
1999{
1964fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void {
20001965 const out_dir = os.path.dirname(output_path);
20011966 const out_basename = os.path.basename(output_path);
20021967 // sym link for libfoo.so.1 to libfoo.so.1.2.3
std/crypto/blake2.zig+470-241
......@@ -6,11 +6,23 @@ const builtin = @import("builtin");
66const htest = @import("test.zig");
77
88const RoundParam = struct {
9 a: usize, b: usize, c: usize, d: usize, x: usize, y: usize,
9 a: usize,
10 b: usize,
11 c: usize,
12 d: usize,
13 x: usize,
14 y: usize,
1015};
1116
1217fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
13 return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, };
18 return RoundParam{
19 .a = a,
20 .b = b,
21 .c = c,
22 .d = d,
23 .x = x,
24 .y = y,
25 };
1426}
1527
1628/////////////////////
......@@ -19,145 +31,153 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam {
1931pub const Blake2s224 = Blake2s(224);
2032pub const Blake2s256 = Blake2s(256);
2133
22fn Blake2s(comptime out_len: usize) type { return struct {
23 const Self = this;
24 const block_size = 64;
25 const digest_size = out_len / 8;
34fn Blake2s(comptime out_len: usize) type {
35 return struct {
36 const Self = this;
37 const block_size = 64;
38 const digest_size = out_len / 8;
39
40 const iv = [8]u32{
41 0x6A09E667,
42 0xBB67AE85,
43 0x3C6EF372,
44 0xA54FF53A,
45 0x510E527F,
46 0x9B05688C,
47 0x1F83D9AB,
48 0x5BE0CD19,
49 };
2650
27 const iv = [8]u32 {
28 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
29 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
30 };
51 const sigma = [10][16]u8{
52 []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
53 []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
54 []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
55 []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
56 []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
57 []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
58 []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
59 []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
60 []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
61 []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
62 };
3163
32 const sigma = [10][16]u8 {
33 []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
34 []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
35 []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
36 []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
37 []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
38 []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
39 []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
40 []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
41 []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
42 []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
43 };
64 h: [8]u32,
65 t: u64,
66 // Streaming cache
67 buf: [64]u8,
68 buf_len: u8,
4469
45 h: [8]u32,
46 t: u64,
47 // Streaming cache
48 buf: [64]u8,
49 buf_len: u8,
50
51 pub fn init() Self {
52 debug.assert(8 <= out_len and out_len <= 512);
53
54 var s: Self = undefined;
55 s.reset();
56 return s;
57 }
58
59 pub fn reset(d: &Self) void {
60 mem.copy(u32, d.h[0..], iv[0..]);
61
62 // No key plus default parameters
63 d.h[0] ^= 0x01010000 ^ u32(out_len >> 3);
64 d.t = 0;
65 d.buf_len = 0;
66 }
67
68 pub fn hash(b: []const u8, out: []u8) void {
69 var d = Self.init();
70 d.update(b);
71 d.final(out);
72 }
73
74 pub fn update(d: &Self, b: []const u8) void {
75 var off: usize = 0;
76
77 // Partial buffer exists from previous update. Copy into buffer then hash.
78 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
79 off += 64 - d.buf_len;
80 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
81 d.t += 64;
82 d.round(d.buf[0..], false);
83 d.buf_len = 0;
70 pub fn init() Self {
71 debug.assert(8 <= out_len and out_len <= 512);
72
73 var s: Self = undefined;
74 s.reset();
75 return s;
8476 }
8577
86 // Full middle blocks.
87 while (off + 64 <= b.len) : (off += 64) {
88 d.t += 64;
89 d.round(b[off..off + 64], false);
78 pub fn reset(d: &Self) void {
79 mem.copy(u32, d.h[0..], iv[0..]);
80
81 // No key plus default parameters
82 d.h[0] ^= 0x01010000 ^ u32(out_len >> 3);
83 d.t = 0;
84 d.buf_len = 0;
9085 }
9186
92 // Copy any remainder for next pass.
93 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
94 d.buf_len += u8(b[off..].len);
95 }
87 pub fn hash(b: []const u8, out: []u8) void {
88 var d = Self.init();
89 d.update(b);
90 d.final(out);
91 }
9692
97 pub fn final(d: &Self, out: []u8) void {
98 debug.assert(out.len >= out_len / 8);
93 pub fn update(d: &Self, b: []const u8) void {
94 var off: usize = 0;
9995
100 mem.set(u8, d.buf[d.buf_len..], 0);
101 d.t += d.buf_len;
102 d.round(d.buf[0..], true);
96 // Partial buffer exists from previous update. Copy into buffer then hash.
97 if (d.buf_len != 0 and d.buf_len + b.len > 64) {
98 off += 64 - d.buf_len;
99 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
100 d.t += 64;
101 d.round(d.buf[0..], false);
102 d.buf_len = 0;
103 }
103104
104 const rr = d.h[0 .. out_len / 32];
105 // Full middle blocks.
106 while (off + 64 <= b.len) : (off += 64) {
107 d.t += 64;
108 d.round(b[off..off + 64], false);
109 }
105110
106 for (rr) |s, j| {
107 mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Little);
111 // Copy any remainder for next pass.
112 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
113 d.buf_len += u8(b[off..].len);
108114 }
109 }
110115
111 fn round(d: &Self, b: []const u8, last: bool) void {
112 debug.assert(b.len == 64);
116 pub fn final(d: &Self, out: []u8) void {
117 debug.assert(out.len >= out_len / 8);
113118
114 var m: [16]u32 = undefined;
115 var v: [16]u32 = undefined;
119 mem.set(u8, d.buf[d.buf_len..], 0);
120 d.t += d.buf_len;
121 d.round(d.buf[0..], true);
116122
117 for (m) |*r, i| {
118 *r = mem.readIntLE(u32, b[4*i .. 4*i + 4]);
119 }
123 const rr = d.h[0..out_len / 32];
120124
121 var k: usize = 0;
122 while (k < 8) : (k += 1) {
123 v[k] = d.h[k];
124 v[k+8] = iv[k];
125 for (rr) |s, j| {
126 mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Little);
127 }
125128 }
126129
127 v[12] ^= @truncate(u32, d.t);
128 v[13] ^= u32(d.t >> 32);
129 if (last) v[14] = ~v[14];
130
131 const rounds = comptime []RoundParam {
132 Rp(0, 4, 8, 12, 0, 1),
133 Rp(1, 5, 9, 13, 2, 3),
134 Rp(2, 6, 10, 14, 4, 5),
135 Rp(3, 7, 11, 15, 6, 7),
136 Rp(0, 5, 10, 15, 8, 9),
137 Rp(1, 6, 11, 12, 10, 11),
138 Rp(2, 7, 8, 13, 12, 13),
139 Rp(3, 4, 9, 14, 14, 15),
140 };
130 fn round(d: &Self, b: []const u8, last: bool) void {
131 debug.assert(b.len == 64);
141132
142 comptime var j: usize = 0;
143 inline while (j < 10) : (j += 1) {
144 inline for (rounds) |r| {
145 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
146 v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16));
147 v[r.c] = v[r.c] +% v[r.d];
148 v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12));
149 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
150 v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8));
151 v[r.c] = v[r.c] +% v[r.d];
152 v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7));
133 var m: [16]u32 = undefined;
134 var v: [16]u32 = undefined;
135
136 for (m) |*r, i| {
137 r.* = mem.readIntLE(u32, b[4 * i..4 * i + 4]);
153138 }
154 }
155139
156 for (d.h) |*r, i| {
157 *r ^= v[i] ^ v[i + 8];
140 var k: usize = 0;
141 while (k < 8) : (k += 1) {
142 v[k] = d.h[k];
143 v[k + 8] = iv[k];
144 }
145
146 v[12] ^= @truncate(u32, d.t);
147 v[13] ^= u32(d.t >> 32);
148 if (last) v[14] = ~v[14];
149
150 const rounds = comptime []RoundParam{
151 Rp(0, 4, 8, 12, 0, 1),
152 Rp(1, 5, 9, 13, 2, 3),
153 Rp(2, 6, 10, 14, 4, 5),
154 Rp(3, 7, 11, 15, 6, 7),
155 Rp(0, 5, 10, 15, 8, 9),
156 Rp(1, 6, 11, 12, 10, 11),
157 Rp(2, 7, 8, 13, 12, 13),
158 Rp(3, 4, 9, 14, 14, 15),
159 };
160
161 comptime var j: usize = 0;
162 inline while (j < 10) : (j += 1) {
163 inline for (rounds) |r| {
164 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
165 v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16));
166 v[r.c] = v[r.c] +% v[r.d];
167 v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12));
168 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
169 v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8));
170 v[r.c] = v[r.c] +% v[r.d];
171 v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7));
172 }
173 }
174
175 for (d.h) |*r, i| {
176 r.* ^= v[i] ^ v[i + 8];
177 }
158178 }
159 }
160};}
179 };
180}
161181
162182test "blake2s224 single" {
163183 const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4";
......@@ -230,7 +250,7 @@ test "blake2s256 streaming" {
230250}
231251
232252test "blake2s256 aligned final" {
233 var block = []u8 {0} ** Blake2s256.block_size;
253 var block = []u8{0} ** Blake2s256.block_size;
234254 var out: [Blake2s256.digest_size]u8 = undefined;
235255
236256 var h = Blake2s256.init();
......@@ -238,154 +258,363 @@ test "blake2s256 aligned final" {
238258 h.final(out[0..]);
239259}
240260
241
242261/////////////////////
243262// Blake2b
244263
245264pub const Blake2b384 = Blake2b(384);
246265pub const Blake2b512 = Blake2b(512);
247266
248fn Blake2b(comptime out_len: usize) type { return struct {
249 const Self = this;
250 const block_size = 128;
251 const digest_size = out_len / 8;
267fn Blake2b(comptime out_len: usize) type {
268 return struct {
269 const Self = this;
270 const block_size = 128;
271 const digest_size = out_len / 8;
272
273 const iv = [8]u64{
274 0x6a09e667f3bcc908,
275 0xbb67ae8584caa73b,
276 0x3c6ef372fe94f82b,
277 0xa54ff53a5f1d36f1,
278 0x510e527fade682d1,
279 0x9b05688c2b3e6c1f,
280 0x1f83d9abfb41bd6b,
281 0x5be0cd19137e2179,
282 };
252283
253 const iv = [8]u64 {
254 0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
255 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
256 0x510e527fade682d1, 0x9b05688c2b3e6c1f,
257 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
258 };
284 const sigma = [12][16]u8{
285 []const u8{
286 0,
287 1,
288 2,
289 3,
290 4,
291 5,
292 6,
293 7,
294 8,
295 9,
296 10,
297 11,
298 12,
299 13,
300 14,
301 15,
302 },
303 []const u8{
304 14,
305 10,
306 4,
307 8,
308 9,
309 15,
310 13,
311 6,
312 1,
313 12,
314 0,
315 2,
316 11,
317 7,
318 5,
319 3,
320 },
321 []const u8{
322 11,
323 8,
324 12,
325 0,
326 5,
327 2,
328 15,
329 13,
330 10,
331 14,
332 3,
333 6,
334 7,
335 1,
336 9,
337 4,
338 },
339 []const u8{
340 7,
341 9,
342 3,
343 1,
344 13,
345 12,
346 11,
347 14,
348 2,
349 6,
350 5,
351 10,
352 4,
353 0,
354 15,
355 8,
356 },
357 []const u8{
358 9,
359 0,
360 5,
361 7,
362 2,
363 4,
364 10,
365 15,
366 14,
367 1,
368 11,
369 12,
370 6,
371 8,
372 3,
373 13,
374 },
375 []const u8{
376 2,
377 12,
378 6,
379 10,
380 0,
381 11,
382 8,
383 3,
384 4,
385 13,
386 7,
387 5,
388 15,
389 14,
390 1,
391 9,
392 },
393 []const u8{
394 12,
395 5,
396 1,
397 15,
398 14,
399 13,
400 4,
401 10,
402 0,
403 7,
404 6,
405 3,
406 9,
407 2,
408 8,
409 11,
410 },
411 []const u8{
412 13,
413 11,
414 7,
415 14,
416 12,
417 1,
418 3,
419 9,
420 5,
421 0,
422 15,
423 4,
424 8,
425 6,
426 2,
427 10,
428 },
429 []const u8{
430 6,
431 15,
432 14,
433 9,
434 11,
435 3,
436 0,
437 8,
438 12,
439 2,
440 13,
441 7,
442 1,
443 4,
444 10,
445 5,
446 },
447 []const u8{
448 10,
449 2,
450 8,
451 4,
452 7,
453 6,
454 1,
455 5,
456 15,
457 11,
458 9,
459 14,
460 3,
461 12,
462 13,
463 0,
464 },
465 []const u8{
466 0,
467 1,
468 2,
469 3,
470 4,
471 5,
472 6,
473 7,
474 8,
475 9,
476 10,
477 11,
478 12,
479 13,
480 14,
481 15,
482 },
483 []const u8{
484 14,
485 10,
486 4,
487 8,
488 9,
489 15,
490 13,
491 6,
492 1,
493 12,
494 0,
495 2,
496 11,
497 7,
498 5,
499 3,
500 },
501 };
259502
260 const sigma = [12][16]u8 {
261 []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
262 []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
263 []const u8 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
264 []const u8 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
265 []const u8 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
266 []const u8 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
267 []const u8 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
268 []const u8 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
269 []const u8 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
270 []const u8 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 },
271 []const u8 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
272 []const u8 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
273 };
503 h: [8]u64,
504 t: u128,
505 // Streaming cache
506 buf: [128]u8,
507 buf_len: u8,
274508
275 h: [8]u64,
276 t: u128,
277 // Streaming cache
278 buf: [128]u8,
279 buf_len: u8,
280
281 pub fn init() Self {
282 debug.assert(8 <= out_len and out_len <= 512);
283
284 var s: Self = undefined;
285 s.reset();
286 return s;
287 }
288
289 pub fn reset(d: &Self) void {
290 mem.copy(u64, d.h[0..], iv[0..]);
291
292 // No key plus default parameters
293 d.h[0] ^= 0x01010000 ^ (out_len >> 3);
294 d.t = 0;
295 d.buf_len = 0;
296 }
297
298 pub fn hash(b: []const u8, out: []u8) void {
299 var d = Self.init();
300 d.update(b);
301 d.final(out);
302 }
303
304 pub fn update(d: &Self, b: []const u8) void {
305 var off: usize = 0;
306
307 // Partial buffer exists from previous update. Copy into buffer then hash.
308 if (d.buf_len != 0 and d.buf_len + b.len > 128) {
309 off += 128 - d.buf_len;
310 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
311 d.t += 128;
312 d.round(d.buf[0..], false);
509 pub fn init() Self {
510 debug.assert(8 <= out_len and out_len <= 512);
511
512 var s: Self = undefined;
513 s.reset();
514 return s;
515 }
516
517 pub fn reset(d: &Self) void {
518 mem.copy(u64, d.h[0..], iv[0..]);
519
520 // No key plus default parameters
521 d.h[0] ^= 0x01010000 ^ (out_len >> 3);
522 d.t = 0;
313523 d.buf_len = 0;
314524 }
315525
316 // Full middle blocks.
317 while (off + 128 <= b.len) : (off += 128) {
318 d.t += 128;
319 d.round(b[off..off + 128], false);
526 pub fn hash(b: []const u8, out: []u8) void {
527 var d = Self.init();
528 d.update(b);
529 d.final(out);
320530 }
321531
322 // Copy any remainder for next pass.
323 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
324 d.buf_len += u8(b[off..].len);
325 }
532 pub fn update(d: &Self, b: []const u8) void {
533 var off: usize = 0;
326534
327 pub fn final(d: &Self, out: []u8) void {
328 mem.set(u8, d.buf[d.buf_len..], 0);
329 d.t += d.buf_len;
330 d.round(d.buf[0..], true);
535 // Partial buffer exists from previous update. Copy into buffer then hash.
536 if (d.buf_len != 0 and d.buf_len + b.len > 128) {
537 off += 128 - d.buf_len;
538 mem.copy(u8, d.buf[d.buf_len..], b[0..off]);
539 d.t += 128;
540 d.round(d.buf[0..], false);
541 d.buf_len = 0;
542 }
331543
332 const rr = d.h[0 .. out_len / 64];
544 // Full middle blocks.
545 while (off + 128 <= b.len) : (off += 128) {
546 d.t += 128;
547 d.round(b[off..off + 128], false);
548 }
333549
334 for (rr) |s, j| {
335 mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Little);
550 // Copy any remainder for next pass.
551 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
552 d.buf_len += u8(b[off..].len);
336553 }
337 }
338554
339 fn round(d: &Self, b: []const u8, last: bool) void {
340 debug.assert(b.len == 128);
555 pub fn final(d: &Self, out: []u8) void {
556 mem.set(u8, d.buf[d.buf_len..], 0);
557 d.t += d.buf_len;
558 d.round(d.buf[0..], true);
341559
342 var m: [16]u64 = undefined;
343 var v: [16]u64 = undefined;
560 const rr = d.h[0..out_len / 64];
344561
345 for (m) |*r, i| {
346 *r = mem.readIntLE(u64, b[8*i .. 8*i + 8]);
562 for (rr) |s, j| {
563 mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Little);
564 }
347565 }
348566
349 var k: usize = 0;
350 while (k < 8) : (k += 1) {
351 v[k] = d.h[k];
352 v[k+8] = iv[k];
353 }
567 fn round(d: &Self, b: []const u8, last: bool) void {
568 debug.assert(b.len == 128);
354569
355 v[12] ^= @truncate(u64, d.t);
356 v[13] ^= u64(d.t >> 64);
357 if (last) v[14] = ~v[14];
358
359 const rounds = comptime []RoundParam {
360 Rp(0, 4, 8, 12, 0, 1),
361 Rp(1, 5, 9, 13, 2, 3),
362 Rp(2, 6, 10, 14, 4, 5),
363 Rp(3, 7, 11, 15, 6, 7),
364 Rp(0, 5, 10, 15, 8, 9),
365 Rp(1, 6, 11, 12, 10, 11),
366 Rp(2, 7, 8, 13, 12, 13),
367 Rp(3, 4, 9, 14, 14, 15),
368 };
570 var m: [16]u64 = undefined;
571 var v: [16]u64 = undefined;
369572
370 comptime var j: usize = 0;
371 inline while (j < 12) : (j += 1) {
372 inline for (rounds) |r| {
373 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
374 v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32));
375 v[r.c] = v[r.c] +% v[r.d];
376 v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24));
377 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
378 v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16));
379 v[r.c] = v[r.c] +% v[r.d];
380 v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63));
573 for (m) |*r, i| {
574 r.* = mem.readIntLE(u64, b[8 * i..8 * i + 8]);
575 }
576
577 var k: usize = 0;
578 while (k < 8) : (k += 1) {
579 v[k] = d.h[k];
580 v[k + 8] = iv[k];
381581 }
382 }
383582
384 for (d.h) |*r, i| {
385 *r ^= v[i] ^ v[i + 8];
583 v[12] ^= @truncate(u64, d.t);
584 v[13] ^= u64(d.t >> 64);
585 if (last) v[14] = ~v[14];
586
587 const rounds = comptime []RoundParam{
588 Rp(0, 4, 8, 12, 0, 1),
589 Rp(1, 5, 9, 13, 2, 3),
590 Rp(2, 6, 10, 14, 4, 5),
591 Rp(3, 7, 11, 15, 6, 7),
592 Rp(0, 5, 10, 15, 8, 9),
593 Rp(1, 6, 11, 12, 10, 11),
594 Rp(2, 7, 8, 13, 12, 13),
595 Rp(3, 4, 9, 14, 14, 15),
596 };
597
598 comptime var j: usize = 0;
599 inline while (j < 12) : (j += 1) {
600 inline for (rounds) |r| {
601 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]];
602 v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32));
603 v[r.c] = v[r.c] +% v[r.d];
604 v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24));
605 v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]];
606 v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16));
607 v[r.c] = v[r.c] +% v[r.d];
608 v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63));
609 }
610 }
611
612 for (d.h) |*r, i| {
613 r.* ^= v[i] ^ v[i + 8];
614 }
386615 }
387 }
388};}
616 };
617}
389618
390619test "blake2b384 single" {
391620 const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100";
......@@ -458,7 +687,7 @@ test "blake2b512 streaming" {
458687}
459688
460689test "blake2b512 aligned final" {
461 var block = []u8 {0} ** Blake2b512.block_size;
690 var block = []u8{0} ** Blake2b512.block_size;
462691 var out: [Blake2b512.digest_size]u8 = undefined;
463692
464693 var h = Blake2b512.init();
std/crypto/hmac.zig+2-2
......@@ -29,12 +29,12 @@ pub fn Hmac(comptime H: type) type {
2929
3030 var o_key_pad: [H.block_size]u8 = undefined;
3131 for (o_key_pad) |*b, i| {
32 *b = scratch[i] ^ 0x5c;
32 b.* = scratch[i] ^ 0x5c;
3333 }
3434
3535 var i_key_pad: [H.block_size]u8 = undefined;
3636 for (i_key_pad) |*b, i| {
37 *b = scratch[i] ^ 0x36;
37 b.* = scratch[i] ^ 0x36;
3838 }
3939
4040 // HMAC(k, m) = H(o_key_pad | H(i_key_pad | message)) where | is concatenation
std/crypto/sha3.zig+180-101
......@@ -10,148 +10,228 @@ pub const Sha3_256 = Keccak(256, 0x06);
1010pub const Sha3_384 = Keccak(384, 0x06);
1111pub const Sha3_512 = Keccak(512, 0x06);
1212
13fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct {
14 const Self = this;
15 const block_size = 200;
16 const digest_size = bits / 8;
17
18 s: [200]u8,
19 offset: usize,
20 rate: usize,
21
22 pub fn init() Self {
23 var d: Self = undefined;
24 d.reset();
25 return d;
26 }
13fn Keccak(comptime bits: usize, comptime delim: u8) type {
14 return struct {
15 const Self = this;
16 const block_size = 200;
17 const digest_size = bits / 8;
18
19 s: [200]u8,
20 offset: usize,
21 rate: usize,
22
23 pub fn init() Self {
24 var d: Self = undefined;
25 d.reset();
26 return d;
27 }
2728
28 pub fn reset(d: &Self) void {
29 mem.set(u8, d.s[0..], 0);
30 d.offset = 0;
31 d.rate = 200 - (bits / 4);
32 }
29 pub fn reset(d: &Self) void {
30 mem.set(u8, d.s[0..], 0);
31 d.offset = 0;
32 d.rate = 200 - (bits / 4);
33 }
3334
34 pub fn hash(b: []const u8, out: []u8) void {
35 var d = Self.init();
36 d.update(b);
37 d.final(out);
38 }
35 pub fn hash(b: []const u8, out: []u8) void {
36 var d = Self.init();
37 d.update(b);
38 d.final(out);
39 }
3940
40 pub fn update(d: &Self, b: []const u8) void {
41 var ip: usize = 0;
42 var len = b.len;
43 var rate = d.rate - d.offset;
44 var offset = d.offset;
41 pub fn update(d: &Self, b: []const u8) void {
42 var ip: usize = 0;
43 var len = b.len;
44 var rate = d.rate - d.offset;
45 var offset = d.offset;
4546
46 // absorb
47 while (len >= rate) {
48 for (d.s[offset .. offset + rate]) |*r, i|
49 *r ^= b[ip..][i];
47 // absorb
48 while (len >= rate) {
49 for (d.s[offset..offset + rate]) |*r, i|
50 r.* ^= b[ip..][i];
5051
51 keccak_f(1600, d.s[0..]);
52 keccak_f(1600, d.s[0..]);
5253
53 ip += rate;
54 len -= rate;
55 rate = d.rate;
56 offset = 0;
57 }
54 ip += rate;
55 len -= rate;
56 rate = d.rate;
57 offset = 0;
58 }
5859
59 for (d.s[offset .. offset + len]) |*r, i|
60 *r ^= b[ip..][i];
60 for (d.s[offset..offset + len]) |*r, i|
61 r.* ^= b[ip..][i];
6162
62 d.offset = offset + len;
63 }
63 d.offset = offset + len;
64 }
6465
65 pub fn final(d: &Self, out: []u8) void {
66 // padding
67 d.s[d.offset] ^= delim;
68 d.s[d.rate - 1] ^= 0x80;
66 pub fn final(d: &Self, out: []u8) void {
67 // padding
68 d.s[d.offset] ^= delim;
69 d.s[d.rate - 1] ^= 0x80;
6970
70 keccak_f(1600, d.s[0..]);
71 keccak_f(1600, d.s[0..]);
7172
72 // squeeze
73 var op: usize = 0;
74 var len: usize = bits / 8;
73 // squeeze
74 var op: usize = 0;
75 var len: usize = bits / 8;
7576
76 while (len >= d.rate) {
77 mem.copy(u8, out[op..], d.s[0..d.rate]);
78 keccak_f(1600, d.s[0..]);
79 op += d.rate;
80 len -= d.rate;
77 while (len >= d.rate) {
78 mem.copy(u8, out[op..], d.s[0..d.rate]);
79 keccak_f(1600, d.s[0..]);
80 op += d.rate;
81 len -= d.rate;
82 }
83
84 mem.copy(u8, out[op..], d.s[0..len]);
8185 }
86 };
87}
8288
83 mem.copy(u8, out[op..], d.s[0..len]);
84 }
85};}
86
87const RC = []const u64 {
88 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
89 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
90 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
91 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
92 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
93 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
89const RC = []const u64{
90 0x0000000000000001,
91 0x0000000000008082,
92 0x800000000000808a,
93 0x8000000080008000,
94 0x000000000000808b,
95 0x0000000080000001,
96 0x8000000080008081,
97 0x8000000000008009,
98 0x000000000000008a,
99 0x0000000000000088,
100 0x0000000080008009,
101 0x000000008000000a,
102 0x000000008000808b,
103 0x800000000000008b,
104 0x8000000000008089,
105 0x8000000000008003,
106 0x8000000000008002,
107 0x8000000000000080,
108 0x000000000000800a,
109 0x800000008000000a,
110 0x8000000080008081,
111 0x8000000000008080,
112 0x0000000080000001,
113 0x8000000080008008,
94114};
95115
96const ROTC = []const usize {
97 1, 3, 6, 10, 15, 21, 28, 36,
98 45, 55, 2, 14, 27, 41, 56, 8,
99 25, 43, 62, 18, 39, 61, 20, 44
116const ROTC = []const usize{
117 1,
118 3,
119 6,
120 10,
121 15,
122 21,
123 28,
124 36,
125 45,
126 55,
127 2,
128 14,
129 27,
130 41,
131 56,
132 8,
133 25,
134 43,
135 62,
136 18,
137 39,
138 61,
139 20,
140 44,
100141};
101142
102const PIL = []const usize {
103 10, 7, 11, 17, 18, 3, 5, 16,
104 8, 21, 24, 4, 15, 23, 19, 13,
105 12, 2, 20, 14, 22, 9, 6, 1
143const PIL = []const usize{
144 10,
145 7,
146 11,
147 17,
148 18,
149 3,
150 5,
151 16,
152 8,
153 21,
154 24,
155 4,
156 15,
157 23,
158 19,
159 13,
160 12,
161 2,
162 20,
163 14,
164 22,
165 9,
166 6,
167 1,
106168};
107169
108const M5 = []const usize {
109 0, 1, 2, 3, 4, 0, 1, 2, 3, 4
170const M5 = []const usize{
171 0,
172 1,
173 2,
174 3,
175 4,
176 0,
177 1,
178 2,
179 3,
180 4,
110181};
111182
112183fn keccak_f(comptime F: usize, d: []u8) void {
113184 debug.assert(d.len == F / 8);
114185
115186 const B = F / 25;
116 const no_rounds = comptime x: { break :x 12 + 2 * math.log2(B); };
187 const no_rounds = comptime x: {
188 break :x 12 + 2 * math.log2(B);
189 };
117190
118 var s = []const u64 {0} ** 25;
119 var t = []const u64 {0} ** 1;
120 var c = []const u64 {0} ** 5;
191 var s = []const u64{0} ** 25;
192 var t = []const u64{0} ** 1;
193 var c = []const u64{0} ** 5;
121194
122195 for (s) |*r, i| {
123 *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]);
196 r.* = mem.readIntLE(u64, d[8 * i..8 * i + 8]);
124197 }
125198
126199 comptime var x: usize = 0;
127200 comptime var y: usize = 0;
128201 for (RC[0..no_rounds]) |round| {
129202 // theta
130 x = 0; inline while (x < 5) : (x += 1) {
131 c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20];
203 x = 0;
204 inline while (x < 5) : (x += 1) {
205 c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20];
132206 }
133 x = 0; inline while (x < 5) : (x += 1) {
134 t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1));
135 y = 0; inline while (y < 5) : (y += 1) {
136 s[x + y*5] ^= t[0];
207 x = 0;
208 inline while (x < 5) : (x += 1) {
209 t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], usize(1));
210 y = 0;
211 inline while (y < 5) : (y += 1) {
212 s[x + y * 5] ^= t[0];
137213 }
138214 }
139215
140216 // rho+pi
141217 t[0] = s[1];
142 x = 0; inline while (x < 24) : (x += 1) {
218 x = 0;
219 inline while (x < 24) : (x += 1) {
143220 c[0] = s[PIL[x]];
144221 s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]);
145222 t[0] = c[0];
146223 }
147224
148225 // chi
149 y = 0; inline while (y < 5) : (y += 1) {
150 x = 0; inline while (x < 5) : (x += 1) {
151 c[x] = s[x + y*5];
226 y = 0;
227 inline while (y < 5) : (y += 1) {
228 x = 0;
229 inline while (x < 5) : (x += 1) {
230 c[x] = s[x + y * 5];
152231 }
153 x = 0; inline while (x < 5) : (x += 1) {
154 s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]);
232 x = 0;
233 inline while (x < 5) : (x += 1) {
234 s[x + y * 5] = c[x] ^ (~c[M5[x + 1]] & c[M5[x + 2]]);
155235 }
156236 }
157237
......@@ -160,11 +240,10 @@ fn keccak_f(comptime F: usize, d: []u8) void {
160240 }
161241
162242 for (s) |r, i| {
163 mem.writeInt(d[8*i .. 8*i + 8], r, builtin.Endian.Little);
243 mem.writeInt(d[8 * i..8 * i + 8], r, builtin.Endian.Little);
164244 }
165245}
166246
167
168247test "sha3-224 single" {
169248 htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", "");
170249 htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc");
......@@ -192,7 +271,7 @@ test "sha3-224 streaming" {
192271}
193272
194273test "sha3-256 single" {
195 htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , "");
274 htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", "");
196275 htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc");
197276 htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
198277}
......@@ -218,7 +297,7 @@ test "sha3-256 streaming" {
218297}
219298
220299test "sha3-256 aligned final" {
221 var block = []u8 {0} ** Sha3_256.block_size;
300 var block = []u8{0} ** Sha3_256.block_size;
222301 var out: [Sha3_256.digest_size]u8 = undefined;
223302
224303 var h = Sha3_256.init();
......@@ -228,7 +307,7 @@ test "sha3-256 aligned final" {
228307
229308test "sha3-384 single" {
230309 const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";
231 htest.assertEqualHash(Sha3_384, h1 , "");
310 htest.assertEqualHash(Sha3_384, h1, "");
232311 const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";
233312 htest.assertEqualHash(Sha3_384, h2, "abc");
234313 const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7";
......@@ -259,7 +338,7 @@ test "sha3-384 streaming" {
259338
260339test "sha3-512 single" {
261340 const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";
262 htest.assertEqualHash(Sha3_512, h1 , "");
341 htest.assertEqualHash(Sha3_512, h1, "");
263342 const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";
264343 htest.assertEqualHash(Sha3_512, h2, "abc");
265344 const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185";
......@@ -289,7 +368,7 @@ test "sha3-512 streaming" {
289368}
290369
291370test "sha3-512 aligned final" {
292 var block = []u8 {0} ** Sha3_512.block_size;
371 var block = []u8{0} ** Sha3_512.block_size;
293372 var out: [Sha3_512.digest_size]u8 = undefined;
294373
295374 var h = Sha3_512.init();
std/crypto/test.zig+1-2
......@@ -14,9 +14,8 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu
1414pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
1515 var expected_bytes: [expected.len / 2]u8 = undefined;
1616 for (expected_bytes) |*r, i| {
17 *r = fmt.parseInt(u8, expected[2*i .. 2*i+2], 16) catch unreachable;
17 r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;
1818 }
1919
2020 debug.assert(mem.eql(u8, expected_bytes, input));
2121}
22
std/debug/index.zig+98-135
......@@ -104,9 +104,7 @@ pub fn panic(comptime format: []const u8, args: ...) noreturn {
104104
105105var panicking: u8 = 0; // TODO make this a bool
106106
107pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize,
108 comptime format: []const u8, args: ...) noreturn
109{
107pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn {
110108 @setCold(true);
111109
112110 if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
......@@ -132,9 +130,7 @@ const WHITE = "\x1b[37;1m";
132130const DIM = "\x1b[2m";
133131const RESET = "\x1b[0m";
134132
135pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator,
136 debug_info: &ElfStackTrace, tty_color: bool) !void
137{
133pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool) !void {
138134 var frame_index: usize = undefined;
139135 var frames_left: usize = undefined;
140136 if (stack_trace.index < stack_trace.instruction_addresses.len) {
......@@ -154,9 +150,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var,
154150 }
155151}
156152
157pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
158 debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void
159{
153pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void {
160154 const AddressState = union(enum) {
161155 NotLookingForStartAddress,
162156 LookingForStartAddress: usize,
......@@ -166,14 +160,14 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
166160 // else AddressState.NotLookingForStartAddress;
167161 var addr_state: AddressState = undefined;
168162 if (start_addr) |addr| {
169 addr_state = AddressState { .LookingForStartAddress = addr };
163 addr_state = AddressState{ .LookingForStartAddress = addr };
170164 } else {
171165 addr_state = AddressState.NotLookingForStartAddress;
172166 }
173167
174168 var fp = @ptrToInt(@frameAddress());
175 while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) {
176 const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize));
169 while (fp != 0) : (fp = @intToPtr(&const usize, fp).*) {
170 const return_address = @intToPtr(&const usize, fp + @sizeOf(usize)).*;
177171
178172 switch (addr_state) {
179173 AddressState.NotLookingForStartAddress => {},
......@@ -200,32 +194,32 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us
200194 // in practice because the compiler dumps everything in a single
201195 // object file. Future improvement: use external dSYM data when
202196 // available.
203 const unknown = macho.Symbol { .name = "???", .address = address };
197 const unknown = macho.Symbol{
198 .name = "???",
199 .address = address,
200 };
204201 const symbol = debug_info.symbol_table.search(address) ?? &unknown;
205 try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++
206 DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n",
207 symbol.name, address);
202 try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n", symbol.name, address);
208203 },
209204 else => {
210205 const compile_unit = findCompileUnit(debug_info, address) catch {
211 try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n",
212 address);
206 try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", address);
213207 return;
214208 };
215209 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
216210 if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| {
217211 defer line_info.deinit();
218 try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++
219 DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n",
220 line_info.file_name, line_info.line, line_info.column,
221 address, compile_unit_name);
212 try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", line_info.file_name, line_info.line, line_info.column, address, compile_unit_name);
222213 if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) {
223214 if (line_info.column == 0) {
224215 try out_stream.write("\n");
225216 } else {
226 {var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) {
227 try out_stream.writeByte(' ');
228 }}
217 {
218 var col_i: usize = 1;
219 while (col_i < line_info.column) : (col_i += 1) {
220 try out_stream.writeByte(' ');
221 }
222 }
229223 try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
230224 }
231225 } else |err| switch (err) {
......@@ -233,7 +227,8 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us
233227 else => return err,
234228 }
235229 } else |err| switch (err) {
236 error.MissingDebugInfo, error.InvalidDebugInfo => {
230 error.MissingDebugInfo,
231 error.InvalidDebugInfo => {
237232 try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name);
238233 },
239234 else => return err,
......@@ -247,7 +242,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace {
247242 builtin.ObjectFormat.elf => {
248243 const st = try allocator.create(ElfStackTrace);
249244 errdefer allocator.destroy(st);
250 *st = ElfStackTrace {
245 st.* = ElfStackTrace{
251246 .self_exe_file = undefined,
252247 .elf = undefined,
253248 .debug_info = undefined,
......@@ -279,9 +274,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace {
279274 const st = try allocator.create(ElfStackTrace);
280275 errdefer allocator.destroy(st);
281276
282 *st = ElfStackTrace {
283 .symbol_table = try macho.loadSymbols(allocator, &io.FileInStream.init(&exe_file)),
284 };
277 st.* = ElfStackTrace{ .symbol_table = try macho.loadSymbols(allocator, &io.FileInStream.init(&exe_file)) };
285278
286279 return st;
287280 },
......@@ -325,8 +318,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: var, line_info: &con
325318 }
326319 }
327320
328 if (amt_read < buf.len)
329 return error.EndOfFile;
321 if (amt_read < buf.len) return error.EndOfFile;
330322 }
331323}
332324
......@@ -418,10 +410,8 @@ const Constant = struct {
418410 signed: bool,
419411
420412 fn asUnsignedLe(self: &const Constant) !u64 {
421 if (self.payload.len > @sizeOf(u64))
422 return error.InvalidDebugInfo;
423 if (self.signed)
424 return error.InvalidDebugInfo;
413 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
414 if (self.signed) return error.InvalidDebugInfo;
425415 return mem.readInt(self.payload, u64, builtin.Endian.Little);
426416 }
427417};
......@@ -438,15 +428,14 @@ const Die = struct {
438428
439429 fn getAttr(self: &const Die, id: u64) ?&const FormValue {
440430 for (self.attrs.toSliceConst()) |*attr| {
441 if (attr.id == id)
442 return &attr.value;
431 if (attr.id == id) return &attr.value;
443432 }
444433 return null;
445434 }
446435
447436 fn getAttrAddr(self: &const Die, id: u64) !u64 {
448437 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
449 return switch (*form_value) {
438 return switch (form_value.*) {
450439 FormValue.Address => |value| value,
451440 else => error.InvalidDebugInfo,
452441 };
......@@ -454,7 +443,7 @@ const Die = struct {
454443
455444 fn getAttrSecOffset(self: &const Die, id: u64) !u64 {
456445 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
457 return switch (*form_value) {
446 return switch (form_value.*) {
458447 FormValue.Const => |value| value.asUnsignedLe(),
459448 FormValue.SecOffset => |value| value,
460449 else => error.InvalidDebugInfo,
......@@ -463,7 +452,7 @@ const Die = struct {
463452
464453 fn getAttrUnsignedLe(self: &const Die, id: u64) !u64 {
465454 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
466 return switch (*form_value) {
455 return switch (form_value.*) {
467456 FormValue.Const => |value| value.asUnsignedLe(),
468457 else => error.InvalidDebugInfo,
469458 };
......@@ -471,7 +460,7 @@ const Die = struct {
471460
472461 fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) ![]u8 {
473462 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
474 return switch (*form_value) {
463 return switch (form_value.*) {
475464 FormValue.String => |value| value,
476465 FormValue.StrPtr => |offset| getString(st, offset),
477466 else => error.InvalidDebugInfo,
......@@ -518,10 +507,8 @@ const LineNumberProgram = struct {
518507 prev_basic_block: bool,
519508 prev_end_sequence: bool,
520509
521 pub fn init(is_stmt: bool, include_dirs: []const []const u8,
522 file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram
523 {
524 return LineNumberProgram {
510 pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram {
511 return LineNumberProgram{
525512 .address = 0,
526513 .file = 1,
527514 .line = 1,
......@@ -548,14 +535,16 @@ const LineNumberProgram = struct {
548535 return error.MissingDebugInfo;
549536 } else if (self.prev_file - 1 >= self.file_entries.len) {
550537 return error.InvalidDebugInfo;
551 } else &self.file_entries.items[self.prev_file - 1];
538 } else
539 &self.file_entries.items[self.prev_file - 1];
552540
553541 const dir_name = if (file_entry.dir_index >= self.include_dirs.len) {
554542 return error.InvalidDebugInfo;
555 } else self.include_dirs[file_entry.dir_index];
543 } else
544 self.include_dirs[file_entry.dir_index];
556545 const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
557546 errdefer self.file_entries.allocator.free(file_name);
558 return LineInfo {
547 return LineInfo{
559548 .line = if (self.prev_line >= 0) usize(self.prev_line) else 0,
560549 .column = self.prev_column,
561550 .file_name = file_name,
......@@ -578,8 +567,7 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: var) ![]u8 {
578567 var buf = ArrayList(u8).init(allocator);
579568 while (true) {
580569 const byte = try in_stream.readByte();
581 if (byte == 0)
582 break;
570 if (byte == 0) break;
583571 try buf.append(byte);
584572 }
585573 return buf.toSlice();
......@@ -600,7 +588,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8
600588
601589fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
602590 const buf = try readAllocBytes(allocator, in_stream, size);
603 return FormValue { .Block = buf };
591 return FormValue{ .Block = buf };
604592}
605593
606594fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
......@@ -609,26 +597,23 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !
609597}
610598
611599fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
612 return FormValue { .Const = Constant {
600 return FormValue{ .Const = Constant{
613601 .signed = signed,
614602 .payload = try readAllocBytes(allocator, in_stream, size),
615 }};
603 } };
616604}
617605
618606fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
619 return if (is_64) try in_stream.readIntLe(u64)
620 else u64(try in_stream.readIntLe(u32)) ;
607 return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));
621608}
622609
623610fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
624 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32))
625 else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64)
626 else unreachable;
611 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;
627612}
628613
629614fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
630615 const buf = try readAllocBytes(allocator, in_stream, size);
631 return FormValue { .Ref = buf };
616 return FormValue{ .Ref = buf };
632617}
633618
634619fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type) !FormValue {
......@@ -646,11 +631,9 @@ const ParseFormValueError = error {
646631 OutOfMemory,
647632};
648633
649fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool)
650 ParseFormValueError!FormValue
651{
634fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue {
652635 return switch (form_id) {
653 DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) },
636 DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
654637 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
655638 DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
656639 DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
......@@ -662,7 +645,8 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
662645 DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
663646 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
664647 DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
665 DW.FORM_udata, DW.FORM_sdata => {
648 DW.FORM_udata,
649 DW.FORM_sdata => {
666650 const block_len = try readULeb128(in_stream);
667651 const signed = form_id == DW.FORM_sdata;
668652 return parseFormValueConstant(allocator, in_stream, signed, block_len);
......@@ -670,11 +654,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
670654 DW.FORM_exprloc => {
671655 const size = try readULeb128(in_stream);
672656 const buf = try readAllocBytes(allocator, in_stream, size);
673 return FormValue { .ExprLoc = buf };
657 return FormValue{ .ExprLoc = buf };
674658 },
675 DW.FORM_flag => FormValue { .Flag = (try in_stream.readByte()) != 0 },
676 DW.FORM_flag_present => FormValue { .Flag = true },
677 DW.FORM_sec_offset => FormValue { .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
659 DW.FORM_flag => FormValue{ .Flag = (try in_stream.readByte()) != 0 },
660 DW.FORM_flag_present => FormValue{ .Flag = true },
661 DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
678662
679663 DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
680664 DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
......@@ -685,11 +669,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
685669 return parseFormValueRefLen(allocator, in_stream, ref_len);
686670 },
687671
688 DW.FORM_ref_addr => FormValue { .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
689 DW.FORM_ref_sig8 => FormValue { .RefSig8 = try in_stream.readIntLe(u64) },
672 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
673 DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },
690674
691 DW.FORM_string => FormValue { .String = try readStringRaw(allocator, in_stream) },
692 DW.FORM_strp => FormValue { .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
675 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
676 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
693677 DW.FORM_indirect => {
694678 const child_form_id = try readULeb128(in_stream);
695679 return parseFormValue(allocator, in_stream, child_form_id, is_64);
......@@ -705,9 +689,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable {
705689 var result = AbbrevTable.init(st.allocator());
706690 while (true) {
707691 const abbrev_code = try readULeb128(in_stream);
708 if (abbrev_code == 0)
709 return result;
710 try result.append(AbbrevTableEntry {
692 if (abbrev_code == 0) return result;
693 try result.append(AbbrevTableEntry{
711694 .abbrev_code = abbrev_code,
712695 .tag_id = try readULeb128(in_stream),
713696 .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes,
......@@ -718,9 +701,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable {
718701 while (true) {
719702 const attr_id = try readULeb128(in_stream);
720703 const form_id = try readULeb128(in_stream);
721 if (attr_id == 0 and form_id == 0)
722 break;
723 try attrs.append(AbbrevAttr {
704 if (attr_id == 0 and form_id == 0) break;
705 try attrs.append(AbbrevAttr{
724706 .attr_id = attr_id,
725707 .form_id = form_id,
726708 });
......@@ -737,7 +719,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable {
737719 }
738720 }
739721 try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset);
740 try st.abbrev_table_list.append(AbbrevTableHeader {
722 try st.abbrev_table_list.append(AbbrevTableHeader{
741723 .offset = abbrev_offset,
742724 .table = try parseAbbrevTable(st),
743725 });
......@@ -746,8 +728,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable {
746728
747729fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&const AbbrevTableEntry {
748730 for (abbrev_table.toSliceConst()) |*table_entry| {
749 if (table_entry.abbrev_code == abbrev_code)
750 return table_entry;
731 if (table_entry.abbrev_code == abbrev_code) return table_entry;
751732 }
752733 return null;
753734}
......@@ -759,14 +740,14 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) !
759740 const abbrev_code = try readULeb128(in_stream);
760741 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo;
761742
762 var result = Die {
743 var result = Die{
763744 .tag_id = table_entry.tag_id,
764745 .has_children = table_entry.has_children,
765746 .attrs = ArrayList(Die.Attr).init(st.allocator()),
766747 };
767748 try result.attrs.resize(table_entry.attrs.len);
768749 for (table_entry.attrs.toSliceConst()) |attr, i| {
769 result.attrs.items[i] = Die.Attr {
750 result.attrs.items[i] = Die.Attr{
770751 .id = attr.attr_id,
771752 .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),
772753 };
......@@ -790,8 +771,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
790771
791772 var is_64: bool = undefined;
792773 const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
793 if (unit_length == 0)
794 return error.MissingDebugInfo;
774 if (unit_length == 0) return error.MissingDebugInfo;
795775 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
796776
797777 if (compile_unit.index != this_index) {
......@@ -803,8 +783,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
803783 // TODO support 3 and 5
804784 if (version != 2 and version != 4) return error.InvalidDebugInfo;
805785
806 const prologue_length = if (is_64) try in_stream.readInt(st.elf.endian, u64)
807 else try in_stream.readInt(st.elf.endian, u32);
786 const prologue_length = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32);
808787 const prog_start_offset = (try in_file.getPos()) + prologue_length;
809788
810789 const minimum_instruction_length = try in_stream.readByte();
......@@ -819,38 +798,37 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
819798 const line_base = try in_stream.readByteSigned();
820799
821800 const line_range = try in_stream.readByte();
822 if (line_range == 0)
823 return error.InvalidDebugInfo;
801 if (line_range == 0) return error.InvalidDebugInfo;
824802
825803 const opcode_base = try in_stream.readByte();
826804
827805 const standard_opcode_lengths = try st.allocator().alloc(u8, opcode_base - 1);
828806
829 {var i: usize = 0; while (i < opcode_base - 1) : (i += 1) {
830 standard_opcode_lengths[i] = try in_stream.readByte();
831 }}
807 {
808 var i: usize = 0;
809 while (i < opcode_base - 1) : (i += 1) {
810 standard_opcode_lengths[i] = try in_stream.readByte();
811 }
812 }
832813
833814 var include_directories = ArrayList([]u8).init(st.allocator());
834815 try include_directories.append(compile_unit_cwd);
835816 while (true) {
836817 const dir = try st.readString();
837 if (dir.len == 0)
838 break;
818 if (dir.len == 0) break;
839819 try include_directories.append(dir);
840820 }
841821
842822 var file_entries = ArrayList(FileEntry).init(st.allocator());
843 var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(),
844 &file_entries, target_address);
823 var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
845824
846825 while (true) {
847826 const file_name = try st.readString();
848 if (file_name.len == 0)
849 break;
827 if (file_name.len == 0) break;
850828 const dir_index = try readULeb128(in_stream);
851829 const mtime = try readULeb128(in_stream);
852830 const len_bytes = try readULeb128(in_stream);
853 try file_entries.append(FileEntry {
831 try file_entries.append(FileEntry{
854832 .file_name = file_name,
855833 .dir_index = dir_index,
856834 .mtime = mtime,
......@@ -866,8 +844,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
866844 var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash
867845 if (opcode == DW.LNS_extended_op) {
868846 const op_size = try readULeb128(in_stream);
869 if (op_size < 1)
870 return error.InvalidDebugInfo;
847 if (op_size < 1) return error.InvalidDebugInfo;
871848 sub_op = try in_stream.readByte();
872849 switch (sub_op) {
873850 DW.LNE_end_sequence => {
......@@ -884,7 +861,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
884861 const dir_index = try readULeb128(in_stream);
885862 const mtime = try readULeb128(in_stream);
886863 const len_bytes = try readULeb128(in_stream);
887 try file_entries.append(FileEntry {
864 try file_entries.append(FileEntry{
888865 .file_name = file_name,
889866 .dir_index = dir_index,
890867 .mtime = mtime,
......@@ -941,11 +918,9 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
941918 const arg = try in_stream.readInt(st.elf.endian, u16);
942919 prog.address += arg;
943920 },
944 DW.LNS_set_prologue_end => {
945 },
921 DW.LNS_set_prologue_end => {},
946922 else => {
947 if (opcode - 1 >= standard_opcode_lengths.len)
948 return error.InvalidDebugInfo;
923 if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
949924 const len_bytes = standard_opcode_lengths[opcode - 1];
950925 try in_file.seekForward(len_bytes);
951926 },
......@@ -972,16 +947,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
972947
973948 var is_64: bool = undefined;
974949 const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
975 if (unit_length == 0)
976 return;
950 if (unit_length == 0) return;
977951 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
978952
979953 const version = try in_stream.readInt(st.elf.endian, u16);
980954 if (version < 2 or version > 5) return error.InvalidDebugInfo;
981955
982 const debug_abbrev_offset =
983 if (is_64) try in_stream.readInt(st.elf.endian, u64)
984 else try in_stream.readInt(st.elf.endian, u32);
956 const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32);
985957
986958 const address_size = try in_stream.readByte();
987959 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
......@@ -992,15 +964,14 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
992964 try st.self_exe_file.seekTo(compile_unit_pos);
993965
994966 const compile_unit_die = try st.allocator().create(Die);
995 *compile_unit_die = try parseDie(st, abbrev_table, is_64);
967 compile_unit_die.* = try parseDie(st, abbrev_table, is_64);
996968
997 if (compile_unit_die.tag_id != DW.TAG_compile_unit)
998 return error.InvalidDebugInfo;
969 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
999970
1000971 const pc_range = x: {
1001972 if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| {
1002973 if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| {
1003 const pc_end = switch (*high_pc_value) {
974 const pc_end = switch (high_pc_value.*) {
1004975 FormValue.Address => |value| value,
1005976 FormValue.Const => |value| b: {
1006977 const offset = try value.asUnsignedLe();
......@@ -1008,7 +979,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
1008979 },
1009980 else => return error.InvalidDebugInfo,
1010981 };
1011 break :x PcRange {
982 break :x PcRange{
1012983 .start = low_pc,
1013984 .end = pc_end,
1014985 };
......@@ -1016,13 +987,12 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
1016987 break :x null;
1017988 }
1018989 } else |err| {
1019 if (err != error.MissingDebugInfo)
1020 return err;
990 if (err != error.MissingDebugInfo) return err;
1021991 break :x null;
1022992 }
1023993 };
1024994
1025 try st.compile_unit_list.append(CompileUnit {
995 try st.compile_unit_list.append(CompileUnit{
1026996 .version = version,
1027997 .is_64 = is_64,
1028998 .pc_range = pc_range,
......@@ -1040,8 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
10401010 const in_stream = &in_file_stream.stream;
10411011 for (st.compile_unit_list.toSlice()) |*compile_unit| {
10421012 if (compile_unit.pc_range) |range| {
1043 if (target_address >= range.start and target_address < range.end)
1044 return compile_unit;
1013 if (target_address >= range.start and target_address < range.end) return compile_unit;
10451014 }
10461015 if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
10471016 var base_address: usize = 0;
......@@ -1063,8 +1032,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
10631032 }
10641033 }
10651034 } else |err| {
1066 if (err != error.MissingDebugInfo)
1067 return err;
1035 if (err != error.MissingDebugInfo) return err;
10681036 continue;
10691037 }
10701038 }
......@@ -1073,8 +1041,8 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
10731041
10741042fn readInitialLength(comptime E: type, in_stream: &io.InStream(E), is_64: &bool) !u64 {
10751043 const first_32_bits = try in_stream.readIntLe(u32);
1076 *is_64 = (first_32_bits == 0xffffffff);
1077 if (*is_64) {
1044 is_64.* = (first_32_bits == 0xffffffff);
1045 if (is_64.*) {
10781046 return in_stream.readIntLe(u64);
10791047 } else {
10801048 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
......@@ -1091,13 +1059,11 @@ fn readULeb128(in_stream: var) !u64 {
10911059
10921060 var operand: u64 = undefined;
10931061
1094 if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand))
1095 return error.InvalidDebugInfo;
1062 if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo;
10961063
10971064 result |= operand;
10981065
1099 if ((byte & 0b10000000) == 0)
1100 return result;
1066 if ((byte & 0b10000000) == 0) return result;
11011067
11021068 shift += 7;
11031069 }
......@@ -1112,15 +1078,13 @@ fn readILeb128(in_stream: var) !i64 {
11121078
11131079 var operand: i64 = undefined;
11141080
1115 if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand))
1116 return error.InvalidDebugInfo;
1081 if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo;
11171082
11181083 result |= operand;
11191084 shift += 7;
11201085
11211086 if ((byte & 0b10000000) == 0) {
1122 if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0)
1123 result |= -(i64(1) << u6(shift));
1087 if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << u6(shift));
11241088 return result;
11251089 }
11261090 }
......@@ -1131,7 +1095,6 @@ pub const global_allocator = &global_fixed_allocator.allocator;
11311095var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]);
11321096var global_allocator_mem: [100 * 1024]u8 = undefined;
11331097
1134
11351098// TODO make thread safe
11361099var debug_info_allocator: ?&mem.Allocator = null;
11371100var debug_info_direct_allocator: std.heap.DirectAllocator = undefined;
std/event.zig+20-33
......@@ -6,7 +6,7 @@ const mem = std.mem;
66const posix = std.os.posix;
77
88pub const TcpServer = struct {
9 handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File) void,
9 handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void,
1010
1111 loop: &Loop,
1212 sockfd: i32,
......@@ -18,13 +18,11 @@ pub const TcpServer = struct {
1818 const PromiseNode = std.LinkedList(promise).Node;
1919
2020 pub fn init(loop: &Loop) !TcpServer {
21 const sockfd = try std.os.posixSocket(posix.AF_INET,
22 posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK,
23 posix.PROTO_tcp);
21 const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
2422 errdefer std.os.close(sockfd);
2523
2624 // TODO can't initialize handler coroutine here because we need well defined copy elision
27 return TcpServer {
25 return TcpServer{
2826 .loop = loop,
2927 .sockfd = sockfd,
3028 .accept_coro = null,
......@@ -34,9 +32,7 @@ pub const TcpServer = struct {
3432 };
3533 }
3634
37 pub fn listen(self: &TcpServer, address: &const std.net.Address,
38 handleRequestFn: async<&mem.Allocator> fn (&TcpServer, &const std.net.Address, &const std.os.File)void) !void
39 {
35 pub fn listen(self: &TcpServer, address: &const std.net.Address, handleRequestFn: async<&mem.Allocator> fn(&TcpServer, &const std.net.Address, &const std.os.File) void) !void {
4036 self.handleRequestFn = handleRequestFn;
4137
4238 try std.os.posixBind(self.sockfd, &address.os_addr);
......@@ -48,7 +44,6 @@ pub const TcpServer = struct {
4844
4945 try self.loop.addFd(self.sockfd, ??self.accept_coro);
5046 errdefer self.loop.removeFd(self.sockfd);
51
5247 }
5348
5449 pub fn deinit(self: &TcpServer) void {
......@@ -60,9 +55,7 @@ pub const TcpServer = struct {
6055 pub async fn handler(self: &TcpServer) void {
6156 while (true) {
6257 var accepted_addr: std.net.Address = undefined;
63 if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr,
64 posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd|
65 {
58 if (std.os.posixAccept(self.sockfd, &accepted_addr.os_addr, posix.SOCK_NONBLOCK | posix.SOCK_CLOEXEC)) |accepted_fd| {
6659 var socket = std.os.File.openHandle(accepted_fd);
6760 _ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) {
6861 error.OutOfMemory => {
......@@ -110,7 +103,7 @@ pub const Loop = struct {
110103
111104 fn init(allocator: &mem.Allocator) !Loop {
112105 const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC);
113 return Loop {
106 return Loop{
114107 .keep_running = true,
115108 .allocator = allocator,
116109 .epollfd = epollfd,
......@@ -118,11 +111,9 @@ pub const Loop = struct {
118111 }
119112
120113 pub fn addFd(self: &Loop, fd: i32, prom: promise) !void {
121 var ev = std.os.linux.epoll_event {
122 .events = std.os.linux.EPOLLIN|std.os.linux.EPOLLOUT|std.os.linux.EPOLLET,
123 .data = std.os.linux.epoll_data {
124 .ptr = @ptrToInt(prom),
125 },
114 var ev = std.os.linux.epoll_event{
115 .events = std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET,
116 .data = std.os.linux.epoll_data{ .ptr = @ptrToInt(prom) },
126117 };
127118 try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev);
128119 }
......@@ -157,9 +148,9 @@ pub const Loop = struct {
157148};
158149
159150pub async fn connect(loop: &Loop, _address: &const std.net.Address) !std.os.File {
160 var address = *_address; // TODO https://github.com/zig-lang/zig/issues/733
151 var address = _address.*; // TODO https://github.com/ziglang/zig/issues/733
161152
162 const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM|posix.SOCK_CLOEXEC|posix.SOCK_NONBLOCK, posix.PROTO_tcp);
153 const sockfd = try std.os.posixSocket(posix.AF_INET, posix.SOCK_STREAM | posix.SOCK_CLOEXEC | posix.SOCK_NONBLOCK, posix.PROTO_tcp);
163154 errdefer std.os.close(sockfd);
164155
165156 try std.os.posixConnectAsync(sockfd, &address.os_addr);
......@@ -179,11 +170,9 @@ test "listen on a port, send bytes, receive bytes" {
179170
180171 const Self = this;
181172
182 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address,
183 _socket: &const std.os.File) void
184 {
173 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void {
185174 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
186 var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
175 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
187176 defer socket.close();
188177 const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) {
189178 error.OutOfMemory => @panic("unable to handle connection: out of memory"),
......@@ -191,14 +180,14 @@ test "listen on a port, send bytes, receive bytes" {
191180 (await next_handler) catch |err| {
192181 std.debug.panic("unable to handle connection: {}\n", err);
193182 };
194 suspend |p| { cancel p; }
183 suspend |p| {
184 cancel p;
185 }
195186 }
196187
197 async fn errorableHandler(self: &Self, _addr: &const std.net.Address,
198 _socket: &const std.os.File) !void
199 {
200 const addr = *_addr; // TODO https://github.com/zig-lang/zig/issues/733
201 var socket = *_socket; // TODO https://github.com/zig-lang/zig/issues/733
188 async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void {
189 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733
190 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
202191
203192 var adapter = std.io.FileOutStream.init(&socket);
204193 var stream = &adapter.stream;
......@@ -210,9 +199,7 @@ test "listen on a port, send bytes, receive bytes" {
210199 const addr = std.net.Address.initIp4(ip4addr, 0);
211200
212201 var loop = try Loop.init(std.debug.global_allocator);
213 var server = MyServer {
214 .tcp_server = try TcpServer.init(&loop),
215 };
202 var server = MyServer{ .tcp_server = try TcpServer.init(&loop) };
216203 defer server.tcp_server.deinit();
217204 try server.tcp_server.listen(addr, MyServer.handler);
218205
std/fmt/errol/index.zig+22-32
......@@ -86,7 +86,7 @@ pub fn errol3(value: f64, buffer: []u8) FloatDecimal {
8686 const data = enum3_data[i];
8787 const digits = buffer[1..data.str.len + 1];
8888 mem.copy(u8, digits, data.str);
89 return FloatDecimal {
89 return FloatDecimal{
9090 .digits = digits,
9191 .exp = data.exp,
9292 };
......@@ -105,7 +105,6 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
105105 return errolFixed(val, buffer);
106106 }
107107
108
109108 // normalize the midpoint
110109
111110 const e = math.frexp(val).exponent;
......@@ -137,11 +136,11 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
137136 }
138137
139138 // compute boundaries
140 var high = HP {
139 var high = HP{
141140 .val = mid.val,
142141 .off = mid.off + (fpnext(val) - val) * lten * ten / 2.0,
143142 };
144 var low = HP {
143 var low = HP{
145144 .val = mid.val,
146145 .off = mid.off + (fpprev(val) - val) * lten * ten / 2.0,
147146 };
......@@ -171,15 +170,12 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
171170 var buf_index: usize = 1;
172171 while (true) {
173172 var hdig = u8(math.floor(high.val));
174 if ((high.val == f64(hdig)) and (high.off < 0))
175 hdig -= 1;
173 if ((high.val == f64(hdig)) and (high.off < 0)) hdig -= 1;
176174
177175 var ldig = u8(math.floor(low.val));
178 if ((low.val == f64(ldig)) and (low.off < 0))
179 ldig -= 1;
176 if ((low.val == f64(ldig)) and (low.off < 0)) ldig -= 1;
180177
181 if (ldig != hdig)
182 break;
178 if (ldig != hdig) break;
183179
184180 buffer[buf_index] = hdig + '0';
185181 buf_index += 1;
......@@ -191,13 +187,12 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
191187
192188 const tmp = (high.val + low.val) / 2.0;
193189 var mdig = u8(math.floor(tmp + 0.5));
194 if ((f64(mdig) - tmp) == 0.5 and (mdig & 0x1) != 0)
195 mdig -= 1;
190 if ((f64(mdig) - tmp) == 0.5 and (mdig & 0x1) != 0) mdig -= 1;
196191
197192 buffer[buf_index] = mdig + '0';
198193 buf_index += 1;
199194
200 return FloatDecimal {
195 return FloatDecimal{
201196 .digits = buffer[1..buf_index],
202197 .exp = exp,
203198 };
......@@ -235,7 +230,7 @@ fn hpProd(in: &const HP, val: f64) HP {
235230 const p = in.val * val;
236231 const e = ((hi * hi2 - p) + lo * hi2 + hi * lo2) + lo * lo2;
237232
238 return HP {
233 return HP{
239234 .val = p,
240235 .off = in.off * val + e,
241236 };
......@@ -246,8 +241,8 @@ fn hpProd(in: &const HP, val: f64) HP {
246241/// @hi: The high bits.
247242/// @lo: The low bits.
248243fn split(val: f64, hi: &f64, lo: &f64) void {
249 *hi = gethi(val);
250 *lo = val - *hi;
244 hi.* = gethi(val);
245 lo.* = val - hi.*;
251246}
252247
253248fn gethi(in: f64) f64 {
......@@ -301,7 +296,6 @@ fn hpMul10(hp: &HP) void {
301296 hpNormalize(hp);
302297}
303298
304
305299/// Integer conversion algorithm, guaranteed correct, optimal, and best.
306300/// @val: The val.
307301/// @buf: The output buffer.
......@@ -343,8 +337,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
343337 }
344338 const m64 = @truncate(u64, @divTrunc(mid, x));
345339
346 if (lf != hf)
347 mi += 19;
340 if (lf != hf) mi += 19;
348341
349342 var buf_index = u64toa(m64, buffer) - 1;
350343
......@@ -354,7 +347,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
354347 buf_index += 1;
355348 }
356349
357 return FloatDecimal {
350 return FloatDecimal{
358351 .digits = buffer[0..buf_index],
359352 .exp = i32(buf_index) + mi,
360353 };
......@@ -396,25 +389,24 @@ fn errolFixed(val: f64, buffer: []u8) FloatDecimal {
396389 buffer[j] = u8(mdig + '0');
397390 j += 1;
398391
399 if(hdig != ldig or j > 50)
400 break;
392 if (hdig != ldig or j > 50) break;
401393 }
402394
403395 if (mid > 0.5) {
404 buffer[j-1] += 1;
405 } else if ((mid == 0.5) and (buffer[j-1] & 0x1) != 0) {
406 buffer[j-1] += 1;
396 buffer[j - 1] += 1;
397 } else if ((mid == 0.5) and (buffer[j - 1] & 0x1) != 0) {
398 buffer[j - 1] += 1;
407399 }
408400 } else {
409 while (buffer[j-1] == '0') {
410 buffer[j-1] = 0;
401 while (buffer[j - 1] == '0') {
402 buffer[j - 1] = 0;
411403 j -= 1;
412404 }
413405 }
414406
415407 buffer[j] = 0;
416408
417 return FloatDecimal {
409 return FloatDecimal{
418410 .digits = buffer[0..j],
419411 .exp = exp,
420412 };
......@@ -587,7 +579,7 @@ fn u64toa(value_param: u64, buffer: []u8) usize {
587579 buffer[buf_index] = c_digits_lut[d8 + 1];
588580 buf_index += 1;
589581 } else {
590 const a = u32(value / kTen16); // 1 to 1844
582 const a = u32(value / kTen16); // 1 to 1844
591583 value %= kTen16;
592584
593585 if (a < 10) {
......@@ -686,7 +678,6 @@ fn fpeint(from: f64) u128 {
686678 return u128(1) << @truncate(u7, (bits >> 52) -% 1023);
687679}
688680
689
690681/// Given two different integers with the same length in terms of the number
691682/// of decimal digits, index the digits from the right-most position starting
692683/// from zero, find the first index where the digits in the two integers
......@@ -713,7 +704,6 @@ fn mismatch10(a: u64, b: u64) i32 {
713704 a_copy /= 10;
714705 b_copy /= 10;
715706
716 if (a_copy == b_copy)
717 return i;
707 if (a_copy == b_copy) return i;
718708 }
719709}
std/fmt/index.zig+137-67
......@@ -11,9 +11,7 @@ const max_int_digits = 65;
1111/// Renders fmt string with args, calling output with slices of bytes.
1212/// If `output` returns an error, the error is returned from `format` and
1313/// `output` is not called again.
14pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void,
15 comptime fmt: []const u8, args: ...) Errors!void
16{
14pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void, comptime fmt: []const u8, args: ...) Errors!void {
1715 const State = enum {
1816 Start,
1917 OpenBrace,
......@@ -27,6 +25,9 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
2725 Character,
2826 Buf,
2927 BufWidth,
28 Bytes,
29 BytesBase,
30 BytesWidth,
3031 };
3132
3233 comptime var start_index = 0;
......@@ -95,6 +96,11 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
9596 '.' => {
9697 state = State.Float;
9798 },
99 'B' => {
100 width = 0;
101 radix = 1000;
102 state = State.Bytes;
103 },
98104 else => @compileError("Unknown format character: " ++ []u8{c}),
99105 },
100106 State.Buf => switch (c) {
......@@ -206,6 +212,47 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
206212 },
207213 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
208214 },
215 State.Bytes => switch (c) {
216 '}' => {
217 try formatBytes(args[next_arg], 0, radix, context, Errors, output);
218 next_arg += 1;
219 state = State.Start;
220 start_index = i + 1;
221 },
222 'i' => {
223 radix = 1024;
224 state = State.BytesBase;
225 },
226 '0' ... '9' => {
227 width_start = i;
228 state = State.BytesWidth;
229 },
230 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
231 },
232 State.BytesBase => switch (c) {
233 '}' => {
234 try formatBytes(args[next_arg], 0, radix, context, Errors, output);
235 next_arg += 1;
236 state = State.Start;
237 start_index = i + 1;
238 },
239 '0' ... '9' => {
240 width_start = i;
241 state = State.BytesWidth;
242 },
243 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
244 },
245 State.BytesWidth => switch (c) {
246 '}' => {
247 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
248 try formatBytes(args[next_arg], width, radix, context, Errors, output);
249 next_arg += 1;
250 state = State.Start;
251 start_index = i + 1;
252 },
253 '0' ... '9' => {},
254 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
255 },
209256 }
210257 }
211258 comptime {
......@@ -221,7 +268,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
221268 }
222269}
223270
224pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
271pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
225272 const T = @typeOf(value);
226273 switch (@typeId(T)) {
227274 builtin.TypeId.Int => {
......@@ -256,7 +303,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@
256303 },
257304 builtin.TypeId.Pointer => {
258305 if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) {
259 return output(context, (*value)[0..]);
306 return output(context, (value.*)[0..]);
260307 } else {
261308 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
262309 }
......@@ -270,13 +317,11 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@
270317 }
271318}
272319
273pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
320pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
274321 return output(context, (&c)[0..1]);
275322}
276323
277pub fn formatBuf(buf: []const u8, width: usize,
278 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
279{
324pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
280325 try output(context, buf);
281326
282327 var leftover_padding = if (width > buf.len) (width - buf.len) else return;
......@@ -289,7 +334,7 @@ pub fn formatBuf(buf: []const u8, width: usize,
289334// Print a float in scientific notation to the specified precision. Null uses full precision.
290335// It should be the case that every full precision, printed value can be re-parsed back to the
291336// same type unambiguously.
292pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
337pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
293338 var x = f64(value);
294339
295340 // Errol doesn't handle these special cases.
......@@ -338,7 +383,7 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,
338383 var printed: usize = 0;
339384 if (float_decimal.digits.len > 1) {
340385 const num_digits = math.min(float_decimal.digits.len, precision + 1);
341 try output(context, float_decimal.digits[1 .. num_digits]);
386 try output(context, float_decimal.digits[1..num_digits]);
342387 printed += num_digits - 1;
343388 }
344389
......@@ -350,12 +395,9 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,
350395 try output(context, float_decimal.digits[0..1]);
351396 try output(context, ".");
352397 if (float_decimal.digits.len > 1) {
353 const num_digits = if (@typeOf(value) == f32)
354 math.min(usize(9), float_decimal.digits.len)
355 else
356 float_decimal.digits.len;
398 const num_digits = if (@typeOf(value) == f32) math.min(usize(9), float_decimal.digits.len) else float_decimal.digits.len;
357399
358 try output(context, float_decimal.digits[1 .. num_digits]);
400 try output(context, float_decimal.digits[1..num_digits]);
359401 } else {
360402 try output(context, "0");
361403 }
......@@ -381,7 +423,7 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var,
381423
382424// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
383425// By default floats are printed at full precision (no rounding).
384pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void {
426pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
385427 var x = f64(value);
386428
387429 // Errol doesn't handle these special cases.
......@@ -431,14 +473,14 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com
431473
432474 if (num_digits_whole > 0) {
433475 // We may have to zero pad, for instance 1e4 requires zero padding.
434 try output(context, float_decimal.digits[0 .. num_digits_whole_no_pad]);
476 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
435477
436478 var i = num_digits_whole_no_pad;
437479 while (i < num_digits_whole) : (i += 1) {
438480 try output(context, "0");
439481 }
440482 } else {
441 try output(context , "0");
483 try output(context, "0");
442484 }
443485
444486 // {.0} special case doesn't want a trailing '.'
......@@ -470,10 +512,10 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com
470512 // Remaining fractional portion, zero-padding if insufficient.
471513 debug.assert(precision >= printed);
472514 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
473 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
515 try output(context, float_decimal.digits[num_digits_whole_no_pad..num_digits_whole_no_pad + precision - printed]);
474516 return;
475517 } else {
476 try output(context, float_decimal.digits[num_digits_whole_no_pad ..]);
518 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
477519 printed += float_decimal.digits.len - num_digits_whole_no_pad;
478520
479521 while (printed < precision) : (printed += 1) {
......@@ -489,14 +531,14 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com
489531
490532 if (num_digits_whole > 0) {
491533 // We may have to zero pad, for instance 1e4 requires zero padding.
492 try output(context, float_decimal.digits[0 .. num_digits_whole_no_pad]);
534 try output(context, float_decimal.digits[0..num_digits_whole_no_pad]);
493535
494536 var i = num_digits_whole_no_pad;
495537 while (i < num_digits_whole) : (i += 1) {
496538 try output(context, "0");
497539 }
498540 } else {
499 try output(context , "0");
541 try output(context, "0");
500542 }
501543
502544 // Omit `.` if no fractional portion
......@@ -516,10 +558,39 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com
516558 }
517559 }
518560
519 try output(context, float_decimal.digits[num_digits_whole_no_pad ..]);
561 try output(context, float_decimal.digits[num_digits_whole_no_pad..]);
520562 }
521563}
522564
565pub fn formatBytes(value: var, width: ?usize, comptime radix: usize,
566 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
567{
568 if (value == 0) {
569 return output(context, "0B");
570 }
571
572 const mags = " KMGTPEZY";
573 const magnitude = switch (radix) {
574 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags.len - 1),
575 1024 => math.min(math.log2(value) / 10, mags.len - 1),
576 else => unreachable,
577 };
578 const new_value = f64(value) / math.pow(f64, f64(radix), f64(magnitude));
579 const suffix = mags[magnitude];
580
581 try formatFloatDecimal(new_value, width, context, Errors, output);
582
583 if (suffix == ' ') {
584 return output(context, "B");
585 }
586
587 const buf = switch (radix) {
588 1000 => []u8 { suffix, 'B' },
589 1024 => []u8 { suffix, 'i', 'B' },
590 else => unreachable,
591 };
592 return output(context, buf);
593}
523594
524595pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
525596 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
......@@ -531,9 +602,7 @@ pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
531602 }
532603}
533604
534fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
535 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
536{
605fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
537606 const uint = @IntType(false, @typeOf(value).bit_count);
538607 if (value < 0) {
539608 const minus_sign: u8 = '-';
......@@ -552,9 +621,7 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize,
552621 }
553622}
554623
555fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
556 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
557{
624fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
558625 // max_int_digits accounts for the minus sign. when printing an unsigned
559626 // number we don't need to do that.
560627 var buf: [max_int_digits - 1]u8 = undefined;
......@@ -566,8 +633,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
566633 index -= 1;
567634 buf[index] = digitToChar(u8(digit), uppercase);
568635 a /= base;
569 if (a == 0)
570 break;
636 if (a == 0) break;
571637 }
572638
573639 const digits_buf = buf[index..];
......@@ -579,8 +645,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
579645 while (true) {
580646 try output(context, (&zero_byte)[0..1]);
581647 leftover_padding -= 1;
582 if (leftover_padding == 0)
583 break;
648 if (leftover_padding == 0) break;
584649 }
585650 mem.set(u8, buf[0..index], '0');
586651 return output(context, buf);
......@@ -592,7 +657,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize,
592657}
593658
594659pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) usize {
595 var context = FormatIntBuf {
660 var context = FormatIntBuf{
596661 .out_buf = out_buf,
597662 .index = 0,
598663 };
......@@ -609,10 +674,8 @@ fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) (error{}!void) {
609674}
610675
611676pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
612 if (!T.is_signed)
613 return parseUnsigned(T, buf, radix);
614 if (buf.len == 0)
615 return T(0);
677 if (!T.is_signed) return parseUnsigned(T, buf, radix);
678 if (buf.len == 0) return T(0);
616679 if (buf[0] == '-') {
617680 return math.negate(try parseUnsigned(T, buf[1..], radix));
618681 } else if (buf[0] == '+') {
......@@ -632,9 +695,10 @@ test "fmt.parseInt" {
632695 assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
633696}
634697
635const ParseUnsignedError = error {
698const ParseUnsignedError = error{
636699 /// The result cannot fit in the type specified
637700 Overflow,
701
638702 /// The input had a byte that was not a digit
639703 InvalidCharacter,
640704};
......@@ -659,8 +723,7 @@ pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
659723 else => return error.InvalidCharacter,
660724 };
661725
662 if (value >= radix)
663 return error.InvalidCharacter;
726 if (value >= radix) return error.InvalidCharacter;
664727
665728 return value;
666729}
......@@ -684,20 +747,21 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void {
684747}
685748
686749pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {
687 var context = BufPrintContext { .remaining = buf, };
750 var context = BufPrintContext{ .remaining = buf };
688751 try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args);
689752 return buf[0..buf.len - context.remaining.len];
690753}
691754
692755pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) ![]u8 {
693756 var size: usize = 0;
694 format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
757 format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {
758 };
695759 const buf = try allocator.alloc(u8, size);
696760 return bufPrint(buf, fmt, args);
697761}
698762
699763fn countSize(size: &usize, bytes: []const u8) (error{}!void) {
700 *size += bytes.len;
764 size.* += bytes.len;
701765}
702766
703767test "buf print int" {
......@@ -738,44 +802,34 @@ test "parse unsigned comptime" {
738802
739803test "fmt.format" {
740804 {
741 var buf1: [32]u8 = undefined;
742805 const value: ?i32 = 1234;
743 const result = try bufPrint(buf1[0..], "nullable: {}\n", value);
744 assert(mem.eql(u8, result, "nullable: 1234\n"));
806 try testFmt("nullable: 1234\n", "nullable: {}\n", value);
745807 }
746808 {
747 var buf1: [32]u8 = undefined;
748809 const value: ?i32 = null;
749 const result = try bufPrint(buf1[0..], "nullable: {}\n", value);
750 assert(mem.eql(u8, result, "nullable: null\n"));
810 try testFmt("nullable: null\n", "nullable: {}\n", value);
751811 }
752812 {
753 var buf1: [32]u8 = undefined;
754813 const value: error!i32 = 1234;
755 const result = try bufPrint(buf1[0..], "error union: {}\n", value);
756 assert(mem.eql(u8, result, "error union: 1234\n"));
814 try testFmt("error union: 1234\n", "error union: {}\n", value);
757815 }
758816 {
759 var buf1: [32]u8 = undefined;
760817 const value: error!i32 = error.InvalidChar;
761 const result = try bufPrint(buf1[0..], "error union: {}\n", value);
762 assert(mem.eql(u8, result, "error union: error.InvalidChar\n"));
818 try testFmt("error union: error.InvalidChar\n", "error union: {}\n", value);
763819 }
764820 {
765 var buf1: [32]u8 = undefined;
766821 const value: u3 = 0b101;
767 const result = try bufPrint(buf1[0..], "u3: {}\n", value);
768 assert(mem.eql(u8, result, "u3: 5\n"));
822 try testFmt("u3: 5\n", "u3: {}\n", value);
769823 }
824 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
825 try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
770826 {
771 // Dummy field because of https://github.com/zig-lang/zig/issues/557.
827 // Dummy field because of https://github.com/ziglang/zig/issues/557.
772828 const Struct = struct {
773829 unused: u8,
774830 };
775831 var buf1: [32]u8 = undefined;
776 const value = Struct {
777 .unused = 42,
778 };
832 const value = Struct{ .unused = 42 };
779833 const result = try bufPrint(buf1[0..], "pointer: {}\n", &value);
780834 assert(mem.startsWith(u8, result, "pointer: Struct@"));
781835 }
......@@ -986,9 +1040,23 @@ test "fmt.format" {
9861040 }
9871041}
9881042
1043fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {
1044 var buf: [100]u8 = undefined;
1045 const result = try bufPrint(buf[0..], template, args);
1046 if (mem.eql(u8, result, expected))
1047 return;
1048
1049 std.debug.warn("\n====== expected this output: =========\n");
1050 std.debug.warn("{}", expected);
1051 std.debug.warn("\n======== instead found this: =========\n");
1052 std.debug.warn("{}", result);
1053 std.debug.warn("\n======================================\n");
1054 return error.TestFailed;
1055}
1056
9891057pub fn trim(buf: []const u8) []const u8 {
9901058 var start: usize = 0;
991 while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { }
1059 while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
9921060
9931061 var end: usize = buf.len;
9941062 while (true) {
......@@ -1000,7 +1068,6 @@ pub fn trim(buf: []const u8) []const u8 {
10001068 }
10011069 }
10021070 break;
1003
10041071 }
10051072 return buf[start..end];
10061073}
......@@ -1015,7 +1082,10 @@ test "fmt.trim" {
10151082
10161083pub fn isWhiteSpace(byte: u8) bool {
10171084 return switch (byte) {
1018 ' ', '\t', '\n', '\r' => true,
1085 ' ',
1086 '\t',
1087 '\n',
1088 '\r' => true,
10191089 else => false,
10201090 };
10211091}
std/hash/crc.zig+16-16
......@@ -9,9 +9,9 @@ const std = @import("../index.zig");
99const debug = std.debug;
1010
1111pub const Polynomial = struct {
12 const IEEE = 0xedb88320;
12 const IEEE = 0xedb88320;
1313 const Castagnoli = 0x82f63b78;
14 const Koopman = 0xeb31d82e;
14 const Koopman = 0xeb31d82e;
1515};
1616
1717// IEEE is by far the most common CRC and so is aliased by default.
......@@ -27,20 +27,22 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
2727
2828 for (tables[0]) |*e, i| {
2929 var crc = u32(i);
30 var j: usize = 0; while (j < 8) : (j += 1) {
30 var j: usize = 0;
31 while (j < 8) : (j += 1) {
3132 if (crc & 1 == 1) {
3233 crc = (crc >> 1) ^ poly;
3334 } else {
3435 crc = (crc >> 1);
3536 }
3637 }
37 *e = crc;
38 e.* = crc;
3839 }
3940
4041 var i: usize = 0;
4142 while (i < 256) : (i += 1) {
4243 var crc = tables[0][i];
43 var j: usize = 1; while (j < 8) : (j += 1) {
44 var j: usize = 1;
45 while (j < 8) : (j += 1) {
4446 const index = @truncate(u8, crc);
4547 crc = tables[0][index] ^ (crc >> 8);
4648 tables[j][i] = crc;
......@@ -53,22 +55,21 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
5355 crc: u32,
5456
5557 pub fn init() Self {
56 return Self {
57 .crc = 0xffffffff,
58 };
58 return Self{ .crc = 0xffffffff };
5959 }
6060
6161 pub fn update(self: &Self, input: []const u8) void {
6262 var i: usize = 0;
6363 while (i + 8 <= input.len) : (i += 8) {
64 const p = input[i..i+8];
64 const p = input[i..i + 8];
6565
6666 // Unrolling this way gives ~50Mb/s increase
67 self.crc ^= (u32(p[0]) << 0);
68 self.crc ^= (u32(p[1]) << 8);
67 self.crc ^= (u32(p[0]) << 0);
68 self.crc ^= (u32(p[1]) << 8);
6969 self.crc ^= (u32(p[2]) << 16);
7070 self.crc ^= (u32(p[3]) << 24);
7171
72
7273 self.crc =
7374 lookup_tables[0][p[7]] ^
7475 lookup_tables[1][p[6]] ^
......@@ -123,14 +124,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
123124
124125 for (table) |*e, i| {
125126 var crc = u32(i * 16);
126 var j: usize = 0; while (j < 8) : (j += 1) {
127 var j: usize = 0;
128 while (j < 8) : (j += 1) {
127129 if (crc & 1 == 1) {
128130 crc = (crc >> 1) ^ poly;
129131 } else {
130132 crc = (crc >> 1);
131133 }
132134 }
133 *e = crc;
135 e.* = crc;
134136 }
135137
136138 break :block table;
......@@ -139,9 +141,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
139141 crc: u32,
140142
141143 pub fn init() Self {
142 return Self {
143 .crc = 0xffffffff,
144 };
144 return Self{ .crc = 0xffffffff };
145145 }
146146
147147 pub fn update(self: &Self, input: []const u8) void {
std/hash_map.zig+57-45
......@@ -9,10 +9,7 @@ const builtin = @import("builtin");
99const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast;
1010const debug_u32 = if (want_modification_safety) u32 else void;
1111
12pub fn HashMap(comptime K: type, comptime V: type,
13 comptime hash: fn(key: K)u32,
14 comptime eql: fn(a: K, b: K)bool) type
15{
12pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K) u32, comptime eql: fn(a: K, b: K) bool) type {
1613 return struct {
1714 entries: []Entry,
1815 size: usize,
......@@ -65,7 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
6562 };
6663
6764 pub fn init(allocator: &Allocator) Self {
68 return Self {
65 return Self{
6966 .entries = []Entry{},
7067 .allocator = allocator,
7168 .size = 0,
......@@ -129,34 +126,36 @@ pub fn HashMap(comptime K: type, comptime V: type,
129126 if (hm.entries.len == 0) return null;
130127 hm.incrementModificationCount();
131128 const start_index = hm.keyToIndex(key);
132 {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
133 const index = (start_index + roll_over) % hm.entries.len;
134 var entry = &hm.entries[index];
135
136 if (!entry.used)
137 return null;
138
139 if (!eql(entry.key, key)) continue;
140
141 while (roll_over < hm.entries.len) : (roll_over += 1) {
142 const next_index = (start_index + roll_over + 1) % hm.entries.len;
143 const next_entry = &hm.entries[next_index];
144 if (!next_entry.used or next_entry.distance_from_start_index == 0) {
145 entry.used = false;
146 hm.size -= 1;
147 return entry;
129 {
130 var roll_over: usize = 0;
131 while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
132 const index = (start_index + roll_over) % hm.entries.len;
133 var entry = &hm.entries[index];
134
135 if (!entry.used) return null;
136
137 if (!eql(entry.key, key)) continue;
138
139 while (roll_over < hm.entries.len) : (roll_over += 1) {
140 const next_index = (start_index + roll_over + 1) % hm.entries.len;
141 const next_entry = &hm.entries[next_index];
142 if (!next_entry.used or next_entry.distance_from_start_index == 0) {
143 entry.used = false;
144 hm.size -= 1;
145 return entry;
146 }
147 entry.* = next_entry.*;
148 entry.distance_from_start_index -= 1;
149 entry = next_entry;
148150 }
149 *entry = *next_entry;
150 entry.distance_from_start_index -= 1;
151 entry = next_entry;
151 unreachable; // shifting everything in the table
152152 }
153 unreachable; // shifting everything in the table
154 }}
153 }
155154 return null;
156155 }
157156
158157 pub fn iterator(hm: &const Self) Iterator {
159 return Iterator {
158 return Iterator{
160159 .hm = hm,
161160 .count = 0,
162161 .index = 0,
......@@ -182,21 +181,23 @@ pub fn HashMap(comptime K: type, comptime V: type,
182181 /// Returns the value that was already there.
183182 fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V {
184183 var key = orig_key;
185 var value = *orig_value;
184 var value = orig_value.*;
186185 const start_index = hm.keyToIndex(key);
187186 var roll_over: usize = 0;
188187 var distance_from_start_index: usize = 0;
189 while (roll_over < hm.entries.len) : ({roll_over += 1; distance_from_start_index += 1;}) {
188 while (roll_over < hm.entries.len) : ({
189 roll_over += 1;
190 distance_from_start_index += 1;
191 }) {
190192 const index = (start_index + roll_over) % hm.entries.len;
191193 const entry = &hm.entries[index];
192194
193195 if (entry.used and !eql(entry.key, key)) {
194196 if (entry.distance_from_start_index < distance_from_start_index) {
195197 // robin hood to the rescue
196 const tmp = *entry;
197 hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
198 distance_from_start_index);
199 *entry = Entry {
198 const tmp = entry.*;
199 hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, distance_from_start_index);
200 entry.* = Entry{
200201 .used = true,
201202 .distance_from_start_index = distance_from_start_index,
202203 .key = key,
......@@ -219,7 +220,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
219220 }
220221
221222 hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
222 *entry = Entry {
223 entry.* = Entry{
223224 .used = true,
224225 .distance_from_start_index = distance_from_start_index,
225226 .key = key,
......@@ -232,13 +233,16 @@ pub fn HashMap(comptime K: type, comptime V: type,
232233
233234 fn internalGet(hm: &const Self, key: K) ?&Entry {
234235 const start_index = hm.keyToIndex(key);
235 {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
236 const index = (start_index + roll_over) % hm.entries.len;
237 const entry = &hm.entries[index];
238
239 if (!entry.used) return null;
240 if (eql(entry.key, key)) return entry;
241 }}
236 {
237 var roll_over: usize = 0;
238 while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) {
239 const index = (start_index + roll_over) % hm.entries.len;
240 const entry = &hm.entries[index];
241
242 if (!entry.used) return null;
243 if (eql(entry.key, key)) return entry;
244 }
245 }
242246 return null;
243247 }
244248
......@@ -282,11 +286,19 @@ test "iterator hash map" {
282286 assert((reset_map.put(2, 22) catch unreachable) == null);
283287 assert((reset_map.put(3, 33) catch unreachable) == null);
284288
285 var keys = []i32 { 1, 2, 3 };
286 var values = []i32 { 11, 22, 33 };
289 var keys = []i32{
290 1,
291 2,
292 3,
293 };
294 var values = []i32{
295 11,
296 22,
297 33,
298 };
287299
288300 var it = reset_map.iterator();
289 var count : usize = 0;
301 var count: usize = 0;
290302 while (it.next()) |next| {
291303 assert(next.key == keys[count]);
292304 assert(next.value == values[count]);
......@@ -305,7 +317,7 @@ test "iterator hash map" {
305317 }
306318
307319 it.reset();
308 var entry = ?? it.next();
320 var entry = ??it.next();
309321 assert(entry.key == keys[0]);
310322 assert(entry.value == values[0]);
311323}
std/heap.zig+52-54
......@@ -10,7 +10,7 @@ const c = std.c;
1010const Allocator = mem.Allocator;
1111
1212pub const c_allocator = &c_allocator_state;
13var c_allocator_state = Allocator {
13var c_allocator_state = Allocator{
1414 .allocFn = cAlloc,
1515 .reallocFn = cRealloc,
1616 .freeFn = cFree,
......@@ -18,10 +18,7 @@ var c_allocator_state = Allocator {
1818
1919fn cAlloc(self: &Allocator, n: usize, alignment: u29) ![]u8 {
2020 assert(alignment <= @alignOf(c_longdouble));
21 return if (c.malloc(n)) |buf|
22 @ptrCast(&u8, buf)[0..n]
23 else
24 error.OutOfMemory;
21 return if (c.malloc(n)) |buf| @ptrCast(&u8, buf)[0..n] else error.OutOfMemory;
2522}
2623
2724fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
......@@ -48,8 +45,8 @@ pub const DirectAllocator = struct {
4845 const HeapHandle = if (builtin.os == Os.windows) os.windows.HANDLE else void;
4946
5047 pub fn init() DirectAllocator {
51 return DirectAllocator {
52 .allocator = Allocator {
48 return DirectAllocator{
49 .allocator = Allocator{
5350 .allocFn = alloc,
5451 .reallocFn = realloc,
5552 .freeFn = free,
......@@ -71,39 +68,39 @@ pub const DirectAllocator = struct {
7168 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
7269
7370 switch (builtin.os) {
74 Os.linux, Os.macosx, Os.ios => {
71 Os.linux,
72 Os.macosx,
73 Os.ios => {
7574 const p = os.posix;
76 const alloc_size = if(alignment <= os.page_size) n else n + alignment;
77 const addr = p.mmap(null, alloc_size, p.PROT_READ|p.PROT_WRITE,
78 p.MAP_PRIVATE|p.MAP_ANONYMOUS, -1, 0);
79 if(addr == p.MAP_FAILED) return error.OutOfMemory;
80
81 if(alloc_size == n) return @intToPtr(&u8, addr)[0..n];
82
75 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
76 const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);
77 if (addr == p.MAP_FAILED) return error.OutOfMemory;
78
79 if (alloc_size == n) return @intToPtr(&u8, addr)[0..n];
80
8381 var aligned_addr = addr & ~usize(alignment - 1);
8482 aligned_addr += alignment;
85
83
8684 //We can unmap the unused portions of our mmap, but we must only
8785 // pass munmap bytes that exist outside our allocated pages or it
8886 // will happily eat us too
89
87
9088 //Since alignment > page_size, we are by definition on a page boundry
9189 const unused_start = addr;
9290 const unused_len = aligned_addr - 1 - unused_start;
9391
9492 var err = p.munmap(unused_start, unused_len);
9593 debug.assert(p.getErrno(err) == 0);
96
94
9795 //It is impossible that there is an unoccupied page at the top of our
9896 // mmap.
99
97
10098 return @intToPtr(&u8, aligned_addr)[0..n];
10199 },
102100 Os.windows => {
103101 const amt = n + alignment + @sizeOf(usize);
104102 const heap_handle = self.heap_handle ?? blk: {
105 const hh = os.windows.HeapCreate(os.windows.HEAP_NO_SERIALIZE, amt, 0)
106 ?? return error.OutOfMemory;
103 const hh = os.windows.HeapCreate(os.windows.HEAP_NO_SERIALIZE, amt, 0) ?? return error.OutOfMemory;
107104 self.heap_handle = hh;
108105 break :blk hh;
109106 };
......@@ -113,7 +110,7 @@ pub const DirectAllocator = struct {
113110 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
114111 const adjusted_addr = root_addr + march_forward_bytes;
115112 const record_addr = adjusted_addr + n;
116 *@intToPtr(&align(1) usize, record_addr) = root_addr;
113 @intToPtr(&align(1) usize, record_addr).* = root_addr;
117114 return @intToPtr(&u8, adjusted_addr)[0..n];
118115 },
119116 else => @compileError("Unsupported OS"),
......@@ -124,7 +121,9 @@ pub const DirectAllocator = struct {
124121 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
125122
126123 switch (builtin.os) {
127 Os.linux, Os.macosx, Os.ios => {
124 Os.linux,
125 Os.macosx,
126 Os.ios => {
128127 if (new_size <= old_mem.len) {
129128 const base_addr = @ptrToInt(old_mem.ptr);
130129 const old_addr_end = base_addr + old_mem.len;
......@@ -144,13 +143,13 @@ pub const DirectAllocator = struct {
144143 Os.windows => {
145144 const old_adjusted_addr = @ptrToInt(old_mem.ptr);
146145 const old_record_addr = old_adjusted_addr + old_mem.len;
147 const root_addr = *@intToPtr(&align(1) usize, old_record_addr);
146 const root_addr = @intToPtr(&align(1) usize, old_record_addr).*;
148147 const old_ptr = @intToPtr(os.windows.LPVOID, root_addr);
149148 const amt = new_size + alignment + @sizeOf(usize);
150149 const new_ptr = os.windows.HeapReAlloc(??self.heap_handle, 0, old_ptr, amt) ?? blk: {
151150 if (new_size > old_mem.len) return error.OutOfMemory;
152151 const new_record_addr = old_record_addr - new_size + old_mem.len;
153 *@intToPtr(&align(1) usize, new_record_addr) = root_addr;
152 @intToPtr(&align(1) usize, new_record_addr).* = root_addr;
154153 return old_mem[0..new_size];
155154 };
156155 const offset = old_adjusted_addr - root_addr;
......@@ -158,7 +157,7 @@ pub const DirectAllocator = struct {
158157 const new_adjusted_addr = new_root_addr + offset;
159158 assert(new_adjusted_addr % alignment == 0);
160159 const new_record_addr = new_adjusted_addr + new_size;
161 *@intToPtr(&align(1) usize, new_record_addr) = new_root_addr;
160 @intToPtr(&align(1) usize, new_record_addr).* = new_root_addr;
162161 return @intToPtr(&u8, new_adjusted_addr)[0..new_size];
163162 },
164163 else => @compileError("Unsupported OS"),
......@@ -169,12 +168,14 @@ pub const DirectAllocator = struct {
169168 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
170169
171170 switch (builtin.os) {
172 Os.linux, Os.macosx, Os.ios => {
171 Os.linux,
172 Os.macosx,
173 Os.ios => {
173174 _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
174175 },
175176 Os.windows => {
176177 const record_addr = @ptrToInt(bytes.ptr) + bytes.len;
177 const root_addr = *@intToPtr(&align(1) usize, record_addr);
178 const root_addr = @intToPtr(&align(1) usize, record_addr).*;
178179 const ptr = @intToPtr(os.windows.LPVOID, root_addr);
179180 _ = os.windows.HeapFree(??self.heap_handle, 0, ptr);
180181 },
......@@ -195,8 +196,8 @@ pub const ArenaAllocator = struct {
195196 const BufNode = std.LinkedList([]u8).Node;
196197
197198 pub fn init(child_allocator: &Allocator) ArenaAllocator {
198 return ArenaAllocator {
199 .allocator = Allocator {
199 return ArenaAllocator{
200 .allocator = Allocator{
200201 .allocFn = alloc,
201202 .reallocFn = realloc,
202203 .freeFn = free,
......@@ -228,7 +229,7 @@ pub const ArenaAllocator = struct {
228229 const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len);
229230 const buf_node_slice = ([]BufNode)(buf[0..@sizeOf(BufNode)]);
230231 const buf_node = &buf_node_slice[0];
231 *buf_node = BufNode {
232 buf_node.* = BufNode{
232233 .data = buf,
233234 .prev = null,
234235 .next = null,
......@@ -253,7 +254,7 @@ pub const ArenaAllocator = struct {
253254 cur_node = try self.createNode(cur_buf.len, n + alignment);
254255 continue;
255256 }
256 const result = cur_buf[adjusted_index .. new_end_index];
257 const result = cur_buf[adjusted_index..new_end_index];
257258 self.end_index = new_end_index;
258259 return result;
259260 }
......@@ -269,7 +270,7 @@ pub const ArenaAllocator = struct {
269270 }
270271 }
271272
272 fn free(allocator: &Allocator, bytes: []u8) void { }
273 fn free(allocator: &Allocator, bytes: []u8) void {}
273274};
274275
275276pub const FixedBufferAllocator = struct {
......@@ -278,8 +279,8 @@ pub const FixedBufferAllocator = struct {
278279 buffer: []u8,
279280
280281 pub fn init(buffer: []u8) FixedBufferAllocator {
281 return FixedBufferAllocator {
282 .allocator = Allocator {
282 return FixedBufferAllocator{
283 .allocator = Allocator{
283284 .allocFn = alloc,
284285 .reallocFn = realloc,
285286 .freeFn = free,
......@@ -299,7 +300,7 @@ pub const FixedBufferAllocator = struct {
299300 if (new_end_index > self.buffer.len) {
300301 return error.OutOfMemory;
301302 }
302 const result = self.buffer[adjusted_index .. new_end_index];
303 const result = self.buffer[adjusted_index..new_end_index];
303304 self.end_index = new_end_index;
304305
305306 return result;
......@@ -315,7 +316,7 @@ pub const FixedBufferAllocator = struct {
315316 }
316317 }
317318
318 fn free(allocator: &Allocator, bytes: []u8) void { }
319 fn free(allocator: &Allocator, bytes: []u8) void {}
319320};
320321
321322/// lock free
......@@ -325,8 +326,8 @@ pub const ThreadSafeFixedBufferAllocator = struct {
325326 buffer: []u8,
326327
327328 pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator {
328 return ThreadSafeFixedBufferAllocator {
329 .allocator = Allocator {
329 return ThreadSafeFixedBufferAllocator{
330 .allocator = Allocator{
330331 .allocFn = alloc,
331332 .reallocFn = realloc,
332333 .freeFn = free,
......@@ -348,8 +349,7 @@ pub const ThreadSafeFixedBufferAllocator = struct {
348349 if (new_end_index > self.buffer.len) {
349350 return error.OutOfMemory;
350351 }
351 end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index,
352 builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) ?? return self.buffer[adjusted_index .. new_end_index];
352 end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) ?? return self.buffer[adjusted_index..new_end_index];
353353 }
354354 }
355355
......@@ -363,11 +363,9 @@ pub const ThreadSafeFixedBufferAllocator = struct {
363363 }
364364 }
365365
366 fn free(allocator: &Allocator, bytes: []u8) void { }
366 fn free(allocator: &Allocator, bytes: []u8) void {}
367367};
368368
369
370
371369test "c_allocator" {
372370 if (builtin.link_libc) {
373371 var slice = c_allocator.alloc(u8, 50) catch return;
......@@ -415,8 +413,8 @@ fn testAllocator(allocator: &mem.Allocator) !void {
415413 var slice = try allocator.alloc(&i32, 100);
416414
417415 for (slice) |*item, i| {
418 *item = try allocator.create(i32);
419 **item = i32(i);
416 item.* = try allocator.create(i32);
417 item.*.* = i32(i);
420418 }
421419
422420 for (slice) |item, i| {
......@@ -434,26 +432,26 @@ fn testAllocator(allocator: &mem.Allocator) !void {
434432fn testAllocatorLargeAlignment(allocator: &mem.Allocator) mem.Allocator.Error!void {
435433 //Maybe a platform's page_size is actually the same as or
436434 // very near usize?
437 if(os.page_size << 2 > @maxValue(usize)) return;
438
435 if (os.page_size << 2 > @maxValue(usize)) return;
436
439437 const USizeShift = @IntType(false, std.math.log2(usize.bit_count));
440438 const large_align = u29(os.page_size << 2);
441
439
442440 var align_mask: usize = undefined;
443441 _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask);
444
442
445443 var slice = try allocator.allocFn(allocator, 500, large_align);
446444 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
447
445
448446 slice = try allocator.reallocFn(allocator, slice, 100, large_align);
449447 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
450
448
451449 slice = try allocator.reallocFn(allocator, slice, 5000, large_align);
452450 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
453
451
454452 slice = try allocator.reallocFn(allocator, slice, 10, large_align);
455453 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
456
454
457455 slice = try allocator.reallocFn(allocator, slice, 20000, large_align);
458456 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
459457
std/io.zig+18-47
......@@ -18,32 +18,17 @@ const is_windows = builtin.os == builtin.Os.windows;
1818const GetStdIoErrs = os.WindowsGetStdHandleErrs;
1919
2020pub fn getStdErr() GetStdIoErrs!File {
21 const handle = if (is_windows)
22 try os.windowsGetStdHandle(os.windows.STD_ERROR_HANDLE)
23 else if (is_posix)
24 os.posix.STDERR_FILENO
25 else
26 unreachable;
21 const handle = if (is_windows) try os.windowsGetStdHandle(os.windows.STD_ERROR_HANDLE) else if (is_posix) os.posix.STDERR_FILENO else unreachable;
2722 return File.openHandle(handle);
2823}
2924
3025pub fn getStdOut() GetStdIoErrs!File {
31 const handle = if (is_windows)
32 try os.windowsGetStdHandle(os.windows.STD_OUTPUT_HANDLE)
33 else if (is_posix)
34 os.posix.STDOUT_FILENO
35 else
36 unreachable;
26 const handle = if (is_windows) try os.windowsGetStdHandle(os.windows.STD_OUTPUT_HANDLE) else if (is_posix) os.posix.STDOUT_FILENO else unreachable;
3727 return File.openHandle(handle);
3828}
3929
4030pub fn getStdIn() GetStdIoErrs!File {
41 const handle = if (is_windows)
42 try os.windowsGetStdHandle(os.windows.STD_INPUT_HANDLE)
43 else if (is_posix)
44 os.posix.STDIN_FILENO
45 else
46 unreachable;
31 const handle = if (is_windows) try os.windowsGetStdHandle(os.windows.STD_INPUT_HANDLE) else if (is_posix) os.posix.STDIN_FILENO else unreachable;
4732 return File.openHandle(handle);
4833}
4934
......@@ -56,11 +41,9 @@ pub const FileInStream = struct {
5641 pub const Stream = InStream(Error);
5742
5843 pub fn init(file: &File) FileInStream {
59 return FileInStream {
44 return FileInStream{
6045 .file = file,
61 .stream = Stream {
62 .readFn = readFn,
63 },
46 .stream = Stream{ .readFn = readFn },
6447 };
6548 }
6649
......@@ -79,11 +62,9 @@ pub const FileOutStream = struct {
7962 pub const Stream = OutStream(Error);
8063
8164 pub fn init(file: &File) FileOutStream {
82 return FileOutStream {
65 return FileOutStream{
8366 .file = file,
84 .stream = Stream {
85 .writeFn = writeFn,
86 },
67 .stream = Stream{ .writeFn = writeFn },
8768 };
8869 }
8970
......@@ -121,8 +102,7 @@ pub fn InStream(comptime ReadError: type) type {
121102 }
122103
123104 const new_buf_size = math.min(max_size, actual_buf_len + os.page_size);
124 if (new_buf_size == actual_buf_len)
125 return error.StreamTooLong;
105 if (new_buf_size == actual_buf_len) return error.StreamTooLong;
126106 try buffer.resize(new_buf_size);
127107 }
128108 }
......@@ -165,9 +145,7 @@ pub fn InStream(comptime ReadError: type) type {
165145 /// memory would be greater than `max_size`, returns `error.StreamTooLong`.
166146 /// Caller owns returned memory.
167147 /// If this function returns an error, the contents from the stream read so far are lost.
168 pub fn readUntilDelimiterAlloc(self: &Self, allocator: &mem.Allocator,
169 delimiter: u8, max_size: usize) ![]u8
170 {
148 pub fn readUntilDelimiterAlloc(self: &Self, allocator: &mem.Allocator, delimiter: u8, max_size: usize) ![]u8 {
171149 var buf = Buffer.initNull(allocator);
172150 defer buf.deinit();
173151
......@@ -283,7 +261,7 @@ pub fn BufferedInStream(comptime Error: type) type {
283261pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type {
284262 return struct {
285263 const Self = this;
286 const Stream = InStream(Error);
264 const Stream = InStream(Error);
287265
288266 pub stream: Stream,
289267
......@@ -294,7 +272,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
294272 end_index: usize,
295273
296274 pub fn init(unbuffered_in_stream: &Stream) Self {
297 return Self {
275 return Self{
298276 .unbuffered_in_stream = unbuffered_in_stream,
299277 .buffer = undefined,
300278
......@@ -305,9 +283,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
305283 .start_index = buffer_size,
306284 .end_index = buffer_size,
307285
308 .stream = Stream {
309 .readFn = readFn,
310 },
286 .stream = Stream{ .readFn = readFn },
311287 };
312288 }
313289
......@@ -368,13 +344,11 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamEr
368344 index: usize,
369345
370346 pub fn init(unbuffered_out_stream: &Stream) Self {
371 return Self {
347 return Self{
372348 .unbuffered_out_stream = unbuffered_out_stream,
373349 .buffer = undefined,
374350 .index = 0,
375 .stream = Stream {
376 .writeFn = writeFn,
377 },
351 .stream = Stream{ .writeFn = writeFn },
378352 };
379353 }
380354
......@@ -416,11 +390,9 @@ pub const BufferOutStream = struct {
416390 pub const Stream = OutStream(Error);
417391
418392 pub fn init(buffer: &Buffer) BufferOutStream {
419 return BufferOutStream {
393 return BufferOutStream{
420394 .buffer = buffer,
421 .stream = Stream {
422 .writeFn = writeFn,
423 },
395 .stream = Stream{ .writeFn = writeFn },
424396 };
425397 }
426398
......@@ -430,7 +402,6 @@ pub const BufferOutStream = struct {
430402 }
431403};
432404
433
434405pub const BufferedAtomicFile = struct {
435406 atomic_file: os.AtomicFile,
436407 file_stream: FileOutStream,
......@@ -441,7 +412,7 @@ pub const BufferedAtomicFile = struct {
441412 var self = try allocator.create(BufferedAtomicFile);
442413 errdefer allocator.destroy(self);
443414
444 *self = BufferedAtomicFile {
415 self.* = BufferedAtomicFile{
445416 .atomic_file = undefined,
446417 .file_stream = undefined,
447418 .buffered_stream = undefined,
......@@ -489,7 +460,7 @@ pub fn readLine(buf: []u8) !usize {
489460 '\r' => {
490461 // trash the following \n
491462 _ = stream.readByte() catch return error.EndOfFile;
492 return index;
463 return index;
493464 },
494465 '\n' => return index,
495466 else => {
std/io_test.zig+17-1
......@@ -1,6 +1,5 @@
11const std = @import("index.zig");
22const io = std.io;
3const allocator = std.debug.global_allocator;
43const DefaultPrng = std.rand.DefaultPrng;
54const assert = std.debug.assert;
65const mem = std.mem;
......@@ -8,6 +7,9 @@ const os = std.os;
87const builtin = @import("builtin");
98
109test "write a file, read it, then delete it" {
10 var raw_bytes: [200 * 1024]u8 = undefined;
11 var allocator = &std.heap.FixedBufferAllocator.init(raw_bytes[0..]).allocator;
12
1113 var data: [1024]u8 = undefined;
1214 var prng = DefaultPrng.init(1234);
1315 prng.random.bytes(data[0..]);
......@@ -44,3 +46,17 @@ test "write a file, read it, then delete it" {
4446 }
4547 try os.deleteFile(allocator, tmp_file_name);
4648}
49
50test "BufferOutStream" {
51 var bytes: [100]u8 = undefined;
52 var allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
53
54 var buffer = try std.Buffer.initSize(allocator, 0);
55 var buf_stream = &std.io.BufferOutStream.init(&buffer).stream;
56
57 const x: i32 = 42;
58 const y: i32 = 1234;
59 try buf_stream.print("x: {}\ny: {}\n", x, y);
60
61 assert(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
62}
std/json.zig+126-85
......@@ -35,7 +35,7 @@ pub const Token = struct {
3535 };
3636
3737 pub fn init(id: Id, count: usize, offset: u1) Token {
38 return Token {
38 return Token{
3939 .id = id,
4040 .offset = offset,
4141 .string_has_escape = false,
......@@ -45,7 +45,7 @@ pub const Token = struct {
4545 }
4646
4747 pub fn initString(count: usize, has_unicode_escape: bool) Token {
48 return Token {
48 return Token{
4949 .id = Id.String,
5050 .offset = 0,
5151 .string_has_escape = has_unicode_escape,
......@@ -55,7 +55,7 @@ pub const Token = struct {
5555 }
5656
5757 pub fn initNumber(count: usize, number_is_integer: bool) Token {
58 return Token {
58 return Token{
5959 .id = Id.Number,
6060 .offset = 0,
6161 .string_has_escape = false,
......@@ -66,7 +66,7 @@ pub const Token = struct {
6666
6767 // A marker token is a zero-length
6868 pub fn initMarker(id: Id) Token {
69 return Token {
69 return Token{
7070 .id = id,
7171 .offset = 0,
7272 .string_has_escape = false,
......@@ -77,7 +77,7 @@ pub const Token = struct {
7777
7878 // Slice into the underlying input string.
7979 pub fn slice(self: &const Token, input: []const u8, i: usize) []const u8 {
80 return input[i + self.offset - self.count .. i + self.offset];
80 return input[i + self.offset - self.count..i + self.offset];
8181 }
8282};
8383
......@@ -86,7 +86,7 @@ pub const Token = struct {
8686// parsing state requires ~40-50 bytes of stack space.
8787//
8888// Conforms strictly to RFC8529.
89const StreamingJsonParser = struct {
89pub const StreamingJsonParser = struct {
9090 // Current state
9191 state: State,
9292 // How many bytes we have counted for the current token
......@@ -105,8 +105,8 @@ const StreamingJsonParser = struct {
105105 stack: u256,
106106 stack_used: u8,
107107
108 const object_bit = 0;
109 const array_bit = 1;
108 const object_bit = 0;
109 const array_bit = 1;
110110 const max_stack_size = @maxValue(u8);
111111
112112 pub fn init() StreamingJsonParser {
......@@ -120,7 +120,7 @@ const StreamingJsonParser = struct {
120120 p.count = 0;
121121 // Set before ever read in main transition function
122122 p.after_string_state = undefined;
123 p.after_value_state = State.ValueEnd; // handle end of values normally
123 p.after_value_state = State.ValueEnd; // handle end of values normally
124124 p.stack = 0;
125125 p.stack_used = 0;
126126 p.complete = false;
......@@ -181,7 +181,7 @@ const StreamingJsonParser = struct {
181181 }
182182 };
183183
184 pub const Error = error {
184 pub const Error = error{
185185 InvalidTopLevel,
186186 TooManyNestedItems,
187187 TooManyClosingItems,
......@@ -206,8 +206,8 @@ const StreamingJsonParser = struct {
206206 //
207207 // There is currently no error recovery on a bad stream.
208208 pub fn feed(p: &StreamingJsonParser, c: u8, token1: &?Token, token2: &?Token) Error!void {
209 *token1 = null;
210 *token2 = null;
209 token1.* = null;
210 token2.* = null;
211211 p.count += 1;
212212
213213 // unlikely
......@@ -228,7 +228,7 @@ const StreamingJsonParser = struct {
228228 p.state = State.ValueBegin;
229229 p.after_string_state = State.ObjectSeparator;
230230
231 *token = Token.initMarker(Token.Id.ObjectBegin);
231 token.* = Token.initMarker(Token.Id.ObjectBegin);
232232 },
233233 '[' => {
234234 p.stack <<= 1;
......@@ -238,7 +238,7 @@ const StreamingJsonParser = struct {
238238 p.state = State.ValueBegin;
239239 p.after_string_state = State.ValueEnd;
240240
241 *token = Token.initMarker(Token.Id.ArrayBegin);
241 token.* = Token.initMarker(Token.Id.ArrayBegin);
242242 },
243243 '-' => {
244244 p.number_is_integer = true;
......@@ -281,7 +281,10 @@ const StreamingJsonParser = struct {
281281 p.after_value_state = State.TopLevelEnd;
282282 p.count = 0;
283283 },
284 0x09, 0x0A, 0x0D, 0x20 => {
284 0x09,
285 0x0A,
286 0x0D,
287 0x20 => {
285288 // whitespace
286289 },
287290 else => {
......@@ -290,7 +293,10 @@ const StreamingJsonParser = struct {
290293 },
291294
292295 State.TopLevelEnd => switch (c) {
293 0x09, 0x0A, 0x0D, 0x20 => {
296 0x09,
297 0x0A,
298 0x0D,
299 0x20 => {
294300 // whitespace
295301 },
296302 else => {
......@@ -324,7 +330,7 @@ const StreamingJsonParser = struct {
324330 else => {},
325331 }
326332
327 *token = Token.initMarker(Token.Id.ObjectEnd);
333 token.* = Token.initMarker(Token.Id.ObjectEnd);
328334 },
329335 ']' => {
330336 if (p.stack & 1 != array_bit) {
......@@ -348,7 +354,7 @@ const StreamingJsonParser = struct {
348354 else => {},
349355 }
350356
351 *token = Token.initMarker(Token.Id.ArrayEnd);
357 token.* = Token.initMarker(Token.Id.ArrayEnd);
352358 },
353359 '{' => {
354360 if (p.stack_used == max_stack_size) {
......@@ -362,7 +368,7 @@ const StreamingJsonParser = struct {
362368 p.state = State.ValueBegin;
363369 p.after_string_state = State.ObjectSeparator;
364370
365 *token = Token.initMarker(Token.Id.ObjectBegin);
371 token.* = Token.initMarker(Token.Id.ObjectBegin);
366372 },
367373 '[' => {
368374 if (p.stack_used == max_stack_size) {
......@@ -376,7 +382,7 @@ const StreamingJsonParser = struct {
376382 p.state = State.ValueBegin;
377383 p.after_string_state = State.ValueEnd;
378384
379 *token = Token.initMarker(Token.Id.ArrayBegin);
385 token.* = Token.initMarker(Token.Id.ArrayBegin);
380386 },
381387 '-' => {
382388 p.state = State.Number;
......@@ -406,7 +412,10 @@ const StreamingJsonParser = struct {
406412 p.state = State.NullLiteral1;
407413 p.count = 0;
408414 },
409 0x09, 0x0A, 0x0D, 0x20 => {
415 0x09,
416 0x0A,
417 0x0D,
418 0x20 => {
410419 // whitespace
411420 },
412421 else => {
......@@ -428,7 +437,7 @@ const StreamingJsonParser = struct {
428437 p.state = State.ValueBegin;
429438 p.after_string_state = State.ObjectSeparator;
430439
431 *token = Token.initMarker(Token.Id.ObjectBegin);
440 token.* = Token.initMarker(Token.Id.ObjectBegin);
432441 },
433442 '[' => {
434443 if (p.stack_used == max_stack_size) {
......@@ -442,7 +451,7 @@ const StreamingJsonParser = struct {
442451 p.state = State.ValueBegin;
443452 p.after_string_state = State.ValueEnd;
444453
445 *token = Token.initMarker(Token.Id.ArrayBegin);
454 token.* = Token.initMarker(Token.Id.ArrayBegin);
446455 },
447456 '-' => {
448457 p.state = State.Number;
......@@ -472,7 +481,10 @@ const StreamingJsonParser = struct {
472481 p.state = State.NullLiteral1;
473482 p.count = 0;
474483 },
475 0x09, 0x0A, 0x0D, 0x20 => {
484 0x09,
485 0x0A,
486 0x0D,
487 0x20 => {
476488 // whitespace
477489 },
478490 else => {
......@@ -501,7 +513,7 @@ const StreamingJsonParser = struct {
501513 p.state = State.TopLevelEnd;
502514 }
503515
504 *token = Token.initMarker(Token.Id.ArrayEnd);
516 token.* = Token.initMarker(Token.Id.ArrayEnd);
505517 },
506518 '}' => {
507519 if (p.stack_used == 0) {
......@@ -519,9 +531,12 @@ const StreamingJsonParser = struct {
519531 p.state = State.TopLevelEnd;
520532 }
521533
522 *token = Token.initMarker(Token.Id.ObjectEnd);
534 token.* = Token.initMarker(Token.Id.ObjectEnd);
523535 },
524 0x09, 0x0A, 0x0D, 0x20 => {
536 0x09,
537 0x0A,
538 0x0D,
539 0x20 => {
525540 // whitespace
526541 },
527542 else => {
......@@ -534,7 +549,10 @@ const StreamingJsonParser = struct {
534549 p.state = State.ValueBegin;
535550 p.after_string_state = State.ValueEnd;
536551 },
537 0x09, 0x0A, 0x0D, 0x20 => {
552 0x09,
553 0x0A,
554 0x0D,
555 0x20 => {
538556 // whitespace
539557 },
540558 else => {
......@@ -553,12 +571,15 @@ const StreamingJsonParser = struct {
553571 p.complete = true;
554572 }
555573
556 *token = Token.initString(p.count - 1, p.string_has_escape);
574 token.* = Token.initString(p.count - 1, p.string_has_escape);
557575 },
558576 '\\' => {
559577 p.state = State.StringEscapeCharacter;
560578 },
561 0x20, 0x21, 0x23 ... 0x5B, 0x5D ... 0x7F => {
579 0x20,
580 0x21,
581 0x23 ... 0x5B,
582 0x5D ... 0x7F => {
562583 // non-control ascii
563584 },
564585 0xC0 ... 0xDF => {
......@@ -599,7 +620,14 @@ const StreamingJsonParser = struct {
599620 // The current JSONTestSuite tests rely on both of this behaviour being present
600621 // however, so we default to the status quo where both are accepted until this
601622 // is further clarified.
602 '"', '\\', '/', 'b', 'f', 'n', 'r', 't' => {
623 '"',
624 '\\',
625 '/',
626 'b',
627 'f',
628 'n',
629 'r',
630 't' => {
603631 p.string_has_escape = true;
604632 p.state = State.String;
605633 },
......@@ -613,28 +641,36 @@ const StreamingJsonParser = struct {
613641 },
614642
615643 State.StringEscapeHexUnicode4 => switch (c) {
616 '0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
644 '0' ... '9',
645 'A' ... 'F',
646 'a' ... 'f' => {
617647 p.state = State.StringEscapeHexUnicode3;
618648 },
619649 else => return error.InvalidUnicodeHexSymbol,
620650 },
621651
622652 State.StringEscapeHexUnicode3 => switch (c) {
623 '0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
653 '0' ... '9',
654 'A' ... 'F',
655 'a' ... 'f' => {
624656 p.state = State.StringEscapeHexUnicode2;
625657 },
626658 else => return error.InvalidUnicodeHexSymbol,
627659 },
628660
629661 State.StringEscapeHexUnicode2 => switch (c) {
630 '0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
662 '0' ... '9',
663 'A' ... 'F',
664 'a' ... 'f' => {
631665 p.state = State.StringEscapeHexUnicode1;
632666 },
633667 else => return error.InvalidUnicodeHexSymbol,
634668 },
635669
636670 State.StringEscapeHexUnicode1 => switch (c) {
637 '0' ... '9', 'A' ... 'F', 'a' ... 'f' => {
671 '0' ... '9',
672 'A' ... 'F',
673 'a' ... 'f' => {
638674 p.state = State.String;
639675 },
640676 else => return error.InvalidUnicodeHexSymbol,
......@@ -662,13 +698,14 @@ const StreamingJsonParser = struct {
662698 p.number_is_integer = false;
663699 p.state = State.NumberFractionalRequired;
664700 },
665 'e', 'E' => {
701 'e',
702 'E' => {
666703 p.number_is_integer = false;
667704 p.state = State.NumberExponent;
668705 },
669706 else => {
670707 p.state = p.after_value_state;
671 *token = Token.initNumber(p.count, p.number_is_integer);
708 token.* = Token.initNumber(p.count, p.number_is_integer);
672709 return true;
673710 },
674711 }
......@@ -681,7 +718,8 @@ const StreamingJsonParser = struct {
681718 p.number_is_integer = false;
682719 p.state = State.NumberFractionalRequired;
683720 },
684 'e', 'E' => {
721 'e',
722 'E' => {
685723 p.number_is_integer = false;
686724 p.state = State.NumberExponent;
687725 },
......@@ -690,7 +728,7 @@ const StreamingJsonParser = struct {
690728 },
691729 else => {
692730 p.state = p.after_value_state;
693 *token = Token.initNumber(p.count, p.number_is_integer);
731 token.* = Token.initNumber(p.count, p.number_is_integer);
694732 return true;
695733 },
696734 }
......@@ -714,13 +752,14 @@ const StreamingJsonParser = struct {
714752 '0' ... '9' => {
715753 // another digit
716754 },
717 'e', 'E' => {
755 'e',
756 'E' => {
718757 p.number_is_integer = false;
719758 p.state = State.NumberExponent;
720759 },
721760 else => {
722761 p.state = p.after_value_state;
723 *token = Token.initNumber(p.count, p.number_is_integer);
762 token.* = Token.initNumber(p.count, p.number_is_integer);
724763 return true;
725764 },
726765 }
......@@ -729,20 +768,22 @@ const StreamingJsonParser = struct {
729768 State.NumberMaybeExponent => {
730769 p.complete = p.after_value_state == State.TopLevelEnd;
731770 switch (c) {
732 'e', 'E' => {
771 'e',
772 'E' => {
733773 p.number_is_integer = false;
734774 p.state = State.NumberExponent;
735775 },
736776 else => {
737777 p.state = p.after_value_state;
738 *token = Token.initNumber(p.count, p.number_is_integer);
778 token.* = Token.initNumber(p.count, p.number_is_integer);
739779 return true;
740780 },
741781 }
742782 },
743783
744784 State.NumberExponent => switch (c) {
745 '-', '+', => {
785 '-',
786 '+' => {
746787 p.complete = false;
747788 p.state = State.NumberExponentDigitsRequired;
748789 },
......@@ -773,7 +814,7 @@ const StreamingJsonParser = struct {
773814 },
774815 else => {
775816 p.state = p.after_value_state;
776 *token = Token.initNumber(p.count, p.number_is_integer);
817 token.* = Token.initNumber(p.count, p.number_is_integer);
777818 return true;
778819 },
779820 }
......@@ -793,7 +834,7 @@ const StreamingJsonParser = struct {
793834 'e' => {
794835 p.state = p.after_value_state;
795836 p.complete = p.state == State.TopLevelEnd;
796 *token = Token.init(Token.Id.True, p.count + 1, 1);
837 token.* = Token.init(Token.Id.True, p.count + 1, 1);
797838 },
798839 else => {
799840 return error.InvalidLiteral;
......@@ -819,7 +860,7 @@ const StreamingJsonParser = struct {
819860 'e' => {
820861 p.state = p.after_value_state;
821862 p.complete = p.state == State.TopLevelEnd;
822 *token = Token.init(Token.Id.False, p.count + 1, 1);
863 token.* = Token.init(Token.Id.False, p.count + 1, 1);
823864 },
824865 else => {
825866 return error.InvalidLiteral;
......@@ -840,7 +881,7 @@ const StreamingJsonParser = struct {
840881 'l' => {
841882 p.state = p.after_value_state;
842883 p.complete = p.state == State.TopLevelEnd;
843 *token = Token.init(Token.Id.Null, p.count + 1, 1);
884 token.* = Token.init(Token.Id.Null, p.count + 1, 1);
844885 },
845886 else => {
846887 return error.InvalidLiteral;
......@@ -895,7 +936,7 @@ pub const Value = union(enum) {
895936 Object: ObjectMap,
896937
897938 pub fn dump(self: &const Value) void {
898 switch (*self) {
939 switch (self.*) {
899940 Value.Null => {
900941 std.debug.warn("null");
901942 },
......@@ -950,7 +991,7 @@ pub const Value = union(enum) {
950991 }
951992
952993 fn dumpIndentLevel(self: &const Value, indent: usize, level: usize) void {
953 switch (*self) {
994 switch (self.*) {
954995 Value.Null => {
955996 std.debug.warn("null");
956997 },
......@@ -1012,7 +1053,7 @@ pub const Value = union(enum) {
10121053};
10131054
10141055// A non-stream JSON parser which constructs a tree of Value's.
1015const JsonParser = struct {
1056pub const JsonParser = struct {
10161057 allocator: &Allocator,
10171058 state: State,
10181059 copy_strings: bool,
......@@ -1027,7 +1068,7 @@ const JsonParser = struct {
10271068 };
10281069
10291070 pub fn init(allocator: &Allocator, copy_strings: bool) JsonParser {
1030 return JsonParser {
1071 return JsonParser{
10311072 .allocator = allocator,
10321073 .state = State.Simple,
10331074 .copy_strings = copy_strings,
......@@ -1082,7 +1123,7 @@ const JsonParser = struct {
10821123
10831124 std.debug.assert(p.stack.len == 1);
10841125
1085 return ValueTree {
1126 return ValueTree{
10861127 .arena = arena,
10871128 .root = p.stack.at(0),
10881129 };
......@@ -1115,11 +1156,11 @@ const JsonParser = struct {
11151156
11161157 switch (token.id) {
11171158 Token.Id.ObjectBegin => {
1118 try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
1159 try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
11191160 p.state = State.ObjectKey;
11201161 },
11211162 Token.Id.ArrayBegin => {
1122 try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
1163 try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) });
11231164 p.state = State.ArrayValue;
11241165 },
11251166 Token.Id.String => {
......@@ -1133,12 +1174,12 @@ const JsonParser = struct {
11331174 p.state = State.ObjectKey;
11341175 },
11351176 Token.Id.True => {
1136 _ = try object.put(key, Value { .Bool = true });
1177 _ = try object.put(key, Value{ .Bool = true });
11371178 _ = p.stack.pop();
11381179 p.state = State.ObjectKey;
11391180 },
11401181 Token.Id.False => {
1141 _ = try object.put(key, Value { .Bool = false });
1182 _ = try object.put(key, Value{ .Bool = false });
11421183 _ = p.stack.pop();
11431184 p.state = State.ObjectKey;
11441185 },
......@@ -1165,11 +1206,11 @@ const JsonParser = struct {
11651206 try p.pushToParent(value);
11661207 },
11671208 Token.Id.ObjectBegin => {
1168 try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
1209 try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
11691210 p.state = State.ObjectKey;
11701211 },
11711212 Token.Id.ArrayBegin => {
1172 try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
1213 try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) });
11731214 p.state = State.ArrayValue;
11741215 },
11751216 Token.Id.String => {
......@@ -1179,10 +1220,10 @@ const JsonParser = struct {
11791220 try array.append(try p.parseNumber(token, input, i));
11801221 },
11811222 Token.Id.True => {
1182 try array.append(Value { .Bool = true });
1223 try array.append(Value{ .Bool = true });
11831224 },
11841225 Token.Id.False => {
1185 try array.append(Value { .Bool = false });
1226 try array.append(Value{ .Bool = false });
11861227 },
11871228 Token.Id.Null => {
11881229 try array.append(Value.Null);
......@@ -1194,11 +1235,11 @@ const JsonParser = struct {
11941235 },
11951236 State.Simple => switch (token.id) {
11961237 Token.Id.ObjectBegin => {
1197 try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
1238 try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
11981239 p.state = State.ObjectKey;
11991240 },
12001241 Token.Id.ArrayBegin => {
1201 try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
1242 try p.stack.append(Value{ .Array = ArrayList(Value).init(allocator) });
12021243 p.state = State.ArrayValue;
12031244 },
12041245 Token.Id.String => {
......@@ -1208,15 +1249,16 @@ const JsonParser = struct {
12081249 try p.stack.append(try p.parseNumber(token, input, i));
12091250 },
12101251 Token.Id.True => {
1211 try p.stack.append(Value { .Bool = true });
1252 try p.stack.append(Value{ .Bool = true });
12121253 },
12131254 Token.Id.False => {
1214 try p.stack.append(Value { .Bool = false });
1255 try p.stack.append(Value{ .Bool = false });
12151256 },
12161257 Token.Id.Null => {
12171258 try p.stack.append(Value.Null);
12181259 },
1219 Token.Id.ObjectEnd, Token.Id.ArrayEnd => {
1260 Token.Id.ObjectEnd,
1261 Token.Id.ArrayEnd => {
12201262 unreachable;
12211263 },
12221264 },
......@@ -1248,15 +1290,14 @@ const JsonParser = struct {
12481290 // TODO: We don't strictly have to copy values which do not contain any escape
12491291 // characters if flagged with the option.
12501292 const slice = token.slice(input, i);
1251 return Value { .String = try mem.dupe(p.allocator, u8, slice) };
1293 return Value{ .String = try mem.dupe(p.allocator, u8, slice) };
12521294 }
12531295
12541296 fn parseNumber(p: &JsonParser, token: &const Token, input: []const u8, i: usize) !Value {
12551297 return if (token.number_is_integer)
1256 Value { .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
1298 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
12571299 else
1258 @panic("TODO: fmt.parseFloat not yet implemented")
1259 ;
1300 @panic("TODO: fmt.parseFloat not yet implemented");
12601301 }
12611302};
12621303
......@@ -1267,21 +1308,21 @@ test "json parser dynamic" {
12671308 defer p.deinit();
12681309
12691310 const s =
1270 \\{
1271 \\ "Image": {
1272 \\ "Width": 800,
1273 \\ "Height": 600,
1274 \\ "Title": "View from 15th Floor",
1275 \\ "Thumbnail": {
1276 \\ "Url": "http://www.example.com/image/481989943",
1277 \\ "Height": 125,
1278 \\ "Width": 100
1279 \\ },
1280 \\ "Animated" : false,
1281 \\ "IDs": [116, 943, 234, 38793]
1282 \\ }
1283 \\}
1284 ;
1311 \\{
1312 \\ "Image": {
1313 \\ "Width": 800,
1314 \\ "Height": 600,
1315 \\ "Title": "View from 15th Floor",
1316 \\ "Thumbnail": {
1317 \\ "Url": "http://www.example.com/image/481989943",
1318 \\ "Height": 125,
1319 \\ "Width": 100
1320 \\ },
1321 \\ "Animated" : false,
1322 \\ "IDs": [116, 943, 234, 38793]
1323 \\ }
1324 \\}
1325 ;
12851326
12861327 var tree = try p.parse(s);
12871328 defer tree.deinit();
std/json_test.zig+15-45
......@@ -431,15 +431,11 @@ test "y_string_two-byte-utf-8" {
431431}
432432
433433test "y_string_u+2028_line_sep" {
434 ok(
435 \\["
"]
436 );
434 ok("[\"\xe2\x80\xa8\"]");
437435}
438436
439437test "y_string_u+2029_par_sep" {
440 ok(
441 \\["
"]
442 );
438 ok("[\"\xe2\x80\xa9\"]");
443439}
444440
445441test "y_string_uescaped_newline" {
......@@ -455,9 +451,7 @@ test "y_string_uEscape" {
455451}
456452
457453test "y_string_unescaped_char_delete" {
458 ok(
459 \\[""]
460 );
454 ok("[\"\x7f\"]");
461455}
462456
463457test "y_string_unicode_2" {
......@@ -527,9 +521,7 @@ test "y_string_utf8" {
527521}
528522
529523test "y_string_with_del_character" {
530 ok(
531 \\["aa"]
532 );
524 ok("[\"a\x7fa\"]");
533525}
534526
535527test "y_structure_lonely_false" {
......@@ -718,9 +710,7 @@ test "n_array_number_and_several_commas" {
718710}
719711
720712test "n_array_spaces_vertical_tab_formfeed" {
721 err(
722 \\[" a"\f]
723 );
713 err("[\"\x0aa\"\\f]");
724714}
725715
726716test "n_array_star_inside" {
......@@ -774,9 +764,7 @@ test "n_incomplete_true" {
774764}
775765
776766test "n_multidigit_number_then_00" {
777 err(
778 \\123
779 );
767 err("123\x00");
780768}
781769
782770test "n_number_0.1.2" {
......@@ -1309,9 +1297,7 @@ test "n_string_escaped_ctrl_char_tab" {
13091297}
13101298
13111299test "n_string_escaped_emoji" {
1312 err(
1313 \\["\🌀"]
1314 );
1300 err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
13151301}
13161302
13171303test "n_string_escape_x" {
......@@ -1357,9 +1343,7 @@ test "n_string_invalid_unicode_escape" {
13571343}
13581344
13591345test "n_string_invalid_utf8_after_escape" {
1360 err(
1361 \\["\å"]
1362 );
1346 err("[\"\\\x75\xc3\xa5\"]");
13631347}
13641348
13651349test "n_string_invalid-utf-8-in-escape" {
......@@ -1405,9 +1389,7 @@ test "n_string_start_escape_unclosed" {
14051389}
14061390
14071391test "n_string_unescaped_crtl_char" {
1408 err(
1409 \\["aa"]
1410 );
1392 err("[\"a\x00a\"]");
14111393}
14121394
14131395test "n_string_unescaped_newline" {
......@@ -1418,9 +1400,7 @@ test "n_string_unescaped_newline" {
14181400}
14191401
14201402test "n_string_unescaped_tab" {
1421 err(
1422 \\[" "]
1423 );
1403 err("[\"\t\"]");
14241404}
14251405
14261406test "n_string_unicode_CapitalU" {
......@@ -1532,9 +1512,7 @@ test "n_structure_no_data" {
15321512}
15331513
15341514test "n_structure_null-byte-outside-string" {
1535 err(
1536 \\[]
1537 );
1515 err("[\x00]");
15381516}
15391517
15401518test "n_structure_number_with_trailing_garbage" {
......@@ -1718,9 +1696,7 @@ test "n_structure_UTF8_BOM_no_data" {
17181696}
17191697
17201698test "n_structure_whitespace_formfeed" {
1721 err(
1722 \\[ ]
1723 );
1699 err("[\x0c]");
17241700}
17251701
17261702test "n_structure_whitespace_U+2060_word_joiner" {
......@@ -1900,21 +1876,15 @@ test "i_string_truncated-utf-8" {
19001876}
19011877
19021878test "i_string_utf16BE_no_BOM" {
1903 any(
1904 \\["é"]
1905 );
1879 any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
19061880}
19071881
19081882test "i_string_utf16LE_no_BOM" {
1909 any(
1910 \\["é"]
1911 );
1883 any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
19121884}
19131885
19141886test "i_string_UTF-16LE_with_BOM" {
1915 any(
1916 \\ÿþ["é"]
1917 );
1887 any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
19181888}
19191889
19201890test "i_string_UTF-8_invalid_sequence" {
std/linked_list.zig+55-40
......@@ -26,10 +26,10 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
2626 data: T,
2727
2828 pub fn init(value: &const T) Node {
29 return Node {
29 return Node{
3030 .prev = null,
3131 .next = null,
32 .data = *value,
32 .data = value.*,
3333 };
3434 }
3535
......@@ -45,18 +45,18 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
4545 };
4646
4747 first: ?&Node,
48 last: ?&Node,
49 len: usize,
48 last: ?&Node,
49 len: usize,
5050
5151 /// Initialize a linked list.
5252 ///
5353 /// Returns:
5454 /// An empty linked list.
5555 pub fn init() Self {
56 return Self {
56 return Self{
5757 .first = null,
58 .last = null,
59 .len = 0,
58 .last = null,
59 .len = 0,
6060 };
6161 }
6262
......@@ -131,7 +131,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
131131 } else {
132132 // Empty list.
133133 list.first = new_node;
134 list.last = new_node;
134 list.last = new_node;
135135 new_node.prev = null;
136136 new_node.next = null;
137137
......@@ -217,7 +217,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na
217217 pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) !&Node {
218218 comptime assert(!isIntrusive());
219219 var node = try list.allocateNode(allocator);
220 *node = Node.init(data);
220 node.* = Node.init(data);
221221 return node;
222222 }
223223 };
......@@ -227,11 +227,11 @@ test "basic linked list test" {
227227 const allocator = debug.global_allocator;
228228 var list = LinkedList(u32).init();
229229
230 var one = try list.createNode(1, allocator);
231 var two = try list.createNode(2, allocator);
230 var one = try list.createNode(1, allocator);
231 var two = try list.createNode(2, allocator);
232232 var three = try list.createNode(3, allocator);
233 var four = try list.createNode(4, allocator);
234 var five = try list.createNode(5, allocator);
233 var four = try list.createNode(4, allocator);
234 var five = try list.createNode(5, allocator);
235235 defer {
236236 list.destroyNode(one, allocator);
237237 list.destroyNode(two, allocator);
......@@ -240,11 +240,11 @@ test "basic linked list test" {
240240 list.destroyNode(five, allocator);
241241 }
242242
243 list.append(two); // {2}
244 list.append(five); // {2, 5}
245 list.prepend(one); // {1, 2, 5}
246 list.insertBefore(five, four); // {1, 2, 4, 5}
247 list.insertAfter(two, three); // {1, 2, 3, 4, 5}
243 list.append(two); // {2}
244 list.append(five); // {2, 5}
245 list.prepend(one); // {1, 2, 5}
246 list.insertBefore(five, four); // {1, 2, 4, 5}
247 list.insertAfter(two, three); // {1, 2, 3, 4, 5}
248248
249249 // Traverse forwards.
250250 {
......@@ -266,13 +266,13 @@ test "basic linked list test" {
266266 }
267267 }
268268
269 var first = list.popFirst(); // {2, 3, 4, 5}
270 var last = list.pop(); // {2, 3, 4}
271 list.remove(three); // {2, 4}
269 var first = list.popFirst(); // {2, 3, 4, 5}
270 var last = list.pop(); // {2, 3, 4}
271 list.remove(three); // {2, 4}
272272
273 assert ((??list.first).data == 2);
274 assert ((??list.last ).data == 4);
275 assert (list.len == 2);
273 assert((??list.first).data == 2);
274 assert((??list.last).data == 4);
275 assert(list.len == 2);
276276}
277277
278278const ElementList = IntrusiveLinkedList(Element, "link");
......@@ -285,17 +285,32 @@ test "basic intrusive linked list test" {
285285 const allocator = debug.global_allocator;
286286 var list = ElementList.init();
287287
288 var one = Element { .value = 1, .link = ElementList.Node.initIntrusive() };
289 var two = Element { .value = 2, .link = ElementList.Node.initIntrusive() };
290 var three = Element { .value = 3, .link = ElementList.Node.initIntrusive() };
291 var four = Element { .value = 4, .link = ElementList.Node.initIntrusive() };
292 var five = Element { .value = 5, .link = ElementList.Node.initIntrusive() };
288 var one = Element{
289 .value = 1,
290 .link = ElementList.Node.initIntrusive(),
291 };
292 var two = Element{
293 .value = 2,
294 .link = ElementList.Node.initIntrusive(),
295 };
296 var three = Element{
297 .value = 3,
298 .link = ElementList.Node.initIntrusive(),
299 };
300 var four = Element{
301 .value = 4,
302 .link = ElementList.Node.initIntrusive(),
303 };
304 var five = Element{
305 .value = 5,
306 .link = ElementList.Node.initIntrusive(),
307 };
293308
294 list.append(&two.link); // {2}
295 list.append(&five.link); // {2, 5}
296 list.prepend(&one.link); // {1, 2, 5}
297 list.insertBefore(&five.link, &four.link); // {1, 2, 4, 5}
298 list.insertAfter(&two.link, &three.link); // {1, 2, 3, 4, 5}
309 list.append(&two.link); // {2}
310 list.append(&five.link); // {2, 5}
311 list.prepend(&one.link); // {1, 2, 5}
312 list.insertBefore(&five.link, &four.link); // {1, 2, 4, 5}
313 list.insertAfter(&two.link, &three.link); // {1, 2, 3, 4, 5}
299314
300315 // Traverse forwards.
301316 {
......@@ -317,11 +332,11 @@ test "basic intrusive linked list test" {
317332 }
318333 }
319334
320 var first = list.popFirst(); // {2, 3, 4, 5}
321 var last = list.pop(); // {2, 3, 4}
322 list.remove(&three.link); // {2, 4}
335 var first = list.popFirst(); // {2, 3, 4, 5}
336 var last = list.pop(); // {2, 3, 4}
337 list.remove(&three.link); // {2, 4}
323338
324 assert ((??list.first).toData().value == 2);
325 assert ((??list.last ).toData().value == 4);
326 assert (list.len == 2);
339 assert((??list.first).toData().value == 2);
340 assert((??list.last).toData().value == 4);
341 assert(list.len == 2);
327342}
std/math/acos.zig+7-7
......@@ -16,7 +16,7 @@ pub fn acos(x: var) @typeOf(x) {
1616}
1717
1818fn r32(z: f32) f32 {
19 const pS0 = 1.6666586697e-01;
19 const pS0 = 1.6666586697e-01;
2020 const pS1 = -4.2743422091e-02;
2121 const pS2 = -8.6563630030e-03;
2222 const qS1 = -7.0662963390e-01;
......@@ -74,16 +74,16 @@ fn acos32(x: f32) f32 {
7474}
7575
7676fn r64(z: f64) f64 {
77 const pS0: f64 = 1.66666666666666657415e-01;
77 const pS0: f64 = 1.66666666666666657415e-01;
7878 const pS1: f64 = -3.25565818622400915405e-01;
79 const pS2: f64 = 2.01212532134862925881e-01;
79 const pS2: f64 = 2.01212532134862925881e-01;
8080 const pS3: f64 = -4.00555345006794114027e-02;
81 const pS4: f64 = 7.91534994289814532176e-04;
82 const pS5: f64 = 3.47933107596021167570e-05;
81 const pS4: f64 = 7.91534994289814532176e-04;
82 const pS5: f64 = 3.47933107596021167570e-05;
8383 const qS1: f64 = -2.40339491173441421878e+00;
84 const qS2: f64 = 2.02094576023350569471e+00;
84 const qS2: f64 = 2.02094576023350569471e+00;
8585 const qS3: f64 = -6.88283971605453293030e-01;
86 const qS4: f64 = 7.70381505559019352791e-02;
86 const qS4: f64 = 7.70381505559019352791e-02;
8787
8888 const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
8989 const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
std/math/asin.zig+9-9
......@@ -17,7 +17,7 @@ pub fn asin(x: var) @typeOf(x) {
1717}
1818
1919fn r32(z: f32) f32 {
20 const pS0 = 1.6666586697e-01;
20 const pS0 = 1.6666586697e-01;
2121 const pS1 = -4.2743422091e-02;
2222 const pS2 = -8.6563630030e-03;
2323 const qS1 = -7.0662963390e-01;
......@@ -37,9 +37,9 @@ fn asin32(x: f32) f32 {
3737 if (ix >= 0x3F800000) {
3838 // |x| >= 1
3939 if (ix == 0x3F800000) {
40 return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact
40 return x * pio2 + 0x1.0p-120; // asin(+-1) = +-pi/2 with inexact
4141 } else {
42 return math.nan(f32); // asin(|x| > 1) is nan
42 return math.nan(f32); // asin(|x| > 1) is nan
4343 }
4444 }
4545
......@@ -66,16 +66,16 @@ fn asin32(x: f32) f32 {
6666}
6767
6868fn r64(z: f64) f64 {
69 const pS0: f64 = 1.66666666666666657415e-01;
69 const pS0: f64 = 1.66666666666666657415e-01;
7070 const pS1: f64 = -3.25565818622400915405e-01;
71 const pS2: f64 = 2.01212532134862925881e-01;
71 const pS2: f64 = 2.01212532134862925881e-01;
7272 const pS3: f64 = -4.00555345006794114027e-02;
73 const pS4: f64 = 7.91534994289814532176e-04;
74 const pS5: f64 = 3.47933107596021167570e-05;
73 const pS4: f64 = 7.91534994289814532176e-04;
74 const pS5: f64 = 3.47933107596021167570e-05;
7575 const qS1: f64 = -2.40339491173441421878e+00;
76 const qS2: f64 = 2.02094576023350569471e+00;
76 const qS2: f64 = 2.02094576023350569471e+00;
7777 const qS3: f64 = -6.88283971605453293030e-01;
78 const qS4: f64 = 7.70381505559019352791e-02;
78 const qS4: f64 = 7.70381505559019352791e-02;
7979
8080 const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5)))));
8181 const q = 1.0 + z * (qS1 + z * (qS2 + z * (qS3 + z * qS4)));
std/math/atan2.zig+34-32
......@@ -31,7 +31,7 @@ pub fn atan2(comptime T: type, x: T, y: T) T {
3131}
3232
3333fn atan2_32(y: f32, x: f32) f32 {
34 const pi: f32 = 3.1415927410e+00;
34 const pi: f32 = 3.1415927410e+00;
3535 const pi_lo: f32 = -8.7422776573e-08;
3636
3737 if (math.isNan(x) or math.isNan(y)) {
......@@ -53,9 +53,10 @@ fn atan2_32(y: f32, x: f32) f32 {
5353
5454 if (iy == 0) {
5555 switch (m) {
56 0, 1 => return y, // atan(+-0, +...)
57 2 => return pi, // atan(+0, -...)
58 3 => return -pi, // atan(-0, -...)
56 0,
57 1 => return y, // atan(+-0, +...)
58 2 => return pi, // atan(+0, -...)
59 3 => return -pi, // atan(-0, -...)
5960 else => unreachable,
6061 }
6162 }
......@@ -71,18 +72,18 @@ fn atan2_32(y: f32, x: f32) f32 {
7172 if (ix == 0x7F800000) {
7273 if (iy == 0x7F800000) {
7374 switch (m) {
74 0 => return pi / 4, // atan(+inf, +inf)
75 1 => return -pi / 4, // atan(-inf, +inf)
76 2 => return 3*pi / 4, // atan(+inf, -inf)
77 3 => return -3*pi / 4, // atan(-inf, -inf)
75 0 => return pi / 4, // atan(+inf, +inf)
76 1 => return -pi / 4, // atan(-inf, +inf)
77 2 => return 3 * pi / 4, // atan(+inf, -inf)
78 3 => return -3 * pi / 4, // atan(-inf, -inf)
7879 else => unreachable,
7980 }
8081 } else {
8182 switch (m) {
82 0 => return 0.0, // atan(+..., +inf)
83 1 => return -0.0, // atan(-..., +inf)
84 2 => return pi, // atan(+..., -inf)
85 3 => return -pi, // atan(-...f, -inf)
83 0 => return 0.0, // atan(+..., +inf)
84 1 => return -0.0, // atan(-..., +inf)
85 2 => return pi, // atan(+..., -inf)
86 3 => return -pi, // atan(-...f, -inf)
8687 else => unreachable,
8788 }
8889 }
......@@ -107,16 +108,16 @@ fn atan2_32(y: f32, x: f32) f32 {
107108 };
108109
109110 switch (m) {
110 0 => return z, // atan(+, +)
111 1 => return -z, // atan(-, +)
112 2 => return pi - (z - pi_lo), // atan(+, -)
113 3 => return (z - pi_lo) - pi, // atan(-, -)
111 0 => return z, // atan(+, +)
112 1 => return -z, // atan(-, +)
113 2 => return pi - (z - pi_lo), // atan(+, -)
114 3 => return (z - pi_lo) - pi, // atan(-, -)
114115 else => unreachable,
115116 }
116117}
117118
118119fn atan2_64(y: f64, x: f64) f64 {
119 const pi: f64 = 3.1415926535897931160E+00;
120 const pi: f64 = 3.1415926535897931160E+00;
120121 const pi_lo: f64 = 1.2246467991473531772E-16;
121122
122123 if (math.isNan(x) or math.isNan(y)) {
......@@ -143,9 +144,10 @@ fn atan2_64(y: f64, x: f64) f64 {
143144
144145 if (iy | ly == 0) {
145146 switch (m) {
146 0, 1 => return y, // atan(+-0, +...)
147 2 => return pi, // atan(+0, -...)
148 3 => return -pi, // atan(-0, -...)
147 0,
148 1 => return y, // atan(+-0, +...)
149 2 => return pi, // atan(+0, -...)
150 3 => return -pi, // atan(-0, -...)
149151 else => unreachable,
150152 }
151153 }
......@@ -161,18 +163,18 @@ fn atan2_64(y: f64, x: f64) f64 {
161163 if (ix == 0x7FF00000) {
162164 if (iy == 0x7FF00000) {
163165 switch (m) {
164 0 => return pi / 4, // atan(+inf, +inf)
165 1 => return -pi / 4, // atan(-inf, +inf)
166 2 => return 3*pi / 4, // atan(+inf, -inf)
167 3 => return -3*pi / 4, // atan(-inf, -inf)
166 0 => return pi / 4, // atan(+inf, +inf)
167 1 => return -pi / 4, // atan(-inf, +inf)
168 2 => return 3 * pi / 4, // atan(+inf, -inf)
169 3 => return -3 * pi / 4, // atan(-inf, -inf)
168170 else => unreachable,
169171 }
170172 } else {
171173 switch (m) {
172 0 => return 0.0, // atan(+..., +inf)
173 1 => return -0.0, // atan(-..., +inf)
174 2 => return pi, // atan(+..., -inf)
175 3 => return -pi, // atan(-...f, -inf)
174 0 => return 0.0, // atan(+..., +inf)
175 1 => return -0.0, // atan(-..., +inf)
176 2 => return pi, // atan(+..., -inf)
177 3 => return -pi, // atan(-...f, -inf)
176178 else => unreachable,
177179 }
178180 }
......@@ -197,10 +199,10 @@ fn atan2_64(y: f64, x: f64) f64 {
197199 };
198200
199201 switch (m) {
200 0 => return z, // atan(+, +)
201 1 => return -z, // atan(-, +)
202 2 => return pi - (z - pi_lo), // atan(+, -)
203 3 => return (z - pi_lo) - pi, // atan(-, -)
202 0 => return z, // atan(+, +)
203 1 => return -z, // atan(-, +)
204 2 => return pi - (z - pi_lo), // atan(+, -)
205 3 => return (z - pi_lo) - pi, // atan(-, -)
204206 else => unreachable,
205207 }
206208}
std/math/cbrt.zig+5-5
......@@ -58,15 +58,15 @@ fn cbrt32(x: f32) f32 {
5858}
5959
6060fn cbrt64(x: f64) f64 {
61 const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20
62 const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20
61 const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20
62 const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20
6363
6464 // |1 / cbrt(x) - p(x)| < 2^(23.5)
65 const P0: f64 = 1.87595182427177009643;
65 const P0: f64 = 1.87595182427177009643;
6666 const P1: f64 = -1.88497979543377169875;
67 const P2: f64 = 1.621429720105354466140;
67 const P2: f64 = 1.621429720105354466140;
6868 const P3: f64 = -0.758397934778766047437;
69 const P4: f64 = 0.145996192886612446982;
69 const P4: f64 = 0.145996192886612446982;
7070
7171 var u = @bitCast(u64, x);
7272 var hx = u32(u >> 32) & 0x7FFFFFFF;
std/math/ceil.zig+2-2
......@@ -56,7 +56,7 @@ fn ceil64(x: f64) f64 {
5656 const e = (u >> 52) & 0x7FF;
5757 var y: f64 = undefined;
5858
59 if (e >= 0x3FF+52 or x == 0) {
59 if (e >= 0x3FF + 52 or x == 0) {
6060 return x;
6161 }
6262
......@@ -68,7 +68,7 @@ fn ceil64(x: f64) f64 {
6868 y = x + math.f64_toint - math.f64_toint - x;
6969 }
7070
71 if (e <= 0x3FF-1) {
71 if (e <= 0x3FF - 1) {
7272 math.forceEval(y);
7373 if (u >> 63 != 0) {
7474 return -0.0;
std/math/complex/exp.zig+11-17
......@@ -19,8 +19,8 @@ pub fn exp(z: var) Complex(@typeOf(z.re)) {
1919fn exp32(z: &const Complex(f32)) Complex(f32) {
2020 @setFloatMode(this, @import("builtin").FloatMode.Strict);
2121
22 const exp_overflow = 0x42b17218; // max_exp * ln2 ~= 88.72283955
23 const cexp_overflow = 0x43400074; // (max_exp - min_denom_exp) * ln2
22 const exp_overflow = 0x42b17218; // max_exp * ln2 ~= 88.72283955
23 const cexp_overflow = 0x43400074; // (max_exp - min_denom_exp) * ln2
2424
2525 const x = z.re;
2626 const y = z.im;
......@@ -41,12 +41,10 @@ fn exp32(z: &const Complex(f32)) Complex(f32) {
4141 // cexp(finite|nan +- i inf|nan) = nan + i nan
4242 if ((hx & 0x7fffffff) != 0x7f800000) {
4343 return Complex(f32).new(y - y, y - y);
44 }
45 // cexp(-inf +- i inf|nan) = 0 + i0
44 } // cexp(-inf +- i inf|nan) = 0 + i0
4645 else if (hx & 0x80000000 != 0) {
4746 return Complex(f32).new(0, 0);
48 }
49 // cexp(+inf +- i inf|nan) = inf + i nan
47 } // cexp(+inf +- i inf|nan) = inf + i nan
5048 else {
5149 return Complex(f32).new(x, y - y);
5250 }
......@@ -55,8 +53,7 @@ fn exp32(z: &const Complex(f32)) Complex(f32) {
5553 // 88.7 <= x <= 192 so must scale
5654 if (hx >= exp_overflow and hx <= cexp_overflow) {
5755 return ldexp_cexp(z, 0);
58 }
59 // - x < exp_overflow => exp(x) won't overflow (common)
56 } // - x < exp_overflow => exp(x) won't overflow (common)
6057 // - x > cexp_overflow, so exp(x) * s overflows for s > 0
6158 // - x = +-inf
6259 // - x = nan
......@@ -67,8 +64,8 @@ fn exp32(z: &const Complex(f32)) Complex(f32) {
6764}
6865
6966fn exp64(z: &const Complex(f64)) Complex(f64) {
70 const exp_overflow = 0x40862e42; // high bits of max_exp * ln2 ~= 710
71 const cexp_overflow = 0x4096b8e4; // (max_exp - min_denorm_exp) * ln2
67 const exp_overflow = 0x40862e42; // high bits of max_exp * ln2 ~= 710
68 const cexp_overflow = 0x4096b8e4; // (max_exp - min_denorm_exp) * ln2
7269
7370 const x = z.re;
7471 const y = z.im;
......@@ -95,12 +92,10 @@ fn exp64(z: &const Complex(f64)) Complex(f64) {
9592 // cexp(finite|nan +- i inf|nan) = nan + i nan
9693 if (lx != 0 or (hx & 0x7fffffff) != 0x7ff00000) {
9794 return Complex(f64).new(y - y, y - y);
98 }
99 // cexp(-inf +- i inf|nan) = 0 + i0
95 } // cexp(-inf +- i inf|nan) = 0 + i0
10096 else if (hx & 0x80000000 != 0) {
10197 return Complex(f64).new(0, 0);
102 }
103 // cexp(+inf +- i inf|nan) = inf + i nan
98 } // cexp(+inf +- i inf|nan) = inf + i nan
10499 else {
105100 return Complex(f64).new(x, y - y);
106101 }
......@@ -109,9 +104,8 @@ fn exp64(z: &const Complex(f64)) Complex(f64) {
109104 // 709.7 <= x <= 1454.3 so must scale
110105 if (hx >= exp_overflow and hx <= cexp_overflow) {
111106 const r = ldexp_cexp(z, 0);
112 return *r;
113 }
114 // - x < exp_overflow => exp(x) won't overflow (common)
107 return r.*;
108 } // - x < exp_overflow => exp(x) won't overflow (common)
115109 // - x > cexp_overflow, so exp(x) * s overflows for s > 0
116110 // - x = +-inf
117111 // - x = nan
std/math/complex/ldexp.zig+7-10
......@@ -15,12 +15,12 @@ pub fn ldexp_cexp(z: var, expt: i32) Complex(@typeOf(z.re)) {
1515}
1616
1717fn frexp_exp32(x: f32, expt: &i32) f32 {
18 const k = 235; // reduction constant
19 const kln2 = 162.88958740; // k * ln2
18 const k = 235; // reduction constant
19 const kln2 = 162.88958740; // k * ln2
2020
2121 const exp_x = math.exp(x - kln2);
2222 const hx = @bitCast(u32, exp_x);
23 *expt = i32(hx >> 23) - (0x7f + 127) + k;
23 expt.* = i32(hx >> 23) - (0x7f + 127) + k;
2424 return @bitCast(f32, (hx & 0x7fffff) | ((0x7f + 127) << 23));
2525}
2626
......@@ -35,15 +35,12 @@ fn ldexp_cexp32(z: &const Complex(f32), expt: i32) Complex(f32) {
3535 const half_expt2 = exptf - half_expt1;
3636 const scale2 = @bitCast(f32, (0x7f + half_expt2) << 23);
3737
38 return Complex(f32).new(
39 math.cos(z.im) * exp_x * scale1 * scale2,
40 math.sin(z.im) * exp_x * scale1 * scale2,
41 );
38 return Complex(f32).new(math.cos(z.im) * exp_x * scale1 * scale2, math.sin(z.im) * exp_x * scale1 * scale2);
4239}
4340
4441fn frexp_exp64(x: f64, expt: &i32) f64 {
45 const k = 1799; // reduction constant
46 const kln2 = 1246.97177782734161156; // k * ln2
42 const k = 1799; // reduction constant
43 const kln2 = 1246.97177782734161156; // k * ln2
4744
4845 const exp_x = math.exp(x - kln2);
4946
......@@ -51,7 +48,7 @@ fn frexp_exp64(x: f64, expt: &i32) f64 {
5148 const hx = u32(fx >> 32);
5249 const lx = @truncate(u32, fx);
5350
54 *expt = i32(hx >> 20) - (0x3ff + 1023) + k;
51 expt.* = i32(hx >> 20) - (0x3ff + 1023) + k;
5552
5653 const high_word = (hx & 0xfffff) | ((0x3ff + 1023) << 20);
5754 return @bitCast(f64, (u64(high_word) << 32) | lx);
std/math/cos.zig+6-6
......@@ -18,20 +18,20 @@ pub fn cos(x: var) @typeOf(x) {
1818}
1919
2020// sin polynomial coefficients
21const S0 = 1.58962301576546568060E-10;
21const S0 = 1.58962301576546568060E-10;
2222const S1 = -2.50507477628578072866E-8;
23const S2 = 2.75573136213857245213E-6;
23const S2 = 2.75573136213857245213E-6;
2424const S3 = -1.98412698295895385996E-4;
25const S4 = 8.33333333332211858878E-3;
25const S4 = 8.33333333332211858878E-3;
2626const S5 = -1.66666666666666307295E-1;
2727
2828// cos polynomial coeffiecients
2929const C0 = -1.13585365213876817300E-11;
30const C1 = 2.08757008419747316778E-9;
30const C1 = 2.08757008419747316778E-9;
3131const C2 = -2.75573141792967388112E-7;
32const C3 = 2.48015872888517045348E-5;
32const C3 = 2.48015872888517045348E-5;
3333const C4 = -1.38888888888730564116E-3;
34const C5 = 4.16666666666665929218E-2;
34const C5 = 4.16666666666665929218E-2;
3535
3636// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
3737//
std/math/floor.zig+2-2
......@@ -57,7 +57,7 @@ fn floor64(x: f64) f64 {
5757 const e = (u >> 52) & 0x7FF;
5858 var y: f64 = undefined;
5959
60 if (e >= 0x3FF+52 or x == 0) {
60 if (e >= 0x3FF + 52 or x == 0) {
6161 return x;
6262 }
6363
......@@ -69,7 +69,7 @@ fn floor64(x: f64) f64 {
6969 y = x + math.f64_toint - math.f64_toint - x;
7070 }
7171
72 if (e <= 0x3FF-1) {
72 if (e <= 0x3FF - 1) {
7373 math.forceEval(y);
7474 if (u >> 63 != 0) {
7575 return -1.0;
std/math/fma.zig+5-2
......@@ -5,7 +5,7 @@ const assert = std.debug.assert;
55pub fn fma(comptime T: type, x: T, y: T, z: T) T {
66 return switch (T) {
77 f32 => fma32(x, y, z),
8 f64 => fma64(x, y ,z),
8 f64 => fma64(x, y, z),
99 else => @compileError("fma not implemented for " ++ @typeName(T)),
1010 };
1111}
......@@ -71,7 +71,10 @@ fn fma64(x: f64, y: f64, z: f64) f64 {
7171 }
7272}
7373
74const dd = struct { hi: f64, lo: f64, };
74const dd = struct {
75 hi: f64,
76 lo: f64,
77};
7578
7679fn dd_add(a: f64, b: f64) dd {
7780 var ret: dd = undefined;
std/math/hypot.zig+4-4
......@@ -39,11 +39,11 @@ fn hypot32(x: f32, y: f32) f32 {
3939 }
4040
4141 var z: f32 = 1.0;
42 if (ux >= (0x7F+60) << 23) {
42 if (ux >= (0x7F + 60) << 23) {
4343 z = 0x1.0p90;
4444 xx *= 0x1.0p-90;
4545 yy *= 0x1.0p-90;
46 } else if (uy < (0x7F-60) << 23) {
46 } else if (uy < (0x7F - 60) << 23) {
4747 z = 0x1.0p-90;
4848 xx *= 0x1.0p-90;
4949 yy *= 0x1.0p-90;
......@@ -57,8 +57,8 @@ fn sq(hi: &f64, lo: &f64, x: f64) void {
5757 const xc = x * split;
5858 const xh = x - xc + xc;
5959 const xl = x - xh;
60 *hi = x * x;
61 *lo = xh * xh - *hi + 2 * xh * xl + xl * xl;
60 hi.* = x * x;
61 lo.* = xh * xh - hi.* + 2 * xh * xl + xl * xl;
6262}
6363
6464fn hypot64(x: f64, y: f64) f64 {
std/math/index.zig+29-46
......@@ -47,12 +47,12 @@ pub fn forceEval(value: var) void {
4747 f32 => {
4848 var x: f32 = undefined;
4949 const p = @ptrCast(&volatile f32, &x);
50 *p = x;
50 p.* = x;
5151 },
5252 f64 => {
5353 var x: f64 = undefined;
5454 const p = @ptrCast(&volatile f64, &x);
55 *p = x;
55 p.* = x;
5656 },
5757 else => {
5858 @compileError("forceEval not implemented for " ++ @typeName(T));
......@@ -179,7 +179,6 @@ test "math" {
179179 _ = @import("complex/index.zig");
180180}
181181
182
183182pub fn min(x: var, y: var) @typeOf(x + y) {
184183 return if (x < y) x else y;
185184}
......@@ -280,10 +279,10 @@ pub fn rotr(comptime T: type, x: T, r: var) T {
280279}
281280
282281test "math.rotr" {
283 assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
284 assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
285 assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
286 assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
282 assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
283 assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
284 assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
285 assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
287286 assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
288287}
289288
......@@ -299,14 +298,13 @@ pub fn rotl(comptime T: type, x: T, r: var) T {
299298}
300299
301300test "math.rotl" {
302 assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
303 assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
304 assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
305 assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
301 assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
302 assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
303 assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
304 assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
306305 assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
307306}
308307
309
310308pub fn Log2Int(comptime T: type) type {
311309 return @IntType(false, log2(T.bit_count));
312310}
......@@ -323,14 +321,14 @@ fn testOverflow() void {
323321 assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
324322}
325323
326
327324pub fn absInt(x: var) !@typeOf(x) {
328325 const T = @typeOf(x);
329326 comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
330327 comptime assert(T.is_signed); // must pass a signed integer to absInt
331 if (x == @minValue(@typeOf(x)))
328
329 if (x == @minValue(@typeOf(x))) {
332330 return error.Overflow;
333 {
331 } else {
334332 @setRuntimeSafety(false);
335333 return if (x < 0) -x else x;
336334 }
......@@ -349,10 +347,8 @@ pub const absFloat = @import("fabs.zig").fabs;
349347
350348pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
351349 @setRuntimeSafety(false);
352 if (denominator == 0)
353 return error.DivisionByZero;
354 if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)
355 return error.Overflow;
350 if (denominator == 0) return error.DivisionByZero;
351 if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow;
356352 return @divTrunc(numerator, denominator);
357353}
358354
......@@ -372,10 +368,8 @@ fn testDivTrunc() void {
372368
373369pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
374370 @setRuntimeSafety(false);
375 if (denominator == 0)
376 return error.DivisionByZero;
377 if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)
378 return error.Overflow;
371 if (denominator == 0) return error.DivisionByZero;
372 if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow;
379373 return @divFloor(numerator, denominator);
380374}
381375
......@@ -395,13 +389,10 @@ fn testDivFloor() void {
395389
396390pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
397391 @setRuntimeSafety(false);
398 if (denominator == 0)
399 return error.DivisionByZero;
400 if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)
401 return error.Overflow;
392 if (denominator == 0) return error.DivisionByZero;
393 if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow;
402394 const result = @divTrunc(numerator, denominator);
403 if (result * denominator != numerator)
404 return error.UnexpectedRemainder;
395 if (result * denominator != numerator) return error.UnexpectedRemainder;
405396 return result;
406397}
407398
......@@ -423,10 +414,8 @@ fn testDivExact() void {
423414
424415pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
425416 @setRuntimeSafety(false);
426 if (denominator == 0)
427 return error.DivisionByZero;
428 if (denominator < 0)
429 return error.NegativeDenominator;
417 if (denominator == 0) return error.DivisionByZero;
418 if (denominator < 0) return error.NegativeDenominator;
430419 return @mod(numerator, denominator);
431420}
432421
......@@ -448,10 +437,8 @@ fn testMod() void {
448437
449438pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
450439 @setRuntimeSafety(false);
451 if (denominator == 0)
452 return error.DivisionByZero;
453 if (denominator < 0)
454 return error.NegativeDenominator;
440 if (denominator == 0) return error.DivisionByZero;
441 if (denominator < 0) return error.NegativeDenominator;
455442 return @rem(numerator, denominator);
456443}
457444
......@@ -475,8 +462,7 @@ fn testRem() void {
475462/// Result is an unsigned integer.
476463pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
477464 const uint = @IntType(false, @typeOf(x).bit_count);
478 if (x >= 0)
479 return uint(x);
465 if (x >= 0) return uint(x);
480466
481467 return uint(-(x + 1)) + 1;
482468}
......@@ -495,15 +481,12 @@ test "math.absCast" {
495481/// Returns the negation of the integer parameter.
496482/// Result is a signed integer.
497483pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
498 if (@typeOf(x).is_signed)
499 return negate(x);
484 if (@typeOf(x).is_signed) return negate(x);
500485
501486 const int = @IntType(true, @typeOf(x).bit_count);
502 if (x > -@minValue(int))
503 return error.Overflow;
487 if (x > -@minValue(int)) return error.Overflow;
504488
505 if (x == -@minValue(int))
506 return @minValue(int);
489 if (x == -@minValue(int)) return @minValue(int);
507490
508491 return -int(x);
509492}
......@@ -546,7 +529,7 @@ pub fn floorPowerOfTwo(comptime T: type, value: T) T {
546529 var x = value;
547530
548531 comptime var i = 1;
549 inline while(T.bit_count > i) : (i *= 2) {
532 inline while (T.bit_count > i) : (i *= 2) {
550533 x |= (x >> i);
551534 }
552535
std/math/ln.zig+2-4
......@@ -120,11 +120,9 @@ pub fn ln_64(x_: f64) f64 {
120120 k -= 54;
121121 x *= 0x1.0p54;
122122 hx = u32(@bitCast(u64, ix) >> 32);
123 }
124 else if (hx >= 0x7FF00000) {
123 } else if (hx >= 0x7FF00000) {
125124 return x;
126 }
127 else if (hx == 0x3FF00000 and ix << 32 == 0) {
125 } else if (hx == 0x3FF00000 and ix << 32 == 0) {
128126 return 0;
129127 }
130128
std/math/log10.zig+8-10
......@@ -35,10 +35,10 @@ pub fn log10(x: var) @typeOf(x) {
3535}
3636
3737pub fn log10_32(x_: f32) f32 {
38 const ivln10hi: f32 = 4.3432617188e-01;
39 const ivln10lo: f32 = -3.1689971365e-05;
40 const log10_2hi: f32 = 3.0102920532e-01;
41 const log10_2lo: f32 = 7.9034151668e-07;
38 const ivln10hi: f32 = 4.3432617188e-01;
39 const ivln10lo: f32 = -3.1689971365e-05;
40 const log10_2hi: f32 = 3.0102920532e-01;
41 const log10_2lo: f32 = 7.9034151668e-07;
4242 const Lg1: f32 = 0xaaaaaa.0p-24;
4343 const Lg2: f32 = 0xccce13.0p-25;
4444 const Lg3: f32 = 0x91e9ee.0p-25;
......@@ -95,8 +95,8 @@ pub fn log10_32(x_: f32) f32 {
9595}
9696
9797pub fn log10_64(x_: f64) f64 {
98 const ivln10hi: f64 = 4.34294481878168880939e-01;
99 const ivln10lo: f64 = 2.50829467116452752298e-11;
98 const ivln10hi: f64 = 4.34294481878168880939e-01;
99 const ivln10lo: f64 = 2.50829467116452752298e-11;
100100 const log10_2hi: f64 = 3.01029995663611771306e-01;
101101 const log10_2lo: f64 = 3.69423907715893078616e-13;
102102 const Lg1: f64 = 6.666666666666735130e-01;
......@@ -126,11 +126,9 @@ pub fn log10_64(x_: f64) f64 {
126126 k -= 54;
127127 x *= 0x1.0p54;
128128 hx = u32(@bitCast(u64, x) >> 32);
129 }
130 else if (hx >= 0x7FF00000) {
129 } else if (hx >= 0x7FF00000) {
131130 return x;
132 }
133 else if (hx == 0x3FF00000 and ix << 32 == 0) {
131 } else if (hx == 0x3FF00000 and ix << 32 == 0) {
134132 return 0;
135133 }
136134
std/math/log2.zig+5-2
......@@ -27,7 +27,10 @@ pub fn log2(x: var) @typeOf(x) {
2727 TypeId.IntLiteral => comptime {
2828 var result = 0;
2929 var x_shifted = x;
30 while (b: {x_shifted >>= 1; break :b x_shifted != 0;}) : (result += 1) {}
30 while (b: {
31 x_shifted >>= 1;
32 break :b x_shifted != 0;
33 }) : (result += 1) {}
3134 return result;
3235 },
3336 TypeId.Int => {
......@@ -38,7 +41,7 @@ pub fn log2(x: var) @typeOf(x) {
3841}
3942
4043pub fn log2_32(x_: f32) f32 {
41 const ivln2hi: f32 = 1.4428710938e+00;
44 const ivln2hi: f32 = 1.4428710938e+00;
4245 const ivln2lo: f32 = -1.7605285393e-04;
4346 const Lg1: f32 = 0xaaaaaa.0p-24;
4447 const Lg2: f32 = 0xccce13.0p-25;
std/math/round.zig+4-4
......@@ -24,13 +24,13 @@ fn round32(x_: f32) f32 {
2424 const e = (u >> 23) & 0xFF;
2525 var y: f32 = undefined;
2626
27 if (e >= 0x7F+23) {
27 if (e >= 0x7F + 23) {
2828 return x;
2929 }
3030 if (u >> 31 != 0) {
3131 x = -x;
3232 }
33 if (e < 0x7F-1) {
33 if (e < 0x7F - 1) {
3434 math.forceEval(x + math.f32_toint);
3535 return 0 * @bitCast(f32, u);
3636 }
......@@ -61,13 +61,13 @@ fn round64(x_: f64) f64 {
6161 const e = (u >> 52) & 0x7FF;
6262 var y: f64 = undefined;
6363
64 if (e >= 0x3FF+52) {
64 if (e >= 0x3FF + 52) {
6565 return x;
6666 }
6767 if (u >> 63 != 0) {
6868 x = -x;
6969 }
70 if (e < 0x3ff-1) {
70 if (e < 0x3ff - 1) {
7171 math.forceEval(x + math.f64_toint);
7272 return 0 * @bitCast(f64, u);
7373 }
std/math/sin.zig+6-6
......@@ -19,20 +19,20 @@ pub fn sin(x: var) @typeOf(x) {
1919}
2020
2121// sin polynomial coefficients
22const S0 = 1.58962301576546568060E-10;
22const S0 = 1.58962301576546568060E-10;
2323const S1 = -2.50507477628578072866E-8;
24const S2 = 2.75573136213857245213E-6;
24const S2 = 2.75573136213857245213E-6;
2525const S3 = -1.98412698295895385996E-4;
26const S4 = 8.33333333332211858878E-3;
26const S4 = 8.33333333332211858878E-3;
2727const S5 = -1.66666666666666307295E-1;
2828
2929// cos polynomial coeffiecients
3030const C0 = -1.13585365213876817300E-11;
31const C1 = 2.08757008419747316778E-9;
31const C1 = 2.08757008419747316778E-9;
3232const C2 = -2.75573141792967388112E-7;
33const C3 = 2.48015872888517045348E-5;
33const C3 = 2.48015872888517045348E-5;
3434const C4 = -1.38888888888730564116E-3;
35const C5 = 4.16666666666665929218E-2;
35const C5 = 4.16666666666665929218E-2;
3636
3737// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
3838//
std/math/tan.zig+3-3
......@@ -19,12 +19,12 @@ pub fn tan(x: var) @typeOf(x) {
1919}
2020
2121const Tp0 = -1.30936939181383777646E4;
22const Tp1 = 1.15351664838587416140E6;
22const Tp1 = 1.15351664838587416140E6;
2323const Tp2 = -1.79565251976484877988E7;
2424
25const Tq1 = 1.36812963470692954678E4;
25const Tq1 = 1.36812963470692954678E4;
2626const Tq2 = -1.32089234440210967447E6;
27const Tq3 = 2.50083801823357915839E7;
27const Tq3 = 2.50083801823357915839E7;
2828const Tq4 = -5.38695755929454629881E7;
2929
3030// NOTE: This is taken from the go stdlib. The musl implementation is much more complex.
std/mem.zig+125-74
......@@ -6,14 +6,14 @@ const builtin = @import("builtin");
66const mem = this;
77
88pub const Allocator = struct {
9 const Error = error {OutOfMemory};
9 const Error = error{OutOfMemory};
1010
1111 /// Allocate byte_count bytes and return them in a slice, with the
1212 /// slice's pointer aligned at least to alignment bytes.
1313 /// The returned newly allocated memory is undefined.
1414 /// `alignment` is guaranteed to be >= 1
1515 /// `alignment` is guaranteed to be a power of 2
16 allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) Error![]u8,
16 allocFn: fn(self: &Allocator, byte_count: usize, alignment: u29) Error![]u8,
1717
1818 /// If `new_byte_count > old_mem.len`:
1919 /// * `old_mem.len` is the same as what was returned from allocFn or reallocFn.
......@@ -26,10 +26,10 @@ pub const Allocator = struct {
2626 /// The returned newly allocated memory is undefined.
2727 /// `alignment` is guaranteed to be >= 1
2828 /// `alignment` is guaranteed to be a power of 2
29 reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8,
29 reallocFn: fn(self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8,
3030
3131 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
32 freeFn: fn (self: &Allocator, old_mem: []u8) void,
32 freeFn: fn(self: &Allocator, old_mem: []u8) void,
3333
3434 fn create(self: &Allocator, comptime T: type) !&T {
3535 if (@sizeOf(T) == 0) return &{};
......@@ -47,7 +47,7 @@ pub const Allocator = struct {
4747 if (@sizeOf(T) == 0) return &{};
4848 const slice = try self.alloc(T, 1);
4949 const ptr = &slice[0];
50 *ptr = *init;
50 ptr.* = init.*;
5151 return ptr;
5252 }
5353
......@@ -59,9 +59,7 @@ pub const Allocator = struct {
5959 return self.alignedAlloc(T, @alignOf(T), n);
6060 }
6161
62 fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29,
63 n: usize) ![]align(alignment) T
64 {
62 fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T {
6563 if (n == 0) {
6664 return (&align(alignment) T)(undefined)[0..0];
6765 }
......@@ -70,7 +68,7 @@ pub const Allocator = struct {
7068 assert(byte_slice.len == byte_count);
7169 // This loop gets optimized out in ReleaseFast mode
7270 for (byte_slice) |*byte| {
73 *byte = undefined;
71 byte.* = undefined;
7472 }
7573 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
7674 }
......@@ -79,9 +77,7 @@ pub const Allocator = struct {
7977 return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
8078 }
8179
82 fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29,
83 old_mem: []align(alignment) T, n: usize) ![]align(alignment) T
84 {
80 fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T {
8581 if (old_mem.len == 0) {
8682 return self.alloc(T, n);
8783 }
......@@ -97,7 +93,7 @@ pub const Allocator = struct {
9793 if (n > old_mem.len) {
9894 // This loop gets optimized out in ReleaseFast mode
9995 for (byte_slice[old_byte_slice.len..]) |*byte| {
100 *byte = undefined;
96 byte.* = undefined;
10197 }
10298 }
10399 return ([]T)(@alignCast(alignment, byte_slice));
......@@ -110,9 +106,7 @@ pub const Allocator = struct {
110106 return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
111107 }
112108
113 fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29,
114 old_mem: []align(alignment) T, n: usize) []align(alignment) T
115 {
109 fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T {
116110 if (n == 0) {
117111 self.free(old_mem);
118112 return old_mem[0..0];
......@@ -131,8 +125,7 @@ pub const Allocator = struct {
131125
132126 fn free(self: &Allocator, memory: var) void {
133127 const bytes = ([]const u8)(memory);
134 if (bytes.len == 0)
135 return;
128 if (bytes.len == 0) return;
136129 const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr));
137130 self.freeFn(self, non_const_ptr[0..bytes.len]);
138131 }
......@@ -146,11 +139,13 @@ pub fn copy(comptime T: type, dest: []T, source: []const T) void {
146139 // this and automatically omit safety checks for loops
147140 @setRuntimeSafety(false);
148141 assert(dest.len >= source.len);
149 for (source) |s, i| dest[i] = s;
142 for (source) |s, i|
143 dest[i] = s;
150144}
151145
152146pub fn set(comptime T: type, dest: []T, value: T) void {
153 for (dest) |*d| *d = value;
147 for (dest) |*d|
148 d.* = value;
154149}
155150
156151/// Returns true if lhs < rhs, false otherwise
......@@ -229,8 +224,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
229224 var i: usize = slice.len;
230225 while (i != 0) {
231226 i -= 1;
232 if (slice[i] == value)
233 return i;
227 if (slice[i] == value) return i;
234228 }
235229 return null;
236230}
......@@ -238,8 +232,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
238232pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
239233 var i: usize = start_index;
240234 while (i < slice.len) : (i += 1) {
241 if (slice[i] == value)
242 return i;
235 if (slice[i] == value) return i;
243236 }
244237 return null;
245238}
......@@ -253,8 +246,7 @@ pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?us
253246 while (i != 0) {
254247 i -= 1;
255248 for (values) |value| {
256 if (slice[i] == value)
257 return i;
249 if (slice[i] == value) return i;
258250 }
259251 }
260252 return null;
......@@ -264,8 +256,7 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val
264256 var i: usize = start_index;
265257 while (i < slice.len) : (i += 1) {
266258 for (values) |value| {
267 if (slice[i] == value)
268 return i;
259 if (slice[i] == value) return i;
269260 }
270261 }
271262 return null;
......@@ -279,28 +270,23 @@ pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize
279270/// To start looking at a different index, slice the haystack first.
280271/// TODO is there even a better algorithm for this?
281272pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
282 if (needle.len > haystack.len)
283 return null;
273 if (needle.len > haystack.len) return null;
284274
285275 var i: usize = haystack.len - needle.len;
286276 while (true) : (i -= 1) {
287 if (mem.eql(T, haystack[i..i+needle.len], needle))
288 return i;
289 if (i == 0)
290 return null;
277 if (mem.eql(T, haystack[i..i + needle.len], needle)) return i;
278 if (i == 0) return null;
291279 }
292280}
293281
294282// TODO boyer-moore algorithm
295283pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
296 if (needle.len > haystack.len)
297 return null;
284 if (needle.len > haystack.len) return null;
298285
299286 var i: usize = start_index;
300287 const end = haystack.len - needle.len;
301288 while (i <= end) : (i += 1) {
302 if (eql(T, haystack[i .. i + needle.len], needle))
303 return i;
289 if (eql(T, haystack[i..i + needle.len], needle)) return i;
304290 }
305291 return null;
306292}
......@@ -355,9 +341,12 @@ pub fn readIntBE(comptime T: type, bytes: []const u8) T {
355341 }
356342 assert(bytes.len == @sizeOf(T));
357343 var result: T = 0;
358 {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
359 result = (result << 8) | T(bytes[i]);
360 }}
344 {
345 comptime var i = 0;
346 inline while (i < @sizeOf(T)) : (i += 1) {
347 result = (result << 8) | T(bytes[i]);
348 }
349 }
361350 return result;
362351}
363352
......@@ -369,9 +358,12 @@ pub fn readIntLE(comptime T: type, bytes: []const u8) T {
369358 }
370359 assert(bytes.len == @sizeOf(T));
371360 var result: T = 0;
372 {comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
373 result |= T(bytes[i]) << i * 8;
374 }}
361 {
362 comptime var i = 0;
363 inline while (i < @sizeOf(T)) : (i += 1) {
364 result |= T(bytes[i]) << i * 8;
365 }
366 }
375367 return result;
376368}
377369
......@@ -393,7 +385,7 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
393385 },
394386 builtin.Endian.Little => {
395387 for (buf) |*b| {
396 *b = @truncate(u8, bits);
388 b.* = @truncate(u8, bits);
397389 bits >>= 8;
398390 }
399391 },
......@@ -401,7 +393,6 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
401393 assert(bits == 0);
402394}
403395
404
405396pub fn hash_slice_u8(k: []const u8) u32 {
406397 // FNV 32-bit hash
407398 var h: u32 = 2166136261;
......@@ -420,7 +411,7 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
420411/// split(" abc def ghi ", " ")
421412/// Will return slices for "abc", "def", "ghi", null, in that order.
422413pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {
423 return SplitIterator {
414 return SplitIterator{
424415 .index = 0,
425416 .buffer = buffer,
426417 .split_bytes = split_bytes,
......@@ -436,7 +427,7 @@ test "mem.split" {
436427}
437428
438429pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
439 return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle);
430 return if (needle.len > haystack.len) false else eql(T, haystack[0..needle.len], needle);
440431}
441432
442433test "mem.startsWith" {
......@@ -445,10 +436,9 @@ test "mem.startsWith" {
445436}
446437
447438pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
448 return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len ..], needle);
439 return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len..], needle);
449440}
450441
451
452442test "mem.endsWith" {
453443 assert(endsWith(u8, "Needle in haystack", "haystack"));
454444 assert(!endsWith(u8, "Bob", "Bo"));
......@@ -542,29 +532,47 @@ test "testReadInt" {
542532}
543533fn testReadIntImpl() void {
544534 {
545 const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 };
546 assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
547 assert(readIntBE(u32, bytes) == 0x12345678);
548 assert(readIntBE(i32, bytes) == 0x12345678);
535 const bytes = []u8{
536 0x12,
537 0x34,
538 0x56,
539 0x78,
540 };
541 assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
542 assert(readIntBE(u32, bytes) == 0x12345678);
543 assert(readIntBE(i32, bytes) == 0x12345678);
549544 assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
550 assert(readIntLE(u32, bytes) == 0x78563412);
551 assert(readIntLE(i32, bytes) == 0x78563412);
545 assert(readIntLE(u32, bytes) == 0x78563412);
546 assert(readIntLE(i32, bytes) == 0x78563412);
552547 }
553548 {
554 const buf = []u8{0x00, 0x00, 0x12, 0x34};
549 const buf = []u8{
550 0x00,
551 0x00,
552 0x12,
553 0x34,
554 };
555555 const answer = readInt(buf, u64, builtin.Endian.Big);
556556 assert(answer == 0x00001234);
557557 }
558558 {
559 const buf = []u8{0x12, 0x34, 0x00, 0x00};
559 const buf = []u8{
560 0x12,
561 0x34,
562 0x00,
563 0x00,
564 };
560565 const answer = readInt(buf, u64, builtin.Endian.Little);
561566 assert(answer == 0x00003412);
562567 }
563568 {
564 const bytes = []u8{0xff, 0xfe};
565 assert(readIntBE(u16, bytes) == 0xfffe);
569 const bytes = []u8{
570 0xff,
571 0xfe,
572 };
573 assert(readIntBE(u16, bytes) == 0xfffe);
566574 assert(readIntBE(i16, bytes) == -0x0002);
567 assert(readIntLE(u16, bytes) == 0xfeff);
575 assert(readIntLE(u16, bytes) == 0xfeff);
568576 assert(readIntLE(i16, bytes) == -0x0101);
569577 }
570578}
......@@ -577,19 +585,38 @@ fn testWriteIntImpl() void {
577585 var bytes: [4]u8 = undefined;
578586
579587 writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
580 assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
588 assert(eql(u8, bytes, []u8{
589 0x12,
590 0x34,
591 0x56,
592 0x78,
593 }));
581594
582595 writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
583 assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
596 assert(eql(u8, bytes, []u8{
597 0x12,
598 0x34,
599 0x56,
600 0x78,
601 }));
584602
585603 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
586 assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 }));
604 assert(eql(u8, bytes, []u8{
605 0x00,
606 0x00,
607 0x12,
608 0x34,
609 }));
587610
588611 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
589 assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 }));
612 assert(eql(u8, bytes, []u8{
613 0x34,
614 0x12,
615 0x00,
616 0x00,
617 }));
590618}
591619
592
593620pub fn min(comptime T: type, slice: []const T) T {
594621 var best = slice[0];
595622 for (slice[1..]) |item| {
......@@ -615,9 +642,9 @@ test "mem.max" {
615642}
616643
617644pub fn swap(comptime T: type, a: &T, b: &T) void {
618 const tmp = *a;
619 *a = *b;
620 *b = tmp;
645 const tmp = a.*;
646 a.* = b.*;
647 b.* = tmp;
621648}
622649
623650/// In-place order reversal of a slice
......@@ -630,10 +657,22 @@ pub fn reverse(comptime T: type, items: []T) void {
630657}
631658
632659test "std.mem.reverse" {
633 var arr = []i32{ 5, 3, 1, 2, 4 };
660 var arr = []i32{
661 5,
662 3,
663 1,
664 2,
665 4,
666 };
634667 reverse(i32, arr[0..]);
635668
636 assert(eql(i32, arr, []i32{ 4, 2, 1, 3, 5 }));
669 assert(eql(i32, arr, []i32{
670 4,
671 2,
672 1,
673 3,
674 5,
675 }));
637676}
638677
639678/// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
......@@ -645,13 +684,25 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void {
645684}
646685
647686test "std.mem.rotate" {
648 var arr = []i32{ 5, 3, 1, 2, 4 };
687 var arr = []i32{
688 5,
689 3,
690 1,
691 2,
692 4,
693 };
649694 rotate(i32, arr[0..], 2);
650695
651 assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }));
696 assert(eql(i32, arr, []i32{
697 1,
698 2,
699 4,
700 5,
701 3,
702 }));
652703}
653704
654// TODO: When https://github.com/zig-lang/zig/issues/649 is solved these can be done by
705// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
655706// endian-casting the pointer and then dereferencing
656707
657708pub fn endianSwapIfLe(comptime T: type, x: T) T {
std/net.zig+16-24
......@@ -19,37 +19,29 @@ pub const Address = struct {
1919 os_addr: OsAddress,
2020
2121 pub fn initIp4(ip4: u32, port: u16) Address {
22 return Address {
23 .os_addr = posix.sockaddr {
24 .in = posix.sockaddr_in {
25 .family = posix.AF_INET,
26 .port = std.mem.endianSwapIfLe(u16, port),
27 .addr = ip4,
28 .zero = []u8{0} ** 8,
29 },
30 },
31 };
22 return Address{ .os_addr = posix.sockaddr{ .in = posix.sockaddr_in{
23 .family = posix.AF_INET,
24 .port = std.mem.endianSwapIfLe(u16, port),
25 .addr = ip4,
26 .zero = []u8{0} ** 8,
27 } } };
3228 }
3329
3430 pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address {
35 return Address {
31 return Address{
3632 .family = posix.AF_INET6,
37 .os_addr = posix.sockaddr {
38 .in6 = posix.sockaddr_in6 {
39 .family = posix.AF_INET6,
40 .port = std.mem.endianSwapIfLe(u16, port),
41 .flowinfo = 0,
42 .addr = ip6.addr,
43 .scope_id = ip6.scope_id,
44 },
45 },
33 .os_addr = posix.sockaddr{ .in6 = posix.sockaddr_in6{
34 .family = posix.AF_INET6,
35 .port = std.mem.endianSwapIfLe(u16, port),
36 .flowinfo = 0,
37 .addr = ip6.addr,
38 .scope_id = ip6.scope_id,
39 } },
4640 };
4741 }
4842
4943 pub fn initPosix(addr: &const posix.sockaddr) Address {
50 return Address {
51 .os_addr = *addr,
52 };
44 return Address{ .os_addr = addr.* };
5345 }
5446
5547 pub fn format(self: &const Address, out_stream: var) !void {
......@@ -98,7 +90,7 @@ pub fn parseIp4(buf: []const u8) !u32 {
9890 }
9991 } else {
10092 return error.InvalidCharacter;
101 }
93 }
10294 }
10395 if (index == 3 and saw_any_digits) {
10496 out_ptr[index] = x;
std/os/child_process.zig+106-94
......@@ -49,7 +49,7 @@ pub const ChildProcess = struct {
4949 err_pipe: if (is_windows) void else [2]i32,
5050 llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
5151
52 pub const SpawnError = error {
52 pub const SpawnError = error{
5353 ProcessFdQuotaExceeded,
5454 Unexpected,
5555 NotDir,
......@@ -88,7 +88,7 @@ pub const ChildProcess = struct {
8888 const child = try allocator.create(ChildProcess);
8989 errdefer allocator.destroy(child);
9090
91 *child = ChildProcess {
91 child.* = ChildProcess{
9292 .allocator = allocator,
9393 .argv = argv,
9494 .pid = undefined,
......@@ -99,8 +99,10 @@ pub const ChildProcess = struct {
9999 .term = null,
100100 .env_map = null,
101101 .cwd = null,
102 .uid = if (is_windows) {} else null,
103 .gid = if (is_windows) {} else null,
102 .uid = if (is_windows) {} else
103 null,
104 .gid = if (is_windows) {} else
105 null,
104106 .stdin = null,
105107 .stdout = null,
106108 .stderr = null,
......@@ -193,9 +195,7 @@ pub const ChildProcess = struct {
193195
194196 /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
195197 /// If it succeeds, the caller owns result.stdout and result.stderr memory.
196 pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8,
197 env_map: ?&const BufMap, max_output_size: usize) !ExecResult
198 {
198 pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?&const BufMap, max_output_size: usize) !ExecResult {
199199 const child = try ChildProcess.init(argv, allocator);
200200 defer child.deinit();
201201
......@@ -218,7 +218,7 @@ pub const ChildProcess = struct {
218218 try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
219219 try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
220220
221 return ExecResult {
221 return ExecResult{
222222 .term = try child.wait(),
223223 .stdout = stdout.toOwnedSlice(),
224224 .stderr = stderr.toOwnedSlice(),
......@@ -255,9 +255,9 @@ pub const ChildProcess = struct {
255255 self.term = (SpawnError!Term)(x: {
256256 var exit_code: windows.DWORD = undefined;
257257 if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
258 break :x Term { .Unknown = 0 };
258 break :x Term{ .Unknown = 0 };
259259 } else {
260 break :x Term { .Exited = @bitCast(i32, exit_code)};
260 break :x Term{ .Exited = @bitCast(i32, exit_code) };
261261 }
262262 });
263263
......@@ -288,9 +288,18 @@ pub const ChildProcess = struct {
288288 }
289289
290290 fn cleanupStreams(self: &ChildProcess) void {
291 if (self.stdin) |*stdin| { stdin.close(); self.stdin = null; }
292 if (self.stdout) |*stdout| { stdout.close(); self.stdout = null; }
293 if (self.stderr) |*stderr| { stderr.close(); self.stderr = null; }
291 if (self.stdin) |*stdin| {
292 stdin.close();
293 self.stdin = null;
294 }
295 if (self.stdout) |*stdout| {
296 stdout.close();
297 self.stdout = null;
298 }
299 if (self.stderr) |*stderr| {
300 stderr.close();
301 self.stderr = null;
302 }
294303 }
295304
296305 fn cleanupAfterWait(self: &ChildProcess, status: i32) !Term {
......@@ -317,25 +326,30 @@ pub const ChildProcess = struct {
317326
318327 fn statusToTerm(status: i32) Term {
319328 return if (posix.WIFEXITED(status))
320 Term { .Exited = posix.WEXITSTATUS(status) }
329 Term{ .Exited = posix.WEXITSTATUS(status) }
321330 else if (posix.WIFSIGNALED(status))
322 Term { .Signal = posix.WTERMSIG(status) }
331 Term{ .Signal = posix.WTERMSIG(status) }
323332 else if (posix.WIFSTOPPED(status))
324 Term { .Stopped = posix.WSTOPSIG(status) }
333 Term{ .Stopped = posix.WSTOPSIG(status) }
325334 else
326 Term { .Unknown = status }
327 ;
335 Term{ .Unknown = status };
328336 }
329337
330338 fn spawnPosix(self: &ChildProcess) !void {
331339 const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined;
332 errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); };
340 errdefer if (self.stdin_behavior == StdIo.Pipe) {
341 destroyPipe(stdin_pipe);
342 };
333343
334344 const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined;
335 errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); };
345 errdefer if (self.stdout_behavior == StdIo.Pipe) {
346 destroyPipe(stdout_pipe);
347 };
336348
337349 const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined;
338 errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); };
350 errdefer if (self.stderr_behavior == StdIo.Pipe) {
351 destroyPipe(stderr_pipe);
352 };
339353
340354 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
341355 const dev_null_fd = if (any_ignore) blk: {
......@@ -346,7 +360,9 @@ pub const ChildProcess = struct {
346360 } else blk: {
347361 break :blk undefined;
348362 };
349 defer { if (any_ignore) os.close(dev_null_fd); }
363 defer {
364 if (any_ignore) os.close(dev_null_fd);
365 }
350366
351367 var env_map_owned: BufMap = undefined;
352368 var we_own_env_map: bool = undefined;
......@@ -358,7 +374,9 @@ pub const ChildProcess = struct {
358374 env_map_owned = try os.getEnvMap(self.allocator);
359375 break :x &env_map_owned;
360376 };
361 defer { if (we_own_env_map) env_map_owned.deinit(); }
377 defer {
378 if (we_own_env_map) env_map_owned.deinit();
379 }
362380
363381 // This pipe is used to communicate errors between the time of fork
364382 // and execve from the child process to the parent process.
......@@ -369,23 +387,21 @@ pub const ChildProcess = struct {
369387 const pid_err = posix.getErrno(pid_result);
370388 if (pid_err > 0) {
371389 return switch (pid_err) {
372 posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources,
390 posix.EAGAIN,
391 posix.ENOMEM,
392 posix.ENOSYS => error.SystemResources,
373393 else => os.unexpectedErrorPosix(pid_err),
374394 };
375395 }
376396 if (pid_result == 0) {
377397 // we are the child
378398
379 setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch
380 |err| forkChildErrReport(err_pipe[1], err);
381 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch
382 |err| forkChildErrReport(err_pipe[1], err);
383 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch
384 |err| forkChildErrReport(err_pipe[1], err);
399 setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
400 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
401 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
385402
386403 if (self.cwd) |cwd| {
387 os.changeCurDir(self.allocator, cwd) catch
388 |err| forkChildErrReport(err_pipe[1], err);
404 os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);
389405 }
390406
391407 if (self.gid) |gid| {
......@@ -396,8 +412,7 @@ pub const ChildProcess = struct {
396412 os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
397413 }
398414
399 os.posixExecve(self.argv, env_map, self.allocator) catch
400 |err| forkChildErrReport(err_pipe[1], err);
415 os.posixExecve(self.argv, env_map, self.allocator) catch |err| forkChildErrReport(err_pipe[1], err);
401416 }
402417
403418 // we are the parent
......@@ -423,37 +438,41 @@ pub const ChildProcess = struct {
423438 self.llnode = LinkedList(&ChildProcess).Node.init(self);
424439 self.term = null;
425440
426 if (self.stdin_behavior == StdIo.Pipe) { os.close(stdin_pipe[0]); }
427 if (self.stdout_behavior == StdIo.Pipe) { os.close(stdout_pipe[1]); }
428 if (self.stderr_behavior == StdIo.Pipe) { os.close(stderr_pipe[1]); }
441 if (self.stdin_behavior == StdIo.Pipe) {
442 os.close(stdin_pipe[0]);
443 }
444 if (self.stdout_behavior == StdIo.Pipe) {
445 os.close(stdout_pipe[1]);
446 }
447 if (self.stderr_behavior == StdIo.Pipe) {
448 os.close(stderr_pipe[1]);
449 }
429450 }
430451
431452 fn spawnWindows(self: &ChildProcess) !void {
432 const saAttr = windows.SECURITY_ATTRIBUTES {
453 const saAttr = windows.SECURITY_ATTRIBUTES{
433454 .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
434455 .bInheritHandle = windows.TRUE,
435456 .lpSecurityDescriptor = null,
436457 };
437458
438 const any_ignore = (self.stdin_behavior == StdIo.Ignore or
439 self.stdout_behavior == StdIo.Ignore or
440 self.stderr_behavior == StdIo.Ignore);
459 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
441460
442461 const nul_handle = if (any_ignore) blk: {
443462 const nul_file_path = "NUL";
444463 var fixed_buffer_mem: [nul_file_path.len + 1]u8 = undefined;
445464 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
446 break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ,
447 windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL);
465 break :blk try os.windowsOpen(&fixed_allocator.allocator, "NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL);
448466 } else blk: {
449467 break :blk undefined;
450468 };
451 defer { if (any_ignore) os.close(nul_handle); }
469 defer {
470 if (any_ignore) os.close(nul_handle);
471 }
452472 if (any_ignore) {
453473 try windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0);
454474 }
455475
456
457476 var g_hChildStd_IN_Rd: ?windows.HANDLE = null;
458477 var g_hChildStd_IN_Wr: ?windows.HANDLE = null;
459478 switch (self.stdin_behavior) {
......@@ -470,7 +489,9 @@ pub const ChildProcess = struct {
470489 g_hChildStd_IN_Rd = null;
471490 },
472491 }
473 errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); };
492 errdefer if (self.stdin_behavior == StdIo.Pipe) {
493 windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr);
494 };
474495
475496 var g_hChildStd_OUT_Rd: ?windows.HANDLE = null;
476497 var g_hChildStd_OUT_Wr: ?windows.HANDLE = null;
......@@ -488,7 +509,9 @@ pub const ChildProcess = struct {
488509 g_hChildStd_OUT_Wr = null;
489510 },
490511 }
491 errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); };
512 errdefer if (self.stdin_behavior == StdIo.Pipe) {
513 windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr);
514 };
492515
493516 var g_hChildStd_ERR_Rd: ?windows.HANDLE = null;
494517 var g_hChildStd_ERR_Wr: ?windows.HANDLE = null;
......@@ -506,12 +529,14 @@ pub const ChildProcess = struct {
506529 g_hChildStd_ERR_Wr = null;
507530 },
508531 }
509 errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); };
532 errdefer if (self.stdin_behavior == StdIo.Pipe) {
533 windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr);
534 };
510535
511536 const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv);
512537 defer self.allocator.free(cmd_line);
513538
514 var siStartInfo = windows.STARTUPINFOA {
539 var siStartInfo = windows.STARTUPINFOA{
515540 .cb = @sizeOf(windows.STARTUPINFOA),
516541 .hStdError = g_hChildStd_ERR_Wr,
517542 .hStdOutput = g_hChildStd_OUT_Wr,
......@@ -534,19 +559,11 @@ pub const ChildProcess = struct {
534559 };
535560 var piProcInfo: windows.PROCESS_INFORMATION = undefined;
536561
537 const cwd_slice = if (self.cwd) |cwd|
538 try cstr.addNullByte(self.allocator, cwd)
539 else
540 null
541 ;
562 const cwd_slice = if (self.cwd) |cwd| try cstr.addNullByte(self.allocator, cwd) else null;
542563 defer if (cwd_slice) |cwd| self.allocator.free(cwd);
543564 const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null;
544565
545 const maybe_envp_buf = if (self.env_map) |env_map|
546 try os.createWindowsEnvBlock(self.allocator, env_map)
547 else
548 null
549 ;
566 const maybe_envp_buf = if (self.env_map) |env_map| try os.createWindowsEnvBlock(self.allocator, env_map) else null;
550567 defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf);
551568 const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null;
552569
......@@ -563,11 +580,8 @@ pub const ChildProcess = struct {
563580 };
564581 defer self.allocator.free(app_name);
565582
566 windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr,
567 &siStartInfo, &piProcInfo) catch |no_path_err|
568 {
569 if (no_path_err != error.FileNotFound)
570 return no_path_err;
583 windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| {
584 if (no_path_err != error.FileNotFound) return no_path_err;
571585
572586 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
573587 defer self.allocator.free(PATH);
......@@ -577,9 +591,7 @@ pub const ChildProcess = struct {
577591 const joined_path = try os.path.join(self.allocator, search_path, app_name);
578592 defer self.allocator.free(joined_path);
579593
580 if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr,
581 &siStartInfo, &piProcInfo)) |_|
582 {
594 if (windowsCreateProcess(joined_path.ptr, cmd_line.ptr, envp_ptr, cwd_ptr, &siStartInfo, &piProcInfo)) |_| {
583595 break;
584596 } else |err| if (err == error.FileNotFound) {
585597 continue;
......@@ -609,9 +621,15 @@ pub const ChildProcess = struct {
609621 self.thread_handle = piProcInfo.hThread;
610622 self.term = null;
611623
612 if (self.stdin_behavior == StdIo.Pipe) { os.close(??g_hChildStd_IN_Rd); }
613 if (self.stderr_behavior == StdIo.Pipe) { os.close(??g_hChildStd_ERR_Wr); }
614 if (self.stdout_behavior == StdIo.Pipe) { os.close(??g_hChildStd_OUT_Wr); }
624 if (self.stdin_behavior == StdIo.Pipe) {
625 os.close(??g_hChildStd_IN_Rd);
626 }
627 if (self.stderr_behavior == StdIo.Pipe) {
628 os.close(??g_hChildStd_ERR_Wr);
629 }
630 if (self.stdout_behavior == StdIo.Pipe) {
631 os.close(??g_hChildStd_OUT_Wr);
632 }
615633 }
616634
617635 fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void {
......@@ -622,18 +640,14 @@ pub const ChildProcess = struct {
622640 StdIo.Ignore => try os.posixDup2(dev_null_fd, std_fileno),
623641 }
624642 }
625
626643};
627644
628fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8,
629 lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void
630{
631 if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0,
632 @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0)
633 {
645fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void {
646 if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) {
634647 const err = windows.GetLastError();
635648 return switch (err) {
636 windows.ERROR.FILE_NOT_FOUND, windows.ERROR.PATH_NOT_FOUND => error.FileNotFound,
649 windows.ERROR.FILE_NOT_FOUND,
650 windows.ERROR.PATH_NOT_FOUND => error.FileNotFound,
637651 windows.ERROR.INVALID_PARAMETER => unreachable,
638652 windows.ERROR.INVALID_NAME => error.InvalidName,
639653 else => os.unexpectedErrorWindows(err),
......@@ -641,18 +655,16 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?
641655 }
642656}
643657
644
645
646
647658/// Caller must dealloc.
648659/// Guarantees a null byte at result[result.len].
649660fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) ![]u8 {
650661 var buf = try Buffer.initSize(allocator, 0);
651662 defer buf.deinit();
652663
664 var buf_stream = &io.BufferOutStream.init(&buf).stream;
665
653666 for (argv) |arg, arg_i| {
654 if (arg_i != 0)
655 try buf.appendByte(' ');
667 if (arg_i != 0) try buf.appendByte(' ');
656668 if (mem.indexOfAny(u8, arg, " \t\n\"") == null) {
657669 try buf.append(arg);
658670 continue;
......@@ -663,18 +675,18 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8)
663675 switch (byte) {
664676 '\\' => backslash_count += 1,
665677 '"' => {
666 try buf.appendByteNTimes('\\', backslash_count * 2 + 1);
678 try buf_stream.writeByteNTimes('\\', backslash_count * 2 + 1);
667679 try buf.appendByte('"');
668680 backslash_count = 0;
669681 },
670682 else => {
671 try buf.appendByteNTimes('\\', backslash_count);
683 try buf_stream.writeByteNTimes('\\', backslash_count);
672684 try buf.appendByte(byte);
673685 backslash_count = 0;
674686 },
675687 }
676688 }
677 try buf.appendByteNTimes('\\', backslash_count * 2);
689 try buf_stream.writeByteNTimes('\\', backslash_count * 2);
678690 try buf.appendByte('"');
679691 }
680692
......@@ -686,7 +698,6 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void {
686698 if (wr) |h| os.close(h);
687699}
688700
689
690701// TODO: workaround for bug where the `const` from `&const` is dropped when the type is
691702// a namespace field lookup
692703const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES;
......@@ -715,8 +726,8 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S
715726 try windowsMakePipe(&rd_h, &wr_h, sattr);
716727 errdefer windowsDestroyPipe(rd_h, wr_h);
717728 try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0);
718 *rd = rd_h;
719 *wr = wr_h;
729 rd.* = rd_h;
730 wr.* = wr_h;
720731}
721732
722733fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void {
......@@ -725,8 +736,8 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const
725736 try windowsMakePipe(&rd_h, &wr_h, sattr);
726737 errdefer windowsDestroyPipe(rd_h, wr_h);
727738 try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0);
728 *rd = rd_h;
729 *wr = wr_h;
739 rd.* = rd_h;
740 wr.* = wr_h;
730741}
731742
732743fn makePipe() ![2]i32 {
......@@ -734,7 +745,8 @@ fn makePipe() ![2]i32 {
734745 const err = posix.getErrno(posix.pipe(&fds));
735746 if (err > 0) {
736747 return switch (err) {
737 posix.EMFILE, posix.ENFILE => error.SystemResources,
748 posix.EMFILE,
749 posix.ENFILE => error.SystemResources,
738750 else => os.unexpectedErrorPosix(err),
739751 };
740752 }
......@@ -742,8 +754,8 @@ fn makePipe() ![2]i32 {
742754}
743755
744756fn destroyPipe(pipe: &const [2]i32) void {
745 os.close((*pipe)[0]);
746 os.close((*pipe)[1]);
757 os.close((pipe.*)[0]);
758 os.close((pipe.*)[1]);
747759}
748760
749761// Child of fork calls this to report an error to the fork parent.
std/os/darwin.zig+182-100
......@@ -10,33 +10,56 @@ pub const STDIN_FILENO = 0;
1010pub const STDOUT_FILENO = 1;
1111pub const STDERR_FILENO = 2;
1212
13pub const PROT_NONE = 0x00; /// [MC2] no permissions
14pub const PROT_READ = 0x01; /// [MC2] pages can be read
15pub const PROT_WRITE = 0x02; /// [MC2] pages can be written
16pub const PROT_EXEC = 0x04; /// [MC2] pages can be executed
17
18pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
19pub const MAP_FILE = 0x0000; /// map from file (default)
20pub const MAP_FIXED = 0x0010; /// interpret addr exactly
21pub const MAP_HASSEMAPHORE = 0x0200; /// region may contain semaphores
22pub const MAP_PRIVATE = 0x0002; /// changes are private
23pub const MAP_SHARED = 0x0001; /// share changes
24pub const MAP_NOCACHE = 0x0400; /// don't cache pages for this mapping
25pub const MAP_NORESERVE = 0x0040; /// don't reserve needed swap area
13/// [MC2] no permissions
14pub const PROT_NONE = 0x00;
15/// [MC2] pages can be read
16pub const PROT_READ = 0x01;
17/// [MC2] pages can be written
18pub const PROT_WRITE = 0x02;
19/// [MC2] pages can be executed
20pub const PROT_EXEC = 0x04;
21
22/// allocated from memory, swap space
23pub const MAP_ANONYMOUS = 0x1000;
24/// map from file (default)
25pub const MAP_FILE = 0x0000;
26/// interpret addr exactly
27pub const MAP_FIXED = 0x0010;
28/// region may contain semaphores
29pub const MAP_HASSEMAPHORE = 0x0200;
30/// changes are private
31pub const MAP_PRIVATE = 0x0002;
32/// share changes
33pub const MAP_SHARED = 0x0001;
34/// don't cache pages for this mapping
35pub const MAP_NOCACHE = 0x0400;
36/// don't reserve needed swap area
37pub const MAP_NORESERVE = 0x0040;
2638pub const MAP_FAILED = @maxValue(usize);
2739
28pub const WNOHANG = 0x00000001; /// [XSI] no hang in wait/no child to reap
29pub const WUNTRACED = 0x00000002; /// [XSI] notify on stop, untraced child
30
31pub const SA_ONSTACK = 0x0001; /// take signal on signal stack
32pub const SA_RESTART = 0x0002; /// restart system on signal return
33pub const SA_RESETHAND = 0x0004; /// reset to SIG_DFL when taking signal
34pub const SA_NOCLDSTOP = 0x0008; /// do not generate SIGCHLD on child stop
35pub const SA_NODEFER = 0x0010; /// don't mask the signal we're delivering
36pub const SA_NOCLDWAIT = 0x0020; /// don't keep zombies around
37pub const SA_SIGINFO = 0x0040; /// signal handler with SA_SIGINFO args
38pub const SA_USERTRAMP = 0x0100; /// do not bounce off kernel's sigtramp
39pub const SA_64REGSET = 0x0200; /// signal handler with SA_SIGINFO args with 64bit regs information
40/// [XSI] no hang in wait/no child to reap
41pub const WNOHANG = 0x00000001;
42/// [XSI] notify on stop, untraced child
43pub const WUNTRACED = 0x00000002;
44
45/// take signal on signal stack
46pub const SA_ONSTACK = 0x0001;
47/// restart system on signal return
48pub const SA_RESTART = 0x0002;
49/// reset to SIG_DFL when taking signal
50pub const SA_RESETHAND = 0x0004;
51/// do not generate SIGCHLD on child stop
52pub const SA_NOCLDSTOP = 0x0008;
53/// don't mask the signal we're delivering
54pub const SA_NODEFER = 0x0010;
55/// don't keep zombies around
56pub const SA_NOCLDWAIT = 0x0020;
57/// signal handler with SA_SIGINFO args
58pub const SA_SIGINFO = 0x0040;
59/// do not bounce off kernel's sigtramp
60pub const SA_USERTRAMP = 0x0100;
61/// signal handler with SA_SIGINFO args with 64bit regs information
62pub const SA_64REGSET = 0x0200;
4063
4164pub const O_LARGEFILE = 0x0000;
4265pub const O_PATH = 0x0000;
......@@ -46,20 +69,34 @@ pub const X_OK = 1;
4669pub const W_OK = 2;
4770pub const R_OK = 4;
4871
49pub const O_RDONLY = 0x0000; /// open for reading only
50pub const O_WRONLY = 0x0001; /// open for writing only
51pub const O_RDWR = 0x0002; /// open for reading and writing
52pub const O_NONBLOCK = 0x0004; /// do not block on open or for data to become available
53pub const O_APPEND = 0x0008; /// append on each write
54pub const O_CREAT = 0x0200; /// create file if it does not exist
55pub const O_TRUNC = 0x0400; /// truncate size to 0
56pub const O_EXCL = 0x0800; /// error if O_CREAT and the file exists
57pub const O_SHLOCK = 0x0010; /// atomically obtain a shared lock
58pub const O_EXLOCK = 0x0020; /// atomically obtain an exclusive lock
59pub const O_NOFOLLOW = 0x0100; /// do not follow symlinks
60pub const O_SYMLINK = 0x200000; /// allow open of symlinks
61pub const O_EVTONLY = 0x8000; /// descriptor requested for event notifications only
62pub const O_CLOEXEC = 0x1000000; /// mark as close-on-exec
72/// open for reading only
73pub const O_RDONLY = 0x0000;
74/// open for writing only
75pub const O_WRONLY = 0x0001;
76/// open for reading and writing
77pub const O_RDWR = 0x0002;
78/// do not block on open or for data to become available
79pub const O_NONBLOCK = 0x0004;
80/// append on each write
81pub const O_APPEND = 0x0008;
82/// create file if it does not exist
83pub const O_CREAT = 0x0200;
84/// truncate size to 0
85pub const O_TRUNC = 0x0400;
86/// error if O_CREAT and the file exists
87pub const O_EXCL = 0x0800;
88/// atomically obtain a shared lock
89pub const O_SHLOCK = 0x0010;
90/// atomically obtain an exclusive lock
91pub const O_EXLOCK = 0x0020;
92/// do not follow symlinks
93pub const O_NOFOLLOW = 0x0100;
94/// allow open of symlinks
95pub const O_SYMLINK = 0x200000;
96/// descriptor requested for event notifications only
97pub const O_EVTONLY = 0x8000;
98/// mark as close-on-exec
99pub const O_CLOEXEC = 0x1000000;
63100
64101pub const O_ACCMODE = 3;
65102pub const O_ALERT = 536870912;
......@@ -87,52 +124,102 @@ pub const DT_LNK = 10;
87124pub const DT_SOCK = 12;
88125pub const DT_WHT = 14;
89126
90pub const SIG_BLOCK = 1; /// block specified signal set
91pub const SIG_UNBLOCK = 2; /// unblock specified signal set
92pub const SIG_SETMASK = 3; /// set specified signal set
93
94pub const SIGHUP = 1; /// hangup
95pub const SIGINT = 2; /// interrupt
96pub const SIGQUIT = 3; /// quit
97pub const SIGILL = 4; /// illegal instruction (not reset when caught)
98pub const SIGTRAP = 5; /// trace trap (not reset when caught)
99pub const SIGABRT = 6; /// abort()
100pub const SIGPOLL = 7; /// pollable event ([XSR] generated, not supported)
101pub const SIGIOT = SIGABRT; /// compatibility
102pub const SIGEMT = 7; /// EMT instruction
103pub const SIGFPE = 8; /// floating point exception
104pub const SIGKILL = 9; /// kill (cannot be caught or ignored)
105pub const SIGBUS = 10; /// bus error
106pub const SIGSEGV = 11; /// segmentation violation
107pub const SIGSYS = 12; /// bad argument to system call
108pub const SIGPIPE = 13; /// write on a pipe with no one to read it
109pub const SIGALRM = 14; /// alarm clock
110pub const SIGTERM = 15; /// software termination signal from kill
111pub const SIGURG = 16; /// urgent condition on IO channel
112pub const SIGSTOP = 17; /// sendable stop signal not from tty
113pub const SIGTSTP = 18; /// stop signal from tty
114pub const SIGCONT = 19; /// continue a stopped process
115pub const SIGCHLD = 20; /// to parent on child stop or exit
116pub const SIGTTIN = 21; /// to readers pgrp upon background tty read
117pub const SIGTTOU = 22; /// like TTIN for output if (tp->t_local&LTOSTOP)
118pub const SIGIO = 23; /// input/output possible signal
119pub const SIGXCPU = 24; /// exceeded CPU time limit
120pub const SIGXFSZ = 25; /// exceeded file size limit
121pub const SIGVTALRM = 26; /// virtual time alarm
122pub const SIGPROF = 27; /// profiling time alarm
123pub const SIGWINCH = 28; /// window size changes
124pub const SIGINFO = 29; /// information request
125pub const SIGUSR1 = 30; /// user defined signal 1
126pub const SIGUSR2 = 31; /// user defined signal 2
127
128fn wstatus(x: i32) i32 { return x & 0o177; }
127/// block specified signal set
128pub const SIG_BLOCK = 1;
129/// unblock specified signal set
130pub const SIG_UNBLOCK = 2;
131/// set specified signal set
132pub const SIG_SETMASK = 3;
133
134/// hangup
135pub const SIGHUP = 1;
136/// interrupt
137pub const SIGINT = 2;
138/// quit
139pub const SIGQUIT = 3;
140/// illegal instruction (not reset when caught)
141pub const SIGILL = 4;
142/// trace trap (not reset when caught)
143pub const SIGTRAP = 5;
144/// abort()
145pub const SIGABRT = 6;
146/// pollable event ([XSR] generated, not supported)
147pub const SIGPOLL = 7;
148/// compatibility
149pub const SIGIOT = SIGABRT;
150/// EMT instruction
151pub const SIGEMT = 7;
152/// floating point exception
153pub const SIGFPE = 8;
154/// kill (cannot be caught or ignored)
155pub const SIGKILL = 9;
156/// bus error
157pub const SIGBUS = 10;
158/// segmentation violation
159pub const SIGSEGV = 11;
160/// bad argument to system call
161pub const SIGSYS = 12;
162/// write on a pipe with no one to read it
163pub const SIGPIPE = 13;
164/// alarm clock
165pub const SIGALRM = 14;
166/// software termination signal from kill
167pub const SIGTERM = 15;
168/// urgent condition on IO channel
169pub const SIGURG = 16;
170/// sendable stop signal not from tty
171pub const SIGSTOP = 17;
172/// stop signal from tty
173pub const SIGTSTP = 18;
174/// continue a stopped process
175pub const SIGCONT = 19;
176/// to parent on child stop or exit
177pub const SIGCHLD = 20;
178/// to readers pgrp upon background tty read
179pub const SIGTTIN = 21;
180/// like TTIN for output if (tp->t_local&LTOSTOP)
181pub const SIGTTOU = 22;
182/// input/output possible signal
183pub const SIGIO = 23;
184/// exceeded CPU time limit
185pub const SIGXCPU = 24;
186/// exceeded file size limit
187pub const SIGXFSZ = 25;
188/// virtual time alarm
189pub const SIGVTALRM = 26;
190/// profiling time alarm
191pub const SIGPROF = 27;
192/// window size changes
193pub const SIGWINCH = 28;
194/// information request
195pub const SIGINFO = 29;
196/// user defined signal 1
197pub const SIGUSR1 = 30;
198/// user defined signal 2
199pub const SIGUSR2 = 31;
200
201fn wstatus(x: i32) i32 {
202 return x & 0o177;
203}
129204const wstopped = 0o177;
130pub fn WEXITSTATUS(x: i32) i32 { return x >> 8; }
131pub fn WTERMSIG(x: i32) i32 { return wstatus(x); }
132pub fn WSTOPSIG(x: i32) i32 { return x >> 8; }
133pub fn WIFEXITED(x: i32) bool { return wstatus(x) == 0; }
134pub fn WIFSTOPPED(x: i32) bool { return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; }
135pub fn WIFSIGNALED(x: i32) bool { return wstatus(x) != wstopped and wstatus(x) != 0; }
205pub fn WEXITSTATUS(x: i32) i32 {
206 return x >> 8;
207}
208pub fn WTERMSIG(x: i32) i32 {
209 return wstatus(x);
210}
211pub fn WSTOPSIG(x: i32) i32 {
212 return x >> 8;
213}
214pub fn WIFEXITED(x: i32) bool {
215 return wstatus(x) == 0;
216}
217pub fn WIFSTOPPED(x: i32) bool {
218 return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13;
219}
220pub fn WIFSIGNALED(x: i32) bool {
221 return wstatus(x) != wstopped and wstatus(x) != 0;
222}
136223
137224/// Get the errno from a syscall return value, or 0 for no error.
138225pub fn getErrno(r: usize) usize {
......@@ -184,11 +271,8 @@ pub fn write(fd: i32, buf: &const u8, nbyte: usize) usize {
184271 return errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte));
185272}
186273
187pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: u32, fd: i32,
188 offset: isize) usize
189{
190 const ptr_result = c.mmap(@ptrCast(&c_void, address), length,
191 @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset);
274pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
275 const ptr_result = c.mmap(@ptrCast(&c_void, address), length, @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset);
192276 const isize_result = @bitCast(isize, @ptrToInt(ptr_result));
193277 return errnoWrap(isize_result);
194278}
......@@ -202,7 +286,7 @@ pub fn unlink(path: &const u8) usize {
202286}
203287
204288pub fn getcwd(buf: &u8, size: usize) usize {
205 return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(*c._errno())) else 0;
289 return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
206290}
207291
208292pub fn waitpid(pid: i32, status: &i32, options: u32) usize {
......@@ -223,7 +307,6 @@ pub fn pipe(fds: &[2]i32) usize {
223307 return errnoWrap(c.pipe(@ptrCast(&c_int, fds)));
224308}
225309
226
227310pub fn getdirentries64(fd: i32, buf_ptr: &u8, buf_len: usize, basep: &i64) usize {
228311 return errnoWrap(@bitCast(isize, c.__getdirentries64(fd, buf_ptr, buf_len, basep)));
229312}
......@@ -269,7 +352,7 @@ pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize {
269352}
270353
271354pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) usize {
272 return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0;
355 return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
273356}
274357
275358pub fn setreuid(ruid: u32, euid: u32) usize {
......@@ -287,8 +370,8 @@ pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&s
287370pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize {
288371 assert(sig != SIGKILL);
289372 assert(sig != SIGSTOP);
290 var cact = c.Sigaction {
291 .handler = @ptrCast(extern fn(c_int)void, act.handler),
373 var cact = c.Sigaction{
374 .handler = @ptrCast(extern fn(c_int) void, act.handler),
292375 .sa_flags = @bitCast(c_int, act.flags),
293376 .sa_mask = act.mask,
294377 };
......@@ -298,8 +381,8 @@ pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigacti
298381 return result;
299382 }
300383 if (oact) |old| {
301 *old = Sigaction {
302 .handler = @ptrCast(extern fn(i32)void, coact.handler),
384 old.* = Sigaction{
385 .handler = @ptrCast(extern fn(i32) void, coact.handler),
303386 .flags = @bitCast(u32, coact.sa_flags),
304387 .mask = coact.sa_mask,
305388 };
......@@ -319,23 +402,22 @@ pub const sockaddr = c.sockaddr;
319402
320403/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
321404pub const Sigaction = struct {
322 handler: extern fn(i32)void,
405 handler: extern fn(i32) void,
323406 mask: sigset_t,
324407 flags: u32,
325408};
326409
327410pub fn sigaddset(set: &sigset_t, signo: u5) void {
328 *set |= u32(1) << (signo - 1);
411 set.* |= u32(1) << (signo - 1);
329412}
330413
331414/// Takes the return value from a syscall and formats it back in the way
332415/// that the kernel represents it to libc. Errno was a mistake, let's make
333416/// it go away forever.
334417fn errnoWrap(value: isize) usize {
335 return @bitCast(usize, if (value == -1) -isize(*c._errno()) else value);
418 return @bitCast(usize, if (value == -1) -isize(c._errno().*) else value);
336419}
337420
338
339421pub const timezone = c.timezone;
340422pub const timeval = c.timeval;
341423pub const mach_timebase_info_data = c.mach_timebase_info_data;
std/os/index.zig+41-45
......@@ -137,7 +137,7 @@ pub fn getRandomBytes(buf: []u8) !void {
137137 }
138138 },
139139 Os.zen => {
140 const randomness = []u8 {
140 const randomness = []u8{
141141 42,
142142 1,
143143 7,
......@@ -239,7 +239,7 @@ pub fn close(handle: FileHandle) void {
239239/// Calls POSIX read, and keeps trying if it gets interrupted.
240240pub fn posixRead(fd: i32, buf: []u8) !void {
241241 // Linux can return EINVAL when read amount is > 0x7ffff000
242 // See https://github.com/zig-lang/zig/pull/743#issuecomment-363158274
242 // See https://github.com/ziglang/zig/pull/743#issuecomment-363158274
243243 const max_buf_len = 0x7ffff000;
244244
245245 var index: usize = 0;
......@@ -265,7 +265,7 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
265265 }
266266}
267267
268pub const PosixWriteError = error {
268pub const PosixWriteError = error{
269269 WouldBlock,
270270 FileClosed,
271271 DestinationAddressRequired,
......@@ -281,7 +281,7 @@ pub const PosixWriteError = error {
281281/// Calls POSIX write, and keeps trying if it gets interrupted.
282282pub fn posixWrite(fd: i32, bytes: []const u8) !void {
283283 // Linux can return EINVAL when write amount is > 0x7ffff000
284 // See https://github.com/zig-lang/zig/pull/743#issuecomment-363165856
284 // See https://github.com/ziglang/zig/pull/743#issuecomment-363165856
285285 const max_bytes_len = 0x7ffff000;
286286
287287 var index: usize = 0;
......@@ -310,7 +310,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
310310 }
311311}
312312
313pub const PosixOpenError = error {
313pub const PosixOpenError = error{
314314 OutOfMemory,
315315 AccessDenied,
316316 FileTooBig,
......@@ -477,7 +477,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, allocator:
477477 return posixExecveErrnoToErr(err);
478478}
479479
480pub const PosixExecveError = error {
480pub const PosixExecveError = error{
481481 SystemResources,
482482 AccessDenied,
483483 InvalidExe,
......@@ -512,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {
512512 };
513513}
514514
515pub var linux_aux_raw = []usize {0} ** 38;
515pub var linux_aux_raw = []usize{0} ** 38;
516516pub var posix_environ_raw: []&u8 = undefined;
517517
518518/// Caller must free result when done.
......@@ -667,7 +667,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con
667667 }
668668}
669669
670pub const WindowsSymLinkError = error {
670pub const WindowsSymLinkError = error{
671671 OutOfMemory,
672672 Unexpected,
673673};
......@@ -686,7 +686,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path
686686 }
687687}
688688
689pub const PosixSymLinkError = error {
689pub const PosixSymLinkError = error{
690690 OutOfMemory,
691691 AccessDenied,
692692 DiskQuota,
......@@ -895,7 +895,7 @@ pub const AtomicFile = struct {
895895 else => return err,
896896 };
897897
898 return AtomicFile {
898 return AtomicFile{
899899 .allocator = allocator,
900900 .file = file,
901901 .tmp_path = tmp_path,
......@@ -1087,7 +1087,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void {
10871087/// removes it. If it cannot be removed because it is a non-empty directory,
10881088/// this function recursively removes its entries and then tries again.
10891089/// TODO non-recursive implementation
1090const DeleteTreeError = error {
1090const DeleteTreeError = error{
10911091 OutOfMemory,
10921092 AccessDenied,
10931093 FileTooBig,
......@@ -1217,7 +1217,7 @@ pub const Dir = struct {
12171217 Os.ios => 0,
12181218 else => {},
12191219 };
1220 return Dir {
1220 return Dir{
12211221 .allocator = allocator,
12221222 .fd = fd,
12231223 .darwin_seek = darwin_seek_init,
......@@ -1294,7 +1294,7 @@ pub const Dir = struct {
12941294 posix.DT_WHT => Entry.Kind.Whiteout,
12951295 else => Entry.Kind.Unknown,
12961296 };
1297 return Entry {
1297 return Entry{
12981298 .name = name,
12991299 .kind = entry_kind,
13001300 };
......@@ -1355,7 +1355,7 @@ pub const Dir = struct {
13551355 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
13561356 else => Entry.Kind.Unknown,
13571357 };
1358 return Entry {
1358 return Entry{
13591359 .name = name,
13601360 .kind = entry_kind,
13611361 };
......@@ -1465,7 +1465,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) !void {
14651465 };
14661466}
14671467
1468pub const WindowsGetStdHandleErrs = error {
1468pub const WindowsGetStdHandleErrs = error{
14691469 NoStdHandles,
14701470 Unexpected,
14711471};
......@@ -1489,7 +1489,7 @@ pub const ArgIteratorPosix = struct {
14891489 count: usize,
14901490
14911491 pub fn init() ArgIteratorPosix {
1492 return ArgIteratorPosix {
1492 return ArgIteratorPosix{
14931493 .index = 0,
14941494 .count = raw.len,
14951495 };
......@@ -1522,16 +1522,14 @@ pub const ArgIteratorWindows = struct {
15221522 quote_count: usize,
15231523 seen_quote_count: usize,
15241524
1525 pub const NextError = error {
1526 OutOfMemory,
1527 };
1525 pub const NextError = error{OutOfMemory};
15281526
15291527 pub fn init() ArgIteratorWindows {
15301528 return initWithCmdLine(windows.GetCommandLineA());
15311529 }
15321530
15331531 pub fn initWithCmdLine(cmd_line: &const u8) ArgIteratorWindows {
1534 return ArgIteratorWindows {
1532 return ArgIteratorWindows{
15351533 .index = 0,
15361534 .cmd_line = cmd_line,
15371535 .in_quote = false,
......@@ -1676,9 +1674,7 @@ pub const ArgIterator = struct {
16761674 inner: InnerType,
16771675
16781676 pub fn init() ArgIterator {
1679 return ArgIterator {
1680 .inner = InnerType.init(),
1681 };
1677 return ArgIterator{ .inner = InnerType.init() };
16821678 }
16831679
16841680 pub const NextError = ArgIteratorWindows.NextError;
......@@ -1757,33 +1753,33 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void {
17571753}
17581754
17591755test "windows arg parsing" {
1760 testWindowsCmdLine(c"a b\tc d", [][]const u8 {
1756 testWindowsCmdLine(c"a b\tc d", [][]const u8{
17611757 "a",
17621758 "b",
17631759 "c",
17641760 "d",
17651761 });
1766 testWindowsCmdLine(c"\"abc\" d e", [][]const u8 {
1762 testWindowsCmdLine(c"\"abc\" d e", [][]const u8{
17671763 "abc",
17681764 "d",
17691765 "e",
17701766 });
1771 testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8 {
1767 testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{
17721768 "a\\\\\\b",
17731769 "de fg",
17741770 "h",
17751771 });
1776 testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8 {
1772 testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{
17771773 "a\\\"b",
17781774 "c",
17791775 "d",
17801776 });
1781 testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8 {
1777 testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{
17821778 "a\\\\b c",
17831779 "d",
17841780 "e",
17851781 });
1786 testWindowsCmdLine(c"a b\tc \"d f", [][]const u8 {
1782 testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{
17871783 "a",
17881784 "b",
17891785 "c",
......@@ -1791,7 +1787,7 @@ test "windows arg parsing" {
17911787 "f",
17921788 });
17931789
1794 testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8 {
1790 testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8{
17951791 ".\\..\\zig-cache\\build",
17961792 "bin\\zig.exe",
17971793 ".\\..",
......@@ -1811,7 +1807,7 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const
18111807
18121808// TODO make this a build variable that you can set
18131809const unexpected_error_tracing = false;
1814const UnexpectedError = error {
1810const UnexpectedError = error{
18151811 /// The Operating System returned an undocumented error code.
18161812 Unexpected,
18171813};
......@@ -1950,7 +1946,7 @@ pub fn isTty(handle: FileHandle) bool {
19501946 }
19511947}
19521948
1953pub const PosixSocketError = error {
1949pub const PosixSocketError = error{
19541950 /// Permission to create a socket of the specified type and/or
19551951 /// pro‐tocol is denied.
19561952 PermissionDenied,
......@@ -1992,7 +1988,7 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 {
19921988 }
19931989}
19941990
1995pub const PosixBindError = error {
1991pub const PosixBindError = error{
19961992 /// The address is protected, and the user is not the superuser.
19971993 /// For UNIX domain sockets: Search permission is denied on a component
19981994 /// of the path prefix.
......@@ -2065,7 +2061,7 @@ pub fn posixBind(fd: i32, addr: &const posix.sockaddr) PosixBindError!void {
20652061 }
20662062}
20672063
2068const PosixListenError = error {
2064const PosixListenError = error{
20692065 /// Another socket is already listening on the same port.
20702066 /// For Internet domain sockets, the socket referred to by sockfd had not previously
20712067 /// been bound to an address and, upon attempting to bind it to an ephemeral port, it
......@@ -2098,7 +2094,7 @@ pub fn posixListen(sockfd: i32, backlog: u32) PosixListenError!void {
20982094 }
20992095}
21002096
2101pub const PosixAcceptError = error {
2097pub const PosixAcceptError = error{
21022098 /// The socket is marked nonblocking and no connections are present to be accepted.
21032099 WouldBlock,
21042100
......@@ -2165,7 +2161,7 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError!
21652161 }
21662162}
21672163
2168pub const LinuxEpollCreateError = error {
2164pub const LinuxEpollCreateError = error{
21692165 /// Invalid value specified in flags.
21702166 InvalidSyscall,
21712167
......@@ -2198,7 +2194,7 @@ pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 {
21982194 }
21992195}
22002196
2201pub const LinuxEpollCtlError = error {
2197pub const LinuxEpollCtlError = error{
22022198 /// epfd or fd is not a valid file descriptor.
22032199 InvalidFileDescriptor,
22042200
......@@ -2271,7 +2267,7 @@ pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usiz
22712267 }
22722268}
22732269
2274pub const PosixGetSockNameError = error {
2270pub const PosixGetSockNameError = error{
22752271 /// Insufficient resources were available in the system to perform the operation.
22762272 SystemResources,
22772273
......@@ -2295,7 +2291,7 @@ pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr {
22952291 }
22962292}
22972293
2298pub const PosixConnectError = error {
2294pub const PosixConnectError = error{
22992295 /// For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket
23002296 /// file, or search permission is denied for one of the directories in the path prefix.
23012297 /// or
......@@ -2485,7 +2481,7 @@ pub const Thread = struct {
24852481 }
24862482};
24872483
2488pub const SpawnThreadError = error {
2484pub const SpawnThreadError = error{
24892485 /// A system-imposed limit on the number of threads was encountered.
24902486 /// There are a number of limits that may trigger this error:
24912487 /// * the RLIMIT_NPROC soft resource limit (set via setrlimit(2)),
......@@ -2517,7 +2513,7 @@ pub const SpawnThreadError = error {
25172513/// caller must call wait on the returned thread
25182514pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread {
25192515 // TODO compile-time call graph analysis to determine stack upper bound
2520 // https://github.com/zig-lang/zig/issues/157
2516 // https://github.com/ziglang/zig/issues/157
25212517 const default_stack_size = 8 * 1024 * 1024;
25222518
25232519 const Context = @typeOf(context);
......@@ -2533,7 +2529,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
25332529 if (@sizeOf(Context) == 0) {
25342530 return startFn({});
25352531 } else {
2536 return startFn(*@ptrCast(&Context, @alignCast(@alignOf(Context), arg)));
2532 return startFn(@ptrCast(&Context, @alignCast(@alignOf(Context), arg)).*);
25372533 }
25382534 }
25392535 };
......@@ -2563,7 +2559,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
25632559 if (@sizeOf(Context) == 0) {
25642560 return startFn({});
25652561 } else {
2566 return startFn(*@intToPtr(&const Context, ctx_addr));
2562 return startFn(@intToPtr(&const Context, ctx_addr).*);
25672563 }
25682564 }
25692565 extern fn posixThreadMain(ctx: ?&c_void) ?&c_void {
......@@ -2571,7 +2567,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
25712567 _ = startFn({});
25722568 return null;
25732569 } else {
2574 _ = startFn(*@ptrCast(&const Context, @alignCast(@alignOf(Context), ctx)));
2570 _ = startFn(@ptrCast(&const Context, @alignCast(@alignOf(Context), ctx)).*);
25752571 return null;
25762572 }
25772573 }
......@@ -2591,7 +2587,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread
25912587 stack_end -= stack_end % @alignOf(Context);
25922588 assert(stack_end >= stack_addr);
25932589 const context_ptr = @alignCast(@alignOf(Context), @intToPtr(&Context, stack_end));
2594 *context_ptr = context;
2590 context_ptr.* = context;
25952591 arg = stack_end;
25962592 }
25972593
std/os/linux/index.zig+189-190
......@@ -30,96 +30,95 @@ pub const FUTEX_PRIVATE_FLAG = 128;
3030
3131pub const FUTEX_CLOCK_REALTIME = 256;
3232
33
34pub const PROT_NONE = 0;
35pub const PROT_READ = 1;
36pub const PROT_WRITE = 2;
37pub const PROT_EXEC = 4;
33pub const PROT_NONE = 0;
34pub const PROT_READ = 1;
35pub const PROT_WRITE = 2;
36pub const PROT_EXEC = 4;
3837pub const PROT_GROWSDOWN = 0x01000000;
39pub const PROT_GROWSUP = 0x02000000;
40
41pub const MAP_FAILED = @maxValue(usize);
42pub const MAP_SHARED = 0x01;
43pub const MAP_PRIVATE = 0x02;
44pub const MAP_TYPE = 0x0f;
45pub const MAP_FIXED = 0x10;
46pub const MAP_ANONYMOUS = 0x20;
47pub const MAP_NORESERVE = 0x4000;
48pub const MAP_GROWSDOWN = 0x0100;
49pub const MAP_DENYWRITE = 0x0800;
38pub const PROT_GROWSUP = 0x02000000;
39
40pub const MAP_FAILED = @maxValue(usize);
41pub const MAP_SHARED = 0x01;
42pub const MAP_PRIVATE = 0x02;
43pub const MAP_TYPE = 0x0f;
44pub const MAP_FIXED = 0x10;
45pub const MAP_ANONYMOUS = 0x20;
46pub const MAP_NORESERVE = 0x4000;
47pub const MAP_GROWSDOWN = 0x0100;
48pub const MAP_DENYWRITE = 0x0800;
5049pub const MAP_EXECUTABLE = 0x1000;
51pub const MAP_LOCKED = 0x2000;
52pub const MAP_POPULATE = 0x8000;
53pub const MAP_NONBLOCK = 0x10000;
54pub const MAP_STACK = 0x20000;
55pub const MAP_HUGETLB = 0x40000;
56pub const MAP_FILE = 0;
50pub const MAP_LOCKED = 0x2000;
51pub const MAP_POPULATE = 0x8000;
52pub const MAP_NONBLOCK = 0x10000;
53pub const MAP_STACK = 0x20000;
54pub const MAP_HUGETLB = 0x40000;
55pub const MAP_FILE = 0;
5756
5857pub const F_OK = 0;
5958pub const X_OK = 1;
6059pub const W_OK = 2;
6160pub const R_OK = 4;
6261
63pub const WNOHANG = 1;
64pub const WUNTRACED = 2;
65pub const WSTOPPED = 2;
66pub const WEXITED = 4;
62pub const WNOHANG = 1;
63pub const WUNTRACED = 2;
64pub const WSTOPPED = 2;
65pub const WEXITED = 4;
6766pub const WCONTINUED = 8;
68pub const WNOWAIT = 0x1000000;
69
70pub const SA_NOCLDSTOP = 1;
71pub const SA_NOCLDWAIT = 2;
72pub const SA_SIGINFO = 4;
73pub const SA_ONSTACK = 0x08000000;
74pub const SA_RESTART = 0x10000000;
75pub const SA_NODEFER = 0x40000000;
76pub const SA_RESETHAND = 0x80000000;
77pub const SA_RESTORER = 0x04000000;
78
79pub const SIGHUP = 1;
80pub const SIGINT = 2;
81pub const SIGQUIT = 3;
82pub const SIGILL = 4;
83pub const SIGTRAP = 5;
84pub const SIGABRT = 6;
85pub const SIGIOT = SIGABRT;
86pub const SIGBUS = 7;
87pub const SIGFPE = 8;
88pub const SIGKILL = 9;
89pub const SIGUSR1 = 10;
90pub const SIGSEGV = 11;
91pub const SIGUSR2 = 12;
92pub const SIGPIPE = 13;
93pub const SIGALRM = 14;
94pub const SIGTERM = 15;
67pub const WNOWAIT = 0x1000000;
68
69pub const SA_NOCLDSTOP = 1;
70pub const SA_NOCLDWAIT = 2;
71pub const SA_SIGINFO = 4;
72pub const SA_ONSTACK = 0x08000000;
73pub const SA_RESTART = 0x10000000;
74pub const SA_NODEFER = 0x40000000;
75pub const SA_RESETHAND = 0x80000000;
76pub const SA_RESTORER = 0x04000000;
77
78pub const SIGHUP = 1;
79pub const SIGINT = 2;
80pub const SIGQUIT = 3;
81pub const SIGILL = 4;
82pub const SIGTRAP = 5;
83pub const SIGABRT = 6;
84pub const SIGIOT = SIGABRT;
85pub const SIGBUS = 7;
86pub const SIGFPE = 8;
87pub const SIGKILL = 9;
88pub const SIGUSR1 = 10;
89pub const SIGSEGV = 11;
90pub const SIGUSR2 = 12;
91pub const SIGPIPE = 13;
92pub const SIGALRM = 14;
93pub const SIGTERM = 15;
9594pub const SIGSTKFLT = 16;
96pub const SIGCHLD = 17;
97pub const SIGCONT = 18;
98pub const SIGSTOP = 19;
99pub const SIGTSTP = 20;
100pub const SIGTTIN = 21;
101pub const SIGTTOU = 22;
102pub const SIGURG = 23;
103pub const SIGXCPU = 24;
104pub const SIGXFSZ = 25;
95pub const SIGCHLD = 17;
96pub const SIGCONT = 18;
97pub const SIGSTOP = 19;
98pub const SIGTSTP = 20;
99pub const SIGTTIN = 21;
100pub const SIGTTOU = 22;
101pub const SIGURG = 23;
102pub const SIGXCPU = 24;
103pub const SIGXFSZ = 25;
105104pub const SIGVTALRM = 26;
106pub const SIGPROF = 27;
107pub const SIGWINCH = 28;
108pub const SIGIO = 29;
109pub const SIGPOLL = 29;
110pub const SIGPWR = 30;
111pub const SIGSYS = 31;
105pub const SIGPROF = 27;
106pub const SIGWINCH = 28;
107pub const SIGIO = 29;
108pub const SIGPOLL = 29;
109pub const SIGPWR = 30;
110pub const SIGSYS = 31;
112111pub const SIGUNUSED = SIGSYS;
113112
114113pub const O_RDONLY = 0o0;
115114pub const O_WRONLY = 0o1;
116pub const O_RDWR = 0o2;
115pub const O_RDWR = 0o2;
117116
118117pub const SEEK_SET = 0;
119118pub const SEEK_CUR = 1;
120119pub const SEEK_END = 2;
121120
122pub const SIG_BLOCK = 0;
121pub const SIG_BLOCK = 0;
123122pub const SIG_UNBLOCK = 1;
124123pub const SIG_SETMASK = 2;
125124
......@@ -408,7 +407,6 @@ pub const DT_LNK = 10;
408407pub const DT_SOCK = 12;
409408pub const DT_WHT = 14;
410409
411
412410pub const TCGETS = 0x5401;
413411pub const TCSETS = 0x5402;
414412pub const TCSETSW = 0x5403;
......@@ -539,23 +537,23 @@ pub const MS_BIND = 4096;
539537pub const MS_MOVE = 8192;
540538pub const MS_REC = 16384;
541539pub const MS_SILENT = 32768;
542pub const MS_POSIXACL = (1<<16);
543pub const MS_UNBINDABLE = (1<<17);
544pub const MS_PRIVATE = (1<<18);
545pub const MS_SLAVE = (1<<19);
546pub const MS_SHARED = (1<<20);
547pub const MS_RELATIME = (1<<21);
548pub const MS_KERNMOUNT = (1<<22);
549pub const MS_I_VERSION = (1<<23);
550pub const MS_STRICTATIME = (1<<24);
551pub const MS_LAZYTIME = (1<<25);
552pub const MS_NOREMOTELOCK = (1<<27);
553pub const MS_NOSEC = (1<<28);
554pub const MS_BORN = (1<<29);
555pub const MS_ACTIVE = (1<<30);
556pub const MS_NOUSER = (1<<31);
557
558pub const MS_RMT_MASK = (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|MS_LAZYTIME);
540pub const MS_POSIXACL = (1 << 16);
541pub const MS_UNBINDABLE = (1 << 17);
542pub const MS_PRIVATE = (1 << 18);
543pub const MS_SLAVE = (1 << 19);
544pub const MS_SHARED = (1 << 20);
545pub const MS_RELATIME = (1 << 21);
546pub const MS_KERNMOUNT = (1 << 22);
547pub const MS_I_VERSION = (1 << 23);
548pub const MS_STRICTATIME = (1 << 24);
549pub const MS_LAZYTIME = (1 << 25);
550pub const MS_NOREMOTELOCK = (1 << 27);
551pub const MS_NOSEC = (1 << 28);
552pub const MS_BORN = (1 << 29);
553pub const MS_ACTIVE = (1 << 30);
554pub const MS_NOUSER = (1 << 31);
555
556pub const MS_RMT_MASK = (MS_RDONLY | MS_SYNCHRONOUS | MS_MANDLOCK | MS_I_VERSION | MS_LAZYTIME);
559557
560558pub const MS_MGC_VAL = 0xc0ed0000;
561559pub const MS_MGC_MSK = 0xffff0000;
......@@ -565,7 +563,6 @@ pub const MNT_DETACH = 2;
565563pub const MNT_EXPIRE = 4;
566564pub const UMOUNT_NOFOLLOW = 8;
567565
568
569566pub const S_IFMT = 0o170000;
570567
571568pub const S_IFDIR = 0o040000;
......@@ -626,15 +623,30 @@ pub const TFD_CLOEXEC = O_CLOEXEC;
626623pub const TFD_TIMER_ABSTIME = 1;
627624pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1);
628625
629fn unsigned(s: i32) u32 { return @bitCast(u32, s); }
630fn signed(s: u32) i32 { return @bitCast(i32, s); }
631pub fn WEXITSTATUS(s: i32) i32 { return signed((unsigned(s) & 0xff00) >> 8); }
632pub fn WTERMSIG(s: i32) i32 { return signed(unsigned(s) & 0x7f); }
633pub fn WSTOPSIG(s: i32) i32 { return WEXITSTATUS(s); }
634pub fn WIFEXITED(s: i32) bool { return WTERMSIG(s) == 0; }
635pub fn WIFSTOPPED(s: i32) bool { return (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00; }
636pub fn WIFSIGNALED(s: i32) bool { return (unsigned(s)&0xffff)-%1 < 0xff; }
637
626fn unsigned(s: i32) u32 {
627 return @bitCast(u32, s);
628}
629fn signed(s: u32) i32 {
630 return @bitCast(i32, s);
631}
632pub fn WEXITSTATUS(s: i32) i32 {
633 return signed((unsigned(s) & 0xff00) >> 8);
634}
635pub fn WTERMSIG(s: i32) i32 {
636 return signed(unsigned(s) & 0x7f);
637}
638pub fn WSTOPSIG(s: i32) i32 {
639 return WEXITSTATUS(s);
640}
641pub fn WIFEXITED(s: i32) bool {
642 return WTERMSIG(s) == 0;
643}
644pub fn WIFSTOPPED(s: i32) bool {
645 return (u16)(((unsigned(s) & 0xffff) *% 0x10001) >> 8) > 0x7f00;
646}
647pub fn WIFSIGNALED(s: i32) bool {
648 return (unsigned(s) & 0xffff) -% 1 < 0xff;
649}
638650
639651pub const winsize = extern struct {
640652 ws_row: u16,
......@@ -707,8 +719,7 @@ pub fn umount2(special: &const u8, flags: u32) usize {
707719}
708720
709721pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
710 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd),
711 @bitCast(usize, offset));
722 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), @bitCast(usize, offset));
712723}
713724
714725pub fn munmap(address: usize, length: usize) usize {
......@@ -812,7 +823,8 @@ pub fn clock_gettime(clk_id: i32, tp: &timespec) usize {
812823 if (@ptrToInt(f) != 0) {
813824 const rc = f(clk_id, tp);
814825 switch (rc) {
815 0, @bitCast(usize, isize(-EINVAL)) => return rc,
826 0,
827 @bitCast(usize, isize(-EINVAL)) => return rc,
816828 else => {},
817829 }
818830 }
......@@ -823,8 +835,7 @@ var vdso_clock_gettime = init_vdso_clock_gettime;
823835extern fn init_vdso_clock_gettime(clk: i32, ts: &timespec) usize {
824836 const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM);
825837 var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr);
826 _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f,
827 builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic);
838 _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic);
828839 if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS));
829840 return f(clk, ts);
830841}
......@@ -918,18 +929,18 @@ pub fn getpid() i32 {
918929}
919930
920931pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) usize {
921 return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG/8);
932 return syscall4(SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG / 8);
922933}
923934
924935pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize {
925936 assert(sig >= 1);
926937 assert(sig != SIGKILL);
927938 assert(sig != SIGSTOP);
928 var ksa = k_sigaction {
939 var ksa = k_sigaction{
929940 .handler = act.handler,
930941 .flags = act.flags | SA_RESTORER,
931942 .mask = undefined,
932 .restorer = @ptrCast(extern fn()void, restore_rt),
943 .restorer = @ptrCast(extern fn() void, restore_rt),
933944 };
934945 var ksa_old: k_sigaction = undefined;
935946 @memcpy(@ptrCast(&u8, &ksa.mask), @ptrCast(&const u8, &act.mask), 8);
......@@ -952,22 +963,22 @@ const all_mask = []usize{@maxValue(usize)};
952963const app_mask = []usize{0xfffffffc7fffffff};
953964
954965const k_sigaction = extern struct {
955 handler: extern fn(i32)void,
966 handler: extern fn(i32) void,
956967 flags: usize,
957 restorer: extern fn()void,
968 restorer: extern fn() void,
958969 mask: [2]u32,
959970};
960971
961972/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
962973pub const Sigaction = struct {
963 handler: extern fn(i32)void,
974 handler: extern fn(i32) void,
964975 mask: sigset_t,
965976 flags: u32,
966977};
967978
968pub const SIG_ERR = @intToPtr(extern fn(i32)void, @maxValue(usize));
969pub const SIG_DFL = @intToPtr(extern fn(i32)void, 0);
970pub const SIG_IGN = @intToPtr(extern fn(i32)void, 1);
979pub const SIG_ERR = @intToPtr(extern fn(i32) void, @maxValue(usize));
980pub const SIG_DFL = @intToPtr(extern fn(i32) void, 0);
981pub const SIG_IGN = @intToPtr(extern fn(i32) void, 1);
971982pub const empty_sigset = []usize{0} ** sigset_t.len;
972983
973984pub fn raise(sig: i32) usize {
......@@ -980,25 +991,25 @@ pub fn raise(sig: i32) usize {
980991}
981992
982993fn blockAllSignals(set: &sigset_t) void {
983 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG/8);
994 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG / 8);
984995}
985996
986997fn blockAppSignals(set: &sigset_t) void {
987 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG/8);
998 _ = syscall4(SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG / 8);
988999}
9891000
9901001fn restoreSignals(set: &sigset_t) void {
991 _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG/8);
1002 _ = syscall4(SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG / 8);
9921003}
9931004
9941005pub fn sigaddset(set: &sigset_t, sig: u6) void {
9951006 const s = sig - 1;
996 (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1));
1007 (set.*)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1));
9971008}
9981009
9991010pub fn sigismember(set: &const sigset_t, sig: u6) bool {
10001011 const s = sig - 1;
1001 return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
1012 return ((set.*)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
10021013}
10031014
10041015pub const in_port_t = u16;
......@@ -1062,9 +1073,7 @@ pub fn recvmsg(fd: i32, msg: &msghdr, flags: u32) usize {
10621073 return syscall3(SYS_recvmsg, usize(fd), @ptrToInt(msg), flags);
10631074}
10641075
1065pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32,
1066 noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize
1067{
1076pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize {
10681077 return syscall6(SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
10691078}
10701079
......@@ -1132,25 +1141,16 @@ pub fn fgetxattr(fd: usize, name: &const u8, value: &void, size: usize) usize {
11321141 return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size);
11331142}
11341143
1135pub fn setxattr(path: &const u8, name: &const u8, value: &const void,
1136 size: usize, flags: usize) usize {
1137
1138 return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value),
1139 size, flags);
1144pub fn setxattr(path: &const u8, name: &const u8, value: &const void, size: usize, flags: usize) usize {
1145 return syscall5(SYS_setxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
11401146}
11411147
1142pub fn lsetxattr(path: &const u8, name: &const u8, value: &const void,
1143 size: usize, flags: usize) usize {
1144
1145 return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value),
1146 size, flags);
1148pub fn lsetxattr(path: &const u8, name: &const u8, value: &const void, size: usize, flags: usize) usize {
1149 return syscall5(SYS_lsetxattr, @ptrToInt(path), @ptrToInt(name), @ptrToInt(value), size, flags);
11471150}
11481151
1149pub fn fsetxattr(fd: usize, name: &const u8, value: &const void,
1150 size: usize, flags: usize) usize {
1151
1152 return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value),
1153 size, flags);
1152pub fn fsetxattr(fd: usize, name: &const u8, value: &const void, size: usize, flags: usize) usize {
1153 return syscall5(SYS_fsetxattr, fd, @ptrToInt(name), @ptrToInt(value), size, flags);
11541154}
11551155
11561156pub fn removexattr(path: &const u8, name: &const u8) usize {
......@@ -1199,7 +1199,7 @@ pub fn timerfd_create(clockid: i32, flags: u32) usize {
11991199
12001200pub const itimerspec = extern struct {
12011201 it_interval: timespec,
1202 it_value: timespec
1202 it_value: timespec,
12031203};
12041204
12051205pub fn timerfd_gettime(fd: i32, curr_value: &itimerspec) usize {
......@@ -1211,30 +1211,30 @@ pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_va
12111211}
12121212
12131213pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
1214pub const _LINUX_CAPABILITY_U32S_1 = 1;
1214pub const _LINUX_CAPABILITY_U32S_1 = 1;
12151215
12161216pub const _LINUX_CAPABILITY_VERSION_2 = 0x20071026;
1217pub const _LINUX_CAPABILITY_U32S_2 = 2;
1217pub const _LINUX_CAPABILITY_U32S_2 = 2;
12181218
12191219pub const _LINUX_CAPABILITY_VERSION_3 = 0x20080522;
1220pub const _LINUX_CAPABILITY_U32S_3 = 2;
1220pub const _LINUX_CAPABILITY_U32S_3 = 2;
12211221
1222pub const VFS_CAP_REVISION_MASK = 0xFF000000;
1223pub const VFS_CAP_REVISION_SHIFT = 24;
1224pub const VFS_CAP_FLAGS_MASK = ~VFS_CAP_REVISION_MASK;
1222pub const VFS_CAP_REVISION_MASK = 0xFF000000;
1223pub const VFS_CAP_REVISION_SHIFT = 24;
1224pub const VFS_CAP_FLAGS_MASK = ~VFS_CAP_REVISION_MASK;
12251225pub const VFS_CAP_FLAGS_EFFECTIVE = 0x000001;
12261226
12271227pub const VFS_CAP_REVISION_1 = 0x01000000;
1228pub const VFS_CAP_U32_1 = 1;
1229pub const XATTR_CAPS_SZ_1 = @sizeOf(u32)*(1 + 2*VFS_CAP_U32_1);
1228pub const VFS_CAP_U32_1 = 1;
1229pub const XATTR_CAPS_SZ_1 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_1);
12301230
12311231pub const VFS_CAP_REVISION_2 = 0x02000000;
1232pub const VFS_CAP_U32_2 = 2;
1233pub const XATTR_CAPS_SZ_2 = @sizeOf(u32)*(1 + 2*VFS_CAP_U32_2);
1232pub const VFS_CAP_U32_2 = 2;
1233pub const XATTR_CAPS_SZ_2 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_2);
12341234
1235pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2;
1236pub const VFS_CAP_U32 = VFS_CAP_U32_2;
1237pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2;
1235pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2;
1236pub const VFS_CAP_U32 = VFS_CAP_U32_2;
1237pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2;
12381238
12391239pub const vfs_cap_data = extern struct {
12401240 //all of these are mandated as little endian
......@@ -1245,49 +1245,48 @@ pub const vfs_cap_data = extern struct {
12451245 };
12461246
12471247 magic_etc: u32,
1248 data: [VFS_CAP_U32]Data,
1248 data: [VFS_CAP_U32]Data,
12491249};
12501250
1251
1252pub const CAP_CHOWN = 0;
1253pub const CAP_DAC_OVERRIDE = 1;
1254pub const CAP_DAC_READ_SEARCH = 2;
1255pub const CAP_FOWNER = 3;
1256pub const CAP_FSETID = 4;
1257pub const CAP_KILL = 5;
1258pub const CAP_SETGID = 6;
1259pub const CAP_SETUID = 7;
1260pub const CAP_SETPCAP = 8;
1261pub const CAP_LINUX_IMMUTABLE = 9;
1262pub const CAP_NET_BIND_SERVICE = 10;
1263pub const CAP_NET_BROADCAST = 11;
1264pub const CAP_NET_ADMIN = 12;
1265pub const CAP_NET_RAW = 13;
1266pub const CAP_IPC_LOCK = 14;
1267pub const CAP_IPC_OWNER = 15;
1268pub const CAP_SYS_MODULE = 16;
1269pub const CAP_SYS_RAWIO = 17;
1270pub const CAP_SYS_CHROOT = 18;
1271pub const CAP_SYS_PTRACE = 19;
1272pub const CAP_SYS_PACCT = 20;
1273pub const CAP_SYS_ADMIN = 21;
1274pub const CAP_SYS_BOOT = 22;
1275pub const CAP_SYS_NICE = 23;
1276pub const CAP_SYS_RESOURCE = 24;
1277pub const CAP_SYS_TIME = 25;
1278pub const CAP_SYS_TTY_CONFIG = 26;
1279pub const CAP_MKNOD = 27;
1280pub const CAP_LEASE = 28;
1281pub const CAP_AUDIT_WRITE = 29;
1282pub const CAP_AUDIT_CONTROL = 30;
1283pub const CAP_SETFCAP = 31;
1284pub const CAP_MAC_OVERRIDE = 32;
1285pub const CAP_MAC_ADMIN = 33;
1286pub const CAP_SYSLOG = 34;
1287pub const CAP_WAKE_ALARM = 35;
1288pub const CAP_BLOCK_SUSPEND = 36;
1289pub const CAP_AUDIT_READ = 37;
1290pub const CAP_LAST_CAP = CAP_AUDIT_READ;
1251pub const CAP_CHOWN = 0;
1252pub const CAP_DAC_OVERRIDE = 1;
1253pub const CAP_DAC_READ_SEARCH = 2;
1254pub const CAP_FOWNER = 3;
1255pub const CAP_FSETID = 4;
1256pub const CAP_KILL = 5;
1257pub const CAP_SETGID = 6;
1258pub const CAP_SETUID = 7;
1259pub const CAP_SETPCAP = 8;
1260pub const CAP_LINUX_IMMUTABLE = 9;
1261pub const CAP_NET_BIND_SERVICE = 10;
1262pub const CAP_NET_BROADCAST = 11;
1263pub const CAP_NET_ADMIN = 12;
1264pub const CAP_NET_RAW = 13;
1265pub const CAP_IPC_LOCK = 14;
1266pub const CAP_IPC_OWNER = 15;
1267pub const CAP_SYS_MODULE = 16;
1268pub const CAP_SYS_RAWIO = 17;
1269pub const CAP_SYS_CHROOT = 18;
1270pub const CAP_SYS_PTRACE = 19;
1271pub const CAP_SYS_PACCT = 20;
1272pub const CAP_SYS_ADMIN = 21;
1273pub const CAP_SYS_BOOT = 22;
1274pub const CAP_SYS_NICE = 23;
1275pub const CAP_SYS_RESOURCE = 24;
1276pub const CAP_SYS_TIME = 25;
1277pub const CAP_SYS_TTY_CONFIG = 26;
1278pub const CAP_MKNOD = 27;
1279pub const CAP_LEASE = 28;
1280pub const CAP_AUDIT_WRITE = 29;
1281pub const CAP_AUDIT_CONTROL = 30;
1282pub const CAP_SETFCAP = 31;
1283pub const CAP_MAC_OVERRIDE = 32;
1284pub const CAP_MAC_ADMIN = 33;
1285pub const CAP_SYSLOG = 34;
1286pub const CAP_WAKE_ALARM = 35;
1287pub const CAP_BLOCK_SUSPEND = 36;
1288pub const CAP_AUDIT_READ = 37;
1289pub const CAP_LAST_CAP = CAP_AUDIT_READ;
12911290
12921291pub fn cap_valid(u8: x) bool {
12931292 return x >= 0 and x <= CAP_LAST_CAP;
std/os/test.zig+1-1
......@@ -12,7 +12,7 @@ const AtomicOrder = builtin.AtomicOrder;
1212test "makePath, put some files in it, deleteTree" {
1313 if (builtin.os == builtin.Os.windows) {
1414 // TODO implement os.Dir for windows
15 // https://github.com/zig-lang/zig/issues/709
15 // https://github.com/ziglang/zig/issues/709
1616 return;
1717 }
1818 try os.makePath(a, "os_test_tmp/b/c");
std/os/time.zig+1-1
......@@ -135,7 +135,7 @@ pub const Timer = struct {
135135
136136 //At some point we may change our minds on RAW, but for now we're
137137 // sticking with posix standard MONOTONIC. For more information, see:
138 // https://github.com/zig-lang/zig/pull/933
138 // https://github.com/ziglang/zig/pull/933
139139 //
140140 //const monotonic_clock_id = switch(builtin.os) {
141141 // Os.linux => linux.CLOCK_MONOTONIC_RAW,
std/segmented_list.zig+40-30
......@@ -95,7 +95,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
9595
9696 /// Deinitialize with `deinit`
9797 pub fn init(allocator: &Allocator) Self {
98 return Self {
98 return Self{
9999 .allocator = allocator,
100100 .len = 0,
101101 .prealloc_segment = undefined,
......@@ -106,7 +106,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
106106 pub fn deinit(self: &Self) void {
107107 self.freeShelves(ShelfIndex(self.dynamic_segments.len), 0);
108108 self.allocator.free(self.dynamic_segments);
109 *self = undefined;
109 self.* = undefined;
110110 }
111111
112112 pub fn at(self: &Self, i: usize) &T {
......@@ -120,7 +120,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
120120
121121 pub fn push(self: &Self, item: &const T) !void {
122122 const new_item_ptr = try self.addOne();
123 *new_item_ptr = *item;
123 new_item_ptr.* = item.*;
124124 }
125125
126126 pub fn pushMany(self: &Self, items: []const T) !void {
......@@ -130,11 +130,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
130130 }
131131
132132 pub fn pop(self: &Self) ?T {
133 if (self.len == 0)
134 return null;
133 if (self.len == 0) return null;
135134
136135 const index = self.len - 1;
137 const result = *self.uncheckedAt(index);
136 const result = self.uncheckedAt(index).*;
138137 self.len = index;
139138 return result;
140139 }
......@@ -247,8 +246,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
247246 shelf_size: usize,
248247
249248 pub fn next(it: &Iterator) ?&T {
250 if (it.index >= it.list.len)
251 return null;
249 if (it.index >= it.list.len) return null;
252250 if (it.index < prealloc_item_count) {
253251 const ptr = &it.list.prealloc_segment[it.index];
254252 it.index += 1;
......@@ -272,12 +270,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
272270 }
273271
274272 pub fn prev(it: &Iterator) ?&T {
275 if (it.index == 0)
276 return null;
273 if (it.index == 0) return null;
277274
278275 it.index -= 1;
279 if (it.index < prealloc_item_count)
280 return &it.list.prealloc_segment[it.index];
276 if (it.index < prealloc_item_count) return &it.list.prealloc_segment[it.index];
281277
282278 if (it.box_index == 0) {
283279 it.shelf_index -= 1;
......@@ -298,21 +294,25 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
298294
299295 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
300296 }
297
298 pub fn set(it: &Iterator, index: usize) void {
299 it.index = index;
300 if (index < prealloc_item_count) return;
301 it.shelf_index = shelfIndex(index);
302 it.box_index = boxIndex(index, it.shelf_index);
303 it.shelf_size = shelfSize(it.shelf_index);
304 }
301305 };
302306
303307 pub fn iterator(self: &Self, start_index: usize) Iterator {
304 var it = Iterator {
308 var it = Iterator{
305309 .list = self,
306 .index = start_index,
310 .index = undefined,
307311 .shelf_index = undefined,
308312 .box_index = undefined,
309313 .shelf_size = undefined,
310314 };
311 if (start_index >= prealloc_item_count) {
312 it.shelf_index = shelfIndex(start_index);
313 it.box_index = boxIndex(start_index, it.shelf_index);
314 it.shelf_size = shelfSize(it.shelf_index);
315 }
315 it.set(start_index);
316316 return it;
317317 }
318318 };
......@@ -335,25 +335,31 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void {
335335 var list = SegmentedList(i32, prealloc).init(allocator);
336336 defer list.deinit();
337337
338 {var i: usize = 0; while (i < 100) : (i += 1) {
339 try list.push(i32(i + 1));
340 assert(list.len == i + 1);
341 }}
338 {
339 var i: usize = 0;
340 while (i < 100) : (i += 1) {
341 try list.push(i32(i + 1));
342 assert(list.len == i + 1);
343 }
344 }
342345
343 {var i: usize = 0; while (i < 100) : (i += 1) {
344 assert(*list.at(i) == i32(i + 1));
345 }}
346 {
347 var i: usize = 0;
348 while (i < 100) : (i += 1) {
349 assert(list.at(i).* == i32(i + 1));
350 }
351 }
346352
347353 {
348354 var it = list.iterator(0);
349355 var x: i32 = 0;
350356 while (it.next()) |item| {
351357 x += 1;
352 assert(*item == x);
358 assert(item.* == x);
353359 }
354360 assert(x == 100);
355361 while (it.prev()) |item| : (x -= 1) {
356 assert(*item == x);
362 assert(item.* == x);
357363 }
358364 assert(x == 0);
359365 }
......@@ -361,14 +367,18 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void {
361367 assert(??list.pop() == 100);
362368 assert(list.len == 99);
363369
364 try list.pushMany([]i32 { 1, 2, 3 });
370 try list.pushMany([]i32{
371 1,
372 2,
373 3,
374 });
365375 assert(list.len == 102);
366376 assert(??list.pop() == 3);
367377 assert(??list.pop() == 2);
368378 assert(??list.pop() == 1);
369379 assert(list.len == 99);
370380
371 try list.pushMany([]const i32 {});
381 try list.pushMany([]const i32{});
372382 assert(list.len == 99);
373383
374384 var i: i32 = 99;
std/sort.zig+398-164
......@@ -5,15 +5,18 @@ const math = std.math;
55const builtin = @import("builtin");
66
77/// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required).
8pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void {
9 {var i: usize = 1; while (i < items.len) : (i += 1) {
10 const x = items[i];
11 var j: usize = i;
12 while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
13 items[j] = items[j - 1];
8pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void {
9 {
10 var i: usize = 1;
11 while (i < items.len) : (i += 1) {
12 const x = items[i];
13 var j: usize = i;
14 while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
15 items[j] = items[j - 1];
16 }
17 items[j] = x;
1418 }
15 items[j] = x;
16 }}
19 }
1720}
1821
1922const Range = struct {
......@@ -21,7 +24,10 @@ const Range = struct {
2124 end: usize,
2225
2326 fn init(start: usize, end: usize) Range {
24 return Range { .start = start, .end = end };
27 return Range{
28 .start = start,
29 .end = end,
30 };
2531 }
2632
2733 fn length(self: &const Range) usize {
......@@ -29,7 +35,6 @@ const Range = struct {
2935 }
3036};
3137
32
3338const Iterator = struct {
3439 size: usize,
3540 power_of_two: usize,
......@@ -42,7 +47,7 @@ const Iterator = struct {
4247 fn init(size2: usize, min_level: usize) Iterator {
4348 const power_of_two = math.floorPowerOfTwo(usize, size2);
4449 const denominator = power_of_two / min_level;
45 return Iterator {
50 return Iterator{
4651 .numerator = 0,
4752 .decimal = 0,
4853 .size = size2,
......@@ -68,7 +73,10 @@ const Iterator = struct {
6873 self.decimal += 1;
6974 }
7075
71 return Range {.start = start, .end = self.decimal};
76 return Range{
77 .start = start,
78 .end = self.decimal,
79 };
7280 }
7381
7482 fn finished(self: &Iterator) bool {
......@@ -100,7 +108,7 @@ const Pull = struct {
100108
101109/// Stable in-place sort. O(n) best case, O(n*log(n)) worst case and average case. O(1) memory (no allocator required).
102110/// Currently implemented as block sort.
103pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void {
111pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void {
104112 // Implementation ported from https://github.com/BonzaiThePenguin/WikiSort/blob/master/WikiSort.c
105113 var cache: [512]T = undefined;
106114
......@@ -123,7 +131,16 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
123131 // http://pages.ripco.net/~jgamble/nw.html
124132 var iterator = Iterator.init(items.len, 4);
125133 while (!iterator.finished()) {
126 var order = []u8{0, 1, 2, 3, 4, 5, 6, 7};
134 var order = []u8{
135 0,
136 1,
137 2,
138 3,
139 4,
140 5,
141 6,
142 7,
143 };
127144 const range = iterator.nextRange();
128145
129146 const sliced_items = items[range.start..];
......@@ -149,56 +166,56 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
149166 swap(T, sliced_items, lessThan, &order, 3, 5);
150167 swap(T, sliced_items, lessThan, &order, 3, 4);
151168 },
152 7 => {
153 swap(T, sliced_items, lessThan, &order, 1, 2);
154 swap(T, sliced_items, lessThan, &order, 3, 4);
155 swap(T, sliced_items, lessThan, &order, 5, 6);
156 swap(T, sliced_items, lessThan, &order, 0, 2);
157 swap(T, sliced_items, lessThan, &order, 3, 5);
158 swap(T, sliced_items, lessThan, &order, 4, 6);
159 swap(T, sliced_items, lessThan, &order, 0, 1);
160 swap(T, sliced_items, lessThan, &order, 4, 5);
161 swap(T, sliced_items, lessThan, &order, 2, 6);
162 swap(T, sliced_items, lessThan, &order, 0, 4);
163 swap(T, sliced_items, lessThan, &order, 1, 5);
164 swap(T, sliced_items, lessThan, &order, 0, 3);
165 swap(T, sliced_items, lessThan, &order, 2, 5);
166 swap(T, sliced_items, lessThan, &order, 1, 3);
167 swap(T, sliced_items, lessThan, &order, 2, 4);
168 swap(T, sliced_items, lessThan, &order, 2, 3);
169 },
170 6 => {
171 swap(T, sliced_items, lessThan, &order, 1, 2);
172 swap(T, sliced_items, lessThan, &order, 4, 5);
173 swap(T, sliced_items, lessThan, &order, 0, 2);
174 swap(T, sliced_items, lessThan, &order, 3, 5);
175 swap(T, sliced_items, lessThan, &order, 0, 1);
176 swap(T, sliced_items, lessThan, &order, 3, 4);
177 swap(T, sliced_items, lessThan, &order, 2, 5);
178 swap(T, sliced_items, lessThan, &order, 0, 3);
179 swap(T, sliced_items, lessThan, &order, 1, 4);
180 swap(T, sliced_items, lessThan, &order, 2, 4);
181 swap(T, sliced_items, lessThan, &order, 1, 3);
182 swap(T, sliced_items, lessThan, &order, 2, 3);
183 },
184 5 => {
185 swap(T, sliced_items, lessThan, &order, 0, 1);
186 swap(T, sliced_items, lessThan, &order, 3, 4);
187 swap(T, sliced_items, lessThan, &order, 2, 4);
188 swap(T, sliced_items, lessThan, &order, 2, 3);
189 swap(T, sliced_items, lessThan, &order, 1, 4);
190 swap(T, sliced_items, lessThan, &order, 0, 3);
191 swap(T, sliced_items, lessThan, &order, 0, 2);
192 swap(T, sliced_items, lessThan, &order, 1, 3);
193 swap(T, sliced_items, lessThan, &order, 1, 2);
194 },
195 4 => {
196 swap(T, sliced_items, lessThan, &order, 0, 1);
197 swap(T, sliced_items, lessThan, &order, 2, 3);
198 swap(T, sliced_items, lessThan, &order, 0, 2);
199 swap(T, sliced_items, lessThan, &order, 1, 3);
200 swap(T, sliced_items, lessThan, &order, 1, 2);
201 },
169 7 => {
170 swap(T, sliced_items, lessThan, &order, 1, 2);
171 swap(T, sliced_items, lessThan, &order, 3, 4);
172 swap(T, sliced_items, lessThan, &order, 5, 6);
173 swap(T, sliced_items, lessThan, &order, 0, 2);
174 swap(T, sliced_items, lessThan, &order, 3, 5);
175 swap(T, sliced_items, lessThan, &order, 4, 6);
176 swap(T, sliced_items, lessThan, &order, 0, 1);
177 swap(T, sliced_items, lessThan, &order, 4, 5);
178 swap(T, sliced_items, lessThan, &order, 2, 6);
179 swap(T, sliced_items, lessThan, &order, 0, 4);
180 swap(T, sliced_items, lessThan, &order, 1, 5);
181 swap(T, sliced_items, lessThan, &order, 0, 3);
182 swap(T, sliced_items, lessThan, &order, 2, 5);
183 swap(T, sliced_items, lessThan, &order, 1, 3);
184 swap(T, sliced_items, lessThan, &order, 2, 4);
185 swap(T, sliced_items, lessThan, &order, 2, 3);
186 },
187 6 => {
188 swap(T, sliced_items, lessThan, &order, 1, 2);
189 swap(T, sliced_items, lessThan, &order, 4, 5);
190 swap(T, sliced_items, lessThan, &order, 0, 2);
191 swap(T, sliced_items, lessThan, &order, 3, 5);
192 swap(T, sliced_items, lessThan, &order, 0, 1);
193 swap(T, sliced_items, lessThan, &order, 3, 4);
194 swap(T, sliced_items, lessThan, &order, 2, 5);
195 swap(T, sliced_items, lessThan, &order, 0, 3);
196 swap(T, sliced_items, lessThan, &order, 1, 4);
197 swap(T, sliced_items, lessThan, &order, 2, 4);
198 swap(T, sliced_items, lessThan, &order, 1, 3);
199 swap(T, sliced_items, lessThan, &order, 2, 3);
200 },
201 5 => {
202 swap(T, sliced_items, lessThan, &order, 0, 1);
203 swap(T, sliced_items, lessThan, &order, 3, 4);
204 swap(T, sliced_items, lessThan, &order, 2, 4);
205 swap(T, sliced_items, lessThan, &order, 2, 3);
206 swap(T, sliced_items, lessThan, &order, 1, 4);
207 swap(T, sliced_items, lessThan, &order, 0, 3);
208 swap(T, sliced_items, lessThan, &order, 0, 2);
209 swap(T, sliced_items, lessThan, &order, 1, 3);
210 swap(T, sliced_items, lessThan, &order, 1, 2);
211 },
212 4 => {
213 swap(T, sliced_items, lessThan, &order, 0, 1);
214 swap(T, sliced_items, lessThan, &order, 2, 3);
215 swap(T, sliced_items, lessThan, &order, 0, 2);
216 swap(T, sliced_items, lessThan, &order, 1, 3);
217 swap(T, sliced_items, lessThan, &order, 1, 2);
218 },
202219 else => {},
203220 }
204221 }
......@@ -273,7 +290,6 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
273290 // we merged two levels at the same time, so we're done with this level already
274291 // (iterator.nextLevel() is called again at the bottom of this outer merge loop)
275292 _ = iterator.nextLevel();
276
277293 } else {
278294 iterator.begin();
279295 while (!iterator.finished()) {
......@@ -303,7 +319,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
303319 // 8. redistribute the two internal buffers back into the items
304320
305321 var block_size: usize = math.sqrt(iterator.length());
306 var buffer_size = iterator.length()/block_size + 1;
322 var buffer_size = iterator.length() / block_size + 1;
307323
308324 // as an optimization, we really only need to pull out the internal buffers once for each level of merges
309325 // after that we can reuse the same buffers over and over, then redistribute it when we're finished with this level
......@@ -316,8 +332,18 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
316332 var start: usize = 0;
317333 var pull_index: usize = 0;
318334 var pull = []Pull{
319 Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),},
320 Pull {.from = 0, .to = 0, .count = 0, .range = Range.init(0, 0),},
335 Pull{
336 .from = 0,
337 .to = 0,
338 .count = 0,
339 .range = Range.init(0, 0),
340 },
341 Pull{
342 .from = 0,
343 .to = 0,
344 .count = 0,
345 .range = Range.init(0, 0),
346 },
321347 };
322348
323349 var buffer1 = Range.init(0, 0);
......@@ -355,7 +381,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
355381 // these values will be pulled out to the start of A
356382 last = A.start;
357383 count = 1;
358 while (count < find) : ({last = index; count += 1;}) {
384 while (count < find) : ({
385 last = index;
386 count += 1;
387 }) {
359388 index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count);
360389 if (index == A.end) break;
361390 }
......@@ -363,7 +392,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
363392
364393 if (count >= buffer_size) {
365394 // keep track of the range within the items where we'll need to "pull out" these values to create the internal buffer
366 pull[pull_index] = Pull {
395 pull[pull_index] = Pull{
367396 .range = Range.init(A.start, B.end),
368397 .count = count,
369398 .from = index,
......@@ -398,7 +427,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
398427 } else if (pull_index == 0 and count > buffer1.length()) {
399428 // keep track of the largest buffer we were able to find
400429 buffer1 = Range.init(A.start, A.start + count);
401 pull[pull_index] = Pull {
430 pull[pull_index] = Pull{
402431 .range = Range.init(A.start, B.end),
403432 .count = count,
404433 .from = index,
......@@ -410,7 +439,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
410439 // these values will be pulled out to the end of B
411440 last = B.end - 1;
412441 count = 1;
413 while (count < find) : ({last = index - 1; count += 1;}) {
442 while (count < find) : ({
443 last = index - 1;
444 count += 1;
445 }) {
414446 index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count);
415447 if (index == B.start) break;
416448 }
......@@ -418,7 +450,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
418450
419451 if (count >= buffer_size) {
420452 // keep track of the range within the items where we'll need to "pull out" these values to create the internal buffe
421 pull[pull_index] = Pull {
453 pull[pull_index] = Pull{
422454 .range = Range.init(A.start, B.end),
423455 .count = count,
424456 .from = index,
......@@ -457,7 +489,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
457489 } else if (pull_index == 0 and count > buffer1.length()) {
458490 // keep track of the largest buffer we were able to find
459491 buffer1 = Range.init(B.end - count, B.end);
460 pull[pull_index] = Pull {
492 pull[pull_index] = Pull{
461493 .range = Range.init(A.start, B.end),
462494 .count = count,
463495 .from = index,
......@@ -496,7 +528,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
496528
497529 // adjust block_size and buffer_size based on the values we were able to pull out
498530 buffer_size = buffer1.length();
499 block_size = iterator.length()/buffer_size + 1;
531 block_size = iterator.length() / buffer_size + 1;
500532
501533 // the first buffer NEEDS to be large enough to tag each of the evenly sized A blocks,
502534 // so this was originally here to test the math for adjusting block_size above
......@@ -547,7 +579,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
547579 // swap the first value of each A block with the value in buffer1
548580 var indexA = buffer1.start;
549581 index = firstA.end;
550 while (index < blockA.end) : ({indexA += 1; index += block_size;}) {
582 while (index < blockA.end) : ({
583 indexA += 1;
584 index += block_size;
585 }) {
551586 mem.swap(T, &items[indexA], &items[index]);
552587 }
553588
......@@ -626,9 +661,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
626661
627662 // if there are no more A blocks remaining, this step is finished!
628663 blockA.start += block_size;
629 if (blockA.length() == 0)
630 break;
631
664 if (blockA.length() == 0) break;
632665 } else if (blockB.length() < block_size) {
633666 // move the last B block, which is unevenly sized, to before the remaining A blocks, by using a rotation
634667 // the cache is disabled here since it might contain the contents of the previous A block
......@@ -709,7 +742,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons
709742}
710743
711744// merge operation without a buffer
712fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)bool) void {
745fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T, &const T) bool) void {
713746 if (A_arg.length() == 0 or B_arg.length() == 0) return;
714747
715748 // this just repeatedly binary searches into B and rotates A into position.
......@@ -730,8 +763,8 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const
730763 // again, this is NOT a general-purpose solution – it only works well in this case!
731764 // kind of like how the O(n^2) insertion sort is used in some places
732765
733 var A = *A_arg;
734 var B = *B_arg;
766 var A = A_arg.*;
767 var B = B_arg.*;
735768
736769 while (true) {
737770 // find the first place in B where the first item in A needs to be inserted
......@@ -751,7 +784,7 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const
751784}
752785
753786// merge operation using an internal buffer
754fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, buffer: &const Range) void {
787fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, buffer: &const Range) void {
755788 // whenever we find a value to add to the final array, swap it with the value that's already in that spot
756789 // when this algorithm is finished, 'buffer' will contain its original contents, but in a different order
757790 var A_count: usize = 0;
......@@ -787,9 +820,9 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s
787820
788821// combine a linear search with a binary search to reduce the number of comparisons in situations
789822// where have some idea as to how many unique values there are and where the next value might be
790fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
823fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
791824 if (range.length() == 0) return range.start;
792 const skip = math.max(range.length()/unique, usize(1));
825 const skip = math.max(range.length() / unique, usize(1));
793826
794827 var index = range.start + skip;
795828 while (lessThan(items[index - 1], value)) : (index += skip) {
......@@ -801,9 +834,9 @@ fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const
801834 return binaryFirst(T, items, value, Range.init(index - skip, index), lessThan);
802835}
803836
804fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
837fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
805838 if (range.length() == 0) return range.start;
806 const skip = math.max(range.length()/unique, usize(1));
839 const skip = math.max(range.length() / unique, usize(1));
807840
808841 var index = range.end - skip;
809842 while (index > range.start and !lessThan(items[index - 1], value)) : (index -= skip) {
......@@ -815,9 +848,9 @@ fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &cons
815848 return binaryFirst(T, items, value, Range.init(index, index + skip), lessThan);
816849}
817850
818fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
851fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
819852 if (range.length() == 0) return range.start;
820 const skip = math.max(range.length()/unique, usize(1));
853 const skip = math.max(range.length() / unique, usize(1));
821854
822855 var index = range.start + skip;
823856 while (!lessThan(value, items[index - 1])) : (index += skip) {
......@@ -829,9 +862,9 @@ fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const
829862 return binaryLast(T, items, value, Range.init(index - skip, index), lessThan);
830863}
831864
832fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize {
865fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize {
833866 if (range.length() == 0) return range.start;
834 const skip = math.max(range.length()/unique, usize(1));
867 const skip = math.max(range.length() / unique, usize(1));
835868
836869 var index = range.end - skip;
837870 while (index > range.start and lessThan(value, items[index - 1])) : (index -= skip) {
......@@ -843,12 +876,12 @@ fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const
843876 return binaryLast(T, items, value, Range.init(index, index + skip), lessThan);
844877}
845878
846fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize {
879fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize {
847880 var start = range.start;
848881 var end = range.end - 1;
849882 if (range.start >= range.end) return range.end;
850883 while (start < end) {
851 const mid = start + (end - start)/2;
884 const mid = start + (end - start) / 2;
852885 if (lessThan(items[mid], value)) {
853886 start = mid + 1;
854887 } else {
......@@ -861,12 +894,12 @@ fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Rang
861894 return start;
862895}
863896
864fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize {
897fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize {
865898 var start = range.start;
866899 var end = range.end - 1;
867900 if (range.start >= range.end) return range.end;
868901 while (start < end) {
869 const mid = start + (end - start)/2;
902 const mid = start + (end - start) / 2;
870903 if (!lessThan(value, items[mid])) {
871904 start = mid + 1;
872905 } else {
......@@ -879,7 +912,7 @@ fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range
879912 return start;
880913}
881914
882fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, into: []T) void {
915fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, into: []T) void {
883916 var A_index: usize = A.start;
884917 var B_index: usize = B.start;
885918 const A_last = A.end;
......@@ -909,7 +942,7 @@ fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, less
909942 }
910943}
911944
912fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, cache: []T) void {
945fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, cache: []T) void {
913946 // A fits into the cache, so use that instead of the internal buffer
914947 var A_index: usize = 0;
915948 var B_index: usize = B.start;
......@@ -937,29 +970,27 @@ fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range,
937970 mem.copy(T, items[insert_index..], cache[A_index..A_last]);
938971}
939972
940fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool, order: &[8]u8, x: usize, y: usize) void {
941 if (lessThan(items[y], items[x]) or
942 ((*order)[x] > (*order)[y] and !lessThan(items[x], items[y])))
943 {
973fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool, order: &[8]u8, x: usize, y: usize) void {
974 if (lessThan(items[y], items[x]) or ((order.*)[x] > (order.*)[y] and !lessThan(items[x], items[y]))) {
944975 mem.swap(T, &items[x], &items[y]);
945 mem.swap(u8, &(*order)[x], &(*order)[y]);
976 mem.swap(u8, &(order.*)[x], &(order.*)[y]);
946977 }
947978}
948979
949980fn i32asc(lhs: &const i32, rhs: &const i32) bool {
950 return *lhs < *rhs;
981 return lhs.* < rhs.*;
951982}
952983
953984fn i32desc(lhs: &const i32, rhs: &const i32) bool {
954 return *rhs < *lhs;
985 return rhs.* < lhs.*;
955986}
956987
957988fn u8asc(lhs: &const u8, rhs: &const u8) bool {
958 return *lhs < *rhs;
989 return lhs.* < rhs.*;
959990}
960991
961992fn u8desc(lhs: &const u8, rhs: &const u8) bool {
962 return *rhs < *lhs;
993 return rhs.* < lhs.*;
963994}
964995
965996test "stable sort" {
......@@ -967,44 +998,125 @@ test "stable sort" {
967998 comptime testStableSort();
968999}
9691000fn testStableSort() void {
970 var expected = []IdAndValue {
971 IdAndValue{.id = 0, .value = 0},
972 IdAndValue{.id = 1, .value = 0},
973 IdAndValue{.id = 2, .value = 0},
974 IdAndValue{.id = 0, .value = 1},
975 IdAndValue{.id = 1, .value = 1},
976 IdAndValue{.id = 2, .value = 1},
977 IdAndValue{.id = 0, .value = 2},
978 IdAndValue{.id = 1, .value = 2},
979 IdAndValue{.id = 2, .value = 2},
1001 var expected = []IdAndValue{
1002 IdAndValue{
1003 .id = 0,
1004 .value = 0,
1005 },
1006 IdAndValue{
1007 .id = 1,
1008 .value = 0,
1009 },
1010 IdAndValue{
1011 .id = 2,
1012 .value = 0,
1013 },
1014 IdAndValue{
1015 .id = 0,
1016 .value = 1,
1017 },
1018 IdAndValue{
1019 .id = 1,
1020 .value = 1,
1021 },
1022 IdAndValue{
1023 .id = 2,
1024 .value = 1,
1025 },
1026 IdAndValue{
1027 .id = 0,
1028 .value = 2,
1029 },
1030 IdAndValue{
1031 .id = 1,
1032 .value = 2,
1033 },
1034 IdAndValue{
1035 .id = 2,
1036 .value = 2,
1037 },
9801038 };
981 var cases = [][9]IdAndValue {
982 []IdAndValue {
983 IdAndValue{.id = 0, .value = 0},
984 IdAndValue{.id = 0, .value = 1},
985 IdAndValue{.id = 0, .value = 2},
986 IdAndValue{.id = 1, .value = 0},
987 IdAndValue{.id = 1, .value = 1},
988 IdAndValue{.id = 1, .value = 2},
989 IdAndValue{.id = 2, .value = 0},
990 IdAndValue{.id = 2, .value = 1},
991 IdAndValue{.id = 2, .value = 2},
1039 var cases = [][9]IdAndValue{
1040 []IdAndValue{
1041 IdAndValue{
1042 .id = 0,
1043 .value = 0,
1044 },
1045 IdAndValue{
1046 .id = 0,
1047 .value = 1,
1048 },
1049 IdAndValue{
1050 .id = 0,
1051 .value = 2,
1052 },
1053 IdAndValue{
1054 .id = 1,
1055 .value = 0,
1056 },
1057 IdAndValue{
1058 .id = 1,
1059 .value = 1,
1060 },
1061 IdAndValue{
1062 .id = 1,
1063 .value = 2,
1064 },
1065 IdAndValue{
1066 .id = 2,
1067 .value = 0,
1068 },
1069 IdAndValue{
1070 .id = 2,
1071 .value = 1,
1072 },
1073 IdAndValue{
1074 .id = 2,
1075 .value = 2,
1076 },
9921077 },
993 []IdAndValue {
994 IdAndValue{.id = 0, .value = 2},
995 IdAndValue{.id = 0, .value = 1},
996 IdAndValue{.id = 0, .value = 0},
997 IdAndValue{.id = 1, .value = 2},
998 IdAndValue{.id = 1, .value = 1},
999 IdAndValue{.id = 1, .value = 0},
1000 IdAndValue{.id = 2, .value = 2},
1001 IdAndValue{.id = 2, .value = 1},
1002 IdAndValue{.id = 2, .value = 0},
1078 []IdAndValue{
1079 IdAndValue{
1080 .id = 0,
1081 .value = 2,
1082 },
1083 IdAndValue{
1084 .id = 0,
1085 .value = 1,
1086 },
1087 IdAndValue{
1088 .id = 0,
1089 .value = 0,
1090 },
1091 IdAndValue{
1092 .id = 1,
1093 .value = 2,
1094 },
1095 IdAndValue{
1096 .id = 1,
1097 .value = 1,
1098 },
1099 IdAndValue{
1100 .id = 1,
1101 .value = 0,
1102 },
1103 IdAndValue{
1104 .id = 2,
1105 .value = 2,
1106 },
1107 IdAndValue{
1108 .id = 2,
1109 .value = 1,
1110 },
1111 IdAndValue{
1112 .id = 2,
1113 .value = 0,
1114 },
10031115 },
10041116 };
10051117 for (cases) |*case| {
1006 insertionSort(IdAndValue, (*case)[0..], cmpByValue);
1007 for (*case) |item, i| {
1118 insertionSort(IdAndValue, (case.*)[0..], cmpByValue);
1119 for (case.*) |item, i| {
10081120 assert(item.id == expected[i].id);
10091121 assert(item.value == expected[i].value);
10101122 }
......@@ -1019,13 +1131,31 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) bool {
10191131}
10201132
10211133test "std.sort" {
1022 const u8cases = [][]const []const u8 {
1023 [][]const u8{"", ""},
1024 [][]const u8{"a", "a"},
1025 [][]const u8{"az", "az"},
1026 [][]const u8{"za", "az"},
1027 [][]const u8{"asdf", "adfs"},
1028 [][]const u8{"one", "eno"},
1134 const u8cases = [][]const []const u8{
1135 [][]const u8{
1136 "",
1137 "",
1138 },
1139 [][]const u8{
1140 "a",
1141 "a",
1142 },
1143 [][]const u8{
1144 "az",
1145 "az",
1146 },
1147 [][]const u8{
1148 "za",
1149 "az",
1150 },
1151 [][]const u8{
1152 "asdf",
1153 "adfs",
1154 },
1155 [][]const u8{
1156 "one",
1157 "eno",
1158 },
10291159 };
10301160
10311161 for (u8cases) |case| {
......@@ -1036,13 +1166,59 @@ test "std.sort" {
10361166 assert(mem.eql(u8, slice, case[1]));
10371167 }
10381168
1039 const i32cases = [][]const []const i32 {
1040 [][]const i32{[]i32{}, []i32{}},
1041 [][]const i32{[]i32{1}, []i32{1}},
1042 [][]const i32{[]i32{0, 1}, []i32{0, 1}},
1043 [][]const i32{[]i32{1, 0}, []i32{0, 1}},
1044 [][]const i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}},
1045 [][]const i32{[]i32{2, 1, 3}, []i32{1, 2, 3}},
1169 const i32cases = [][]const []const i32{
1170 [][]const i32{
1171 []i32{},
1172 []i32{},
1173 },
1174 [][]const i32{
1175 []i32{1},
1176 []i32{1},
1177 },
1178 [][]const i32{
1179 []i32{
1180 0,
1181 1,
1182 },
1183 []i32{
1184 0,
1185 1,
1186 },
1187 },
1188 [][]const i32{
1189 []i32{
1190 1,
1191 0,
1192 },
1193 []i32{
1194 0,
1195 1,
1196 },
1197 },
1198 [][]const i32{
1199 []i32{
1200 1,
1201 -1,
1202 0,
1203 },
1204 []i32{
1205 -1,
1206 0,
1207 1,
1208 },
1209 },
1210 [][]const i32{
1211 []i32{
1212 2,
1213 1,
1214 3,
1215 },
1216 []i32{
1217 1,
1218 2,
1219 3,
1220 },
1221 },
10461222 };
10471223
10481224 for (i32cases) |case| {
......@@ -1055,13 +1231,59 @@ test "std.sort" {
10551231}
10561232
10571233test "std.sort descending" {
1058 const rev_cases = [][]const []const i32 {
1059 [][]const i32{[]i32{}, []i32{}},
1060 [][]const i32{[]i32{1}, []i32{1}},
1061 [][]const i32{[]i32{0, 1}, []i32{1, 0}},
1062 [][]const i32{[]i32{1, 0}, []i32{1, 0}},
1063 [][]const i32{[]i32{1, -1, 0}, []i32{1, 0, -1}},
1064 [][]const i32{[]i32{2, 1, 3}, []i32{3, 2, 1}},
1234 const rev_cases = [][]const []const i32{
1235 [][]const i32{
1236 []i32{},
1237 []i32{},
1238 },
1239 [][]const i32{
1240 []i32{1},
1241 []i32{1},
1242 },
1243 [][]const i32{
1244 []i32{
1245 0,
1246 1,
1247 },
1248 []i32{
1249 1,
1250 0,
1251 },
1252 },
1253 [][]const i32{
1254 []i32{
1255 1,
1256 0,
1257 },
1258 []i32{
1259 1,
1260 0,
1261 },
1262 },
1263 [][]const i32{
1264 []i32{
1265 1,
1266 -1,
1267 0,
1268 },
1269 []i32{
1270 1,
1271 0,
1272 -1,
1273 },
1274 },
1275 [][]const i32{
1276 []i32{
1277 2,
1278 1,
1279 3,
1280 },
1281 []i32{
1282 3,
1283 2,
1284 1,
1285 },
1286 },
10651287 };
10661288
10671289 for (rev_cases) |case| {
......@@ -1074,10 +1296,22 @@ test "std.sort descending" {
10741296}
10751297
10761298test "another sort case" {
1077 var arr = []i32{ 5, 3, 1, 2, 4 };
1299 var arr = []i32{
1300 5,
1301 3,
1302 1,
1303 2,
1304 4,
1305 };
10781306 sort(i32, arr[0..], i32asc);
10791307
1080 assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));
1308 assert(mem.eql(i32, arr, []i32{
1309 1,
1310 2,
1311 3,
1312 4,
1313 5,
1314 }));
10811315}
10821316
10831317test "sort fuzz testing" {
......@@ -1112,7 +1346,7 @@ fn fuzzTest(rng: &std.rand.Random) void {
11121346 }
11131347}
11141348
1115pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T {
1349pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T {
11161350 var i: usize = 0;
11171351 var smallest = items[0];
11181352 for (items[1..]) |item| {
......@@ -1123,7 +1357,7 @@ pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const
11231357 return smallest;
11241358}
11251359
1126pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T {
1360pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T {
11271361 var i: usize = 0;
11281362 var biggest = items[0];
11291363 for (items[1..]) |item| {
std/special/bootstrap.zig+4-4
......@@ -27,10 +27,10 @@ extern fn zen_start() noreturn {
2727nakedcc fn _start() noreturn {
2828 switch (builtin.arch) {
2929 builtin.Arch.x86_64 => {
30 argc_ptr = asm("lea (%%rsp), %[argc]": [argc] "=r" (-> &usize));
30 argc_ptr = asm ("lea (%%rsp), %[argc]" : [argc] "=r" (-> &usize));
3131 },
3232 builtin.Arch.i386 => {
33 argc_ptr = asm("lea (%%esp), %[argc]": [argc] "=r" (-> &usize));
33 argc_ptr = asm ("lea (%%esp), %[argc]" : [argc] "=r" (-> &usize));
3434 },
3535 else => @compileError("unsupported arch"),
3636 }
......@@ -46,7 +46,7 @@ extern fn WinMainCRTStartup() noreturn {
4646}
4747
4848fn posixCallMainAndExit() noreturn {
49 const argc = *argc_ptr;
49 const argc = argc_ptr.*;
5050 const argv = @ptrCast(&&u8, &argc_ptr[1]);
5151 const envp_nullable = @ptrCast(&?&u8, &argv[argc + 1]);
5252 var envp_count: usize = 0;
......@@ -56,7 +56,7 @@ fn posixCallMainAndExit() noreturn {
5656 const auxv = &@ptrCast(&usize, envp.ptr)[envp_count + 1];
5757 var i: usize = 0;
5858 while (auxv[i] != 0) : (i += 2) {
59 if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i+1];
59 if (auxv[i] < std.os.linux_aux_raw.len) std.os.linux_aux_raw[auxv[i]] = auxv[i + 1];
6060 }
6161 std.debug.assert(std.os.linux_aux_raw[std.elf.AT_PAGESZ] == std.os.page_size);
6262 }
std/special/compiler_rt/comparetf2.zig+2-2
......@@ -1,4 +1,4 @@
1// TODO https://github.com/zig-lang/zig/issues/305
1// TODO https://github.com/ziglang/zig/issues/305
22// and then make the return types of some of these functions the enum instead of c_int
33const LE_LESS = c_int(-1);
44const LE_EQUAL = c_int(0);
......@@ -59,7 +59,7 @@ pub extern fn __letf2(a: f128, b: f128) c_int {
5959 ;
6060}
6161
62// TODO https://github.com/zig-lang/zig/issues/305
62// TODO https://github.com/ziglang/zig/issues/305
6363// and then make the return types of some of these functions the enum instead of c_int
6464const GE_LESS = c_int(-1);
6565const GE_EQUAL = c_int(0);
std/special/compiler_rt/fixuint.zig+2-4
......@@ -36,12 +36,10 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
3636 const significand: rep_t = (aAbs & significandMask) | implicitBit;
3737
3838 // If either the value or the exponent is negative, the result is zero.
39 if (sign == -1 or exponent < 0)
40 return 0;
39 if (sign == -1 or exponent < 0) return 0;
4140
4241 // If the value is too large for the integer type, saturate.
43 if (c_uint(exponent) >= fixuint_t.bit_count)
44 return ~fixuint_t(0);
42 if (c_uint(exponent) >= fixuint_t.bit_count) return ~fixuint_t(0);
4543
4644 // If 0 <= exponent < significandBits, right shift to get the result.
4745 // Otherwise, shift left.
std/special/compiler_rt/fixunsdfdi.zig-1
......@@ -9,4 +9,3 @@ pub extern fn __fixunsdfdi(a: f64) u64 {
99test "import fixunsdfdi" {
1010 _ = @import("fixunsdfdi_test.zig");
1111}
12
std/special/compiler_rt/fixunsdfsi.zig-1
......@@ -9,4 +9,3 @@ pub extern fn __fixunsdfsi(a: f64) u32 {
99test "import fixunsdfsi" {
1010 _ = @import("fixunsdfsi_test.zig");
1111}
12
std/special/compiler_rt/fixunssfti.zig-1
......@@ -9,4 +9,3 @@ pub extern fn __fixunssfti(a: f32) u128 {
99test "import fixunssfti" {
1010 _ = @import("fixunssfti_test.zig");
1111}
12
std/special/compiler_rt/fixunstfti.zig-1
......@@ -9,4 +9,3 @@ pub extern fn __fixunstfti(a: f128) u128 {
99test "import fixunstfti" {
1010 _ = @import("fixunstfti_test.zig");
1111}
12
std/special/compiler_rt/index.zig+674-144
......@@ -92,9 +92,10 @@ pub fn setXmm0(comptime T: type, value: T) void {
9292 const aligned_value: T align(16) = value;
9393 asm volatile (
9494 \\movaps (%[ptr]), %%xmm0
95 :
96 : [ptr] "r" (&aligned_value)
97 : "xmm0");
95
96 :
97 : [ptr] "r" (&aligned_value)
98 : "xmm0");
9899}
99100
100101extern fn __udivdi3(a: u64, b: u64) u64 {
......@@ -283,26 +284,27 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) u32 {
283284 @setRuntimeSafety(is_test);
284285
285286 const d = __udivsi3(a, b);
286 *rem = u32(i32(a) -% (i32(d) * i32(b)));
287 rem.* = u32(i32(a) -% (i32(d) * i32(b)));
287288 return d;
288289}
289290
290
291291extern fn __udivsi3(n: u32, d: u32) u32 {
292292 @setRuntimeSafety(is_test);
293293
294294 const n_uword_bits: c_uint = u32.bit_count;
295295 // special cases
296 if (d == 0)
297 return 0; // ?!
298 if (n == 0)
299 return 0;
296 if (d == 0) return 0; // ?!
297 if (n == 0) return 0;
300298 var sr = @bitCast(c_uint, c_int(@clz(d)) - c_int(@clz(n)));
301299 // 0 <= sr <= n_uword_bits - 1 or sr large
302 if (sr > n_uword_bits - 1) // d > r
300 if (sr > n_uword_bits - 1) {
301 // d > r
303302 return 0;
304 if (sr == n_uword_bits - 1) // d == 1
303 }
304 if (sr == n_uword_bits - 1) {
305 // d == 1
305306 return n;
307 }
306308 sr += 1;
307309 // 1 <= sr <= n_uword_bits - 1
308310 // Not a special case
......@@ -341,139 +343,667 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void {
341343}
342344
343345test "test_udivsi3" {
344 const cases = [][3]u32 {
345 []u32{0x00000000, 0x00000001, 0x00000000},
346 []u32{0x00000000, 0x00000002, 0x00000000},
347 []u32{0x00000000, 0x00000003, 0x00000000},
348 []u32{0x00000000, 0x00000010, 0x00000000},
349 []u32{0x00000000, 0x078644FA, 0x00000000},
350 []u32{0x00000000, 0x0747AE14, 0x00000000},
351 []u32{0x00000000, 0x7FFFFFFF, 0x00000000},
352 []u32{0x00000000, 0x80000000, 0x00000000},
353 []u32{0x00000000, 0xFFFFFFFD, 0x00000000},
354 []u32{0x00000000, 0xFFFFFFFE, 0x00000000},
355 []u32{0x00000000, 0xFFFFFFFF, 0x00000000},
356 []u32{0x00000001, 0x00000001, 0x00000001},
357 []u32{0x00000001, 0x00000002, 0x00000000},
358 []u32{0x00000001, 0x00000003, 0x00000000},
359 []u32{0x00000001, 0x00000010, 0x00000000},
360 []u32{0x00000001, 0x078644FA, 0x00000000},
361 []u32{0x00000001, 0x0747AE14, 0x00000000},
362 []u32{0x00000001, 0x7FFFFFFF, 0x00000000},
363 []u32{0x00000001, 0x80000000, 0x00000000},
364 []u32{0x00000001, 0xFFFFFFFD, 0x00000000},
365 []u32{0x00000001, 0xFFFFFFFE, 0x00000000},
366 []u32{0x00000001, 0xFFFFFFFF, 0x00000000},
367 []u32{0x00000002, 0x00000001, 0x00000002},
368 []u32{0x00000002, 0x00000002, 0x00000001},
369 []u32{0x00000002, 0x00000003, 0x00000000},
370 []u32{0x00000002, 0x00000010, 0x00000000},
371 []u32{0x00000002, 0x078644FA, 0x00000000},
372 []u32{0x00000002, 0x0747AE14, 0x00000000},
373 []u32{0x00000002, 0x7FFFFFFF, 0x00000000},
374 []u32{0x00000002, 0x80000000, 0x00000000},
375 []u32{0x00000002, 0xFFFFFFFD, 0x00000000},
376 []u32{0x00000002, 0xFFFFFFFE, 0x00000000},
377 []u32{0x00000002, 0xFFFFFFFF, 0x00000000},
378 []u32{0x00000003, 0x00000001, 0x00000003},
379 []u32{0x00000003, 0x00000002, 0x00000001},
380 []u32{0x00000003, 0x00000003, 0x00000001},
381 []u32{0x00000003, 0x00000010, 0x00000000},
382 []u32{0x00000003, 0x078644FA, 0x00000000},
383 []u32{0x00000003, 0x0747AE14, 0x00000000},
384 []u32{0x00000003, 0x7FFFFFFF, 0x00000000},
385 []u32{0x00000003, 0x80000000, 0x00000000},
386 []u32{0x00000003, 0xFFFFFFFD, 0x00000000},
387 []u32{0x00000003, 0xFFFFFFFE, 0x00000000},
388 []u32{0x00000003, 0xFFFFFFFF, 0x00000000},
389 []u32{0x00000010, 0x00000001, 0x00000010},
390 []u32{0x00000010, 0x00000002, 0x00000008},
391 []u32{0x00000010, 0x00000003, 0x00000005},
392 []u32{0x00000010, 0x00000010, 0x00000001},
393 []u32{0x00000010, 0x078644FA, 0x00000000},
394 []u32{0x00000010, 0x0747AE14, 0x00000000},
395 []u32{0x00000010, 0x7FFFFFFF, 0x00000000},
396 []u32{0x00000010, 0x80000000, 0x00000000},
397 []u32{0x00000010, 0xFFFFFFFD, 0x00000000},
398 []u32{0x00000010, 0xFFFFFFFE, 0x00000000},
399 []u32{0x00000010, 0xFFFFFFFF, 0x00000000},
400 []u32{0x078644FA, 0x00000001, 0x078644FA},
401 []u32{0x078644FA, 0x00000002, 0x03C3227D},
402 []u32{0x078644FA, 0x00000003, 0x028216FE},
403 []u32{0x078644FA, 0x00000010, 0x0078644F},
404 []u32{0x078644FA, 0x078644FA, 0x00000001},
405 []u32{0x078644FA, 0x0747AE14, 0x00000001},
406 []u32{0x078644FA, 0x7FFFFFFF, 0x00000000},
407 []u32{0x078644FA, 0x80000000, 0x00000000},
408 []u32{0x078644FA, 0xFFFFFFFD, 0x00000000},
409 []u32{0x078644FA, 0xFFFFFFFE, 0x00000000},
410 []u32{0x078644FA, 0xFFFFFFFF, 0x00000000},
411 []u32{0x0747AE14, 0x00000001, 0x0747AE14},
412 []u32{0x0747AE14, 0x00000002, 0x03A3D70A},
413 []u32{0x0747AE14, 0x00000003, 0x026D3A06},
414 []u32{0x0747AE14, 0x00000010, 0x00747AE1},
415 []u32{0x0747AE14, 0x078644FA, 0x00000000},
416 []u32{0x0747AE14, 0x0747AE14, 0x00000001},
417 []u32{0x0747AE14, 0x7FFFFFFF, 0x00000000},
418 []u32{0x0747AE14, 0x80000000, 0x00000000},
419 []u32{0x0747AE14, 0xFFFFFFFD, 0x00000000},
420 []u32{0x0747AE14, 0xFFFFFFFE, 0x00000000},
421 []u32{0x0747AE14, 0xFFFFFFFF, 0x00000000},
422 []u32{0x7FFFFFFF, 0x00000001, 0x7FFFFFFF},
423 []u32{0x7FFFFFFF, 0x00000002, 0x3FFFFFFF},
424 []u32{0x7FFFFFFF, 0x00000003, 0x2AAAAAAA},
425 []u32{0x7FFFFFFF, 0x00000010, 0x07FFFFFF},
426 []u32{0x7FFFFFFF, 0x078644FA, 0x00000011},
427 []u32{0x7FFFFFFF, 0x0747AE14, 0x00000011},
428 []u32{0x7FFFFFFF, 0x7FFFFFFF, 0x00000001},
429 []u32{0x7FFFFFFF, 0x80000000, 0x00000000},
430 []u32{0x7FFFFFFF, 0xFFFFFFFD, 0x00000000},
431 []u32{0x7FFFFFFF, 0xFFFFFFFE, 0x00000000},
432 []u32{0x7FFFFFFF, 0xFFFFFFFF, 0x00000000},
433 []u32{0x80000000, 0x00000001, 0x80000000},
434 []u32{0x80000000, 0x00000002, 0x40000000},
435 []u32{0x80000000, 0x00000003, 0x2AAAAAAA},
436 []u32{0x80000000, 0x00000010, 0x08000000},
437 []u32{0x80000000, 0x078644FA, 0x00000011},
438 []u32{0x80000000, 0x0747AE14, 0x00000011},
439 []u32{0x80000000, 0x7FFFFFFF, 0x00000001},
440 []u32{0x80000000, 0x80000000, 0x00000001},
441 []u32{0x80000000, 0xFFFFFFFD, 0x00000000},
442 []u32{0x80000000, 0xFFFFFFFE, 0x00000000},
443 []u32{0x80000000, 0xFFFFFFFF, 0x00000000},
444 []u32{0xFFFFFFFD, 0x00000001, 0xFFFFFFFD},
445 []u32{0xFFFFFFFD, 0x00000002, 0x7FFFFFFE},
446 []u32{0xFFFFFFFD, 0x00000003, 0x55555554},
447 []u32{0xFFFFFFFD, 0x00000010, 0x0FFFFFFF},
448 []u32{0xFFFFFFFD, 0x078644FA, 0x00000022},
449 []u32{0xFFFFFFFD, 0x0747AE14, 0x00000023},
450 []u32{0xFFFFFFFD, 0x7FFFFFFF, 0x00000001},
451 []u32{0xFFFFFFFD, 0x80000000, 0x00000001},
452 []u32{0xFFFFFFFD, 0xFFFFFFFD, 0x00000001},
453 []u32{0xFFFFFFFD, 0xFFFFFFFE, 0x00000000},
454 []u32{0xFFFFFFFD, 0xFFFFFFFF, 0x00000000},
455 []u32{0xFFFFFFFE, 0x00000001, 0xFFFFFFFE},
456 []u32{0xFFFFFFFE, 0x00000002, 0x7FFFFFFF},
457 []u32{0xFFFFFFFE, 0x00000003, 0x55555554},
458 []u32{0xFFFFFFFE, 0x00000010, 0x0FFFFFFF},
459 []u32{0xFFFFFFFE, 0x078644FA, 0x00000022},
460 []u32{0xFFFFFFFE, 0x0747AE14, 0x00000023},
461 []u32{0xFFFFFFFE, 0x7FFFFFFF, 0x00000002},
462 []u32{0xFFFFFFFE, 0x80000000, 0x00000001},
463 []u32{0xFFFFFFFE, 0xFFFFFFFD, 0x00000001},
464 []u32{0xFFFFFFFE, 0xFFFFFFFE, 0x00000001},
465 []u32{0xFFFFFFFE, 0xFFFFFFFF, 0x00000000},
466 []u32{0xFFFFFFFF, 0x00000001, 0xFFFFFFFF},
467 []u32{0xFFFFFFFF, 0x00000002, 0x7FFFFFFF},
468 []u32{0xFFFFFFFF, 0x00000003, 0x55555555},
469 []u32{0xFFFFFFFF, 0x00000010, 0x0FFFFFFF},
470 []u32{0xFFFFFFFF, 0x078644FA, 0x00000022},
471 []u32{0xFFFFFFFF, 0x0747AE14, 0x00000023},
472 []u32{0xFFFFFFFF, 0x7FFFFFFF, 0x00000002},
473 []u32{0xFFFFFFFF, 0x80000000, 0x00000001},
474 []u32{0xFFFFFFFF, 0xFFFFFFFD, 0x00000001},
475 []u32{0xFFFFFFFF, 0xFFFFFFFE, 0x00000001},
476 []u32{0xFFFFFFFF, 0xFFFFFFFF, 0x00000001},
346 const cases = [][3]u32{
347 []u32{
348 0x00000000,
349 0x00000001,
350 0x00000000,
351 },
352 []u32{
353 0x00000000,
354 0x00000002,
355 0x00000000,
356 },
357 []u32{
358 0x00000000,
359 0x00000003,
360 0x00000000,
361 },
362 []u32{
363 0x00000000,
364 0x00000010,
365 0x00000000,
366 },
367 []u32{
368 0x00000000,
369 0x078644FA,
370 0x00000000,
371 },
372 []u32{
373 0x00000000,
374 0x0747AE14,
375 0x00000000,
376 },
377 []u32{
378 0x00000000,
379 0x7FFFFFFF,
380 0x00000000,
381 },
382 []u32{
383 0x00000000,
384 0x80000000,
385 0x00000000,
386 },
387 []u32{
388 0x00000000,
389 0xFFFFFFFD,
390 0x00000000,
391 },
392 []u32{
393 0x00000000,
394 0xFFFFFFFE,
395 0x00000000,
396 },
397 []u32{
398 0x00000000,
399 0xFFFFFFFF,
400 0x00000000,
401 },
402 []u32{
403 0x00000001,
404 0x00000001,
405 0x00000001,
406 },
407 []u32{
408 0x00000001,
409 0x00000002,
410 0x00000000,
411 },
412 []u32{
413 0x00000001,
414 0x00000003,
415 0x00000000,
416 },
417 []u32{
418 0x00000001,
419 0x00000010,
420 0x00000000,
421 },
422 []u32{
423 0x00000001,
424 0x078644FA,
425 0x00000000,
426 },
427 []u32{
428 0x00000001,
429 0x0747AE14,
430 0x00000000,
431 },
432 []u32{
433 0x00000001,
434 0x7FFFFFFF,
435 0x00000000,
436 },
437 []u32{
438 0x00000001,
439 0x80000000,
440 0x00000000,
441 },
442 []u32{
443 0x00000001,
444 0xFFFFFFFD,
445 0x00000000,
446 },
447 []u32{
448 0x00000001,
449 0xFFFFFFFE,
450 0x00000000,
451 },
452 []u32{
453 0x00000001,
454 0xFFFFFFFF,
455 0x00000000,
456 },
457 []u32{
458 0x00000002,
459 0x00000001,
460 0x00000002,
461 },
462 []u32{
463 0x00000002,
464 0x00000002,
465 0x00000001,
466 },
467 []u32{
468 0x00000002,
469 0x00000003,
470 0x00000000,
471 },
472 []u32{
473 0x00000002,
474 0x00000010,
475 0x00000000,
476 },
477 []u32{
478 0x00000002,
479 0x078644FA,
480 0x00000000,
481 },
482 []u32{
483 0x00000002,
484 0x0747AE14,
485 0x00000000,
486 },
487 []u32{
488 0x00000002,
489 0x7FFFFFFF,
490 0x00000000,
491 },
492 []u32{
493 0x00000002,
494 0x80000000,
495 0x00000000,
496 },
497 []u32{
498 0x00000002,
499 0xFFFFFFFD,
500 0x00000000,
501 },
502 []u32{
503 0x00000002,
504 0xFFFFFFFE,
505 0x00000000,
506 },
507 []u32{
508 0x00000002,
509 0xFFFFFFFF,
510 0x00000000,
511 },
512 []u32{
513 0x00000003,
514 0x00000001,
515 0x00000003,
516 },
517 []u32{
518 0x00000003,
519 0x00000002,
520 0x00000001,
521 },
522 []u32{
523 0x00000003,
524 0x00000003,
525 0x00000001,
526 },
527 []u32{
528 0x00000003,
529 0x00000010,
530 0x00000000,
531 },
532 []u32{
533 0x00000003,
534 0x078644FA,
535 0x00000000,
536 },
537 []u32{
538 0x00000003,
539 0x0747AE14,
540 0x00000000,
541 },
542 []u32{
543 0x00000003,
544 0x7FFFFFFF,
545 0x00000000,
546 },
547 []u32{
548 0x00000003,
549 0x80000000,
550 0x00000000,
551 },
552 []u32{
553 0x00000003,
554 0xFFFFFFFD,
555 0x00000000,
556 },
557 []u32{
558 0x00000003,
559 0xFFFFFFFE,
560 0x00000000,
561 },
562 []u32{
563 0x00000003,
564 0xFFFFFFFF,
565 0x00000000,
566 },
567 []u32{
568 0x00000010,
569 0x00000001,
570 0x00000010,
571 },
572 []u32{
573 0x00000010,
574 0x00000002,
575 0x00000008,
576 },
577 []u32{
578 0x00000010,
579 0x00000003,
580 0x00000005,
581 },
582 []u32{
583 0x00000010,
584 0x00000010,
585 0x00000001,
586 },
587 []u32{
588 0x00000010,
589 0x078644FA,
590 0x00000000,
591 },
592 []u32{
593 0x00000010,
594 0x0747AE14,
595 0x00000000,
596 },
597 []u32{
598 0x00000010,
599 0x7FFFFFFF,
600 0x00000000,
601 },
602 []u32{
603 0x00000010,
604 0x80000000,
605 0x00000000,
606 },
607 []u32{
608 0x00000010,
609 0xFFFFFFFD,
610 0x00000000,
611 },
612 []u32{
613 0x00000010,
614 0xFFFFFFFE,
615 0x00000000,
616 },
617 []u32{
618 0x00000010,
619 0xFFFFFFFF,
620 0x00000000,
621 },
622 []u32{
623 0x078644FA,
624 0x00000001,
625 0x078644FA,
626 },
627 []u32{
628 0x078644FA,
629 0x00000002,
630 0x03C3227D,
631 },
632 []u32{
633 0x078644FA,
634 0x00000003,
635 0x028216FE,
636 },
637 []u32{
638 0x078644FA,
639 0x00000010,
640 0x0078644F,
641 },
642 []u32{
643 0x078644FA,
644 0x078644FA,
645 0x00000001,
646 },
647 []u32{
648 0x078644FA,
649 0x0747AE14,
650 0x00000001,
651 },
652 []u32{
653 0x078644FA,
654 0x7FFFFFFF,
655 0x00000000,
656 },
657 []u32{
658 0x078644FA,
659 0x80000000,
660 0x00000000,
661 },
662 []u32{
663 0x078644FA,
664 0xFFFFFFFD,
665 0x00000000,
666 },
667 []u32{
668 0x078644FA,
669 0xFFFFFFFE,
670 0x00000000,
671 },
672 []u32{
673 0x078644FA,
674 0xFFFFFFFF,
675 0x00000000,
676 },
677 []u32{
678 0x0747AE14,
679 0x00000001,
680 0x0747AE14,
681 },
682 []u32{
683 0x0747AE14,
684 0x00000002,
685 0x03A3D70A,
686 },
687 []u32{
688 0x0747AE14,
689 0x00000003,
690 0x026D3A06,
691 },
692 []u32{
693 0x0747AE14,
694 0x00000010,
695 0x00747AE1,
696 },
697 []u32{
698 0x0747AE14,
699 0x078644FA,
700 0x00000000,
701 },
702 []u32{
703 0x0747AE14,
704 0x0747AE14,
705 0x00000001,
706 },
707 []u32{
708 0x0747AE14,
709 0x7FFFFFFF,
710 0x00000000,
711 },
712 []u32{
713 0x0747AE14,
714 0x80000000,
715 0x00000000,
716 },
717 []u32{
718 0x0747AE14,
719 0xFFFFFFFD,
720 0x00000000,
721 },
722 []u32{
723 0x0747AE14,
724 0xFFFFFFFE,
725 0x00000000,
726 },
727 []u32{
728 0x0747AE14,
729 0xFFFFFFFF,
730 0x00000000,
731 },
732 []u32{
733 0x7FFFFFFF,
734 0x00000001,
735 0x7FFFFFFF,
736 },
737 []u32{
738 0x7FFFFFFF,
739 0x00000002,
740 0x3FFFFFFF,
741 },
742 []u32{
743 0x7FFFFFFF,
744 0x00000003,
745 0x2AAAAAAA,
746 },
747 []u32{
748 0x7FFFFFFF,
749 0x00000010,
750 0x07FFFFFF,
751 },
752 []u32{
753 0x7FFFFFFF,
754 0x078644FA,
755 0x00000011,
756 },
757 []u32{
758 0x7FFFFFFF,
759 0x0747AE14,
760 0x00000011,
761 },
762 []u32{
763 0x7FFFFFFF,
764 0x7FFFFFFF,
765 0x00000001,
766 },
767 []u32{
768 0x7FFFFFFF,
769 0x80000000,
770 0x00000000,
771 },
772 []u32{
773 0x7FFFFFFF,
774 0xFFFFFFFD,
775 0x00000000,
776 },
777 []u32{
778 0x7FFFFFFF,
779 0xFFFFFFFE,
780 0x00000000,
781 },
782 []u32{
783 0x7FFFFFFF,
784 0xFFFFFFFF,
785 0x00000000,
786 },
787 []u32{
788 0x80000000,
789 0x00000001,
790 0x80000000,
791 },
792 []u32{
793 0x80000000,
794 0x00000002,
795 0x40000000,
796 },
797 []u32{
798 0x80000000,
799 0x00000003,
800 0x2AAAAAAA,
801 },
802 []u32{
803 0x80000000,
804 0x00000010,
805 0x08000000,
806 },
807 []u32{
808 0x80000000,
809 0x078644FA,
810 0x00000011,
811 },
812 []u32{
813 0x80000000,
814 0x0747AE14,
815 0x00000011,
816 },
817 []u32{
818 0x80000000,
819 0x7FFFFFFF,
820 0x00000001,
821 },
822 []u32{
823 0x80000000,
824 0x80000000,
825 0x00000001,
826 },
827 []u32{
828 0x80000000,
829 0xFFFFFFFD,
830 0x00000000,
831 },
832 []u32{
833 0x80000000,
834 0xFFFFFFFE,
835 0x00000000,
836 },
837 []u32{
838 0x80000000,
839 0xFFFFFFFF,
840 0x00000000,
841 },
842 []u32{
843 0xFFFFFFFD,
844 0x00000001,
845 0xFFFFFFFD,
846 },
847 []u32{
848 0xFFFFFFFD,
849 0x00000002,
850 0x7FFFFFFE,
851 },
852 []u32{
853 0xFFFFFFFD,
854 0x00000003,
855 0x55555554,
856 },
857 []u32{
858 0xFFFFFFFD,
859 0x00000010,
860 0x0FFFFFFF,
861 },
862 []u32{
863 0xFFFFFFFD,
864 0x078644FA,
865 0x00000022,
866 },
867 []u32{
868 0xFFFFFFFD,
869 0x0747AE14,
870 0x00000023,
871 },
872 []u32{
873 0xFFFFFFFD,
874 0x7FFFFFFF,
875 0x00000001,
876 },
877 []u32{
878 0xFFFFFFFD,
879 0x80000000,
880 0x00000001,
881 },
882 []u32{
883 0xFFFFFFFD,
884 0xFFFFFFFD,
885 0x00000001,
886 },
887 []u32{
888 0xFFFFFFFD,
889 0xFFFFFFFE,
890 0x00000000,
891 },
892 []u32{
893 0xFFFFFFFD,
894 0xFFFFFFFF,
895 0x00000000,
896 },
897 []u32{
898 0xFFFFFFFE,
899 0x00000001,
900 0xFFFFFFFE,
901 },
902 []u32{
903 0xFFFFFFFE,
904 0x00000002,
905 0x7FFFFFFF,
906 },
907 []u32{
908 0xFFFFFFFE,
909 0x00000003,
910 0x55555554,
911 },
912 []u32{
913 0xFFFFFFFE,
914 0x00000010,
915 0x0FFFFFFF,
916 },
917 []u32{
918 0xFFFFFFFE,
919 0x078644FA,
920 0x00000022,
921 },
922 []u32{
923 0xFFFFFFFE,
924 0x0747AE14,
925 0x00000023,
926 },
927 []u32{
928 0xFFFFFFFE,
929 0x7FFFFFFF,
930 0x00000002,
931 },
932 []u32{
933 0xFFFFFFFE,
934 0x80000000,
935 0x00000001,
936 },
937 []u32{
938 0xFFFFFFFE,
939 0xFFFFFFFD,
940 0x00000001,
941 },
942 []u32{
943 0xFFFFFFFE,
944 0xFFFFFFFE,
945 0x00000001,
946 },
947 []u32{
948 0xFFFFFFFE,
949 0xFFFFFFFF,
950 0x00000000,
951 },
952 []u32{
953 0xFFFFFFFF,
954 0x00000001,
955 0xFFFFFFFF,
956 },
957 []u32{
958 0xFFFFFFFF,
959 0x00000002,
960 0x7FFFFFFF,
961 },
962 []u32{
963 0xFFFFFFFF,
964 0x00000003,
965 0x55555555,
966 },
967 []u32{
968 0xFFFFFFFF,
969 0x00000010,
970 0x0FFFFFFF,
971 },
972 []u32{
973 0xFFFFFFFF,
974 0x078644FA,
975 0x00000022,
976 },
977 []u32{
978 0xFFFFFFFF,
979 0x0747AE14,
980 0x00000023,
981 },
982 []u32{
983 0xFFFFFFFF,
984 0x7FFFFFFF,
985 0x00000002,
986 },
987 []u32{
988 0xFFFFFFFF,
989 0x80000000,
990 0x00000001,
991 },
992 []u32{
993 0xFFFFFFFF,
994 0xFFFFFFFD,
995 0x00000001,
996 },
997 []u32{
998 0xFFFFFFFF,
999 0xFFFFFFFE,
1000 0x00000001,
1001 },
1002 []u32{
1003 0xFFFFFFFF,
1004 0xFFFFFFFF,
1005 0x00000001,
1006 },
4771007 };
4781008
4791009 for (cases) |case| {
std/special/compiler_rt/udivmod.zig+23-20
......@@ -1,7 +1,10 @@
11const builtin = @import("builtin");
22const is_test = builtin.is_test;
33
4const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 };
4const low = switch (builtin.endian) {
5 builtin.Endian.Big => 1,
6 builtin.Endian.Little => 0,
7};
58const high = 1 - low;
69
710pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) DoubleInt {
......@@ -11,8 +14,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
1114 const SignedDoubleInt = @IntType(true, DoubleInt.bit_count);
1215 const Log2SingleInt = @import("std").math.Log2Int(SingleInt);
1316
14 const n = *@ptrCast(&const [2]SingleInt, &a); // TODO issue #421
15 const d = *@ptrCast(&const [2]SingleInt, &b); // TODO issue #421
17 const n = @ptrCast(&const [2]SingleInt, &a).*; // TODO issue #421
18 const d = @ptrCast(&const [2]SingleInt, &b).*; // TODO issue #421
1619 var q: [2]SingleInt = undefined;
1720 var r: [2]SingleInt = undefined;
1821 var sr: c_uint = undefined;
......@@ -23,7 +26,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
2326 // ---
2427 // 0 X
2528 if (maybe_rem) |rem| {
26 *rem = n[low] % d[low];
29 rem.* = n[low] % d[low];
2730 }
2831 return n[low] / d[low];
2932 }
......@@ -31,7 +34,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
3134 // ---
3235 // K X
3336 if (maybe_rem) |rem| {
34 *rem = n[low];
37 rem.* = n[low];
3538 }
3639 return 0;
3740 }
......@@ -42,7 +45,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
4245 // ---
4346 // 0 0
4447 if (maybe_rem) |rem| {
45 *rem = n[high] % d[low];
48 rem.* = n[high] % d[low];
4649 }
4750 return n[high] / d[low];
4851 }
......@@ -54,7 +57,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
5457 if (maybe_rem) |rem| {
5558 r[high] = n[high] % d[high];
5659 r[low] = 0;
57 *rem = *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]); // TODO issue #421
60 rem.* = @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
5861 }
5962 return n[high] / d[high];
6063 }
......@@ -66,7 +69,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
6669 if (maybe_rem) |rem| {
6770 r[low] = n[low];
6871 r[high] = n[high] & (d[high] - 1);
69 *rem = *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]); // TODO issue #421
72 rem.* = @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
7073 }
7174 return n[high] >> Log2SingleInt(@ctz(d[high]));
7275 }
......@@ -77,7 +80,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
7780 // 0 <= sr <= SingleInt.bit_count - 2 or sr large
7881 if (sr > SingleInt.bit_count - 2) {
7982 if (maybe_rem) |rem| {
80 *rem = a;
83 rem.* = a;
8184 }
8285 return 0;
8386 }
......@@ -98,7 +101,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
98101 if ((d[low] & (d[low] - 1)) == 0) {
99102 // d is a power of 2
100103 if (maybe_rem) |rem| {
101 *rem = n[low] & (d[low] - 1);
104 rem.* = n[low] & (d[low] - 1);
102105 }
103106 if (d[low] == 1) {
104107 return a;
......@@ -106,7 +109,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
106109 sr = @ctz(d[low]);
107110 q[high] = n[high] >> Log2SingleInt(sr);
108111 q[low] = (n[high] << Log2SingleInt(SingleInt.bit_count - sr)) | (n[low] >> Log2SingleInt(sr));
109 return *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0]); // TODO issue #421
112 return @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0]).*; // TODO issue #421
110113 }
111114 // K X
112115 // ---
......@@ -141,7 +144,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
141144 // 0 <= sr <= SingleInt.bit_count - 1 or sr large
142145 if (sr > SingleInt.bit_count - 1) {
143146 if (maybe_rem) |rem| {
144 *rem = a;
147 rem.* = a;
145148 }
146149 return 0;
147150 }
......@@ -170,25 +173,25 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
170173 var r_all: DoubleInt = undefined;
171174 while (sr > 0) : (sr -= 1) {
172175 // r:q = ((r:q) << 1) | carry
173 r[high] = (r[high] << 1) | (r[low] >> (SingleInt.bit_count - 1));
174 r[low] = (r[low] << 1) | (q[high] >> (SingleInt.bit_count - 1));
175 q[high] = (q[high] << 1) | (q[low] >> (SingleInt.bit_count - 1));
176 q[low] = (q[low] << 1) | carry;
176 r[high] = (r[high] << 1) | (r[low] >> (SingleInt.bit_count - 1));
177 r[low] = (r[low] << 1) | (q[high] >> (SingleInt.bit_count - 1));
178 q[high] = (q[high] << 1) | (q[low] >> (SingleInt.bit_count - 1));
179 q[low] = (q[low] << 1) | carry;
177180 // carry = 0;
178181 // if (r.all >= b)
179182 // {
180183 // r.all -= b;
181184 // carry = 1;
182185 // }
183 r_all = *@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]); // TODO issue #421
186 r_all = @ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
184187 const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1);
185188 carry = u32(s & 1);
186189 r_all -= b & @bitCast(DoubleInt, s);
187 r = *@ptrCast(&[2]SingleInt, &r_all); // TODO issue #421
190 r = @ptrCast(&[2]SingleInt, &r_all).*; // TODO issue #421
188191 }
189 const q_all = ((*@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0])) << 1) | carry; // TODO issue #421
192 const q_all = ((@ptrCast(&align(@alignOf(SingleInt)) DoubleInt, &q[0]).*) << 1) | carry; // TODO issue #421
190193 if (maybe_rem) |rem| {
191 *rem = r_all;
194 rem.* = r_all;
192195 }
193196 return q_all;
194197}
std/special/compiler_rt/udivmodti4.zig+1-1
......@@ -9,7 +9,7 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) u128 {
99
1010pub extern fn __udivmodti4_windows_x86_64(a: &const u128, b: &const u128, maybe_rem: ?&u128) void {
1111 @setRuntimeSafety(builtin.is_test);
12 compiler_rt.setXmm0(u128, udivmod(u128, *a, *b, maybe_rem));
12 compiler_rt.setXmm0(u128, udivmod(u128, a.*, b.*, maybe_rem));
1313}
1414
1515test "import udivmodti4" {
std/special/compiler_rt/umodti3.zig+1-1
......@@ -11,5 +11,5 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {
1111
1212pub extern fn __umodti3_windows_x86_64(a: &const u128, b: &const u128) void {
1313 @setRuntimeSafety(builtin.is_test);
14 compiler_rt.setXmm0(u128, __umodti3(*a, *b));
14 compiler_rt.setXmm0(u128, __umodti3(a.*, b.*));
1515}
std/zig/ast.zig+123-105
......@@ -40,7 +40,7 @@ pub const Tree = struct {
4040 };
4141
4242 pub fn tokenLocationPtr(self: &Tree, start_index: usize, token: &const Token) Location {
43 var loc = Location {
43 var loc = Location{
4444 .line = 0,
4545 .column = 0,
4646 .line_start = start_index,
......@@ -67,6 +67,28 @@ pub const Tree = struct {
6767 pub fn tokenLocation(self: &Tree, start_index: usize, token_index: TokenIndex) Location {
6868 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));
6969 }
70
71 pub fn dump(self: &Tree) void {
72 self.root_node.base.dump(0);
73 }
74
75 /// Skips over comments
76 pub fn prevToken(self: &Tree, token_index: TokenIndex) TokenIndex {
77 var index = token_index - 1;
78 while (self.tokens.at(index).id == Token.Id.LineComment) {
79 index -= 1;
80 }
81 return index;
82 }
83
84 /// Skips over comments
85 pub fn nextToken(self: &Tree, token_index: TokenIndex) TokenIndex {
86 var index = token_index + 1;
87 while (self.tokens.at(index).id == Token.Id.LineComment) {
88 index += 1;
89 }
90 return index;
91 }
7092};
7193
7294pub const Error = union(enum) {
......@@ -76,6 +98,7 @@ pub const Error = union(enum) {
7698 UnattachedDocComment: UnattachedDocComment,
7799 ExpectedEqOrSemi: ExpectedEqOrSemi,
78100 ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,
101 ExpectedColonOrRParen: ExpectedColonOrRParen,
79102 ExpectedLabelable: ExpectedLabelable,
80103 ExpectedInlinable: ExpectedInlinable,
81104 ExpectedAsmOutputReturnOrType: ExpectedAsmOutputReturnOrType,
......@@ -90,14 +113,15 @@ pub const Error = union(enum) {
90113 ExpectedCommaOrEnd: ExpectedCommaOrEnd,
91114
92115 pub fn render(self: &Error, tokens: &Tree.TokenList, stream: var) !void {
93 switch (*self) {
94 // TODO https://github.com/zig-lang/zig/issues/683
116 switch (self.*) {
117 // TODO https://github.com/ziglang/zig/issues/683
95118 @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
96119 @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
97120 @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
98121 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
99122 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
100123 @TagType(Error).ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
124 @TagType(Error).ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
101125 @TagType(Error).ExpectedLabelable => |*x| return x.render(tokens, stream),
102126 @TagType(Error).ExpectedInlinable => |*x| return x.render(tokens, stream),
103127 @TagType(Error).ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
......@@ -114,14 +138,15 @@ pub const Error = union(enum) {
114138 }
115139
116140 pub fn loc(self: &Error) TokenIndex {
117 switch (*self) {
118 // TODO https://github.com/zig-lang/zig/issues/683
141 switch (self.*) {
142 // TODO https://github.com/ziglang/zig/issues/683
119143 @TagType(Error).InvalidToken => |x| return x.token,
120144 @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
121145 @TagType(Error).ExpectedAggregateKw => |x| return x.token,
122146 @TagType(Error).UnattachedDocComment => |x| return x.token,
123147 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,
124148 @TagType(Error).ExpectedSemiOrLBrace => |x| return x.token,
149 @TagType(Error).ExpectedColonOrRParen => |x| return x.token,
125150 @TagType(Error).ExpectedLabelable => |x| return x.token,
126151 @TagType(Error).ExpectedInlinable => |x| return x.token,
127152 @TagType(Error).ExpectedAsmOutputReturnOrType => |x| return x.token,
......@@ -139,15 +164,13 @@ pub const Error = union(enum) {
139164
140165 pub const InvalidToken = SingleTokenError("Invalid token {}");
141166 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");
142 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++
143 @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++
144 @tagName(Token.Id.Keyword_enum) ++ ", found {}");
167 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
145168 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
146169 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
170 pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found {}");
147171 pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}");
148172 pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}");
149 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++
150 @tagName(Token.Id.Identifier) ++ ", found {}");
173 pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}");
151174 pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found {}");
152175 pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found {}");
153176
......@@ -160,8 +183,7 @@ pub const Error = union(enum) {
160183 node: &Node,
161184
162185 pub fn render(self: &ExpectedCall, tokens: &Tree.TokenList, stream: var) !void {
163 return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ ", found {}",
164 @tagName(self.node.id));
186 return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ ", found {}", @tagName(self.node.id));
165187 }
166188 };
167189
......@@ -169,8 +191,7 @@ pub const Error = union(enum) {
169191 node: &Node,
170192
171193 pub fn render(self: &ExpectedCallOrFnProto, tokens: &Tree.TokenList, stream: var) !void {
172 return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ " or " ++
173 @tagName(Node.Id.FnProto) ++ ", found {}", @tagName(self.node.id));
194 return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ " or " ++ @tagName(Node.Id.FnProto) ++ ", found {}", @tagName(self.node.id));
174195 }
175196 };
176197
......@@ -273,7 +294,6 @@ pub const Node = struct {
273294 Block,
274295
275296 // Misc
276 LineComment,
277297 DocComment,
278298 SwitchCase,
279299 SwitchElse,
......@@ -360,7 +380,6 @@ pub const Node = struct {
360380 Id.SwitchElse,
361381 Id.FieldInitializer,
362382 Id.DocComment,
363 Id.LineComment,
364383 Id.TestDecl => return false,
365384 Id.While => {
366385 const while_node = @fieldParentPtr(While, "base", n);
......@@ -415,6 +434,20 @@ pub const Node = struct {
415434 }
416435 }
417436
437 pub fn dump(self: &Node, indent: usize) void {
438 {
439 var i: usize = 0;
440 while (i < indent) : (i += 1) {
441 std.debug.warn(" ");
442 }
443 }
444 std.debug.warn("{}\n", @tagName(self.id));
445
446 var child_i: usize = 0;
447 while (self.iterate(child_i)) |child| : (child_i += 1) {
448 child.dump(indent + 2);
449 }
450 }
418451
419452 pub const Root = struct {
420453 base: Node,
......@@ -426,17 +459,17 @@ pub const Node = struct {
426459
427460 pub fn iterate(self: &Root, index: usize) ?&Node {
428461 if (index < self.decls.len) {
429 return self.decls.items[self.decls.len - index - 1];
462 return self.decls.at(index).*;
430463 }
431464 return null;
432465 }
433466
434467 pub fn firstToken(self: &Root) TokenIndex {
435 return if (self.decls.len == 0) self.eof_token else (*self.decls.at(0)).firstToken();
468 return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken();
436469 }
437470
438471 pub fn lastToken(self: &Root) TokenIndex {
439 return if (self.decls.len == 0) self.eof_token else (*self.decls.at(self.decls.len - 1)).lastToken();
472 return if (self.decls.len == 0) self.eof_token else (self.decls.at(self.decls.len - 1).*).lastToken();
440473 }
441474 };
442475
......@@ -493,6 +526,7 @@ pub const Node = struct {
493526 base: Node,
494527 doc_comments: ?&DocComment,
495528 visib_token: ?TokenIndex,
529 use_token: TokenIndex,
496530 expr: &Node,
497531 semicolon_token: TokenIndex,
498532
......@@ -507,7 +541,7 @@ pub const Node = struct {
507541
508542 pub fn firstToken(self: &Use) TokenIndex {
509543 if (self.visib_token) |visib_token| return visib_token;
510 return self.expr.firstToken();
544 return self.use_token;
511545 }
512546
513547 pub fn lastToken(self: &Use) TokenIndex {
......@@ -526,7 +560,7 @@ pub const Node = struct {
526560 pub fn iterate(self: &ErrorSetDecl, index: usize) ?&Node {
527561 var i = index;
528562
529 if (i < self.decls.len) return *self.decls.at(i);
563 if (i < self.decls.len) return self.decls.at(i).*;
530564 i -= self.decls.len;
531565
532566 return null;
......@@ -543,27 +577,15 @@ pub const Node = struct {
543577
544578 pub const ContainerDecl = struct {
545579 base: Node,
546 ltoken: TokenIndex,
547 layout: Layout,
548 kind: Kind,
580 layout_token: ?TokenIndex,
581 kind_token: TokenIndex,
549582 init_arg_expr: InitArg,
550583 fields_and_decls: DeclList,
584 lbrace_token: TokenIndex,
551585 rbrace_token: TokenIndex,
552586
553587 pub const DeclList = Root.DeclList;
554588
555 const Layout = enum {
556 Auto,
557 Extern,
558 Packed,
559 };
560
561 const Kind = enum {
562 Struct,
563 Enum,
564 Union,
565 };
566
567589 const InitArg = union(enum) {
568590 None,
569591 Enum: ?&Node,
......@@ -579,17 +601,20 @@ pub const Node = struct {
579601 i -= 1;
580602 },
581603 InitArg.None,
582 InitArg.Enum => { }
604 InitArg.Enum => {},
583605 }
584606
585 if (i < self.fields_and_decls.len) return *self.fields_and_decls.at(i);
607 if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i).*;
586608 i -= self.fields_and_decls.len;
587609
588610 return null;
589611 }
590612
591613 pub fn firstToken(self: &ContainerDecl) TokenIndex {
592 return self.ltoken;
614 if (self.layout_token) |layout_token| {
615 return layout_token;
616 }
617 return self.kind_token;
593618 }
594619
595620 pub fn lastToken(self: &ContainerDecl) TokenIndex {
......@@ -790,8 +815,16 @@ pub const Node = struct {
790815 pub fn iterate(self: &FnProto, index: usize) ?&Node {
791816 var i = index;
792817
793 if (self.body_node) |body_node| {
794 if (i < 1) return body_node;
818 if (self.lib_name) |lib_name| {
819 if (i < 1) return lib_name;
820 i -= 1;
821 }
822
823 if (i < self.params.len) return self.params.at(self.params.len - i - 1).*;
824 i -= self.params.len;
825
826 if (self.align_expr) |align_expr| {
827 if (i < 1) return align_expr;
795828 i -= 1;
796829 }
797830
......@@ -807,16 +840,8 @@ pub const Node = struct {
807840 },
808841 }
809842
810 if (self.align_expr) |align_expr| {
811 if (i < 1) return align_expr;
812 i -= 1;
813 }
814
815 if (i < self.params.len) return self.params.items[self.params.len - i - 1];
816 i -= self.params.len;
817
818 if (self.lib_name) |lib_name| {
819 if (i < 1) return lib_name;
843 if (self.body_node) |body_node| {
844 if (i < 1) return body_node;
820845 i -= 1;
821846 }
822847
......@@ -914,7 +939,7 @@ pub const Node = struct {
914939 pub fn iterate(self: &Block, index: usize) ?&Node {
915940 var i = index;
916941
917 if (i < self.statements.len) return self.statements.items[i];
942 if (i < self.statements.len) return self.statements.at(i).*;
918943 i -= self.statements.len;
919944
920945 return null;
......@@ -1099,7 +1124,8 @@ pub const Node = struct {
10991124 base: Node,
11001125 switch_token: TokenIndex,
11011126 expr: &Node,
1102 /// these can be SwitchCase nodes or LineComment nodes
1127
1128 /// these must be SwitchCase nodes
11031129 cases: CaseList,
11041130 rbrace: TokenIndex,
11051131
......@@ -1111,7 +1137,7 @@ pub const Node = struct {
11111137 if (i < 1) return self.expr;
11121138 i -= 1;
11131139
1114 if (i < self.cases.len) return *self.cases.at(i);
1140 if (i < self.cases.len) return self.cases.at(i).*;
11151141 i -= self.cases.len;
11161142
11171143 return null;
......@@ -1129,6 +1155,7 @@ pub const Node = struct {
11291155 pub const SwitchCase = struct {
11301156 base: Node,
11311157 items: ItemList,
1158 arrow_token: TokenIndex,
11321159 payload: ?&Node,
11331160 expr: &Node,
11341161
......@@ -1137,7 +1164,7 @@ pub const Node = struct {
11371164 pub fn iterate(self: &SwitchCase, index: usize) ?&Node {
11381165 var i = index;
11391166
1140 if (i < self.items.len) return *self.items.at(i);
1167 if (i < self.items.len) return self.items.at(i).*;
11411168 i -= self.items.len;
11421169
11431170 if (self.payload) |payload| {
......@@ -1152,7 +1179,7 @@ pub const Node = struct {
11521179 }
11531180
11541181 pub fn firstToken(self: &SwitchCase) TokenIndex {
1155 return (*self.items.at(0)).firstToken();
1182 return (self.items.at(0).*).firstToken();
11561183 }
11571184
11581185 pub fn lastToken(self: &SwitchCase) TokenIndex {
......@@ -1464,14 +1491,14 @@ pub const Node = struct {
14641491 op: Op,
14651492 rhs: &Node,
14661493
1467 const Op = union(enum) {
1494 pub const Op = union(enum) {
14681495 AddrOf: AddrOfInfo,
14691496 ArrayType: &Node,
14701497 Await,
14711498 BitNot,
14721499 BoolNot,
14731500 Cancel,
1474 Deref,
1501 PointerType,
14751502 MaybeType,
14761503 Negation,
14771504 NegationWrap,
......@@ -1481,12 +1508,20 @@ pub const Node = struct {
14811508 UnwrapMaybe,
14821509 };
14831510
1484 const AddrOfInfo = struct {
1485 align_expr: ?&Node,
1486 bit_offset_start_token: ?TokenIndex,
1487 bit_offset_end_token: ?TokenIndex,
1511 pub const AddrOfInfo = struct {
1512 align_info: ?Align,
14881513 const_token: ?TokenIndex,
14891514 volatile_token: ?TokenIndex,
1515
1516 pub const Align = struct {
1517 node: &Node,
1518 bit_range: ?BitRange,
1519
1520 pub const BitRange = struct {
1521 start: &Node,
1522 end: &Node,
1523 };
1524 };
14901525 };
14911526
14921527 pub fn iterate(self: &PrefixOp, index: usize) ?&Node {
......@@ -1513,7 +1548,6 @@ pub const Node = struct {
15131548 Op.BitNot,
15141549 Op.BoolNot,
15151550 Op.Cancel,
1516 Op.Deref,
15171551 Op.MaybeType,
15181552 Op.Negation,
15191553 Op.NegationWrap,
......@@ -1573,6 +1607,7 @@ pub const Node = struct {
15731607 Slice: Slice,
15741608 ArrayInitializer: InitList,
15751609 StructInitializer: InitList,
1610 Deref,
15761611
15771612 pub const InitList = SegmentedList(&Node, 2);
15781613
......@@ -1596,15 +1631,15 @@ pub const Node = struct {
15961631 i -= 1;
15971632
15981633 switch (self.op) {
1599 Op.Call => |call_info| {
1600 if (i < call_info.params.len) return *call_info.params.at(i);
1634 @TagType(Op).Call => |*call_info| {
1635 if (i < call_info.params.len) return call_info.params.at(i).*;
16011636 i -= call_info.params.len;
16021637 },
16031638 Op.ArrayAccess => |index_expr| {
16041639 if (i < 1) return index_expr;
16051640 i -= 1;
16061641 },
1607 Op.Slice => |range| {
1642 @TagType(Op).Slice => |range| {
16081643 if (i < 1) return range.start;
16091644 i -= 1;
16101645
......@@ -1613,12 +1648,12 @@ pub const Node = struct {
16131648 i -= 1;
16141649 }
16151650 },
1616 Op.ArrayInitializer => |exprs| {
1617 if (i < exprs.len) return *exprs.at(i);
1651 Op.ArrayInitializer => |*exprs| {
1652 if (i < exprs.len) return exprs.at(i).*;
16181653 i -= exprs.len;
16191654 },
1620 Op.StructInitializer => |fields| {
1621 if (i < fields.len) return *fields.at(i);
1655 Op.StructInitializer => |*fields| {
1656 if (i < fields.len) return fields.at(i).*;
16221657 i -= fields.len;
16231658 },
16241659 }
......@@ -1811,7 +1846,7 @@ pub const Node = struct {
18111846 pub fn iterate(self: &BuiltinCall, index: usize) ?&Node {
18121847 var i = index;
18131848
1814 if (i < self.params.len) return *self.params.at(i);
1849 if (i < self.params.len) return self.params.at(i).*;
18151850 i -= self.params.len;
18161851
18171852 return null;
......@@ -1854,11 +1889,11 @@ pub const Node = struct {
18541889 }
18551890
18561891 pub fn firstToken(self: &MultilineStringLiteral) TokenIndex {
1857 return *self.lines.at(0);
1892 return self.lines.at(0).*;
18581893 }
18591894
18601895 pub fn lastToken(self: &MultilineStringLiteral) TokenIndex {
1861 return *self.lines.at(self.lines.len - 1);
1896 return self.lines.at(self.lines.len - 1).*;
18621897 }
18631898 };
18641899
......@@ -1949,13 +1984,15 @@ pub const Node = struct {
19491984
19501985 pub const AsmOutput = struct {
19511986 base: Node,
1987 lbracket: TokenIndex,
19521988 symbolic_name: &Node,
19531989 constraint: &Node,
19541990 kind: Kind,
1991 rparen: TokenIndex,
19551992
19561993 const Kind = union(enum) {
19571994 Variable: &Identifier,
1958 Return: &Node
1995 Return: &Node,
19591996 };
19601997
19611998 pub fn iterate(self: &AsmOutput, index: usize) ?&Node {
......@@ -1975,29 +2012,28 @@ pub const Node = struct {
19752012 Kind.Return => |return_type| {
19762013 if (i < 1) return return_type;
19772014 i -= 1;
1978 }
2015 },
19792016 }
19802017
19812018 return null;
19822019 }
19832020
19842021 pub fn firstToken(self: &AsmOutput) TokenIndex {
1985 return self.symbolic_name.firstToken();
2022 return self.lbracket;
19862023 }
19872024
19882025 pub fn lastToken(self: &AsmOutput) TokenIndex {
1989 return switch (self.kind) {
1990 Kind.Variable => |variable_name| variable_name.lastToken(),
1991 Kind.Return => |return_type| return_type.lastToken(),
1992 };
2026 return self.rparen;
19932027 }
19942028 };
19952029
19962030 pub const AsmInput = struct {
19972031 base: Node,
2032 lbracket: TokenIndex,
19982033 symbolic_name: &Node,
19992034 constraint: &Node,
20002035 expr: &Node,
2036 rparen: TokenIndex,
20012037
20022038 pub fn iterate(self: &AsmInput, index: usize) ?&Node {
20032039 var i = index;
......@@ -2015,11 +2051,11 @@ pub const Node = struct {
20152051 }
20162052
20172053 pub fn firstToken(self: &AsmInput) TokenIndex {
2018 return self.symbolic_name.firstToken();
2054 return self.lbracket;
20192055 }
20202056
20212057 pub fn lastToken(self: &AsmInput) TokenIndex {
2022 return self.expr.lastToken();
2058 return self.rparen;
20232059 }
20242060 };
20252061
......@@ -2040,13 +2076,13 @@ pub const Node = struct {
20402076 pub fn iterate(self: &Asm, index: usize) ?&Node {
20412077 var i = index;
20422078
2043 if (i < self.outputs.len) return &(*self.outputs.at(index)).base;
2079 if (i < self.outputs.len) return &(self.outputs.at(index).*).base;
20442080 i -= self.outputs.len;
20452081
2046 if (i < self.inputs.len) return &(*self.inputs.at(index)).base;
2082 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;
20472083 i -= self.inputs.len;
20482084
2049 if (i < self.clobbers.len) return *self.clobbers.at(index);
2085 if (i < self.clobbers.len) return self.clobbers.at(index).*;
20502086 i -= self.clobbers.len;
20512087
20522088 return null;
......@@ -2112,23 +2148,6 @@ pub const Node = struct {
21122148 }
21132149 };
21142150
2115 pub const LineComment = struct {
2116 base: Node,
2117 token: TokenIndex,
2118
2119 pub fn iterate(self: &LineComment, index: usize) ?&Node {
2120 return null;
2121 }
2122
2123 pub fn firstToken(self: &LineComment) TokenIndex {
2124 return self.token;
2125 }
2126
2127 pub fn lastToken(self: &LineComment) TokenIndex {
2128 return self.token;
2129 }
2130 };
2131
21322151 pub const DocComment = struct {
21332152 base: Node,
21342153 lines: LineList,
......@@ -2140,11 +2159,11 @@ pub const Node = struct {
21402159 }
21412160
21422161 pub fn firstToken(self: &DocComment) TokenIndex {
2143 return *self.lines.at(0);
2162 return self.lines.at(0).*;
21442163 }
21452164
21462165 pub fn lastToken(self: &DocComment) TokenIndex {
2147 return *self.lines.at(self.lines.len - 1);
2166 return self.lines.at(self.lines.len - 1).*;
21482167 }
21492168 };
21502169
......@@ -2173,4 +2192,3 @@ pub const Node = struct {
21732192 }
21742193 };
21752194};
2176
std/zig/parse.zig+1350-1622
......@@ -7,9 +7,8 @@ const Token = std.zig.Token;
77const TokenIndex = ast.TokenIndex;
88const Error = ast.Error;
99
10/// Returns an AST tree, allocated with the parser's allocator.
1110/// Result should be freed with tree.deinit() when there are
12/// no more references to any AST nodes of the tree.
11/// no more references to any of the tokens or nodes.
1312pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1413 var tree_arena = std.heap.ArenaAllocator.init(allocator);
1514 errdefer tree_arena.deinit();
......@@ -18,17 +17,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1817 defer stack.deinit();
1918
2019 const arena = &tree_arena.allocator;
21 const root_node = try createNode(arena, ast.Node.Root,
22 ast.Node.Root {
23 .base = undefined,
24 .decls = ast.Node.Root.DeclList.init(arena),
25 .doc_comments = null,
26 // initialized when we get the eof token
27 .eof_token = undefined,
28 }
29 );
20 const root_node = try arena.construct(ast.Node.Root{
21 .base = ast.Node{ .id = ast.Node.Id.Root },
22 .decls = ast.Node.Root.DeclList.init(arena),
23 .doc_comments = null,
24 // initialized when we get the eof token
25 .eof_token = undefined,
26 });
3027
31 var tree = ast.Tree {
28 var tree = ast.Tree{
3229 .source = source,
3330 .root_node = root_node,
3431 .arena_allocator = tree_arena,
......@@ -39,12 +36,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
3936 var tokenizer = Tokenizer.init(tree.source);
4037 while (true) {
4138 const token_ptr = try tree.tokens.addOne();
42 *token_ptr = tokenizer.next();
43 if (token_ptr.id == Token.Id.Eof)
44 break;
39 token_ptr.* = tokenizer.next();
40 if (token_ptr.id == Token.Id.Eof) break;
4541 }
4642 var tok_it = tree.tokens.iterator(0);
4743
44 // skip over line comments at the top of the file
45 while (true) {
46 const next_tok = tok_it.peek() ?? break;
47 if (next_tok.id != Token.Id.LineComment) break;
48 _ = tok_it.next();
49 }
50
4851 try stack.append(State.TopLevel);
4952
5053 while (true) {
......@@ -53,10 +56,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
5356
5457 switch (state) {
5558 State.TopLevel => {
56 while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| {
57 try root_node.decls.push(&line_comment.base);
58 }
59
6059 const comments = try eatDocComments(arena, &tok_it, &tree);
6160
6261 const token = nextToken(&tok_it, &tree);
......@@ -66,33 +65,27 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
6665 Token.Id.Keyword_test => {
6766 stack.append(State.TopLevel) catch unreachable;
6867
69 const block = try arena.construct(ast.Node.Block {
70 .base = ast.Node {
71 .id = ast.Node.Id.Block,
72 },
68 const block = try arena.construct(ast.Node.Block{
69 .base = ast.Node{ .id = ast.Node.Id.Block },
7370 .label = null,
7471 .lbrace = undefined,
7572 .statements = ast.Node.Block.StatementList.init(arena),
7673 .rbrace = undefined,
7774 });
78 const test_node = try arena.construct(ast.Node.TestDecl {
79 .base = ast.Node {
80 .id = ast.Node.Id.TestDecl,
81 },
75 const test_node = try arena.construct(ast.Node.TestDecl{
76 .base = ast.Node{ .id = ast.Node.Id.TestDecl },
8277 .doc_comments = comments,
8378 .test_token = token_index,
8479 .name = undefined,
8580 .body_node = &block.base,
8681 });
8782 try root_node.decls.push(&test_node.base);
88 try stack.append(State { .Block = block });
89 try stack.append(State {
90 .ExpectTokenSave = ExpectTokenSave {
91 .id = Token.Id.LBrace,
92 .ptr = &block.rbrace,
93 }
94 });
95 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &test_node.name } });
83 try stack.append(State{ .Block = block });
84 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
85 .id = Token.Id.LBrace,
86 .ptr = &block.lbrace,
87 } });
88 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &test_node.name } });
9689 continue;
9790 },
9891 Token.Id.Eof => {
......@@ -102,31 +95,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
10295 },
10396 Token.Id.Keyword_pub => {
10497 stack.append(State.TopLevel) catch unreachable;
105 try stack.append(State {
106 .TopLevelExtern = TopLevelDeclCtx {
107 .decls = &root_node.decls,
108 .visib_token = token_index,
109 .extern_export_inline_token = null,
110 .lib_name = null,
111 .comments = comments,
112 }
113 });
98 try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{
99 .decls = &root_node.decls,
100 .visib_token = token_index,
101 .extern_export_inline_token = null,
102 .lib_name = null,
103 .comments = comments,
104 } });
114105 continue;
115106 },
116107 Token.Id.Keyword_comptime => {
117 const block = try createNode(arena, ast.Node.Block,
118 ast.Node.Block {
119 .base = undefined,
120 .label = null,
121 .lbrace = undefined,
122 .statements = ast.Node.Block.StatementList.init(arena),
123 .rbrace = undefined,
124 }
125 );
126 const node = try arena.construct(ast.Node.Comptime {
127 .base = ast.Node {
128 .id = ast.Node.Id.Comptime,
129 },
108 const block = try arena.construct(ast.Node.Block{
109 .base = ast.Node{ .id = ast.Node.Id.Block },
110 .label = null,
111 .lbrace = undefined,
112 .statements = ast.Node.Block.StatementList.init(arena),
113 .rbrace = undefined,
114 });
115 const node = try arena.construct(ast.Node.Comptime{
116 .base = ast.Node{ .id = ast.Node.Id.Comptime },
130117 .comptime_token = token_index,
131118 .expr = &block.base,
132119 .doc_comments = comments,
......@@ -134,27 +121,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
134121 try root_node.decls.push(&node.base);
135122
136123 stack.append(State.TopLevel) catch unreachable;
137 try stack.append(State { .Block = block });
138 try stack.append(State {
139 .ExpectTokenSave = ExpectTokenSave {
140 .id = Token.Id.LBrace,
141 .ptr = &block.rbrace,
142 }
143 });
124 try stack.append(State{ .Block = block });
125 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
126 .id = Token.Id.LBrace,
127 .ptr = &block.lbrace,
128 } });
144129 continue;
145130 },
146131 else => {
147 putBackToken(&tok_it, &tree);
132 prevToken(&tok_it, &tree);
148133 stack.append(State.TopLevel) catch unreachable;
149 try stack.append(State {
150 .TopLevelExtern = TopLevelDeclCtx {
151 .decls = &root_node.decls,
152 .visib_token = null,
153 .extern_export_inline_token = null,
154 .lib_name = null,
155 .comments = comments,
156 }
157 });
134 try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{
135 .decls = &root_node.decls,
136 .visib_token = null,
137 .extern_export_inline_token = null,
138 .lib_name = null,
139 .comments = comments,
140 } });
158141 continue;
159142 },
160143 }
......@@ -164,41 +147,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
164147 const token_index = token.index;
165148 const token_ptr = token.ptr;
166149 switch (token_ptr.id) {
167 Token.Id.Keyword_export, Token.Id.Keyword_inline => {
168 stack.append(State {
169 .TopLevelDecl = TopLevelDeclCtx {
170 .decls = ctx.decls,
171 .visib_token = ctx.visib_token,
172 .extern_export_inline_token = AnnotatedToken {
173 .index = token_index,
174 .ptr = token_ptr,
175 },
176 .lib_name = null,
177 .comments = ctx.comments,
150 Token.Id.Keyword_export,
151 Token.Id.Keyword_inline => {
152 stack.append(State{ .TopLevelDecl = TopLevelDeclCtx{
153 .decls = ctx.decls,
154 .visib_token = ctx.visib_token,
155 .extern_export_inline_token = AnnotatedToken{
156 .index = token_index,
157 .ptr = token_ptr,
178158 },
179 }) catch unreachable;
159 .lib_name = null,
160 .comments = ctx.comments,
161 } }) catch unreachable;
180162 continue;
181163 },
182164 Token.Id.Keyword_extern => {
183 stack.append(State {
184 .TopLevelLibname = TopLevelDeclCtx {
185 .decls = ctx.decls,
186 .visib_token = ctx.visib_token,
187 .extern_export_inline_token = AnnotatedToken {
188 .index = token_index,
189 .ptr = token_ptr,
190 },
191 .lib_name = null,
192 .comments = ctx.comments,
165 stack.append(State{ .TopLevelLibname = TopLevelDeclCtx{
166 .decls = ctx.decls,
167 .visib_token = ctx.visib_token,
168 .extern_export_inline_token = AnnotatedToken{
169 .index = token_index,
170 .ptr = token_ptr,
193171 },
194 }) catch unreachable;
172 .lib_name = null,
173 .comments = ctx.comments,
174 } }) catch unreachable;
195175 continue;
196176 },
197177 else => {
198 putBackToken(&tok_it, &tree);
199 stack.append(State { .TopLevelDecl = ctx }) catch unreachable;
178 prevToken(&tok_it, &tree);
179 stack.append(State{ .TopLevelDecl = ctx }) catch unreachable;
200180 continue;
201 }
181 },
202182 }
203183 },
204184 State.TopLevelLibname => |ctx| {
......@@ -207,20 +187,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
207187 const lib_name_token_index = lib_name_token.index;
208188 const lib_name_token_ptr = lib_name_token.ptr;
209189 break :blk (try parseStringLiteral(arena, &tok_it, lib_name_token_ptr, lib_name_token_index, &tree)) ?? {
210 putBackToken(&tok_it, &tree);
190 prevToken(&tok_it, &tree);
211191 break :blk null;
212192 };
213193 };
214194
215 stack.append(State {
216 .TopLevelDecl = TopLevelDeclCtx {
217 .decls = ctx.decls,
218 .visib_token = ctx.visib_token,
219 .extern_export_inline_token = ctx.extern_export_inline_token,
220 .lib_name = lib_name,
221 .comments = ctx.comments,
222 },
223 }) catch unreachable;
195 stack.append(State{ .TopLevelDecl = TopLevelDeclCtx{
196 .decls = ctx.decls,
197 .visib_token = ctx.visib_token,
198 .extern_export_inline_token = ctx.extern_export_inline_token,
199 .lib_name = lib_name,
200 .comments = ctx.comments,
201 } }) catch unreachable;
224202 continue;
225203 },
226204 State.TopLevelDecl => |ctx| {
......@@ -230,14 +208,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
230208 switch (token_ptr.id) {
231209 Token.Id.Keyword_use => {
232210 if (ctx.extern_export_inline_token) |annotated_token| {
233 *(try tree.errors.addOne()) = Error {
234 .InvalidToken = Error.InvalidToken { .token = annotated_token.index },
235 };
211 ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } };
236212 return tree;
237213 }
238214
239 const node = try arena.construct(ast.Node.Use {
240 .base = ast.Node {.id = ast.Node.Id.Use },
215 const node = try arena.construct(ast.Node.Use{
216 .base = ast.Node{ .id = ast.Node.Id.Use },
217 .use_token = token_index,
241218 .visib_token = ctx.visib_token,
242219 .expr = undefined,
243220 .semicolon_token = undefined,
......@@ -245,44 +222,39 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
245222 });
246223 try ctx.decls.push(&node.base);
247224
248 stack.append(State {
249 .ExpectTokenSave = ExpectTokenSave {
250 .id = Token.Id.Semicolon,
251 .ptr = &node.semicolon_token,
252 }
253 }) catch unreachable;
254 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
225 stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
226 .id = Token.Id.Semicolon,
227 .ptr = &node.semicolon_token,
228 } }) catch unreachable;
229 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
255230 continue;
256231 },
257 Token.Id.Keyword_var, Token.Id.Keyword_const => {
232 Token.Id.Keyword_var,
233 Token.Id.Keyword_const => {
258234 if (ctx.extern_export_inline_token) |annotated_token| {
259235 if (annotated_token.ptr.id == Token.Id.Keyword_inline) {
260 *(try tree.errors.addOne()) = Error {
261 .InvalidToken = Error.InvalidToken { .token = annotated_token.index },
262 };
236 ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } };
263237 return tree;
264238 }
265239 }
266240
267 try stack.append(State {
268 .VarDecl = VarDeclCtx {
269 .comments = ctx.comments,
270 .visib_token = ctx.visib_token,
271 .lib_name = ctx.lib_name,
272 .comptime_token = null,
273 .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,
274 .mut_token = token_index,
275 .list = ctx.decls
276 }
277 });
278 continue;
279 },
280 Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc,
281 Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {
282 const fn_proto = try arena.construct(ast.Node.FnProto {
283 .base = ast.Node {
284 .id = ast.Node.Id.FnProto,
285 },
241 try stack.append(State{ .VarDecl = VarDeclCtx{
242 .comments = ctx.comments,
243 .visib_token = ctx.visib_token,
244 .lib_name = ctx.lib_name,
245 .comptime_token = null,
246 .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,
247 .mut_token = token_index,
248 .list = ctx.decls,
249 } });
250 continue;
251 },
252 Token.Id.Keyword_fn,
253 Token.Id.Keyword_nakedcc,
254 Token.Id.Keyword_stdcallcc,
255 Token.Id.Keyword_async => {
256 const fn_proto = try arena.construct(ast.Node.FnProto{
257 .base = ast.Node{ .id = ast.Node.Id.FnProto },
286258 .doc_comments = ctx.comments,
287259 .visib_token = ctx.visib_token,
288260 .name_token = null,
......@@ -298,38 +270,33 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
298270 .align_expr = null,
299271 });
300272 try ctx.decls.push(&fn_proto.base);
301 stack.append(State { .FnDef = fn_proto }) catch unreachable;
302 try stack.append(State { .FnProto = fn_proto });
273 stack.append(State{ .FnDef = fn_proto }) catch unreachable;
274 try stack.append(State{ .FnProto = fn_proto });
303275
304276 switch (token_ptr.id) {
305 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
277 Token.Id.Keyword_nakedcc,
278 Token.Id.Keyword_stdcallcc => {
306279 fn_proto.cc_token = token_index;
307 try stack.append(State {
308 .ExpectTokenSave = ExpectTokenSave {
309 .id = Token.Id.Keyword_fn,
310 .ptr = &fn_proto.fn_token,
311 }
312 });
280 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
281 .id = Token.Id.Keyword_fn,
282 .ptr = &fn_proto.fn_token,
283 } });
313284 continue;
314285 },
315286 Token.Id.Keyword_async => {
316 const async_node = try createNode(arena, ast.Node.AsyncAttribute,
317 ast.Node.AsyncAttribute {
318 .base = undefined,
319 .async_token = token_index,
320 .allocator_type = null,
321 .rangle_bracket = null,
322 }
323 );
287 const async_node = try arena.construct(ast.Node.AsyncAttribute{
288 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
289 .async_token = token_index,
290 .allocator_type = null,
291 .rangle_bracket = null,
292 });
324293 fn_proto.async_attr = async_node;
325294
326 try stack.append(State {
327 .ExpectTokenSave = ExpectTokenSave {
328 .id = Token.Id.Keyword_fn,
329 .ptr = &fn_proto.fn_token,
330 }
331 });
332 try stack.append(State { .AsyncAllocator = async_node });
295 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
296 .id = Token.Id.Keyword_fn,
297 .ptr = &fn_proto.fn_token,
298 } });
299 try stack.append(State{ .AsyncAllocator = async_node });
333300 continue;
334301 },
335302 Token.Id.Keyword_fn => {
......@@ -340,44 +307,37 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
340307 }
341308 },
342309 else => {
343 *(try tree.errors.addOne()) = Error {
344 .ExpectedVarDeclOrFn = Error.ExpectedVarDeclOrFn { .token = token_index },
345 };
310 ((try tree.errors.addOne())).* = Error{ .ExpectedVarDeclOrFn = Error.ExpectedVarDeclOrFn{ .token = token_index } };
346311 return tree;
347312 },
348313 }
349314 },
350315 State.TopLevelExternOrField => |ctx| {
351316 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {
352 std.debug.assert(ctx.container_decl.kind == ast.Node.ContainerDecl.Kind.Struct);
353 const node = try arena.construct(ast.Node.StructField {
354 .base = ast.Node {
355 .id = ast.Node.Id.StructField,
356 },
317 const node = try arena.construct(ast.Node.StructField{
318 .base = ast.Node{ .id = ast.Node.Id.StructField },
357319 .doc_comments = ctx.comments,
358320 .visib_token = ctx.visib_token,
359321 .name_token = identifier,
360322 .type_expr = undefined,
361323 });
362324 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
363 *node_ptr = &node.base;
325 node_ptr.* = &node.base;
364326
365 stack.append(State { .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable;
366 try stack.append(State { .Expression = OptionalCtx { .Required = &node.type_expr } });
367 try stack.append(State { .ExpectToken = Token.Id.Colon });
327 stack.append(State{ .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable;
328 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.type_expr } });
329 try stack.append(State{ .ExpectToken = Token.Id.Colon });
368330 continue;
369331 }
370332
371333 stack.append(State{ .ContainerDecl = ctx.container_decl }) catch unreachable;
372 try stack.append(State {
373 .TopLevelExtern = TopLevelDeclCtx {
374 .decls = &ctx.container_decl.fields_and_decls,
375 .visib_token = ctx.visib_token,
376 .extern_export_inline_token = null,
377 .lib_name = null,
378 .comments = ctx.comments,
379 }
380 });
334 try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{
335 .decls = &ctx.container_decl.fields_and_decls,
336 .visib_token = ctx.visib_token,
337 .extern_export_inline_token = null,
338 .lib_name = null,
339 .comments = ctx.comments,
340 } });
381341 continue;
382342 },
383343
......@@ -386,10 +346,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
386346 const eq_tok_index = eq_tok.index;
387347 const eq_tok_ptr = eq_tok.ptr;
388348 if (eq_tok_ptr.id != Token.Id.Equal) {
389 putBackToken(&tok_it, &tree);
349 prevToken(&tok_it, &tree);
390350 continue;
391351 }
392 stack.append(State { .Expression = ctx }) catch unreachable;
352 stack.append(State{ .Expression = ctx }) catch unreachable;
393353 continue;
394354 },
395355
......@@ -397,31 +357,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
397357 const token = nextToken(&tok_it, &tree);
398358 const token_index = token.index;
399359 const token_ptr = token.ptr;
400 const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.ContainerDecl,
401 ast.Node.ContainerDecl {
402 .base = undefined,
403 .ltoken = ctx.ltoken,
404 .layout = ctx.layout,
405 .kind = switch (token_ptr.id) {
406 Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct,
407 Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union,
408 Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum,
409 else => {
410 *(try tree.errors.addOne()) = Error {
411 .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index },
412 };
413 return tree;
414 },
360 const node = try arena.construct(ast.Node.ContainerDecl{
361 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },
362 .layout_token = ctx.layout_token,
363 .kind_token = switch (token_ptr.id) {
364 Token.Id.Keyword_struct,
365 Token.Id.Keyword_union,
366 Token.Id.Keyword_enum => token_index,
367 else => {
368 ((try tree.errors.addOne())).* = Error{ .ExpectedAggregateKw = Error.ExpectedAggregateKw{ .token = token_index } };
369 return tree;
415370 },
416 .init_arg_expr = ast.Node.ContainerDecl.InitArg.None,
417 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
418 .rbrace_token = undefined,
419 }
420 );
371 },
372 .init_arg_expr = ast.Node.ContainerDecl.InitArg.None,
373 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
374 .lbrace_token = undefined,
375 .rbrace_token = undefined,
376 });
377 ctx.opt_ctx.store(&node.base);
421378
422 stack.append(State { .ContainerDecl = node }) catch unreachable;
423 try stack.append(State { .ExpectToken = Token.Id.LBrace });
424 try stack.append(State { .ContainerInitArgStart = node });
379 stack.append(State{ .ContainerDecl = node }) catch unreachable;
380 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
381 .id = Token.Id.LBrace,
382 .ptr = &node.lbrace_token,
383 } });
384 try stack.append(State{ .ContainerInitArgStart = node });
425385 continue;
426386 },
427387
......@@ -430,8 +390,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
430390 continue;
431391 }
432392
433 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
434 try stack.append(State { .ContainerInitArg = container_decl });
393 stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable;
394 try stack.append(State{ .ContainerInitArg = container_decl });
435395 continue;
436396 },
437397
......@@ -441,61 +401,53 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
441401 const init_arg_token_ptr = init_arg_token.ptr;
442402 switch (init_arg_token_ptr.id) {
443403 Token.Id.Keyword_enum => {
444 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg {.Enum = null};
404 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Enum = null };
445405 const lparen_tok = nextToken(&tok_it, &tree);
446406 const lparen_tok_index = lparen_tok.index;
447407 const lparen_tok_ptr = lparen_tok.ptr;
448408 if (lparen_tok_ptr.id == Token.Id.LParen) {
449 try stack.append(State { .ExpectToken = Token.Id.RParen } );
450 try stack.append(State { .Expression = OptionalCtx {
451 .RequiredNull = &container_decl.init_arg_expr.Enum,
452 } });
409 try stack.append(State{ .ExpectToken = Token.Id.RParen });
410 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } });
453411 } else {
454 putBackToken(&tok_it, &tree);
412 prevToken(&tok_it, &tree);
455413 }
456414 },
457415 else => {
458 putBackToken(&tok_it, &tree);
459 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg { .Type = undefined };
460 stack.append(State { .Expression = OptionalCtx { .Required = &container_decl.init_arg_expr.Type } }) catch unreachable;
416 prevToken(&tok_it, &tree);
417 container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined };
418 stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable;
461419 },
462420 }
463421 continue;
464422 },
465423
466424 State.ContainerDecl => |container_decl| {
467 while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| {
468 try container_decl.fields_and_decls.push(&line_comment.base);
469 }
470
471425 const comments = try eatDocComments(arena, &tok_it, &tree);
472426 const token = nextToken(&tok_it, &tree);
473427 const token_index = token.index;
474428 const token_ptr = token.ptr;
475429 switch (token_ptr.id) {
476430 Token.Id.Identifier => {
477 switch (container_decl.kind) {
478 ast.Node.ContainerDecl.Kind.Struct => {
479 const node = try arena.construct(ast.Node.StructField {
480 .base = ast.Node {
481 .id = ast.Node.Id.StructField,
482 },
431 switch (tree.tokens.at(container_decl.kind_token).id) {
432 Token.Id.Keyword_struct => {
433 const node = try arena.construct(ast.Node.StructField{
434 .base = ast.Node{ .id = ast.Node.Id.StructField },
483435 .doc_comments = comments,
484436 .visib_token = null,
485437 .name_token = token_index,
486438 .type_expr = undefined,
487439 });
488440 const node_ptr = try container_decl.fields_and_decls.addOne();
489 *node_ptr = &node.base;
441 node_ptr.* = &node.base;
490442
491 try stack.append(State { .FieldListCommaOrEnd = container_decl });
492 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.type_expr } });
493 try stack.append(State { .ExpectToken = Token.Id.Colon });
443 try stack.append(State{ .FieldListCommaOrEnd = container_decl });
444 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.type_expr } });
445 try stack.append(State{ .ExpectToken = Token.Id.Colon });
494446 continue;
495447 },
496 ast.Node.ContainerDecl.Kind.Union => {
497 const node = try arena.construct(ast.Node.UnionTag {
498 .base = ast.Node {.id = ast.Node.Id.UnionTag },
448 Token.Id.Keyword_union => {
449 const node = try arena.construct(ast.Node.UnionTag{
450 .base = ast.Node{ .id = ast.Node.Id.UnionTag },
499451 .name_token = token_index,
500452 .type_expr = null,
501453 .value_expr = null,
......@@ -503,101 +455,89 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
503455 });
504456 try container_decl.fields_and_decls.push(&node.base);
505457
506 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
507 try stack.append(State { .FieldInitValue = OptionalCtx { .RequiredNull = &node.value_expr } });
508 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &node.type_expr } });
509 try stack.append(State { .IfToken = Token.Id.Colon });
458 stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable;
459 try stack.append(State{ .FieldInitValue = OptionalCtx{ .RequiredNull = &node.value_expr } });
460 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &node.type_expr } });
461 try stack.append(State{ .IfToken = Token.Id.Colon });
510462 continue;
511463 },
512 ast.Node.ContainerDecl.Kind.Enum => {
513 const node = try arena.construct(ast.Node.EnumTag {
514 .base = ast.Node { .id = ast.Node.Id.EnumTag },
464 Token.Id.Keyword_enum => {
465 const node = try arena.construct(ast.Node.EnumTag{
466 .base = ast.Node{ .id = ast.Node.Id.EnumTag },
515467 .name_token = token_index,
516468 .value = null,
517469 .doc_comments = comments,
518470 });
519471 try container_decl.fields_and_decls.push(&node.base);
520472
521 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
522 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &node.value } });
523 try stack.append(State { .IfToken = Token.Id.Equal });
473 stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable;
474 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &node.value } });
475 try stack.append(State{ .IfToken = Token.Id.Equal });
524476 continue;
525477 },
478 else => unreachable,
526479 }
527480 },
528481 Token.Id.Keyword_pub => {
529 switch (container_decl.kind) {
530 ast.Node.ContainerDecl.Kind.Struct => {
531 try stack.append(State {
532 .TopLevelExternOrField = TopLevelExternOrFieldCtx {
533 .visib_token = token_index,
534 .container_decl = container_decl,
535 .comments = comments,
536 }
537 });
482 switch (tree.tokens.at(container_decl.kind_token).id) {
483 Token.Id.Keyword_struct => {
484 try stack.append(State{ .TopLevelExternOrField = TopLevelExternOrFieldCtx{
485 .visib_token = token_index,
486 .container_decl = container_decl,
487 .comments = comments,
488 } });
538489 continue;
539490 },
540491 else => {
541492 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
542 try stack.append(State {
543 .TopLevelExtern = TopLevelDeclCtx {
544 .decls = &container_decl.fields_and_decls,
545 .visib_token = token_index,
546 .extern_export_inline_token = null,
547 .lib_name = null,
548 .comments = comments,
549 }
550 });
493 try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{
494 .decls = &container_decl.fields_and_decls,
495 .visib_token = token_index,
496 .extern_export_inline_token = null,
497 .lib_name = null,
498 .comments = comments,
499 } });
551500 continue;
552 }
501 },
553502 }
554503 },
555504 Token.Id.Keyword_export => {
556505 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
557 try stack.append(State {
558 .TopLevelExtern = TopLevelDeclCtx {
559 .decls = &container_decl.fields_and_decls,
560 .visib_token = token_index,
561 .extern_export_inline_token = null,
562 .lib_name = null,
563 .comments = comments,
564 }
565 });
506 try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{
507 .decls = &container_decl.fields_and_decls,
508 .visib_token = token_index,
509 .extern_export_inline_token = null,
510 .lib_name = null,
511 .comments = comments,
512 } });
566513 continue;
567514 },
568515 Token.Id.RBrace => {
569516 if (comments != null) {
570 *(try tree.errors.addOne()) = Error {
571 .UnattachedDocComment = Error.UnattachedDocComment { .token = token_index },
572 };
517 ((try tree.errors.addOne())).* = Error{ .UnattachedDocComment = Error.UnattachedDocComment{ .token = token_index } };
573518 return tree;
574519 }
575520 container_decl.rbrace_token = token_index;
576521 continue;
577522 },
578523 else => {
579 putBackToken(&tok_it, &tree);
524 prevToken(&tok_it, &tree);
580525 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
581 try stack.append(State {
582 .TopLevelExtern = TopLevelDeclCtx {
583 .decls = &container_decl.fields_and_decls,
584 .visib_token = null,
585 .extern_export_inline_token = null,
586 .lib_name = null,
587 .comments = comments,
588 }
589 });
526 try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{
527 .decls = &container_decl.fields_and_decls,
528 .visib_token = null,
529 .extern_export_inline_token = null,
530 .lib_name = null,
531 .comments = comments,
532 } });
590533 continue;
591 }
534 },
592535 }
593536 },
594537
595
596538 State.VarDecl => |ctx| {
597 const var_decl = try arena.construct(ast.Node.VarDecl {
598 .base = ast.Node {
599 .id = ast.Node.Id.VarDecl,
600 },
539 const var_decl = try arena.construct(ast.Node.VarDecl{
540 .base = ast.Node{ .id = ast.Node.Id.VarDecl },
601541 .doc_comments = ctx.comments,
602542 .visib_token = ctx.visib_token,
603543 .mut_token = ctx.mut_token,
......@@ -614,31 +554,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
614554 });
615555 try ctx.list.push(&var_decl.base);
616556
617 try stack.append(State { .VarDeclAlign = var_decl });
618 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} });
619 try stack.append(State { .IfToken = Token.Id.Colon });
620 try stack.append(State {
621 .ExpectTokenSave = ExpectTokenSave {
622 .id = Token.Id.Identifier,
623 .ptr = &var_decl.name_token,
624 }
625 });
557 try stack.append(State{ .VarDeclAlign = var_decl });
558 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &var_decl.type_node } });
559 try stack.append(State{ .IfToken = Token.Id.Colon });
560 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
561 .id = Token.Id.Identifier,
562 .ptr = &var_decl.name_token,
563 } });
626564 continue;
627565 },
628566 State.VarDeclAlign => |var_decl| {
629 try stack.append(State { .VarDeclEq = var_decl });
567 try stack.append(State{ .VarDeclEq = var_decl });
630568
631569 const next_token = nextToken(&tok_it, &tree);
632570 const next_token_index = next_token.index;
633571 const next_token_ptr = next_token.ptr;
634572 if (next_token_ptr.id == Token.Id.Keyword_align) {
635 try stack.append(State { .ExpectToken = Token.Id.RParen });
636 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.align_node} });
637 try stack.append(State { .ExpectToken = Token.Id.LParen });
573 try stack.append(State{ .ExpectToken = Token.Id.RParen });
574 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.align_node } });
575 try stack.append(State{ .ExpectToken = Token.Id.LParen });
638576 continue;
639577 }
640578
641 putBackToken(&tok_it, &tree);
579 prevToken(&tok_it, &tree);
642580 continue;
643581 },
644582 State.VarDeclEq => |var_decl| {
......@@ -648,13 +586,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
648586 switch (token_ptr.id) {
649587 Token.Id.Equal => {
650588 var_decl.eq_token = token_index;
651 stack.append(State {
652 .ExpectTokenSave = ExpectTokenSave {
653 .id = Token.Id.Semicolon,
654 .ptr = &var_decl.semicolon_token,
655 },
656 }) catch unreachable;
657 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } });
589 stack.append(State{ .VarDeclSemiColon = var_decl }) catch unreachable;
590 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.init_node } });
658591 continue;
659592 },
660593 Token.Id.Semicolon => {
......@@ -662,45 +595,63 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
662595 continue;
663596 },
664597 else => {
665 *(try tree.errors.addOne()) = Error {
666 .ExpectedEqOrSemi = Error.ExpectedEqOrSemi { .token = token_index },
667 };
598 ((try tree.errors.addOne())).* = Error{ .ExpectedEqOrSemi = Error.ExpectedEqOrSemi{ .token = token_index } };
668599 return tree;
669 }
600 },
670601 }
671602 },
672603
604 State.VarDeclSemiColon => |var_decl| {
605 const semicolon_token = nextToken(&tok_it, &tree);
606
607 if (semicolon_token.ptr.id != Token.Id.Semicolon) {
608 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
609 .token = semicolon_token.index,
610 .expected_id = Token.Id.Semicolon,
611 } };
612 return tree;
613 }
614
615 var_decl.semicolon_token = semicolon_token.index;
616
617 if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {
618 const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token);
619 if (loc.line == 0) {
620 try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments);
621 } else {
622 prevToken(&tok_it, &tree);
623 }
624 }
625 },
673626
674627 State.FnDef => |fn_proto| {
675628 const token = nextToken(&tok_it, &tree);
676629 const token_index = token.index;
677630 const token_ptr = token.ptr;
678 switch(token_ptr.id) {
631 switch (token_ptr.id) {
679632 Token.Id.LBrace => {
680 const block = try arena.construct(ast.Node.Block {
681 .base = ast.Node { .id = ast.Node.Id.Block },
633 const block = try arena.construct(ast.Node.Block{
634 .base = ast.Node{ .id = ast.Node.Id.Block },
682635 .label = null,
683636 .lbrace = token_index,
684637 .statements = ast.Node.Block.StatementList.init(arena),
685638 .rbrace = undefined,
686639 });
687640 fn_proto.body_node = &block.base;
688 stack.append(State { .Block = block }) catch unreachable;
641 stack.append(State{ .Block = block }) catch unreachable;
689642 continue;
690643 },
691644 Token.Id.Semicolon => continue,
692645 else => {
693 *(try tree.errors.addOne()) = Error {
694 .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace { .token = token_index },
695 };
646 ((try tree.errors.addOne())).* = Error{ .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace{ .token = token_index } };
696647 return tree;
697648 },
698649 }
699650 },
700651 State.FnProto => |fn_proto| {
701 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
702 try stack.append(State { .ParamDecl = fn_proto });
703 try stack.append(State { .ExpectToken = Token.Id.LParen });
652 stack.append(State{ .FnProtoAlign = fn_proto }) catch unreachable;
653 try stack.append(State{ .ParamDecl = fn_proto });
654 try stack.append(State{ .ExpectToken = Token.Id.LParen });
704655
705656 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |name_token| {
706657 fn_proto.name_token = name_token;
......@@ -708,12 +659,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
708659 continue;
709660 },
710661 State.FnProtoAlign => |fn_proto| {
711 stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable;
662 stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable;
712663
713664 if (eatToken(&tok_it, &tree, Token.Id.Keyword_align)) |align_token| {
714 try stack.append(State { .ExpectToken = Token.Id.RParen });
715 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } });
716 try stack.append(State { .ExpectToken = Token.Id.LParen });
665 try stack.append(State{ .ExpectToken = Token.Id.RParen });
666 try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } });
667 try stack.append(State{ .ExpectToken = Token.Id.LParen });
717668 }
718669 continue;
719670 },
......@@ -723,42 +674,37 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
723674 const token_ptr = token.ptr;
724675 switch (token_ptr.id) {
725676 Token.Id.Bang => {
726 fn_proto.return_type = ast.Node.FnProto.ReturnType { .InferErrorSet = undefined };
727 stack.append(State {
728 .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.InferErrorSet },
729 }) catch unreachable;
677 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .InferErrorSet = undefined };
678 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.InferErrorSet } }) catch unreachable;
730679 continue;
731680 },
732681 else => {
733682 // TODO: this is a special case. Remove this when #760 is fixed
734683 if (token_ptr.id == Token.Id.Keyword_error) {
735684 if ((??tok_it.peek()).id == Token.Id.LBrace) {
736 const error_type_node = try arena.construct(ast.Node.ErrorType {
737 .base = ast.Node { .id = ast.Node.Id.ErrorType },
685 const error_type_node = try arena.construct(ast.Node.ErrorType{
686 .base = ast.Node{ .id = ast.Node.Id.ErrorType },
738687 .token = token_index,
739688 });
740 fn_proto.return_type = ast.Node.FnProto.ReturnType {
741 .Explicit = &error_type_node.base,
742 };
689 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };
743690 continue;
744691 }
745692 }
746693
747 putBackToken(&tok_it, &tree);
748 fn_proto.return_type = ast.Node.FnProto.ReturnType { .Explicit = undefined };
749 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.Explicit }, }) catch unreachable;
694 prevToken(&tok_it, &tree);
695 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined };
696 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable;
750697 continue;
751698 },
752699 }
753700 },
754701
755
756702 State.ParamDecl => |fn_proto| {
757703 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
758704 continue;
759705 }
760 const param_decl = try arena.construct(ast.Node.ParamDecl {
761 .base = ast.Node {.id = ast.Node.Id.ParamDecl },
706 const param_decl = try arena.construct(ast.Node.ParamDecl{
707 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
762708 .comptime_token = null,
763709 .noalias_token = null,
764710 .name_token = null,
......@@ -767,14 +713,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
767713 });
768714 try fn_proto.params.push(&param_decl.base);
769715
770 stack.append(State {
771 .ParamDeclEnd = ParamDeclEndCtx {
772 .param_decl = param_decl,
773 .fn_proto = fn_proto,
774 }
775 }) catch unreachable;
776 try stack.append(State { .ParamDeclName = param_decl });
777 try stack.append(State { .ParamDeclAliasOrComptime = param_decl });
716 stack.append(State{ .ParamDeclEnd = ParamDeclEndCtx{
717 .param_decl = param_decl,
718 .fn_proto = fn_proto,
719 } }) catch unreachable;
720 try stack.append(State{ .ParamDeclName = param_decl });
721 try stack.append(State{ .ParamDeclAliasOrComptime = param_decl });
778722 continue;
779723 },
780724 State.ParamDeclAliasOrComptime => |param_decl| {
......@@ -792,7 +736,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
792736 if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| {
793737 param_decl.name_token = ident_token;
794738 } else {
795 putBackToken(&tok_it, &tree);
739 prevToken(&tok_it, &tree);
796740 }
797741 }
798742 continue;
......@@ -800,21 +744,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
800744 State.ParamDeclEnd => |ctx| {
801745 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
802746 ctx.param_decl.var_args_token = ellipsis3;
803 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
747 stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable;
804748 continue;
805749 }
806750
807 try stack.append(State { .ParamDeclComma = ctx.fn_proto });
808 try stack.append(State {
809 .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node }
810 });
751 try stack.append(State{ .ParamDeclComma = ctx.fn_proto });
752 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &ctx.param_decl.type_node } });
811753 continue;
812754 },
813755 State.ParamDeclComma => |fn_proto| {
814756 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {
815757 ExpectCommaOrEndResult.end_token => |t| {
816758 if (t == null) {
817 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;
759 stack.append(State{ .ParamDecl = fn_proto }) catch unreachable;
818760 }
819761 continue;
820762 },
......@@ -827,12 +769,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
827769
828770 State.MaybeLabeledExpression => |ctx| {
829771 if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| {
830 stack.append(State {
831 .LabeledExpression = LabelCtx {
832 .label = ctx.label,
833 .opt_ctx = ctx.opt_ctx,
834 }
835 }) catch unreachable;
772 stack.append(State{ .LabeledExpression = LabelCtx{
773 .label = ctx.label,
774 .opt_ctx = ctx.opt_ctx,
775 } }) catch unreachable;
836776 continue;
837777 }
838778
......@@ -845,74 +785,63 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
845785 const token_ptr = token.ptr;
846786 switch (token_ptr.id) {
847787 Token.Id.LBrace => {
848 const block = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.Block,
849 ast.Node.Block {
850 .base = undefined,
851 .label = ctx.label,
852 .lbrace = token_index,
853 .statements = ast.Node.Block.StatementList.init(arena),
854 .rbrace = undefined,
855 }
856 );
857 stack.append(State { .Block = block }) catch unreachable;
788 const block = try arena.construct(ast.Node.Block{
789 .base = ast.Node{ .id = ast.Node.Id.Block },
790 .label = ctx.label,
791 .lbrace = token_index,
792 .statements = ast.Node.Block.StatementList.init(arena),
793 .rbrace = undefined,
794 });
795 ctx.opt_ctx.store(&block.base);
796 stack.append(State{ .Block = block }) catch unreachable;
858797 continue;
859798 },
860799 Token.Id.Keyword_while => {
861 stack.append(State {
862 .While = LoopCtx {
863 .label = ctx.label,
864 .inline_token = null,
865 .loop_token = token_index,
866 .opt_ctx = ctx.opt_ctx.toRequired(),
867 }
868 }) catch unreachable;
800 stack.append(State{ .While = LoopCtx{
801 .label = ctx.label,
802 .inline_token = null,
803 .loop_token = token_index,
804 .opt_ctx = ctx.opt_ctx.toRequired(),
805 } }) catch unreachable;
869806 continue;
870807 },
871808 Token.Id.Keyword_for => {
872 stack.append(State {
873 .For = LoopCtx {
874 .label = ctx.label,
875 .inline_token = null,
876 .loop_token = token_index,
877 .opt_ctx = ctx.opt_ctx.toRequired(),
878 }
879 }) catch unreachable;
809 stack.append(State{ .For = LoopCtx{
810 .label = ctx.label,
811 .inline_token = null,
812 .loop_token = token_index,
813 .opt_ctx = ctx.opt_ctx.toRequired(),
814 } }) catch unreachable;
880815 continue;
881816 },
882817 Token.Id.Keyword_suspend => {
883 const node = try arena.construct(ast.Node.Suspend {
884 .base = ast.Node {
885 .id = ast.Node.Id.Suspend,
886 },
818 const node = try arena.construct(ast.Node.Suspend{
819 .base = ast.Node{ .id = ast.Node.Id.Suspend },
887820 .label = ctx.label,
888821 .suspend_token = token_index,
889822 .payload = null,
890823 .body = null,
891824 });
892825 ctx.opt_ctx.store(&node.base);
893 stack.append(State { .SuspendBody = node }) catch unreachable;
894 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
826 stack.append(State{ .SuspendBody = node }) catch unreachable;
827 try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });
895828 continue;
896829 },
897830 Token.Id.Keyword_inline => {
898 stack.append(State {
899 .Inline = InlineCtx {
900 .label = ctx.label,
901 .inline_token = token_index,
902 .opt_ctx = ctx.opt_ctx.toRequired(),
903 }
904 }) catch unreachable;
831 stack.append(State{ .Inline = InlineCtx{
832 .label = ctx.label,
833 .inline_token = token_index,
834 .opt_ctx = ctx.opt_ctx.toRequired(),
835 } }) catch unreachable;
905836 continue;
906837 },
907838 else => {
908839 if (ctx.opt_ctx != OptionalCtx.Optional) {
909 *(try tree.errors.addOne()) = Error {
910 .ExpectedLabelable = Error.ExpectedLabelable { .token = token_index },
911 };
840 ((try tree.errors.addOne())).* = Error{ .ExpectedLabelable = Error.ExpectedLabelable{ .token = token_index } };
912841 return tree;
913842 }
914843
915 putBackToken(&tok_it, &tree);
844 prevToken(&tok_it, &tree);
916845 continue;
917846 },
918847 }
......@@ -923,112 +852,101 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
923852 const token_ptr = token.ptr;
924853 switch (token_ptr.id) {
925854 Token.Id.Keyword_while => {
926 stack.append(State {
927 .While = LoopCtx {
928 .inline_token = ctx.inline_token,
929 .label = ctx.label,
930 .loop_token = token_index,
931 .opt_ctx = ctx.opt_ctx.toRequired(),
932 }
933 }) catch unreachable;
855 stack.append(State{ .While = LoopCtx{
856 .inline_token = ctx.inline_token,
857 .label = ctx.label,
858 .loop_token = token_index,
859 .opt_ctx = ctx.opt_ctx.toRequired(),
860 } }) catch unreachable;
934861 continue;
935862 },
936863 Token.Id.Keyword_for => {
937 stack.append(State {
938 .For = LoopCtx {
939 .inline_token = ctx.inline_token,
940 .label = ctx.label,
941 .loop_token = token_index,
942 .opt_ctx = ctx.opt_ctx.toRequired(),
943 }
944 }) catch unreachable;
864 stack.append(State{ .For = LoopCtx{
865 .inline_token = ctx.inline_token,
866 .label = ctx.label,
867 .loop_token = token_index,
868 .opt_ctx = ctx.opt_ctx.toRequired(),
869 } }) catch unreachable;
945870 continue;
946871 },
947872 else => {
948873 if (ctx.opt_ctx != OptionalCtx.Optional) {
949 *(try tree.errors.addOne()) = Error {
950 .ExpectedInlinable = Error.ExpectedInlinable { .token = token_index },
951 };
874 ((try tree.errors.addOne())).* = Error{ .ExpectedInlinable = Error.ExpectedInlinable{ .token = token_index } };
952875 return tree;
953876 }
954877
955 putBackToken(&tok_it, &tree);
878 prevToken(&tok_it, &tree);
956879 continue;
957880 },
958881 }
959882 },
960883 State.While => |ctx| {
961 const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.While,
962 ast.Node.While {
963 .base = undefined,
964 .label = ctx.label,
965 .inline_token = ctx.inline_token,
966 .while_token = ctx.loop_token,
967 .condition = undefined,
968 .payload = null,
969 .continue_expr = null,
970 .body = undefined,
971 .@"else" = null,
972 }
973 );
974 stack.append(State { .Else = &node.@"else" }) catch unreachable;
975 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
976 try stack.append(State { .WhileContinueExpr = &node.continue_expr });
977 try stack.append(State { .IfToken = Token.Id.Colon });
978 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
979 try stack.append(State { .ExpectToken = Token.Id.RParen });
980 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
981 try stack.append(State { .ExpectToken = Token.Id.LParen });
884 const node = try arena.construct(ast.Node.While{
885 .base = ast.Node{ .id = ast.Node.Id.While },
886 .label = ctx.label,
887 .inline_token = ctx.inline_token,
888 .while_token = ctx.loop_token,
889 .condition = undefined,
890 .payload = null,
891 .continue_expr = null,
892 .body = undefined,
893 .@"else" = null,
894 });
895 ctx.opt_ctx.store(&node.base);
896 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
897 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
898 try stack.append(State{ .WhileContinueExpr = &node.continue_expr });
899 try stack.append(State{ .IfToken = Token.Id.Colon });
900 try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } });
901 try stack.append(State{ .ExpectToken = Token.Id.RParen });
902 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.condition } });
903 try stack.append(State{ .ExpectToken = Token.Id.LParen });
982904 continue;
983905 },
984906 State.WhileContinueExpr => |dest| {
985 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
986 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } });
987 try stack.append(State { .ExpectToken = Token.Id.LParen });
907 stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable;
908 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = dest } });
909 try stack.append(State{ .ExpectToken = Token.Id.LParen });
988910 continue;
989911 },
990912 State.For => |ctx| {
991 const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.For,
992 ast.Node.For {
993 .base = undefined,
994 .label = ctx.label,
995 .inline_token = ctx.inline_token,
996 .for_token = ctx.loop_token,
997 .array_expr = undefined,
998 .payload = null,
999 .body = undefined,
1000 .@"else" = null,
1001 }
1002 );
1003 stack.append(State { .Else = &node.@"else" }) catch unreachable;
1004 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
1005 try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } });
1006 try stack.append(State { .ExpectToken = Token.Id.RParen });
1007 try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } });
1008 try stack.append(State { .ExpectToken = Token.Id.LParen });
913 const node = try arena.construct(ast.Node.For{
914 .base = ast.Node{ .id = ast.Node.Id.For },
915 .label = ctx.label,
916 .inline_token = ctx.inline_token,
917 .for_token = ctx.loop_token,
918 .array_expr = undefined,
919 .payload = null,
920 .body = undefined,
921 .@"else" = null,
922 });
923 ctx.opt_ctx.store(&node.base);
924 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
925 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
926 try stack.append(State{ .PointerIndexPayload = OptionalCtx{ .Optional = &node.payload } });
927 try stack.append(State{ .ExpectToken = Token.Id.RParen });
928 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.array_expr } });
929 try stack.append(State{ .ExpectToken = Token.Id.LParen });
1009930 continue;
1010931 },
1011932 State.Else => |dest| {
1012933 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
1013 const node = try createNode(arena, ast.Node.Else,
1014 ast.Node.Else {
1015 .base = undefined,
1016 .else_token = else_token,
1017 .payload = null,
1018 .body = undefined,
1019 }
1020 );
1021 *dest = node;
934 const node = try arena.construct(ast.Node.Else{
935 .base = ast.Node{ .id = ast.Node.Id.Else },
936 .else_token = else_token,
937 .payload = null,
938 .body = undefined,
939 });
940 dest.* = node;
1022941
1023 stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable;
1024 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
942 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable;
943 try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });
1025944 continue;
1026945 } else {
1027946 continue;
1028947 }
1029948 },
1030949
1031
1032950 State.Block => |block| {
1033951 const token = nextToken(&tok_it, &tree);
1034952 const token_index = token.index;
......@@ -1039,17 +957,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1039957 continue;
1040958 },
1041959 else => {
1042 putBackToken(&tok_it, &tree);
1043 stack.append(State { .Block = block }) catch unreachable;
1044
1045 var any_comments = false;
1046 while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| {
1047 try block.statements.push(&line_comment.base);
1048 any_comments = true;
1049 }
1050 if (any_comments) continue;
960 prevToken(&tok_it, &tree);
961 stack.append(State{ .Block = block }) catch unreachable;
1051962
1052 try stack.append(State { .Statement = block });
963 try stack.append(State{ .Statement = block });
1053964 continue;
1054965 },
1055966 }
......@@ -1060,33 +971,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1060971 const token_ptr = token.ptr;
1061972 switch (token_ptr.id) {
1062973 Token.Id.Keyword_comptime => {
1063 stack.append(State {
1064 .ComptimeStatement = ComptimeStatementCtx {
1065 .comptime_token = token_index,
1066 .block = block,
1067 }
1068 }) catch unreachable;
1069 continue;
1070 },
1071 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1072 stack.append(State {
1073 .VarDecl = VarDeclCtx {
1074 .comments = null,
1075 .visib_token = null,
1076 .comptime_token = null,
1077 .extern_export_token = null,
1078 .lib_name = null,
1079 .mut_token = token_index,
1080 .list = &block.statements,
1081 }
1082 }) catch unreachable;
974 stack.append(State{ .ComptimeStatement = ComptimeStatementCtx{
975 .comptime_token = token_index,
976 .block = block,
977 } }) catch unreachable;
1083978 continue;
1084979 },
1085 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
1086 const node = try arena.construct(ast.Node.Defer {
1087 .base = ast.Node {
1088 .id = ast.Node.Id.Defer,
1089 },
980 Token.Id.Keyword_var,
981 Token.Id.Keyword_const => {
982 stack.append(State{ .VarDecl = VarDeclCtx{
983 .comments = null,
984 .visib_token = null,
985 .comptime_token = null,
986 .extern_export_token = null,
987 .lib_name = null,
988 .mut_token = token_index,
989 .list = &block.statements,
990 } }) catch unreachable;
991 continue;
992 },
993 Token.Id.Keyword_defer,
994 Token.Id.Keyword_errdefer => {
995 const node = try arena.construct(ast.Node.Defer{
996 .base = ast.Node{ .id = ast.Node.Id.Defer },
1090997 .defer_token = token_index,
1091998 .kind = switch (token_ptr.id) {
1092999 Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional,
......@@ -1096,15 +1003,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
10961003 .expr = undefined,
10971004 });
10981005 const node_ptr = try block.statements.addOne();
1099 *node_ptr = &node.base;
1006 node_ptr.* = &node.base;
11001007
1101 stack.append(State { .Semicolon = node_ptr }) catch unreachable;
1102 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
1008 stack.append(State{ .Semicolon = node_ptr }) catch unreachable;
1009 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
11031010 continue;
11041011 },
11051012 Token.Id.LBrace => {
1106 const inner_block = try arena.construct(ast.Node.Block {
1107 .base = ast.Node { .id = ast.Node.Id.Block },
1013 const inner_block = try arena.construct(ast.Node.Block{
1014 .base = ast.Node{ .id = ast.Node.Id.Block },
11081015 .label = null,
11091016 .lbrace = token_index,
11101017 .statements = ast.Node.Block.StatementList.init(arena),
......@@ -1112,16 +1019,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
11121019 });
11131020 try block.statements.push(&inner_block.base);
11141021
1115 stack.append(State { .Block = inner_block }) catch unreachable;
1022 stack.append(State{ .Block = inner_block }) catch unreachable;
11161023 continue;
11171024 },
11181025 else => {
1119 putBackToken(&tok_it, &tree);
1026 prevToken(&tok_it, &tree);
11201027 const statement = try block.statements.addOne();
1121 try stack.append(State { .Semicolon = statement });
1122 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } });
1028 try stack.append(State{ .Semicolon = statement });
1029 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } });
11231030 continue;
1124 }
1031 },
11251032 }
11261033 },
11271034 State.ComptimeStatement => |ctx| {
......@@ -1129,34 +1036,33 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
11291036 const token_index = token.index;
11301037 const token_ptr = token.ptr;
11311038 switch (token_ptr.id) {
1132 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1133 stack.append(State {
1134 .VarDecl = VarDeclCtx {
1135 .comments = null,
1136 .visib_token = null,
1137 .comptime_token = ctx.comptime_token,
1138 .extern_export_token = null,
1139 .lib_name = null,
1140 .mut_token = token_index,
1141 .list = &ctx.block.statements,
1142 }
1143 }) catch unreachable;
1039 Token.Id.Keyword_var,
1040 Token.Id.Keyword_const => {
1041 stack.append(State{ .VarDecl = VarDeclCtx{
1042 .comments = null,
1043 .visib_token = null,
1044 .comptime_token = ctx.comptime_token,
1045 .extern_export_token = null,
1046 .lib_name = null,
1047 .mut_token = token_index,
1048 .list = &ctx.block.statements,
1049 } }) catch unreachable;
11441050 continue;
11451051 },
11461052 else => {
1147 putBackToken(&tok_it, &tree);
1148 putBackToken(&tok_it, &tree);
1053 prevToken(&tok_it, &tree);
1054 prevToken(&tok_it, &tree);
11491055 const statement = try ctx.block.statements.addOne();
1150 try stack.append(State { .Semicolon = statement });
1151 try stack.append(State { .Expression = OptionalCtx { .Required = statement } });
1056 try stack.append(State{ .Semicolon = statement });
1057 try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } });
11521058 continue;
1153 }
1059 },
11541060 }
11551061 },
11561062 State.Semicolon => |node_ptr| {
1157 const node = *node_ptr;
1063 const node = node_ptr.*;
11581064 if (node.requireSemiColon()) {
1159 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1065 stack.append(State{ .ExpectToken = Token.Id.Semicolon }) catch unreachable;
11601066 continue;
11611067 }
11621068 continue;
......@@ -1167,28 +1073,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
11671073 const lbracket_index = lbracket.index;
11681074 const lbracket_ptr = lbracket.ptr;
11691075 if (lbracket_ptr.id != Token.Id.LBracket) {
1170 putBackToken(&tok_it, &tree);
1076 prevToken(&tok_it, &tree);
11711077 continue;
11721078 }
11731079
1174 const node = try createNode(arena, ast.Node.AsmOutput,
1175 ast.Node.AsmOutput {
1176 .base = undefined,
1177 .symbolic_name = undefined,
1178 .constraint = undefined,
1179 .kind = undefined,
1180 }
1181 );
1080 const node = try arena.construct(ast.Node.AsmOutput{
1081 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },
1082 .lbracket = lbracket_index,
1083 .symbolic_name = undefined,
1084 .constraint = undefined,
1085 .kind = undefined,
1086 .rparen = undefined,
1087 });
11821088 try items.push(node);
11831089
1184 stack.append(State { .AsmOutputItems = items }) catch unreachable;
1185 try stack.append(State { .IfToken = Token.Id.Comma });
1186 try stack.append(State { .ExpectToken = Token.Id.RParen });
1187 try stack.append(State { .AsmOutputReturnOrType = node });
1188 try stack.append(State { .ExpectToken = Token.Id.LParen });
1189 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1190 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1191 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1090 stack.append(State{ .AsmOutputItems = items }) catch unreachable;
1091 try stack.append(State{ .IfToken = Token.Id.Comma });
1092 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1093 .id = Token.Id.RParen,
1094 .ptr = &node.rparen,
1095 } });
1096 try stack.append(State{ .AsmOutputReturnOrType = node });
1097 try stack.append(State{ .ExpectToken = Token.Id.LParen });
1098 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } });
1099 try stack.append(State{ .ExpectToken = Token.Id.RBracket });
1100 try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.symbolic_name } });
11921101 continue;
11931102 },
11941103 State.AsmOutputReturnOrType => |node| {
......@@ -1197,20 +1106,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
11971106 const token_ptr = token.ptr;
11981107 switch (token_ptr.id) {
11991108 Token.Id.Identifier => {
1200 node.kind = ast.Node.AsmOutput.Kind { .Variable = try createLiteral(arena, ast.Node.Identifier, token_index) };
1109 node.kind = ast.Node.AsmOutput.Kind{ .Variable = try createLiteral(arena, ast.Node.Identifier, token_index) };
12011110 continue;
12021111 },
12031112 Token.Id.Arrow => {
1204 node.kind = ast.Node.AsmOutput.Kind { .Return = undefined };
1205 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.kind.Return } });
1113 node.kind = ast.Node.AsmOutput.Kind{ .Return = undefined };
1114 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.kind.Return } });
12061115 continue;
12071116 },
12081117 else => {
1209 *(try tree.errors.addOne()) = Error {
1210 .ExpectedAsmOutputReturnOrType = Error.ExpectedAsmOutputReturnOrType {
1211 .token = token_index,
1212 },
1213 };
1118 ((try tree.errors.addOne())).* = Error{ .ExpectedAsmOutputReturnOrType = Error.ExpectedAsmOutputReturnOrType{ .token = token_index } };
12141119 return tree;
12151120 },
12161121 }
......@@ -1220,55 +1125,57 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
12201125 const lbracket_index = lbracket.index;
12211126 const lbracket_ptr = lbracket.ptr;
12221127 if (lbracket_ptr.id != Token.Id.LBracket) {
1223 putBackToken(&tok_it, &tree);
1128 prevToken(&tok_it, &tree);
12241129 continue;
12251130 }
12261131
1227 const node = try createNode(arena, ast.Node.AsmInput,
1228 ast.Node.AsmInput {
1229 .base = undefined,
1230 .symbolic_name = undefined,
1231 .constraint = undefined,
1232 .expr = undefined,
1233 }
1234 );
1132 const node = try arena.construct(ast.Node.AsmInput{
1133 .base = ast.Node{ .id = ast.Node.Id.AsmInput },
1134 .lbracket = lbracket_index,
1135 .symbolic_name = undefined,
1136 .constraint = undefined,
1137 .expr = undefined,
1138 .rparen = undefined,
1139 });
12351140 try items.push(node);
12361141
1237 stack.append(State { .AsmInputItems = items }) catch unreachable;
1238 try stack.append(State { .IfToken = Token.Id.Comma });
1239 try stack.append(State { .ExpectToken = Token.Id.RParen });
1240 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
1241 try stack.append(State { .ExpectToken = Token.Id.LParen });
1242 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1243 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1244 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1142 stack.append(State{ .AsmInputItems = items }) catch unreachable;
1143 try stack.append(State{ .IfToken = Token.Id.Comma });
1144 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1145 .id = Token.Id.RParen,
1146 .ptr = &node.rparen,
1147 } });
1148 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
1149 try stack.append(State{ .ExpectToken = Token.Id.LParen });
1150 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } });
1151 try stack.append(State{ .ExpectToken = Token.Id.RBracket });
1152 try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.symbolic_name } });
12451153 continue;
12461154 },
12471155 State.AsmClobberItems => |items| {
1248 stack.append(State { .AsmClobberItems = items }) catch unreachable;
1249 try stack.append(State { .IfToken = Token.Id.Comma });
1250 try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } });
1156 stack.append(State{ .AsmClobberItems = items }) catch unreachable;
1157 try stack.append(State{ .IfToken = Token.Id.Comma });
1158 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } });
12511159 continue;
12521160 },
12531161
1254
12551162 State.ExprListItemOrEnd => |list_state| {
12561163 if (eatToken(&tok_it, &tree, list_state.end)) |token_index| {
1257 *list_state.ptr = token_index;
1164 (list_state.ptr).* = token_index;
12581165 continue;
12591166 }
12601167
1261 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
1262 try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } });
1168 stack.append(State{ .ExprListCommaOrEnd = list_state }) catch unreachable;
1169 try stack.append(State{ .Expression = OptionalCtx{ .Required = try list_state.list.addOne() } });
12631170 continue;
12641171 },
12651172 State.ExprListCommaOrEnd => |list_state| {
12661173 switch (expectCommaOrEnd(&tok_it, &tree, list_state.end)) {
12671174 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1268 *list_state.ptr = end;
1175 (list_state.ptr).* = end;
12691176 continue;
12701177 } else {
1271 stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable;
1178 stack.append(State{ .ExprListItemOrEnd = list_state }) catch unreachable;
12721179 continue;
12731180 },
12741181 ExpectCommaOrEndResult.parse_error => |e| {
......@@ -1278,49 +1185,39 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
12781185 }
12791186 },
12801187 State.FieldInitListItemOrEnd => |list_state| {
1281 while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| {
1282 try list_state.list.push(&line_comment.base);
1283 }
1284
12851188 if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {
1286 *list_state.ptr = rbrace;
1189 (list_state.ptr).* = rbrace;
12871190 continue;
12881191 }
12891192
1290 const node = try arena.construct(ast.Node.FieldInitializer {
1291 .base = ast.Node {
1292 .id = ast.Node.Id.FieldInitializer,
1293 },
1193 const node = try arena.construct(ast.Node.FieldInitializer{
1194 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },
12941195 .period_token = undefined,
12951196 .name_token = undefined,
12961197 .expr = undefined,
12971198 });
12981199 try list_state.list.push(&node.base);
12991200
1300 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
1301 try stack.append(State { .Expression = OptionalCtx{ .Required = &node.expr } });
1302 try stack.append(State { .ExpectToken = Token.Id.Equal });
1303 try stack.append(State {
1304 .ExpectTokenSave = ExpectTokenSave {
1305 .id = Token.Id.Identifier,
1306 .ptr = &node.name_token,
1307 }
1308 });
1309 try stack.append(State {
1310 .ExpectTokenSave = ExpectTokenSave {
1311 .id = Token.Id.Period,
1312 .ptr = &node.period_token,
1313 }
1314 });
1201 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;
1202 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
1203 try stack.append(State{ .ExpectToken = Token.Id.Equal });
1204 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1205 .id = Token.Id.Identifier,
1206 .ptr = &node.name_token,
1207 } });
1208 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1209 .id = Token.Id.Period,
1210 .ptr = &node.period_token,
1211 } });
13151212 continue;
13161213 },
13171214 State.FieldInitListCommaOrEnd => |list_state| {
13181215 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
13191216 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1320 *list_state.ptr = end;
1217 (list_state.ptr).* = end;
13211218 continue;
13221219 } else {
1323 stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable;
1220 stack.append(State{ .FieldInitListItemOrEnd = list_state }) catch unreachable;
13241221 continue;
13251222 },
13261223 ExpectCommaOrEndResult.parse_error => |e| {
......@@ -1335,7 +1232,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
13351232 container_decl.rbrace_token = end;
13361233 continue;
13371234 } else {
1338 try stack.append(State { .ContainerDecl = container_decl });
1235 try stack.append(State{ .ContainerDecl = container_decl });
13391236 continue;
13401237 },
13411238 ExpectCommaOrEndResult.parse_error => |e| {
......@@ -1345,28 +1242,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
13451242 }
13461243 },
13471244 State.ErrorTagListItemOrEnd => |list_state| {
1348 while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| {
1349 try list_state.list.push(&line_comment.base);
1350 }
1351
13521245 if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {
1353 *list_state.ptr = rbrace;
1246 (list_state.ptr).* = rbrace;
13541247 continue;
13551248 }
13561249
13571250 const node_ptr = try list_state.list.addOne();
13581251
1359 try stack.append(State { .ErrorTagListCommaOrEnd = list_state });
1360 try stack.append(State { .ErrorTag = node_ptr });
1252 try stack.append(State{ .ErrorTagListCommaOrEnd = list_state });
1253 try stack.append(State{ .ErrorTag = node_ptr });
13611254 continue;
13621255 },
13631256 State.ErrorTagListCommaOrEnd => |list_state| {
13641257 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
13651258 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1366 *list_state.ptr = end;
1259 (list_state.ptr).* = end;
13671260 continue;
13681261 } else {
1369 stack.append(State { .ErrorTagListItemOrEnd = list_state }) catch unreachable;
1262 stack.append(State{ .ErrorTagListItemOrEnd = list_state }) catch unreachable;
13701263 continue;
13711264 },
13721265 ExpectCommaOrEndResult.parse_error => |e| {
......@@ -1376,40 +1269,35 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
13761269 }
13771270 },
13781271 State.SwitchCaseOrEnd => |list_state| {
1379 while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| {
1380 try list_state.list.push(&line_comment.base);
1381 }
1382
13831272 if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| {
1384 *list_state.ptr = rbrace;
1273 (list_state.ptr).* = rbrace;
13851274 continue;
13861275 }
13871276
13881277 const comments = try eatDocComments(arena, &tok_it, &tree);
1389 const node = try arena.construct(ast.Node.SwitchCase {
1390 .base = ast.Node {
1391 .id = ast.Node.Id.SwitchCase,
1392 },
1278 const node = try arena.construct(ast.Node.SwitchCase{
1279 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },
13931280 .items = ast.Node.SwitchCase.ItemList.init(arena),
13941281 .payload = null,
13951282 .expr = undefined,
1283 .arrow_token = undefined,
13961284 });
13971285 try list_state.list.push(&node.base);
1398 try stack.append(State { .SwitchCaseCommaOrEnd = list_state });
1399 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } });
1400 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
1401 try stack.append(State { .SwitchCaseFirstItem = &node.items });
1286 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });
1287 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
1288 try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } });
1289 try stack.append(State{ .SwitchCaseFirstItem = node });
14021290
14031291 continue;
14041292 },
14051293
14061294 State.SwitchCaseCommaOrEnd => |list_state| {
1407 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {
1295 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
14081296 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1409 *list_state.ptr = end;
1297 (list_state.ptr).* = end;
14101298 continue;
14111299 } else {
1412 try stack.append(State { .SwitchCaseOrEnd = list_state });
1300 try stack.append(State{ .SwitchCaseOrEnd = list_state });
14131301 continue;
14141302 },
14151303 ExpectCommaOrEndResult.parse_error => |e| {
......@@ -1419,34 +1307,48 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
14191307 }
14201308 },
14211309
1422 State.SwitchCaseFirstItem => |case_items| {
1310 State.SwitchCaseFirstItem => |switch_case| {
14231311 const token = nextToken(&tok_it, &tree);
14241312 const token_index = token.index;
14251313 const token_ptr = token.ptr;
14261314 if (token_ptr.id == Token.Id.Keyword_else) {
1427 const else_node = try arena.construct(ast.Node.SwitchElse {
1428 .base = ast.Node{ .id = ast.Node.Id.SwitchElse},
1315 const else_node = try arena.construct(ast.Node.SwitchElse{
1316 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },
14291317 .token = token_index,
14301318 });
1431 try case_items.push(&else_node.base);
1319 try switch_case.items.push(&else_node.base);
14321320
1433 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });
1321 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1322 .id = Token.Id.EqualAngleBracketRight,
1323 .ptr = &switch_case.arrow_token,
1324 } });
14341325 continue;
14351326 } else {
1436 putBackToken(&tok_it, &tree);
1437 try stack.append(State { .SwitchCaseItem = case_items });
1327 prevToken(&tok_it, &tree);
1328 stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
1329 try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
14381330 continue;
14391331 }
14401332 },
1441 State.SwitchCaseItem => |case_items| {
1442 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
1443 try stack.append(State { .RangeExpressionBegin = OptionalCtx { .Required = try case_items.addOne() } });
1333 State.SwitchCaseItemOrEnd => |switch_case| {
1334 const token = nextToken(&tok_it, &tree);
1335 if (token.ptr.id == Token.Id.EqualAngleBracketRight) {
1336 switch_case.arrow_token = token.index;
1337 continue;
1338 } else {
1339 prevToken(&tok_it, &tree);
1340 stack.append(State{ .SwitchCaseItemCommaOrEnd = switch_case }) catch unreachable;
1341 try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try switch_case.items.addOne() } });
1342 continue;
1343 }
14441344 },
1445 State.SwitchCaseItemCommaOrEnd => |case_items| {
1345 State.SwitchCaseItemCommaOrEnd => |switch_case| {
14461346 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) {
1447 ExpectCommaOrEndResult.end_token => |t| {
1448 if (t == null) {
1449 stack.append(State { .SwitchCaseItem = case_items }) catch unreachable;
1347 ExpectCommaOrEndResult.end_token => |end_token| {
1348 if (end_token) |t| {
1349 switch_case.arrow_token = t;
1350 } else {
1351 stack.append(State{ .SwitchCaseItemOrEnd = switch_case }) catch unreachable;
14501352 }
14511353 continue;
14521354 },
......@@ -1458,10 +1360,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
14581360 continue;
14591361 },
14601362
1461
14621363 State.SuspendBody => |suspend_node| {
14631364 if (suspend_node.payload != null) {
1464 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = &suspend_node.body } });
1365 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } });
14651366 }
14661367 continue;
14671368 },
......@@ -1471,13 +1372,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
14711372 }
14721373
14731374 async_node.rangle_bracket = TokenIndex(0);
1474 try stack.append(State {
1475 .ExpectTokenSave = ExpectTokenSave {
1476 .id = Token.Id.AngleBracketRight,
1477 .ptr = &??async_node.rangle_bracket,
1478 }
1479 });
1480 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } });
1375 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1376 .id = Token.Id.AngleBracketRight,
1377 .ptr = &??async_node.rangle_bracket,
1378 } });
1379 try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &async_node.allocator_type } });
14811380 continue;
14821381 },
14831382 State.AsyncEnd => |ctx| {
......@@ -1496,27 +1395,20 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
14961395 continue;
14971396 }
14981397
1499 *(try tree.errors.addOne()) = Error {
1500 .ExpectedCall = Error.ExpectedCall { .node = node },
1501 };
1398 ((try tree.errors.addOne())).* = Error{ .ExpectedCall = Error.ExpectedCall{ .node = node } };
15021399 return tree;
15031400 },
15041401 else => {
1505 *(try tree.errors.addOne()) = Error {
1506 .ExpectedCallOrFnProto = Error.ExpectedCallOrFnProto { .node = node },
1507 };
1402 ((try tree.errors.addOne())).* = Error{ .ExpectedCallOrFnProto = Error.ExpectedCallOrFnProto{ .node = node } };
15081403 return tree;
1509 }
1404 },
15101405 }
15111406 },
15121407
1513
15141408 State.ExternType => |ctx| {
15151409 if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {
1516 const fn_proto = try arena.construct(ast.Node.FnProto {
1517 .base = ast.Node {
1518 .id = ast.Node.Id.FnProto,
1519 },
1410 const fn_proto = try arena.construct(ast.Node.FnProto{
1411 .base = ast.Node{ .id = ast.Node.Id.FnProto },
15201412 .doc_comments = ctx.comments,
15211413 .visib_token = null,
15221414 .name_token = null,
......@@ -1532,17 +1424,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
15321424 .align_expr = null,
15331425 });
15341426 ctx.opt_ctx.store(&fn_proto.base);
1535 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1427 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
15361428 continue;
15371429 }
15381430
1539 stack.append(State {
1540 .ContainerKind = ContainerKindCtx {
1541 .opt_ctx = ctx.opt_ctx,
1542 .ltoken = ctx.extern_token,
1543 .layout = ast.Node.ContainerDecl.Layout.Extern,
1544 },
1545 }) catch unreachable;
1431 stack.append(State{ .ContainerKind = ContainerKindCtx{
1432 .opt_ctx = ctx.opt_ctx,
1433 .layout_token = ctx.extern_token,
1434 } }) catch unreachable;
15461435 continue;
15471436 },
15481437 State.SliceOrArrayAccess => |node| {
......@@ -1552,20 +1441,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
15521441 switch (token_ptr.id) {
15531442 Token.Id.Ellipsis2 => {
15541443 const start = node.op.ArrayAccess;
1555 node.op = ast.Node.SuffixOp.Op {
1556 .Slice = ast.Node.SuffixOp.Op.Slice {
1557 .start = start,
1558 .end = null,
1559 }
1560 };
1444 node.op = ast.Node.SuffixOp.Op{ .Slice = ast.Node.SuffixOp.Op.Slice{
1445 .start = start,
1446 .end = null,
1447 } };
15611448
1562 stack.append(State {
1563 .ExpectTokenSave = ExpectTokenSave {
1564 .id = Token.Id.RBracket,
1565 .ptr = &node.rtoken,
1566 }
1567 }) catch unreachable;
1568 try stack.append(State { .Expression = OptionalCtx { .Optional = &node.op.Slice.end } });
1449 stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1450 .id = Token.Id.RBracket,
1451 .ptr = &node.rtoken,
1452 } }) catch unreachable;
1453 try stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.op.Slice.end } });
15691454 continue;
15701455 },
15711456 Token.Id.RBracket => {
......@@ -1573,35 +1458,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
15731458 continue;
15741459 },
15751460 else => {
1576 *(try tree.errors.addOne()) = Error {
1577 .ExpectedSliceOrRBracket = Error.ExpectedSliceOrRBracket { .token = token_index },
1578 };
1461 ((try tree.errors.addOne())).* = Error{ .ExpectedSliceOrRBracket = Error.ExpectedSliceOrRBracket{ .token = token_index } };
15791462 return tree;
1580 }
1463 },
15811464 }
15821465 },
15831466 State.SliceOrArrayType => |node| {
15841467 if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| {
1585 node.op = ast.Node.PrefixOp.Op {
1586 .SliceType = ast.Node.PrefixOp.AddrOfInfo {
1587 .align_expr = null,
1588 .bit_offset_start_token = null,
1589 .bit_offset_end_token = null,
1590 .const_token = null,
1591 .volatile_token = null,
1592 }
1593 };
1594 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1595 try stack.append(State { .AddrOfModifiers = &node.op.SliceType });
1468 node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{
1469 .align_info = null,
1470 .const_token = null,
1471 .volatile_token = null,
1472 } };
1473 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
1474 try stack.append(State{ .AddrOfModifiers = &node.op.SliceType });
15961475 continue;
15971476 }
15981477
1599 node.op = ast.Node.PrefixOp.Op { .ArrayType = undefined };
1600 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1601 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1602 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayType } });
1478 node.op = ast.Node.PrefixOp.Op{ .ArrayType = undefined };
1479 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
1480 try stack.append(State{ .ExpectToken = Token.Id.RBracket });
1481 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } });
16031482 continue;
16041483 },
1484
16051485 State.AddrOfModifiers => |addr_of_info| {
16061486 const token = nextToken(&tok_it, &tree);
16071487 const token_index = token.index;
......@@ -1609,23 +1489,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
16091489 switch (token_ptr.id) {
16101490 Token.Id.Keyword_align => {
16111491 stack.append(state) catch unreachable;
1612 if (addr_of_info.align_expr != null) {
1613 *(try tree.errors.addOne()) = Error {
1614 .ExtraAlignQualifier = Error.ExtraAlignQualifier { .token = token_index },
1615 };
1492 if (addr_of_info.align_info != null) {
1493 ((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } };
16161494 return tree;
16171495 }
1618 try stack.append(State { .ExpectToken = Token.Id.RParen });
1619 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &addr_of_info.align_expr} });
1620 try stack.append(State { .ExpectToken = Token.Id.LParen });
1496 addr_of_info.align_info = ast.Node.PrefixOp.AddrOfInfo.Align {
1497 .node = undefined,
1498 .bit_range = null,
1499 };
1500 // TODO https://github.com/ziglang/zig/issues/1022
1501 const align_info = &??addr_of_info.align_info;
1502
1503 try stack.append(State{ .AlignBitRange = align_info });
1504 try stack.append(State{ .Expression = OptionalCtx{ .Required = &align_info.node } });
1505 try stack.append(State{ .ExpectToken = Token.Id.LParen });
16211506 continue;
16221507 },
16231508 Token.Id.Keyword_const => {
16241509 stack.append(state) catch unreachable;
16251510 if (addr_of_info.const_token != null) {
1626 *(try tree.errors.addOne()) = Error {
1627 .ExtraConstQualifier = Error.ExtraConstQualifier { .token = token_index },
1628 };
1511 ((try tree.errors.addOne())).* = Error{ .ExtraConstQualifier = Error.ExtraConstQualifier{ .token = token_index } };
16291512 return tree;
16301513 }
16311514 addr_of_info.const_token = token_index;
......@@ -1634,21 +1517,43 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
16341517 Token.Id.Keyword_volatile => {
16351518 stack.append(state) catch unreachable;
16361519 if (addr_of_info.volatile_token != null) {
1637 *(try tree.errors.addOne()) = Error {
1638 .ExtraVolatileQualifier = Error.ExtraVolatileQualifier { .token = token_index },
1639 };
1520 ((try tree.errors.addOne())).* = Error{ .ExtraVolatileQualifier = Error.ExtraVolatileQualifier{ .token = token_index } };
16401521 return tree;
16411522 }
16421523 addr_of_info.volatile_token = token_index;
16431524 continue;
16441525 },
16451526 else => {
1646 putBackToken(&tok_it, &tree);
1527 prevToken(&tok_it, &tree);
16471528 continue;
16481529 },
16491530 }
16501531 },
16511532
1533 State.AlignBitRange => |align_info| {
1534 const token = nextToken(&tok_it, &tree);
1535 switch (token.ptr.id) {
1536 Token.Id.Colon => {
1537 align_info.bit_range = ast.Node.PrefixOp.AddrOfInfo.Align.BitRange(undefined);
1538 const bit_range = &??align_info.bit_range;
1539
1540 try stack.append(State{ .ExpectToken = Token.Id.RParen });
1541 try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.end } });
1542 try stack.append(State{ .ExpectToken = Token.Id.Colon });
1543 try stack.append(State{ .Expression = OptionalCtx{ .Required = &bit_range.start } });
1544 continue;
1545 },
1546 Token.Id.RParen => continue,
1547 else => {
1548 (try tree.errors.addOne()).* = Error{
1549 .ExpectedColonOrRParen = Error.ExpectedColonOrRParen{
1550 .token = token.index,
1551 }
1552 };
1553 return tree;
1554 },
1555 }
1556 },
16521557
16531558 State.Payload => |opt_ctx| {
16541559 const token = nextToken(&tok_it, &tree);
......@@ -1656,35 +1561,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
16561561 const token_ptr = token.ptr;
16571562 if (token_ptr.id != Token.Id.Pipe) {
16581563 if (opt_ctx != OptionalCtx.Optional) {
1659 *(try tree.errors.addOne()) = Error {
1660 .ExpectedToken = Error.ExpectedToken {
1661 .token = token_index,
1662 .expected_id = Token.Id.Pipe,
1663 },
1664 };
1564 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
1565 .token = token_index,
1566 .expected_id = Token.Id.Pipe,
1567 } };
16651568 return tree;
16661569 }
16671570
1668 putBackToken(&tok_it, &tree);
1571 prevToken(&tok_it, &tree);
16691572 continue;
16701573 }
16711574
1672 const node = try createToCtxNode(arena, opt_ctx, ast.Node.Payload,
1673 ast.Node.Payload {
1674 .base = undefined,
1675 .lpipe = token_index,
1676 .error_symbol = undefined,
1677 .rpipe = undefined
1678 }
1679 );
1575 const node = try arena.construct(ast.Node.Payload{
1576 .base = ast.Node{ .id = ast.Node.Id.Payload },
1577 .lpipe = token_index,
1578 .error_symbol = undefined,
1579 .rpipe = undefined,
1580 });
1581 opt_ctx.store(&node.base);
16801582
1681 stack.append(State {
1682 .ExpectTokenSave = ExpectTokenSave {
1683 .id = Token.Id.Pipe,
1684 .ptr = &node.rpipe,
1685 }
1686 }) catch unreachable;
1687 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } });
1583 stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1584 .id = Token.Id.Pipe,
1585 .ptr = &node.rpipe,
1586 } }) catch unreachable;
1587 try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.error_symbol } });
16881588 continue;
16891589 },
16901590 State.PointerPayload => |opt_ctx| {
......@@ -1693,42 +1593,35 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
16931593 const token_ptr = token.ptr;
16941594 if (token_ptr.id != Token.Id.Pipe) {
16951595 if (opt_ctx != OptionalCtx.Optional) {
1696 *(try tree.errors.addOne()) = Error {
1697 .ExpectedToken = Error.ExpectedToken {
1698 .token = token_index,
1699 .expected_id = Token.Id.Pipe,
1700 },
1701 };
1596 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
1597 .token = token_index,
1598 .expected_id = Token.Id.Pipe,
1599 } };
17021600 return tree;
17031601 }
17041602
1705 putBackToken(&tok_it, &tree);
1603 prevToken(&tok_it, &tree);
17061604 continue;
17071605 }
17081606
1709 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PointerPayload,
1710 ast.Node.PointerPayload {
1711 .base = undefined,
1712 .lpipe = token_index,
1713 .ptr_token = null,
1714 .value_symbol = undefined,
1715 .rpipe = undefined
1716 }
1717 );
1718
1719 try stack.append(State {
1720 .ExpectTokenSave = ExpectTokenSave {
1721 .id = Token.Id.Pipe,
1722 .ptr = &node.rpipe,
1723 }
1724 });
1725 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } });
1726 try stack.append(State {
1727 .OptionalTokenSave = OptionalTokenSave {
1728 .id = Token.Id.Asterisk,
1729 .ptr = &node.ptr_token,
1730 }
1607 const node = try arena.construct(ast.Node.PointerPayload{
1608 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },
1609 .lpipe = token_index,
1610 .ptr_token = null,
1611 .value_symbol = undefined,
1612 .rpipe = undefined,
17311613 });
1614 opt_ctx.store(&node.base);
1615
1616 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1617 .id = Token.Id.Pipe,
1618 .ptr = &node.rpipe,
1619 } });
1620 try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.value_symbol } });
1621 try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{
1622 .id = Token.Id.Asterisk,
1623 .ptr = &node.ptr_token,
1624 } });
17321625 continue;
17331626 },
17341627 State.PointerIndexPayload => |opt_ctx| {
......@@ -1737,76 +1630,69 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
17371630 const token_ptr = token.ptr;
17381631 if (token_ptr.id != Token.Id.Pipe) {
17391632 if (opt_ctx != OptionalCtx.Optional) {
1740 *(try tree.errors.addOne()) = Error {
1741 .ExpectedToken = Error.ExpectedToken {
1742 .token = token_index,
1743 .expected_id = Token.Id.Pipe,
1744 },
1745 };
1633 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
1634 .token = token_index,
1635 .expected_id = Token.Id.Pipe,
1636 } };
17461637 return tree;
17471638 }
17481639
1749 putBackToken(&tok_it, &tree);
1640 prevToken(&tok_it, &tree);
17501641 continue;
17511642 }
17521643
1753 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PointerIndexPayload,
1754 ast.Node.PointerIndexPayload {
1755 .base = undefined,
1756 .lpipe = token_index,
1757 .ptr_token = null,
1758 .value_symbol = undefined,
1759 .index_symbol = null,
1760 .rpipe = undefined
1761 }
1762 );
1763
1764 stack.append(State {
1765 .ExpectTokenSave = ExpectTokenSave {
1766 .id = Token.Id.Pipe,
1767 .ptr = &node.rpipe,
1768 }
1769 }) catch unreachable;
1770 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.index_symbol } });
1771 try stack.append(State { .IfToken = Token.Id.Comma });
1772 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } });
1773 try stack.append(State {
1774 .OptionalTokenSave = OptionalTokenSave {
1775 .id = Token.Id.Asterisk,
1776 .ptr = &node.ptr_token,
1777 }
1644 const node = try arena.construct(ast.Node.PointerIndexPayload{
1645 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },
1646 .lpipe = token_index,
1647 .ptr_token = null,
1648 .value_symbol = undefined,
1649 .index_symbol = null,
1650 .rpipe = undefined,
17781651 });
1652 opt_ctx.store(&node.base);
1653
1654 stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
1655 .id = Token.Id.Pipe,
1656 .ptr = &node.rpipe,
1657 } }) catch unreachable;
1658 try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.index_symbol } });
1659 try stack.append(State{ .IfToken = Token.Id.Comma });
1660 try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.value_symbol } });
1661 try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{
1662 .id = Token.Id.Asterisk,
1663 .ptr = &node.ptr_token,
1664 } });
17791665 continue;
17801666 },
17811667
1782
17831668 State.Expression => |opt_ctx| {
17841669 const token = nextToken(&tok_it, &tree);
17851670 const token_index = token.index;
17861671 const token_ptr = token.ptr;
17871672 switch (token_ptr.id) {
1788 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1789 const node = try createToCtxNode(arena, opt_ctx, ast.Node.ControlFlowExpression,
1790 ast.Node.ControlFlowExpression {
1791 .base = undefined,
1792 .ltoken = token_index,
1793 .kind = undefined,
1794 .rhs = null,
1795 }
1796 );
1673 Token.Id.Keyword_return,
1674 Token.Id.Keyword_break,
1675 Token.Id.Keyword_continue => {
1676 const node = try arena.construct(ast.Node.ControlFlowExpression{
1677 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },
1678 .ltoken = token_index,
1679 .kind = undefined,
1680 .rhs = null,
1681 });
1682 opt_ctx.store(&node.base);
17971683
1798 stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable;
1684 stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable;
17991685
18001686 switch (token_ptr.id) {
18011687 Token.Id.Keyword_break => {
1802 node.kind = ast.Node.ControlFlowExpression.Kind { .Break = null };
1803 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Break } });
1804 try stack.append(State { .IfToken = Token.Id.Colon });
1688 node.kind = ast.Node.ControlFlowExpression.Kind{ .Break = null };
1689 try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.kind.Break } });
1690 try stack.append(State{ .IfToken = Token.Id.Colon });
18051691 },
18061692 Token.Id.Keyword_continue => {
1807 node.kind = ast.Node.ControlFlowExpression.Kind { .Continue = null };
1808 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } });
1809 try stack.append(State { .IfToken = Token.Id.Colon });
1693 node.kind = ast.Node.ControlFlowExpression.Kind{ .Continue = null };
1694 try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.kind.Continue } });
1695 try stack.append(State{ .IfToken = Token.Id.Colon });
18101696 },
18111697 Token.Id.Keyword_return => {
18121698 node.kind = ast.Node.ControlFlowExpression.Kind.Return;
......@@ -1815,58 +1701,58 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
18151701 }
18161702 continue;
18171703 },
1818 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
1819 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp,
1820 ast.Node.PrefixOp {
1821 .base = undefined,
1822 .op_token = token_index,
1823 .op = switch (token_ptr.id) {
1824 Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} },
1825 Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} },
1826 Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} },
1827 else => unreachable,
1828 },
1829 .rhs = undefined,
1830 }
1831 );
1704 Token.Id.Keyword_try,
1705 Token.Id.Keyword_cancel,
1706 Token.Id.Keyword_resume => {
1707 const node = try arena.construct(ast.Node.PrefixOp{
1708 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
1709 .op_token = token_index,
1710 .op = switch (token_ptr.id) {
1711 Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} },
1712 Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op{ .Cancel = void{} },
1713 Token.Id.Keyword_resume => ast.Node.PrefixOp.Op{ .Resume = void{} },
1714 else => unreachable,
1715 },
1716 .rhs = undefined,
1717 });
1718 opt_ctx.store(&node.base);
18321719
1833 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1720 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
18341721 continue;
18351722 },
18361723 else => {
18371724 if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr, token_index)) {
1838 putBackToken(&tok_it, &tree);
1839 stack.append(State { .UnwrapExpressionBegin = opt_ctx }) catch unreachable;
1725 prevToken(&tok_it, &tree);
1726 stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable;
18401727 }
18411728 continue;
1842 }
1729 },
18431730 }
18441731 },
18451732 State.RangeExpressionBegin => |opt_ctx| {
1846 stack.append(State { .RangeExpressionEnd = opt_ctx }) catch unreachable;
1847 try stack.append(State { .Expression = opt_ctx });
1733 stack.append(State{ .RangeExpressionEnd = opt_ctx }) catch unreachable;
1734 try stack.append(State{ .Expression = opt_ctx });
18481735 continue;
18491736 },
18501737 State.RangeExpressionEnd => |opt_ctx| {
18511738 const lhs = opt_ctx.get() ?? continue;
18521739
18531740 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
1854 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1855 ast.Node.InfixOp {
1856 .base = undefined,
1857 .lhs = lhs,
1858 .op_token = ellipsis3,
1859 .op = ast.Node.InfixOp.Op.Range,
1860 .rhs = undefined,
1861 }
1862 );
1863 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1741 const node = try arena.construct(ast.Node.InfixOp{
1742 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1743 .lhs = lhs,
1744 .op_token = ellipsis3,
1745 .op = ast.Node.InfixOp.Op.Range,
1746 .rhs = undefined,
1747 });
1748 opt_ctx.store(&node.base);
1749 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
18641750 continue;
18651751 }
18661752 },
18671753 State.AssignmentExpressionBegin => |opt_ctx| {
1868 stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable;
1869 try stack.append(State { .Expression = opt_ctx });
1754 stack.append(State{ .AssignmentExpressionEnd = opt_ctx }) catch unreachable;
1755 try stack.append(State{ .Expression = opt_ctx });
18701756 continue;
18711757 },
18721758
......@@ -1877,27 +1763,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
18771763 const token_index = token.index;
18781764 const token_ptr = token.ptr;
18791765 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
1880 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1881 ast.Node.InfixOp {
1882 .base = undefined,
1883 .lhs = lhs,
1884 .op_token = token_index,
1885 .op = ass_id,
1886 .rhs = undefined,
1887 }
1888 );
1889 stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1890 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
1766 const node = try arena.construct(ast.Node.InfixOp{
1767 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1768 .lhs = lhs,
1769 .op_token = token_index,
1770 .op = ass_id,
1771 .rhs = undefined,
1772 });
1773 opt_ctx.store(&node.base);
1774 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1775 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
18911776 continue;
18921777 } else {
1893 putBackToken(&tok_it, &tree);
1778 prevToken(&tok_it, &tree);
18941779 continue;
18951780 }
18961781 },
18971782
18981783 State.UnwrapExpressionBegin => |opt_ctx| {
1899 stack.append(State { .UnwrapExpressionEnd = opt_ctx }) catch unreachable;
1900 try stack.append(State { .BoolOrExpressionBegin = opt_ctx });
1784 stack.append(State{ .UnwrapExpressionEnd = opt_ctx }) catch unreachable;
1785 try stack.append(State{ .BoolOrExpressionBegin = opt_ctx });
19011786 continue;
19021787 },
19031788
......@@ -1908,32 +1793,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19081793 const token_index = token.index;
19091794 const token_ptr = token.ptr;
19101795 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
1911 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1912 ast.Node.InfixOp {
1913 .base = undefined,
1914 .lhs = lhs,
1915 .op_token = token_index,
1916 .op = unwrap_id,
1917 .rhs = undefined,
1918 }
1919 );
1796 const node = try arena.construct(ast.Node.InfixOp{
1797 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1798 .lhs = lhs,
1799 .op_token = token_index,
1800 .op = unwrap_id,
1801 .rhs = undefined,
1802 });
1803 opt_ctx.store(&node.base);
19201804
1921 stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1922 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
1805 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1806 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
19231807
19241808 if (node.op == ast.Node.InfixOp.Op.Catch) {
1925 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } });
1809 try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.op.Catch } });
19261810 }
19271811 continue;
19281812 } else {
1929 putBackToken(&tok_it, &tree);
1813 prevToken(&tok_it, &tree);
19301814 continue;
19311815 }
19321816 },
19331817
19341818 State.BoolOrExpressionBegin => |opt_ctx| {
1935 stack.append(State { .BoolOrExpressionEnd = opt_ctx }) catch unreachable;
1936 try stack.append(State { .BoolAndExpressionBegin = opt_ctx });
1819 stack.append(State{ .BoolOrExpressionEnd = opt_ctx }) catch unreachable;
1820 try stack.append(State{ .BoolAndExpressionBegin = opt_ctx });
19371821 continue;
19381822 },
19391823
......@@ -1941,24 +1825,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19411825 const lhs = opt_ctx.get() ?? continue;
19421826
19431827 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {
1944 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1945 ast.Node.InfixOp {
1946 .base = undefined,
1947 .lhs = lhs,
1948 .op_token = or_token,
1949 .op = ast.Node.InfixOp.Op.BoolOr,
1950 .rhs = undefined,
1951 }
1952 );
1953 stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1954 try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1828 const node = try arena.construct(ast.Node.InfixOp{
1829 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1830 .lhs = lhs,
1831 .op_token = or_token,
1832 .op = ast.Node.InfixOp.Op.BoolOr,
1833 .rhs = undefined,
1834 });
1835 opt_ctx.store(&node.base);
1836 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1837 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
19551838 continue;
19561839 }
19571840 },
19581841
19591842 State.BoolAndExpressionBegin => |opt_ctx| {
1960 stack.append(State { .BoolAndExpressionEnd = opt_ctx }) catch unreachable;
1961 try stack.append(State { .ComparisonExpressionBegin = opt_ctx });
1843 stack.append(State{ .BoolAndExpressionEnd = opt_ctx }) catch unreachable;
1844 try stack.append(State{ .ComparisonExpressionBegin = opt_ctx });
19621845 continue;
19631846 },
19641847
......@@ -1966,24 +1849,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19661849 const lhs = opt_ctx.get() ?? continue;
19671850
19681851 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {
1969 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1970 ast.Node.InfixOp {
1971 .base = undefined,
1972 .lhs = lhs,
1973 .op_token = and_token,
1974 .op = ast.Node.InfixOp.Op.BoolAnd,
1975 .rhs = undefined,
1976 }
1977 );
1978 stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1979 try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1852 const node = try arena.construct(ast.Node.InfixOp{
1853 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1854 .lhs = lhs,
1855 .op_token = and_token,
1856 .op = ast.Node.InfixOp.Op.BoolAnd,
1857 .rhs = undefined,
1858 });
1859 opt_ctx.store(&node.base);
1860 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1861 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
19801862 continue;
19811863 }
19821864 },
19831865
19841866 State.ComparisonExpressionBegin => |opt_ctx| {
1985 stack.append(State { .ComparisonExpressionEnd = opt_ctx }) catch unreachable;
1986 try stack.append(State { .BinaryOrExpressionBegin = opt_ctx });
1867 stack.append(State{ .ComparisonExpressionEnd = opt_ctx }) catch unreachable;
1868 try stack.append(State{ .BinaryOrExpressionBegin = opt_ctx });
19871869 continue;
19881870 },
19891871
......@@ -1994,27 +1876,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19941876 const token_index = token.index;
19951877 const token_ptr = token.ptr;
19961878 if (tokenIdToComparison(token_ptr.id)) |comp_id| {
1997 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1998 ast.Node.InfixOp {
1999 .base = undefined,
2000 .lhs = lhs,
2001 .op_token = token_index,
2002 .op = comp_id,
2003 .rhs = undefined,
2004 }
2005 );
2006 stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2007 try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1879 const node = try arena.construct(ast.Node.InfixOp{
1880 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1881 .lhs = lhs,
1882 .op_token = token_index,
1883 .op = comp_id,
1884 .rhs = undefined,
1885 });
1886 opt_ctx.store(&node.base);
1887 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1888 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
20081889 continue;
20091890 } else {
2010 putBackToken(&tok_it, &tree);
1891 prevToken(&tok_it, &tree);
20111892 continue;
20121893 }
20131894 },
20141895
20151896 State.BinaryOrExpressionBegin => |opt_ctx| {
2016 stack.append(State { .BinaryOrExpressionEnd = opt_ctx }) catch unreachable;
2017 try stack.append(State { .BinaryXorExpressionBegin = opt_ctx });
1897 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx }) catch unreachable;
1898 try stack.append(State{ .BinaryXorExpressionBegin = opt_ctx });
20181899 continue;
20191900 },
20201901
......@@ -2022,24 +1903,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20221903 const lhs = opt_ctx.get() ?? continue;
20231904
20241905 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {
2025 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2026 ast.Node.InfixOp {
2027 .base = undefined,
2028 .lhs = lhs,
2029 .op_token = pipe,
2030 .op = ast.Node.InfixOp.Op.BitOr,
2031 .rhs = undefined,
2032 }
2033 );
2034 stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2035 try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1906 const node = try arena.construct(ast.Node.InfixOp{
1907 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1908 .lhs = lhs,
1909 .op_token = pipe,
1910 .op = ast.Node.InfixOp.Op.BitOr,
1911 .rhs = undefined,
1912 });
1913 opt_ctx.store(&node.base);
1914 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1915 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
20361916 continue;
20371917 }
20381918 },
20391919
20401920 State.BinaryXorExpressionBegin => |opt_ctx| {
2041 stack.append(State { .BinaryXorExpressionEnd = opt_ctx }) catch unreachable;
2042 try stack.append(State { .BinaryAndExpressionBegin = opt_ctx });
1921 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx }) catch unreachable;
1922 try stack.append(State{ .BinaryAndExpressionBegin = opt_ctx });
20431923 continue;
20441924 },
20451925
......@@ -2047,24 +1927,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20471927 const lhs = opt_ctx.get() ?? continue;
20481928
20491929 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {
2050 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2051 ast.Node.InfixOp {
2052 .base = undefined,
2053 .lhs = lhs,
2054 .op_token = caret,
2055 .op = ast.Node.InfixOp.Op.BitXor,
2056 .rhs = undefined,
2057 }
2058 );
2059 stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2060 try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1930 const node = try arena.construct(ast.Node.InfixOp{
1931 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1932 .lhs = lhs,
1933 .op_token = caret,
1934 .op = ast.Node.InfixOp.Op.BitXor,
1935 .rhs = undefined,
1936 });
1937 opt_ctx.store(&node.base);
1938 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1939 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
20611940 continue;
20621941 }
20631942 },
20641943
20651944 State.BinaryAndExpressionBegin => |opt_ctx| {
2066 stack.append(State { .BinaryAndExpressionEnd = opt_ctx }) catch unreachable;
2067 try stack.append(State { .BitShiftExpressionBegin = opt_ctx });
1945 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx }) catch unreachable;
1946 try stack.append(State{ .BitShiftExpressionBegin = opt_ctx });
20681947 continue;
20691948 },
20701949
......@@ -2072,24 +1951,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20721951 const lhs = opt_ctx.get() ?? continue;
20731952
20741953 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {
2075 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2076 ast.Node.InfixOp {
2077 .base = undefined,
2078 .lhs = lhs,
2079 .op_token = ampersand,
2080 .op = ast.Node.InfixOp.Op.BitAnd,
2081 .rhs = undefined,
2082 }
2083 );
2084 stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2085 try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1954 const node = try arena.construct(ast.Node.InfixOp{
1955 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1956 .lhs = lhs,
1957 .op_token = ampersand,
1958 .op = ast.Node.InfixOp.Op.BitAnd,
1959 .rhs = undefined,
1960 });
1961 opt_ctx.store(&node.base);
1962 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1963 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
20861964 continue;
20871965 }
20881966 },
20891967
20901968 State.BitShiftExpressionBegin => |opt_ctx| {
2091 stack.append(State { .BitShiftExpressionEnd = opt_ctx }) catch unreachable;
2092 try stack.append(State { .AdditionExpressionBegin = opt_ctx });
1969 stack.append(State{ .BitShiftExpressionEnd = opt_ctx }) catch unreachable;
1970 try stack.append(State{ .AdditionExpressionBegin = opt_ctx });
20931971 continue;
20941972 },
20951973
......@@ -2100,27 +1978,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
21001978 const token_index = token.index;
21011979 const token_ptr = token.ptr;
21021980 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
2103 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2104 ast.Node.InfixOp {
2105 .base = undefined,
2106 .lhs = lhs,
2107 .op_token = token_index,
2108 .op = bitshift_id,
2109 .rhs = undefined,
2110 }
2111 );
2112 stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2113 try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1981 const node = try arena.construct(ast.Node.InfixOp{
1982 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1983 .lhs = lhs,
1984 .op_token = token_index,
1985 .op = bitshift_id,
1986 .rhs = undefined,
1987 });
1988 opt_ctx.store(&node.base);
1989 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1990 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
21141991 continue;
21151992 } else {
2116 putBackToken(&tok_it, &tree);
1993 prevToken(&tok_it, &tree);
21171994 continue;
21181995 }
21191996 },
21201997
21211998 State.AdditionExpressionBegin => |opt_ctx| {
2122 stack.append(State { .AdditionExpressionEnd = opt_ctx }) catch unreachable;
2123 try stack.append(State { .MultiplyExpressionBegin = opt_ctx });
1999 stack.append(State{ .AdditionExpressionEnd = opt_ctx }) catch unreachable;
2000 try stack.append(State{ .MultiplyExpressionBegin = opt_ctx });
21242001 continue;
21252002 },
21262003
......@@ -2131,27 +2008,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
21312008 const token_index = token.index;
21322009 const token_ptr = token.ptr;
21332010 if (tokenIdToAddition(token_ptr.id)) |add_id| {
2134 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2135 ast.Node.InfixOp {
2136 .base = undefined,
2137 .lhs = lhs,
2138 .op_token = token_index,
2139 .op = add_id,
2140 .rhs = undefined,
2141 }
2142 );
2143 stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2144 try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2011 const node = try arena.construct(ast.Node.InfixOp{
2012 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2013 .lhs = lhs,
2014 .op_token = token_index,
2015 .op = add_id,
2016 .rhs = undefined,
2017 });
2018 opt_ctx.store(&node.base);
2019 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2020 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
21452021 continue;
21462022 } else {
2147 putBackToken(&tok_it, &tree);
2023 prevToken(&tok_it, &tree);
21482024 continue;
21492025 }
21502026 },
21512027
21522028 State.MultiplyExpressionBegin => |opt_ctx| {
2153 stack.append(State { .MultiplyExpressionEnd = opt_ctx }) catch unreachable;
2154 try stack.append(State { .CurlySuffixExpressionBegin = opt_ctx });
2029 stack.append(State{ .MultiplyExpressionEnd = opt_ctx }) catch unreachable;
2030 try stack.append(State{ .CurlySuffixExpressionBegin = opt_ctx });
21552031 continue;
21562032 },
21572033
......@@ -2162,28 +2038,27 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
21622038 const token_index = token.index;
21632039 const token_ptr = token.ptr;
21642040 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
2165 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2166 ast.Node.InfixOp {
2167 .base = undefined,
2168 .lhs = lhs,
2169 .op_token = token_index,
2170 .op = mult_id,
2171 .rhs = undefined,
2172 }
2173 );
2174 stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2175 try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2041 const node = try arena.construct(ast.Node.InfixOp{
2042 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2043 .lhs = lhs,
2044 .op_token = token_index,
2045 .op = mult_id,
2046 .rhs = undefined,
2047 });
2048 opt_ctx.store(&node.base);
2049 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2050 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
21762051 continue;
21772052 } else {
2178 putBackToken(&tok_it, &tree);
2053 prevToken(&tok_it, &tree);
21792054 continue;
21802055 }
21812056 },
21822057
21832058 State.CurlySuffixExpressionBegin => |opt_ctx| {
2184 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable;
2185 try stack.append(State { .IfToken = Token.Id.LBrace });
2186 try stack.append(State { .TypeExprBegin = opt_ctx });
2059 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable;
2060 try stack.append(State{ .IfToken = Token.Id.LBrace });
2061 try stack.append(State{ .TypeExprBegin = opt_ctx });
21872062 continue;
21882063 },
21892064
......@@ -2191,52 +2066,43 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
21912066 const lhs = opt_ctx.get() ?? continue;
21922067
21932068 if ((??tok_it.peek()).id == Token.Id.Period) {
2194 const node = try arena.construct(ast.Node.SuffixOp {
2195 .base = ast.Node { .id = ast.Node.Id.SuffixOp },
2069 const node = try arena.construct(ast.Node.SuffixOp{
2070 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
21962071 .lhs = lhs,
2197 .op = ast.Node.SuffixOp.Op {
2198 .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena),
2199 },
2072 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
22002073 .rtoken = undefined,
22012074 });
22022075 opt_ctx.store(&node.base);
22032076
2204 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2205 try stack.append(State { .IfToken = Token.Id.LBrace });
2206 try stack.append(State {
2207 .FieldInitListItemOrEnd = ListSave(@typeOf(node.op.StructInitializer)) {
2208 .list = &node.op.StructInitializer,
2209 .ptr = &node.rtoken,
2210 }
2211 });
2077 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2078 try stack.append(State{ .IfToken = Token.Id.LBrace });
2079 try stack.append(State{ .FieldInitListItemOrEnd = ListSave(@typeOf(node.op.StructInitializer)){
2080 .list = &node.op.StructInitializer,
2081 .ptr = &node.rtoken,
2082 } });
22122083 continue;
22132084 }
22142085
2215 const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp,
2216 ast.Node.SuffixOp {
2217 .base = undefined,
2218 .lhs = lhs,
2219 .op = ast.Node.SuffixOp.Op {
2220 .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena),
2221 },
2222 .rtoken = undefined,
2223 }
2224 );
2225 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2226 try stack.append(State { .IfToken = Token.Id.LBrace });
2227 try stack.append(State {
2228 .ExprListItemOrEnd = ExprListCtx {
2229 .list = &node.op.ArrayInitializer,
2230 .end = Token.Id.RBrace,
2231 .ptr = &node.rtoken,
2232 }
2086 const node = try arena.construct(ast.Node.SuffixOp{
2087 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2088 .lhs = lhs,
2089 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
2090 .rtoken = undefined,
22332091 });
2092 opt_ctx.store(&node.base);
2093 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2094 try stack.append(State{ .IfToken = Token.Id.LBrace });
2095 try stack.append(State{ .ExprListItemOrEnd = ExprListCtx{
2096 .list = &node.op.ArrayInitializer,
2097 .end = Token.Id.RBrace,
2098 .ptr = &node.rtoken,
2099 } });
22342100 continue;
22352101 },
22362102
22372103 State.TypeExprBegin => |opt_ctx| {
2238 stack.append(State { .TypeExprEnd = opt_ctx }) catch unreachable;
2239 try stack.append(State { .PrefixOpExpression = opt_ctx });
2104 stack.append(State{ .TypeExprEnd = opt_ctx }) catch unreachable;
2105 try stack.append(State{ .PrefixOpExpression = opt_ctx });
22402106 continue;
22412107 },
22422108
......@@ -2244,17 +2110,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
22442110 const lhs = opt_ctx.get() ?? continue;
22452111
22462112 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {
2247 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2248 ast.Node.InfixOp {
2249 .base = undefined,
2250 .lhs = lhs,
2251 .op_token = bang,
2252 .op = ast.Node.InfixOp.Op.ErrorUnion,
2253 .rhs = undefined,
2254 }
2255 );
2256 stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2257 try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } });
2113 const node = try arena.construct(ast.Node.InfixOp{
2114 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2115 .lhs = lhs,
2116 .op_token = bang,
2117 .op = ast.Node.InfixOp.Op.ErrorUnion,
2118 .rhs = undefined,
2119 });
2120 opt_ctx.store(&node.base);
2121 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2122 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });
22582123 continue;
22592124 }
22602125 },
......@@ -2264,65 +2129,58 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
22642129 const token_index = token.index;
22652130 const token_ptr = token.ptr;
22662131 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
2267 var node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp,
2268 ast.Node.PrefixOp {
2269 .base = undefined,
2270 .op_token = token_index,
2271 .op = prefix_id,
2272 .rhs = undefined,
2273 }
2274 );
2132 var node = try arena.construct(ast.Node.PrefixOp{
2133 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2134 .op_token = token_index,
2135 .op = prefix_id,
2136 .rhs = undefined,
2137 });
2138 opt_ctx.store(&node.base);
22752139
22762140 // Treat '**' token as two derefs
22772141 if (token_ptr.id == Token.Id.AsteriskAsterisk) {
2278 const child = try createNode(arena, ast.Node.PrefixOp,
2279 ast.Node.PrefixOp {
2280 .base = undefined,
2281 .op_token = token_index,
2282 .op = prefix_id,
2283 .rhs = undefined,
2284 }
2285 );
2142 const child = try arena.construct(ast.Node.PrefixOp{
2143 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2144 .op_token = token_index,
2145 .op = prefix_id,
2146 .rhs = undefined,
2147 });
22862148 node.rhs = &child.base;
22872149 node = child;
22882150 }
22892151
2290 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
2152 stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
22912153 if (node.op == ast.Node.PrefixOp.Op.AddrOf) {
2292 try stack.append(State { .AddrOfModifiers = &node.op.AddrOf });
2154 try stack.append(State{ .AddrOfModifiers = &node.op.AddrOf });
22932155 }
22942156 continue;
22952157 } else {
2296 putBackToken(&tok_it, &tree);
2297 stack.append(State { .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;
2158 prevToken(&tok_it, &tree);
2159 stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;
22982160 continue;
22992161 }
23002162 },
23012163
23022164 State.SuffixOpExpressionBegin => |opt_ctx| {
23032165 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {
2304 const async_node = try createNode(arena, ast.Node.AsyncAttribute,
2305 ast.Node.AsyncAttribute {
2306 .base = undefined,
2307 .async_token = async_token,
2308 .allocator_type = null,
2309 .rangle_bracket = null,
2310 }
2311 );
2312 stack.append(State {
2313 .AsyncEnd = AsyncEndCtx {
2314 .ctx = opt_ctx,
2315 .attribute = async_node,
2316 }
2317 }) catch unreachable;
2318 try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() });
2319 try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() });
2320 try stack.append(State { .AsyncAllocator = async_node });
2166 const async_node = try arena.construct(ast.Node.AsyncAttribute{
2167 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
2168 .async_token = async_token,
2169 .allocator_type = null,
2170 .rangle_bracket = null,
2171 });
2172 stack.append(State{ .AsyncEnd = AsyncEndCtx{
2173 .ctx = opt_ctx,
2174 .attribute = async_node,
2175 } }) catch unreachable;
2176 try stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() });
2177 try stack.append(State{ .PrimaryExpression = opt_ctx.toRequired() });
2178 try stack.append(State{ .AsyncAllocator = async_node });
23212179 continue;
23222180 }
23232181
2324 stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable;
2325 try stack.append(State { .PrimaryExpression = opt_ctx });
2182 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx }) catch unreachable;
2183 try stack.append(State{ .PrimaryExpression = opt_ctx });
23262184 continue;
23272185 },
23282186
......@@ -2334,61 +2192,66 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
23342192 const token_ptr = token.ptr;
23352193 switch (token_ptr.id) {
23362194 Token.Id.LParen => {
2337 const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp,
2338 ast.Node.SuffixOp {
2339 .base = undefined,
2340 .lhs = lhs,
2341 .op = ast.Node.SuffixOp.Op {
2342 .Call = ast.Node.SuffixOp.Op.Call {
2343 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena),
2344 .async_attr = null,
2345 }
2346 },
2347 .rtoken = undefined,
2348 }
2349 );
2350 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2351 try stack.append(State {
2352 .ExprListItemOrEnd = ExprListCtx {
2353 .list = &node.op.Call.params,
2354 .end = Token.Id.RParen,
2355 .ptr = &node.rtoken,
2356 }
2195 const node = try arena.construct(ast.Node.SuffixOp{
2196 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2197 .lhs = lhs,
2198 .op = ast.Node.SuffixOp.Op{ .Call = ast.Node.SuffixOp.Op.Call{
2199 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena),
2200 .async_attr = null,
2201 } },
2202 .rtoken = undefined,
23572203 });
2204 opt_ctx.store(&node.base);
2205
2206 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2207 try stack.append(State{ .ExprListItemOrEnd = ExprListCtx{
2208 .list = &node.op.Call.params,
2209 .end = Token.Id.RParen,
2210 .ptr = &node.rtoken,
2211 } });
23582212 continue;
23592213 },
23602214 Token.Id.LBracket => {
2361 const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp,
2362 ast.Node.SuffixOp {
2363 .base = undefined,
2364 .lhs = lhs,
2365 .op = ast.Node.SuffixOp.Op {
2366 .ArrayAccess = undefined,
2367 },
2368 .rtoken = undefined
2369 }
2370 );
2371 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2372 try stack.append(State { .SliceOrArrayAccess = node });
2373 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }});
2215 const node = try arena.construct(ast.Node.SuffixOp{
2216 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2217 .lhs = lhs,
2218 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },
2219 .rtoken = undefined,
2220 });
2221 opt_ctx.store(&node.base);
2222
2223 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2224 try stack.append(State{ .SliceOrArrayAccess = node });
2225 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayAccess } });
23742226 continue;
23752227 },
23762228 Token.Id.Period => {
2377 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2378 ast.Node.InfixOp {
2379 .base = undefined,
2229 if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {
2230 const node = try arena.construct(ast.Node.SuffixOp{
2231 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23802232 .lhs = lhs,
2381 .op_token = token_index,
2382 .op = ast.Node.InfixOp.Op.Period,
2383 .rhs = undefined,
2384 }
2385 );
2386 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2387 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } });
2233 .op = ast.Node.SuffixOp.Op.Deref,
2234 .rtoken = asterisk_token,
2235 });
2236 opt_ctx.store(&node.base);
2237 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2238 continue;
2239 }
2240 const node = try arena.construct(ast.Node.InfixOp{
2241 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2242 .lhs = lhs,
2243 .op_token = token_index,
2244 .op = ast.Node.InfixOp.Op.Period,
2245 .rhs = undefined,
2246 });
2247 opt_ctx.store(&node.base);
2248
2249 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2250 try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } });
23882251 continue;
23892252 },
23902253 else => {
2391 putBackToken(&tok_it, &tree);
2254 prevToken(&tok_it, &tree);
23922255 continue;
23932256 },
23942257 }
......@@ -2413,7 +2276,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
24132276 _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.UndefinedLiteral, token.index);
24142277 continue;
24152278 },
2416 Token.Id.Keyword_true, Token.Id.Keyword_false => {
2279 Token.Id.Keyword_true,
2280 Token.Id.Keyword_false => {
24172281 _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.BoolLiteral, token.index);
24182282 continue;
24192283 },
......@@ -2434,10 +2298,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
24342298 continue;
24352299 },
24362300 Token.Id.Keyword_promise => {
2437 const node = try arena.construct(ast.Node.PromiseType {
2438 .base = ast.Node {
2439 .id = ast.Node.Id.PromiseType,
2440 },
2301 const node = try arena.construct(ast.Node.PromiseType{
2302 .base = ast.Node{ .id = ast.Node.Id.PromiseType },
24412303 .promise_token = token.index,
24422304 .result = null,
24432305 });
......@@ -2446,124 +2308,109 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
24462308 const next_token_index = next_token.index;
24472309 const next_token_ptr = next_token.ptr;
24482310 if (next_token_ptr.id != Token.Id.Arrow) {
2449 putBackToken(&tok_it, &tree);
2311 prevToken(&tok_it, &tree);
24502312 continue;
24512313 }
2452 node.result = ast.Node.PromiseType.Result {
2314 node.result = ast.Node.PromiseType.Result{
24532315 .arrow_token = next_token_index,
24542316 .return_type = undefined,
24552317 };
24562318 const return_type_ptr = &((??node.result).return_type);
2457 try stack.append(State { .Expression = OptionalCtx { .Required = return_type_ptr, } });
2319 try stack.append(State{ .Expression = OptionalCtx{ .Required = return_type_ptr } });
24582320 continue;
24592321 },
2460 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
2322 Token.Id.StringLiteral,
2323 Token.Id.MultilineStringLiteralLine => {
24612324 opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, &tree)) ?? unreachable);
24622325 continue;
24632326 },
24642327 Token.Id.LParen => {
2465 const node = try createToCtxNode(arena, opt_ctx, ast.Node.GroupedExpression,
2466 ast.Node.GroupedExpression {
2467 .base = undefined,
2468 .lparen = token.index,
2469 .expr = undefined,
2470 .rparen = undefined,
2471 }
2472 );
2473 stack.append(State {
2474 .ExpectTokenSave = ExpectTokenSave {
2475 .id = Token.Id.RParen,
2476 .ptr = &node.rparen,
2477 }
2478 }) catch unreachable;
2479 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2328 const node = try arena.construct(ast.Node.GroupedExpression{
2329 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },
2330 .lparen = token.index,
2331 .expr = undefined,
2332 .rparen = undefined,
2333 });
2334 opt_ctx.store(&node.base);
2335
2336 stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
2337 .id = Token.Id.RParen,
2338 .ptr = &node.rparen,
2339 } }) catch unreachable;
2340 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
24802341 continue;
24812342 },
24822343 Token.Id.Builtin => {
2483 const node = try createToCtxNode(arena, opt_ctx, ast.Node.BuiltinCall,
2484 ast.Node.BuiltinCall {
2485 .base = undefined,
2486 .builtin_token = token.index,
2487 .params = ast.Node.BuiltinCall.ParamList.init(arena),
2488 .rparen_token = undefined,
2489 }
2490 );
2491 stack.append(State {
2492 .ExprListItemOrEnd = ExprListCtx {
2493 .list = &node.params,
2494 .end = Token.Id.RParen,
2495 .ptr = &node.rparen_token,
2496 }
2497 }) catch unreachable;
2498 try stack.append(State { .ExpectToken = Token.Id.LParen, });
2344 const node = try arena.construct(ast.Node.BuiltinCall{
2345 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
2346 .builtin_token = token.index,
2347 .params = ast.Node.BuiltinCall.ParamList.init(arena),
2348 .rparen_token = undefined,
2349 });
2350 opt_ctx.store(&node.base);
2351
2352 stack.append(State{ .ExprListItemOrEnd = ExprListCtx{
2353 .list = &node.params,
2354 .end = Token.Id.RParen,
2355 .ptr = &node.rparen_token,
2356 } }) catch unreachable;
2357 try stack.append(State{ .ExpectToken = Token.Id.LParen });
24992358 continue;
25002359 },
25012360 Token.Id.LBracket => {
2502 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp,
2503 ast.Node.PrefixOp {
2504 .base = undefined,
2505 .op_token = token.index,
2506 .op = undefined,
2507 .rhs = undefined,
2508 }
2509 );
2510 stack.append(State { .SliceOrArrayType = node }) catch unreachable;
2361 const node = try arena.construct(ast.Node.PrefixOp{
2362 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2363 .op_token = token.index,
2364 .op = undefined,
2365 .rhs = undefined,
2366 });
2367 opt_ctx.store(&node.base);
2368
2369 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;
25112370 continue;
25122371 },
25132372 Token.Id.Keyword_error => {
2514 stack.append(State {
2515 .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx {
2516 .error_token = token.index,
2517 .opt_ctx = opt_ctx
2518 }
2519 }) catch unreachable;
2373 stack.append(State{ .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx{
2374 .error_token = token.index,
2375 .opt_ctx = opt_ctx,
2376 } }) catch unreachable;
25202377 continue;
25212378 },
25222379 Token.Id.Keyword_packed => {
2523 stack.append(State {
2524 .ContainerKind = ContainerKindCtx {
2525 .opt_ctx = opt_ctx,
2526 .ltoken = token.index,
2527 .layout = ast.Node.ContainerDecl.Layout.Packed,
2528 },
2529 }) catch unreachable;
2380 stack.append(State{ .ContainerKind = ContainerKindCtx{
2381 .opt_ctx = opt_ctx,
2382 .layout_token = token.index,
2383 } }) catch unreachable;
25302384 continue;
25312385 },
25322386 Token.Id.Keyword_extern => {
2533 stack.append(State {
2534 .ExternType = ExternTypeCtx {
2535 .opt_ctx = opt_ctx,
2536 .extern_token = token.index,
2537 .comments = null,
2538 },
2539 }) catch unreachable;
2387 stack.append(State{ .ExternType = ExternTypeCtx{
2388 .opt_ctx = opt_ctx,
2389 .extern_token = token.index,
2390 .comments = null,
2391 } }) catch unreachable;
25402392 continue;
25412393 },
2542 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
2543 putBackToken(&tok_it, &tree);
2544 stack.append(State {
2545 .ContainerKind = ContainerKindCtx {
2546 .opt_ctx = opt_ctx,
2547 .ltoken = token.index,
2548 .layout = ast.Node.ContainerDecl.Layout.Auto,
2549 },
2550 }) catch unreachable;
2394 Token.Id.Keyword_struct,
2395 Token.Id.Keyword_union,
2396 Token.Id.Keyword_enum => {
2397 prevToken(&tok_it, &tree);
2398 stack.append(State{ .ContainerKind = ContainerKindCtx{
2399 .opt_ctx = opt_ctx,
2400 .layout_token = null,
2401 } }) catch unreachable;
25512402 continue;
25522403 },
25532404 Token.Id.Identifier => {
2554 stack.append(State {
2555 .MaybeLabeledExpression = MaybeLabeledExpressionCtx {
2556 .label = token.index,
2557 .opt_ctx = opt_ctx
2558 }
2559 }) catch unreachable;
2405 stack.append(State{ .MaybeLabeledExpression = MaybeLabeledExpressionCtx{
2406 .label = token.index,
2407 .opt_ctx = opt_ctx,
2408 } }) catch unreachable;
25602409 continue;
25612410 },
25622411 Token.Id.Keyword_fn => {
2563 const fn_proto = try arena.construct(ast.Node.FnProto {
2564 .base = ast.Node {
2565 .id = ast.Node.Id.FnProto,
2566 },
2412 const fn_proto = try arena.construct(ast.Node.FnProto{
2413 .base = ast.Node{ .id = ast.Node.Id.FnProto },
25672414 .doc_comments = null,
25682415 .visib_token = null,
25692416 .name_token = null,
......@@ -2579,14 +2426,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
25792426 .align_expr = null,
25802427 });
25812428 opt_ctx.store(&fn_proto.base);
2582 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2429 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
25832430 continue;
25842431 },
2585 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
2586 const fn_proto = try arena.construct(ast.Node.FnProto {
2587 .base = ast.Node {
2588 .id = ast.Node.Id.FnProto,
2589 },
2432 Token.Id.Keyword_nakedcc,
2433 Token.Id.Keyword_stdcallcc => {
2434 const fn_proto = try arena.construct(ast.Node.FnProto{
2435 .base = ast.Node{ .id = ast.Node.Id.FnProto },
25902436 .doc_comments = null,
25912437 .visib_token = null,
25922438 .name_token = null,
......@@ -2602,116 +2448,97 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
26022448 .align_expr = null,
26032449 });
26042450 opt_ctx.store(&fn_proto.base);
2605 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2606 try stack.append(State {
2607 .ExpectTokenSave = ExpectTokenSave {
2608 .id = Token.Id.Keyword_fn,
2609 .ptr = &fn_proto.fn_token
2610 }
2611 });
2451 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
2452 try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
2453 .id = Token.Id.Keyword_fn,
2454 .ptr = &fn_proto.fn_token,
2455 } });
26122456 continue;
26132457 },
26142458 Token.Id.Keyword_asm => {
2615 const node = try createToCtxNode(arena, opt_ctx, ast.Node.Asm,
2616 ast.Node.Asm {
2617 .base = undefined,
2618 .asm_token = token.index,
2619 .volatile_token = null,
2620 .template = undefined,
2621 .outputs = ast.Node.Asm.OutputList.init(arena),
2622 .inputs = ast.Node.Asm.InputList.init(arena),
2623 .clobbers = ast.Node.Asm.ClobberList.init(arena),
2624 .rparen = undefined,
2625 }
2626 );
2627 stack.append(State {
2628 .ExpectTokenSave = ExpectTokenSave {
2629 .id = Token.Id.RParen,
2630 .ptr = &node.rparen,
2631 }
2632 }) catch unreachable;
2633 try stack.append(State { .AsmClobberItems = &node.clobbers });
2634 try stack.append(State { .IfToken = Token.Id.Colon });
2635 try stack.append(State { .AsmInputItems = &node.inputs });
2636 try stack.append(State { .IfToken = Token.Id.Colon });
2637 try stack.append(State { .AsmOutputItems = &node.outputs });
2638 try stack.append(State { .IfToken = Token.Id.Colon });
2639 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.template } });
2640 try stack.append(State { .ExpectToken = Token.Id.LParen });
2641 try stack.append(State {
2642 .OptionalTokenSave = OptionalTokenSave {
2643 .id = Token.Id.Keyword_volatile,
2644 .ptr = &node.volatile_token,
2645 }
2459 const node = try arena.construct(ast.Node.Asm{
2460 .base = ast.Node{ .id = ast.Node.Id.Asm },
2461 .asm_token = token.index,
2462 .volatile_token = null,
2463 .template = undefined,
2464 .outputs = ast.Node.Asm.OutputList.init(arena),
2465 .inputs = ast.Node.Asm.InputList.init(arena),
2466 .clobbers = ast.Node.Asm.ClobberList.init(arena),
2467 .rparen = undefined,
26462468 });
2469 opt_ctx.store(&node.base);
2470
2471 stack.append(State{ .ExpectTokenSave = ExpectTokenSave{
2472 .id = Token.Id.RParen,
2473 .ptr = &node.rparen,
2474 } }) catch unreachable;
2475 try stack.append(State{ .AsmClobberItems = &node.clobbers });
2476 try stack.append(State{ .IfToken = Token.Id.Colon });
2477 try stack.append(State{ .AsmInputItems = &node.inputs });
2478 try stack.append(State{ .IfToken = Token.Id.Colon });
2479 try stack.append(State{ .AsmOutputItems = &node.outputs });
2480 try stack.append(State{ .IfToken = Token.Id.Colon });
2481 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.template } });
2482 try stack.append(State{ .ExpectToken = Token.Id.LParen });
2483 try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{
2484 .id = Token.Id.Keyword_volatile,
2485 .ptr = &node.volatile_token,
2486 } });
26472487 },
26482488 Token.Id.Keyword_inline => {
2649 stack.append(State {
2650 .Inline = InlineCtx {
2651 .label = null,
2652 .inline_token = token.index,
2653 .opt_ctx = opt_ctx,
2654 }
2655 }) catch unreachable;
2489 stack.append(State{ .Inline = InlineCtx{
2490 .label = null,
2491 .inline_token = token.index,
2492 .opt_ctx = opt_ctx,
2493 } }) catch unreachable;
26562494 continue;
26572495 },
26582496 else => {
26592497 if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr, token.index)) {
2660 putBackToken(&tok_it, &tree);
2498 prevToken(&tok_it, &tree);
26612499 if (opt_ctx != OptionalCtx.Optional) {
2662 *(try tree.errors.addOne()) = Error {
2663 .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr { .token = token.index },
2664 };
2500 ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } };
26652501 return tree;
26662502 }
26672503 }
26682504 continue;
2669 }
2505 },
26702506 }
26712507 },
26722508
2673
26742509 State.ErrorTypeOrSetDecl => |ctx| {
26752510 if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {
26762511 _ = try createToCtxLiteral(arena, ctx.opt_ctx, ast.Node.ErrorType, ctx.error_token);
26772512 continue;
26782513 }
26792514
2680 const node = try arena.construct(ast.Node.ErrorSetDecl {
2681 .base = ast.Node {
2682 .id = ast.Node.Id.ErrorSetDecl,
2683 },
2515 const node = try arena.construct(ast.Node.ErrorSetDecl{
2516 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },
26842517 .error_token = ctx.error_token,
26852518 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),
26862519 .rbrace_token = undefined,
26872520 });
26882521 ctx.opt_ctx.store(&node.base);
26892522
2690 stack.append(State {
2691 .ErrorTagListItemOrEnd = ListSave(@typeOf(node.decls)) {
2692 .list = &node.decls,
2693 .ptr = &node.rbrace_token,
2694 }
2695 }) catch unreachable;
2523 stack.append(State{ .ErrorTagListItemOrEnd = ListSave(@typeOf(node.decls)){
2524 .list = &node.decls,
2525 .ptr = &node.rbrace_token,
2526 } }) catch unreachable;
26962527 continue;
26972528 },
26982529 State.StringLiteral => |opt_ctx| {
26992530 const token = nextToken(&tok_it, &tree);
27002531 const token_index = token.index;
27012532 const token_ptr = token.ptr;
2702 opt_ctx.store(
2703 (try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? {
2704 putBackToken(&tok_it, &tree);
2705 if (opt_ctx != OptionalCtx.Optional) {
2706 *(try tree.errors.addOne()) = Error {
2707 .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr { .token = token_index },
2708 };
2709 return tree;
2710 }
2711
2712 continue;
2533 opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? {
2534 prevToken(&tok_it, &tree);
2535 if (opt_ctx != OptionalCtx.Optional) {
2536 ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } };
2537 return tree;
27132538 }
2714 );
2539
2540 continue;
2541 });
27152542 },
27162543
27172544 State.Identifier => |opt_ctx| {
......@@ -2724,12 +2551,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
27242551 const token = nextToken(&tok_it, &tree);
27252552 const token_index = token.index;
27262553 const token_ptr = token.ptr;
2727 *(try tree.errors.addOne()) = Error {
2728 .ExpectedToken = Error.ExpectedToken {
2729 .token = token_index,
2730 .expected_id = Token.Id.Identifier,
2731 },
2732 };
2554 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
2555 .token = token_index,
2556 .expected_id = Token.Id.Identifier,
2557 } };
27332558 return tree;
27342559 }
27352560 },
......@@ -2740,23 +2565,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
27402565 const ident_token_index = ident_token.index;
27412566 const ident_token_ptr = ident_token.ptr;
27422567 if (ident_token_ptr.id != Token.Id.Identifier) {
2743 *(try tree.errors.addOne()) = Error {
2744 .ExpectedToken = Error.ExpectedToken {
2745 .token = ident_token_index,
2746 .expected_id = Token.Id.Identifier,
2747 },
2748 };
2568 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
2569 .token = ident_token_index,
2570 .expected_id = Token.Id.Identifier,
2571 } };
27492572 return tree;
27502573 }
27512574
2752 const node = try arena.construct(ast.Node.ErrorTag {
2753 .base = ast.Node {
2754 .id = ast.Node.Id.ErrorTag,
2755 },
2575 const node = try arena.construct(ast.Node.ErrorTag{
2576 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },
27562577 .doc_comments = comments,
27572578 .name_token = ident_token_index,
27582579 });
2759 *node_ptr = &node.base;
2580 node_ptr.* = &node.base;
27602581 continue;
27612582 },
27622583
......@@ -2765,12 +2586,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
27652586 const token_index = token.index;
27662587 const token_ptr = token.ptr;
27672588 if (token_ptr.id != token_id) {
2768 *(try tree.errors.addOne()) = Error {
2769 .ExpectedToken = Error.ExpectedToken {
2770 .token = token_index,
2771 .expected_id = token_id,
2772 },
2773 };
2589 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
2590 .token = token_index,
2591 .expected_id = token_id,
2592 } };
27742593 return tree;
27752594 }
27762595 continue;
......@@ -2780,15 +2599,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
27802599 const token_index = token.index;
27812600 const token_ptr = token.ptr;
27822601 if (token_ptr.id != expect_token_save.id) {
2783 *(try tree.errors.addOne()) = Error {
2784 .ExpectedToken = Error.ExpectedToken {
2785 .token = token_index,
2786 .expected_id = expect_token_save.id,
2787 },
2788 };
2602 ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{
2603 .token = token_index,
2604 .expected_id = expect_token_save.id,
2605 } };
27892606 return tree;
27902607 }
2791 *expect_token_save.ptr = token_index;
2608 expect_token_save.ptr.* = token_index;
27922609 continue;
27932610 },
27942611 State.IfToken => |token_id| {
......@@ -2801,7 +2618,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
28012618 },
28022619 State.IfTokenSave => |if_token_save| {
28032620 if (eatToken(&tok_it, &tree, if_token_save.id)) |token_index| {
2804 *if_token_save.ptr = token_index;
2621 (if_token_save.ptr).* = token_index;
28052622 continue;
28062623 }
28072624
......@@ -2810,7 +2627,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
28102627 },
28112628 State.OptionalTokenSave => |optional_token_save| {
28122629 if (eatToken(&tok_it, &tree, optional_token_save.id)) |token_index| {
2813 *optional_token_save.ptr = token_index;
2630 (optional_token_save.ptr).* = token_index;
28142631 continue;
28152632 }
28162633
......@@ -2857,8 +2674,7 @@ const ExternTypeCtx = struct {
28572674
28582675const ContainerKindCtx = struct {
28592676 opt_ctx: OptionalCtx,
2860 ltoken: TokenIndex,
2861 layout: ast.Node.ContainerDecl.Layout,
2677 layout_token: ?TokenIndex,
28622678};
28632679
28642680const ExpectTokenSave = struct {
......@@ -2933,28 +2749,28 @@ const OptionalCtx = union(enum) {
29332749 Required: &&ast.Node,
29342750
29352751 pub fn store(self: &const OptionalCtx, value: &ast.Node) void {
2936 switch (*self) {
2937 OptionalCtx.Optional => |ptr| *ptr = value,
2938 OptionalCtx.RequiredNull => |ptr| *ptr = value,
2939 OptionalCtx.Required => |ptr| *ptr = value,
2752 switch (self.*) {
2753 OptionalCtx.Optional => |ptr| ptr.* = value,
2754 OptionalCtx.RequiredNull => |ptr| ptr.* = value,
2755 OptionalCtx.Required => |ptr| ptr.* = value,
29402756 }
29412757 }
29422758
29432759 pub fn get(self: &const OptionalCtx) ?&ast.Node {
2944 switch (*self) {
2945 OptionalCtx.Optional => |ptr| return *ptr,
2946 OptionalCtx.RequiredNull => |ptr| return ??*ptr,
2947 OptionalCtx.Required => |ptr| return *ptr,
2760 switch (self.*) {
2761 OptionalCtx.Optional => |ptr| return ptr.*,
2762 OptionalCtx.RequiredNull => |ptr| return ??ptr.*,
2763 OptionalCtx.Required => |ptr| return ptr.*,
29482764 }
29492765 }
29502766
29512767 pub fn toRequired(self: &const OptionalCtx) OptionalCtx {
2952 switch (*self) {
2768 switch (self.*) {
29532769 OptionalCtx.Optional => |ptr| {
2954 return OptionalCtx { .RequiredNull = ptr };
2770 return OptionalCtx{ .RequiredNull = ptr };
29552771 },
2956 OptionalCtx.RequiredNull => |ptr| return *self,
2957 OptionalCtx.Required => |ptr| return *self,
2772 OptionalCtx.RequiredNull => |ptr| return self.*,
2773 OptionalCtx.Required => |ptr| return self.*,
29582774 }
29592775 }
29602776};
......@@ -2979,6 +2795,7 @@ const State = union(enum) {
29792795 VarDecl: VarDeclCtx,
29802796 VarDeclAlign: &ast.Node.VarDecl,
29812797 VarDeclEq: &ast.Node.VarDecl,
2798 VarDeclSemiColon: &ast.Node.VarDecl,
29822799
29832800 FnDef: &ast.Node.FnProto,
29842801 FnProto: &ast.Node.FnProto,
......@@ -3019,9 +2836,9 @@ const State = union(enum) {
30192836 ErrorTagListCommaOrEnd: ListSave(ast.Node.ErrorSetDecl.DeclList),
30202837 SwitchCaseOrEnd: ListSave(ast.Node.Switch.CaseList),
30212838 SwitchCaseCommaOrEnd: ListSave(ast.Node.Switch.CaseList),
3022 SwitchCaseFirstItem: &ast.Node.SwitchCase.ItemList,
3023 SwitchCaseItem: &ast.Node.SwitchCase.ItemList,
3024 SwitchCaseItemCommaOrEnd: &ast.Node.SwitchCase.ItemList,
2839 SwitchCaseFirstItem: &ast.Node.SwitchCase,
2840 SwitchCaseItemCommaOrEnd: &ast.Node.SwitchCase,
2841 SwitchCaseItemOrEnd: &ast.Node.SwitchCase,
30252842
30262843 SuspendBody: &ast.Node.Suspend,
30272844 AsyncAllocator: &ast.Node.AsyncAttribute,
......@@ -3031,6 +2848,7 @@ const State = union(enum) {
30312848 SliceOrArrayAccess: &ast.Node.SuffixOp,
30322849 SliceOrArrayType: &ast.Node.PrefixOp,
30332850 AddrOfModifiers: &ast.Node.PrefixOp.AddrOfInfo,
2851 AlignBitRange: &ast.Node.PrefixOp.AddrOfInfo.Align,
30342852
30352853 Payload: OptionalCtx,
30362854 PointerPayload: OptionalCtx,
......@@ -3075,7 +2893,6 @@ const State = union(enum) {
30752893 Identifier: OptionalCtx,
30762894 ErrorTag: &&ast.Node,
30772895
3078
30792896 IfToken: @TagType(Token.Id),
30802897 IfTokenSave: ExpectTokenSave,
30812898 ExpectToken: @TagType(Token.Id),
......@@ -3083,25 +2900,27 @@ const State = union(enum) {
30832900 OptionalTokenSave: OptionalTokenSave,
30842901};
30852902
2903fn pushDocComment(arena: &mem.Allocator, line_comment: TokenIndex, result: &?&ast.Node.DocComment) !void {
2904 const node = blk: {
2905 if (result.*) |comment_node| {
2906 break :blk comment_node;
2907 } else {
2908 const comment_node = try arena.construct(ast.Node.DocComment{
2909 .base = ast.Node{ .id = ast.Node.Id.DocComment },
2910 .lines = ast.Node.DocComment.LineList.init(arena),
2911 });
2912 result.* = comment_node;
2913 break :blk comment_node;
2914 }
2915 };
2916 try node.lines.push(line_comment);
2917}
2918
30862919fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.DocComment {
30872920 var result: ?&ast.Node.DocComment = null;
30882921 while (true) {
30892922 if (eatToken(tok_it, tree, Token.Id.DocComment)) |line_comment| {
3090 const node = blk: {
3091 if (result) |comment_node| {
3092 break :blk comment_node;
3093 } else {
3094 const comment_node = try arena.construct(ast.Node.DocComment {
3095 .base = ast.Node {
3096 .id = ast.Node.Id.DocComment,
3097 },
3098 .lines = ast.Node.DocComment.LineList.init(arena),
3099 });
3100 result = comment_node;
3101 break :blk comment_node;
3102 }
3103 };
3104 try node.lines.push(line_comment);
2923 try pushDocComment(arena, line_comment, &result);
31052924 continue;
31062925 }
31072926 break;
......@@ -3109,26 +2928,14 @@ fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, t
31092928 return result;
31102929}
31112930
3112fn eatLineComment(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.LineComment {
3113 const token = eatToken(tok_it, tree, Token.Id.LineComment) ?? return null;
3114 return try arena.construct(ast.Node.LineComment {
3115 .base = ast.Node {
3116 .id = ast.Node.Id.LineComment,
3117 },
3118 .token = token,
3119 });
3120}
3121
3122fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator,
3123 token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node
3124{
2931fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node {
31252932 switch (token_ptr.id) {
31262933 Token.Id.StringLiteral => {
31272934 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;
31282935 },
31292936 Token.Id.MultilineStringLiteralLine => {
3130 const node = try arena.construct(ast.Node.MultilineStringLiteral {
3131 .base = ast.Node { .id = ast.Node.Id.MultilineStringLiteral },
2937 const node = try arena.construct(ast.Node.MultilineStringLiteral{
2938 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },
31322939 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),
31332940 });
31342941 try node.lines.push(token_index);
......@@ -3137,7 +2944,7 @@ fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterato
31372944 const multiline_str_index = multiline_str.index;
31382945 const multiline_str_ptr = multiline_str.ptr;
31392946 if (multiline_str_ptr.id != Token.Id.MultilineStringLiteralLine) {
3140 putBackToken(tok_it, tree);
2947 prevToken(tok_it, tree);
31412948 break;
31422949 }
31432950
......@@ -3152,71 +2959,62 @@ fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterato
31522959 }
31532960}
31542961
3155fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx,
3156 token_ptr: &const Token, token_index: TokenIndex) !bool {
2962fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, token_ptr: &const Token, token_index: TokenIndex) !bool {
31572963 switch (token_ptr.id) {
31582964 Token.Id.Keyword_suspend => {
3159 const node = try createToCtxNode(arena, ctx, ast.Node.Suspend,
3160 ast.Node.Suspend {
3161 .base = undefined,
3162 .label = null,
3163 .suspend_token = token_index,
3164 .payload = null,
3165 .body = null,
3166 }
3167 );
2965 const node = try arena.construct(ast.Node.Suspend{
2966 .base = ast.Node{ .id = ast.Node.Id.Suspend },
2967 .label = null,
2968 .suspend_token = token_index,
2969 .payload = null,
2970 .body = null,
2971 });
2972 ctx.store(&node.base);
31682973
3169 stack.append(State { .SuspendBody = node }) catch unreachable;
3170 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
2974 stack.append(State{ .SuspendBody = node }) catch unreachable;
2975 try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });
31712976 return true;
31722977 },
31732978 Token.Id.Keyword_if => {
3174 const node = try createToCtxNode(arena, ctx, ast.Node.If,
3175 ast.Node.If {
3176 .base = undefined,
3177 .if_token = token_index,
3178 .condition = undefined,
3179 .payload = null,
3180 .body = undefined,
3181 .@"else" = null,
3182 }
3183 );
2979 const node = try arena.construct(ast.Node.If{
2980 .base = ast.Node{ .id = ast.Node.Id.If },
2981 .if_token = token_index,
2982 .condition = undefined,
2983 .payload = null,
2984 .body = undefined,
2985 .@"else" = null,
2986 });
2987 ctx.store(&node.base);
31842988
3185 stack.append(State { .Else = &node.@"else" }) catch unreachable;
3186 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
3187 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
3188 try stack.append(State { .ExpectToken = Token.Id.RParen });
3189 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
3190 try stack.append(State { .ExpectToken = Token.Id.LParen });
2989 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
2990 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
2991 try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } });
2992 try stack.append(State{ .ExpectToken = Token.Id.RParen });
2993 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.condition } });
2994 try stack.append(State{ .ExpectToken = Token.Id.LParen });
31912995 return true;
31922996 },
31932997 Token.Id.Keyword_while => {
3194 stack.append(State {
3195 .While = LoopCtx {
3196 .label = null,
3197 .inline_token = null,
3198 .loop_token = token_index,
3199 .opt_ctx = *ctx,
3200 }
3201 }) catch unreachable;
2998 stack.append(State{ .While = LoopCtx{
2999 .label = null,
3000 .inline_token = null,
3001 .loop_token = token_index,
3002 .opt_ctx = ctx.*,
3003 } }) catch unreachable;
32023004 return true;
32033005 },
32043006 Token.Id.Keyword_for => {
3205 stack.append(State {
3206 .For = LoopCtx {
3207 .label = null,
3208 .inline_token = null,
3209 .loop_token = token_index,
3210 .opt_ctx = *ctx,
3211 }
3212 }) catch unreachable;
3007 stack.append(State{ .For = LoopCtx{
3008 .label = null,
3009 .inline_token = null,
3010 .loop_token = token_index,
3011 .opt_ctx = ctx.*,
3012 } }) catch unreachable;
32133013 return true;
32143014 },
32153015 Token.Id.Keyword_switch => {
3216 const node = try arena.construct(ast.Node.Switch {
3217 .base = ast.Node {
3218 .id = ast.Node.Id.Switch,
3219 },
3016 const node = try arena.construct(ast.Node.Switch{
3017 .base = ast.Node{ .id = ast.Node.Id.Switch },
32203018 .switch_token = token_index,
32213019 .expr = undefined,
32223020 .cases = ast.Node.Switch.CaseList.init(arena),
......@@ -3224,45 +3022,43 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con
32243022 });
32253023 ctx.store(&node.base);
32263024
3227 stack.append(State {
3228 .SwitchCaseOrEnd = ListSave(@typeOf(node.cases)) {
3229 .list = &node.cases,
3230 .ptr = &node.rbrace,
3231 },
3232 }) catch unreachable;
3233 try stack.append(State { .ExpectToken = Token.Id.LBrace });
3234 try stack.append(State { .ExpectToken = Token.Id.RParen });
3235 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
3236 try stack.append(State { .ExpectToken = Token.Id.LParen });
3025 stack.append(State{ .SwitchCaseOrEnd = ListSave(@typeOf(node.cases)){
3026 .list = &node.cases,
3027 .ptr = &node.rbrace,
3028 } }) catch unreachable;
3029 try stack.append(State{ .ExpectToken = Token.Id.LBrace });
3030 try stack.append(State{ .ExpectToken = Token.Id.RParen });
3031 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
3032 try stack.append(State{ .ExpectToken = Token.Id.LParen });
32373033 return true;
32383034 },
32393035 Token.Id.Keyword_comptime => {
3240 const node = try createToCtxNode(arena, ctx, ast.Node.Comptime,
3241 ast.Node.Comptime {
3242 .base = undefined,
3243 .comptime_token = token_index,
3244 .expr = undefined,
3245 .doc_comments = null,
3246 }
3247 );
3248 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
3036 const node = try arena.construct(ast.Node.Comptime{
3037 .base = ast.Node{ .id = ast.Node.Id.Comptime },
3038 .comptime_token = token_index,
3039 .expr = undefined,
3040 .doc_comments = null,
3041 });
3042 ctx.store(&node.base);
3043
3044 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
32493045 return true;
32503046 },
32513047 Token.Id.LBrace => {
3252 const block = try arena.construct(ast.Node.Block {
3253 .base = ast.Node {.id = ast.Node.Id.Block },
3048 const block = try arena.construct(ast.Node.Block{
3049 .base = ast.Node{ .id = ast.Node.Id.Block },
32543050 .label = null,
32553051 .lbrace = token_index,
32563052 .statements = ast.Node.Block.StatementList.init(arena),
32573053 .rbrace = undefined,
32583054 });
32593055 ctx.store(&block.base);
3260 stack.append(State { .Block = block }) catch unreachable;
3056 stack.append(State{ .Block = block }) catch unreachable;
32613057 return true;
32623058 },
32633059 else => {
32643060 return false;
3265 }
3061 },
32663062 }
32673063}
32683064
......@@ -3276,20 +3072,16 @@ fn expectCommaOrEnd(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, end:
32763072 const token_index = token.index;
32773073 const token_ptr = token.ptr;
32783074 switch (token_ptr.id) {
3279 Token.Id.Comma => return ExpectCommaOrEndResult { .end_token = null},
3075 Token.Id.Comma => return ExpectCommaOrEndResult{ .end_token = null },
32803076 else => {
32813077 if (end == token_ptr.id) {
3282 return ExpectCommaOrEndResult { .end_token = token_index };
3078 return ExpectCommaOrEndResult{ .end_token = token_index };
32833079 }
32843080
3285 return ExpectCommaOrEndResult {
3286 .parse_error = Error {
3287 .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd {
3288 .token = token_index,
3289 .end_id = end,
3290 },
3291 },
3292 };
3081 return ExpectCommaOrEndResult{ .parse_error = Error{ .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd{
3082 .token = token_index,
3083 .end_id = end,
3084 } } };
32933085 },
32943086 }
32953087}
......@@ -3297,127 +3089,102 @@ fn expectCommaOrEnd(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, end:
32973089fn tokenIdToAssignment(id: &const Token.Id) ?ast.Node.InfixOp.Op {
32983090 // TODO: We have to cast all cases because of this:
32993091 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
3300 return switch (*id) {
3301 Token.Id.AmpersandEqual => ast.Node.InfixOp.Op { .AssignBitAnd = {} },
3302 Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op { .AssignBitShiftLeft = {} },
3303 Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op { .AssignBitShiftRight = {} },
3304 Token.Id.AsteriskEqual => ast.Node.InfixOp.Op { .AssignTimes = {} },
3305 Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op { .AssignTimesWarp = {} },
3306 Token.Id.CaretEqual => ast.Node.InfixOp.Op { .AssignBitXor = {} },
3307 Token.Id.Equal => ast.Node.InfixOp.Op { .Assign = {} },
3308 Token.Id.MinusEqual => ast.Node.InfixOp.Op { .AssignMinus = {} },
3309 Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op { .AssignMinusWrap = {} },
3310 Token.Id.PercentEqual => ast.Node.InfixOp.Op { .AssignMod = {} },
3311 Token.Id.PipeEqual => ast.Node.InfixOp.Op { .AssignBitOr = {} },
3312 Token.Id.PlusEqual => ast.Node.InfixOp.Op { .AssignPlus = {} },
3313 Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op { .AssignPlusWrap = {} },
3314 Token.Id.SlashEqual => ast.Node.InfixOp.Op { .AssignDiv = {} },
3092 return switch (id.*) {
3093 Token.Id.AmpersandEqual => ast.Node.InfixOp.Op{ .AssignBitAnd = {} },
3094 Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op{ .AssignBitShiftLeft = {} },
3095 Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op{ .AssignBitShiftRight = {} },
3096 Token.Id.AsteriskEqual => ast.Node.InfixOp.Op{ .AssignTimes = {} },
3097 Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op{ .AssignTimesWarp = {} },
3098 Token.Id.CaretEqual => ast.Node.InfixOp.Op{ .AssignBitXor = {} },
3099 Token.Id.Equal => ast.Node.InfixOp.Op{ .Assign = {} },
3100 Token.Id.MinusEqual => ast.Node.InfixOp.Op{ .AssignMinus = {} },
3101 Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op{ .AssignMinusWrap = {} },
3102 Token.Id.PercentEqual => ast.Node.InfixOp.Op{ .AssignMod = {} },
3103 Token.Id.PipeEqual => ast.Node.InfixOp.Op{ .AssignBitOr = {} },
3104 Token.Id.PlusEqual => ast.Node.InfixOp.Op{ .AssignPlus = {} },
3105 Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op{ .AssignPlusWrap = {} },
3106 Token.Id.SlashEqual => ast.Node.InfixOp.Op{ .AssignDiv = {} },
33153107 else => null,
33163108 };
33173109}
33183110
33193111fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
33203112 return switch (id) {
3321 Token.Id.Keyword_catch => ast.Node.InfixOp.Op { .Catch = null },
3322 Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op { .UnwrapMaybe = void{} },
3113 Token.Id.Keyword_catch => ast.Node.InfixOp.Op{ .Catch = null },
3114 Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op{ .UnwrapMaybe = void{} },
33233115 else => null,
33243116 };
33253117}
33263118
33273119fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
33283120 return switch (id) {
3329 Token.Id.BangEqual => ast.Node.InfixOp.Op { .BangEqual = void{} },
3330 Token.Id.EqualEqual => ast.Node.InfixOp.Op { .EqualEqual = void{} },
3331 Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op { .LessThan = void{} },
3332 Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op { .LessOrEqual = void{} },
3333 Token.Id.AngleBracketRight => ast.Node.InfixOp.Op { .GreaterThan = void{} },
3334 Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op { .GreaterOrEqual = void{} },
3121 Token.Id.BangEqual => ast.Node.InfixOp.Op{ .BangEqual = void{} },
3122 Token.Id.EqualEqual => ast.Node.InfixOp.Op{ .EqualEqual = void{} },
3123 Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op{ .LessThan = void{} },
3124 Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op{ .LessOrEqual = void{} },
3125 Token.Id.AngleBracketRight => ast.Node.InfixOp.Op{ .GreaterThan = void{} },
3126 Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op{ .GreaterOrEqual = void{} },
33353127 else => null,
33363128 };
33373129}
33383130
33393131fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
33403132 return switch (id) {
3341 Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op { .BitShiftLeft = void{} },
3342 Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op { .BitShiftRight = void{} },
3133 Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op{ .BitShiftLeft = void{} },
3134 Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op{ .BitShiftRight = void{} },
33433135 else => null,
33443136 };
33453137}
33463138
33473139fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
33483140 return switch (id) {
3349 Token.Id.Minus => ast.Node.InfixOp.Op { .Sub = void{} },
3350 Token.Id.MinusPercent => ast.Node.InfixOp.Op { .SubWrap = void{} },
3351 Token.Id.Plus => ast.Node.InfixOp.Op { .Add = void{} },
3352 Token.Id.PlusPercent => ast.Node.InfixOp.Op { .AddWrap = void{} },
3353 Token.Id.PlusPlus => ast.Node.InfixOp.Op { .ArrayCat = void{} },
3141 Token.Id.Minus => ast.Node.InfixOp.Op{ .Sub = void{} },
3142 Token.Id.MinusPercent => ast.Node.InfixOp.Op{ .SubWrap = void{} },
3143 Token.Id.Plus => ast.Node.InfixOp.Op{ .Add = void{} },
3144 Token.Id.PlusPercent => ast.Node.InfixOp.Op{ .AddWrap = void{} },
3145 Token.Id.PlusPlus => ast.Node.InfixOp.Op{ .ArrayCat = void{} },
33543146 else => null,
33553147 };
33563148}
33573149
33583150fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op {
33593151 return switch (id) {
3360 Token.Id.Slash => ast.Node.InfixOp.Op { .Div = void{} },
3361 Token.Id.Asterisk => ast.Node.InfixOp.Op { .Mult = void{} },
3362 Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op { .ArrayMult = void{} },
3363 Token.Id.AsteriskPercent => ast.Node.InfixOp.Op { .MultWrap = void{} },
3364 Token.Id.Percent => ast.Node.InfixOp.Op { .Mod = void{} },
3365 Token.Id.PipePipe => ast.Node.InfixOp.Op { .MergeErrorSets = void{} },
3152 Token.Id.Slash => ast.Node.InfixOp.Op{ .Div = void{} },
3153 Token.Id.Asterisk => ast.Node.InfixOp.Op{ .Mult = void{} },
3154 Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op{ .ArrayMult = void{} },
3155 Token.Id.AsteriskPercent => ast.Node.InfixOp.Op{ .MultWrap = void{} },
3156 Token.Id.Percent => ast.Node.InfixOp.Op{ .Mod = void{} },
3157 Token.Id.PipePipe => ast.Node.InfixOp.Op{ .MergeErrorSets = void{} },
33663158 else => null,
33673159 };
33683160}
33693161
33703162fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
33713163 return switch (id) {
3372 Token.Id.Bang => ast.Node.PrefixOp.Op { .BoolNot = void{} },
3373 Token.Id.Tilde => ast.Node.PrefixOp.Op { .BitNot = void{} },
3374 Token.Id.Minus => ast.Node.PrefixOp.Op { .Negation = void{} },
3375 Token.Id.MinusPercent => ast.Node.PrefixOp.Op { .NegationWrap = void{} },
3376 Token.Id.Asterisk, Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op { .Deref = void{} },
3377 Token.Id.Ampersand => ast.Node.PrefixOp.Op {
3378 .AddrOf = ast.Node.PrefixOp.AddrOfInfo {
3379 .align_expr = null,
3380 .bit_offset_start_token = null,
3381 .bit_offset_end_token = null,
3382 .const_token = null,
3383 .volatile_token = null,
3384 },
3385 },
3386 Token.Id.QuestionMark => ast.Node.PrefixOp.Op { .MaybeType = void{} },
3387 Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op { .UnwrapMaybe = void{} },
3388 Token.Id.Keyword_await => ast.Node.PrefixOp.Op { .Await = void{} },
3389 Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{ } },
3164 Token.Id.Bang => ast.Node.PrefixOp.Op{ .BoolNot = void{} },
3165 Token.Id.Tilde => ast.Node.PrefixOp.Op{ .BitNot = void{} },
3166 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
3167 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
3168 Token.Id.Asterisk,
3169 Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} },
3170 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{
3171 .align_info = null,
3172 .const_token = null,
3173 .volatile_token = null,
3174 } },
3175 Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .MaybeType = void{} },
3176 Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op{ .UnwrapMaybe = void{} },
3177 Token.Id.Keyword_await => ast.Node.PrefixOp.Op{ .Await = void{} },
3178 Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} },
33903179 else => null,
33913180 };
33923181}
33933182
3394fn createNode(arena: &mem.Allocator, comptime T: type, init_to: &const T) !&T {
3395 const node = try arena.create(T);
3396 *node = *init_to;
3397 node.base = blk: {
3398 const id = ast.Node.typeToId(T);
3399 break :blk ast.Node {
3400 .id = id,
3401 };
3402 };
3403
3404 return node;
3405}
3406
3407fn createToCtxNode(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, init_to: &const T) !&T {
3408 const node = try createNode(arena, T, init_to);
3409 opt_ctx.store(&node.base);
3410
3411 return node;
3412}
3413
34143183fn createLiteral(arena: &mem.Allocator, comptime T: type, token_index: TokenIndex) !&T {
3415 return createNode(arena, T,
3416 T {
3417 .base = undefined,
3418 .token = token_index,
3419 }
3420 );
3184 return arena.construct(T{
3185 .base = ast.Node{ .id = ast.Node.typeToId(T) },
3186 .token = token_index,
3187 });
34213188}
34223189
34233190fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, token_index: TokenIndex) !&T {
......@@ -3428,73 +3195,34 @@ fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, compti
34283195}
34293196
34303197fn eatToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, id: @TagType(Token.Id)) ?TokenIndex {
3431 const token = nextToken(tok_it, tree);
3198 const token = ??tok_it.peek();
34323199
3433 if (token.ptr.id == id)
3434 return token.index;
3200 if (token.id == id) {
3201 return nextToken(tok_it, tree).index;
3202 }
34353203
3436 putBackToken(tok_it, tree);
34373204 return null;
34383205}
34393206
34403207fn nextToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) AnnotatedToken {
3441 const result = AnnotatedToken {
3208 const result = AnnotatedToken{
34423209 .index = tok_it.index,
34433210 .ptr = ??tok_it.next(),
34443211 };
3445 // possibly skip a following same line token
3446 const token = tok_it.next() ?? return result;
3447 if (token.id != Token.Id.LineComment) {
3448 putBackToken(tok_it, tree);
3449 return result;
3450 }
3451 const loc = tree.tokenLocationPtr(result.ptr.end, token);
3452 if (loc.line != 0) {
3453 putBackToken(tok_it, tree);
3454 }
3455 return result;
3456}
3212 assert(result.ptr.id != Token.Id.LineComment);
34573213
3458fn putBackToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) void {
3459 const prev_tok = ??tok_it.prev();
3460 if (prev_tok.id == Token.Id.LineComment) {
3461 const minus2_tok = tok_it.prev() ?? return;
3462 const loc = tree.tokenLocationPtr(minus2_tok.end, prev_tok);
3463 if (loc.line != 0) {
3464 _ = tok_it.next();
3465 }
3214 while (true) {
3215 const next_tok = tok_it.peek() ?? return result;
3216 if (next_tok.id != Token.Id.LineComment) return result;
3217 _ = tok_it.next();
34663218 }
34673219}
34683220
3469const RenderAstFrame = struct {
3470 node: &ast.Node,
3471 indent: usize,
3472};
3473
3474pub fn renderAst(allocator: &mem.Allocator, tree: &const ast.Tree, stream: var) !void {
3475 var stack = std.ArrayList(State).init(allocator);
3476 defer stack.deinit();
3477
3478 try stack.append(RenderAstFrame {
3479 .node = &root_node.base,
3480 .indent = 0,
3481 });
3482
3483 while (stack.popOrNull()) |frame| {
3484 {
3485 var i: usize = 0;
3486 while (i < frame.indent) : (i += 1) {
3487 try stream.print(" ");
3488 }
3489 }
3490 try stream.print("{}\n", @tagName(frame.node.id));
3491 var child_i: usize = 0;
3492 while (frame.node.iterate(child_i)) |child| : (child_i += 1) {
3493 try stack.append(RenderAstFrame {
3494 .node = child,
3495 .indent = frame.indent + 2,
3496 });
3497 }
3221fn prevToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) void {
3222 while (true) {
3223 const prev_tok = tok_it.prev() ?? return;
3224 if (prev_tok.id == Token.Id.LineComment) continue;
3225 return;
34983226 }
34993227}
35003228
std/zig/parser_test.zig+274-9
......@@ -1,3 +1,271 @@
1test "zig fmt: switch cases trailing comma" {
2 try testTransform(
3 \\fn switch_cases(x: i32) void {
4 \\ switch (x) {
5 \\ 1,2,3 => {},
6 \\ 4,5, => {},
7 \\ 6...8, => {},
8 \\ else => {},
9 \\ }
10 \\}
11 ,
12 \\fn switch_cases(x: i32) void {
13 \\ switch (x) {
14 \\ 1, 2, 3 => {},
15 \\ 4,
16 \\ 5, => {},
17 \\ 6 ... 8 => {},
18 \\ else => {},
19 \\ }
20 \\}
21 \\
22 );
23}
24
25test "zig fmt: slice align" {
26 try testCanonical(
27 \\const A = struct {
28 \\ items: []align(A) T,
29 \\};
30 \\
31 );
32}
33
34test "zig fmt: add trailing comma to array literal" {
35 try testTransform(
36 \\comptime {
37 \\ return []u16{'m', 's', 'y', 's', '-' // hi
38 \\ };
39 \\}
40 ,
41 \\comptime {
42 \\ return []u16{
43 \\ 'm',
44 \\ 's',
45 \\ 'y',
46 \\ 's',
47 \\ '-', // hi
48 \\ };
49 \\}
50 \\
51 );
52}
53
54test "zig fmt: first thing in file is line comment" {
55 try testCanonical(
56 \\// Introspection and determination of system libraries needed by zig.
57 \\
58 \\// Introspection and determination of system libraries needed by zig.
59 \\
60 \\const std = @import("std");
61 \\
62 );
63}
64
65test "zig fmt: line comment after doc comment" {
66 try testCanonical(
67 \\/// doc comment
68 \\// line comment
69 \\fn foo() void {}
70 \\
71 );
72}
73
74test "zig fmt: float literal with exponent" {
75 try testCanonical(
76 \\test "bit field alignment" {
77 \\ assert(@typeOf(&blah.b) == &align(1:3:6) const u3);
78 \\}
79 \\
80 );
81}
82
83test "zig fmt: float literal with exponent" {
84 try testCanonical(
85 \\test "aoeu" {
86 \\ switch (state) {
87 \\ TermState.Start => switch (c) {
88 \\ '\x1b' => state = TermState.Escape,
89 \\ else => try out.writeByte(c),
90 \\ },
91 \\ }
92 \\}
93 \\
94 );
95}
96test "zig fmt: float literal with exponent" {
97 try testCanonical(
98 \\pub const f64_true_min = 4.94065645841246544177e-324;
99 \\const threshold = 0x1.a827999fcef32p+1022;
100 \\
101 );
102}
103
104test "zig fmt: if-else end of comptime" {
105 try testCanonical(
106 \\comptime {
107 \\ if (a) {
108 \\ b();
109 \\ } else {
110 \\ b();
111 \\ }
112 \\}
113 \\
114 );
115}
116
117test "zig fmt: nested blocks" {
118 try testCanonical(
119 \\comptime {
120 \\ {
121 \\ {
122 \\ {
123 \\ a();
124 \\ }
125 \\ }
126 \\ }
127 \\}
128 \\
129 );
130}
131
132test "zig fmt: block with same line comment after end brace" {
133 try testCanonical(
134 \\comptime {
135 \\ {
136 \\ b();
137 \\ } // comment
138 \\}
139 \\
140 );
141}
142
143test "zig fmt: statements with comment between" {
144 try testCanonical(
145 \\comptime {
146 \\ a = b;
147 \\ // comment
148 \\ a = b;
149 \\}
150 \\
151 );
152}
153
154test "zig fmt: statements with empty line between" {
155 try testCanonical(
156 \\comptime {
157 \\ a = b;
158 \\
159 \\ a = b;
160 \\}
161 \\
162 );
163}
164
165test "zig fmt: ptr deref operator" {
166 try testCanonical(
167 \\const a = b.*;
168 \\
169 );
170}
171
172test "zig fmt: comment after if before another if" {
173 try testCanonical(
174 \\test "aoeu" {
175 \\ // comment
176 \\ if (x) {
177 \\ bar();
178 \\ }
179 \\}
180 \\
181 \\test "aoeu" {
182 \\ if (x) {
183 \\ foo();
184 \\ }
185 \\ // comment
186 \\ if (x) {
187 \\ bar();
188 \\ }
189 \\}
190 \\
191 );
192}
193
194test "zig fmt: line comment between if block and else keyword" {
195 try testCanonical(
196 \\test "aoeu" {
197 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
198 \\ if ((hx & 0x7fffffff) != 0x7f800000) {
199 \\ return Complex(f32).new(y - y, y - y);
200 \\ }
201 \\ // cexp(-inf +- i inf|nan) = 0 + i0
202 \\ else if (hx & 0x80000000 != 0) {
203 \\ return Complex(f32).new(0, 0);
204 \\ }
205 \\ // cexp(+inf +- i inf|nan) = inf + i nan
206 \\ // another comment
207 \\ else {
208 \\ return Complex(f32).new(x, y - y);
209 \\ }
210 \\}
211 \\
212 );
213}
214
215test "zig fmt: same line comments in expression" {
216 try testCanonical(
217 \\test "aoeu" {
218 \\ const x = ( // a
219 \\ 0 // b
220 \\ ); // c
221 \\}
222 \\
223 );
224}
225
226test "zig fmt: add comma on last switch prong" {
227 try testTransform(
228 \\test "aoeu" {
229 \\switch (self.init_arg_expr) {
230 \\ InitArg.Type => |t| { },
231 \\ InitArg.None,
232 \\ InitArg.Enum => { }
233 \\}
234 \\ switch (self.init_arg_expr) {
235 \\ InitArg.Type => |t| { },
236 \\ InitArg.None,
237 \\ InitArg.Enum => { }//line comment
238 \\ }
239 \\}
240 ,
241 \\test "aoeu" {
242 \\ switch (self.init_arg_expr) {
243 \\ InitArg.Type => |t| {},
244 \\ InitArg.None, InitArg.Enum => {},
245 \\ }
246 \\ switch (self.init_arg_expr) {
247 \\ InitArg.Type => |t| {},
248 \\ InitArg.None, InitArg.Enum => {}, //line comment
249 \\ }
250 \\}
251 \\
252 );
253}
254
255test "zig fmt: same-line doc comment on variable declaration" {
256 try testTransform(
257 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
258 \\pub const MAP_FILE = 0x0000; /// map from file (default)
259 \\
260 ,
261 \\/// allocated from memory, swap space
262 \\pub const MAP_ANONYMOUS = 0x1000;
263 \\/// map from file (default)
264 \\pub const MAP_FILE = 0x0000;
265 \\
266 );
267}
268
1269test "zig fmt: same-line comment after a statement" {
2270 try testCanonical(
3271 \\test "" {
......@@ -71,13 +339,6 @@ test "zig fmt: switch with empty body" {
71339 );
72340}
73341
74test "zig fmt: float literal with exponent" {
75 try testCanonical(
76 \\pub const f64_true_min = 4.94065645841246544177e-324;
77 \\
78 );
79}
80
81342test "zig fmt: line comments in struct initializer" {
82343 try testCanonical(
83344 \\fn foo() void {
......@@ -539,6 +800,11 @@ test "zig fmt: multiline string" {
539800 \\ c\\two)
540801 \\ c\\three
541802 \\ ;
803 \\ const s3 = // hi
804 \\ \\one
805 \\ \\two)
806 \\ \\three
807 \\ ;
542808 \\}
543809 \\
544810 );
......@@ -759,8 +1025,7 @@ test "zig fmt: switch" {
7591025 \\ switch (0) {
7601026 \\ 0 => {},
7611027 \\ 1 => unreachable,
762 \\ 2,
763 \\ 3 => {},
1028 \\ 2, 3 => {},
7641029 \\ 4 ... 7 => {},
7651030 \\ 1 + 4 * 3 + 22 => {},
7661031 \\ else => {
std/zig/render.zig+1363-1120
......@@ -1,1270 +1,1513 @@
11const std = @import("../index.zig");
2const builtin = @import("builtin");
23const assert = std.debug.assert;
34const mem = std.mem;
45const ast = std.zig.ast;
56const Token = std.zig.Token;
67
7const RenderState = union(enum) {
8 TopLevelDecl: &ast.Node,
9 ParamDecl: &ast.Node,
10 Text: []const u8,
11 Expression: &ast.Node,
12 VarDecl: &ast.Node.VarDecl,
13 Statement: &ast.Node,
14 PrintIndent,
15 Indent: usize,
16 MaybeSemiColon: &ast.Node,
17 Token: ast.TokenIndex,
18 NonBreakToken: ast.TokenIndex,
19};
20
218const indent_delta = 4;
229
23pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
24 var stack = std.ArrayList(RenderState).init(allocator);
25 defer stack.deinit();
26
27 {
28 try stack.append(RenderState { .Text = "\n"});
29
30 var i = tree.root_node.decls.len;
31 while (i != 0) {
32 i -= 1;
33 const decl = *tree.root_node.decls.at(i);
34 try stack.append(RenderState {.TopLevelDecl = decl});
35 if (i != 0) {
36 try stack.append(RenderState {
37 .Text = blk: {
38 const prev_node = *tree.root_node.decls.at(i - 1);
39 const prev_node_last_token = tree.tokens.at(prev_node.lastToken());
40 const loc = tree.tokenLocation(prev_node_last_token.end, decl.firstToken());
41 if (loc.line >= 2) {
42 break :blk "\n\n";
43 }
44 break :blk "\n";
45 },
46 });
10pub const Error = error{
11 /// Ran out of memory allocating call stack frames to complete rendering.
12 OutOfMemory,
13};
14
15pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(stream).Child.Error || Error)!void {
16 comptime assert(@typeId(@typeOf(stream)) == builtin.TypeId.Pointer);
17
18 // render all the line comments at the beginning of the file
19 var tok_it = tree.tokens.iterator(0);
20 while (tok_it.next()) |token| {
21 if (token.id != Token.Id.LineComment) break;
22 try stream.print("{}\n", tree.tokenSlicePtr(token));
23 if (tok_it.peek()) |next_token| {
24 const loc = tree.tokenLocationPtr(token.end, next_token);
25 if (loc.line >= 2) {
26 try stream.writeByte('\n');
4727 }
4828 }
4929 }
5030
51 var indent: usize = 0;
52 while (stack.popOrNull()) |state| {
53 switch (state) {
54 RenderState.TopLevelDecl => |decl| {
55 switch (decl.id) {
56 ast.Node.Id.FnProto => {
57 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
58 try renderComments(tree, stream, fn_proto, indent);
59
60 if (fn_proto.body_node) |body_node| {
61 stack.append(RenderState { .Expression = body_node}) catch unreachable;
62 try stack.append(RenderState { .Text = " "});
63 } else {
64 stack.append(RenderState { .Text = ";" }) catch unreachable;
65 }
6631
67 try stack.append(RenderState { .Expression = decl });
68 },
69 ast.Node.Id.Use => {
70 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
71 if (use_decl.visib_token) |visib_token| {
72 try stream.print("{} ", tree.tokenSlice(visib_token));
73 }
74 try stream.print("use ");
75 try stack.append(RenderState { .Text = ";" });
76 try stack.append(RenderState { .Expression = use_decl.expr });
77 },
78 ast.Node.Id.VarDecl => {
79 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
80 try renderComments(tree, stream, var_decl, indent);
81 try stack.append(RenderState { .VarDecl = var_decl});
82 },
83 ast.Node.Id.TestDecl => {
84 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
85 try renderComments(tree, stream, test_decl, indent);
86 try stream.print("test ");
87 try stack.append(RenderState { .Expression = test_decl.body_node });
88 try stack.append(RenderState { .Text = " " });
89 try stack.append(RenderState { .Expression = test_decl.name });
90 },
91 ast.Node.Id.StructField => {
92 const field = @fieldParentPtr(ast.Node.StructField, "base", decl);
93 try renderComments(tree, stream, field, indent);
94 if (field.visib_token) |visib_token| {
95 try stream.print("{} ", tree.tokenSlice(visib_token));
96 }
97 try stream.print("{}: ", tree.tokenSlice(field.name_token));
98 try stack.append(RenderState { .Token = field.lastToken() + 1 });
99 try stack.append(RenderState { .Expression = field.type_expr});
100 },
101 ast.Node.Id.UnionTag => {
102 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
103 try renderComments(tree, stream, tag, indent);
104 try stream.print("{}", tree.tokenSlice(tag.name_token));
105
106 try stack.append(RenderState { .Text = "," });
107
108 if (tag.value_expr) |value_expr| {
109 try stack.append(RenderState { .Expression = value_expr });
110 try stack.append(RenderState { .Text = " = " });
111 }
32 var it = tree.root_node.decls.iterator(0);
33 while (it.next()) |decl| {
34 try renderTopLevelDecl(allocator, stream, tree, 0, decl.*);
35 if (it.peek()) |next_decl| {
36 try renderExtraNewline(tree, stream, next_decl.*);
37 }
38 }
39}
11240
113 if (tag.type_expr) |type_expr| {
114 try stream.print(": ");
115 try stack.append(RenderState { .Expression = type_expr});
116 }
117 },
118 ast.Node.Id.EnumTag => {
119 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
120 try renderComments(tree, stream, tag, indent);
121 try stream.print("{}", tree.tokenSlice(tag.name_token));
122
123 try stack.append(RenderState { .Text = "," });
124 if (tag.value) |value| {
125 try stream.print(" = ");
126 try stack.append(RenderState { .Expression = value});
127 }
128 },
129 ast.Node.Id.ErrorTag => {
130 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", decl);
131 try renderComments(tree, stream, tag, indent);
132 try stream.print("{}", tree.tokenSlice(tag.name_token));
133 },
134 ast.Node.Id.Comptime => {
135 try stack.append(RenderState { .MaybeSemiColon = decl });
136 try stack.append(RenderState { .Expression = decl });
137 },
138 ast.Node.Id.LineComment => {
139 const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", decl);
140 try stream.write(tree.tokenSlice(line_comment_node.token));
141 },
142 else => unreachable,
143 }
144 },
145
146 RenderState.VarDecl => |var_decl| {
147 try stack.append(RenderState { .Token = var_decl.semicolon_token });
148 if (var_decl.init_node) |init_node| {
149 try stack.append(RenderState { .Expression = init_node });
150 const text = if (init_node.id == ast.Node.Id.MultilineStringLiteral) " =" else " = ";
151 try stack.append(RenderState { .Text = text });
152 }
153 if (var_decl.align_node) |align_node| {
154 try stack.append(RenderState { .Text = ")" });
155 try stack.append(RenderState { .Expression = align_node });
156 try stack.append(RenderState { .Text = " align(" });
157 }
158 if (var_decl.type_node) |type_node| {
159 try stack.append(RenderState { .Expression = type_node });
160 try stack.append(RenderState { .Text = ": " });
161 }
162 try stack.append(RenderState { .Text = tree.tokenSlice(var_decl.name_token) });
163 try stack.append(RenderState { .Text = " " });
164 try stack.append(RenderState { .Text = tree.tokenSlice(var_decl.mut_token) });
41fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void {
42 var first_token = node.firstToken();
43 while (tree.tokens.at(first_token - 1).id == Token.Id.DocComment) {
44 first_token -= 1;
45 }
46 const prev_token_end = tree.tokens.at(first_token - 1).end;
47 const loc = tree.tokenLocation(prev_token_end, first_token);
48 if (loc.line >= 2) {
49 try stream.writeByte('\n');
50 }
51}
16552
166 if (var_decl.comptime_token) |comptime_token| {
167 try stack.append(RenderState { .Text = " " });
168 try stack.append(RenderState { .Text = tree.tokenSlice(comptime_token) });
169 }
53fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, decl: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
54 switch (decl.id) {
55 ast.Node.Id.FnProto => {
56 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
57
58 try renderDocComments(tree, stream, fn_proto, indent);
59
60 if (fn_proto.body_node) |body_node| {
61 try renderExpression(allocator, stream, tree, indent, decl, Space.Space);
62 try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline);
63 } else {
64 try renderExpression(allocator, stream, tree, indent, decl, Space.None);
65 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline);
66 }
67 },
68
69 ast.Node.Id.Use => {
70 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
71
72 if (use_decl.visib_token) |visib_token| {
73 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
74 }
75 try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use
76 try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None);
77 try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ;
78 },
79
80 ast.Node.Id.VarDecl => {
81 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
82
83 try renderDocComments(tree, stream, var_decl, indent);
84 try renderVarDecl(allocator, stream, tree, indent, var_decl);
85 },
86
87 ast.Node.Id.TestDecl => {
88 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
89
90 try renderDocComments(tree, stream, test_decl, indent);
91 try renderToken(tree, stream, test_decl.test_token, indent, Space.Space);
92 try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space);
93 try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline);
94 },
95
96 ast.Node.Id.StructField => {
97 const field = @fieldParentPtr(ast.Node.StructField, "base", decl);
98
99 try renderDocComments(tree, stream, field, indent);
100 if (field.visib_token) |visib_token| {
101 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
102 }
103 try renderToken(tree, stream, field.name_token, indent, Space.None); // name
104 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // :
105 try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.None); // type
106 try renderToken(tree, stream, tree.nextToken(field.lastToken()), indent, Space.Newline); // ,
107 },
108
109 ast.Node.Id.UnionTag => {
110 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
111
112 try renderDocComments(tree, stream, tag, indent);
113
114 const name_space = if (tag.type_expr == null and tag.value_expr != null) Space.Space else Space.None;
115 try renderToken(tree, stream, tag.name_token, indent, name_space); // name
116
117 if (tag.type_expr) |type_expr| {
118 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // :
119
120 const after_type_space = if (tag.value_expr == null) Space.None else Space.Space;
121 try renderExpression(allocator, stream, tree, indent, type_expr, after_type_space);
122 }
123
124 if (tag.value_expr) |value_expr| {
125 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // =
126 try renderExpression(allocator, stream, tree, indent, value_expr, Space.None);
127 }
128
129 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // ,
130 },
131
132 ast.Node.Id.EnumTag => {
133 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
134
135 try renderDocComments(tree, stream, tag, indent);
136
137 const after_name_space = if (tag.value == null) Space.None else Space.Space;
138 try renderToken(tree, stream, tag.name_token, indent, after_name_space); // name
139
140 if (tag.value) |value| {
141 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // =
142 try renderExpression(allocator, stream, tree, indent, value, Space.None);
143 }
144
145 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline); // ,
146 },
170147
171 if (var_decl.extern_export_token) |extern_export_token| {
172 if (var_decl.lib_name != null) {
173 try stack.append(RenderState { .Text = " " });
174 try stack.append(RenderState { .Expression = ??var_decl.lib_name });
148 ast.Node.Id.Comptime => {
149 assert(!decl.requireSemiColon());
150 try renderExpression(allocator, stream, tree, indent, decl, Space.Newline);
151 },
152 else => unreachable,
153 }
154}
155
156fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node, space: Space) (@typeOf(stream).Child.Error || Error)!void {
157 switch (base.id) {
158 ast.Node.Id.Identifier => {
159 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);
160 try renderToken(tree, stream, identifier.token, indent, space);
161 },
162 ast.Node.Id.Block => {
163 const block = @fieldParentPtr(ast.Node.Block, "base", base);
164
165 if (block.label) |label| {
166 try renderToken(tree, stream, label, indent, Space.None);
167 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);
168 }
169
170 if (block.statements.len == 0) {
171 try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None);
172 try renderToken(tree, stream, block.rbrace, indent, space);
173 } else {
174 const block_indent = indent + indent_delta;
175 try renderToken(tree, stream, block.lbrace, block_indent, Space.Newline);
176
177 var it = block.statements.iterator(0);
178 while (it.next()) |statement| {
179 try stream.writeByteNTimes(' ', block_indent);
180 try renderStatement(allocator, stream, tree, block_indent, statement.*);
181
182 if (it.peek()) |next_statement| {
183 try renderExtraNewline(tree, stream, next_statement.*);
175184 }
176 try stack.append(RenderState { .Text = " " });
177 try stack.append(RenderState { .Text = tree.tokenSlice(extern_export_token) });
178185 }
179186
180 if (var_decl.visib_token) |visib_token| {
181 try stack.append(RenderState { .Text = " " });
182 try stack.append(RenderState { .Text = tree.tokenSlice(visib_token) });
183 }
184 },
187 try stream.writeByteNTimes(' ', indent);
188 try renderToken(tree, stream, block.rbrace, indent, space);
189 }
190 },
191 ast.Node.Id.Defer => {
192 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
193
194 try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space);
195 try renderExpression(allocator, stream, tree, indent, defer_node.expr, space);
196 },
197 ast.Node.Id.Comptime => {
198 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
199
200 try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space);
201 try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space);
202 },
203
204 ast.Node.Id.AsyncAttribute => {
205 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
206
207 if (async_attr.allocator_type) |allocator_type| {
208 try renderToken(tree, stream, async_attr.async_token, indent, Space.None);
209
210 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, Space.None);
211 try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None);
212 try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space);
213 } else {
214 try renderToken(tree, stream, async_attr.async_token, indent, space);
215 }
216 },
185217
186 RenderState.ParamDecl => |base| {
187 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
188 if (param_decl.comptime_token) |comptime_token| {
189 try stream.print("{} ", tree.tokenSlice(comptime_token));
190 }
191 if (param_decl.noalias_token) |noalias_token| {
192 try stream.print("{} ", tree.tokenSlice(noalias_token));
193 }
194 if (param_decl.name_token) |name_token| {
195 try stream.print("{}: ", tree.tokenSlice(name_token));
196 }
197 if (param_decl.var_args_token) |var_args_token| {
198 try stream.print("{}", tree.tokenSlice(var_args_token));
218 ast.Node.Id.Suspend => {
219 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
220
221 if (suspend_node.label) |label| {
222 try renderToken(tree, stream, label, indent, Space.None);
223 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);
224 }
225
226 if (suspend_node.payload) |payload| {
227 if (suspend_node.body) |body| {
228 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
229 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
230 try renderExpression(allocator, stream, tree, indent, body, space);
199231 } else {
200 try stack.append(RenderState { .Expression = param_decl.type_node});
232 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
233 try renderExpression(allocator, stream, tree, indent, payload, space);
201234 }
202 },
203 RenderState.Text => |bytes| {
204 try stream.write(bytes);
205 },
206 RenderState.Expression => |base| switch (base.id) {
207 ast.Node.Id.Identifier => {
208 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);
209 try stream.print("{}", tree.tokenSlice(identifier.token));
235 } else if (suspend_node.body) |body| {
236 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);
237 try renderExpression(allocator, stream, tree, indent, body, space);
238 } else {
239 try renderToken(tree, stream, suspend_node.suspend_token, indent, space);
240 }
241 },
242
243 ast.Node.Id.InfixOp => {
244 const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);
245
246 const op_token = tree.tokens.at(infix_op_node.op_token);
247 const op_space = switch (infix_op_node.op) {
248 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion => Space.None,
249 else => Space.Space,
250 };
251 try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space);
252 try renderToken(tree, stream, infix_op_node.op_token, indent, op_space);
253
254 switch (infix_op_node.op) {
255 ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {
256 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
210257 },
211 ast.Node.Id.Block => {
212 const block = @fieldParentPtr(ast.Node.Block, "base", base);
213 if (block.label) |label| {
214 try stream.print("{}: ", tree.tokenSlice(label));
215 }
258 else => {},
259 }
216260
217 if (block.statements.len == 0) {
218 try stream.write("{}");
219 } else {
220 try stream.write("{");
221 try stack.append(RenderState { .Text = "}"});
222 try stack.append(RenderState.PrintIndent);
223 try stack.append(RenderState { .Indent = indent});
224 try stack.append(RenderState { .Text = "\n"});
225 var i = block.statements.len;
226 while (i != 0) {
227 i -= 1;
228 const statement_node = *block.statements.at(i);
229 try stack.append(RenderState { .Statement = statement_node});
230 try stack.append(RenderState.PrintIndent);
231 try stack.append(RenderState { .Indent = indent + indent_delta});
232 try stack.append(RenderState {
233 .Text = blk: {
234 if (i != 0) {
235 const prev_node = *block.statements.at(i - 1);
236 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
237 const loc = tree.tokenLocation(prev_node_last_token_end, statement_node.firstToken());
238 if (loc.line >= 2) {
239 break :blk "\n\n";
240 }
241 }
242 break :blk "\n";
243 },
244 });
261 try renderExpression(allocator, stream, tree, indent, infix_op_node.rhs, space);
262 },
263
264 ast.Node.Id.PrefixOp => {
265 const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base);
266
267 switch (prefix_op_node.op) {
268 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
269 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // &
270 if (addr_of_info.align_info) |align_info| {
271 const lparen_token = tree.prevToken(align_info.node.firstToken());
272 const align_token = tree.prevToken(lparen_token);
273
274 try renderToken(tree, stream, align_token, indent, Space.None); // align
275 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
276
277 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
278
279 if (align_info.bit_range) |bit_range| {
280 const colon1 = tree.prevToken(bit_range.start.firstToken());
281 const colon2 = tree.prevToken(bit_range.end.firstToken());
282
283 try renderToken(tree, stream, colon1, indent, Space.None); // :
284 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
285 try renderToken(tree, stream, colon2, indent, Space.None); // :
286 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
287
288 const rparen_token = tree.nextToken(bit_range.end.lastToken());
289 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
290 } else {
291 const rparen_token = tree.nextToken(align_info.node.lastToken());
292 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
245293 }
246294 }
247 },
248 ast.Node.Id.Defer => {
249 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
250 try stream.print("{} ", tree.tokenSlice(defer_node.defer_token));
251 try stack.append(RenderState { .Expression = defer_node.expr });
252 },
253 ast.Node.Id.Comptime => {
254 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
255 try stream.print("{} ", tree.tokenSlice(comptime_node.comptime_token));
256 try stack.append(RenderState { .Expression = comptime_node.expr });
257 },
258 ast.Node.Id.AsyncAttribute => {
259 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
260 try stream.print("{}", tree.tokenSlice(async_attr.async_token));
261
262 if (async_attr.allocator_type) |allocator_type| {
263 try stack.append(RenderState { .Text = ">" });
264 try stack.append(RenderState { .Expression = allocator_type });
265 try stack.append(RenderState { .Text = "<" });
295 if (addr_of_info.const_token) |const_token| {
296 try renderToken(tree, stream, const_token, indent, Space.Space); // const
266297 }
267 },
268 ast.Node.Id.Suspend => {
269 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
270 if (suspend_node.label) |label| {
271 try stream.print("{}: ", tree.tokenSlice(label));
298 if (addr_of_info.volatile_token) |volatile_token| {
299 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
272300 }
273 try stream.print("{}", tree.tokenSlice(suspend_node.suspend_token));
301 },
274302
275 if (suspend_node.body) |body| {
276 try stack.append(RenderState { .Expression = body });
277 try stack.append(RenderState { .Text = " " });
278 }
303 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
304 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
305 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]
279306
280 if (suspend_node.payload) |payload| {
281 try stack.append(RenderState { .Expression = payload });
282 try stack.append(RenderState { .Text = " " });
283 }
284 },
285 ast.Node.Id.InfixOp => {
286 const prefix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);
287 try stack.append(RenderState { .Expression = prefix_op_node.rhs });
288
289 if (prefix_op_node.op == ast.Node.InfixOp.Op.Catch) {
290 if (prefix_op_node.op.Catch) |payload| {
291 try stack.append(RenderState { .Text = " " });
292 try stack.append(RenderState { .Expression = payload });
307 if (addr_of_info.align_info) |align_info| {
308 const lparen_token = tree.prevToken(align_info.node.firstToken());
309 const align_token = tree.prevToken(lparen_token);
310
311 try renderToken(tree, stream, align_token, indent, Space.None); // align
312 try renderToken(tree, stream, lparen_token, indent, Space.None); // (
313
314 try renderExpression(allocator, stream, tree, indent, align_info.node, Space.None);
315
316 if (align_info.bit_range) |bit_range| {
317 const colon1 = tree.prevToken(bit_range.start.firstToken());
318 const colon2 = tree.prevToken(bit_range.end.firstToken());
319
320 try renderToken(tree, stream, colon1, indent, Space.None); // :
321 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);
322 try renderToken(tree, stream, colon2, indent, Space.None); // :
323 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);
324
325 const rparen_token = tree.nextToken(bit_range.end.lastToken());
326 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
327 } else {
328 const rparen_token = tree.nextToken(align_info.node.lastToken());
329 try renderToken(tree, stream, rparen_token, indent, Space.Space); // )
293330 }
294 try stack.append(RenderState { .Text = " catch " });
295 } else {
296 const text = switch (prefix_op_node.op) {
297 ast.Node.InfixOp.Op.Add => " + ",
298 ast.Node.InfixOp.Op.AddWrap => " +% ",
299 ast.Node.InfixOp.Op.ArrayCat => " ++ ",
300 ast.Node.InfixOp.Op.ArrayMult => " ** ",
301 ast.Node.InfixOp.Op.Assign => " = ",
302 ast.Node.InfixOp.Op.AssignBitAnd => " &= ",
303 ast.Node.InfixOp.Op.AssignBitOr => " |= ",
304 ast.Node.InfixOp.Op.AssignBitShiftLeft => " <<= ",
305 ast.Node.InfixOp.Op.AssignBitShiftRight => " >>= ",
306 ast.Node.InfixOp.Op.AssignBitXor => " ^= ",
307 ast.Node.InfixOp.Op.AssignDiv => " /= ",
308 ast.Node.InfixOp.Op.AssignMinus => " -= ",
309 ast.Node.InfixOp.Op.AssignMinusWrap => " -%= ",
310 ast.Node.InfixOp.Op.AssignMod => " %= ",
311 ast.Node.InfixOp.Op.AssignPlus => " += ",
312 ast.Node.InfixOp.Op.AssignPlusWrap => " +%= ",
313 ast.Node.InfixOp.Op.AssignTimes => " *= ",
314 ast.Node.InfixOp.Op.AssignTimesWarp => " *%= ",
315 ast.Node.InfixOp.Op.BangEqual => " != ",
316 ast.Node.InfixOp.Op.BitAnd => " & ",
317 ast.Node.InfixOp.Op.BitOr => " | ",
318 ast.Node.InfixOp.Op.BitShiftLeft => " << ",
319 ast.Node.InfixOp.Op.BitShiftRight => " >> ",
320 ast.Node.InfixOp.Op.BitXor => " ^ ",
321 ast.Node.InfixOp.Op.BoolAnd => " and ",
322 ast.Node.InfixOp.Op.BoolOr => " or ",
323 ast.Node.InfixOp.Op.Div => " / ",
324 ast.Node.InfixOp.Op.EqualEqual => " == ",
325 ast.Node.InfixOp.Op.ErrorUnion => "!",
326 ast.Node.InfixOp.Op.GreaterOrEqual => " >= ",
327 ast.Node.InfixOp.Op.GreaterThan => " > ",
328 ast.Node.InfixOp.Op.LessOrEqual => " <= ",
329 ast.Node.InfixOp.Op.LessThan => " < ",
330 ast.Node.InfixOp.Op.MergeErrorSets => " || ",
331 ast.Node.InfixOp.Op.Mod => " % ",
332 ast.Node.InfixOp.Op.Mult => " * ",
333 ast.Node.InfixOp.Op.MultWrap => " *% ",
334 ast.Node.InfixOp.Op.Period => ".",
335 ast.Node.InfixOp.Op.Sub => " - ",
336 ast.Node.InfixOp.Op.SubWrap => " -% ",
337 ast.Node.InfixOp.Op.UnwrapMaybe => " ?? ",
338 ast.Node.InfixOp.Op.Range => " ... ",
339 ast.Node.InfixOp.Op.Catch => unreachable,
340 };
341
342 try stack.append(RenderState { .Text = text });
343331 }
344 try stack.append(RenderState { .Expression = prefix_op_node.lhs });
345 },
346 ast.Node.Id.PrefixOp => {
347 const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base);
348 try stack.append(RenderState { .Expression = prefix_op_node.rhs });
349 switch (prefix_op_node.op) {
350 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
351 try stream.write("&");
352 if (addr_of_info.volatile_token != null) {
353 try stack.append(RenderState { .Text = "volatile "});
354 }
355 if (addr_of_info.const_token != null) {
356 try stack.append(RenderState { .Text = "const "});
357 }
358 if (addr_of_info.align_expr) |align_expr| {
359 try stream.print("align(");
360 try stack.append(RenderState { .Text = ") "});
361 try stack.append(RenderState { .Expression = align_expr});
362 }
363 },
364 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
365 try stream.write("[]");
366 if (addr_of_info.volatile_token != null) {
367 try stack.append(RenderState { .Text = "volatile "});
368 }
369 if (addr_of_info.const_token != null) {
370 try stack.append(RenderState { .Text = "const "});
371 }
372 if (addr_of_info.align_expr) |align_expr| {
373 try stream.print("align(");
374 try stack.append(RenderState { .Text = ") "});
375 try stack.append(RenderState { .Expression = align_expr});
376 }
377 },
378 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
379 try stack.append(RenderState { .Text = "]"});
380 try stack.append(RenderState { .Expression = array_index});
381 try stack.append(RenderState { .Text = "["});
382 },
383 ast.Node.PrefixOp.Op.BitNot => try stream.write("~"),
384 ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"),
385 ast.Node.PrefixOp.Op.Deref => try stream.write("*"),
386 ast.Node.PrefixOp.Op.Negation => try stream.write("-"),
387 ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"),
388 ast.Node.PrefixOp.Op.Try => try stream.write("try "),
389 ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"),
390 ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"),
391 ast.Node.PrefixOp.Op.Await => try stream.write("await "),
392 ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "),
393 ast.Node.PrefixOp.Op.Resume => try stream.write("resume "),
332 if (addr_of_info.const_token) |const_token| {
333 try renderToken(tree, stream, const_token, indent, Space.Space);
394334 }
395 },
396 ast.Node.Id.SuffixOp => {
397 const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base);
398
399 switch (suffix_op.op) {
400 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
401 try stack.append(RenderState { .Text = ")"});
402 var i = call_info.params.len;
403 while (i != 0) {
404 i -= 1;
405 const param_node = *call_info.params.at(i);
406 try stack.append(RenderState { .Expression = param_node});
407 if (i != 0) {
408 try stack.append(RenderState { .Text = ", " });
409 }
410 }
411 try stack.append(RenderState { .Text = "("});
412 try stack.append(RenderState { .Expression = suffix_op.lhs });
413
414 if (call_info.async_attr) |async_attr| {
415 try stack.append(RenderState { .Text = " "});
416 try stack.append(RenderState { .Expression = &async_attr.base });
417 }
418 },
419 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {
420 try stack.append(RenderState { .Text = "]"});
421 try stack.append(RenderState { .Expression = index_expr});
422 try stack.append(RenderState { .Text = "["});
423 try stack.append(RenderState { .Expression = suffix_op.lhs });
424 },
425 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {
426 try stack.append(RenderState { .Text = "]"});
427 if (range.end) |end| {
428 try stack.append(RenderState { .Expression = end});
429 }
430 try stack.append(RenderState { .Text = ".."});
431 try stack.append(RenderState { .Expression = range.start});
432 try stack.append(RenderState { .Text = "["});
433 try stack.append(RenderState { .Expression = suffix_op.lhs });
434 },
435 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
436 if (field_inits.len == 0) {
437 try stack.append(RenderState { .Text = "{}" });
438 try stack.append(RenderState { .Expression = suffix_op.lhs });
439 continue;
440 }
441 if (field_inits.len == 1) {
442 const field_init = *field_inits.at(0);
443
444 try stack.append(RenderState { .Text = " }" });
445 try stack.append(RenderState { .Expression = field_init });
446 try stack.append(RenderState { .Text = "{ " });
447 try stack.append(RenderState { .Expression = suffix_op.lhs });
448 continue;
449 }
450 try stack.append(RenderState { .Text = "}"});
451 try stack.append(RenderState.PrintIndent);
452 try stack.append(RenderState { .Indent = indent });
453 try stack.append(RenderState { .Text = "\n" });
454 var i = field_inits.len;
455 while (i != 0) {
456 i -= 1;
457 const field_init = *field_inits.at(i);
458 if (field_init.id != ast.Node.Id.LineComment) {
459 try stack.append(RenderState { .Text = "," });
460 }
461 try stack.append(RenderState { .Expression = field_init });
462 try stack.append(RenderState.PrintIndent);
463 if (i != 0) {
464 try stack.append(RenderState { .Text = blk: {
465 const prev_node = *field_inits.at(i - 1);
466 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
467 const loc = tree.tokenLocation(prev_node_last_token_end, field_init.firstToken());
468 if (loc.line >= 2) {
469 break :blk "\n\n";
470 }
471 break :blk "\n";
472 }});
473 }
474 }
475 try stack.append(RenderState { .Indent = indent + indent_delta });
476 try stack.append(RenderState { .Text = "{\n"});
477 try stack.append(RenderState { .Expression = suffix_op.lhs });
478 },
479 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
480 if (exprs.len == 0) {
481 try stack.append(RenderState { .Text = "{}" });
482 try stack.append(RenderState { .Expression = suffix_op.lhs });
483 continue;
484 }
485 if (exprs.len == 1) {
486 const expr = *exprs.at(0);
487
488 try stack.append(RenderState { .Text = "}" });
489 try stack.append(RenderState { .Expression = expr });
490 try stack.append(RenderState { .Text = "{" });
491 try stack.append(RenderState { .Expression = suffix_op.lhs });
492 continue;
493 }
494
495 try stack.append(RenderState { .Text = "}"});
496 try stack.append(RenderState.PrintIndent);
497 try stack.append(RenderState { .Indent = indent });
498 var i = exprs.len;
499 while (i != 0) {
500 i -= 1;
501 const expr = *exprs.at(i);
502 try stack.append(RenderState { .Text = ",\n" });
503 try stack.append(RenderState { .Expression = expr });
504 try stack.append(RenderState.PrintIndent);
505 }
506 try stack.append(RenderState { .Indent = indent + indent_delta });
507 try stack.append(RenderState { .Text = "{\n"});
508 try stack.append(RenderState { .Expression = suffix_op.lhs });
509 },
335 if (addr_of_info.volatile_token) |volatile_token| {
336 try renderToken(tree, stream, volatile_token, indent, Space.Space);
510337 }
511338 },
512 ast.Node.Id.ControlFlowExpression => {
513 const flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", base);
514339
515 if (flow_expr.rhs) |rhs| {
516 try stack.append(RenderState { .Expression = rhs });
517 try stack.append(RenderState { .Text = " " });
518 }
519
520 switch (flow_expr.kind) {
521 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {
522 try stream.print("break");
523 if (maybe_label) |label| {
524 try stream.print(" :");
525 try stack.append(RenderState { .Expression = label });
526 }
527 },
528 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {
529 try stream.print("continue");
530 if (maybe_label) |label| {
531 try stream.print(" :");
532 try stack.append(RenderState { .Expression = label });
533 }
534 },
535 ast.Node.ControlFlowExpression.Kind.Return => {
536 try stream.print("return");
537 },
538
539 }
340 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
341 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [
342 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);
343 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ]
540344 },
541 ast.Node.Id.Payload => {
542 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
543 try stack.append(RenderState { .Text = "|"});
544 try stack.append(RenderState { .Expression = payload.error_symbol });
545 try stack.append(RenderState { .Text = "|"});
345 ast.Node.PrefixOp.Op.BitNot,
346 ast.Node.PrefixOp.Op.BoolNot,
347 ast.Node.PrefixOp.Op.Negation,
348 ast.Node.PrefixOp.Op.NegationWrap,
349 ast.Node.PrefixOp.Op.UnwrapMaybe,
350 ast.Node.PrefixOp.Op.MaybeType,
351 ast.Node.PrefixOp.Op.PointerType => {
352 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None);
546353 },
547 ast.Node.Id.PointerPayload => {
548 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
549 try stack.append(RenderState { .Text = "|"});
550 try stack.append(RenderState { .Expression = payload.value_symbol });
551
552 if (payload.ptr_token) |ptr_token| {
553 try stack.append(RenderState { .Text = tree.tokenSlice(ptr_token) });
554 }
555354
556 try stack.append(RenderState { .Text = "|"});
355 ast.Node.PrefixOp.Op.Try,
356 ast.Node.PrefixOp.Op.Await,
357 ast.Node.PrefixOp.Op.Cancel,
358 ast.Node.PrefixOp.Op.Resume => {
359 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.Space);
557360 },
558 ast.Node.Id.PointerIndexPayload => {
559 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
560 try stack.append(RenderState { .Text = "|"});
361 }
362
363 try renderExpression(allocator, stream, tree, indent, prefix_op_node.rhs, space);
364 },
561365
562 if (payload.index_symbol) |index_symbol| {
563 try stack.append(RenderState { .Expression = index_symbol });
564 try stack.append(RenderState { .Text = ", "});
366 ast.Node.Id.SuffixOp => {
367 const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base);
368
369 switch (suffix_op.op) {
370 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
371 if (call_info.async_attr) |async_attr| {
372 try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space);
565373 }
566374
567 try stack.append(RenderState { .Expression = payload.value_symbol });
375 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
376
377 const lparen = tree.nextToken(suffix_op.lhs.lastToken());
378 try renderToken(tree, stream, lparen, indent, Space.None);
568379
569 if (payload.ptr_token) |ptr_token| {
570 try stack.append(RenderState { .Text = tree.tokenSlice(ptr_token) });
380 var it = call_info.params.iterator(0);
381 while (it.next()) |param_node| {
382 try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None);
383
384 if (it.peek() != null) {
385 const comma = tree.nextToken(param_node.*.lastToken());
386 try renderToken(tree, stream, comma, indent, Space.Space);
387 }
571388 }
572389
573 try stack.append(RenderState { .Text = "|"});
574 },
575 ast.Node.Id.GroupedExpression => {
576 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
577 try stack.append(RenderState { .Text = ")"});
578 try stack.append(RenderState { .Expression = grouped_expr.expr });
579 try stack.append(RenderState { .Text = "("});
580 },
581 ast.Node.Id.FieldInitializer => {
582 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
583 try stream.print(".{} = ", tree.tokenSlice(field_init.name_token));
584 try stack.append(RenderState { .Expression = field_init.expr });
585 },
586 ast.Node.Id.IntegerLiteral => {
587 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);
588 try stream.print("{}", tree.tokenSlice(integer_literal.token));
589 },
590 ast.Node.Id.FloatLiteral => {
591 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);
592 try stream.print("{}", tree.tokenSlice(float_literal.token));
593 },
594 ast.Node.Id.StringLiteral => {
595 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);
596 try stream.print("{}", tree.tokenSlice(string_literal.token));
597 },
598 ast.Node.Id.CharLiteral => {
599 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
600 try stream.print("{}", tree.tokenSlice(char_literal.token));
601 },
602 ast.Node.Id.BoolLiteral => {
603 const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
604 try stream.print("{}", tree.tokenSlice(bool_literal.token));
390 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
605391 },
606 ast.Node.Id.NullLiteral => {
607 const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base);
608 try stream.print("{}", tree.tokenSlice(null_literal.token));
609 },
610 ast.Node.Id.ThisLiteral => {
611 const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base);
612 try stream.print("{}", tree.tokenSlice(this_literal.token));
613 },
614 ast.Node.Id.Unreachable => {
615 const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base);
616 try stream.print("{}", tree.tokenSlice(unreachable_node.token));
617 },
618 ast.Node.Id.ErrorType => {
619 const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base);
620 try stream.print("{}", tree.tokenSlice(error_type.token));
392
393 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {
394 const lbracket = tree.prevToken(index_expr.firstToken());
395 const rbracket = tree.nextToken(index_expr.lastToken());
396
397 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
398 try renderToken(tree, stream, lbracket, indent, Space.None); // [
399 try renderExpression(allocator, stream, tree, indent, index_expr, Space.None);
400 try renderToken(tree, stream, rbracket, indent, space); // ]
621401 },
622 ast.Node.Id.VarType => {
623 const var_type = @fieldParentPtr(ast.Node.VarType, "base", base);
624 try stream.print("{}", tree.tokenSlice(var_type.token));
402
403 ast.Node.SuffixOp.Op.Deref => {
404 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
405 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // .
406 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // *
625407 },
626 ast.Node.Id.ContainerDecl => {
627 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
628408
629 switch (container_decl.layout) {
630 ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "),
631 ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "),
632 ast.Node.ContainerDecl.Layout.Auto => { },
633 }
409 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {
410 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
634411
635 switch (container_decl.kind) {
636 ast.Node.ContainerDecl.Kind.Struct => try stream.print("struct"),
637 ast.Node.ContainerDecl.Kind.Enum => try stream.print("enum"),
638 ast.Node.ContainerDecl.Kind.Union => try stream.print("union"),
639 }
412 const lbracket = tree.prevToken(range.start.firstToken());
413 const dotdot = tree.nextToken(range.start.lastToken());
640414
641 if (container_decl.fields_and_decls.len == 0) {
642 try stack.append(RenderState { .Text = "{}"});
643 } else {
644 try stack.append(RenderState { .Text = "}"});
645 try stack.append(RenderState.PrintIndent);
646 try stack.append(RenderState { .Indent = indent });
647 try stack.append(RenderState { .Text = "\n"});
648
649 var i = container_decl.fields_and_decls.len;
650 while (i != 0) {
651 i -= 1;
652 const node = *container_decl.fields_and_decls.at(i);
653 try stack.append(RenderState { .TopLevelDecl = node});
654 try stack.append(RenderState.PrintIndent);
655 try stack.append(RenderState {
656 .Text = blk: {
657 if (i != 0) {
658 const prev_node = *container_decl.fields_and_decls.at(i - 1);
659 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
660 const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken());
661 if (loc.line >= 2) {
662 break :blk "\n\n";
663 }
664 }
665 break :blk "\n";
666 },
667 });
668 }
669 try stack.append(RenderState { .Indent = indent + indent_delta});
670 try stack.append(RenderState { .Text = "{"});
415 try renderToken(tree, stream, lbracket, indent, Space.None); // [
416 try renderExpression(allocator, stream, tree, indent, range.start, Space.None);
417 try renderToken(tree, stream, dotdot, indent, Space.None); // ..
418 if (range.end) |end| {
419 try renderExpression(allocator, stream, tree, indent, end, Space.None);
671420 }
421 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ]
422 },
423
424 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
425 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
672426
673 switch (container_decl.init_arg_expr) {
674 ast.Node.ContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}),
675 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
676 if (enum_tag_type) |expr| {
677 try stack.append(RenderState { .Text = ")) "});
678 try stack.append(RenderState { .Expression = expr});
679 try stack.append(RenderState { .Text = "(enum("});
680 } else {
681 try stack.append(RenderState { .Text = "(enum) "});
682 }
683 },
684 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
685 try stack.append(RenderState { .Text = ") "});
686 try stack.append(RenderState { .Expression = type_expr});
687 try stack.append(RenderState { .Text = "("});
688 },
427 if (field_inits.len == 0) {
428 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
429 try renderToken(tree, stream, lbrace, indent, Space.None);
430 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
431 return;
689432 }
690 },
691 ast.Node.Id.ErrorSetDecl => {
692 const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
693433
694 if (err_set_decl.decls.len == 0) {
695 try stream.write("error{}");
696 continue;
434 if (field_inits.len == 1) {
435 const field_init = field_inits.at(0).*;
436
437 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
438 try renderToken(tree, stream, lbrace, indent, Space.Space);
439 try renderExpression(allocator, stream, tree, indent, field_init, Space.Space);
440 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
441 return;
697442 }
698443
699 if (err_set_decl.decls.len == 1) blk: {
700 const node = *err_set_decl.decls.at(0);
444 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
445 try renderToken(tree, stream, lbrace, indent, Space.Newline);
446
447 const new_indent = indent + indent_delta;
448
449 var it = field_inits.iterator(0);
450 while (it.next()) |field_init| {
451 try stream.writeByteNTimes(' ', new_indent);
452
453 if (it.peek()) |next_field_init| {
454 try renderExpression(allocator, stream, tree, new_indent, field_init.*, Space.None);
701455
702 // if there are any doc comments or same line comments
703 // don't try to put it all on one line
704 if (node.cast(ast.Node.ErrorTag)) |tag| {
705 if (tag.doc_comments != null) break :blk;
456 const comma = tree.nextToken(field_init.*.lastToken());
457 try renderToken(tree, stream, comma, new_indent, Space.Newline);
458
459 try renderExtraNewline(tree, stream, next_field_init.*);
706460 } else {
707 break :blk;
461 try renderTrailingComma(allocator, stream, tree, new_indent, field_init.*, Space.Newline);
708462 }
463 }
709464
465 try stream.writeByteNTimes(' ', indent);
466 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
467 },
468
469 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
470 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
710471
711 try stream.write("error{");
712 try stack.append(RenderState { .Text = "}" });
713 try stack.append(RenderState { .TopLevelDecl = node });
714 continue;
472 if (exprs.len == 0) {
473 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
474 try renderToken(tree, stream, lbrace, indent, Space.None);
475 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
476 return;
477 }
478 if (exprs.len == 1) {
479 const expr = exprs.at(0).*;
480
481 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
482 try renderToken(tree, stream, lbrace, indent, Space.None);
483 try renderExpression(allocator, stream, tree, indent, expr, Space.None);
484 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
485 return;
715486 }
716487
717 try stream.write("error{");
488 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);
489
490 const new_indent = indent + indent_delta;
491 try renderToken(tree, stream, lbrace, new_indent, Space.Newline);
492
493 var it = exprs.iterator(0);
494 while (it.next()) |expr| {
495 try stream.writeByteNTimes(' ', new_indent);
496
497 if (it.peek()) |next_expr| {
498 try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);
718499
719 try stack.append(RenderState { .Text = "}"});
720 try stack.append(RenderState.PrintIndent);
721 try stack.append(RenderState { .Indent = indent });
722 try stack.append(RenderState { .Text = "\n"});
500 const comma = tree.nextToken(expr.*.lastToken());
501 try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
723502
724 var i = err_set_decl.decls.len;
725 while (i != 0) {
726 i -= 1;
727 const node = *err_set_decl.decls.at(i);
728 if (node.id != ast.Node.Id.LineComment) {
729 try stack.append(RenderState { .Text = "," });
503 try renderExtraNewline(tree, stream, next_expr.*);
504 } else {
505 try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline);
730506 }
731 try stack.append(RenderState { .TopLevelDecl = node });
732 try stack.append(RenderState.PrintIndent);
733 try stack.append(RenderState {
734 .Text = blk: {
735 if (i != 0) {
736 const prev_node = *err_set_decl.decls.at(i - 1);
737 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
738 const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken());
739 if (loc.line >= 2) {
740 break :blk "\n\n";
741 }
742 }
743 break :blk "\n";
744 },
745 });
746 }
747 try stack.append(RenderState { .Indent = indent + indent_delta});
748 },
749 ast.Node.Id.MultilineStringLiteral => {
750 const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
751 try stream.print("\n");
752
753 var i : usize = 0;
754 while (i < multiline_str_literal.lines.len) : (i += 1) {
755 const t = *multiline_str_literal.lines.at(i);
756 try stream.writeByteNTimes(' ', indent + indent_delta);
757 try stream.print("{}", tree.tokenSlice(t));
758507 }
508
759509 try stream.writeByteNTimes(' ', indent);
510 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
760511 },
761 ast.Node.Id.UndefinedLiteral => {
762 const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base);
763 try stream.print("{}", tree.tokenSlice(undefined_literal.token));
764 },
765 ast.Node.Id.BuiltinCall => {
766 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
767 try stream.print("{}(", tree.tokenSlice(builtin_call.builtin_token));
768 try stack.append(RenderState { .Text = ")"});
769 var i = builtin_call.params.len;
770 while (i != 0) {
771 i -= 1;
772 const param_node = *builtin_call.params.at(i);
773 try stack.append(RenderState { .Expression = param_node});
774 if (i != 0) {
775 try stack.append(RenderState { .Text = ", " });
776 }
512 }
513 },
514
515 ast.Node.Id.ControlFlowExpression => {
516 const flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", base);
517
518 switch (flow_expr.kind) {
519 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {
520 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;
521 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
522 if (maybe_label) |label| {
523 const colon = tree.nextToken(flow_expr.ltoken);
524 try renderToken(tree, stream, colon, indent, Space.None);
525
526 const expr_space = if (flow_expr.rhs != null) Space.Space else space;
527 try renderExpression(allocator, stream, tree, indent, label, expr_space);
777528 }
778529 },
779 ast.Node.Id.FnProto => {
780 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
781
782 switch (fn_proto.return_type) {
783 ast.Node.FnProto.ReturnType.Explicit => |node| {
784 try stack.append(RenderState { .Expression = node});
785 },
786 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {
787 try stack.append(RenderState { .Expression = node});
788 try stack.append(RenderState { .Text = "!"});
789 },
530 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {
531 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;
532 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
533 if (maybe_label) |label| {
534 const colon = tree.nextToken(flow_expr.ltoken);
535 try renderToken(tree, stream, colon, indent, Space.None);
536
537 const expr_space = if (flow_expr.rhs != null) Space.Space else space;
538 try renderExpression(allocator, stream, tree, indent, label, space);
790539 }
540 },
541 ast.Node.ControlFlowExpression.Kind.Return => {
542 const kw_space = if (flow_expr.rhs != null) Space.Space else space;
543 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);
544 },
545 }
791546
792 if (fn_proto.align_expr) |align_expr| {
793 try stack.append(RenderState { .Text = ") " });
794 try stack.append(RenderState { .Expression = align_expr});
795 try stack.append(RenderState { .Text = "align(" });
796 }
547 if (flow_expr.rhs) |rhs| {
548 try renderExpression(allocator, stream, tree, indent, rhs, space);
549 }
550 },
797551
798 try stack.append(RenderState { .Text = ") " });
799 var i = fn_proto.params.len;
800 while (i != 0) {
801 i -= 1;
802 const param_decl_node = *fn_proto.params.at(i);
803 try stack.append(RenderState { .ParamDecl = param_decl_node});
804 if (i != 0) {
805 try stack.append(RenderState { .Text = ", " });
806 }
807 }
552 ast.Node.Id.Payload => {
553 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
808554
809 try stack.append(RenderState { .Text = "(" });
810 if (fn_proto.name_token) |name_token| {
811 try stack.append(RenderState { .Text = tree.tokenSlice(name_token) });
812 try stack.append(RenderState { .Text = " " });
813 }
555 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
556 try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None);
557 try renderToken(tree, stream, payload.rpipe, indent, space);
558 },
814559
815 try stack.append(RenderState { .Text = "fn" });
560 ast.Node.Id.PointerPayload => {
561 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
816562
817 if (fn_proto.async_attr) |async_attr| {
818 try stack.append(RenderState { .Text = " " });
819 try stack.append(RenderState { .Expression = &async_attr.base });
820 }
563 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
564 if (payload.ptr_token) |ptr_token| {
565 try renderToken(tree, stream, ptr_token, indent, Space.None);
566 }
567 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);
568 try renderToken(tree, stream, payload.rpipe, indent, space);
569 },
821570
822 if (fn_proto.cc_token) |cc_token| {
823 try stack.append(RenderState { .Text = " " });
824 try stack.append(RenderState { .Text = tree.tokenSlice(cc_token) });
825 }
571 ast.Node.Id.PointerIndexPayload => {
572 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
826573
827 if (fn_proto.lib_name) |lib_name| {
828 try stack.append(RenderState { .Text = " " });
829 try stack.append(RenderState { .Expression = lib_name });
830 }
831 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
832 try stack.append(RenderState { .Text = " " });
833 try stack.append(RenderState { .Text = tree.tokenSlice(extern_export_inline_token) });
834 }
574 try renderToken(tree, stream, payload.lpipe, indent, Space.None);
575 if (payload.ptr_token) |ptr_token| {
576 try renderToken(tree, stream, ptr_token, indent, Space.None);
577 }
578 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);
835579
836 if (fn_proto.visib_token) |visib_token_index| {
837 const visib_token = tree.tokens.at(visib_token_index);
838 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);
839 try stack.append(RenderState { .Text = " " });
840 try stack.append(RenderState { .Text = tree.tokenSlice(visib_token_index) });
841 }
580 if (payload.index_symbol) |index_symbol| {
581 const comma = tree.nextToken(payload.value_symbol.lastToken());
582
583 try renderToken(tree, stream, comma, indent, Space.Space);
584 try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None);
585 }
586
587 try renderToken(tree, stream, payload.rpipe, indent, space);
588 },
589
590 ast.Node.Id.GroupedExpression => {
591 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
592
593 try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None);
594 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None);
595 try renderToken(tree, stream, grouped_expr.rparen, indent, space);
596 },
597
598 ast.Node.Id.FieldInitializer => {
599 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
600
601 try renderToken(tree, stream, field_init.period_token, indent, Space.None); // .
602 try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name
603 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // =
604 try renderExpression(allocator, stream, tree, indent, field_init.expr, space);
605 },
606
607 ast.Node.Id.IntegerLiteral => {
608 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);
609 try renderToken(tree, stream, integer_literal.token, indent, space);
610 },
611 ast.Node.Id.FloatLiteral => {
612 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);
613 try renderToken(tree, stream, float_literal.token, indent, space);
614 },
615 ast.Node.Id.StringLiteral => {
616 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);
617 try renderToken(tree, stream, string_literal.token, indent, space);
618 },
619 ast.Node.Id.CharLiteral => {
620 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
621 try renderToken(tree, stream, char_literal.token, indent, space);
622 },
623 ast.Node.Id.BoolLiteral => {
624 const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
625 try renderToken(tree, stream, bool_literal.token, indent, space);
626 },
627 ast.Node.Id.NullLiteral => {
628 const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base);
629 try renderToken(tree, stream, null_literal.token, indent, space);
630 },
631 ast.Node.Id.ThisLiteral => {
632 const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base);
633 try renderToken(tree, stream, this_literal.token, indent, space);
634 },
635 ast.Node.Id.Unreachable => {
636 const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base);
637 try renderToken(tree, stream, unreachable_node.token, indent, space);
638 },
639 ast.Node.Id.ErrorType => {
640 const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base);
641 try renderToken(tree, stream, error_type.token, indent, space);
642 },
643 ast.Node.Id.VarType => {
644 const var_type = @fieldParentPtr(ast.Node.VarType, "base", base);
645 try renderToken(tree, stream, var_type.token, indent, space);
646 },
647 ast.Node.Id.ContainerDecl => {
648 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
649
650 if (container_decl.layout_token) |layout_token| {
651 try renderToken(tree, stream, layout_token, indent, Space.Space);
652 }
653
654 switch (container_decl.init_arg_expr) {
655 ast.Node.ContainerDecl.InitArg.None => {
656 try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union
842657 },
843 ast.Node.Id.PromiseType => {
844 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);
845 try stream.write(tree.tokenSlice(promise_type.promise_token));
846 if (promise_type.result) |result| {
847 try stream.write(tree.tokenSlice(result.arrow_token));
848 try stack.append(RenderState { .Expression = result.return_type});
658 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
659 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union
660
661 const lparen = tree.nextToken(container_decl.kind_token);
662 const enum_token = tree.nextToken(lparen);
663
664 try renderToken(tree, stream, lparen, indent, Space.None); // (
665 try renderToken(tree, stream, enum_token, indent, Space.None); // enum
666
667 if (enum_tag_type) |expr| {
668 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // (
669 try renderExpression(allocator, stream, tree, indent, expr, Space.None);
670
671 const rparen = tree.nextToken(expr.lastToken());
672 try renderToken(tree, stream, rparen, indent, Space.None); // )
673 try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // )
674 } else {
675 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.Space); // )
849676 }
850677 },
851 ast.Node.Id.LineComment => {
852 const line_comment_node = @fieldParentPtr(ast.Node.LineComment, "base", base);
853 try stream.write(tree.tokenSlice(line_comment_node.token));
678 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
679 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union
680
681 const lparen = tree.nextToken(container_decl.kind_token);
682 const rparen = tree.nextToken(type_expr.lastToken());
683
684 try renderToken(tree, stream, lparen, indent, Space.None); // (
685 try renderExpression(allocator, stream, tree, indent, type_expr, Space.None);
686 try renderToken(tree, stream, rparen, indent, Space.Space); // )
854687 },
855 ast.Node.Id.DocComment => unreachable, // doc comments are attached to nodes
856 ast.Node.Id.Switch => {
857 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
688 }
858689
859 try stream.print("{} (", tree.tokenSlice(switch_node.switch_token));
690 if (container_decl.fields_and_decls.len == 0) {
691 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // {
692 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }
693 } else {
694 const new_indent = indent + indent_delta;
695 try renderToken(tree, stream, container_decl.lbrace_token, new_indent, Space.Newline); // {
860696
861 if (switch_node.cases.len == 0) {
862 try stack.append(RenderState { .Text = ") {}"});
863 try stack.append(RenderState { .Expression = switch_node.expr });
864 continue;
865 }
697 var it = container_decl.fields_and_decls.iterator(0);
698 while (it.next()) |decl| {
699 try stream.writeByteNTimes(' ', new_indent);
700 try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*);
866701
867 try stack.append(RenderState { .Text = "}"});
868 try stack.append(RenderState.PrintIndent);
869 try stack.append(RenderState { .Indent = indent });
870 try stack.append(RenderState { .Text = "\n"});
871
872 var i = switch_node.cases.len;
873 while (i != 0) {
874 i -= 1;
875 const node = *switch_node.cases.at(i);
876 try stack.append(RenderState { .Expression = node});
877 try stack.append(RenderState.PrintIndent);
878 try stack.append(RenderState {
879 .Text = blk: {
880 if (i != 0) {
881 const prev_node = *switch_node.cases.at(i - 1);
882 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
883 const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken());
884 if (loc.line >= 2) {
885 break :blk "\n\n";
886 }
887 }
888 break :blk "\n";
889 },
890 });
702 if (it.peek()) |next_decl| {
703 try renderExtraNewline(tree, stream, next_decl.*);
891704 }
892 try stack.append(RenderState { .Indent = indent + indent_delta});
893 try stack.append(RenderState { .Text = ") {"});
894 try stack.append(RenderState { .Expression = switch_node.expr });
895 },
896 ast.Node.Id.SwitchCase => {
897 const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
898
899 try stack.append(RenderState { .Token = switch_case.lastToken() + 1 });
900 try stack.append(RenderState { .Expression = switch_case.expr });
901 if (switch_case.payload) |payload| {
902 try stack.append(RenderState { .Text = " " });
903 try stack.append(RenderState { .Expression = payload });
904 }
905 try stack.append(RenderState { .Text = " => "});
705 }
906706
907 var i = switch_case.items.len;
908 while (i != 0) {
909 i -= 1;
910 try stack.append(RenderState { .Expression = *switch_case.items.at(i) });
707 try stream.writeByteNTimes(' ', indent);
708 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }
709 }
710 },
911711
912 if (i != 0) {
913 try stack.append(RenderState.PrintIndent);
914 try stack.append(RenderState { .Text = ",\n" });
915 }
916 }
712 ast.Node.Id.ErrorSetDecl => {
713 const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
714
715 const lbrace = tree.nextToken(err_set_decl.error_token);
716
717 if (err_set_decl.decls.len == 0) {
718 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None);
719 try renderToken(tree, stream, lbrace, indent, Space.None);
720 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space);
721 return;
722 }
723
724 if (err_set_decl.decls.len == 1) blk: {
725 const node = err_set_decl.decls.at(0).*;
726
727 // if there are any doc comments or same line comments
728 // don't try to put it all on one line
729 if (node.cast(ast.Node.ErrorTag)) |tag| {
730 if (tag.doc_comments != null) break :blk;
731 } else {
732 break :blk;
733 }
734
735 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error
736 try renderToken(tree, stream, lbrace, indent, Space.None); // {
737 try renderExpression(allocator, stream, tree, indent, node, Space.None);
738 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }
739 return;
740 }
741
742 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error
743 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {
744 const new_indent = indent + indent_delta;
745
746 var it = err_set_decl.decls.iterator(0);
747 while (it.next()) |node| {
748 try stream.writeByteNTimes(' ', new_indent);
749
750 if (it.peek()) |next_node| {
751 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);
752 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,
753
754 try renderExtraNewline(tree, stream, next_node.*);
755 } else {
756 try renderTrailingComma(allocator, stream, tree, new_indent, node.*, Space.Newline);
757 }
758 }
759
760 try stream.writeByteNTimes(' ', indent);
761 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }
762 },
763
764 ast.Node.Id.ErrorTag => {
765 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
766
767 try renderDocComments(tree, stream, tag, indent);
768 try renderToken(tree, stream, tag.name_token, indent, space); // name
769 },
770
771 ast.Node.Id.MultilineStringLiteral => {
772 const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
773
774 var skip_first_indent = true;
775 if (tree.tokens.at(multiline_str_literal.firstToken() - 1).id != Token.Id.LineComment) {
776 try stream.print("\n");
777 skip_first_indent = false;
778 }
779
780 var i: usize = 0;
781 while (i < multiline_str_literal.lines.len) : (i += 1) {
782 const t = multiline_str_literal.lines.at(i).*;
783 if (!skip_first_indent) {
784 try stream.writeByteNTimes(' ', indent + indent_delta);
785 }
786 try renderToken(tree, stream, t, indent, Space.None);
787 skip_first_indent = false;
788 }
789 try stream.writeByteNTimes(' ', indent);
790 },
791 ast.Node.Id.UndefinedLiteral => {
792 const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base);
793 try renderToken(tree, stream, undefined_literal.token, indent, space);
794 },
795
796 ast.Node.Id.BuiltinCall => {
797 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
798
799 try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name
800 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // (
801
802 var it = builtin_call.params.iterator(0);
803 while (it.next()) |param_node| {
804 try renderExpression(allocator, stream, tree, indent, param_node.*, Space.None);
805
806 if (it.peek() != null) {
807 const comma_token = tree.nextToken(param_node.*.lastToken());
808 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,
809 }
810 }
811 try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // )
812 },
813
814 ast.Node.Id.FnProto => {
815 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
816
817 if (fn_proto.visib_token) |visib_token_index| {
818 const visib_token = tree.tokens.at(visib_token_index);
819 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);
820
821 try renderToken(tree, stream, visib_token_index, indent, Space.Space); // pub
822 }
823
824 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
825 try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export
826 }
827
828 if (fn_proto.lib_name) |lib_name| {
829 try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space);
830 }
831
832 if (fn_proto.cc_token) |cc_token| {
833 try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc
834 }
835
836 if (fn_proto.async_attr) |async_attr| {
837 try renderExpression(allocator, stream, tree, indent, &async_attr.base, Space.Space);
838 }
839
840 if (fn_proto.name_token) |name_token| blk: {
841 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn
842 try renderToken(tree, stream, name_token, indent, Space.None); // name
843 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.None); // (
844 } else blk: {
845 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn
846 try renderToken(tree, stream, tree.nextToken(fn_proto.fn_token), indent, Space.None); // (
847 }
848
849 var it = fn_proto.params.iterator(0);
850 while (it.next()) |param_decl_node| {
851 try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*);
852
853 if (it.peek() != null) {
854 const comma = tree.nextToken(param_decl_node.*.lastToken());
855 try renderToken(tree, stream, comma, indent, Space.Space); // ,
856 }
857 }
858
859 const rparen = tree.prevToken(switch (fn_proto.return_type) {
860 ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(),
861 ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()),
862 });
863 try renderToken(tree, stream, rparen, indent, Space.Space); // )
864
865 if (fn_proto.align_expr) |align_expr| {
866 const align_rparen = tree.nextToken(align_expr.lastToken());
867 const align_lparen = tree.prevToken(align_expr.firstToken());
868 const align_kw = tree.prevToken(align_lparen);
869
870 try renderToken(tree, stream, align_kw, indent, Space.None); // align
871 try renderToken(tree, stream, align_lparen, indent, Space.None); // (
872 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);
873 try renderToken(tree, stream, align_rparen, indent, Space.Space); // )
874 }
875
876 switch (fn_proto.return_type) {
877 ast.Node.FnProto.ReturnType.Explicit => |node| {
878 try renderExpression(allocator, stream, tree, indent, node, space);
917879 },
918 ast.Node.Id.SwitchElse => {
919 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
920 try stream.print("{}", tree.tokenSlice(switch_else.token));
880 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {
881 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // !
882 try renderExpression(allocator, stream, tree, indent, node, space);
921883 },
922 ast.Node.Id.Else => {
923 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
924 try stream.print("{}", tree.tokenSlice(else_node.else_token));
925
926 switch (else_node.body.id) {
927 ast.Node.Id.Block, ast.Node.Id.If,
928 ast.Node.Id.For, ast.Node.Id.While,
929 ast.Node.Id.Switch => {
930 try stream.print(" ");
931 try stack.append(RenderState { .Expression = else_node.body });
932 },
933 else => {
934 try stack.append(RenderState { .Indent = indent });
935 try stack.append(RenderState { .Expression = else_node.body });
936 try stack.append(RenderState.PrintIndent);
937 try stack.append(RenderState { .Indent = indent + indent_delta });
938 try stack.append(RenderState { .Text = "\n" });
939 }
940 }
884 }
885 },
886
887 ast.Node.Id.PromiseType => {
888 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);
889
890 if (promise_type.result) |result| {
891 try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise
892 try renderToken(tree, stream, result.arrow_token, indent, Space.None); // ->
893 try renderExpression(allocator, stream, tree, indent, result.return_type, space);
894 } else {
895 try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise
896 }
897 },
898
899 ast.Node.Id.DocComment => unreachable, // doc comments are attached to nodes
900
901 ast.Node.Id.Switch => {
902 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
903
904 try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch
905 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // (
906
907 const rparen = tree.nextToken(switch_node.expr.lastToken());
908 const lbrace = tree.nextToken(rparen);
909
910 if (switch_node.cases.len == 0) {
911 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);
912 try renderToken(tree, stream, rparen, indent, Space.Space); // )
913 try renderToken(tree, stream, lbrace, indent, Space.None); // {
914 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }
915 return;
916 }
917
918 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);
919
920 try renderToken(tree, stream, rparen, indent, Space.Space); // )
921 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {
922
923 const new_indent = indent + indent_delta;
924
925 var it = switch_node.cases.iterator(0);
926 while (it.next()) |node| {
927 try stream.writeByteNTimes(' ', new_indent);
928 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.Newline);
941929
942 if (else_node.payload) |payload| {
943 try stack.append(RenderState { .Text = " " });
944 try stack.append(RenderState { .Expression = payload });
930 if (it.peek()) |next_node| {
931 try renderExtraNewline(tree, stream, next_node.*);
932 }
933 }
934
935 try stream.writeByteNTimes(' ', indent);
936 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }
937 },
938
939 ast.Node.Id.SwitchCase => {
940 const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
941
942 assert(switch_case.items.len != 0);
943 const src_has_trailing_comma = blk: {
944 const last_node = switch_case.items.at(switch_case.items.len - 1).*;
945 const maybe_comma = tree.nextToken(last_node.lastToken());
946 break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma;
947 };
948
949 if (switch_case.items.len == 1 or !src_has_trailing_comma) {
950 var it = switch_case.items.iterator(0);
951 while (it.next()) |node| {
952 if (it.peek()) |next_node| {
953 try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
954
955 const comma_token = tree.nextToken(node.*.lastToken());
956 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,
957 try renderExtraNewline(tree, stream, next_node.*);
958 } else {
959 try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);
945960 }
946 },
947 ast.Node.Id.While => {
948 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
949 if (while_node.label) |label| {
950 try stream.print("{}: ", tree.tokenSlice(label));
961 }
962 } else {
963 var it = switch_case.items.iterator(0);
964 while (true) {
965 const node = ??it.next();
966 if (it.peek()) |next_node| {
967 try renderExpression(allocator, stream, tree, indent, node.*, Space.None);
968
969 const comma_token = tree.nextToken(node.*.lastToken());
970 try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,
971 try renderExtraNewline(tree, stream, next_node.*);
972 try stream.writeByteNTimes(' ', indent);
973 } else {
974 try renderTrailingComma(allocator, stream, tree, indent, node.*, Space.Space);
975 break;
951976 }
977 }
978 }
952979
953 if (while_node.inline_token) |inline_token| {
954 try stream.print("{} ", tree.tokenSlice(inline_token));
955 }
980 try renderToken(tree, stream, switch_case.arrow_token, indent, Space.Space); // =>
956981
957 try stream.print("{} ", tree.tokenSlice(while_node.while_token));
982 if (switch_case.payload) |payload| {
983 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
984 }
958985
959 if (while_node.@"else") |@"else"| {
960 try stack.append(RenderState { .Expression = &@"else".base });
986 try renderTrailingComma(allocator, stream, tree, indent, switch_case.expr, space);
987 },
988 ast.Node.Id.SwitchElse => {
989 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
990 try renderToken(tree, stream, switch_else.token, indent, space);
991 },
992 ast.Node.Id.Else => {
993 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
994
995 const block_body = switch (else_node.body.id) {
996 ast.Node.Id.Block,
997 ast.Node.Id.If,
998 ast.Node.Id.For,
999 ast.Node.Id.While,
1000 ast.Node.Id.Switch => true,
1001 else => false,
1002 };
1003
1004 const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline;
1005 try renderToken(tree, stream, else_node.else_token, indent, after_else_space);
1006
1007 if (else_node.payload) |payload| {
1008 const payload_space = if (block_body) Space.Space else Space.Newline;
1009 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1010 }
9611011
962 if (while_node.body.id == ast.Node.Id.Block) {
963 try stack.append(RenderState { .Text = " " });
964 } else {
965 try stack.append(RenderState.PrintIndent);
966 try stack.append(RenderState { .Text = "\n" });
967 }
968 }
1012 if (block_body) {
1013 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1014 } else {
1015 try stream.writeByteNTimes(' ', indent + indent_delta);
1016 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1017 }
1018 },
1019
1020 ast.Node.Id.While => {
1021 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
1022
1023 if (while_node.label) |label| {
1024 try renderToken(tree, stream, label, indent, Space.None); // label
1025 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :
1026 }
1027
1028 if (while_node.inline_token) |inline_token| {
1029 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline
1030 }
1031
1032 try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while
1033 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // (
1034 try renderExpression(allocator, stream, tree, indent, while_node.condition, Space.None);
1035
1036 {
1037 const rparen = tree.nextToken(while_node.condition.lastToken());
1038 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or
1039 while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1040 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1041 }
1042
1043 if (while_node.payload) |payload| {
1044 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1045 }
1046
1047 if (while_node.continue_expr) |continue_expr| {
1048 const rparen = tree.nextToken(continue_expr.lastToken());
1049 const lparen = tree.prevToken(continue_expr.firstToken());
1050 const colon = tree.prevToken(lparen);
1051
1052 try renderToken(tree, stream, colon, indent, Space.Space); // :
1053 try renderToken(tree, stream, lparen, indent, Space.None); // (
1054
1055 try renderExpression(allocator, stream, tree, indent, continue_expr, Space.None);
1056
1057 const rparen_space = if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1058 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1059 }
1060
1061 const body_space = blk: {
1062 if (while_node.@"else" != null) {
1063 break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1064 } else {
1065 break :blk space;
1066 }
1067 };
1068
1069 if (while_node.body.id == ast.Node.Id.Block) {
1070 try renderExpression(allocator, stream, tree, indent, while_node.body, body_space);
1071 } else {
1072 try stream.writeByteNTimes(' ', indent + indent_delta);
1073 try renderExpression(allocator, stream, tree, indent, while_node.body, body_space);
1074 }
1075
1076 if (while_node.@"else") |@"else"| {
1077 if (while_node.body.id == ast.Node.Id.Block) {
1078 } else {
1079 try stream.writeByteNTimes(' ', indent);
1080 }
1081
1082 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1083 }
1084 },
1085
1086 ast.Node.Id.For => {
1087 const for_node = @fieldParentPtr(ast.Node.For, "base", base);
1088
1089 if (for_node.label) |label| {
1090 try renderToken(tree, stream, label, indent, Space.None); // label
1091 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :
1092 }
1093
1094 if (for_node.inline_token) |inline_token| {
1095 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline
1096 }
1097
1098 try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for
1099 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // (
1100 try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None);
9691101
970 if (while_node.body.id == ast.Node.Id.Block) {
971 try stack.append(RenderState { .Expression = while_node.body });
972 try stack.append(RenderState { .Text = " " });
1102 const rparen = tree.nextToken(for_node.array_expr.lastToken());
1103 const rparen_space = if (for_node.payload != null or
1104 for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1105 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1106
1107 if (for_node.payload) |payload| {
1108 const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1109 try renderExpression(allocator, stream, tree, indent, payload, payload_space);
1110 }
1111
1112 const body_space = blk: {
1113 if (for_node.@"else" != null) {
1114 if (for_node.body.id == ast.Node.Id.Block) {
1115 break :blk Space.Space;
9731116 } else {
974 try stack.append(RenderState { .Indent = indent });
975 try stack.append(RenderState { .Expression = while_node.body });
976 try stack.append(RenderState.PrintIndent);
977 try stack.append(RenderState { .Indent = indent + indent_delta });
978 try stack.append(RenderState { .Text = "\n" });
1117 break :blk Space.Newline;
9791118 }
1119 } else {
1120 break :blk space;
1121 }
1122 };
1123 if (for_node.body.id == ast.Node.Id.Block) {
1124 try renderExpression(allocator, stream, tree, indent, for_node.body, body_space);
1125 } else {
1126 try stream.writeByteNTimes(' ', indent + indent_delta);
1127 try renderExpression(allocator, stream, tree, indent, for_node.body, body_space);
1128 }
9801129
981 if (while_node.continue_expr) |continue_expr| {
982 try stack.append(RenderState { .Text = ")" });
983 try stack.append(RenderState { .Expression = continue_expr });
984 try stack.append(RenderState { .Text = ": (" });
985 try stack.append(RenderState { .Text = " " });
986 }
1130 if (for_node.@"else") |@"else"| {
1131 if (for_node.body.id != ast.Node.Id.Block) {
1132 try stream.writeByteNTimes(' ', indent);
1133 }
9871134
988 if (while_node.payload) |payload| {
989 try stack.append(RenderState { .Expression = payload });
990 try stack.append(RenderState { .Text = " " });
991 }
1135 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1136 }
1137 },
9921138
993 try stack.append(RenderState { .Text = ")" });
994 try stack.append(RenderState { .Expression = while_node.condition });
995 try stack.append(RenderState { .Text = "(" });
996 },
997 ast.Node.Id.For => {
998 const for_node = @fieldParentPtr(ast.Node.For, "base", base);
999 if (for_node.label) |label| {
1000 try stream.print("{}: ", tree.tokenSlice(label));
1001 }
1139 ast.Node.Id.If => {
1140 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
10021141
1003 if (for_node.inline_token) |inline_token| {
1004 try stream.print("{} ", tree.tokenSlice(inline_token));
1005 }
1142 try renderToken(tree, stream, if_node.if_token, indent, Space.Space);
1143 try renderToken(tree, stream, tree.prevToken(if_node.condition.firstToken()), indent, Space.None);
10061144
1007 try stream.print("{} ", tree.tokenSlice(for_node.for_token));
1145 try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None);
1146 try renderToken(tree, stream, tree.nextToken(if_node.condition.lastToken()), indent, Space.Space);
10081147
1009 if (for_node.@"else") |@"else"| {
1010 try stack.append(RenderState { .Expression = &@"else".base });
1148 if (if_node.payload) |payload| {
1149 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
1150 }
10111151
1012 if (for_node.body.id == ast.Node.Id.Block) {
1013 try stack.append(RenderState { .Text = " " });
1152 switch (if_node.body.id) {
1153 ast.Node.Id.Block,
1154 ast.Node.Id.If,
1155 ast.Node.Id.For,
1156 ast.Node.Id.While,
1157 ast.Node.Id.Switch => {
1158 if (if_node.@"else") |@"else"| {
1159 if (if_node.body.id == ast.Node.Id.Block) {
1160 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);
10141161 } else {
1015 try stack.append(RenderState.PrintIndent);
1016 try stack.append(RenderState { .Text = "\n" });
1162 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Newline);
1163 try stream.writeByteNTimes(' ', indent);
10171164 }
1018 }
10191165
1020 if (for_node.body.id == ast.Node.Id.Block) {
1021 try stack.append(RenderState { .Expression = for_node.body });
1022 try stack.append(RenderState { .Text = " " });
1166 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
10231167 } else {
1024 try stack.append(RenderState { .Indent = indent });
1025 try stack.append(RenderState { .Expression = for_node.body });
1026 try stack.append(RenderState.PrintIndent);
1027 try stack.append(RenderState { .Indent = indent + indent_delta });
1028 try stack.append(RenderState { .Text = "\n" });
1168 try renderExpression(allocator, stream, tree, indent, if_node.body, space);
10291169 }
1030
1031 if (for_node.payload) |payload| {
1032 try stack.append(RenderState { .Expression = payload });
1033 try stack.append(RenderState { .Text = " " });
1034 }
1035
1036 try stack.append(RenderState { .Text = ")" });
1037 try stack.append(RenderState { .Expression = for_node.array_expr });
1038 try stack.append(RenderState { .Text = "(" });
10391170 },
1040 ast.Node.Id.If => {
1041 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
1042 try stream.print("{} ", tree.tokenSlice(if_node.if_token));
1043
1044 switch (if_node.body.id) {
1045 ast.Node.Id.Block, ast.Node.Id.If,
1046 ast.Node.Id.For, ast.Node.Id.While,
1047 ast.Node.Id.Switch => {
1048 if (if_node.@"else") |@"else"| {
1049 try stack.append(RenderState { .Expression = &@"else".base });
1050
1051 if (if_node.body.id == ast.Node.Id.Block) {
1052 try stack.append(RenderState { .Text = " " });
1053 } else {
1054 try stack.append(RenderState.PrintIndent);
1055 try stack.append(RenderState { .Text = "\n" });
1056 }
1057 }
1058 },
1059 else => {
1060 if (if_node.@"else") |@"else"| {
1061 try stack.append(RenderState { .Expression = @"else".body });
1062
1063 if (@"else".payload) |payload| {
1064 try stack.append(RenderState { .Text = " " });
1065 try stack.append(RenderState { .Expression = payload });
1066 }
1067
1068 try stack.append(RenderState { .Text = " " });
1069 try stack.append(RenderState { .Text = tree.tokenSlice(@"else".else_token) });
1070 try stack.append(RenderState { .Text = " " });
1071 }
1171 else => {
1172 if (if_node.@"else") |@"else"| {
1173 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);
1174 try renderToken(tree, stream, @"else".else_token, indent, Space.Space);
1175
1176 if (@"else".payload) |payload| {
1177 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);
10721178 }
1179
1180 try renderExpression(allocator, stream, tree, indent, @"else".body, space);
1181 } else {
1182 try renderExpression(allocator, stream, tree, indent, if_node.body, space);
10731183 }
1184 },
1185 }
1186 },
10741187
1075 try stack.append(RenderState { .Expression = if_node.body });
1188 ast.Node.Id.Asm => {
1189 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
10761190
1077 if (if_node.payload) |payload| {
1078 try stack.append(RenderState { .Text = " " });
1079 try stack.append(RenderState { .Expression = payload });
1080 }
1191 try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm
10811192
1082 try stack.append(RenderState { .NonBreakToken = if_node.condition.lastToken() + 1 });
1083 try stack.append(RenderState { .Expression = if_node.condition });
1084 try stack.append(RenderState { .Text = "(" });
1085 },
1086 ast.Node.Id.Asm => {
1087 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
1088 try stream.print("{} ", tree.tokenSlice(asm_node.asm_token));
1193 if (asm_node.volatile_token) |volatile_token| {
1194 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile
1195 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // (
1196 } else {
1197 try renderToken(tree, stream, tree.nextToken(asm_node.asm_token), indent, Space.None); // (
1198 }
10891199
1090 if (asm_node.volatile_token) |volatile_token| {
1091 try stream.print("{} ", tree.tokenSlice(volatile_token));
1092 }
1200 try renderExpression(allocator, stream, tree, indent, asm_node.template, Space.Newline);
1201 const indent_once = indent + indent_delta;
1202 try stream.writeByteNTimes(' ', indent_once);
1203 try stream.print(": ");
1204 const indent_extra = indent_once + 2;
10931205
1094 try stack.append(RenderState { .Indent = indent });
1095 try stack.append(RenderState { .Text = ")" });
1096 {
1097 var i = asm_node.clobbers.len;
1098 while (i != 0) {
1099 i -= 1;
1100 try stack.append(RenderState { .Expression = *asm_node.clobbers.at(i) });
1101
1102 if (i != 0) {
1103 try stack.append(RenderState { .Text = ", " });
1104 }
1105 }
1206 {
1207 var it = asm_node.outputs.iterator(0);
1208 while (it.next()) |asm_output| {
1209 const node = &(asm_output.*).base;
1210 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
1211
1212 if (it.peek()) |next_asm_output| {
1213 const next_node = &(next_asm_output.*).base;
1214
1215 const comma = tree.prevToken(next_asm_output.*.firstToken());
1216 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,
1217 try renderExtraNewline(tree, stream, next_node);
1218
1219 try stream.writeByteNTimes(' ', indent_extra);
11061220 }
1107 try stack.append(RenderState { .Text = ": " });
1108 try stack.append(RenderState.PrintIndent);
1109 try stack.append(RenderState { .Indent = indent + indent_delta });
1110 try stack.append(RenderState { .Text = "\n" });
1111 {
1112 var i = asm_node.inputs.len;
1113 while (i != 0) {
1114 i -= 1;
1115 const node = *asm_node.inputs.at(i);
1116 try stack.append(RenderState { .Expression = &node.base});
1117
1118 if (i != 0) {
1119 try stack.append(RenderState.PrintIndent);
1120 try stack.append(RenderState {
1121 .Text = blk: {
1122 const prev_node = *asm_node.inputs.at(i - 1);
1123 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
1124 const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken());
1125 if (loc.line >= 2) {
1126 break :blk "\n\n";
1127 }
1128 break :blk "\n";
1129 },
1130 });
1131 try stack.append(RenderState { .Text = "," });
1132 }
1133 }
1221 }
1222 }
1223
1224 try stream.write("\n");
1225 try stream.writeByteNTimes(' ', indent_once);
1226 try stream.write(": ");
1227
1228 {
1229 var it = asm_node.inputs.iterator(0);
1230 while (it.next()) |asm_input| {
1231 const node = &(asm_input.*).base;
1232 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
1233
1234 if (it.peek()) |next_asm_input| {
1235 const next_node = &(next_asm_input.*).base;
1236
1237 const comma = tree.prevToken(next_asm_input.*.firstToken());
1238 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,
1239 try renderExtraNewline(tree, stream, next_node);
1240
1241 try stream.writeByteNTimes(' ', indent_extra);
11341242 }
1135 try stack.append(RenderState { .Indent = indent + indent_delta + 2});
1136 try stack.append(RenderState { .Text = ": "});
1137 try stack.append(RenderState.PrintIndent);
1138 try stack.append(RenderState { .Indent = indent + indent_delta});
1139 try stack.append(RenderState { .Text = "\n" });
1140 {
1141 var i = asm_node.outputs.len;
1142 while (i != 0) {
1143 i -= 1;
1144 const node = *asm_node.outputs.at(i);
1145 try stack.append(RenderState { .Expression = &node.base});
1146
1147 if (i != 0) {
1148 try stack.append(RenderState.PrintIndent);
1149 try stack.append(RenderState {
1150 .Text = blk: {
1151 const prev_node = *asm_node.outputs.at(i - 1);
1152 const prev_node_last_token_end = tree.tokens.at(prev_node.lastToken()).end;
1153 const loc = tree.tokenLocation(prev_node_last_token_end, node.firstToken());
1154 if (loc.line >= 2) {
1155 break :blk "\n\n";
1156 }
1157 break :blk "\n";
1158 },
1159 });
1160 try stack.append(RenderState { .Text = "," });
1161 }
1162 }
1243 }
1244 }
1245
1246 try stream.write("\n");
1247 try stream.writeByteNTimes(' ', indent_once);
1248 try stream.write(": ");
1249
1250 {
1251 var it = asm_node.clobbers.iterator(0);
1252 while (it.next()) |node| {
1253 try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None);
1254
1255 if (it.peek() != null) {
1256 try stream.write(", ");
11631257 }
1164 try stack.append(RenderState { .Indent = indent + indent_delta + 2});
1165 try stack.append(RenderState { .Text = ": "});
1166 try stack.append(RenderState.PrintIndent);
1167 try stack.append(RenderState { .Indent = indent + indent_delta});
1168 try stack.append(RenderState { .Text = "\n" });
1169 try stack.append(RenderState { .Expression = asm_node.template });
1170 try stack.append(RenderState { .Text = "(" });
1171 },
1172 ast.Node.Id.AsmInput => {
1173 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
1174
1175 try stack.append(RenderState { .Text = ")"});
1176 try stack.append(RenderState { .Expression = asm_input.expr});
1177 try stack.append(RenderState { .Text = " ("});
1178 try stack.append(RenderState { .Expression = asm_input.constraint });
1179 try stack.append(RenderState { .Text = "] "});
1180 try stack.append(RenderState { .Expression = asm_input.symbolic_name });
1181 try stack.append(RenderState { .Text = "["});
1258 }
1259 }
1260
1261 try renderToken(tree, stream, asm_node.rparen, indent, space);
1262 },
1263
1264 ast.Node.Id.AsmInput => {
1265 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
1266
1267 try stream.write("[");
1268 try renderExpression(allocator, stream, tree, indent, asm_input.symbolic_name, Space.None);
1269 try stream.write("] ");
1270 try renderExpression(allocator, stream, tree, indent, asm_input.constraint, Space.None);
1271 try stream.write(" (");
1272 try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None);
1273 try renderToken(tree, stream, asm_input.lastToken(), indent, space); // )
1274 },
1275
1276 ast.Node.Id.AsmOutput => {
1277 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
1278
1279 try stream.write("[");
1280 try renderExpression(allocator, stream, tree, indent, asm_output.symbolic_name, Space.None);
1281 try stream.write("] ");
1282 try renderExpression(allocator, stream, tree, indent, asm_output.constraint, Space.None);
1283 try stream.write(" (");
1284
1285 switch (asm_output.kind) {
1286 ast.Node.AsmOutput.Kind.Variable => |variable_name| {
1287 try renderExpression(allocator, stream, tree, indent, &variable_name.base, Space.None);
11821288 },
1183 ast.Node.Id.AsmOutput => {
1184 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
1185
1186 try stack.append(RenderState { .Text = ")"});
1187 switch (asm_output.kind) {
1188 ast.Node.AsmOutput.Kind.Variable => |variable_name| {
1189 try stack.append(RenderState { .Expression = &variable_name.base});
1190 },
1191 ast.Node.AsmOutput.Kind.Return => |return_type| {
1192 try stack.append(RenderState { .Expression = return_type});
1193 try stack.append(RenderState { .Text = "-> "});
1194 },
1195 }
1196 try stack.append(RenderState { .Text = " ("});
1197 try stack.append(RenderState { .Expression = asm_output.constraint });
1198 try stack.append(RenderState { .Text = "] "});
1199 try stack.append(RenderState { .Expression = asm_output.symbolic_name });
1200 try stack.append(RenderState { .Text = "["});
1289 ast.Node.AsmOutput.Kind.Return => |return_type| {
1290 try stream.write("-> ");
1291 try renderExpression(allocator, stream, tree, indent, return_type, Space.None);
12011292 },
1293 }
12021294
1203 ast.Node.Id.StructField,
1204 ast.Node.Id.UnionTag,
1205 ast.Node.Id.EnumTag,
1206 ast.Node.Id.ErrorTag,
1207 ast.Node.Id.Root,
1208 ast.Node.Id.VarDecl,
1209 ast.Node.Id.Use,
1210 ast.Node.Id.TestDecl,
1211 ast.Node.Id.ParamDecl => unreachable,
1212 },
1213 RenderState.Statement => |base| {
1214 switch (base.id) {
1215 ast.Node.Id.VarDecl => {
1216 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
1217 try stack.append(RenderState { .VarDecl = var_decl});
1218 },
1219 else => {
1220 try stack.append(RenderState { .MaybeSemiColon = base });
1221 try stack.append(RenderState { .Expression = base });
1222 },
1223 }
1224 },
1225 RenderState.Indent => |new_indent| indent = new_indent,
1226 RenderState.PrintIndent => try stream.writeByteNTimes(' ', indent),
1227 RenderState.Token => |token_index| try renderToken(tree, stream, token_index, indent, true),
1228 RenderState.NonBreakToken => |token_index| try renderToken(tree, stream, token_index, indent, false),
1229 RenderState.MaybeSemiColon => |base| {
1230 if (base.requireSemiColon()) {
1231 const semicolon_index = base.lastToken() + 1;
1232 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);
1233 try renderToken(tree, stream, semicolon_index, indent, true);
1234 }
1235 },
1295 try renderToken(tree, stream, asm_output.lastToken(), indent, space); // )
1296 },
1297
1298 ast.Node.Id.StructField,
1299 ast.Node.Id.UnionTag,
1300 ast.Node.Id.EnumTag,
1301 ast.Node.Id.Root,
1302 ast.Node.Id.VarDecl,
1303 ast.Node.Id.Use,
1304 ast.Node.Id.TestDecl,
1305 ast.Node.Id.ParamDecl => unreachable,
1306 }
1307}
1308
1309fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize,
1310 var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void
1311{
1312 if (var_decl.visib_token) |visib_token| {
1313 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub
1314 }
1315
1316 if (var_decl.extern_export_token) |extern_export_token| {
1317 try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern
1318
1319 if (var_decl.lib_name) |lib_name| {
1320 try renderExpression(allocator, stream, tree, indent, lib_name, Space.Space); // "lib"
12361321 }
12371322 }
1323
1324 if (var_decl.comptime_token) |comptime_token| {
1325 try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime
1326 }
1327
1328 try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var
1329
1330 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
1331 var_decl.init_node != null)) Space.Space else Space.None;
1332 try renderToken(tree, stream, var_decl.name_token, indent, name_space);
1333
1334 if (var_decl.type_node) |type_node| {
1335 try renderToken(tree, stream, tree.nextToken(var_decl.name_token), indent, Space.Space);
1336 const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None;
1337 try renderExpression(allocator, stream, tree, indent, type_node, s);
1338 }
1339
1340 if (var_decl.align_node) |align_node| {
1341 const lparen = tree.prevToken(align_node.firstToken());
1342 const align_kw = tree.prevToken(lparen);
1343 const rparen = tree.nextToken(align_node.lastToken());
1344 try renderToken(tree, stream, align_kw, indent, Space.None); // align
1345 try renderToken(tree, stream, lparen, indent, Space.None); // (
1346 try renderExpression(allocator, stream, tree, indent, align_node, Space.None);
1347 const s = if (var_decl.init_node != null) Space.Space else Space.None;
1348 try renderToken(tree, stream, rparen, indent, s); // )
1349 }
1350
1351 if (var_decl.init_node) |init_node| {
1352 const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space;
1353 try renderToken(tree, stream, var_decl.eq_token, indent, s); // =
1354 try renderExpression(allocator, stream, tree, indent, init_node, Space.None);
1355 }
1356
1357 try renderToken(tree, stream, var_decl.semicolon_token, indent, Space.Newline);
1358}
1359
1360fn renderParamDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
1361 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
1362
1363 if (param_decl.comptime_token) |comptime_token| {
1364 try renderToken(tree, stream, comptime_token, indent, Space.Space);
1365 }
1366 if (param_decl.noalias_token) |noalias_token| {
1367 try renderToken(tree, stream, noalias_token, indent, Space.Space);
1368 }
1369 if (param_decl.name_token) |name_token| {
1370 try renderToken(tree, stream, name_token, indent, Space.None);
1371 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // :
1372 }
1373 if (param_decl.var_args_token) |var_args_token| {
1374 try renderToken(tree, stream, var_args_token, indent, Space.None);
1375 } else {
1376 try renderExpression(allocator, stream, tree, indent, param_decl.type_node, Space.None);
1377 }
12381378}
12391379
1240fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool) !void {
1241 const token = tree.tokens.at(token_index);
1380fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
1381 switch (base.id) {
1382 ast.Node.Id.VarDecl => {
1383 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
1384 try renderVarDecl(allocator, stream, tree, indent, var_decl);
1385 },
1386 else => {
1387 if (base.requireSemiColon()) {
1388 try renderExpression(allocator, stream, tree, indent, base, Space.None);
1389
1390 const semicolon_index = tree.nextToken(base.lastToken());
1391 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);
1392 try renderToken(tree, stream, semicolon_index, indent, Space.Newline);
1393 } else {
1394 try renderExpression(allocator, stream, tree, indent, base, Space.Newline);
1395 }
1396 },
1397 }
1398}
1399
1400const Space = enum {
1401 None,
1402 Newline,
1403 Space,
1404 NoNewline,
1405 NoIndent,
1406 NoComment,
1407};
1408
1409fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, space: Space) (@typeOf(stream).Child.Error || Error)!void {
1410 var token = tree.tokens.at(token_index);
12421411 try stream.write(tree.tokenSlicePtr(token));
12431412
1244 const next_token = tree.tokens.at(token_index + 1);
1245 if (next_token.id == Token.Id.LineComment) {
1246 const loc = tree.tokenLocationPtr(token.end, next_token);
1247 if (loc.line == 0) {
1248 try stream.print(" {}", tree.tokenSlicePtr(next_token));
1249 if (!line_break) {
1250 try stream.write("\n");
1251 try stream.writeByteNTimes(' ', indent + indent_delta);
1252 return;
1413 if (space == Space.NoComment) return;
1414
1415 var next_token = tree.tokens.at(token_index + 1);
1416 if (next_token.id != Token.Id.LineComment) {
1417 switch (space) {
1418 Space.None, Space.NoNewline, Space.NoIndent => return,
1419 Space.Newline => return stream.write("\n"),
1420 Space.Space => return stream.writeByte(' '),
1421 Space.NoComment => unreachable,
1422 }
1423 }
1424
1425 var loc = tree.tokenLocationPtr(token.end, next_token);
1426 var offset: usize = 1;
1427 if (loc.line == 0) {
1428 try stream.print(" {}", tree.tokenSlicePtr(next_token));
1429 offset = 2;
1430 token = next_token;
1431 next_token = tree.tokens.at(token_index + offset);
1432 if (next_token.id != Token.Id.LineComment) {
1433 switch (space) {
1434 Space.None, Space.Space => {
1435 try stream.writeByte('\n');
1436 const after_comment_token = tree.tokens.at(token_index + offset);
1437 const next_line_indent = switch (after_comment_token.id) {
1438 Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent,
1439 else => indent + indent_delta,
1440 };
1441 try stream.writeByteNTimes(' ', next_line_indent);
1442 },
1443 Space.Newline, Space.NoIndent => try stream.write("\n"),
1444 Space.NoNewline => {},
1445 Space.NoComment => unreachable,
12531446 }
1447 return;
12541448 }
1449 loc = tree.tokenLocationPtr(token.end, next_token);
12551450 }
12561451
1257 if (!line_break) {
1258 try stream.writeByte(' ');
1452 while (true) {
1453 assert(loc.line != 0);
1454 const newline_count = if (loc.line == 1) u8(1) else u8(2);
1455 try stream.writeByteNTimes('\n', newline_count);
1456 try stream.writeByteNTimes(' ', indent);
1457 try stream.write(tree.tokenSlicePtr(next_token));
1458
1459 offset += 1;
1460 token = next_token;
1461 next_token = tree.tokens.at(token_index + offset);
1462 if (next_token.id != Token.Id.LineComment) {
1463 switch (space) {
1464 Space.Newline, Space.NoIndent => try stream.writeByte('\n'),
1465 Space.None, Space.Space => {
1466 try stream.writeByte('\n');
1467
1468 const after_comment_token = tree.tokens.at(token_index + offset);
1469 const next_line_indent = switch (after_comment_token.id) {
1470 Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent,
1471 else => indent,
1472 };
1473 try stream.writeByteNTimes(' ', next_line_indent);
1474 },
1475 Space.NoNewline => {},
1476 Space.NoComment => unreachable,
1477 }
1478 return;
1479 }
1480 loc = tree.tokenLocationPtr(token.end, next_token);
12591481 }
12601482}
12611483
1262fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) !void {
1484fn renderDocComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@typeOf(stream).Child.Error || Error)!void {
12631485 const comment = node.doc_comments ?? return;
12641486 var it = comment.lines.iterator(0);
12651487 while (it.next()) |line_token_index| {
1266 try stream.print("{}\n", tree.tokenSlice(*line_token_index));
1488 try renderToken(tree, stream, line_token_index.*, indent, Space.Newline);
12671489 try stream.writeByteNTimes(' ', indent);
12681490 }
12691491}
12701492
1493fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node,
1494 space: Space) (@typeOf(stream).Child.Error || Error)!void
1495{
1496 const end_token = base.lastToken() + 1;
1497 switch (tree.tokens.at(end_token).id) {
1498 Token.Id.Comma => {
1499 try renderExpression(allocator, stream, tree, indent, base, Space.None);
1500 try renderToken(tree, stream, end_token, indent, space); // ,
1501 },
1502 Token.Id.LineComment => {
1503 try renderExpression(allocator, stream, tree, indent, base, Space.NoComment);
1504 try stream.write(", ");
1505 try renderToken(tree, stream, end_token, indent, space);
1506 },
1507 else => {
1508 try renderExpression(allocator, stream, tree, indent, base, Space.None);
1509 try stream.write(",\n");
1510 assert(space == Space.Newline);
1511 },
1512 }
1513}
std/zig/tokenizer.zig+103-6
......@@ -6,12 +6,12 @@ pub const Token = struct {
66 start: usize,
77 end: usize,
88
9 const Keyword = struct {
9 pub const Keyword = struct {
1010 bytes: []const u8,
1111 id: Id,
1212 };
1313
14 const keywords = []Keyword {
14 pub const keywords = []Keyword {
1515 Keyword{.bytes="align", .id = Id.Keyword_align},
1616 Keyword{.bytes="and", .id = Id.Keyword_and},
1717 Keyword{.bytes="asm", .id = Id.Keyword_asm},
......@@ -62,6 +62,7 @@ pub const Token = struct {
6262 Keyword{.bytes="while", .id = Id.Keyword_while},
6363 };
6464
65 // TODO perfect hash at comptime
6566 fn getKeyword(bytes: []const u8) ?Id {
6667 for (keywords) |kw| {
6768 if (mem.eql(u8, kw.bytes, bytes)) {
......@@ -219,6 +220,8 @@ pub const Tokenizer = struct {
219220 MultilineStringLiteralLineBackslash,
220221 CharLiteral,
221222 CharLiteralBackslash,
223 CharLiteralEscape1,
224 CharLiteralEscape2,
222225 CharLiteralEnd,
223226 Backslash,
224227 Equal,
......@@ -236,10 +239,15 @@ pub const Tokenizer = struct {
236239 Zero,
237240 IntegerLiteral,
238241 IntegerLiteralWithRadix,
242 IntegerLiteralWithRadixHex,
239243 NumberDot,
244 NumberDotHex,
240245 FloatFraction,
246 FloatFractionHex,
241247 FloatExponentUnsigned,
248 FloatExponentUnsignedHex,
242249 FloatExponentNumber,
250 FloatExponentNumberHex,
243251 Ampersand,
244252 Caret,
245253 Percent,
......@@ -606,11 +614,34 @@ pub const Tokenizer = struct {
606614 result.id = Token.Id.Invalid;
607615 break;
608616 },
617 'x' => {
618 state = State.CharLiteralEscape1;
619 },
609620 else => {
610621 state = State.CharLiteralEnd;
611622 },
612623 },
613624
625 State.CharLiteralEscape1 => switch (c) {
626 '0'...'9', 'a'...'z', 'A'...'F' => {
627 state = State.CharLiteralEscape2;
628 },
629 else => {
630 result.id = Token.Id.Invalid;
631 break;
632 },
633 },
634
635 State.CharLiteralEscape2 => switch (c) {
636 '0'...'9', 'a'...'z', 'A'...'F' => {
637 state = State.CharLiteralEnd;
638 },
639 else => {
640 result.id = Token.Id.Invalid;
641 break;
642 },
643 },
644
614645 State.CharLiteralEnd => switch (c) {
615646 '\'' => {
616647 result.id = Token.Id.CharLiteral;
......@@ -839,9 +870,12 @@ pub const Tokenizer = struct {
839870 else => self.checkLiteralCharacter(),
840871 },
841872 State.Zero => switch (c) {
842 'b', 'o', 'x' => {
873 'b', 'o' => {
843874 state = State.IntegerLiteralWithRadix;
844875 },
876 'x' => {
877 state = State.IntegerLiteralWithRadixHex;
878 },
845879 else => {
846880 // reinterpret as a normal number
847881 self.index -= 1;
......@@ -862,8 +896,15 @@ pub const Tokenizer = struct {
862896 '.' => {
863897 state = State.NumberDot;
864898 },
899 '0'...'9' => {},
900 else => break,
901 },
902 State.IntegerLiteralWithRadixHex => switch (c) {
903 '.' => {
904 state = State.NumberDotHex;
905 },
865906 'p', 'P' => {
866 state = State.FloatExponentUnsigned;
907 state = State.FloatExponentUnsignedHex;
867908 },
868909 '0'...'9', 'a'...'f', 'A'...'F' => {},
869910 else => break,
......@@ -880,13 +921,32 @@ pub const Tokenizer = struct {
880921 state = State.FloatFraction;
881922 },
882923 },
924 State.NumberDotHex => switch (c) {
925 '.' => {
926 self.index -= 1;
927 state = State.Start;
928 break;
929 },
930 else => {
931 self.index -= 1;
932 result.id = Token.Id.FloatLiteral;
933 state = State.FloatFractionHex;
934 },
935 },
883936 State.FloatFraction => switch (c) {
884 'p', 'P', 'e', 'E' => {
937 'e', 'E' => {
885938 state = State.FloatExponentUnsigned;
886939 },
887940 '0'...'9' => {},
888941 else => break,
889942 },
943 State.FloatFractionHex => switch (c) {
944 'p', 'P' => {
945 state = State.FloatExponentUnsignedHex;
946 },
947 '0'...'9', 'a'...'f', 'A'...'F' => {},
948 else => break,
949 },
890950 State.FloatExponentUnsigned => switch (c) {
891951 '+', '-' => {
892952 state = State.FloatExponentNumber;
......@@ -897,7 +957,21 @@ pub const Tokenizer = struct {
897957 state = State.FloatExponentNumber;
898958 }
899959 },
960 State.FloatExponentUnsignedHex => switch (c) {
961 '+', '-' => {
962 state = State.FloatExponentNumberHex;
963 },
964 else => {
965 // reinterpret as a normal exponent number
966 self.index -= 1;
967 state = State.FloatExponentNumberHex;
968 }
969 },
900970 State.FloatExponentNumber => switch (c) {
971 '0'...'9' => {},
972 else => break,
973 },
974 State.FloatExponentNumberHex => switch (c) {
901975 '0'...'9', 'a'...'f', 'A'...'F' => {},
902976 else => break,
903977 },
......@@ -908,8 +982,11 @@ pub const Tokenizer = struct {
908982 State.C,
909983 State.IntegerLiteral,
910984 State.IntegerLiteralWithRadix,
985 State.IntegerLiteralWithRadixHex,
911986 State.FloatFraction,
987 State.FloatFractionHex,
912988 State.FloatExponentNumber,
989 State.FloatExponentNumberHex,
913990 State.StringLiteral, // find this error later
914991 State.MultilineStringLiteralLine,
915992 State.Builtin => {},
......@@ -928,12 +1005,16 @@ pub const Tokenizer = struct {
9281005 },
9291006
9301007 State.NumberDot,
1008 State.NumberDotHex,
9311009 State.FloatExponentUnsigned,
1010 State.FloatExponentUnsignedHex,
9321011 State.SawAtSign,
9331012 State.Backslash,
9341013 State.MultilineStringLiteralLineBackslash,
9351014 State.CharLiteral,
9361015 State.CharLiteralBackslash,
1016 State.CharLiteralEscape1,
1017 State.CharLiteralEscape2,
9371018 State.CharLiteralEnd,
9381019 State.StringLiteralBackslash => {
9391020 result.id = Token.Id.Invalid;
......@@ -1073,7 +1154,14 @@ test "tokenizer" {
10731154 });
10741155}
10751156
1076test "tokenizer - float literal" {
1157test "tokenizer - char literal with hex escape" {
1158 testTokenize( \\'\x1b'
1159 , []Token.Id {
1160 Token.Id.CharLiteral,
1161 });
1162}
1163
1164test "tokenizer - float literal e exponent" {
10771165 testTokenize("a = 4.94065645841246544177e-324;\n", []Token.Id {
10781166 Token.Id.Identifier,
10791167 Token.Id.Equal,
......@@ -1082,6 +1170,15 @@ test "tokenizer - float literal" {
10821170 });
10831171}
10841172
1173test "tokenizer - float literal p exponent" {
1174 testTokenize("a = 0x1.a827999fcef32p+1022;\n", []Token.Id {
1175 Token.Id.Identifier,
1176 Token.Id.Equal,
1177 Token.Id.FloatLiteral,
1178 Token.Id.Semicolon,
1179 });
1180}
1181
10851182test "tokenizer - chars" {
10861183 testTokenize("'c'", []Token.Id {Token.Id.CharLiteral});
10871184}
test/behavior.zig+4-2
......@@ -23,6 +23,7 @@ comptime {
2323 _ = @import("cases/eval.zig");
2424 _ = @import("cases/field_parent_ptr.zig");
2525 _ = @import("cases/fn.zig");
26 _ = @import("cases/fn_in_struct_in_comptime.zig");
2627 _ = @import("cases/for.zig");
2728 _ = @import("cases/generics.zig");
2829 _ = @import("cases/if.zig");
......@@ -32,11 +33,12 @@ comptime {
3233 _ = @import("cases/math.zig");
3334 _ = @import("cases/misc.zig");
3435 _ = @import("cases/namespace_depends_on_compile_var/index.zig");
36 _ = @import("cases/new_stack_call.zig");
3537 _ = @import("cases/null.zig");
38 _ = @import("cases/pointers.zig");
3639 _ = @import("cases/pub_enum/index.zig");
3740 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
3841 _ = @import("cases/reflection.zig");
39 _ = @import("cases/type_info.zig");
4042 _ = @import("cases/sizeof_and_typeof.zig");
4143 _ = @import("cases/slice.zig");
4244 _ = @import("cases/struct.zig");
......@@ -48,10 +50,10 @@ comptime {
4850 _ = @import("cases/syntax.zig");
4951 _ = @import("cases/this.zig");
5052 _ = @import("cases/try.zig");
53 _ = @import("cases/type_info.zig");
5154 _ = @import("cases/undefined.zig");
5255 _ = @import("cases/union.zig");
5356 _ = @import("cases/var_args.zig");
5457 _ = @import("cases/void.zig");
5558 _ = @import("cases/while.zig");
56 _ = @import("cases/fn_in_struct_in_comptime.zig");
5759}
test/build_examples.zig+1-1
......@@ -9,7 +9,7 @@ pub fn addCases(cases: &tests.BuildExamplesContext) void {
99 cases.add("example/guess_number/main.zig");
1010 if (!is_windows) {
1111 // TODO get this test passing on windows
12 // See https://github.com/zig-lang/zig/issues/538
12 // See https://github.com/ziglang/zig/issues/538
1313 cases.addBuildFile("example/shared_library/build.zig");
1414 cases.addBuildFile("example/mix_o_files/build.zig");
1515 }
test/cases/align.zig+60-26
......@@ -10,7 +10,9 @@ test "global variable alignment" {
1010 assert(@typeOf(slice) == []align(4) u8);
1111}
1212
13fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
1416fn noop1() align(1) void {}
1517fn noop4() align(4) void {}
1618
......@@ -22,7 +24,6 @@ test "function alignment" {
2224 noop4();
2325}
2426
25
2627var baz: packed struct {
2728 a: u32,
2829 b: u32,
......@@ -32,7 +33,6 @@ test "packed struct alignment" {
3233 assert(@typeOf(&baz.b) == &align(1) u32);
3334}
3435
35
3636const blah: packed struct {
3737 a: u3,
3838 b: u3,
......@@ -53,29 +53,43 @@ test "implicitly decreasing pointer alignment" {
5353 assert(addUnaligned(&a, &b) == 7);
5454}
5555
56fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { return *a + *b; }
56fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 {
57 return a.* + b.*;
58}
5759
5860test "implicitly decreasing slice alignment" {
5961 const a: u32 align(4) = 3;
6062 const b: u32 align(8) = 4;
6163 assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
6264}
63fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; }
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
6468
6569test "specifying alignment allows pointer cast" {
6670 testBytesAlign(0x33);
6771}
6872fn testBytesAlign(b: u8) void {
69 var bytes align(4) = []u8{b, b, b, b};
73 var bytes align(4) = []u8 {
74 b,
75 b,
76 b,
77 b,
78 };
7079 const ptr = @ptrCast(&u32, &bytes[0]);
71 assert(*ptr == 0x33333333);
80 assert(ptr.* == 0x33333333);
7281}
7382
7483test "specifying alignment allows slice cast" {
7584 testBytesAlignSlice(0x33);
7685}
7786fn testBytesAlignSlice(b: u8) void {
78 var bytes align(4) = []u8{b, b, b, b};
87 var bytes align(4) = []u8 {
88 b,
89 b,
90 b,
91 b,
92 };
7993 const slice = ([]u32)(bytes[0..]);
8094 assert(slice[0] == 0x33333333);
8195}
......@@ -89,11 +103,14 @@ fn expectsOnly1(x: &align(1) u32) void {
89103 expects4(@alignCast(4, x));
90104}
91105fn expects4(x: &align(4) u32) void {
92 *x += 1;
106 x.* += 1;
93107}
94108
95109test "@alignCast slices" {
96 var array align(4) = []u32{1, 1};
110 var array align(4) = []u32 {
111 1,
112 1,
113 };
97114 const slice = array[0..];
98115 sliceExpectsOnly1(slice);
99116 assert(slice[0] == 2);
......@@ -105,31 +122,34 @@ fn sliceExpects4(slice: []align(4) u32) void {
105122 slice[0] += 1;
106123}
107124
108
109125test "implicitly decreasing fn alignment" {
110126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
111127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
112128}
113129
114fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
130fn testImplicitlyDecreaseFnAlign(ptr: fn() align(1) i32, answer: i32) void {
115131 assert(ptr() == answer);
116132}
117133
118fn alignedSmall() align(8) i32 { return 1234; }
119fn alignedBig() align(16) i32 { return 5678; }
120
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
121140
122141test "@alignCast functions" {
123142 assert(fnExpectsOnly1(simple4) == 0x19);
124143}
125fn fnExpectsOnly1(ptr: fn()align(1) i32) i32 {
144fn fnExpectsOnly1(ptr: fn() align(1) i32) i32 {
126145 return fnExpects4(@alignCast(4, ptr));
127146}
128fn fnExpects4(ptr: fn()align(4) i32) i32 {
147fn fnExpects4(ptr: fn() align(4) i32) i32 {
129148 return ptr();
130149}
131fn simple4() align(4) i32 { return 0x19; }
132
150fn simple4() align(4) i32 {
151 return 0x19;
152}
133153
134154test "generic function with align param" {
135155 assert(whyWouldYouEverDoThis(1) == 0x1);
......@@ -137,8 +157,9 @@ test "generic function with align param" {
137157 assert(whyWouldYouEverDoThis(8) == 0x1);
138158}
139159
140fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { return 0x1; }
141
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
142163
143164test "@ptrCast preserves alignment of bigger source" {
144165 var x: u32 align(16) = 1234;
......@@ -146,24 +167,38 @@ test "@ptrCast preserves alignment of bigger source" {
146167 assert(@typeOf(ptr) == &align(16) u8);
147168}
148169
149
150170test "compile-time known array index has best alignment possible" {
151171 // take full advantage of over-alignment
152 var array align(4) = []u8 {1, 2, 3, 4};
172 var array align(4) = []u8 {
173 1,
174 2,
175 3,
176 4,
177 };
153178 assert(@typeOf(&array[0]) == &align(4) u8);
154179 assert(@typeOf(&array[1]) == &u8);
155180 assert(@typeOf(&array[2]) == &align(2) u8);
156181 assert(@typeOf(&array[3]) == &u8);
157182
158183 // because align is too small but we still figure out to use 2
159 var bigger align(2) = []u64{1, 2, 3, 4};
184 var bigger align(2) = []u64 {
185 1,
186 2,
187 3,
188 4,
189 };
160190 assert(@typeOf(&bigger[0]) == &align(2) u64);
161191 assert(@typeOf(&bigger[1]) == &align(2) u64);
162192 assert(@typeOf(&bigger[2]) == &align(2) u64);
163193 assert(@typeOf(&bigger[3]) == &align(2) u64);
164194
165195 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
166 var smaller align(2) = []u32{1, 2, 3, 4};
196 var smaller align(2) = []u32 {
197 1,
198 2,
199 3,
200 4,
201 };
167202 testIndex(&smaller[0], 0, &align(2) u32);
168203 testIndex(&smaller[0], 1, &align(2) u32);
169204 testIndex(&smaller[0], 2, &align(2) u32);
......@@ -182,7 +217,6 @@ fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) void {
182217 assert(@typeOf(&ptr[index]) == T);
183218}
184219
185
186220test "alignstack" {
187221 assert(fnWithAlignedStack() == 1234);
188222}
test/cases/alignof.zig+5-1
......@@ -1,7 +1,11 @@
11const assert = @import("std").debug.assert;
22const builtin = @import("builtin");
33
4const Foo = struct { x: u32, y: u32, z: u32, };
4const Foo = struct {
5 x: u32,
6 y: u32,
7 z: u32,
8};
59
610test "@alignOf(T) before referencing T" {
711 comptime assert(@alignOf(Foo) != @maxValue(usize));
test/cases/array.zig+31-10
......@@ -2,9 +2,9 @@ const assert = @import("std").debug.assert;
22const mem = @import("std").mem;
33
44test "arrays" {
5 var array : [5]u32 = undefined;
5 var array: [5]u32 = undefined;
66
7 var i : u32 = 0;
7 var i: u32 = 0;
88 while (i < 5) {
99 array[i] = i + 1;
1010 i = array[i];
......@@ -34,24 +34,41 @@ test "void arrays" {
3434}
3535
3636test "array literal" {
37 const hex_mult = []u16{4096, 256, 16, 1};
37 const hex_mult = []u16 {
38 4096,
39 256,
40 16,
41 1,
42 };
3843
3944 assert(hex_mult.len == 4);
4045 assert(hex_mult[1] == 256);
4146}
4247
4348test "array dot len const expr" {
44 assert(comptime x: {break :x some_array.len == 4;});
49 assert(comptime x: {
50 break :x some_array.len == 4;
51 });
4552}
4653
4754const ArrayDotLenConstExpr = struct {
4855 y: [some_array.len]u8,
4956};
50const some_array = []u8 {0, 1, 2, 3};
51
57const some_array = []u8 {
58 0,
59 1,
60 2,
61 3,
62};
5263
5364test "nested arrays" {
54 const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"};
65 const array_of_strings = [][]const u8 {
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
5572 for (array_of_strings) |s, i| {
5673 if (i == 0) assert(mem.eql(u8, s, "hello"));
5774 if (i == 1) assert(mem.eql(u8, s, "this"));
......@@ -61,7 +78,6 @@ test "nested arrays" {
6178 }
6279}
6380
64
6581var s_array: [8]Sub = undefined;
6682const Sub = struct {
6783 b: u8,
......@@ -70,7 +86,9 @@ const Str = struct {
7086 a: []Sub,
7187};
7288test "set global var array via slice embedded in struct" {
73 var s = Str { .a = s_array[0..]};
89 var s = Str {
90 .a = s_array[0..],
91 };
7492
7593 s.a[0].b = 1;
7694 s.a[1].b = 2;
......@@ -82,7 +100,10 @@ test "set global var array via slice embedded in struct" {
82100}
83101
84102test "array literal with specified size" {
85 var array = [2]u8{1, 2};
103 var array = [2]u8 {
104 1,
105 2,
106 };
86107 assert(array[0] == 1);
87108 assert(array[1] == 2);
88109}
test/cases/bitcast.zig+6-2
......@@ -10,5 +10,9 @@ fn testBitCast_i32_u32() void {
1010 assert(conv2(@maxValue(u32)) == -1);
1111}
1212
13fn conv(x: i32) u32 { return @bitCast(u32, x); }
14fn conv2(x: u32) i32 { return @bitCast(i32, x); }
13fn conv(x: i32) u32 {
14 return @bitCast(u32, x);
15}
16fn conv2(x: u32) i32 {
17 return @bitCast(i32, x);
18}
test/cases/bugs/394.zig+14-3
......@@ -1,9 +1,20 @@
1const E = union(enum) { A: [9]u8, B: u64, };
2const S = struct { x: u8, y: E, };
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
39
410const assert = @import("std").debug.assert;
511
612test "bug 394 fixed" {
7 const x = S { .x = 3, .y = E {.B = 1 } };
13 const x = S {
14 .x = 3,
15 .y = E {
16 .B = 1,
17 },
18 };
819 assert(x.x == 3);
920}
test/cases/bugs/655.zig+1-1
......@@ -8,5 +8,5 @@ test "function with &const parameter with type dereferenced by namespace" {
88}
99
1010fn foo(x: &const other_file.Integer) void {
11 std.debug.assert(*x == 1234);
11 std.debug.assert(x.* == 1234);
1212}
test/cases/bugs/656.zig+7-4
......@@ -14,12 +14,15 @@ test "nullable if after an if in a switch prong of a switch with 2 prongs in an
1414}
1515
1616fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp { .AddrOf = Value { .align_expr = 1234 } };
18 if (a) {
19 } else {
17 var prefix_op = PrefixOp {
18 .AddrOf = Value {
19 .align_expr = 1234,
20 },
21 };
22 if (a) {} else {
2023 switch (prefix_op) {
2124 PrefixOp.AddrOf => |addr_of_info| {
22 if (b) { }
25 if (b) {}
2326 if (addr_of_info.align_expr) |align_expr| {
2427 assert(align_expr == 1234);
2528 }
test/cases/bugs/828.zig+5-5
......@@ -1,10 +1,10 @@
11const CountBy = struct {
22 a: usize,
3
3
44 const One = CountBy {
55 .a = 1,
66 };
7
7
88 pub fn counter(self: &const CountBy) Counter {
99 return Counter {
1010 .i = 0,
......@@ -14,7 +14,7 @@ const CountBy = struct {
1414
1515const Counter = struct {
1616 i: usize,
17
17
1818 pub fn count(self: &Counter) bool {
1919 self.i += 1;
2020 return self.i <= 10;
......@@ -24,8 +24,8 @@ const Counter = struct {
2424fn constCount(comptime cb: &const CountBy, comptime unused: u32) void {
2525 comptime {
2626 var cnt = cb.counter();
27 if(cnt.i != 0) @compileError("Counter instance reused!");
28 while(cnt.count()){}
27 if (cnt.i != 0) @compileError("Counter instance reused!");
28 while (cnt.count()) {}
2929 }
3030}
3131
test/cases/bugs/920.zig+12-7
......@@ -12,8 +12,7 @@ const ZigTable = struct {
1212 zero_case: fn(&Random, f64) f64,
1313};
1414
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64,
16 comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable {
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64, comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable {
1716 var tables: ZigTable = undefined;
1817
1918 tables.is_symmetric = is_symmetric;
......@@ -26,12 +25,12 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co
2625
2726 for (tables.x[2..256]) |*entry, i| {
2827 const last = tables.x[2 + i - 1];
29 *entry = f_inv(v / last + f(last));
28 entry.* = f_inv(v / last + f(last));
3029 }
3130 tables.x[256] = 0;
3231
3332 for (tables.f[0..]) |*entry, i| {
34 *entry = f(tables.x[i]);
33 entry.* = f(tables.x[i]);
3534 }
3635
3736 return tables;
......@@ -40,9 +39,15 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co
4039const norm_r = 3.6541528853610088;
4140const norm_v = 0.00492867323399;
4241
43fn norm_f(x: f64) f64 { return math.exp(-x * x / 2.0); }
44fn norm_f_inv(y: f64) f64 { return math.sqrt(-2.0 * math.ln(y)); }
45fn norm_zero_case(random: &Random, u: f64) f64 { return 0.0; }
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: &Random, u: f64) f64 {
49 return 0.0;
50}
4651
4752const NormalDist = blk: {
4853 @setEvalBranchQuota(30000);
test/cases/cast.zig+42-28
......@@ -17,7 +17,7 @@ test "pointer reinterpret const float to int" {
1717 const float: f64 = 5.99999999999994648725e-01;
1818 const float_ptr = &float;
1919 const int_ptr = @ptrCast(&const i32, float_ptr);
20 const int_val = *int_ptr;
20 const int_val = int_ptr.*;
2121 assert(int_val == 858993411);
2222}
2323
......@@ -29,25 +29,31 @@ test "implicitly cast a pointer to a const pointer of it" {
2929}
3030
3131fn funcWithConstPtrPtr(x: &const &i32) void {
32 **x += 1;
32 x.*.* += 1;
3333}
3434
3535test "implicitly cast a container to a const pointer of it" {
36 const z = Struct(void) { .x = void{} };
36 const z = Struct(void) {
37 .x = void{},
38 };
3739 assert(0 == @sizeOf(@typeOf(z)));
3840 assert(void{} == Struct(void).pointer(z).x);
3941 assert(void{} == Struct(void).pointer(&z).x);
4042 assert(void{} == Struct(void).maybePointer(z).x);
4143 assert(void{} == Struct(void).maybePointer(&z).x);
4244 assert(void{} == Struct(void).maybePointer(null).x);
43 const s = Struct(u8) { .x = 42 };
45 const s = Struct(u8) {
46 .x = 42,
47 };
4448 assert(0 != @sizeOf(@typeOf(s)));
4549 assert(42 == Struct(u8).pointer(s).x);
4650 assert(42 == Struct(u8).pointer(&s).x);
4751 assert(42 == Struct(u8).maybePointer(s).x);
4852 assert(42 == Struct(u8).maybePointer(&s).x);
4953 assert(0 == Struct(u8).maybePointer(null).x);
50 const u = Union { .x = 42 };
54 const u = Union {
55 .x = 42,
56 };
5157 assert(42 == Union.pointer(u).x);
5258 assert(42 == Union.pointer(&u).x);
5359 assert(42 == Union.maybePointer(u).x);
......@@ -67,12 +73,14 @@ fn Struct(comptime T: type) type {
6773 x: T,
6874
6975 fn pointer(self: &const Self) Self {
70 return *self;
76 return self.*;
7177 }
7278
7379 fn maybePointer(self: ?&const Self) Self {
74 const none = Self { .x = if (T == void) void{} else 0 };
75 return *(self ?? &none);
80 const none = Self {
81 .x = if (T == void) void{} else 0,
82 };
83 return (self ?? &none).*;
7684 }
7785 };
7886}
......@@ -81,12 +89,14 @@ const Union = union {
8189 x: u8,
8290
8391 fn pointer(self: &const Union) Union {
84 return *self;
92 return self.*;
8593 }
8694
8795 fn maybePointer(self: ?&const Union) Union {
88 const none = Union { .x = 0 };
89 return *(self ?? &none);
96 const none = Union {
97 .x = 0,
98 };
99 return (self ?? &none).*;
90100 }
91101};
92102
......@@ -95,11 +105,11 @@ const Enum = enum {
95105 Some,
96106
97107 fn pointer(self: &const Enum) Enum {
98 return *self;
108 return self.*;
99109 }
100110
101111 fn maybePointer(self: ?&const Enum) Enum {
102 return *(self ?? &Enum.None);
112 return (self ?? &Enum.None).*;
103113 }
104114};
105115
......@@ -108,19 +118,21 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
108118 const Self = this;
109119 x: u8,
110120 fn constConst(p: &const &const Self) u8 {
111 return (*p).x;
121 return (p.*).x;
112122 }
113123 fn maybeConstConst(p: ?&const &const Self) u8 {
114 return (*??p).x;
124 return ((??p).*).x;
115125 }
116126 fn constConstConst(p: &const &const &const Self) u8 {
117 return (**p).x;
127 return (p.*.*).x;
118128 }
119129 fn maybeConstConstConst(p: ?&const &const &const Self) u8 {
120 return (**??p).x;
130 return ((??p).*.*).x;
121131 }
122132 };
123 const s = S { .x = 42 };
133 const s = S {
134 .x = 42,
135 };
124136 const p = &s;
125137 const q = &p;
126138 const r = &q;
......@@ -154,7 +166,6 @@ fn boolToStr(b: bool) []const u8 {
154166 return if (b) "true" else "false";
155167}
156168
157
158169test "peer resolve array and const slice" {
159170 testPeerResolveArrayConstSlice(true);
160171 comptime testPeerResolveArrayConstSlice(true);
......@@ -168,12 +179,12 @@ fn testPeerResolveArrayConstSlice(b: bool) void {
168179
169180test "integer literal to &const int" {
170181 const x: &const i32 = 3;
171 assert(*x == 3);
182 assert(x.* == 3);
172183}
173184
174185test "string literal to &const []const u8" {
175186 const x: &const []const u8 = "hello";
176 assert(mem.eql(u8, *x, "hello"));
187 assert(mem.eql(u8, x.*, "hello"));
177188}
178189
179190test "implicitly cast from T to error!?T" {
......@@ -191,7 +202,9 @@ fn castToMaybeTypeError(z: i32) void {
191202 const f = z;
192203 const g: error!?i32 = f;
193204
194 const a = A{ .a = z };
205 const a = A {
206 .a = z,
207 };
195208 const b: error!?A = a;
196209 assert((??(b catch unreachable)).a == 1);
197210}
......@@ -205,7 +218,6 @@ fn implicitIntLitToMaybe() void {
205218 const g: error!?i32 = 1;
206219}
207220
208
209221test "return null from fn() error!?&T" {
210222 const a = returnNullFromMaybeTypeErrorRef();
211223 const b = returnNullLitFromMaybeTypeErrorRef();
......@@ -235,7 +247,6 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize {
235247 return usize(3);
236248}
237249
238
239250test "peer type resolution: [0]u8 and []const u8" {
240251 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
241252 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
......@@ -246,7 +257,7 @@ test "peer type resolution: [0]u8 and []const u8" {
246257}
247258fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
248259 if (a) {
249 return []const u8 {};
260 return []const u8{};
250261 }
251262
252263 return slice[0..1];
......@@ -261,7 +272,6 @@ fn castToMaybeSlice() ?[]const u8 {
261272 return "hi";
262273}
263274
264
265275test "implicitly cast from [0]T to error![]T" {
266276 testCastZeroArrayToErrSliceMut();
267277 comptime testCastZeroArrayToErrSliceMut();
......@@ -329,7 +339,6 @@ fn foo(args: ...) void {
329339 assert(@typeOf(args[0]) == &const [5]u8);
330340}
331341
332
333342test "peer type resolution: error and [N]T" {
334343 // TODO: implicit error!T to error!U where T can implicitly cast to U
335344 //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
......@@ -378,7 +387,12 @@ fn cast128Float(x: u128) f128 {
378387}
379388
380389test "const slice widen cast" {
381 const bytes align(4) = []u8{0x12, 0x12, 0x12, 0x12};
390 const bytes align(4) = []u8 {
391 0x12,
392 0x12,
393 0x12,
394 0x12,
395 };
382396
383397 const u32_value = ([]const u32)(bytes[0..])[0];
384398 assert(u32_value == 0x12121212);
test/cases/coroutines.zig+9-9
......@@ -36,7 +36,7 @@ async fn testAsyncSeq() void {
3636 suspend;
3737 seq('d');
3838}
39var points = []u8{0} ** "abcdefg".len;
39var points = []u8 {0} ** "abcdefg".len;
4040var index: usize = 0;
4141
4242fn seq(c: u8) void {
......@@ -94,7 +94,7 @@ async fn await_another() i32 {
9494 return 1234;
9595}
9696
97var await_points = []u8{0} ** "abcdefghi".len;
97var await_points = []u8 {0} ** "abcdefghi".len;
9898var await_seq_index: usize = 0;
9999
100100fn await_seq(c: u8) void {
......@@ -102,7 +102,6 @@ fn await_seq(c: u8) void {
102102 await_seq_index += 1;
103103}
104104
105
106105var early_final_result: i32 = 0;
107106
108107test "coroutine await early return" {
......@@ -126,7 +125,7 @@ async fn early_another() i32 {
126125 return 1234;
127126}
128127
129var early_points = []u8{0} ** "abcdef".len;
128var early_points = []u8 {0} ** "abcdef".len;
130129var early_seq_index: usize = 0;
131130
132131fn early_seq(c: u8) void {
......@@ -175,8 +174,8 @@ test "async fn pointer in a struct field" {
175174}
176175
177176async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void {
178 defer *y += 2;
179 *y += 1;
177 defer y.* += 2;
178 y.* += 1;
180179 suspend;
181180}
182181
......@@ -205,7 +204,8 @@ test "error return trace across suspend points - async return" {
205204 cancel p2;
206205}
207206
208fn nonFailing() promise->error!void {
207// TODO https://github.com/ziglang/zig/issues/760
208fn nonFailing() (promise->error!void) {
209209 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
210210}
211211
......@@ -239,7 +239,7 @@ async fn testBreakFromSuspend(my_result: &i32) void {
239239 s: suspend |p| {
240240 break :s;
241241 }
242 *my_result += 1;
242 my_result.* += 1;
243243 suspend;
244 *my_result += 1;
244 my_result.* += 1;
245245}
test/cases/defer.zig+12-3
......@@ -5,9 +5,18 @@ var index: usize = undefined;
55
66fn runSomeErrorDefers(x: bool) !bool {
77 index = 0;
8 defer {result[index] = 'a'; index += 1;}
9 errdefer {result[index] = 'b'; index += 1;}
10 defer {result[index] = 'c'; index += 1;}
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
1120 return if (x) x else error.FalseNotAllowed;
1221}
1322
test/cases/enum.zig+548-58
......@@ -2,8 +2,15 @@ const assert = @import("std").debug.assert;
22const mem = @import("std").mem;
33
44test "enum type" {
5 const foo1 = Foo{ .One = 13};
6 const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }};
5 const foo1 = Foo {
6 .One = 13,
7 };
8 const foo2 = Foo {
9 .Two = Point {
10 .x = 1234,
11 .y = 5678,
12 },
13 };
714 const bar = Bar.B;
815
916 assert(bar == Bar.B);
......@@ -41,26 +48,31 @@ const Bar = enum {
4148};
4249
4350fn returnAnInt(x: i32) Foo {
44 return Foo { .One = x };
51 return Foo {
52 .One = x,
53 };
4554}
4655
47
4856test "constant enum with payload" {
49 var empty = AnEnumWithPayload {.Empty = {}};
50 var full = AnEnumWithPayload {.Full = 13};
57 var empty = AnEnumWithPayload {
58 .Empty = {},
59 };
60 var full = AnEnumWithPayload {
61 .Full = 13,
62 };
5163 shouldBeEmpty(empty);
5264 shouldBeNotEmpty(full);
5365}
5466
5567fn shouldBeEmpty(x: &const AnEnumWithPayload) void {
56 switch (*x) {
68 switch (x.*) {
5769 AnEnumWithPayload.Empty => {},
5870 else => unreachable,
5971 }
6072}
6173
6274fn shouldBeNotEmpty(x: &const AnEnumWithPayload) void {
63 switch (*x) {
75 switch (x.*) {
6476 AnEnumWithPayload.Empty => unreachable,
6577 else => {},
6678 }
......@@ -71,8 +83,6 @@ const AnEnumWithPayload = union(enum) {
7183 Full: i32,
7284};
7385
74
75
7686const Number = enum {
7787 Zero,
7888 One,
......@@ -93,7 +103,6 @@ fn shouldEqual(n: Number, expected: u3) void {
93103 assert(u3(n) == expected);
94104}
95105
96
97106test "int to enum" {
98107 testIntToEnumEval(3);
99108}
......@@ -108,7 +117,6 @@ const IntToEnumNumber = enum {
108117 Four,
109118};
110119
111
112120test "@tagName" {
113121 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114122 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
......@@ -124,7 +132,6 @@ const BareNumber = enum {
124132 Three,
125133};
126134
127
128135test "enum alignment" {
129136 comptime {
130137 assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
......@@ -137,47 +144,529 @@ const AlignTestEnum = union(enum) {
137144 B: u64,
138145};
139146
140const ValueCount1 = enum { I0 };
141const ValueCount2 = enum { I0, I1 };
147const ValueCount1 = enum {
148 I0,
149};
150const ValueCount2 = enum {
151 I0,
152 I1,
153};
142154const ValueCount256 = enum {
143 I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15,
144 I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31,
145 I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47,
146 I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63,
147 I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79,
148 I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95,
149 I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109,
150 I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123,
151 I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137,
152 I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151,
153 I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165,
154 I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179,
155 I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193,
156 I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207,
157 I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221,
158 I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235,
159 I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249,
160 I250, I251, I252, I253, I254, I255
155 I0,
156 I1,
157 I2,
158 I3,
159 I4,
160 I5,
161 I6,
162 I7,
163 I8,
164 I9,
165 I10,
166 I11,
167 I12,
168 I13,
169 I14,
170 I15,
171 I16,
172 I17,
173 I18,
174 I19,
175 I20,
176 I21,
177 I22,
178 I23,
179 I24,
180 I25,
181 I26,
182 I27,
183 I28,
184 I29,
185 I30,
186 I31,
187 I32,
188 I33,
189 I34,
190 I35,
191 I36,
192 I37,
193 I38,
194 I39,
195 I40,
196 I41,
197 I42,
198 I43,
199 I44,
200 I45,
201 I46,
202 I47,
203 I48,
204 I49,
205 I50,
206 I51,
207 I52,
208 I53,
209 I54,
210 I55,
211 I56,
212 I57,
213 I58,
214 I59,
215 I60,
216 I61,
217 I62,
218 I63,
219 I64,
220 I65,
221 I66,
222 I67,
223 I68,
224 I69,
225 I70,
226 I71,
227 I72,
228 I73,
229 I74,
230 I75,
231 I76,
232 I77,
233 I78,
234 I79,
235 I80,
236 I81,
237 I82,
238 I83,
239 I84,
240 I85,
241 I86,
242 I87,
243 I88,
244 I89,
245 I90,
246 I91,
247 I92,
248 I93,
249 I94,
250 I95,
251 I96,
252 I97,
253 I98,
254 I99,
255 I100,
256 I101,
257 I102,
258 I103,
259 I104,
260 I105,
261 I106,
262 I107,
263 I108,
264 I109,
265 I110,
266 I111,
267 I112,
268 I113,
269 I114,
270 I115,
271 I116,
272 I117,
273 I118,
274 I119,
275 I120,
276 I121,
277 I122,
278 I123,
279 I124,
280 I125,
281 I126,
282 I127,
283 I128,
284 I129,
285 I130,
286 I131,
287 I132,
288 I133,
289 I134,
290 I135,
291 I136,
292 I137,
293 I138,
294 I139,
295 I140,
296 I141,
297 I142,
298 I143,
299 I144,
300 I145,
301 I146,
302 I147,
303 I148,
304 I149,
305 I150,
306 I151,
307 I152,
308 I153,
309 I154,
310 I155,
311 I156,
312 I157,
313 I158,
314 I159,
315 I160,
316 I161,
317 I162,
318 I163,
319 I164,
320 I165,
321 I166,
322 I167,
323 I168,
324 I169,
325 I170,
326 I171,
327 I172,
328 I173,
329 I174,
330 I175,
331 I176,
332 I177,
333 I178,
334 I179,
335 I180,
336 I181,
337 I182,
338 I183,
339 I184,
340 I185,
341 I186,
342 I187,
343 I188,
344 I189,
345 I190,
346 I191,
347 I192,
348 I193,
349 I194,
350 I195,
351 I196,
352 I197,
353 I198,
354 I199,
355 I200,
356 I201,
357 I202,
358 I203,
359 I204,
360 I205,
361 I206,
362 I207,
363 I208,
364 I209,
365 I210,
366 I211,
367 I212,
368 I213,
369 I214,
370 I215,
371 I216,
372 I217,
373 I218,
374 I219,
375 I220,
376 I221,
377 I222,
378 I223,
379 I224,
380 I225,
381 I226,
382 I227,
383 I228,
384 I229,
385 I230,
386 I231,
387 I232,
388 I233,
389 I234,
390 I235,
391 I236,
392 I237,
393 I238,
394 I239,
395 I240,
396 I241,
397 I242,
398 I243,
399 I244,
400 I245,
401 I246,
402 I247,
403 I248,
404 I249,
405 I250,
406 I251,
407 I252,
408 I253,
409 I254,
410 I255,
161411};
162412const ValueCount257 = enum {
163 I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15,
164 I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31,
165 I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47,
166 I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63,
167 I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79,
168 I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95,
169 I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109,
170 I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123,
171 I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137,
172 I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151,
173 I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165,
174 I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179,
175 I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193,
176 I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207,
177 I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221,
178 I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235,
179 I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249,
180 I250, I251, I252, I253, I254, I255, I256
413 I0,
414 I1,
415 I2,
416 I3,
417 I4,
418 I5,
419 I6,
420 I7,
421 I8,
422 I9,
423 I10,
424 I11,
425 I12,
426 I13,
427 I14,
428 I15,
429 I16,
430 I17,
431 I18,
432 I19,
433 I20,
434 I21,
435 I22,
436 I23,
437 I24,
438 I25,
439 I26,
440 I27,
441 I28,
442 I29,
443 I30,
444 I31,
445 I32,
446 I33,
447 I34,
448 I35,
449 I36,
450 I37,
451 I38,
452 I39,
453 I40,
454 I41,
455 I42,
456 I43,
457 I44,
458 I45,
459 I46,
460 I47,
461 I48,
462 I49,
463 I50,
464 I51,
465 I52,
466 I53,
467 I54,
468 I55,
469 I56,
470 I57,
471 I58,
472 I59,
473 I60,
474 I61,
475 I62,
476 I63,
477 I64,
478 I65,
479 I66,
480 I67,
481 I68,
482 I69,
483 I70,
484 I71,
485 I72,
486 I73,
487 I74,
488 I75,
489 I76,
490 I77,
491 I78,
492 I79,
493 I80,
494 I81,
495 I82,
496 I83,
497 I84,
498 I85,
499 I86,
500 I87,
501 I88,
502 I89,
503 I90,
504 I91,
505 I92,
506 I93,
507 I94,
508 I95,
509 I96,
510 I97,
511 I98,
512 I99,
513 I100,
514 I101,
515 I102,
516 I103,
517 I104,
518 I105,
519 I106,
520 I107,
521 I108,
522 I109,
523 I110,
524 I111,
525 I112,
526 I113,
527 I114,
528 I115,
529 I116,
530 I117,
531 I118,
532 I119,
533 I120,
534 I121,
535 I122,
536 I123,
537 I124,
538 I125,
539 I126,
540 I127,
541 I128,
542 I129,
543 I130,
544 I131,
545 I132,
546 I133,
547 I134,
548 I135,
549 I136,
550 I137,
551 I138,
552 I139,
553 I140,
554 I141,
555 I142,
556 I143,
557 I144,
558 I145,
559 I146,
560 I147,
561 I148,
562 I149,
563 I150,
564 I151,
565 I152,
566 I153,
567 I154,
568 I155,
569 I156,
570 I157,
571 I158,
572 I159,
573 I160,
574 I161,
575 I162,
576 I163,
577 I164,
578 I165,
579 I166,
580 I167,
581 I168,
582 I169,
583 I170,
584 I171,
585 I172,
586 I173,
587 I174,
588 I175,
589 I176,
590 I177,
591 I178,
592 I179,
593 I180,
594 I181,
595 I182,
596 I183,
597 I184,
598 I185,
599 I186,
600 I187,
601 I188,
602 I189,
603 I190,
604 I191,
605 I192,
606 I193,
607 I194,
608 I195,
609 I196,
610 I197,
611 I198,
612 I199,
613 I200,
614 I201,
615 I202,
616 I203,
617 I204,
618 I205,
619 I206,
620 I207,
621 I208,
622 I209,
623 I210,
624 I211,
625 I212,
626 I213,
627 I214,
628 I215,
629 I216,
630 I217,
631 I218,
632 I219,
633 I220,
634 I221,
635 I222,
636 I223,
637 I224,
638 I225,
639 I226,
640 I227,
641 I228,
642 I229,
643 I230,
644 I231,
645 I232,
646 I233,
647 I234,
648 I235,
649 I236,
650 I237,
651 I238,
652 I239,
653 I240,
654 I241,
655 I242,
656 I243,
657 I244,
658 I245,
659 I246,
660 I247,
661 I248,
662 I249,
663 I250,
664 I251,
665 I252,
666 I253,
667 I254,
668 I255,
669 I256,
181670};
182671
183672test "enum sizes" {
......@@ -189,11 +678,11 @@ test "enum sizes" {
189678 }
190679}
191680
192const Small2 = enum (u2) {
681const Small2 = enum(u2) {
193682 One,
194683 Two,
195684};
196const Small = enum (u2) {
685const Small = enum(u2) {
197686 One,
198687 Two,
199688 Three,
......@@ -213,8 +702,7 @@ test "set enum tag type" {
213702 }
214703}
215704
216
217const A = enum (u3) {
705const A = enum(u3) {
218706 One,
219707 Two,
220708 Three,
......@@ -225,7 +713,7 @@ const A = enum (u3) {
225713 Four2,
226714};
227715
228const B = enum (u3) {
716const B = enum(u3) {
229717 One3,
230718 Two3,
231719 Three3,
......@@ -236,7 +724,7 @@ const B = enum (u3) {
236724 Four23,
237725};
238726
239const C = enum (u2) {
727const C = enum(u2) {
240728 One4,
241729 Two4,
242730 Three4,
......@@ -389,7 +877,9 @@ test "enum with tag values don't require parens" {
389877}
390878
391879test "enum with 1 field but explicit tag type should still have the tag type" {
392 const Enum = enum(u8) { B = 2 };
880 const Enum = enum(u8) {
881 B = 2,
882 };
393883 comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
394884}
395885
test/cases/enum_with_members.zig+7-3
......@@ -7,7 +7,7 @@ const ET = union(enum) {
77 UINT: u32,
88
99 pub fn print(a: &const ET, buf: []u8) error!usize {
10 return switch (*a) {
10 return switch (a.*) {
1111 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
1212 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
1313 };
......@@ -15,8 +15,12 @@ const ET = union(enum) {
1515};
1616
1717test "enum with members" {
18 const a = ET { .SINT = -42 };
19 const b = ET { .UINT = 42 };
18 const a = ET {
19 .SINT = -42,
20 };
21 const b = ET {
22 .UINT = 42,
23 };
2024 var buf: [20]u8 = undefined;
2125
2226 assert((a.print(buf[0..]) catch unreachable) == 3);
test/cases/error.zig+30-26
......@@ -30,14 +30,12 @@ test "@errorName" {
3030 assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
3131}
3232
33
3433test "error values" {
3534 const a = i32(error.err1);
3635 const b = i32(error.err2);
3736 assert(a != b);
3837}
3938
40
4139test "redefinition of error values allowed" {
4240 shouldBeNotEqual(error.AnError, error.SecondError);
4341}
......@@ -45,7 +43,6 @@ fn shouldBeNotEqual(a: error, b: error) void {
4543 if (a == b) unreachable;
4644}
4745
48
4946test "error binary operator" {
5047 const a = errBinaryOperatorG(true) catch 3;
5148 const b = errBinaryOperatorG(false) catch 3;
......@@ -56,20 +53,20 @@ fn errBinaryOperatorG(x: bool) error!isize {
5653 return if (x) error.ItBroke else isize(10);
5754}
5855
59
6056test "unwrap simple value from error" {
6157 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
6258 assert(i == 13);
6359}
64fn unwrapSimpleValueFromErrorDo() error!isize { return 13; }
65
60fn unwrapSimpleValueFromErrorDo() error!isize {
61 return 13;
62}
6663
6764test "error return in assignment" {
6865 doErrReturnInAssignment() catch unreachable;
6966}
7067
7168fn doErrReturnInAssignment() error!void {
72 var x : i32 = undefined;
69 var x: i32 = undefined;
7370 x = try makeANonErr();
7471}
7572
......@@ -95,7 +92,10 @@ test "error set type " {
9592 comptime testErrorSetType();
9693}
9794
98const MyErrSet = error {OutOfMemory, FileNotFound};
95const MyErrSet = error {
96 OutOfMemory,
97 FileNotFound,
98};
9999
100100fn testErrorSetType() void {
101101 assert(@memberCount(MyErrSet) == 2);
......@@ -109,14 +109,19 @@ fn testErrorSetType() void {
109109 }
110110}
111111
112
113112test "explicit error set cast" {
114113 testExplicitErrorSetCast(Set1.A);
115114 comptime testExplicitErrorSetCast(Set1.A);
116115}
117116
118const Set1 = error{A, B};
119const Set2 = error{A, C};
117const Set1 = error {
118 A,
119 B,
120};
121const Set2 = error {
122 A,
123 C,
124};
120125
121126fn testExplicitErrorSetCast(set1: Set1) void {
122127 var x = Set2(set1);
......@@ -129,7 +134,8 @@ test "comptime test error for empty error set" {
129134 comptime testComptimeTestErrorEmptySet(1234);
130135}
131136
132const EmptyErrorSet = error {};
137const EmptyErrorSet = error {
138};
133139
134140fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
135141 if (x) |v| assert(v == 1234) else |err| @compileError("bad");
......@@ -145,7 +151,9 @@ test "comptime err to int of error set with only 1 possible value" {
145151 testErrToIntWithOnePossibleValue(error.A, u32(error.A));
146152 comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A));
147153}
148fn testErrToIntWithOnePossibleValue(x: error{A}, comptime value: u32) void {
154fn testErrToIntWithOnePossibleValue(x: error {
155 A,
156}, comptime value: u32) void {
149157 if (u32(x) != value) {
150158 @compileError("bad");
151159 }
......@@ -176,7 +184,6 @@ fn quux_1() !i32 {
176184 return error.C;
177185}
178186
179
180187test "error: fn returning empty error set can be passed as fn returning any error" {
181188 entry();
182189 comptime entry();
......@@ -186,24 +193,24 @@ fn entry() void {
186193 foo2(bar2);
187194}
188195
189fn foo2(f: fn()error!void) void {
196fn foo2(f: fn() error!void) void {
190197 const x = f();
191198}
192199
193fn bar2() (error{}!void) { }
194
200fn bar2() (error {
201}!void) {}
195202
196203test "error: Zero sized error set returned with value payload crash" {
197204 _ = foo3(0);
198205 _ = comptime foo3(0);
199206}
200207
201const Error = error{};
208const Error = error {
209};
202210fn foo3(b: usize) Error!usize {
203211 return b;
204212}
205213
206
207214test "error: Infer error set from literals" {
208215 _ = nullLiteral("n") catch |err| handleErrors(err);
209216 _ = floatLiteral("n") catch |err| handleErrors(err);
......@@ -215,29 +222,26 @@ test "error: Infer error set from literals" {
215222
216223fn handleErrors(err: var) noreturn {
217224 switch (err) {
218 error.T => {}
225 error.T => {},
219226 }
220227
221228 unreachable;
222229}
223230
224231fn nullLiteral(str: []const u8) !?i64 {
225 if (str[0] == 'n')
226 return null;
232 if (str[0] == 'n') return null;
227233
228234 return error.T;
229235}
230236
231237fn floatLiteral(str: []const u8) !?f64 {
232 if (str[0] == 'n')
233 return 1.0;
238 if (str[0] == 'n') return 1.0;
234239
235240 return error.T;
236241}
237242
238243fn intLiteral(str: []const u8) !?i64 {
239 if (str[0] == 'n')
240 return 1;
244 if (str[0] == 'n') return 1;
241245
242246 return error.T;
243247}
test/cases/eval.zig+105-55
......@@ -11,8 +11,6 @@ fn fibonacci(x: i32) i32 {
1111 return fibonacci(x - 1) + fibonacci(x - 2);
1212}
1313
14
15
1614fn unwrapAndAddOne(blah: ?i32) i32 {
1715 return ??blah + 1;
1816}
......@@ -40,13 +38,13 @@ test "inline variable gets result of const if" {
4038 assert(gimme1or2(false) == 2);
4139}
4240
43
4441test "static function evaluation" {
4542 assert(statically_added_number == 3);
4643}
4744const statically_added_number = staticAdd(1, 2);
48fn staticAdd(a: i32, b: i32) i32 { return a + b; }
49
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
5048
5149test "const expr eval on single expr blocks" {
5250 assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
......@@ -64,9 +62,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
6462 return result;
6563}
6664
67
68
69
7065test "statically initialized list" {
7166 assert(static_point_list[0].x == 1);
7267 assert(static_point_list[0].y == 2);
......@@ -77,7 +72,10 @@ const Point = struct {
7772 x: i32,
7873 y: i32,
7974};
80const static_point_list = []Point { makePoint(1, 2), makePoint(3, 4) };
75const static_point_list = []Point {
76 makePoint(1, 2),
77 makePoint(3, 4),
78};
8179fn makePoint(x: i32, y: i32) Point {
8280 return Point {
8381 .x = x,
......@@ -85,7 +83,6 @@ fn makePoint(x: i32, y: i32) Point {
8583 };
8684}
8785
88
8986test "static eval list init" {
9087 assert(static_vec3.data[2] == 1.0);
9188 assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
......@@ -96,17 +93,19 @@ pub const Vec3 = struct {
9693};
9794pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
9895 return Vec3 {
99 .data = []f32 { x, y, z, },
96 .data = []f32 {
97 x,
98 y,
99 z,
100 },
100101 };
101102}
102103
103
104104test "constant expressions" {
105 var array : [array_size]u8 = undefined;
105 var array: [array_size]u8 = undefined;
106106 assert(@sizeOf(@typeOf(array)) == 20);
107107}
108const array_size : u8 = 20;
109
108const array_size: u8 = 20;
110109
111110test "constant struct with negation" {
112111 assert(vertices[0].x == -0.6);
......@@ -119,12 +118,29 @@ const Vertex = struct {
119118 b: f32,
120119};
121120const vertices = []Vertex {
122 Vertex { .x = -0.6, .y = -0.4, .r = 1.0, .g = 0.0, .b = 0.0 },
123 Vertex { .x = 0.6, .y = -0.4, .r = 0.0, .g = 1.0, .b = 0.0 },
124 Vertex { .x = 0.0, .y = 0.6, .r = 0.0, .g = 0.0, .b = 1.0 },
121 Vertex {
122 .x = -0.6,
123 .y = -0.4,
124 .r = 1.0,
125 .g = 0.0,
126 .b = 0.0,
127 },
128 Vertex {
129 .x = 0.6,
130 .y = -0.4,
131 .r = 0.0,
132 .g = 1.0,
133 .b = 0.0,
134 },
135 Vertex {
136 .x = 0.0,
137 .y = 0.6,
138 .r = 0.0,
139 .g = 0.0,
140 .b = 1.0,
141 },
125142};
126143
127
128144test "statically initialized struct" {
129145 st_init_str_foo.x += 1;
130146 assert(st_init_str_foo.x == 14);
......@@ -133,15 +149,21 @@ const StInitStrFoo = struct {
133149 x: i32,
134150 y: bool,
135151};
136var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, };
137
152var st_init_str_foo = StInitStrFoo {
153 .x = 13,
154 .y = true,
155};
138156
139157test "statically initalized array literal" {
140 const y : [4]u8 = st_init_arr_lit_x;
158 const y: [4]u8 = st_init_arr_lit_x;
141159 assert(y[3] == 4);
142160}
143const st_init_arr_lit_x = []u8{1,2,3,4};
144
161const st_init_arr_lit_x = []u8 {
162 1,
163 2,
164 3,
165 4,
166};
145167
146168test "const slice" {
147169 comptime {
......@@ -198,14 +220,29 @@ const CmdFn = struct {
198220 func: fn(i32) i32,
199221};
200222
201const cmd_fns = []CmdFn{
202 CmdFn {.name = "one", .func = one},
203 CmdFn {.name = "two", .func = two},
204 CmdFn {.name = "three", .func = three},
223const cmd_fns = []CmdFn {
224 CmdFn {
225 .name = "one",
226 .func = one,
227 },
228 CmdFn {
229 .name = "two",
230 .func = two,
231 },
232 CmdFn {
233 .name = "three",
234 .func = three,
235 },
205236};
206fn one(value: i32) i32 { return value + 1; }
207fn two(value: i32) i32 { return value + 2; }
208fn three(value: i32) i32 { return value + 3; }
237fn one(value: i32) i32 {
238 return value + 1;
239}
240fn two(value: i32) i32 {
241 return value + 2;
242}
243fn three(value: i32) i32 {
244 return value + 3;
245}
209246
210247fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
211248 var result: i32 = start_value;
......@@ -229,7 +266,7 @@ test "eval @setRuntimeSafety at compile-time" {
229266 assert(result == 1234);
230267}
231268
232fn fnWithSetRuntimeSafety() i32{
269fn fnWithSetRuntimeSafety() i32 {
233270 @setRuntimeSafety(true);
234271 return 1234;
235272}
......@@ -244,7 +281,6 @@ fn fnWithFloatMode() f32 {
244281 return 1234.0;
245282}
246283
247
248284const SimpleStruct = struct {
249285 field: i32,
250286
......@@ -253,7 +289,9 @@ const SimpleStruct = struct {
253289 }
254290};
255291
256var simple_struct = SimpleStruct{ .field = 1234, };
292var simple_struct = SimpleStruct {
293 .field = 1234,
294};
257295
258296const bound_fn = simple_struct.method;
259297
......@@ -261,8 +299,6 @@ test "call method on bound fn referring to var instance" {
261299 assert(bound_fn() == 1237);
262300}
263301
264
265
266302test "ptr to local array argument at comptime" {
267303 comptime {
268304 var bytes: [10]u8 = undefined;
......@@ -277,7 +313,6 @@ fn modifySomeBytes(bytes: []u8) void {
277313 bytes[9] = 'b';
278314}
279315
280
281316test "comparisons 0 <= uint and 0 > uint should be comptime" {
282317 testCompTimeUIntComparisons(1234);
283318}
......@@ -296,8 +331,6 @@ fn testCompTimeUIntComparisons(x: u32) void {
296331 }
297332}
298333
299
300
301334test "const ptr to variable data changes at runtime" {
302335 assert(foo_ref.name[0] == 'a');
303336 foo_ref.name = "b";
......@@ -308,11 +341,11 @@ const Foo = struct {
308341 name: []const u8,
309342};
310343
311var foo_contents = Foo { .name = "a", };
344var foo_contents = Foo {
345 .name = "a",
346};
312347const foo_ref = &foo_contents;
313348
314
315
316349test "create global array with for loop" {
317350 assert(global_array[5] == 5 * 5);
318351 assert(global_array[9] == 9 * 9);
......@@ -321,7 +354,7 @@ test "create global array with for loop" {
321354const global_array = x: {
322355 var result: [10]usize = undefined;
323356 for (result) |*item, index| {
324 *item = index * index;
357 item.* = index * index;
325358 }
326359 break :x result;
327360};
......@@ -379,7 +412,7 @@ test "f128 at compile time is lossy" {
379412
380413pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
381414 return struct {
382 pub const Node = struct { };
415 pub const Node = struct {};
383416 };
384417}
385418
......@@ -401,10 +434,10 @@ fn copyWithPartialInline(s: []u32, b: []u8) void {
401434 comptime var i: usize = 0;
402435 inline while (i < 4) : (i += 1) {
403436 s[i] = 0;
404 s[i] |= u32(b[i*4+0]) << 24;
405 s[i] |= u32(b[i*4+1]) << 16;
406 s[i] |= u32(b[i*4+2]) << 8;
407 s[i] |= u32(b[i*4+3]) << 0;
437 s[i] |= u32(b[i * 4 + 0]) << 24;
438 s[i] |= u32(b[i * 4 + 1]) << 16;
439 s[i] |= u32(b[i * 4 + 2]) << 8;
440 s[i] |= u32(b[i * 4 + 3]) << 0;
408441 }
409442}
410443
......@@ -413,7 +446,7 @@ test "binary math operator in partially inlined function" {
413446 var b: [16]u8 = undefined;
414447
415448 for (b) |*r, i|
416 *r = u8(i + 1);
449 r.* = u8(i + 1);
417450
418451 copyWithPartialInline(s[0..], b[0..]);
419452 assert(s[0] == 0x1020304);
......@@ -422,7 +455,6 @@ test "binary math operator in partially inlined function" {
422455 assert(s[3] == 0xd0e0f10);
423456}
424457
425
426458test "comptime function with the same args is memoized" {
427459 comptime {
428460 assert(MakeType(i32) == MakeType(i32));
......@@ -447,12 +479,12 @@ test "comptime function with mutable pointer is not memoized" {
447479}
448480
449481fn increment(value: &i32) void {
450 *value += 1;
482 value.* += 1;
451483}
452484
453485fn generateTable(comptime T: type) [1010]T {
454 var res : [1010]T = undefined;
455 var i : usize = 0;
486 var res: [1010]T = undefined;
487 var i: usize = 0;
456488 while (i < 1010) : (i += 1) {
457489 res[i] = T(i);
458490 }
......@@ -496,9 +528,10 @@ const SingleFieldStruct = struct {
496528 }
497529};
498530test "const ptr to comptime mutable data is not memoized" {
499
500531 comptime {
501 var foo = SingleFieldStruct {.x = 1};
532 var foo = SingleFieldStruct {
533 .x = 1,
534 };
502535 assert(foo.read_x() == 1);
503536 foo.x = 2;
504537 assert(foo.read_x() == 2);
......@@ -536,3 +569,20 @@ test "runtime 128 bit integer division" {
536569 var c = a / b;
537570 assert(c == 15231399999);
538571}
572
573pub const Info = struct {
574 version: u8,
575};
576
577pub const diamond_info = Info {
578 .version = 0,
579};
580
581test "comptime modification of const struct field" {
582 comptime {
583 var res = diamond_info;
584 res.version = 1;
585 assert(diamond_info.version == 0);
586 assert(res.version == 1);
587 }
588}
test/cases/fn.zig+26-18
......@@ -7,7 +7,6 @@ fn testParamsAdd(a: i32, b: i32) i32 {
77 return a + b;
88}
99
10
1110test "local variables" {
1211 testLocVars(2);
1312}
......@@ -16,7 +15,6 @@ fn testLocVars(b: i32) void {
1615 if (a + b != 3) unreachable;
1716}
1817
19
2018test "void parameters" {
2119 voidFun(1, void{}, 2, {});
2220}
......@@ -27,9 +25,8 @@ fn voidFun(a: i32, b: void, c: i32, d: void) void {
2725 return vv;
2826}
2927
30
3128test "mutable local variables" {
32 var zero : i32 = 0;
29 var zero: i32 = 0;
3330 assert(zero == 0);
3431
3532 var i = i32(0);
......@@ -41,7 +38,7 @@ test "mutable local variables" {
4138
4239test "separate block scopes" {
4340 {
44 const no_conflict : i32 = 5;
41 const no_conflict: i32 = 5;
4542 assert(no_conflict == 5);
4643 }
4744
......@@ -56,8 +53,7 @@ test "call function with empty string" {
5653 acceptsString("");
5754}
5855
59fn acceptsString(foo: []u8) void { }
60
56fn acceptsString(foo: []u8) void {}
6157
6258fn @"weird function name"() i32 {
6359 return 1234;
......@@ -70,31 +66,43 @@ test "implicit cast function unreachable return" {
7066 wantsFnWithVoid(fnWithUnreachable);
7167}
7268
73fn wantsFnWithVoid(f: fn() void) void { }
69fn wantsFnWithVoid(f: fn() void) void {}
7470
7571fn fnWithUnreachable() noreturn {
7672 unreachable;
7773}
7874
79
8075test "function pointers" {
81 const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, };
76 const fns = []@typeOf(fn1) {
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
8282 for (fns) |f, i| {
8383 assert(f() == u32(i) + 5);
8484 }
8585}
86fn fn1() u32 {return 5;}
87fn fn2() u32 {return 6;}
88fn fn3() u32 {return 7;}
89fn fn4() u32 {return 8;}
90
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
9198
9299test "inline function call" {
93100 assert(@inlineCall(add, 3, 9) == 12);
94101}
95102
96fn add(a: i32, b: i32) i32 { return a + b; }
97
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
98106
99107test "number literal as an argument" {
100108 numberLiteralArg(3);
......@@ -110,4 +118,4 @@ test "assign inline fn to const variable" {
110118 a();
111119}
112120
113inline fn inlineFn() void { }
121inline fn inlineFn() void {}
test/cases/for.zig+37-7
......@@ -3,8 +3,14 @@ const assert = std.debug.assert;
33const mem = std.mem;
44
55test "continue in for loop" {
6 const array = []i32 {1, 2, 3, 4, 5};
7 var sum : i32 = 0;
6 const array = []i32 {
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
814 for (array) |x| {
915 sum += x;
1016 if (x < 3) {
......@@ -24,17 +30,39 @@ test "for loop with pointer elem var" {
2430}
2531fn mangleString(s: []u8) void {
2632 for (s) |*c| {
27 *c += 1;
33 c.* += 1;
2834 }
2935}
3036
3137test "basic for loop" {
32 const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 };
38 const expected_result = []u8 {
39 9,
40 8,
41 7,
42 6,
43 0,
44 1,
45 2,
46 3,
47 9,
48 8,
49 7,
50 6,
51 0,
52 1,
53 2,
54 3,
55 };
3356
3457 var buffer: [expected_result.len]u8 = undefined;
3558 var buf_index: usize = 0;
3659
37 const array = []u8 {9, 8, 7, 6};
60 const array = []u8 {
61 9,
62 8,
63 7,
64 6,
65 };
3866 for (array) |item| {
3967 buffer[buf_index] = item;
4068 buf_index += 1;
......@@ -65,7 +93,8 @@ fn testBreakOuter() void {
6593 var array = "aoeu";
6694 var count: usize = 0;
6795 outer: for (array) |_| {
68 for (array) |_2| { // TODO shouldn't get error for redeclaring "_"
96 // TODO shouldn't get error for redeclaring "_"
97 for (array) |_2| {
6998 count += 1;
7099 break :outer;
71100 }
......@@ -82,7 +111,8 @@ fn testContinueOuter() void {
82111 var array = "aoeu";
83112 var counter: usize = 0;
84113 outer: for (array) |_| {
85 for (array) |_2| { // TODO shouldn't get error for redeclaring "_"
114 // TODO shouldn't get error for redeclaring "_"
115 for (array) |_2| {
86116 counter += 1;
87117 continue :outer;
88118 }
test/cases/generics.zig+28-14
......@@ -37,7 +37,6 @@ test "fn with comptime args" {
3737 assert(sameButWithFloats(0.43, 0.49) == 0.49);
3838}
3939
40
4140test "var params" {
4241 assert(max_i32(12, 34) == 34);
4342 assert(max_f64(1.2, 3.4) == 3.4);
......@@ -60,7 +59,6 @@ fn max_f64(a: f64, b: f64) f64 {
6059 return max_var(a, b);
6160}
6261
63
6462pub fn List(comptime T: type) type {
6563 return SmallList(T, 8);
6664}
......@@ -82,10 +80,15 @@ test "function with return type type" {
8280 assert(list2.prealloc_items.len == 8);
8381}
8482
85
8683test "generic struct" {
87 var a1 = GenNode(i32) {.value = 13, .next = null,};
88 var b1 = GenNode(bool) {.value = true, .next = null,};
84 var a1 = GenNode(i32) {
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool) {
89 .value = true,
90 .next = null,
91 };
8992 assert(a1.value == 13);
9093 assert(a1.value == a1.getVal());
9194 assert(b1.getVal());
......@@ -94,7 +97,9 @@ fn GenNode(comptime T: type) type {
9497 return struct {
9598 value: T,
9699 next: ?&GenNode(T),
97 fn getVal(n: &const GenNode(T)) T { return n.value; }
100 fn getVal(n: &const GenNode(T)) T {
101 return n.value;
102 }
98103 };
99104}
100105
......@@ -107,7 +112,6 @@ fn GenericDataThing(comptime count: isize) type {
107112 };
108113}
109114
110
111115test "use generic param in generic param" {
112116 assert(aGenericFn(i32, 3, 4) == 7);
113117}
......@@ -115,21 +119,31 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
115119 return a + b;
116120}
117121
118
119122test "generic fn with implicit cast" {
120123 assert(getFirstByte(u8, []u8 {13}) == 13);
121 assert(getFirstByte(u16, []u16 {0, 13}) == 0);
124 assert(getFirstByte(u16, []u16 {
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?&const u8) u8 {
130 return (??ptr).*;
122131}
123fn getByte(ptr: ?&const u8) u8 {return *??ptr;}
124132fn getFirstByte(comptime T: type, mem: []const T) u8 {
125133 return getByte(@ptrCast(&const u8, &mem[0]));
126134}
127135
136const foos = []fn(var) bool {
137 foo1,
138 foo2,
139};
128140
129const foos = []fn(var) bool { foo1, foo2 };
130
131fn foo1(arg: var) bool { return arg; }
132fn foo2(arg: var) bool { return !arg; }
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
133147
134148test "array of generic fns" {
135149 assert(foos[0](true));
test/cases/if.zig-1
......@@ -23,7 +23,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
2323 }
2424}
2525
26
2726test "else if expression" {
2827 assert(elseIfExpressionF(1) == 1);
2928}
test/cases/import/a_namespace.zig+3-1
......@@ -1 +1,3 @@
1pub fn foo() i32 { return 1234; }
1pub fn foo() i32 {
2 return 1234;
3}
test/cases/ir_block_deps.zig+3-1
......@@ -11,7 +11,9 @@ fn foo(id: u64) !i32 {
1111 };
1212}
1313
14fn getErrInt() error!i32 { return 0; }
14fn getErrInt() error!i32 {
15 return 0;
16}
1517
1618test "ir block deps" {
1719 assert((foo(1) catch unreachable) == 0);
test/cases/math.zig+40-52
......@@ -28,25 +28,12 @@ fn testDivision() void {
2828 assert(divTrunc(f32, -5.0, 3.0) == -1.0);
2929
3030 comptime {
31 assert(
32 1194735857077236777412821811143690633098347576 %
33 508740759824825164163191790951174292733114988 ==
34 177254337427586449086438229241342047632117600);
35 assert(@rem(-1194735857077236777412821811143690633098347576,
36 508740759824825164163191790951174292733114988) ==
37 -177254337427586449086438229241342047632117600);
38 assert(1194735857077236777412821811143690633098347576 /
39 508740759824825164163191790951174292733114988 ==
40 2);
41 assert(@divTrunc(-1194735857077236777412821811143690633098347576,
42 508740759824825164163191790951174292733114988) ==
43 -2);
44 assert(@divTrunc(1194735857077236777412821811143690633098347576,
45 -508740759824825164163191790951174292733114988) ==
46 -2);
47 assert(@divTrunc(-1194735857077236777412821811143690633098347576,
48 -508740759824825164163191790951174292733114988) ==
49 2);
31 assert(1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600);
32 assert(@rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600);
33 assert(1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2);
34 assert(@divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2);
35 assert(@divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2);
36 assert(@divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2);
5037 assert(4126227191251978491697987544882340798050766755606969681711 % 10 == 1);
5138 }
5239}
......@@ -114,18 +101,28 @@ fn ctz(x: var) usize {
114101
115102test "assignment operators" {
116103 var i: u32 = 0;
117 i += 5; assert(i == 5);
118 i -= 2; assert(i == 3);
119 i *= 20; assert(i == 60);
120 i /= 3; assert(i == 20);
121 i %= 11; assert(i == 9);
122 i <<= 1; assert(i == 18);
123 i >>= 2; assert(i == 4);
104 i += 5;
105 assert(i == 5);
106 i -= 2;
107 assert(i == 3);
108 i *= 20;
109 assert(i == 60);
110 i /= 3;
111 assert(i == 20);
112 i %= 11;
113 assert(i == 9);
114 i <<= 1;
115 assert(i == 18);
116 i >>= 2;
117 assert(i == 4);
124118 i = 6;
125 i &= 5; assert(i == 4);
126 i ^= 6; assert(i == 2);
119 i &= 5;
120 assert(i == 4);
121 i ^= 6;
122 assert(i == 2);
127123 i = 6;
128 i |= 3; assert(i == 7);
124 i |= 3;
125 assert(i == 7);
129126}
130127
131128test "three expr in a row" {
......@@ -138,7 +135,7 @@ fn testThreeExprInARow(f: bool, t: bool) void {
138135 assertFalse(1 | 2 | 4 != 7);
139136 assertFalse(3 ^ 6 ^ 8 != 13);
140137 assertFalse(7 & 14 & 28 != 4);
141 assertFalse(9 << 1 << 2 != 9 << 3);
138 assertFalse(9 << 1 << 2 != 9 << 3);
142139 assertFalse(90 >> 1 >> 2 != 90 >> 3);
143140 assertFalse(100 - 1 + 1000 != 1099);
144141 assertFalse(5 * 4 / 2 % 3 != 1);
......@@ -150,7 +147,6 @@ fn assertFalse(b: bool) void {
150147 assert(!b);
151148}
152149
153
154150test "const number literal" {
155151 const one = 1;
156152 const eleven = ten + one;
......@@ -159,8 +155,6 @@ test "const number literal" {
159155}
160156const ten = 10;
161157
162
163
164158test "unsigned wrapping" {
165159 testUnsignedWrappingEval(@maxValue(u32));
166160 comptime testUnsignedWrappingEval(@maxValue(u32));
......@@ -214,8 +208,12 @@ const DivResult = struct {
214208};
215209
216210test "binary not" {
217 assert(comptime x: {break :x ~u16(0b1010101010101010) == 0b0101010101010101;});
218 assert(comptime x: {break :x ~u64(2147483647) == 18446744071562067968;});
211 assert(comptime x: {
212 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
213 });
214 assert(comptime x: {
215 break :x ~u64(2147483647) == 18446744071562067968;
216 });
219217 testBinaryNot(0b1010101010101010);
220218}
221219
......@@ -319,27 +317,15 @@ fn testShrExact(x: u8) void {
319317
320318test "big number addition" {
321319 comptime {
322 assert(
323 35361831660712422535336160538497375248 +
324 101752735581729509668353361206450473702 ==
325 137114567242441932203689521744947848950);
326 assert(
327 594491908217841670578297176641415611445982232488944558774612 +
328 390603545391089362063884922208143568023166603618446395589768 ==
329 985095453608931032642182098849559179469148836107390954364380);
320 assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
321 assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
330322 }
331323}
332324
333325test "big number multiplication" {
334326 comptime {
335 assert(
336 45960427431263824329884196484953148229 *
337 128339149605334697009938835852565949723 ==
338 5898522172026096622534201617172456926982464453350084962781392314016180490567);
339 assert(
340 594491908217841670578297176641415611445982232488944558774612 *
341 390603545391089362063884922208143568023166603618446395589768 ==
342 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016);
327 assert(45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567);
328 assert(594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016);
343329 }
344330}
345331
......@@ -405,7 +391,9 @@ test "f128" {
405391 comptime test_f128();
406392}
407393
408fn make_f128(x: f128) f128 { return x; }
394fn make_f128(x: f128) f128 {
395 return x;
396}
409397
410398fn test_f128() void {
411399 assert(@sizeOf(f128) == 16);
test/cases/misc.zig+139-88
......@@ -4,6 +4,7 @@ const cstr = @import("std").cstr;
44const builtin = @import("builtin");
55
66// normal comment
7
78/// this is a documentation comment
89/// doc comment line 2
910fn emptyFunctionWithComments() void {}
......@@ -16,8 +17,7 @@ comptime {
1617 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
1718}
1819
19extern fn disabledExternFn() void {
20}
20extern fn disabledExternFn() void {}
2121
2222test "call disabled extern fn" {
2323 disabledExternFn();
......@@ -110,17 +110,29 @@ fn testShortCircuit(f: bool, t: bool) void {
110110 var hit_3 = f;
111111 var hit_4 = f;
112112
113 if (t or x: {assert(f); break :x f;}) {
113 if (t or x: {
114 assert(f);
115 break :x f;
116 }) {
114117 hit_1 = t;
115118 }
116 if (f or x: { hit_2 = t; break :x f; }) {
119 if (f or x: {
120 hit_2 = t;
121 break :x f;
122 }) {
117123 assert(f);
118124 }
119125
120 if (t and x: { hit_3 = t; break :x f; }) {
126 if (t and x: {
127 hit_3 = t;
128 break :x f;
129 }) {
121130 assert(f);
122131 }
123 if (f and x: {assert(f); break :x f;}) {
132 if (f and x: {
133 assert(f);
134 break :x f;
135 }) {
124136 assert(f);
125137 } else {
126138 hit_4 = t;
......@@ -146,8 +158,8 @@ test "return string from function" {
146158 assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
147159}
148160
149const g1 : i32 = 1233 + 1;
150var g2 : i32 = 0;
161const g1: i32 = 1233 + 1;
162var g2: i32 = 0;
151163
152164test "global variables" {
153165 assert(g2 == 0);
......@@ -155,10 +167,9 @@ test "global variables" {
155167 assert(g2 == 1234);
156168}
157169
158
159170test "memcpy and memset intrinsics" {
160 var foo : [20]u8 = undefined;
161 var bar : [20]u8 = undefined;
171 var foo: [20]u8 = undefined;
172 var bar: [20]u8 = undefined;
162173
163174 @memset(&foo[0], 'A', foo.len);
164175 @memcpy(&bar[0], &foo[0], bar.len);
......@@ -167,12 +178,14 @@ test "memcpy and memset intrinsics" {
167178}
168179
169180test "builtin static eval" {
170 const x : i32 = comptime x: {break :x 1 + 2 + 3;};
181 const x: i32 = comptime x: {
182 break :x 1 + 2 + 3;
183 };
171184 assert(x == comptime 6);
172185}
173186
174187test "slicing" {
175 var array : [20]i32 = undefined;
188 var array: [20]i32 = undefined;
176189
177190 array[5] = 1234;
178191
......@@ -187,15 +200,15 @@ test "slicing" {
187200 if (slice_rest.len != 10) unreachable;
188201}
189202
190
191203test "constant equal function pointers" {
192204 const alias = emptyFn;
193 assert(comptime x: {break :x emptyFn == alias;});
205 assert(comptime x: {
206 break :x emptyFn == alias;
207 });
194208}
195209
196210fn emptyFn() void {}
197211
198
199212test "hex escape" {
200213 assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
201214}
......@@ -219,7 +232,7 @@ test "string escapes" {
219232}
220233
221234test "multiline string" {
222 const s1 =
235 const s1 =
223236 \\one
224237 \\two)
225238 \\three
......@@ -229,7 +242,7 @@ test "multiline string" {
229242}
230243
231244test "multiline C string" {
232 const s1 =
245 const s1 =
233246 c\\one
234247 c\\two)
235248 c\\three
......@@ -238,18 +251,16 @@ test "multiline C string" {
238251 assert(cstr.cmp(s1, s2) == 0);
239252}
240253
241
242254test "type equality" {
243255 assert(&const u8 != &u8);
244256}
245257
246
247258const global_a: i32 = 1234;
248259const global_b: &const i32 = &global_a;
249260const global_c: &const f32 = @ptrCast(&const f32, global_b);
250261test "compile time global reinterpret" {
251262 const d = @ptrCast(&const i32, global_c);
252 assert(*d == 1234);
263 assert(d.* == 1234);
253264}
254265
255266test "explicit cast maybe pointers" {
......@@ -261,12 +272,11 @@ test "generic malloc free" {
261272 const a = memAlloc(u8, 10) catch unreachable;
262273 memFree(u8, a);
263274}
264var some_mem : [100]u8 = undefined;
275var some_mem: [100]u8 = undefined;
265276fn memAlloc(comptime T: type, n: usize) error![]T {
266277 return @ptrCast(&T, &some_mem[0])[0..n];
267278}
268fn memFree(comptime T: type, memory: []T) void { }
269
279fn memFree(comptime T: type, memory: []T) void {}
270280
271281test "cast undefined" {
272282 const array: [100]u8 = undefined;
......@@ -275,32 +285,35 @@ test "cast undefined" {
275285}
276286fn testCastUndefined(x: []const u8) void {}
277287
278
279288test "cast small unsigned to larger signed" {
280289 assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
281290 assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
282291}
283fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; }
284fn castSmallUnsignedToLargerSigned2(x: u16) i64 { return x; }
285
292fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
293 return x;
294}
295fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
296 return x;
297}
286298
287299test "implicit cast after unreachable" {
288300 assert(outer() == 1234);
289301}
290fn inner() i32 { return 1234; }
302fn inner() i32 {
303 return 1234;
304}
291305fn outer() i64 {
292306 return inner();
293307}
294308
295
296309test "pointer dereferencing" {
297310 var x = i32(3);
298311 const y = &x;
299312
300 *y += 1;
313 y.* += 1;
301314
302315 assert(x == 4);
303 assert(*y == 4);
316 assert(y.* == 4);
304317}
305318
306319test "call result of if else expression" {
......@@ -310,9 +323,12 @@ test "call result of if else expression" {
310323fn f2(x: bool) []const u8 {
311324 return (if (x) fA else fB)();
312325}
313fn fA() []const u8 { return "a"; }
314fn fB() []const u8 { return "b"; }
315
326fn fA() []const u8 {
327 return "a";
328}
329fn fB() []const u8 {
330 return "b";
331}
316332
317333test "const expression eval handling of variables" {
318334 var x = true;
......@@ -321,8 +337,6 @@ test "const expression eval handling of variables" {
321337 }
322338}
323339
324
325
326340test "constant enum initialization with differing sizes" {
327341 test3_1(test3_foo);
328342 test3_2(test3_bar);
......@@ -336,10 +350,17 @@ const Test3Point = struct {
336350 x: i32,
337351 y: i32,
338352};
339const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}};
340const test3_bar = Test3Foo { .Two = 13};
353const test3_foo = Test3Foo {
354 .Three = Test3Point {
355 .x = 3,
356 .y = 4,
357 },
358};
359const test3_bar = Test3Foo {
360 .Two = 13,
361};
341362fn test3_1(f: &const Test3Foo) void {
342 switch (*f) {
363 switch (f.*) {
343364 Test3Foo.Three => |pt| {
344365 assert(pt.x == 3);
345366 assert(pt.y == 4);
......@@ -348,7 +369,7 @@ fn test3_1(f: &const Test3Foo) void {
348369 }
349370}
350371fn test3_2(f: &const Test3Foo) void {
351 switch (*f) {
372 switch (f.*) {
352373 Test3Foo.Two => |x| {
353374 assert(x == 13);
354375 },
......@@ -356,23 +377,19 @@ fn test3_2(f: &const Test3Foo) void {
356377 }
357378}
358379
359
360380test "character literals" {
361381 assert('\'' == single_quote);
362382}
363383const single_quote = '\'';
364384
365
366
367385test "take address of parameter" {
368386 testTakeAddressOfParameter(12.34);
369387}
370388fn testTakeAddressOfParameter(f: f32) void {
371389 const f_ptr = &f;
372 assert(*f_ptr == 12.34);
390 assert(f_ptr.* == 12.34);
373391}
374392
375
376393test "pointer comparison" {
377394 const a = ([]const u8)("a");
378395 const b = &a;
......@@ -382,23 +399,30 @@ fn ptrEql(a: &const []const u8, b: &const []const u8) bool {
382399 return a == b;
383400}
384401
385
386402test "C string concatenation" {
387403 const a = c"OK" ++ c" IT " ++ c"WORKED";
388404 const b = c"OK IT WORKED";
389405
390406 const len = cstr.len(b);
391407 const len_with_null = len + 1;
392 {var i: u32 = 0; while (i < len_with_null) : (i += 1) {
393 assert(a[i] == b[i]);
394 }}
408 {
409 var i: u32 = 0;
410 while (i < len_with_null) : (i += 1) {
411 assert(a[i] == b[i]);
412 }
413 }
395414 assert(a[len] == 0);
396415 assert(b[len] == 0);
397416}
398417
399418test "cast slice to u8 slice" {
400419 assert(@sizeOf(i32) == 4);
401 var big_thing_array = []i32{1, 2, 3, 4};
420 var big_thing_array = []i32 {
421 1,
422 2,
423 3,
424 4,
425 };
402426 const big_thing_slice: []i32 = big_thing_array[0..];
403427 const bytes = ([]u8)(big_thing_slice);
404428 assert(bytes.len == 4 * 4);
......@@ -421,25 +445,22 @@ test "pointer to void return type" {
421445}
422446fn testPointerToVoidReturnType() error!void {
423447 const a = testPointerToVoidReturnType2();
424 return *a;
448 return a.*;
425449}
426450const test_pointer_to_void_return_type_x = void{};
427451fn testPointerToVoidReturnType2() &const void {
428452 return &test_pointer_to_void_return_type_x;
429453}
430454
431
432455test "non const ptr to aliased type" {
433456 const int = i32;
434457 assert(?&int == ?&i32);
435458}
436459
437
438
439460test "array 2D const double ptr" {
440461 const rect_2d_vertexes = [][1]f32 {
441 []f32{1.0},
442 []f32{2.0},
462 []f32 {1.0},
463 []f32 {2.0},
443464 };
444465 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
445466}
......@@ -450,10 +471,21 @@ fn testArray2DConstDoublePtr(ptr: &const f32) void {
450471}
451472
452473const Tid = builtin.TypeId;
453const AStruct = struct { x: i32, };
454const AnEnum = enum { One, Two, };
455const AUnionEnum = union(enum) { One: i32, Two: void, };
456const AUnion = union { One: void, Two: void };
474const AStruct = struct {
475 x: i32,
476};
477const AnEnum = enum {
478 One,
479 Two,
480};
481const AUnionEnum = union(enum) {
482 One: i32,
483 Two: void,
484};
485const AUnion = union {
486 One: void,
487 Two: void,
488};
457489
458490test "@typeId" {
459491 comptime {
......@@ -481,9 +513,11 @@ test "@typeId" {
481513 assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
482514 assert(@typeId(AUnionEnum) == Tid.Union);
483515 assert(@typeId(AUnion) == Tid.Union);
484 assert(@typeId(fn()void) == Tid.Fn);
516 assert(@typeId(fn() void) == Tid.Fn);
485517 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
486 assert(@typeId(@typeOf(x: {break :x this;})) == Tid.Block);
518 assert(@typeId(@typeOf(x: {
519 break :x this;
520 })) == Tid.Block);
487521 // TODO bound fn
488522 // TODO arg tuple
489523 // TODO opaque
......@@ -499,8 +533,7 @@ test "@canImplicitCast" {
499533}
500534
501535test "@typeName" {
502 const Struct = struct {
503 };
536 const Struct = struct {};
504537 const Union = union {
505538 unused: u8,
506539 };
......@@ -510,7 +543,7 @@ test "@typeName" {
510543 comptime {
511544 assert(mem.eql(u8, @typeName(i64), "i64"));
512545 assert(mem.eql(u8, @typeName(&usize), "&usize"));
513 // https://github.com/zig-lang/zig/issues/675
546 // https://github.com/ziglang/zig/issues/675
514547 assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
515548 assert(mem.eql(u8, @typeName(Struct), "Struct"));
516549 assert(mem.eql(u8, @typeName(Union), "Union"));
......@@ -525,14 +558,19 @@ fn TypeFromFn(comptime T: type) type {
525558test "volatile load and store" {
526559 var number: i32 = 1234;
527560 const ptr = (&volatile i32)(&number);
528 *ptr += 1;
529 assert(*ptr == 1235);
561 ptr.* += 1;
562 assert(ptr.* == 1235);
530563}
531564
532565test "slice string literal has type []const u8" {
533566 comptime {
534567 assert(@typeOf("aoeu"[0..]) == []const u8);
535 const array = []i32{1, 2, 3, 4};
568 const array = []i32 {
569 1,
570 2,
571 3,
572 4,
573 };
536574 assert(@typeOf(array[0..]) == []const i32);
537575 }
538576}
......@@ -544,12 +582,15 @@ const GDTEntry = struct {
544582 field: i32,
545583};
546584var gdt = []GDTEntry {
547 GDTEntry {.field = 1},
548 GDTEntry {.field = 2},
585 GDTEntry {
586 .field = 1,
587 },
588 GDTEntry {
589 .field = 2,
590 },
549591};
550592var global_ptr = &gdt[0];
551593
552
553594// can't really run this test but we can make sure it has no compile error
554595// and generates code
555596const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000];
......@@ -584,7 +625,7 @@ test "comptime if inside runtime while which unconditionally breaks" {
584625}
585626fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
586627 while (cond) {
587 if (false) { }
628 if (false) {}
588629 break;
589630 }
590631}
......@@ -607,7 +648,9 @@ fn testStructInFn() void {
607648 kind: BlockKind,
608649 };
609650
610 var block = Block { .kind = 1234 };
651 var block = Block {
652 .kind = 1234,
653 };
611654
612655 block.kind += 1;
613656
......@@ -617,7 +660,9 @@ fn testStructInFn() void {
617660fn fnThatClosesOverLocalConst() type {
618661 const c = 1;
619662 return struct {
620 fn g() i32 { return c; }
663 fn g() i32 {
664 return c;
665 }
621666 };
622667}
623668
......@@ -635,22 +680,29 @@ fn thisIsAColdFn() void {
635680 @setCold(true);
636681}
637682
638
639const PackedStruct = packed struct { a: u8, b: u8, };
640const PackedUnion = packed union { a: u8, b: u32, };
641const PackedEnum = packed enum { A, B, };
683const PackedStruct = packed struct {
684 a: u8,
685 b: u8,
686};
687const PackedUnion = packed union {
688 a: u8,
689 b: u32,
690};
691const PackedEnum = packed enum {
692 A,
693 B,
694};
642695
643696test "packed struct, enum, union parameters in extern function" {
644 testPackedStuff(
645 PackedStruct{.a = 1, .b = 2},
646 PackedUnion{.a = 1},
647 PackedEnum.A,
648 );
649}
650
651export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {
697 testPackedStuff(PackedStruct {
698 .a = 1,
699 .b = 2,
700 }, PackedUnion {
701 .a = 1,
702 }, PackedEnum.A);
652703}
653704
705export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {}
654706
655707test "slicing zero length array" {
656708 const s1 = ""[0..];
......@@ -661,7 +713,6 @@ test "slicing zero length array" {
661713 assert(mem.eql(u32, s2, []u32{}));
662714}
663715
664
665716const addr1 = @ptrCast(&const u8, emptyFn);
666717test "comptime cast fn to ptr" {
667718 const addr2 = @ptrCast(&const u8, emptyFn);
test/cases/namespace_depends_on_compile_var/index.zig+1-1
......@@ -8,7 +8,7 @@ test "namespace depends on compile var" {
88 assert(!some_namespace.a_bool);
99 }
1010}
11const some_namespace = switch(builtin.os) {
11const some_namespace = switch (builtin.os) {
1212 builtin.Os.linux => @import("a.zig"),
1313 else => @import("b.zig"),
1414};
test/cases/new_stack_call.zig created+26
......@@ -0,0 +1,26 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 assert(arg == 1234);
14 assert(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assert(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assert(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/cases/null.zig+12-15
......@@ -1,7 +1,7 @@
11const assert = @import("std").debug.assert;
22
33test "nullable type" {
4 const x : ?bool = true;
4 const x: ?bool = true;
55
66 if (x) |y| {
77 if (y) {
......@@ -13,13 +13,13 @@ test "nullable type" {
1313 unreachable;
1414 }
1515
16 const next_x : ?i32 = null;
16 const next_x: ?i32 = null;
1717
1818 const z = next_x ?? 1234;
1919
2020 assert(z == 1234);
2121
22 const final_x : ?i32 = 13;
22 const final_x: ?i32 = 13;
2323
2424 const num = final_x ?? unreachable;
2525
......@@ -30,19 +30,17 @@ test "test maybe object and get a pointer to the inner value" {
3030 var maybe_bool: ?bool = true;
3131
3232 if (maybe_bool) |*b| {
33 *b = false;
33 b.* = false;
3434 }
3535
3636 assert(??maybe_bool == false);
3737}
3838
39
4039test "rhs maybe unwrap return" {
4140 const x: ?bool = true;
4241 const y = x ?? return;
4342}
4443
45
4644test "maybe return" {
4745 maybeReturnImpl();
4846 comptime maybeReturnImpl();
......@@ -50,8 +48,7 @@ test "maybe return" {
5048
5149fn maybeReturnImpl() void {
5250 assert(??foo(1235));
53 if (foo(null) != null)
54 unreachable;
51 if (foo(null) != null) unreachable;
5552 assert(!??foo(1234));
5653}
5754
......@@ -60,12 +57,16 @@ fn foo(x: ?i32) ?bool {
6057 return value > 1234;
6158}
6259
63
6460test "if var maybe pointer" {
65 assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15);
61 assert(shouldBeAPlus1(Particle {
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
6667}
6768fn shouldBeAPlus1(p: &const Particle) u64 {
68 var maybe_particle: ?Particle = *p;
69 var maybe_particle: ?Particle = p.*;
6970 if (maybe_particle) |*particle| {
7071 particle.a += 1;
7172 }
......@@ -81,7 +82,6 @@ const Particle = struct {
8182 d: u64,
8283};
8384
84
8585test "null literal outside function" {
8686 const is_null = here_is_a_null_literal.context == null;
8787 assert(is_null);
......@@ -96,7 +96,6 @@ const here_is_a_null_literal = SillyStruct {
9696 .context = null,
9797};
9898
99
10099test "test null runtime" {
101100 testTestNullRuntime(null);
102101}
......@@ -123,8 +122,6 @@ fn bar(x: ?void) ?void {
123122 }
124123}
125124
126
127
128125const StructWithNullable = struct {
129126 field: ?i32,
130127};
test/cases/pointers.zig created+14
......@@ -0,0 +1,14 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assert(x == 1235);
14}
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig+1-1
......@@ -23,7 +23,7 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
2323 if (c) {
2424 const output_path = b;
2525
26 if (c2) { }
26 if (c2) {}
2727
2828 a(output_path);
2929 }
test/cases/reflection.zig+3-2
......@@ -23,7 +23,9 @@ test "reflection: function return type, var args, and param types" {
2323 }
2424}
2525
26fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; }
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
2729fn dummy_varargs(args: ...) void {}
2830
2931test "reflection: struct member types and names" {
......@@ -54,7 +56,6 @@ test "reflection: enum member types and names" {
5456 assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
5557 assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
5658 }
57
5859}
5960
6061test "reflection: @field" {
test/cases/slice.zig+6-2
......@@ -18,7 +18,11 @@ test "slice child property" {
1818}
1919
2020test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{1, 2, 3};
21 var an_array = []u8 {
22 1,
23 2,
24 3,
25 };
2226 assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
2327}
2428
......@@ -27,7 +31,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
2731}
2832
2933test "implicitly cast array of size 0 to slice" {
30 var msg = []u8 {};
34 var msg = []u8{};
3135 assertLenIsZero(msg);
3236}
3337
test/cases/struct.zig+48-35
......@@ -2,9 +2,11 @@ const assert = @import("std").debug.assert;
22const builtin = @import("builtin");
33
44const StructWithNoFields = struct {
5 fn add(a: i32, b: i32) i32 { return a + b; }
5 fn add(a: i32, b: i32) i32 {
6 return a + b;
7 }
68};
7const empty_global_instance = StructWithNoFields {};
9const empty_global_instance = StructWithNoFields{};
810
911test "call struct static method" {
1012 const result = StructWithNoFields.add(3, 4);
......@@ -34,12 +36,11 @@ test "void struct fields" {
3436 assert(@sizeOf(VoidStructFieldsFoo) == 4);
3537}
3638const VoidStructFieldsFoo = struct {
37 a : void,
38 b : i32,
39 c : void,
39 a: void,
40 b: i32,
41 c: void,
4042};
4143
42
4344test "structs" {
4445 var foo: StructFoo = undefined;
4546 @memset(@ptrCast(&u8, &foo), 0, @sizeOf(StructFoo));
......@@ -50,9 +51,9 @@ test "structs" {
5051 assert(foo.c == 100);
5152}
5253const StructFoo = struct {
53 a : i32,
54 b : bool,
55 c : f32,
54 a: i32,
55 b: bool,
56 c: f32,
5657};
5758fn testFoo(foo: &const StructFoo) void {
5859 assert(foo.b);
......@@ -61,7 +62,6 @@ fn testMutation(foo: &StructFoo) void {
6162 foo.c = 100;
6263}
6364
64
6565const Node = struct {
6666 val: Val,
6767 next: &Node,
......@@ -72,10 +72,10 @@ const Val = struct {
7272};
7373
7474test "struct point to self" {
75 var root : Node = undefined;
75 var root: Node = undefined;
7676 root.val.x = 1;
7777
78 var node : Node = undefined;
78 var node: Node = undefined;
7979 node.next = &root;
8080 node.val.x = 2;
8181
......@@ -85,8 +85,8 @@ test "struct point to self" {
8585}
8686
8787test "struct byval assign" {
88 var foo1 : StructFoo = undefined;
89 var foo2 : StructFoo = undefined;
88 var foo1: StructFoo = undefined;
89 var foo2: StructFoo = undefined;
9090
9191 foo1.a = 1234;
9292 foo2.a = 0;
......@@ -96,46 +96,57 @@ test "struct byval assign" {
9696}
9797
9898fn structInitializer() void {
99 const val = Val { .x = 42 };
99 const val = Val {
100 .x = 42,
101 };
100102 assert(val.x == 42);
101103}
102104
103
104105test "fn call of struct field" {
105 assert(callStructField(Foo {.ptr = aFunc,}) == 13);
106 assert(callStructField(Foo {
107 .ptr = aFunc,
108 }) == 13);
106109}
107110
108111const Foo = struct {
109112 ptr: fn() i32,
110113};
111114
112fn aFunc() i32 { return 13; }
115fn aFunc() i32 {
116 return 13;
117}
113118
114119fn callStructField(foo: &const Foo) i32 {
115120 return foo.ptr();
116121}
117122
118
119123test "store member function in variable" {
120 const instance = MemberFnTestFoo { .x = 1234, };
124 const instance = MemberFnTestFoo {
125 .x = 1234,
126 };
121127 const memberFn = MemberFnTestFoo.member;
122128 const result = memberFn(instance);
123129 assert(result == 1234);
124130}
125131const MemberFnTestFoo = struct {
126132 x: i32,
127 fn member(foo: &const MemberFnTestFoo) i32 { return foo.x; }
133 fn member(foo: &const MemberFnTestFoo) i32 {
134 return foo.x;
135 }
128136};
129137
130
131138test "call member function directly" {
132 const instance = MemberFnTestFoo { .x = 1234, };
139 const instance = MemberFnTestFoo {
140 .x = 1234,
141 };
133142 const result = MemberFnTestFoo.member(instance);
134143 assert(result == 1234);
135144}
136145
137146test "member functions" {
138 const r = MemberFnRand {.seed = 1234};
147 const r = MemberFnRand {
148 .seed = 1234,
149 };
139150 assert(r.getSeed() == 1234);
140151}
141152const MemberFnRand = struct {
......@@ -170,17 +181,16 @@ const EmptyStruct = struct {
170181 }
171182};
172183
173
174184test "return empty struct from fn" {
175185 _ = testReturnEmptyStructFromFn();
176186}
177187const EmptyStruct2 = struct {};
178188fn testReturnEmptyStructFromFn() EmptyStruct2 {
179 return EmptyStruct2 {};
189 return EmptyStruct2{};
180190}
181191
182192test "pass slice of empty struct to fn" {
183 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
193 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2 {EmptyStruct2{}}) == 1);
184194}
185195fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
186196 return slice.len;
......@@ -201,7 +211,6 @@ test "packed struct" {
201211 assert(four == 4);
202212}
203213
204
205214const BitField1 = packed struct {
206215 a: u3,
207216 b: u3,
......@@ -301,7 +310,7 @@ test "packed array 24bits" {
301310 assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302311 }
303312
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
313 var bytes = []u8 {0} ** (@sizeOf(FooArray24Bits) + 1);
305314 bytes[bytes.len - 1] = 0xaa;
306315 const ptr = &([]FooArray24Bits)(bytes[0..bytes.len - 1])[0];
307316 assert(ptr.a == 0);
......@@ -351,7 +360,7 @@ test "aligned array of packed struct" {
351360 assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
352361 }
353362
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
363 var bytes = []u8 {0xbb} ** @sizeOf(FooArrayOfAligned);
355364 const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0];
356365
357366 assert(ptr.a[0].a == 0xbb);
......@@ -360,11 +369,15 @@ test "aligned array of packed struct" {
360369 assert(ptr.a[1].b == 0xbb);
361370}
362371
363
364
365372test "runtime struct initialization of bitfield" {
366 const s1 = Nibbles { .x = x1, .y = x1 };
367 const s2 = Nibbles { .x = u4(x2), .y = u4(x2) };
373 const s1 = Nibbles {
374 .x = x1,
375 .y = x1,
376 };
377 const s2 = Nibbles {
378 .x = u4(x2),
379 .y = u4(x2),
380 };
368381
369382 assert(s1.x == x1);
370383 assert(s1.y == x1);
......@@ -394,7 +407,7 @@ test "native bit field understands endianness" {
394407 var all: u64 = 0x7765443322221111;
395408 var bytes: [8]u8 = undefined;
396409 @memcpy(&bytes[0], @ptrCast(&u8, &all), 8);
397 var bitfields = *@ptrCast(&Bitfields, &bytes[0]);
410 var bitfields = @ptrCast(&Bitfields, &bytes[0]).*;
398411
399412 assert(bitfields.f1 == 0x1111);
400413 assert(bitfields.f2 == 0x2222);
test/cases/struct_contains_null_ptr_itself.zig-1
......@@ -19,4 +19,3 @@ pub const Node = struct {
1919pub const NodeLineComment = struct {
2020 base: Node,
2121};
22
test/cases/struct_contains_slice_of_itself.zig+1-1
......@@ -6,7 +6,7 @@ const Node = struct {
66};
77
88test "struct contains slice of itself" {
9 var other_nodes = []Node{
9 var other_nodes = []Node {
1010 Node {
1111 .payload = 31,
1212 .children = []Node{},
test/cases/switch.zig+33-16
......@@ -6,7 +6,10 @@ test "switch with numbers" {
66
77fn testSwitchWithNumbers(x: u32) void {
88 const result = switch (x) {
9 1, 2, 3, 4 ... 8 => false,
9 1,
10 2,
11 3,
12 4 ... 8 => false,
1013 13 => true,
1114 else => false,
1215 };
......@@ -34,8 +37,10 @@ test "implicit comptime switch" {
3437 const result = switch (x) {
3538 3 => 10,
3639 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
40 5,
41 6 => 12,
42 7,
43 8 => 13,
3944 else => 14,
4045 };
4146
......@@ -61,7 +66,6 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void {
6166 }
6267}
6368
64
6569test "switch statement" {
6670 nonConstSwitch(SwitchStatmentFoo.C);
6771}
......@@ -81,11 +85,16 @@ const SwitchStatmentFoo = enum {
8185 D,
8286};
8387
84
8588test "switch prong with variable" {
86 switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13});
87 switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0});
88 switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}});
89 switchProngWithVarFn(SwitchProngWithVarEnum {
90 .One = 13,
91 });
92 switchProngWithVarFn(SwitchProngWithVarEnum {
93 .Two = 13.0,
94 });
95 switchProngWithVarFn(SwitchProngWithVarEnum {
96 .Meh = {},
97 });
8998}
9099const SwitchProngWithVarEnum = union(enum) {
91100 One: i32,
......@@ -93,7 +102,7 @@ const SwitchProngWithVarEnum = union(enum) {
93102 Meh: void,
94103};
95104fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) void {
96 switch(*a) {
105 switch (a.*) {
97106 SwitchProngWithVarEnum.One => |x| {
98107 assert(x == 13);
99108 },
......@@ -112,9 +121,11 @@ test "switch on enum using pointer capture" {
112121}
113122
114123fn testSwitchEnumPtrCapture() void {
115 var value = SwitchProngWithVarEnum { .One = 1234 };
124 var value = SwitchProngWithVarEnum {
125 .One = 1234,
126 };
116127 switch (value) {
117 SwitchProngWithVarEnum.One => |*x| *x += 1,
128 SwitchProngWithVarEnum.One => |*x| x.* += 1,
118129 else => unreachable,
119130 }
120131 switch (value) {
......@@ -125,8 +136,12 @@ fn testSwitchEnumPtrCapture() void {
125136
126137test "switch with multiple expressions" {
127138 const x = switch (returnsFive()) {
128 1, 2, 3 => 1,
129 4, 5, 6 => 2,
139 1,
140 2,
141 3 => 1,
142 4,
143 5,
144 6 => 2,
130145 else => i32(3),
131146 };
132147 assert(x == 2);
......@@ -135,14 +150,15 @@ fn returnsFive() i32 {
135150 return 5;
136151}
137152
138
139153const Number = union(enum) {
140154 One: u64,
141155 Two: u8,
142156 Three: f32,
143157};
144158
145const number = Number { .Three = 1.23 };
159const number = Number {
160 .Three = 1.23,
161};
146162
147163fn returnsFalse() bool {
148164 switch (number) {
......@@ -198,7 +214,8 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
198214 return switch (x) {
199215 0 ... 100 => u8(0),
200216 101 ... 200 => 1,
201 201, 203 => 2,
217 201,
218 203 => 2,
202219 202 => 4,
203220 204 ... 255 => 3,
204221 };
test/cases/switch_prong_err_enum.zig+6-2
......@@ -14,14 +14,18 @@ const FormValue = union(enum) {
1414
1515fn doThing(form_id: u64) error!FormValue {
1616 return switch (form_id) {
17 17 => FormValue { .Address = try readOnce() },
17 17 => FormValue {
18 .Address = try readOnce(),
19 },
1820 else => error.InvalidDebugInfo,
1921 };
2022}
2123
2224test "switch prong returns error enum" {
2325 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| { assert(payload == 1); },
26 FormValue.Address => |payload| {
27 assert(payload == 1);
28 },
2529 else => unreachable,
2630 }
2731 assert(read_count == 1);
test/cases/switch_prong_implicit_cast.zig+6-2
......@@ -7,8 +7,12 @@ const FormValue = union(enum) {
77
88fn foo(id: u64) !FormValue {
99 return switch (id) {
10 2 => FormValue { .Two = true },
11 1 => FormValue { .One = {} },
10 2 => FormValue {
11 .Two = true,
12 },
13 1 => FormValue {
14 .One = {},
15 },
1216 else => return error.Whatever,
1317 };
1418}
test/cases/syntax.zig-7
......@@ -2,11 +2,9 @@
22
33const struct_trailing_comma = struct { x: i32, y: i32, };
44const struct_no_comma = struct { x: i32, y: i32 };
5const struct_no_comma_void_type = struct { x: i32, y };
65const struct_fn_no_comma = struct { fn m() void {} y: i32 };
76
87const enum_no_comma = enum { A, B };
9const enum_no_comma_type = enum { A, B: i32 };
108
119fn container_init() void {
1210 const S = struct { x: i32, y: i32 };
......@@ -36,16 +34,11 @@ fn switch_prongs(x: i32) void {
3634
3735const fn_no_comma = fn(i32, i32)void;
3836const fn_trailing_comma = fn(i32, i32,)void;
39const fn_vararg_trailing_comma = fn(i32, i32, ...,)void;
4037
4138fn fn_calls() void {
4239 fn add(x: i32, y: i32,) i32 { x + y };
4340 _ = add(1, 2);
4441 _ = add(1, 2,);
45
46 fn swallow(x: ...,) void {};
47 _ = swallow(1,2,3,);
48 _ = swallow();
4942}
5043
5144fn asm_lists() void {
test/cases/try.zig+3-5
......@@ -3,14 +3,12 @@ const assert = @import("std").debug.assert;
33test "try on error union" {
44 tryOnErrorUnionImpl();
55 comptime tryOnErrorUnionImpl();
6
76}
87
98fn tryOnErrorUnionImpl() void {
10 const x = if (returnsTen()) |val|
11 val + 1
12 else |err| switch (err) {
13 error.ItBroke, error.NoMem => 1,
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke,
11 error.NoMem => 1,
1412 error.CrappedOut => i32(2),
1513 else => unreachable,
1614 };
test/cases/type_info.zig+177-142
......@@ -4,167 +4,199 @@ const TypeInfo = @import("builtin").TypeInfo;
44const TypeId = @import("builtin").TypeId;
55
66test "type info: tag type, void info" {
7 comptime {
8 assert(@TagType(TypeInfo) == TypeId);
9 const void_info = @typeInfo(void);
10 assert(TypeId(void_info) == TypeId.Void);
11 assert(void_info.Void == {});
12 }
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assert(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assert(TypeId(void_info) == TypeId.Void);
15 assert(void_info.Void == {});
1316}
1417
1518test "type info: integer, floating point type info" {
16 comptime {
17 const u8_info = @typeInfo(u8);
18 assert(TypeId(u8_info) == TypeId.Int);
19 assert(!u8_info.Int.is_signed);
20 assert(u8_info.Int.bits == 8);
19 testIntFloat();
20 comptime testIntFloat();
21}
2122
22 const f64_info = @typeInfo(f64);
23 assert(TypeId(f64_info) == TypeId.Float);
24 assert(f64_info.Float.bits == 64);
25 }
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assert(TypeId(u8_info) == TypeId.Int);
26 assert(!u8_info.Int.is_signed);
27 assert(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assert(TypeId(f64_info) == TypeId.Float);
31 assert(f64_info.Float.bits == 64);
2632}
2733
2834test "type info: pointer type info" {
29 comptime {
30 const u32_ptr_info = @typeInfo(&u32);
31 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
32 assert(u32_ptr_info.Pointer.is_const == false);
33 assert(u32_ptr_info.Pointer.is_volatile == false);
34 assert(u32_ptr_info.Pointer.alignment == 4);
35 assert(u32_ptr_info.Pointer.child == u32);
36 }
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(&u32);
41 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assert(u32_ptr_info.Pointer.is_const == false);
43 assert(u32_ptr_info.Pointer.is_volatile == false);
44 assert(u32_ptr_info.Pointer.alignment == 4);
45 assert(u32_ptr_info.Pointer.child == u32);
3746}
3847
3948test "type info: slice type info" {
40 comptime {
41 const u32_slice_info = @typeInfo([]u32);
42 assert(TypeId(u32_slice_info) == TypeId.Slice);
43 assert(u32_slice_info.Slice.is_const == false);
44 assert(u32_slice_info.Slice.is_volatile == false);
45 assert(u32_slice_info.Slice.alignment == 4);
46 assert(u32_slice_info.Slice.child == u32);
47 }
49 testSlice();
50 comptime testSlice();
51}
52
53fn testSlice() void {
54 const u32_slice_info = @typeInfo([]u32);
55 assert(TypeId(u32_slice_info) == TypeId.Slice);
56 assert(u32_slice_info.Slice.is_const == false);
57 assert(u32_slice_info.Slice.is_volatile == false);
58 assert(u32_slice_info.Slice.alignment == 4);
59 assert(u32_slice_info.Slice.child == u32);
4860}
4961
5062test "type info: array type info" {
51 comptime {
52 const arr_info = @typeInfo([42]bool);
53 assert(TypeId(arr_info) == TypeId.Array);
54 assert(arr_info.Array.len == 42);
55 assert(arr_info.Array.child == bool);
56 }
63 testArray();
64 comptime testArray();
65}
66
67fn testArray() void {
68 const arr_info = @typeInfo([42]bool);
69 assert(TypeId(arr_info) == TypeId.Array);
70 assert(arr_info.Array.len == 42);
71 assert(arr_info.Array.child == bool);
5772}
5873
5974test "type info: nullable type info" {
60 comptime {
61 const null_info = @typeInfo(?void);
62 assert(TypeId(null_info) == TypeId.Nullable);
63 assert(null_info.Nullable.child == void);
64 }
75 testNullable();
76 comptime testNullable();
77}
78
79fn testNullable() void {
80 const null_info = @typeInfo(?void);
81 assert(TypeId(null_info) == TypeId.Nullable);
82 assert(null_info.Nullable.child == void);
6583}
6684
6785test "type info: promise info" {
68 comptime {
69 const null_promise_info = @typeInfo(promise);
70 assert(TypeId(null_promise_info) == TypeId.Promise);
71 assert(null_promise_info.Promise.child == @typeOf(undefined));
86 testPromise();
87 comptime testPromise();
88}
7289
73 const promise_info = @typeInfo(promise->usize);
74 assert(TypeId(promise_info) == TypeId.Promise);
75 assert(promise_info.Promise.child == usize);
76 }
90fn testPromise() void {
91 const null_promise_info = @typeInfo(promise);
92 assert(TypeId(null_promise_info) == TypeId.Promise);
93 assert(null_promise_info.Promise.child == @typeOf(undefined));
7794
95 const promise_info = @typeInfo(promise->usize);
96 assert(TypeId(promise_info) == TypeId.Promise);
97 assert(promise_info.Promise.child == usize);
7898}
7999
80100test "type info: error set, error union info" {
81 comptime {
82 const TestErrorSet = error {
83 First,
84 Second,
85 Third,
86 };
87
88 const error_set_info = @typeInfo(TestErrorSet);
89 assert(TypeId(error_set_info) == TypeId.ErrorSet);
90 assert(error_set_info.ErrorSet.errors.len == 3);
91 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
92 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
93
94 const error_union_info = @typeInfo(TestErrorSet!usize);
95 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
96 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
97 assert(error_union_info.ErrorUnion.payload == usize);
98 }
101 testErrorSet();
102 comptime testErrorSet();
103}
104
105fn testErrorSet() void {
106 const TestErrorSet = error {
107 First,
108 Second,
109 Third,
110 };
111
112 const error_set_info = @typeInfo(TestErrorSet);
113 assert(TypeId(error_set_info) == TypeId.ErrorSet);
114 assert(error_set_info.ErrorSet.errors.len == 3);
115 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
116 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
117
118 const error_union_info = @typeInfo(TestErrorSet!usize);
119 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
120 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
121 assert(error_union_info.ErrorUnion.payload == usize);
99122}
100123
101124test "type info: enum info" {
102 comptime {
103 const Os = @import("builtin").Os;
125 testEnum();
126 comptime testEnum();
127}
104128
105 const os_info = @typeInfo(Os);
106 assert(TypeId(os_info) == TypeId.Enum);
107 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
108 assert(os_info.Enum.fields.len == 32);
109 assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
110 assert(os_info.Enum.fields[10].value == 10);
111 assert(os_info.Enum.tag_type == u5);
112 assert(os_info.Enum.defs.len == 0);
113 }
129fn testEnum() void {
130 const Os = @import("builtin").Os;
131
132 const os_info = @typeInfo(Os);
133 assert(TypeId(os_info) == TypeId.Enum);
134 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
135 assert(os_info.Enum.fields.len == 32);
136 assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
137 assert(os_info.Enum.fields[10].value == 10);
138 assert(os_info.Enum.tag_type == u5);
139 assert(os_info.Enum.defs.len == 0);
114140}
115141
116142test "type info: union info" {
117 comptime {
118 const typeinfo_info = @typeInfo(TypeInfo);
119 assert(TypeId(typeinfo_info) == TypeId.Union);
120 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
121 assert(typeinfo_info.Union.tag_type == TypeId);
122 assert(typeinfo_info.Union.fields.len == 26);
123 assert(typeinfo_info.Union.fields[4].enum_field != null);
124 assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
125 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
126 assert(typeinfo_info.Union.defs.len == 21);
127
128 const TestNoTagUnion = union {
129 Foo: void,
130 Bar: u32,
131 };
132
133 const notag_union_info = @typeInfo(TestNoTagUnion);
134 assert(TypeId(notag_union_info) == TypeId.Union);
135 assert(notag_union_info.Union.tag_type == @typeOf(undefined));
136 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
137 assert(notag_union_info.Union.fields.len == 2);
138 assert(notag_union_info.Union.fields[0].enum_field == null);
139 assert(notag_union_info.Union.fields[1].field_type == u32);
140
141 const TestExternUnion = extern union {
142 foo: &c_void,
143 };
144
145 const extern_union_info = @typeInfo(TestExternUnion);
146 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
147 assert(extern_union_info.Union.tag_type == @typeOf(undefined));
148 assert(extern_union_info.Union.fields[0].enum_field == null);
149 assert(extern_union_info.Union.fields[0].field_type == &c_void);
150 }
143 testUnion();
144 comptime testUnion();
145}
146
147fn testUnion() void {
148 const typeinfo_info = @typeInfo(TypeInfo);
149 assert(TypeId(typeinfo_info) == TypeId.Union);
150 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
151 assert(typeinfo_info.Union.tag_type == TypeId);
152 assert(typeinfo_info.Union.fields.len == 26);
153 assert(typeinfo_info.Union.fields[4].enum_field != null);
154 assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
155 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
156 assert(typeinfo_info.Union.defs.len == 21);
157
158 const TestNoTagUnion = union {
159 Foo: void,
160 Bar: u32,
161 };
162
163 const notag_union_info = @typeInfo(TestNoTagUnion);
164 assert(TypeId(notag_union_info) == TypeId.Union);
165 assert(notag_union_info.Union.tag_type == @typeOf(undefined));
166 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
167 assert(notag_union_info.Union.fields.len == 2);
168 assert(notag_union_info.Union.fields[0].enum_field == null);
169 assert(notag_union_info.Union.fields[1].field_type == u32);
170
171 const TestExternUnion = extern union {
172 foo: &c_void,
173 };
174
175 const extern_union_info = @typeInfo(TestExternUnion);
176 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
177 assert(extern_union_info.Union.tag_type == @typeOf(undefined));
178 assert(extern_union_info.Union.fields[0].enum_field == null);
179 assert(extern_union_info.Union.fields[0].field_type == &c_void);
151180}
152181
153182test "type info: struct info" {
154 comptime {
155 const struct_info = @typeInfo(TestStruct);
156 assert(TypeId(struct_info) == TypeId.Struct);
157 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
158 assert(struct_info.Struct.fields.len == 3);
159 assert(struct_info.Struct.fields[1].offset == null);
160 assert(struct_info.Struct.fields[2].field_type == &TestStruct);
161 assert(struct_info.Struct.defs.len == 2);
162 assert(struct_info.Struct.defs[0].is_pub);
163 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
164 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
165 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
166 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
167 }
183 testStruct();
184 comptime testStruct();
185}
186
187fn testStruct() void {
188 const struct_info = @typeInfo(TestStruct);
189 assert(TypeId(struct_info) == TypeId.Struct);
190 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
191 assert(struct_info.Struct.fields.len == 3);
192 assert(struct_info.Struct.fields[1].offset == null);
193 assert(struct_info.Struct.fields[2].field_type == &TestStruct);
194 assert(struct_info.Struct.defs.len == 2);
195 assert(struct_info.Struct.defs[0].is_pub);
196 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
197 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
198 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
199 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
168200}
169201
170202const TestStruct = packed struct {
......@@ -178,21 +210,24 @@ const TestStruct = packed struct {
178210};
179211
180212test "type info: function type info" {
181 comptime {
182 const fn_info = @typeInfo(@typeOf(foo));
183 assert(TypeId(fn_info) == TypeId.Fn);
184 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
185 assert(fn_info.Fn.is_generic);
186 assert(fn_info.Fn.args.len == 2);
187 assert(fn_info.Fn.is_var_args);
188 assert(fn_info.Fn.return_type == @typeOf(undefined));
189 assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
190
191 const test_instance: TestStruct = undefined;
192 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
193 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
194 assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
195 }
213 testFunction();
214 comptime testFunction();
215}
216
217fn testFunction() void {
218 const fn_info = @typeInfo(@typeOf(foo));
219 assert(TypeId(fn_info) == TypeId.Fn);
220 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
221 assert(fn_info.Fn.is_generic);
222 assert(fn_info.Fn.args.len == 2);
223 assert(fn_info.Fn.is_var_args);
224 assert(fn_info.Fn.return_type == @typeOf(undefined));
225 assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
226
227 const test_instance: TestStruct = undefined;
228 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
229 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
230 assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
196231}
197232
198233fn foo(comptime a: usize, b: bool, args: ...) usize {
test/cases/undefined.zig+2-2
......@@ -63,6 +63,6 @@ test "assign undefined to struct with method" {
6363}
6464
6565test "type name of undefined" {
66 const x = undefined;
67 assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
66 const x = undefined;
67 assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
6868}
test/cases/union.zig+50-36
......@@ -10,38 +10,41 @@ const Agg = struct {
1010 val2: Value,
1111};
1212
13const v1 = Value { .Int = 1234 };
14const v2 = Value { .Array = []u8{3} ** 9 };
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
1515
16const err = (error!Agg)(Agg {
16const err = (error!Agg)(Agg{
1717 .val1 = v1,
1818 .val2 = v2,
1919});
2020
21const array = []Value { v1, v2, v1, v2};
22
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
2327
2428test "unions embedded in aggregate types" {
2529 switch (array[1]) {
2630 Value.Array => |arr| assert(arr[4] == 3),
2731 else => unreachable,
2832 }
29 switch((err catch unreachable).val1) {
33 switch ((err catch unreachable).val1) {
3034 Value.Int => |x| assert(x == 1234),
3135 else => unreachable,
3236 }
3337}
3438
35
3639const Foo = union {
3740 float: f64,
3841 int: i32,
3942};
4043
4144test "basic unions" {
42 var foo = Foo { .int = 1 };
45 var foo = Foo{ .int = 1 };
4346 assert(foo.int == 1);
44 foo = Foo {.float = 12.34};
47 foo = Foo{ .float = 12.34 };
4548 assert(foo.float == 12.34);
4649}
4750
......@@ -66,11 +69,11 @@ test "init union with runtime value" {
6669}
6770
6871fn setFloat(foo: &Foo, x: f64) void {
69 *foo = Foo { .float = x };
72 foo.* = Foo{ .float = x };
7073}
7174
7275fn setInt(foo: &Foo, x: i32) void {
73 *foo = Foo { .int = x };
76 foo.* = Foo{ .int = x };
7477}
7578
7679const FooExtern = extern union {
......@@ -79,13 +82,12 @@ const FooExtern = extern union {
7982};
8083
8184test "basic extern unions" {
82 var foo = FooExtern { .int = 1 };
85 var foo = FooExtern{ .int = 1 };
8386 assert(foo.int == 1);
8487 foo.float = 12.34;
8588 assert(foo.float == 12.34);
8689}
8790
88
8991const Letter = enum {
9092 A,
9193 B,
......@@ -103,12 +105,12 @@ test "union with specified enum tag" {
103105}
104106
105107fn doTest() void {
106 assert(bar(Payload {.A = 1234}) == -10);
108 assert(bar(Payload{ .A = 1234 }) == -10);
107109}
108110
109111fn bar(value: &const Payload) i32 {
110 assert(Letter(*value) == Letter.A);
111 return switch (*value) {
112 assert(Letter(value.*) == Letter.A);
113 return switch (value.*) {
112114 Payload.A => |x| return x - 1244,
113115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
114116 Payload.C => |x| if (x) i32(30) else 31,
......@@ -141,13 +143,13 @@ const MultipleChoice2 = union(enum(u32)) {
141143
142144test "union(enum(u32)) with specified and unspecified tag values" {
143145 comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
144 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 {.C = 123});
145 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} );
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
146148}
147149
148150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void {
149 assert(u32(@TagType(MultipleChoice2)(*x)) == 60);
150 assert(1123 == switch (*x) {
151 assert(u32(@TagType(MultipleChoice2)(x.*)) == 60);
152 assert(1123 == switch (x.*) {
151153 MultipleChoice2.A => 1,
152154 MultipleChoice2.B => 2,
153155 MultipleChoice2.C => |v| i32(1000) + v,
......@@ -160,10 +162,9 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void
160162 });
161163}
162164
163
164165const ExternPtrOrInt = extern union {
165166 ptr: &u8,
166 int: u64
167 int: u64,
167168};
168169test "extern union size" {
169170 comptime assert(@sizeOf(ExternPtrOrInt) == 8);
......@@ -171,7 +172,7 @@ test "extern union size" {
171172
172173const PackedPtrOrInt = packed union {
173174 ptr: &u8,
174 int: u64
175 int: u64,
175176};
176177test "extern union size" {
177178 comptime assert(@sizeOf(PackedPtrOrInt) == 8);
......@@ -184,8 +185,16 @@ test "union with only 1 field which is void should be zero bits" {
184185 comptime assert(@sizeOf(ZeroBits) == 0);
185186}
186187
187const TheTag = enum {A, B, C};
188const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 };
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
189198test "union field access gives the enum values" {
190199 assert(TheUnion.A == TheTag.A);
191200 assert(TheUnion.B == TheTag.B);
......@@ -193,20 +202,28 @@ test "union field access gives the enum values" {
193202}
194203
195204test "cast union to tag type of union" {
196 testCastUnionToTagType(TheUnion {.B = 1234});
197 comptime testCastUnionToTagType(TheUnion {.B = 1234});
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
198207}
199208
200209fn testCastUnionToTagType(x: &const TheUnion) void {
201 assert(TheTag(*x) == TheTag.B);
210 assert(TheTag(x.*) == TheTag.B);
202211}
203212
204213test "cast tag type of union to union" {
205214 var x: Value2 = Letter2.B;
206215 assert(Letter2(x) == Letter2.B);
207216}
208const Letter2 = enum { A, B, C };
209const Value2 = union(Letter2) { A: i32, B, C, };
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
210227
211228test "implicit cast union to its tag type" {
212229 var x: Value2 = Letter2.B;
......@@ -227,19 +244,16 @@ const TheUnion2 = union(enum) {
227244};
228245
229246fn assertIsTheUnion2Item1(value: &const TheUnion2) void {
230 assert(*value == TheUnion2.Item1);
247 assert(value.* == TheUnion2.Item1);
231248}
232249
233
234250pub const PackThis = union(enum) {
235251 Invalid: bool,
236252 StringLiteral: u2,
237253};
238254
239255test "constant packed union" {
240 testConstPackedUnion([]PackThis {
241 PackThis { .StringLiteral = 1 },
242 });
256 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
243257}
244258
245259fn testConstPackedUnion(expected_tokens: []const PackThis) void {
......@@ -252,7 +266,7 @@ test "switch on union with only 1 field" {
252266 switch (r) {
253267 PartialInst.Compiled => {
254268 var z: PartialInstWithPayload = undefined;
255 z = PartialInstWithPayload { .Compiled = 1234 };
269 z = PartialInstWithPayload{ .Compiled = 1234 };
256270 switch (z) {
257271 PartialInstWithPayload.Compiled => |x| {
258272 assert(x == 1234);
test/cases/var_args.zig+16-9
......@@ -2,9 +2,12 @@ const assert = @import("std").debug.assert;
22
33fn add(args: ...) i32 {
44 var sum = i32(0);
5 {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) {
6 sum += args[i];
7 }}
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
811 return sum;
912}
1013
......@@ -55,18 +58,23 @@ fn extraFn(extra: u32, args: ...) usize {
5558 return args.len;
5659}
5760
61const foos = []fn(...) bool {
62 foo1,
63 foo2,
64};
5865
59const foos = []fn(...) bool { foo1, foo2 };
60
61fn foo1(args: ...) bool { return true; }
62fn foo2(args: ...) bool { return false; }
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
6372
6473test "array of var args functions" {
6574 assert(foos[0]());
6675 assert(!foos[1]());
6776}
6877
69
7078test "pass array and slice of same array to var args should have same pointers" {
7179 const array = "hi";
7280 const slice: []const u8 = array;
......@@ -79,7 +87,6 @@ fn assertSlicePtrsEql(args: ...) void {
7987 assert(s1.ptr == s2.ptr);
8088}
8189
82
8390test "pass zero length array to var args param" {
8491 doNothingWithFirstArg("");
8592}
test/cases/while.zig+41-24
......@@ -1,7 +1,7 @@
11const assert = @import("std").debug.assert;
22
33test "while loop" {
4 var i : i32 = 0;
4 var i: i32 = 0;
55 while (i < 4) {
66 i += 1;
77 }
......@@ -35,7 +35,7 @@ test "continue and break" {
3535}
3636var continue_and_break_counter: i32 = 0;
3737fn runContinueAndBreakTest() void {
38 var i : i32 = 0;
38 var i: i32 = 0;
3939 while (true) {
4040 continue_and_break_counter += 2;
4141 i += 1;
......@@ -58,10 +58,13 @@ fn returnWithImplicitCastFromWhileLoopTest() error!void {
5858
5959test "while with continue expression" {
6060 var sum: i32 = 0;
61 {var i: i32 = 0; while (i < 10) : (i += 1) {
62 if (i == 5) continue;
63 sum += i;
64 }}
61 {
62 var i: i32 = 0;
63 while (i < 10) : (i += 1) {
64 if (i == 5) continue;
65 sum += i;
66 }
67 }
6568 assert(sum == 40);
6669}
6770
......@@ -117,17 +120,13 @@ test "while with error union condition" {
117120
118121var numbers_left: i32 = undefined;
119122fn getNumberOrErr() error!i32 {
120 return if (numbers_left == 0)
121 error.OutOfNumbers
122 else x: {
123 return if (numbers_left == 0) error.OutOfNumbers else x: {
123124 numbers_left -= 1;
124125 break :x numbers_left;
125126 };
126127}
127128fn getNumberOrNull() ?i32 {
128 return if (numbers_left == 0)
129 null
130 else x: {
129 return if (numbers_left == 0) null else x: {
131130 numbers_left -= 1;
132131 break :x numbers_left;
133132 };
......@@ -136,42 +135,48 @@ fn getNumberOrNull() ?i32 {
136135test "while on nullable with else result follow else prong" {
137136 const result = while (returnNull()) |value| {
138137 break value;
139 } else i32(2);
138 } else
139 i32(2);
140140 assert(result == 2);
141141}
142142
143143test "while on nullable with else result follow break prong" {
144144 const result = while (returnMaybe(10)) |value| {
145145 break value;
146 } else i32(2);
146 } else
147 i32(2);
147148 assert(result == 10);
148149}
149150
150151test "while on error union with else result follow else prong" {
151152 const result = while (returnError()) |value| {
152153 break value;
153 } else |err| i32(2);
154 } else|err|
155 i32(2);
154156 assert(result == 2);
155157}
156158
157159test "while on error union with else result follow break prong" {
158160 const result = while (returnSuccess(10)) |value| {
159161 break value;
160 } else |err| i32(2);
162 } else|err|
163 i32(2);
161164 assert(result == 10);
162165}
163166
164167test "while on bool with else result follow else prong" {
165168 const result = while (returnFalse()) {
166169 break i32(10);
167 } else i32(2);
170 } else
171 i32(2);
168172 assert(result == 2);
169173}
170174
171175test "while on bool with else result follow break prong" {
172176 const result = while (returnTrue()) {
173177 break i32(10);
174 } else i32(2);
178 } else
179 i32(2);
175180 assert(result == 10);
176181}
177182
......@@ -202,9 +207,21 @@ fn testContinueOuter() void {
202207 }
203208}
204209
205fn returnNull() ?i32 { return null; }
206fn returnMaybe(x: i32) ?i32 { return x; }
207fn returnError() error!i32 { return error.YouWantedAnError; }
208fn returnSuccess(x: i32) error!i32 { return x; }
209fn returnFalse() bool { return false; }
210fn returnTrue() bool { return true; }
210fn returnNull() ?i32 {
211 return null;
212}
213fn returnMaybe(x: i32) ?i32 {
214 return x;
215}
216fn returnError() error!i32 {
217 return error.YouWantedAnError;
218}
219fn returnSuccess(x: i32) error!i32 {
220 return x;
221}
222fn returnFalse() bool {
223 return false;
224}
225fn returnTrue() bool {
226 return true;
227}
test/compare_output.zig+4-4
......@@ -131,7 +131,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
131131 \\const is_windows = builtin.os == builtin.Os.windows;
132132 \\const c = @cImport({
133133 \\ if (is_windows) {
134 \\ // See https://github.com/zig-lang/zig/issues/515
134 \\ // See https://github.com/ziglang/zig/issues/515
135135 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1");
136136 \\ @cInclude("io.h");
137137 \\ @cInclude("fcntl.h");
......@@ -287,9 +287,9 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
287287 \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int {
288288 \\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable);
289289 \\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable);
290 \\ if (*a_int < *b_int) {
290 \\ if (a_int.* < b_int.*) {
291291 \\ return -1;
292 \\ } else if (*a_int > *b_int) {
292 \\ } else if (a_int.* > b_int.*) {
293293 \\ return 1;
294294 \\ } else {
295295 \\ return 0;
......@@ -316,7 +316,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
316316 \\const is_windows = builtin.os == builtin.Os.windows;
317317 \\const c = @cImport({
318318 \\ if (is_windows) {
319 \\ // See https://github.com/zig-lang/zig/issues/515
319 \\ // See https://github.com/ziglang/zig/issues/515
320320 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1");
321321 \\ @cInclude("io.h");
322322 \\ @cInclude("fcntl.h");
test/compile_errors.zig+15-15
......@@ -4,7 +4,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
44 cases.add("invalid deref on switch target",
55 \\comptime {
66 \\ var tile = Tile.Empty;
7 \\ switch (*tile) {
7 \\ switch (tile.*) {
88 \\ Tile.Empty => {},
99 \\ Tile.Filled => {},
1010 \\ }
......@@ -14,7 +14,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
1414 \\ Filled,
1515 \\};
1616 ,
17 ".tmp_source.zig:3:13: error: invalid deref on switch target");
17 ".tmp_source.zig:3:17: error: invalid deref on switch target");
1818
1919 cases.add("invalid field access in comptime",
2020 \\comptime { var x = doesnt_exist.whatever; }
......@@ -1408,14 +1408,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
14081408 \\ Two: i32,
14091409 \\};
14101410 \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool {
1411 \\ return *a == *b;
1411 \\ return a.* == b.*;
14121412 \\}
14131413 \\
14141414 \\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); }
14151415 \\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); }
14161416 ,
14171417 ".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'",
1418 ".tmp_source.zig:9:15: error: operator not allowed for type 'EnumWithData'");
1418 ".tmp_source.zig:9:16: error: operator not allowed for type 'EnumWithData'");
14191419
14201420 cases.add("non-const switch number literal",
14211421 \\export fn foo() void {
......@@ -1513,7 +1513,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
15131513 \\var bytes: [ext()]u8 = undefined;
15141514 \\export fn f() void {
15151515 \\ for (bytes) |*b, i| {
1516 \\ *b = u8(i);
1516 \\ b.* = u8(i);
15171517 \\ }
15181518 \\}
15191519 , ".tmp_source.zig:2:13: error: unable to evaluate constant expression");
......@@ -1819,7 +1819,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
18191819 \\}
18201820 \\
18211821 \\fn bar(x: &const u3) u3 {
1822 \\ return *x;
1822 \\ return x.*;
18231823 \\}
18241824 \\
18251825 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
......@@ -1903,12 +1903,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
19031903 \\var s_buffer: [10]u8 = undefined;
19041904 \\pub fn pass(in: []u8) []u8 {
19051905 \\ var out = &s_buffer;
1906 \\ *out[0] = in[0];
1907 \\ return (*out)[0..1];
1906 \\ out[0].* = in[0];
1907 \\ return out.*[0..1];
19081908 \\}
19091909 \\
19101910 \\export fn entry() usize { return @sizeOf(@typeOf(pass)); }
1911 , ".tmp_source.zig:4:5: error: attempt to dereference non pointer type '[10]u8'");
1911 , ".tmp_source.zig:4:11: error: attempt to dereference non pointer type '[10]u8'");
19121912
19131913 cases.add("pass const ptr to mutable ptr fn",
19141914 \\fn foo() bool {
......@@ -2434,7 +2434,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
24342434 \\}
24352435 \\
24362436 \\fn bar(x: &u32) void {
2437 \\ *x += 1;
2437 \\ x.* += 1;
24382438 \\}
24392439 ,
24402440 ".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'");
......@@ -2461,7 +2461,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
24612461 \\export fn entry() u32 {
24622462 \\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04};
24632463 \\ const ptr = @ptrCast(&u32, &bytes[0]);
2464 \\ return *ptr;
2464 \\ return ptr.*;
24652465 \\}
24662466 ,
24672467 ".tmp_source.zig:3:17: error: cast increases pointer alignment",
......@@ -2540,14 +2540,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
25402540 \\
25412541 \\export fn entry(opaque: &Opaque) void {
25422542 \\ var m2 = &2;
2543 \\ const y: u32 = *m2;
2543 \\ const y: u32 = m2.*;
25442544 \\
25452545 \\ var a = undefined;
25462546 \\ var b = 1;
25472547 \\ var c = 1.0;
25482548 \\ var d = this;
25492549 \\ var e = null;
2550 \\ var f = *opaque;
2550 \\ var f = opaque.*;
25512551 \\ var g = i32;
25522552 \\ var h = @import("std");
25532553 \\ var i = (Foo {}).bar;
......@@ -3136,13 +3136,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
31363136 \\ foo(a);
31373137 \\}
31383138 \\fn foo(a: &const Payload) void {
3139 \\ switch (*a) {
3139 \\ switch (a.*) {
31403140 \\ Payload.A => {},
31413141 \\ else => unreachable,
31423142 \\ }
31433143 \\}
31443144 ,
3145 ".tmp_source.zig:11:13: error: switch on union which has no attached enum",
3145 ".tmp_source.zig:11:14: error: switch on union which has no attached enum",
31463146 ".tmp_source.zig:1:17: note: consider 'union(enum)' here");
31473147
31483148 cases.add("enum in field count range but not matching tag",
test/standalone/brace_expansion/main.zig+23-20
......@@ -16,7 +16,7 @@ const Token = union(enum) {
1616
1717var global_allocator: &mem.Allocator = undefined;
1818
19fn tokenize(input:[] const u8) !ArrayList(Token) {
19fn tokenize(input: []const u8) !ArrayList(Token) {
2020 const State = enum {
2121 Start,
2222 Word,
......@@ -29,7 +29,8 @@ fn tokenize(input:[] const u8) !ArrayList(Token) {
2929 for (input) |b, i| {
3030 switch (state) {
3131 State.Start => switch (b) {
32 'a'...'z', 'A'...'Z' => {
32 'a' ... 'z',
33 'A' ... 'Z' => {
3334 state = State.Word;
3435 tok_begin = i;
3536 },
......@@ -39,9 +40,12 @@ fn tokenize(input:[] const u8) !ArrayList(Token) {
3940 else => return error.InvalidInput,
4041 },
4142 State.Word => switch (b) {
42 'a'...'z', 'A'...'Z' => {},
43 '{', '}', ',' => {
44 try token_list.append(Token { .Word = input[tok_begin..i] });
43 'a' ... 'z',
44 'A' ... 'Z' => {},
45 '{',
46 '}',
47 ',' => {
48 try token_list.append(Token{ .Word = input[tok_begin..i] });
4549 switch (b) {
4650 '{' => try token_list.append(Token.OpenBrace),
4751 '}' => try token_list.append(Token.CloseBrace),
......@@ -56,7 +60,7 @@ fn tokenize(input:[] const u8) !ArrayList(Token) {
5660 }
5761 switch (state) {
5862 State.Start => {},
59 State.Word => try token_list.append(Token {.Word = input[tok_begin..] }),
63 State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
6064 }
6165 try token_list.append(Token.Eof);
6266 return token_list;
......@@ -68,24 +72,24 @@ const Node = union(enum) {
6872 Combine: []Node,
6973};
7074
71const ParseError = error {
75const ParseError = error{
7276 InvalidInput,
7377 OutOfMemory,
7478};
7579
7680fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node {
77 const first_token = tokens.items[*token_index];
78 *token_index += 1;
81 const first_token = tokens.items[token_index.*];
82 token_index.* += 1;
7983
8084 const result_node = switch (first_token) {
81 Token.Word => |word| Node { .Scalar = word },
85 Token.Word => |word| Node{ .Scalar = word },
8286 Token.OpenBrace => blk: {
8387 var list = ArrayList(Node).init(global_allocator);
8488 while (true) {
8589 try list.append(try parse(tokens, token_index));
8690
87 const token = tokens.items[*token_index];
88 *token_index += 1;
91 const token = tokens.items[token_index.*];
92 token_index.* += 1;
8993
9094 switch (token) {
9195 Token.CloseBrace => break,
......@@ -93,17 +97,18 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node {
9397 else => return error.InvalidInput,
9498 }
9599 }
96 break :blk Node { .List = list };
100 break :blk Node{ .List = list };
97101 },
98102 else => return error.InvalidInput,
99103 };
100104
101 switch (tokens.items[*token_index]) {
102 Token.Word, Token.OpenBrace => {
105 switch (tokens.items[token_index.*]) {
106 Token.Word,
107 Token.OpenBrace => {
103108 const pair = try global_allocator.alloc(Node, 2);
104109 pair[0] = result_node;
105110 pair[1] = try parse(tokens, token_index);
106 return Node { .Combine = pair };
111 return Node{ .Combine = pair };
107112 },
108113 else => return result_node,
109114 }
......@@ -137,13 +142,11 @@ fn expandString(input: []const u8, output: &Buffer) !void {
137142 }
138143}
139144
140const ExpandNodeError = error {
141 OutOfMemory,
142};
145const ExpandNodeError = error{OutOfMemory};
143146
144147fn expandNode(node: &const Node, output: &ArrayList(Buffer)) ExpandNodeError!void {
145148 assert(output.len == 0);
146 switch (*node) {
149 switch (node.*) {
147150 Node.Scalar => |scalar| {
148151 try output.append(try Buffer.init(global_allocator, scalar));
149152 },
test/tests.zig+90-100
......@@ -27,18 +27,18 @@ const TestTarget = struct {
2727 environ: builtin.Environ,
2828};
2929
30const test_targets = []TestTarget {
31 TestTarget {
30const test_targets = []TestTarget{
31 TestTarget{
3232 .os = builtin.Os.linux,
3333 .arch = builtin.Arch.x86_64,
3434 .environ = builtin.Environ.gnu,
3535 },
36 TestTarget {
36 TestTarget{
3737 .os = builtin.Os.macosx,
3838 .arch = builtin.Arch.x86_64,
3939 .environ = builtin.Environ.unknown,
4040 },
41 TestTarget {
41 TestTarget{
4242 .os = builtin.Os.windows,
4343 .arch = builtin.Arch.x86_64,
4444 .environ = builtin.Environ.msvc,
......@@ -49,7 +49,7 @@ const max_stdout_size = 1 * 1024 * 1024; // 1 MB
4949
5050pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
5151 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
52 *cases = CompareOutputContext {
52 cases.* = CompareOutputContext{
5353 .b = b,
5454 .step = b.step("test-compare-output", "Run the compare output tests"),
5555 .test_index = 0,
......@@ -63,7 +63,7 @@ pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build
6363
6464pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
6565 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
66 *cases = CompareOutputContext {
66 cases.* = CompareOutputContext{
6767 .b = b,
6868 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
6969 .test_index = 0,
......@@ -77,7 +77,7 @@ pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build
7777
7878pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
7979 const cases = b.allocator.create(CompileErrorContext) catch unreachable;
80 *cases = CompileErrorContext {
80 cases.* = CompileErrorContext{
8181 .b = b,
8282 .step = b.step("test-compile-errors", "Run the compile error tests"),
8383 .test_index = 0,
......@@ -91,7 +91,7 @@ pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.
9191
9292pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
9393 const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
94 *cases = BuildExamplesContext {
94 cases.* = BuildExamplesContext{
9595 .b = b,
9696 .step = b.step("test-build-examples", "Build the examples"),
9797 .test_index = 0,
......@@ -105,7 +105,7 @@ pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.
105105
106106pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
107107 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
108 *cases = CompareOutputContext {
108 cases.* = CompareOutputContext{
109109 .b = b,
110110 .step = b.step("test-asm-link", "Run the assemble and link tests"),
111111 .test_index = 0,
......@@ -119,7 +119,7 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &bui
119119
120120pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
121121 const cases = b.allocator.create(TranslateCContext) catch unreachable;
122 *cases = TranslateCContext {
122 cases.* = TranslateCContext{
123123 .b = b,
124124 .step = b.step("test-translate-c", "Run the C transation tests"),
125125 .test_index = 0,
......@@ -133,7 +133,7 @@ pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.St
133133
134134pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
135135 const cases = b.allocator.create(GenHContext) catch unreachable;
136 *cases = GenHContext {
136 cases.* = GenHContext{
137137 .b = b,
138138 .step = b.step("test-gen-h", "Run the C header file generation tests"),
139139 .test_index = 0,
......@@ -145,22 +145,26 @@ pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
145145 return cases.step;
146146}
147147
148
149pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8,
150 name:[] const u8, desc: []const u8, with_lldb: bool) &build.Step
151{
148pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8, name: []const u8, desc: []const u8, with_lldb: bool) &build.Step {
152149 const step = b.step(b.fmt("test-{}", name), desc);
153150 for (test_targets) |test_target| {
154151 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
155 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
156 for ([]bool{false, true}) |link_libc| {
152 for ([]Mode{
153 Mode.Debug,
154 Mode.ReleaseSafe,
155 Mode.ReleaseFast,
156 Mode.ReleaseSmall,
157 }) |mode| {
158 for ([]bool{
159 false,
160 true,
161 }) |link_libc| {
157162 if (link_libc and !is_native) {
158163 // don't assume we have a cross-compiling libc set up
159164 continue;
160165 }
161166 const these_tests = b.addTest(root_src);
162 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os),
163 @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
167 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
164168 these_tests.setFilter(test_filter);
165169 these_tests.setBuildMode(mode);
166170 if (!is_native) {
......@@ -171,7 +175,15 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
171175 }
172176 if (with_lldb) {
173177 these_tests.setExecCmd([]?[]const u8{
174 "lldb", null, "-o", "run", "-o", "bt", "-o", "exit"});
178 "lldb",
179 null,
180 "-o",
181 "run",
182 "-o",
183 "bt",
184 "-o",
185 "exit",
186 });
175187 }
176188 step.dependOn(&these_tests.step);
177189 }
......@@ -206,7 +218,7 @@ pub const CompareOutputContext = struct {
206218 };
207219
208220 pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
209 self.sources.append(SourceFile {
221 self.sources.append(SourceFile{
210222 .filename = filename,
211223 .source = source,
212224 }) catch unreachable;
......@@ -226,13 +238,10 @@ pub const CompareOutputContext = struct {
226238 test_index: usize,
227239 cli_args: []const []const u8,
228240
229 pub fn create(context: &CompareOutputContext, exe_path: []const u8,
230 name: []const u8, expected_output: []const u8,
231 cli_args: []const []const u8) &RunCompareOutputStep
232 {
241 pub fn create(context: &CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) &RunCompareOutputStep {
233242 const allocator = context.b.allocator;
234243 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
235 *ptr = RunCompareOutputStep {
244 ptr.* = RunCompareOutputStep{
236245 .context = context,
237246 .exe_path = exe_path,
238247 .name = name,
......@@ -258,7 +267,7 @@ pub const CompareOutputContext = struct {
258267 args.append(arg) catch unreachable;
259268 }
260269
261 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
270 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
262271
263272 const child = os.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable;
264273 defer child.deinit();
......@@ -295,7 +304,6 @@ pub const CompareOutputContext = struct {
295304 },
296305 }
297306
298
299307 if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) {
300308 warn(
301309 \\
......@@ -318,12 +326,10 @@ pub const CompareOutputContext = struct {
318326 name: []const u8,
319327 test_index: usize,
320328
321 pub fn create(context: &CompareOutputContext, exe_path: []const u8,
322 name: []const u8) &RuntimeSafetyRunStep
323 {
329 pub fn create(context: &CompareOutputContext, exe_path: []const u8, name: []const u8) &RuntimeSafetyRunStep {
324330 const allocator = context.b.allocator;
325331 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
326 *ptr = RuntimeSafetyRunStep {
332 ptr.* = RuntimeSafetyRunStep{
327333 .context = context,
328334 .exe_path = exe_path,
329335 .name = name,
......@@ -340,7 +346,7 @@ pub const CompareOutputContext = struct {
340346
341347 const full_exe_path = b.pathFromRoot(self.exe_path);
342348
343 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
349 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
344350
345351 const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable;
346352 defer child.deinit();
......@@ -358,19 +364,16 @@ pub const CompareOutputContext = struct {
358364 switch (term) {
359365 Term.Exited => |code| {
360366 if (code != expected_exit_code) {
361 warn("\nProgram expected to exit with code {} " ++
362 "but exited with code {}\n", expected_exit_code, code);
367 warn("\nProgram expected to exit with code {} " ++ "but exited with code {}\n", expected_exit_code, code);
363368 return error.TestFailed;
364369 }
365370 },
366371 Term.Signal => |sig| {
367 warn("\nProgram expected to exit with code {} " ++
368 "but instead signaled {}\n", expected_exit_code, sig);
372 warn("\nProgram expected to exit with code {} " ++ "but instead signaled {}\n", expected_exit_code, sig);
369373 return error.TestFailed;
370374 },
371375 else => {
372 warn("\nProgram expected to exit with code {}" ++
373 " but exited in an unexpected way\n", expected_exit_code);
376 warn("\nProgram expected to exit with code {}" ++ " but exited in an unexpected way\n", expected_exit_code);
374377 return error.TestFailed;
375378 },
376379 }
......@@ -379,10 +382,8 @@ pub const CompareOutputContext = struct {
379382 }
380383 };
381384
382 pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8,
383 expected_output: []const u8, special: Special) TestCase
384 {
385 var tc = TestCase {
385 pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8, special: Special) TestCase {
386 var tc = TestCase{
386387 .name = name,
387388 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
388389 .expected_output = expected_output,
......@@ -395,9 +396,7 @@ pub const CompareOutputContext = struct {
395396 return tc;
396397 }
397398
398 pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8,
399 expected_output: []const u8) TestCase
400 {
399 pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) TestCase {
401400 return createExtra(self, name, source, expected_output, Special.None);
402401 }
403402
......@@ -431,8 +430,7 @@ pub const CompareOutputContext = struct {
431430 Special.Asm => {
432431 const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable;
433432 if (self.test_filter) |filter| {
434 if (mem.indexOf(u8, annotated_case_name, filter) == null)
435 return;
433 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
436434 }
437435
438436 const exe = b.addExecutable("test", null);
......@@ -444,19 +442,21 @@ pub const CompareOutputContext = struct {
444442 exe.step.dependOn(&write_src.step);
445443 }
446444
447 const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name,
448 case.expected_output, case.cli_args);
445 const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args);
449446 run_and_cmp_output.step.dependOn(&exe.step);
450447
451448 self.step.dependOn(&run_and_cmp_output.step);
452449 },
453450 Special.None => {
454 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
455 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})",
456 "compare-output", case.name, @tagName(mode)) catch unreachable;
451 for ([]Mode{
452 Mode.Debug,
453 Mode.ReleaseSafe,
454 Mode.ReleaseFast,
455 Mode.ReleaseSmall,
456 }) |mode| {
457 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-output", case.name, @tagName(mode)) catch unreachable;
457458 if (self.test_filter) |filter| {
458 if (mem.indexOf(u8, annotated_case_name, filter) == null)
459 continue;
459 if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
460460 }
461461
462462 const exe = b.addExecutable("test", root_src);
......@@ -471,8 +471,7 @@ pub const CompareOutputContext = struct {
471471 exe.step.dependOn(&write_src.step);
472472 }
473473
474 const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(),
475 annotated_case_name, case.expected_output, case.cli_args);
474 const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args);
476475 run_and_cmp_output.step.dependOn(&exe.step);
477476
478477 self.step.dependOn(&run_and_cmp_output.step);
......@@ -481,8 +480,7 @@ pub const CompareOutputContext = struct {
481480 Special.RuntimeSafety => {
482481 const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable;
483482 if (self.test_filter) |filter| {
484 if (mem.indexOf(u8, annotated_case_name, filter) == null)
485 return;
483 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
486484 }
487485
488486 const exe = b.addExecutable("test", root_src);
......@@ -524,7 +522,7 @@ pub const CompileErrorContext = struct {
524522 };
525523
526524 pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
527 self.sources.append(SourceFile {
525 self.sources.append(SourceFile{
528526 .filename = filename,
529527 .source = source,
530528 }) catch unreachable;
......@@ -543,12 +541,10 @@ pub const CompileErrorContext = struct {
543541 case: &const TestCase,
544542 build_mode: Mode,
545543
546 pub fn create(context: &CompileErrorContext, name: []const u8,
547 case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep
548 {
544 pub fn create(context: &CompileErrorContext, name: []const u8, case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep {
549545 const allocator = context.b.allocator;
550546 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
551 *ptr = CompileCmpOutputStep {
547 ptr.* = CompileCmpOutputStep{
552548 .step = build.Step.init("CompileCmpOutput", allocator, make),
553549 .context = context,
554550 .name = name,
......@@ -586,7 +582,7 @@ pub const CompileErrorContext = struct {
586582 Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
587583 }
588584
589 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
585 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
590586
591587 if (b.verbose) {
592588 printInvocation(zig_args.toSliceConst());
......@@ -626,7 +622,6 @@ pub const CompileErrorContext = struct {
626622 },
627623 }
628624
629
630625 const stdout = stdout_buf.toSliceConst();
631626 const stderr = stderr_buf.toSliceConst();
632627
......@@ -666,11 +661,9 @@ pub const CompileErrorContext = struct {
666661 warn("\n");
667662 }
668663
669 pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8,
670 expected_lines: ...) &TestCase
671 {
664 pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) &TestCase {
672665 const tc = self.b.allocator.create(TestCase) catch unreachable;
673 *tc = TestCase {
666 tc.* = TestCase{
674667 .name = name,
675668 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
676669 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
......@@ -705,12 +698,13 @@ pub const CompileErrorContext = struct {
705698 pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void {
706699 const b = self.b;
707700
708 for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
709 const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
710 case.name, @tagName(mode)) catch unreachable;
701 for ([]Mode{
702 Mode.Debug,
703 Mode.ReleaseFast,
704 }) |mode| {
705 const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", case.name, @tagName(mode)) catch unreachable;
711706 if (self.test_filter) |filter| {
712 if (mem.indexOf(u8, annotated_case_name, filter) == null)
713 continue;
707 if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
714708 }
715709
716710 const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode);
......@@ -744,8 +738,7 @@ pub const BuildExamplesContext = struct {
744738
745739 const annotated_case_name = b.fmt("build {} (Debug)", build_file);
746740 if (self.test_filter) |filter| {
747 if (mem.indexOf(u8, annotated_case_name, filter) == null)
748 return;
741 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
749742 }
750743
751744 var zig_args = ArrayList([]const u8).init(b.allocator);
......@@ -773,12 +766,15 @@ pub const BuildExamplesContext = struct {
773766 pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void {
774767 const b = self.b;
775768
776 for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
777 const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})",
778 root_src, @tagName(mode)) catch unreachable;
769 for ([]Mode{
770 Mode.Debug,
771 Mode.ReleaseSafe,
772 Mode.ReleaseFast,
773 Mode.ReleaseSmall,
774 }) |mode| {
775 const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", root_src, @tagName(mode)) catch unreachable;
779776 if (self.test_filter) |filter| {
780 if (mem.indexOf(u8, annotated_case_name, filter) == null)
781 continue;
777 if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
782778 }
783779
784780 const exe = b.addExecutable("test", root_src);
......@@ -813,7 +809,7 @@ pub const TranslateCContext = struct {
813809 };
814810
815811 pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
816 self.sources.append(SourceFile {
812 self.sources.append(SourceFile{
817813 .filename = filename,
818814 .source = source,
819815 }) catch unreachable;
......@@ -834,7 +830,7 @@ pub const TranslateCContext = struct {
834830 pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep {
835831 const allocator = context.b.allocator;
836832 const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
837 *ptr = TranslateCCmpOutputStep {
833 ptr.* = TranslateCCmpOutputStep{
838834 .step = build.Step.init("ParseCCmpOutput", allocator, make),
839835 .context = context,
840836 .name = name,
......@@ -857,7 +853,7 @@ pub const TranslateCContext = struct {
857853 zig_args.append("translate-c") catch unreachable;
858854 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
859855
860 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
856 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
861857
862858 if (b.verbose) {
863859 printInvocation(zig_args.toSliceConst());
......@@ -939,11 +935,9 @@ pub const TranslateCContext = struct {
939935 warn("\n");
940936 }
941937
942 pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8,
943 source: []const u8, expected_lines: ...) &TestCase
944 {
938 pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) &TestCase {
945939 const tc = self.b.allocator.create(TestCase) catch unreachable;
946 *tc = TestCase {
940 tc.* = TestCase{
947941 .name = name,
948942 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
949943 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
......@@ -977,8 +971,7 @@ pub const TranslateCContext = struct {
977971
978972 const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;
979973 if (self.test_filter) |filter| {
980 if (mem.indexOf(u8, annotated_case_name, filter) == null)
981 return;
974 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
982975 }
983976
984977 const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case);
......@@ -1009,7 +1002,7 @@ pub const GenHContext = struct {
10091002 };
10101003
10111004 pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
1012 self.sources.append(SourceFile {
1005 self.sources.append(SourceFile{
10131006 .filename = filename,
10141007 .source = source,
10151008 }) catch unreachable;
......@@ -1031,7 +1024,7 @@ pub const GenHContext = struct {
10311024 pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep {
10321025 const allocator = context.b.allocator;
10331026 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
1034 *ptr = GenHCmpOutputStep {
1027 ptr.* = GenHCmpOutputStep{
10351028 .step = build.Step.init("ParseCCmpOutput", allocator, make),
10361029 .context = context,
10371030 .h_path = h_path,
......@@ -1047,7 +1040,7 @@ pub const GenHContext = struct {
10471040 const self = @fieldParentPtr(GenHCmpOutputStep, "step", step);
10481041 const b = self.context.b;
10491042
1050 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
1043 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
10511044
10521045 const full_h_path = b.pathFromRoot(self.h_path);
10531046 const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
......@@ -1076,11 +1069,9 @@ pub const GenHContext = struct {
10761069 warn("\n");
10771070 }
10781071
1079 pub fn create(self: &GenHContext, filename: []const u8, name: []const u8,
1080 source: []const u8, expected_lines: ...) &TestCase
1081 {
1072 pub fn create(self: &GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) &TestCase {
10821073 const tc = self.b.allocator.create(TestCase) catch unreachable;
1083 *tc = TestCase {
1074 tc.* = TestCase{
10841075 .name = name,
10851076 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
10861077 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
......@@ -1105,8 +1096,7 @@ pub const GenHContext = struct {
11051096 const mode = builtin.Mode.Debug;
11061097 const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
11071098 if (self.test_filter) |filter| {
1108 if (mem.indexOf(u8, annotated_case_name, filter) == null)
1109 return;
1099 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
11101100 }
11111101
11121102 const obj = b.addObject("test", root_src);
test/translate_c.zig+50-50
......@@ -720,43 +720,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
720720 \\ var a: c_int = 0;
721721 \\ a += x: {
722722 \\ const _ref = &a;
723 \\ (*_ref) = ((*_ref) + 1);
724 \\ break :x *_ref;
723 \\ _ref.* = (_ref.* + 1);
724 \\ break :x _ref.*;
725725 \\ };
726726 \\ a -= x: {
727727 \\ const _ref = &a;
728 \\ (*_ref) = ((*_ref) - 1);
729 \\ break :x *_ref;
728 \\ _ref.* = (_ref.* - 1);
729 \\ break :x _ref.*;
730730 \\ };
731731 \\ a *= x: {
732732 \\ const _ref = &a;
733 \\ (*_ref) = ((*_ref) * 1);
734 \\ break :x *_ref;
733 \\ _ref.* = (_ref.* * 1);
734 \\ break :x _ref.*;
735735 \\ };
736736 \\ a &= x: {
737737 \\ const _ref = &a;
738 \\ (*_ref) = ((*_ref) & 1);
739 \\ break :x *_ref;
738 \\ _ref.* = (_ref.* & 1);
739 \\ break :x _ref.*;
740740 \\ };
741741 \\ a |= x: {
742742 \\ const _ref = &a;
743 \\ (*_ref) = ((*_ref) | 1);
744 \\ break :x *_ref;
743 \\ _ref.* = (_ref.* | 1);
744 \\ break :x _ref.*;
745745 \\ };
746746 \\ a ^= x: {
747747 \\ const _ref = &a;
748 \\ (*_ref) = ((*_ref) ^ 1);
749 \\ break :x *_ref;
748 \\ _ref.* = (_ref.* ^ 1);
749 \\ break :x _ref.*;
750750 \\ };
751751 \\ a >>= @import("std").math.Log2Int(c_int)(x: {
752752 \\ const _ref = &a;
753 \\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_int)(1));
754 \\ break :x *_ref;
753 \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_int)(1));
754 \\ break :x _ref.*;
755755 \\ });
756756 \\ a <<= @import("std").math.Log2Int(c_int)(x: {
757757 \\ const _ref = &a;
758 \\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_int)(1));
759 \\ break :x *_ref;
758 \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_int)(1));
759 \\ break :x _ref.*;
760760 \\ });
761761 \\}
762762 );
......@@ -778,43 +778,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
778778 \\ var a: c_uint = c_uint(0);
779779 \\ a +%= x: {
780780 \\ const _ref = &a;
781 \\ (*_ref) = ((*_ref) +% c_uint(1));
782 \\ break :x *_ref;
781 \\ _ref.* = (_ref.* +% c_uint(1));
782 \\ break :x _ref.*;
783783 \\ };
784784 \\ a -%= x: {
785785 \\ const _ref = &a;
786 \\ (*_ref) = ((*_ref) -% c_uint(1));
787 \\ break :x *_ref;
786 \\ _ref.* = (_ref.* -% c_uint(1));
787 \\ break :x _ref.*;
788788 \\ };
789789 \\ a *%= x: {
790790 \\ const _ref = &a;
791 \\ (*_ref) = ((*_ref) *% c_uint(1));
792 \\ break :x *_ref;
791 \\ _ref.* = (_ref.* *% c_uint(1));
792 \\ break :x _ref.*;
793793 \\ };
794794 \\ a &= x: {
795795 \\ const _ref = &a;
796 \\ (*_ref) = ((*_ref) & c_uint(1));
797 \\ break :x *_ref;
796 \\ _ref.* = (_ref.* & c_uint(1));
797 \\ break :x _ref.*;
798798 \\ };
799799 \\ a |= x: {
800800 \\ const _ref = &a;
801 \\ (*_ref) = ((*_ref) | c_uint(1));
802 \\ break :x *_ref;
801 \\ _ref.* = (_ref.* | c_uint(1));
802 \\ break :x _ref.*;
803803 \\ };
804804 \\ a ^= x: {
805805 \\ const _ref = &a;
806 \\ (*_ref) = ((*_ref) ^ c_uint(1));
807 \\ break :x *_ref;
806 \\ _ref.* = (_ref.* ^ c_uint(1));
807 \\ break :x _ref.*;
808808 \\ };
809809 \\ a >>= @import("std").math.Log2Int(c_uint)(x: {
810810 \\ const _ref = &a;
811 \\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_uint)(1));
812 \\ break :x *_ref;
811 \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_uint)(1));
812 \\ break :x _ref.*;
813813 \\ });
814814 \\ a <<= @import("std").math.Log2Int(c_uint)(x: {
815815 \\ const _ref = &a;
816 \\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_uint)(1));
817 \\ break :x *_ref;
816 \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_uint)(1));
817 \\ break :x _ref.*;
818818 \\ });
819819 \\}
820820 );
......@@ -853,26 +853,26 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
853853 \\ u -%= 1;
854854 \\ i = x: {
855855 \\ const _ref = &i;
856 \\ const _tmp = *_ref;
857 \\ (*_ref) += 1;
856 \\ const _tmp = _ref.*;
857 \\ _ref.* += 1;
858858 \\ break :x _tmp;
859859 \\ };
860860 \\ i = x: {
861861 \\ const _ref = &i;
862 \\ const _tmp = *_ref;
863 \\ (*_ref) -= 1;
862 \\ const _tmp = _ref.*;
863 \\ _ref.* -= 1;
864864 \\ break :x _tmp;
865865 \\ };
866866 \\ u = x: {
867867 \\ const _ref = &u;
868 \\ const _tmp = *_ref;
869 \\ (*_ref) +%= 1;
868 \\ const _tmp = _ref.*;
869 \\ _ref.* +%= 1;
870870 \\ break :x _tmp;
871871 \\ };
872872 \\ u = x: {
873873 \\ const _ref = &u;
874 \\ const _tmp = *_ref;
875 \\ (*_ref) -%= 1;
874 \\ const _tmp = _ref.*;
875 \\ _ref.* -%= 1;
876876 \\ break :x _tmp;
877877 \\ };
878878 \\}
......@@ -901,23 +901,23 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
901901 \\ u -%= 1;
902902 \\ i = x: {
903903 \\ const _ref = &i;
904 \\ (*_ref) += 1;
905 \\ break :x *_ref;
904 \\ _ref.* += 1;
905 \\ break :x _ref.*;
906906 \\ };
907907 \\ i = x: {
908908 \\ const _ref = &i;
909 \\ (*_ref) -= 1;
910 \\ break :x *_ref;
909 \\ _ref.* -= 1;
910 \\ break :x _ref.*;
911911 \\ };
912912 \\ u = x: {
913913 \\ const _ref = &u;
914 \\ (*_ref) +%= 1;
915 \\ break :x *_ref;
914 \\ _ref.* +%= 1;
915 \\ break :x _ref.*;
916916 \\ };
917917 \\ u = x: {
918918 \\ const _ref = &u;
919 \\ (*_ref) -%= 1;
920 \\ break :x *_ref;
919 \\ _ref.* -%= 1;
920 \\ break :x _ref.*;
921921 \\ };
922922 \\}
923923 );
......@@ -985,7 +985,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
985985 \\}
986986 ,
987987 \\pub export fn foo(x: ?&c_int) void {
988 \\ (*??x) = 1;
988 \\ (??x).* = 1;
989989 \\}
990990 );
991991
......@@ -1013,7 +1013,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
10131013 \\pub fn foo() c_int {
10141014 \\ var x: c_int = 1234;
10151015 \\ var ptr: ?&c_int = &x;
1016 \\ return *??ptr;
1016 \\ return (??ptr).*;
10171017 \\}
10181018 );
10191019