| author | |
| committer | |
| log | 83a78094788038fcf487e5947945a1f5900d564a |
| tree | a8639a11bea5a2fc2b9c5aebf30011f7675f37d7 |
| parent | 942d384831196acf24868c32ef84409b05441960 |
| parent | c38b165db4a16ba6a5c6d13537177db656fc4033 |
| signature |
Pointer Reform - change prefix deref syntax to postfix deref syntax117 files changed, 6037 insertions(+), 4268 deletions(-)
build.zig+34-25| ... | ... | @@ -16,7 +16,7 @@ pub fn build(b: &Builder) !void { |
| 16 | 16 | var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); |
| 17 | 17 | |
| 18 | 18 | 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{ | |
| 20 | 20 | docgen_exe.getOutputPath(), |
| 21 | 21 | rel_zig_exe, |
| 22 | 22 | "doc/langref.html.in", |
| ... | ... | @@ -30,7 +30,10 @@ pub fn build(b: &Builder) !void { |
| 30 | 30 | const test_step = b.step("test", "Run all the tests"); |
| 31 | 31 | |
| 32 | 32 | // 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 | }); | |
| 34 | 37 | var index: usize = 0; |
| 35 | 38 | const cmake_binary_dir = nextValue(&index, build_info); |
| 36 | 39 | const cxx_compiler = nextValue(&index, build_info); |
| ... | ... | @@ -67,7 +70,10 @@ pub fn build(b: &Builder) !void { |
| 67 | 70 | dependOnLib(exe, llvm); |
| 68 | 71 | |
| 69 | 72 | 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 | }); | |
| 71 | 77 | const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next(); |
| 72 | 78 | if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) { |
| 73 | 79 | warn( |
| ... | ... | @@ -111,17 +117,11 @@ pub fn build(b: &Builder) !void { |
| 111 | 117 | |
| 112 | 118 | test_step.dependOn(docs_step); |
| 113 | 119 | |
| 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)); | |
| 117 | 121 | |
| 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)); | |
| 121 | 123 | |
| 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)); | |
| 125 | 125 | |
| 126 | 126 | test_step.dependOn(tests.addCompareOutputTests(b, test_filter)); |
| 127 | 127 | test_step.dependOn(tests.addBuildExampleTests(b, test_filter)); |
| ... | ... | @@ -149,8 +149,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) vo |
| 149 | 149 | |
| 150 | 150 | fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void { |
| 151 | 151 | 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); | |
| 154 | 153 | } |
| 155 | 154 | |
| 156 | 155 | const LibraryDep = struct { |
| ... | ... | @@ -161,11 +160,21 @@ const LibraryDep = struct { |
| 161 | 160 | }; |
| 162 | 161 | |
| 163 | 162 | fn 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 | }); | |
| 167 | 176 | |
| 168 | var result = LibraryDep { | |
| 177 | var result = LibraryDep{ | |
| 169 | 178 | .libs = ArrayList([]const u8).init(b.allocator), |
| 170 | 179 | .system_libs = ArrayList([]const u8).init(b.allocator), |
| 171 | 180 | .includes = ArrayList([]const u8).init(b.allocator), |
| ... | ... | @@ -227,17 +236,17 @@ pub fn installCHeaders(b: &Builder, c_header_files: []const u8) void { |
| 227 | 236 | } |
| 228 | 237 | |
| 229 | 238 | fn 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.*]) { | |
| 233 | 242 | '\n' => { |
| 234 | const result = build_info[start..*index]; | |
| 235 | *index += 1; | |
| 243 | const result = build_info[start..index.*]; | |
| 244 | index.* += 1; | |
| 236 | 245 | return result; |
| 237 | 246 | }, |
| 238 | 247 | '\r' => { |
| 239 | const result = build_info[start..*index]; | |
| 240 | *index += 2; | |
| 248 | const result = build_info[start..index.*]; | |
| 249 | index.* += 2; | |
| 241 | 250 | return result; |
| 242 | 251 | }, |
| 243 | 252 | else => continue, |
doc/langref.html.in+34-32| ... | ... | @@ -1232,7 +1232,7 @@ mem.eql(u8, pattern, "ababab")</code></pre> |
| 1232 | 1232 | </td> |
| 1233 | 1233 | </tr> |
| 1234 | 1234 | <tr> |
| 1235 | <td><pre><code class="zig">*a<code></pre></td> | |
| 1235 | <td><pre><code class="zig">a.*<code></pre></td> | |
| 1236 | 1236 | <td> |
| 1237 | 1237 | <ul> |
| 1238 | 1238 | <li>{#link|Pointers#}</li> |
| ... | ... | @@ -1244,7 +1244,7 @@ mem.eql(u8, pattern, "ababab")</code></pre> |
| 1244 | 1244 | <td> |
| 1245 | 1245 | <pre><code class="zig">const x: u32 = 1234; |
| 1246 | 1246 | const ptr = &amp;x; |
| 1247 | *x == 1234</code></pre> | |
| 1247 | x.* == 1234</code></pre> | |
| 1248 | 1248 | </td> |
| 1249 | 1249 | </tr> |
| 1250 | 1250 | <tr> |
| ... | ... | @@ -1258,7 +1258,7 @@ const ptr = &amp;x; |
| 1258 | 1258 | <td> |
| 1259 | 1259 | <pre><code class="zig">const x: u32 = 1234; |
| 1260 | 1260 | const ptr = &amp;x; |
| 1261 | *x == 1234</code></pre> | |
| 1261 | x.* == 1234</code></pre> | |
| 1262 | 1262 | </td> |
| 1263 | 1263 | </tr> |
| 1264 | 1264 | </table> |
| ... | ... | @@ -1267,8 +1267,8 @@ const ptr = &amp;x; |
| 1267 | 1267 | {#header_open|Precedence#} |
| 1268 | 1268 | <pre><code>x() x[] x.y |
| 1269 | 1269 | a!b |
| 1270 | !x -x -%x ~x *x &amp;x ?x ??x | |
| 1271 | x{} | |
| 1270 | !x -x -%x ~x &amp;x ?x ??x | |
| 1271 | x{} x.* | |
| 1272 | 1272 | ! * / % ** *% |
| 1273 | 1273 | + - ++ +% -% |
| 1274 | 1274 | &lt;&lt; &gt;&gt; |
| ... | ... | @@ -1316,7 +1316,7 @@ var some_integers: [100]i32 = undefined; |
| 1316 | 1316 | |
| 1317 | 1317 | test "modify an array" { |
| 1318 | 1318 | for (some_integers) |*item, i| { |
| 1319 | *item = i32(i); | |
| 1319 | item.* = i32(i); | |
| 1320 | 1320 | } |
| 1321 | 1321 | assert(some_integers[10] == 10); |
| 1322 | 1322 | assert(some_integers[99] == 99); |
| ... | ... | @@ -1357,7 +1357,7 @@ comptime { |
| 1357 | 1357 | var fancy_array = init: { |
| 1358 | 1358 | var initial_value: [10]Point = undefined; |
| 1359 | 1359 | for (initial_value) |*pt, i| { |
| 1360 | *pt = Point { | |
| 1360 | pt.* = Point { | |
| 1361 | 1361 | .x = i32(i), |
| 1362 | 1362 | .y = i32(i) * 2, |
| 1363 | 1363 | }; |
| ... | ... | @@ -1400,7 +1400,7 @@ test "address of syntax" { |
| 1400 | 1400 | const x_ptr = &x; |
| 1401 | 1401 | |
| 1402 | 1402 | // Deference a pointer: |
| 1403 | assert(*x_ptr == 1234); | |
| 1403 | assert(x_ptr.* == 1234); | |
| 1404 | 1404 | |
| 1405 | 1405 | // When you get the address of a const variable, you get a const pointer. |
| 1406 | 1406 | assert(@typeOf(x_ptr) == &const i32); |
| ... | ... | @@ -1409,8 +1409,8 @@ test "address of syntax" { |
| 1409 | 1409 | var y: i32 = 5678; |
| 1410 | 1410 | const y_ptr = &y; |
| 1411 | 1411 | assert(@typeOf(y_ptr) == &i32); |
| 1412 | *y_ptr += 1; | |
| 1413 | assert(*y_ptr == 5679); | |
| 1412 | y_ptr.* += 1; | |
| 1413 | assert(y_ptr.* == 5679); | |
| 1414 | 1414 | } |
| 1415 | 1415 | |
| 1416 | 1416 | test "pointer array access" { |
| ... | ... | @@ -1448,9 +1448,9 @@ comptime { |
| 1448 | 1448 | // @ptrCast. |
| 1449 | 1449 | var x: i32 = 1; |
| 1450 | 1450 | const ptr = &x; |
| 1451 | *ptr += 1; | |
| 1451 | ptr.* += 1; | |
| 1452 | 1452 | x += 1; |
| 1453 | assert(*ptr == 3); | |
| 1453 | assert(ptr.* == 3); | |
| 1454 | 1454 | } |
| 1455 | 1455 | |
| 1456 | 1456 | test "@ptrToInt and @intToPtr" { |
| ... | ... | @@ -1492,7 +1492,7 @@ test "nullable pointers" { |
| 1492 | 1492 | var x: i32 = 1; |
| 1493 | 1493 | ptr = &x; |
| 1494 | 1494 | |
| 1495 | assert(*??ptr == 1); | |
| 1495 | assert((??ptr).* == 1); | |
| 1496 | 1496 | |
| 1497 | 1497 | // Nullable pointers are the same size as normal pointers, because pointer |
| 1498 | 1498 | // value 0 is used as the null value. |
| ... | ... | @@ -1505,7 +1505,7 @@ test "pointer casting" { |
| 1505 | 1505 | // conversions are not possible. |
| 1506 | 1506 | const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12}; |
| 1507 | 1507 | const u32_ptr = @ptrCast(&const u32, &bytes[0]); |
| 1508 | assert(*u32_ptr == 0x12121212); | |
| 1508 | assert(u32_ptr.* == 0x12121212); | |
| 1509 | 1509 | |
| 1510 | 1510 | // Even this example is contrived - there are better ways to do the above than |
| 1511 | 1511 | // pointer casting. For example, using a slice narrowing cast: |
| ... | ... | @@ -1610,7 +1610,7 @@ fn foo(bytes: []u8) u32 { |
| 1610 | 1610 | <code>u8</code> can alias any memory. |
| 1611 | 1611 | </p> |
| 1612 | 1612 | <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> | |
| 1614 | 1614 | <p>Instead, use {#link|@bitCast#}: |
| 1615 | 1615 | <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre> |
| 1616 | 1616 | <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p> |
| ... | ... | @@ -2040,7 +2040,7 @@ const Variant = union(enum) { |
| 2040 | 2040 | Bool: bool, |
| 2041 | 2041 | |
| 2042 | 2042 | fn truthy(self: &const Variant) bool { |
| 2043 | return switch (*self) { | |
| 2043 | return switch (self.*) { | |
| 2044 | 2044 | Variant.Int => |x_int| x_int != 0, |
| 2045 | 2045 | Variant.Bool => |x_bool| x_bool, |
| 2046 | 2046 | }; |
| ... | ... | @@ -2151,7 +2151,7 @@ test "switch enum" { |
| 2151 | 2151 | |
| 2152 | 2152 | // A reference to the matched value can be obtained using `*` syntax. |
| 2153 | 2153 | Item.C => |*item| blk: { |
| 2154 | (*item).x += 1; | |
| 2154 | item.*.x += 1; | |
| 2155 | 2155 | break :blk 6; |
| 2156 | 2156 | }, |
| 2157 | 2157 | |
| ... | ... | @@ -2374,7 +2374,7 @@ test "for reference" { |
| 2374 | 2374 | // Iterate over the slice by reference by |
| 2375 | 2375 | // specifying that the capture value is a pointer. |
| 2376 | 2376 | for (items) |*value| { |
| 2377 | *value += 1; | |
| 2377 | value.* += 1; | |
| 2378 | 2378 | } |
| 2379 | 2379 | |
| 2380 | 2380 | assert(items[0] == 4); |
| ... | ... | @@ -2483,7 +2483,7 @@ test "if nullable" { |
| 2483 | 2483 | // Access the value by reference using a pointer capture. |
| 2484 | 2484 | var c: ?u32 = 3; |
| 2485 | 2485 | if (c) |*value| { |
| 2486 | *value = 2; | |
| 2486 | value.* = 2; | |
| 2487 | 2487 | } |
| 2488 | 2488 | |
| 2489 | 2489 | if (c) |value| { |
| ... | ... | @@ -2524,7 +2524,7 @@ test "if error union" { |
| 2524 | 2524 | // Access the value by reference using a pointer capture. |
| 2525 | 2525 | var c: error!u32 = 3; |
| 2526 | 2526 | if (c) |*value| { |
| 2527 | *value = 9; | |
| 2527 | value.* = 9; | |
| 2528 | 2528 | } else |err| { |
| 2529 | 2529 | unreachable; |
| 2530 | 2530 | } |
| ... | ... | @@ -3872,7 +3872,7 @@ pub fn main() void { |
| 3872 | 3872 | {#header_open|@addWithOverflow#} |
| 3873 | 3873 | <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre> |
| 3874 | 3874 | <p> |
| 3875 | Performs <code>*result = a + b</code>. If overflow or underflow occurs, | |
| 3875 | Performs <code>result.* = a + b</code>. If overflow or underflow occurs, | |
| 3876 | 3876 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| 3877 | 3877 | If no overflow or underflow occurs, returns <code>false</code>. |
| 3878 | 3878 | </p> |
| ... | ... | @@ -4073,9 +4073,9 @@ comptime { |
| 4073 | 4073 | </p> |
| 4074 | 4074 | {#code_begin|syntax#} |
| 4075 | 4075 | fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T { |
| 4076 | const old_value = *ptr; | |
| 4076 | const old_value = ptr.*; | |
| 4077 | 4077 | if (old_value == expected_value) { |
| 4078 | *ptr = new_value; | |
| 4078 | ptr.* = new_value; | |
| 4079 | 4079 | return null; |
| 4080 | 4080 | } else { |
| 4081 | 4081 | return old_value; |
| ... | ... | @@ -4100,9 +4100,9 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_v |
| 4100 | 4100 | </p> |
| 4101 | 4101 | {#code_begin|syntax#} |
| 4102 | 4102 | fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T { |
| 4103 | const old_value = *ptr; | |
| 4103 | const old_value = ptr.*; | |
| 4104 | 4104 | if (old_value == expected_value and usuallyTrueButSometimesFalse()) { |
| 4105 | *ptr = new_value; | |
| 4105 | ptr.* = new_value; | |
| 4106 | 4106 | return null; |
| 4107 | 4107 | } else { |
| 4108 | 4108 | return old_value; |
| ... | ... | @@ -4447,7 +4447,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre> |
| 4447 | 4447 | This function is a low level intrinsic with no safety mechanisms. Most |
| 4448 | 4448 | code should not use this function, instead using something like this: |
| 4449 | 4449 | </p> |
| 4450 | <pre><code class="zig">for (dest[0...byte_count]) |*b| *b = c;</code></pre> | |
| 4450 | <pre><code class="zig">for (dest[0...byte_count]) |*b| b.* = c;</code></pre> | |
| 4451 | 4451 | <p> |
| 4452 | 4452 | The optimizer is intelligent enough to turn the above snippet into a memset. |
| 4453 | 4453 | </p> |
| ... | ... | @@ -4480,7 +4480,7 @@ mem.set(u8, dest, c);</code></pre> |
| 4480 | 4480 | {#header_open|@mulWithOverflow#} |
| 4481 | 4481 | <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre> |
| 4482 | 4482 | <p> |
| 4483 | Performs <code>*result = a * b</code>. If overflow or underflow occurs, | |
| 4483 | Performs <code>result.* = a * b</code>. If overflow or underflow occurs, | |
| 4484 | 4484 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| 4485 | 4485 | If no overflow or underflow occurs, returns <code>false</code>. |
| 4486 | 4486 | </p> |
| ... | ... | @@ -4514,7 +4514,7 @@ fn targetFunction(x: i32) usize { |
| 4514 | 4514 | |
| 4515 | 4515 | var local_variable: i32 = 42; |
| 4516 | 4516 | const ptr = &local_variable; |
| 4517 | *ptr += 1; | |
| 4517 | ptr.* += 1; | |
| 4518 | 4518 | |
| 4519 | 4519 | assert(local_variable == 43); |
| 4520 | 4520 | return @ptrToInt(ptr); |
| ... | ... | @@ -4746,7 +4746,7 @@ pub const FloatMode = enum { |
| 4746 | 4746 | {#header_open|@shlWithOverflow#} |
| 4747 | 4747 | <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -&gt; bool</code></pre> |
| 4748 | 4748 | <p> |
| 4749 | Performs <code>*result = a &lt;&lt; b</code>. If overflow or underflow occurs, | |
| 4749 | Performs <code>result.* = a &lt;&lt; b</code>. If overflow or underflow occurs, | |
| 4750 | 4750 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| 4751 | 4751 | If no overflow or underflow occurs, returns <code>false</code>. |
| 4752 | 4752 | </p> |
| ... | ... | @@ -4790,7 +4790,7 @@ pub const FloatMode = enum { |
| 4790 | 4790 | {#header_open|@subWithOverflow#} |
| 4791 | 4791 | <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre> |
| 4792 | 4792 | <p> |
| 4793 | Performs <code>*result = a - b</code>. If overflow or underflow occurs, | |
| 4793 | Performs <code>result.* = a - b</code>. If overflow or underflow occurs, | |
| 4794 | 4794 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| 4795 | 4795 | If no overflow or underflow occurs, returns <code>false</code>. |
| 4796 | 4796 | </p> |
| ... | ... | @@ -6382,10 +6382,12 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%" |
| 6382 | 6382 | |
| 6383 | 6383 | PrefixOpExpression = PrefixOp TypeExpr | SuffixOpExpression |
| 6384 | 6384 | |
| 6385 | SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) | |
| 6385 | SuffixOpExpression = ("async" option("&lt;" SuffixOpExpression "&gt;") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | PtrDerefExpression) | |
| 6386 | 6386 | |
| 6387 | 6387 | FieldAccessExpression = "." Symbol |
| 6388 | 6388 | |
| 6389 | PtrDerefExpression = ".*" | |
| 6390 | ||
| 6389 | 6391 | FnCallExpression = "(" list(Expression, ",") ")" |
| 6390 | 6392 | |
| 6391 | 6393 | ArrayAccessExpression = "[" Expression "]" |
| ... | ... | @@ -6398,7 +6400,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",") |
| 6398 | 6400 | |
| 6399 | 6401 | StructLiteralField = "." Symbol "=" Expression |
| 6400 | 6402 | |
| 6401 | PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" | |
| 6403 | PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" | |
| 6402 | 6404 | |
| 6403 | 6405 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType |
| 6404 | 6406 |
src-self-hosted/arg.zig+41-33| ... | ... | @@ -30,24 +30,22 @@ fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | // Modifies the current argument index during iteration |
| 33 | fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize, | |
| 34 | allowed_set: ?[]const []const u8, index: &usize) !FlagArg { | |
| 35 | ||
| 33 | fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: &usize) !FlagArg { | |
| 36 | 34 | 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? | |
| 38 | 36 | 1 => { |
| 39 | if (*index + 1 >= args.len) { | |
| 37 | if (index.* + 1 >= args.len) { | |
| 40 | 38 | return error.MissingFlagArguments; |
| 41 | 39 | } |
| 42 | 40 | |
| 43 | *index += 1; | |
| 44 | const arg = args[*index]; | |
| 41 | index.* += 1; | |
| 42 | const arg = args[index.*]; | |
| 45 | 43 | |
| 46 | 44 | if (!argInAllowedSet(allowed_set, arg)) { |
| 47 | 45 | return error.ArgumentNotInAllowedSet; |
| 48 | 46 | } |
| 49 | 47 | |
| 50 | return FlagArg { .Single = arg }; | |
| 48 | return FlagArg{ .Single = arg }; | |
| 51 | 49 | }, |
| 52 | 50 | else => |needed| { |
| 53 | 51 | var extra = ArrayList([]const u8).init(allocator); |
| ... | ... | @@ -55,12 +53,12 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: |
| 55 | 53 | |
| 56 | 54 | var j: usize = 0; |
| 57 | 55 | while (j < needed) : (j += 1) { |
| 58 | if (*index + 1 >= args.len) { | |
| 56 | if (index.* + 1 >= args.len) { | |
| 59 | 57 | return error.MissingFlagArguments; |
| 60 | 58 | } |
| 61 | 59 | |
| 62 | *index += 1; | |
| 63 | const arg = args[*index]; | |
| 60 | index.* += 1; | |
| 61 | const arg = args[index.*]; | |
| 64 | 62 | |
| 65 | 63 | if (!argInAllowedSet(allowed_set, arg)) { |
| 66 | 64 | return error.ArgumentNotInAllowedSet; |
| ... | ... | @@ -69,7 +67,7 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: |
| 69 | 67 | try extra.append(arg); |
| 70 | 68 | } |
| 71 | 69 | |
| 72 | return FlagArg { .Many = extra }; | |
| 70 | return FlagArg{ .Many = extra }; | |
| 73 | 71 | }, |
| 74 | 72 | } |
| 75 | 73 | } |
| ... | ... | @@ -82,7 +80,7 @@ pub const Args = struct { |
| 82 | 80 | positionals: ArrayList([]const u8), |
| 83 | 81 | |
| 84 | 82 | pub fn parse(allocator: &Allocator, comptime spec: []const Flag, args: []const []const u8) !Args { |
| 85 | var parsed = Args { | |
| 83 | var parsed = Args{ | |
| 86 | 84 | .flags = HashMapFlags.init(allocator), |
| 87 | 85 | .positionals = ArrayList([]const u8).init(allocator), |
| 88 | 86 | }; |
| ... | ... | @@ -116,11 +114,7 @@ pub const Args = struct { |
| 116 | 114 | }; |
| 117 | 115 | |
| 118 | 116 | 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); | |
| 124 | 118 | |
| 125 | 119 | // MergeN creation disallows 0 length flag entry (doesn't make sense) |
| 126 | 120 | switch (flag_args) { |
| ... | ... | @@ -129,7 +123,7 @@ pub const Args = struct { |
| 129 | 123 | FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()), |
| 130 | 124 | } |
| 131 | 125 | |
| 132 | _ = try parsed.flags.put(flag_name_trimmed, FlagArg { .Many = prev }); | |
| 126 | _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev }); | |
| 133 | 127 | } else { |
| 134 | 128 | _ = try parsed.flags.put(flag_name_trimmed, flag_args); |
| 135 | 129 | } |
| ... | ... | @@ -163,7 +157,9 @@ pub const Args = struct { |
| 163 | 157 | pub fn single(self: &Args, name: []const u8) ?[]const u8 { |
| 164 | 158 | if (self.flags.get(name)) |entry| { |
| 165 | 159 | switch (entry.value) { |
| 166 | FlagArg.Single => |inner| { return inner; }, | |
| 160 | FlagArg.Single => |inner| { | |
| 161 | return inner; | |
| 162 | }, | |
| 167 | 163 | else => @panic("attempted to retrieve flag with wrong type"), |
| 168 | 164 | } |
| 169 | 165 | } else { |
| ... | ... | @@ -175,7 +171,9 @@ pub const Args = struct { |
| 175 | 171 | pub fn many(self: &Args, name: []const u8) ?[]const []const u8 { |
| 176 | 172 | if (self.flags.get(name)) |entry| { |
| 177 | 173 | switch (entry.value) { |
| 178 | FlagArg.Many => |inner| { return inner.toSliceConst(); }, | |
| 174 | FlagArg.Many => |inner| { | |
| 175 | return inner.toSliceConst(); | |
| 176 | }, | |
| 179 | 177 | else => @panic("attempted to retrieve flag with wrong type"), |
| 180 | 178 | } |
| 181 | 179 | } else { |
| ... | ... | @@ -207,7 +205,7 @@ pub const Flag = struct { |
| 207 | 205 | } |
| 208 | 206 | |
| 209 | 207 | pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag { |
| 210 | return Flag { | |
| 208 | return Flag{ | |
| 211 | 209 | .name = name, |
| 212 | 210 | .required = n, |
| 213 | 211 | .mergable = false, |
| ... | ... | @@ -220,7 +218,7 @@ pub const Flag = struct { |
| 220 | 218 | @compileError("n must be greater than 0"); |
| 221 | 219 | } |
| 222 | 220 | |
| 223 | return Flag { | |
| 221 | return Flag{ | |
| 224 | 222 | .name = name, |
| 225 | 223 | .required = n, |
| 226 | 224 | .mergable = true, |
| ... | ... | @@ -229,7 +227,7 @@ pub const Flag = struct { |
| 229 | 227 | } |
| 230 | 228 | |
| 231 | 229 | pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag { |
| 232 | return Flag { | |
| 230 | return Flag{ | |
| 233 | 231 | .name = name, |
| 234 | 232 | .required = 1, |
| 235 | 233 | .mergable = false, |
| ... | ... | @@ -239,26 +237,36 @@ pub const Flag = struct { |
| 239 | 237 | }; |
| 240 | 238 | |
| 241 | 239 | test "parse arguments" { |
| 242 | const spec1 = comptime []const Flag { | |
| 240 | const spec1 = comptime []const Flag{ | |
| 243 | 241 | Flag.Bool("--help"), |
| 244 | 242 | Flag.Bool("--init"), |
| 245 | 243 | 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 | }), | |
| 247 | 249 | Flag.ArgN("--pkg-begin", 2), |
| 248 | 250 | Flag.ArgMergeN("--object", 1), |
| 249 | 251 | Flag.ArgN("--library", 1), |
| 250 | 252 | }; |
| 251 | 253 | |
| 252 | const cliargs = []const []const u8 { | |
| 254 | const cliargs = []const []const u8{ | |
| 253 | 255 | "build", |
| 254 | 256 | "--help", |
| 255 | 257 | "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", | |
| 262 | 270 | "pos2", |
| 263 | 271 | }; |
| 264 | 272 |
src-self-hosted/module.zig+9-9| ... | ... | @@ -96,6 +96,7 @@ pub const Module = struct { |
| 96 | 96 | pub const LinkLib = struct { |
| 97 | 97 | name: []const u8, |
| 98 | 98 | path: ?[]const u8, |
| 99 | ||
| 99 | 100 | /// the list of symbols we depend on from this lib |
| 100 | 101 | symbols: ArrayList([]u8), |
| 101 | 102 | provided_explicitly: bool, |
| ... | ... | @@ -130,9 +131,7 @@ pub const Module = struct { |
| 130 | 131 | } |
| 131 | 132 | }; |
| 132 | 133 | |
| 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 { | |
| 136 | 135 | var name_buffer = try Buffer.init(allocator, name); |
| 137 | 136 | errdefer name_buffer.deinit(); |
| 138 | 137 | |
| ... | ... | @@ -148,14 +147,14 @@ pub const Module = struct { |
| 148 | 147 | const module_ptr = try allocator.create(Module); |
| 149 | 148 | errdefer allocator.destroy(module_ptr); |
| 150 | 149 | |
| 151 | *module_ptr = Module { | |
| 150 | module_ptr.* = Module{ | |
| 152 | 151 | .allocator = allocator, |
| 153 | 152 | .name = name_buffer, |
| 154 | 153 | .root_src_path = root_src_path, |
| 155 | 154 | .module = module, |
| 156 | 155 | .context = context, |
| 157 | 156 | .builder = builder, |
| 158 | .target = *target, | |
| 157 | .target = target.*, | |
| 159 | 158 | .kind = kind, |
| 160 | 159 | .build_mode = build_mode, |
| 161 | 160 | .zig_lib_dir = zig_lib_dir, |
| ... | ... | @@ -221,8 +220,10 @@ pub const Module = struct { |
| 221 | 220 | |
| 222 | 221 | pub fn build(self: &Module) !void { |
| 223 | 222 | 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 | }); | |
| 226 | 227 | defer c_compatible_args.deinit(); |
| 227 | 228 | c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr); |
| 228 | 229 | } |
| ... | ... | @@ -261,7 +262,6 @@ pub const Module = struct { |
| 261 | 262 | |
| 262 | 263 | warn("====llvm ir:====\n"); |
| 263 | 264 | self.dump(); |
| 264 | ||
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | pub fn link(self: &Module, out_file: ?[]const u8) !void { |
| ... | ... | @@ -285,7 +285,7 @@ pub const Module = struct { |
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | const link_lib = try self.allocator.create(LinkLib); |
| 288 | *link_lib = LinkLib { | |
| 288 | link_lib.* = LinkLib{ | |
| 289 | 289 | .name = name, |
| 290 | 290 | .path = null, |
| 291 | 291 | .provided_explicitly = provided_explicitly, |
src-self-hosted/target.zig+4-3| ... | ... | @@ -12,7 +12,7 @@ pub const Target = union(enum) { |
| 12 | 12 | Cross: CrossTarget, |
| 13 | 13 | |
| 14 | 14 | pub fn oFileExt(self: &const Target) []const u8 { |
| 15 | const environ = switch (*self) { | |
| 15 | const environ = switch (self.*) { | |
| 16 | 16 | Target.Native => builtin.environ, |
| 17 | 17 | Target.Cross => |t| t.environ, |
| 18 | 18 | }; |
| ... | ... | @@ -30,7 +30,7 @@ pub const Target = union(enum) { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | pub fn getOs(self: &const Target) builtin.Os { |
| 33 | return switch (*self) { | |
| 33 | return switch (self.*) { | |
| 34 | 34 | Target.Native => builtin.os, |
| 35 | 35 | Target.Cross => |t| t.os, |
| 36 | 36 | }; |
| ... | ... | @@ -38,7 +38,8 @@ pub const Target = union(enum) { |
| 38 | 38 | |
| 39 | 39 | pub fn isDarwin(self: &const Target) bool { |
| 40 | 40 | return switch (self.getOs()) { |
| 41 | builtin.Os.ios, builtin.Os.macosx => true, | |
| 41 | builtin.Os.ios, | |
| 42 | builtin.Os.macosx => true, | |
| 42 | 43 | else => false, |
| 43 | 44 | }; |
| 44 | 45 | } |
src/all_types.hpp+6-1| ... | ... | @@ -379,6 +379,7 @@ enum NodeType { |
| 379 | 379 | NodeTypeArrayAccessExpr, |
| 380 | 380 | NodeTypeSliceExpr, |
| 381 | 381 | NodeTypeFieldAccessExpr, |
| 382 | NodeTypePtrDeref, | |
| 382 | 383 | NodeTypeUse, |
| 383 | 384 | NodeTypeBoolLiteral, |
| 384 | 385 | NodeTypeNullLiteral, |
| ... | ... | @@ -603,13 +604,16 @@ struct AstNodeFieldAccessExpr { |
| 603 | 604 | Buf *field_name; |
| 604 | 605 | }; |
| 605 | 606 | |
| 607 | struct AstNodePtrDerefExpr { | |
| 608 | AstNode *target; | |
| 609 | }; | |
| 610 | ||
| 606 | 611 | enum PrefixOp { |
| 607 | 612 | PrefixOpInvalid, |
| 608 | 613 | PrefixOpBoolNot, |
| 609 | 614 | PrefixOpBinNot, |
| 610 | 615 | PrefixOpNegation, |
| 611 | 616 | PrefixOpNegationWrap, |
| 612 | PrefixOpDereference, | |
| 613 | 617 | PrefixOpMaybe, |
| 614 | 618 | PrefixOpUnwrapMaybe, |
| 615 | 619 | }; |
| ... | ... | @@ -911,6 +915,7 @@ struct AstNode { |
| 911 | 915 | AstNodeCompTime comptime_expr; |
| 912 | 916 | AstNodeAsmExpr asm_expr; |
| 913 | 917 | AstNodeFieldAccessExpr field_access_expr; |
| 918 | AstNodePtrDerefExpr ptr_deref_expr; | |
| 914 | 919 | AstNodeContainerDecl container_decl; |
| 915 | 920 | AstNodeStructField struct_field; |
| 916 | 921 | AstNodeStringLiteral string_literal; |
src/analyze.cpp+1| ... | ... | @@ -3281,6 +3281,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3281 | 3281 | case NodeTypeUnreachable: |
| 3282 | 3282 | case NodeTypeAsmExpr: |
| 3283 | 3283 | case NodeTypeFieldAccessExpr: |
| 3284 | case NodeTypePtrDeref: | |
| 3284 | 3285 | case NodeTypeStructField: |
| 3285 | 3286 | case NodeTypeContainerInitExpr: |
| 3286 | 3287 | case NodeTypeStructValueField: |
src/ast_render.cpp+9-1| ... | ... | @@ -66,7 +66,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 66 | 66 | case PrefixOpNegationWrap: return "-%"; |
| 67 | 67 | case PrefixOpBoolNot: return "!"; |
| 68 | 68 | case PrefixOpBinNot: return "~"; |
| 69 | case PrefixOpDereference: return "*"; | |
| 70 | 69 | case PrefixOpMaybe: return "?"; |
| 71 | 70 | case PrefixOpUnwrapMaybe: return "??"; |
| 72 | 71 | } |
| ... | ... | @@ -222,6 +221,8 @@ static const char *node_type_str(NodeType node_type) { |
| 222 | 221 | return "AsmExpr"; |
| 223 | 222 | case NodeTypeFieldAccessExpr: |
| 224 | 223 | return "FieldAccessExpr"; |
| 224 | case NodeTypePtrDeref: | |
| 225 | return "PtrDerefExpr"; | |
| 225 | 226 | case NodeTypeContainerDecl: |
| 226 | 227 | return "ContainerDecl"; |
| 227 | 228 | case NodeTypeStructField: |
| ... | ... | @@ -696,6 +697,13 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 696 | 697 | print_symbol(ar, rhs); |
| 697 | 698 | break; |
| 698 | 699 | } |
| 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 | } | |
| 699 | 707 | case NodeTypeUndefinedLiteral: |
| 700 | 708 | fprintf(ar->f, "undefined"); |
| 701 | 709 | break; |
src/ir.cpp+10-4| ... | ... | @@ -4609,8 +4609,14 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4609 | 4609 | } |
| 4610 | 4610 | |
| 4611 | 4611 | static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, AstNode *node, IrUnOp op_id, LVal lval) { |
| 4612 | assert(node->type == NodeTypePrefixOpExpr); | |
| 4613 | 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 | } | |
| 4614 | 4620 | |
| 4615 | 4621 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, lval); |
| 4616 | 4622 | if (value == irb->codegen->invalid_instruction) |
| ... | ... | @@ -4751,8 +4757,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 4751 | 4757 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval); |
| 4752 | 4758 | case PrefixOpNegationWrap: |
| 4753 | 4759 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); |
| 4754 | case PrefixOpDereference: | |
| 4755 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); | |
| 4756 | 4760 | case PrefixOpMaybe: |
| 4757 | 4761 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval); |
| 4758 | 4762 | case PrefixOpUnwrapMaybe: |
| ... | ... | @@ -6588,6 +6592,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6588 | 6592 | |
| 6589 | 6593 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); |
| 6590 | 6594 | } |
| 6595 | case NodeTypePtrDeref: | |
| 6596 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); | |
| 6591 | 6597 | case NodeTypeThisLiteral: |
| 6592 | 6598 | return ir_lval_wrap(irb, scope, ir_gen_this_literal(irb, scope, node), lval); |
| 6593 | 6599 | case NodeTypeBoolLiteral: |
src/parser.cpp+25-18| ... | ... | @@ -1046,11 +1046,12 @@ static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index |
| 1046 | 1046 | } |
| 1047 | 1047 | |
| 1048 | 1048 | /* |
| 1049 | SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) | |
| 1049 | SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | PtrDerefExpression | SliceExpression) | |
| 1050 | 1050 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) |
| 1051 | 1051 | ArrayAccessExpression : token(LBracket) Expression token(RBracket) |
| 1052 | 1052 | SliceExpression = "[" Expression ".." option(Expression) "]" |
| 1053 | 1053 | FieldAccessExpression : token(Dot) token(Symbol) |
| 1054 | PtrDerefExpression = ".*" | |
| 1054 | 1055 | StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression |
| 1055 | 1056 | */ |
| 1056 | 1057 | static 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, |
| 1131 | 1132 | } else if (first_token->id == TokenIdDot) { |
| 1132 | 1133 | *token_index += 1; |
| 1133 | 1134 | |
| 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; | |
| 1135 | 1139 | |
| 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 | } | |
| 1139 | 1155 | |
| 1140 | primary_expr = node; | |
| 1141 | 1156 | } else { |
| 1142 | 1157 | return primary_expr; |
| 1143 | 1158 | } |
| ... | ... | @@ -1150,10 +1165,8 @@ static PrefixOp tok_to_prefix_op(Token *token) { |
| 1150 | 1165 | case TokenIdDash: return PrefixOpNegation; |
| 1151 | 1166 | case TokenIdMinusPercent: return PrefixOpNegationWrap; |
| 1152 | 1167 | case TokenIdTilde: return PrefixOpBinNot; |
| 1153 | case TokenIdStar: return PrefixOpDereference; | |
| 1154 | 1168 | case TokenIdMaybe: return PrefixOpMaybe; |
| 1155 | 1169 | case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe; |
| 1156 | case TokenIdStarStar: return PrefixOpDereference; | |
| 1157 | 1170 | default: return PrefixOpInvalid; |
| 1158 | 1171 | } |
| 1159 | 1172 | } |
| ... | ... | @@ -1199,7 +1212,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) { |
| 1199 | 1212 | |
| 1200 | 1213 | /* |
| 1201 | 1214 | PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression |
| 1202 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" | |
| 1215 | PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" | |
| 1203 | 1216 | */ |
| 1204 | 1217 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1205 | 1218 | Token *token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -1222,15 +1235,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, |
| 1222 | 1235 | |
| 1223 | 1236 | AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); |
| 1224 | 1237 | 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 | } | |
| 1234 | 1238 | |
| 1235 | 1239 | AstNode *prefix_op_expr = ast_parse_error_set_expr(pc, token_index, true); |
| 1236 | 1240 | 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 |
| 3012 | 3016 | case NodeTypeFieldAccessExpr: |
| 3013 | 3017 | visit_field(&node->data.field_access_expr.struct_expr, visit, context); |
| 3014 | 3018 | break; |
| 3019 | case NodeTypePtrDeref: | |
| 3020 | visit_field(&node->data.ptr_deref_expr.target, visit, context); | |
| 3021 | break; | |
| 3015 | 3022 | case NodeTypeUse: |
| 3016 | 3023 | visit_field(&node->data.use.expr, visit, context); |
| 3017 | 3024 | break; |
src/translate_c.cpp+53-30| ... | ... | @@ -247,6 +247,12 @@ static AstNode *trans_create_node_field_access_str(Context *c, AstNode *containe |
| 247 | 247 | return trans_create_node_field_access(c, container, buf_create_from_str(field_name)); |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | static 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 | ||
| 250 | 256 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { |
| 251 | 257 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); |
| 252 | 258 | node->data.prefix_op_expr.prefix_op = op; |
| ... | ... | @@ -1412,8 +1418,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1412 | 1418 | AstNode *operation_type_cast = trans_c_cast(c, rhs_location, |
| 1413 | 1419 | stmt->getComputationLHSType(), |
| 1414 | 1420 | stmt->getLHS()->getType(), |
| 1415 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1416 | trans_create_node_symbol(c, tmp_var_name))); | |
| 1421 | trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name))); | |
| 1417 | 1422 | |
| 1418 | 1423 | // result_type(... >> u5(rhs)) |
| 1419 | 1424 | AstNode *result_type_cast = trans_c_cast(c, rhs_location, |
| ... | ... | @@ -1426,7 +1431,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1426 | 1431 | |
| 1427 | 1432 | // *_ref = ... |
| 1428 | 1433 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1429 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1434 | trans_create_node_ptr_deref(c, | |
| 1430 | 1435 | trans_create_node_symbol(c, tmp_var_name)), |
| 1431 | 1436 | BinOpTypeAssign, result_type_cast); |
| 1432 | 1437 | |
| ... | ... | @@ -1436,7 +1441,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result |
| 1436 | 1441 | // break :x *_ref |
| 1437 | 1442 | child_scope->node->data.block.statements.append( |
| 1438 | 1443 | trans_create_node_break(c, label_name, |
| 1439 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1444 | trans_create_node_ptr_deref(c, | |
| 1440 | 1445 | trans_create_node_symbol(c, tmp_var_name)))); |
| 1441 | 1446 | } |
| 1442 | 1447 | |
| ... | ... | @@ -1483,11 +1488,11 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1483 | 1488 | if (rhs == nullptr) return nullptr; |
| 1484 | 1489 | |
| 1485 | 1490 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1486 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1491 | trans_create_node_ptr_deref(c, | |
| 1487 | 1492 | trans_create_node_symbol(c, tmp_var_name)), |
| 1488 | 1493 | BinOpTypeAssign, |
| 1489 | 1494 | trans_create_node_bin_op(c, |
| 1490 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1495 | trans_create_node_ptr_deref(c, | |
| 1491 | 1496 | trans_create_node_symbol(c, tmp_var_name)), |
| 1492 | 1497 | bin_op, |
| 1493 | 1498 | rhs)); |
| ... | ... | @@ -1496,7 +1501,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, |
| 1496 | 1501 | // break :x *_ref |
| 1497 | 1502 | child_scope->node->data.block.statements.append( |
| 1498 | 1503 | trans_create_node_break(c, label_name, |
| 1499 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1504 | trans_create_node_ptr_deref(c, | |
| 1500 | 1505 | trans_create_node_symbol(c, tmp_var_name)))); |
| 1501 | 1506 | |
| 1502 | 1507 | return child_scope->node; |
| ... | ... | @@ -1817,13 +1822,13 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr |
| 1817 | 1822 | // const _tmp = *_ref; |
| 1818 | 1823 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| 1819 | 1824 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, |
| 1820 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1825 | trans_create_node_ptr_deref(c, | |
| 1821 | 1826 | trans_create_node_symbol(c, ref_var_name))); |
| 1822 | 1827 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| 1823 | 1828 | |
| 1824 | 1829 | // *_ref += 1; |
| 1825 | 1830 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1826 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1831 | trans_create_node_ptr_deref(c, | |
| 1827 | 1832 | trans_create_node_symbol(c, ref_var_name)), |
| 1828 | 1833 | assign_op, |
| 1829 | 1834 | trans_create_node_unsigned(c, 1)); |
| ... | ... | @@ -1871,14 +1876,14 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra |
| 1871 | 1876 | |
| 1872 | 1877 | // *_ref += 1; |
| 1873 | 1878 | AstNode *assign_statement = trans_create_node_bin_op(c, |
| 1874 | trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1879 | trans_create_node_ptr_deref(c, | |
| 1875 | 1880 | trans_create_node_symbol(c, ref_var_name)), |
| 1876 | 1881 | assign_op, |
| 1877 | 1882 | trans_create_node_unsigned(c, 1)); |
| 1878 | 1883 | child_scope->node->data.block.statements.append(assign_statement); |
| 1879 | 1884 | |
| 1880 | 1885 | // break :x *_ref |
| 1881 | AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference, | |
| 1886 | AstNode *deref_expr = trans_create_node_ptr_deref(c, | |
| 1882 | 1887 | trans_create_node_symbol(c, ref_var_name)); |
| 1883 | 1888 | child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, deref_expr)); |
| 1884 | 1889 | |
| ... | ... | @@ -1923,7 +1928,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 1923 | 1928 | if (is_fn_ptr) |
| 1924 | 1929 | return value_node; |
| 1925 | 1930 | AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node); |
| 1926 | return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped); | |
| 1931 | return trans_create_node_ptr_deref(c, unwrapped); | |
| 1927 | 1932 | } |
| 1928 | 1933 | case UO_Plus: |
| 1929 | 1934 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus"); |
| ... | ... | @@ -4443,27 +4448,45 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t |
| 4443 | 4448 | } |
| 4444 | 4449 | } |
| 4445 | 4450 | |
| 4446 | static PrefixOp ctok_to_prefix_op(CTok *token) { | |
| 4447 | switch (token->id) { | |
| 4448 | case CTokIdBang: return PrefixOpBoolNot; | |
| 4449 | case CTokIdMinus: return PrefixOpNegation; | |
| 4450 | case CTokIdTilde: return PrefixOpBinNot; | |
| 4451 | case CTokIdAsterisk: return PrefixOpDereference; | |
| 4452 | default: return PrefixOpInvalid; | |
| 4453 | } | |
| 4454 | } | |
| 4455 | 4451 | static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) { |
| 4456 | 4452 | CTok *op_tok = &ctok->tokens.at(*tok_i); |
| 4457 | PrefixOp prefix_op = ctok_to_prefix_op(op_tok); | |
| 4458 | if (prefix_op == PrefixOpInvalid) { | |
| 4459 | return parse_ctok_suffix_op_expr(c, ctok, tok_i); | |
| 4460 | } | |
| 4461 | *tok_i += 1; | |
| 4462 | 4453 | |
| 4463 | AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); | |
| 4464 | if (prefix_op_expr == nullptr) | |
| 4465 | return nullptr; | |
| 4466 | return trans_create_node_prefix_op(c, prefix_op, prefix_op_expr); | |
| 4454 | switch (op_tok->id) { | |
| 4455 | case CTokIdBang: | |
| 4456 | { | |
| 4457 | *tok_i += 1; | |
| 4458 | AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); | |
| 4459 | if (prefix_op_expr == nullptr) | |
| 4460 | return nullptr; | |
| 4461 | return trans_create_node_prefix_op(c, PrefixOpBoolNot, prefix_op_expr); | |
| 4462 | } | |
| 4463 | case CTokIdMinus: | |
| 4464 | { | |
| 4465 | *tok_i += 1; | |
| 4466 | AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); | |
| 4467 | if (prefix_op_expr == nullptr) | |
| 4468 | return nullptr; | |
| 4469 | return trans_create_node_prefix_op(c, PrefixOpNegation, prefix_op_expr); | |
| 4470 | } | |
| 4471 | case CTokIdTilde: | |
| 4472 | { | |
| 4473 | *tok_i += 1; | |
| 4474 | AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); | |
| 4475 | if (prefix_op_expr == nullptr) | |
| 4476 | return nullptr; | |
| 4477 | return trans_create_node_prefix_op(c, PrefixOpBinNot, prefix_op_expr); | |
| 4478 | } | |
| 4479 | case CTokIdAsterisk: | |
| 4480 | { | |
| 4481 | *tok_i += 1; | |
| 4482 | AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i); | |
| 4483 | if (prefix_op_expr == nullptr) | |
| 4484 | return nullptr; | |
| 4485 | return trans_create_node_ptr_deref(c, prefix_op_expr); | |
| 4486 | } | |
| 4487 | default: | |
| 4488 | return parse_ctok_suffix_op_expr(c, ctok, tok_i); | |
| 4489 | } | |
| 4467 | 4490 | } |
| 4468 | 4491 | |
| 4469 | 4492 | static 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 { |
| 8 | 8 | return AlignedArrayList(T, @alignOf(T)); |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ | |
| 11 | pub fn AlignedArrayList(comptime T: type, comptime A: u29) type { | |
| 12 | 12 | return struct { |
| 13 | 13 | const Self = this; |
| 14 | 14 | |
| ... | ... | @@ -21,7 +21,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ |
| 21 | 21 | |
| 22 | 22 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 23 | 23 | pub fn init(allocator: &Allocator) Self { |
| 24 | return Self { | |
| 24 | return Self{ | |
| 25 | 25 | .items = []align(A) T{}, |
| 26 | 26 | .len = 0, |
| 27 | 27 | .allocator = allocator, |
| ... | ... | @@ -52,7 +52,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ |
| 52 | 52 | /// allocated with `allocator`. |
| 53 | 53 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 54 | 54 | pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) Self { |
| 55 | return Self { | |
| 55 | return Self{ | |
| 56 | 56 | .items = slice, |
| 57 | 57 | .len = slice.len, |
| 58 | 58 | .allocator = allocator, |
| ... | ... | @@ -63,7 +63,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ |
| 63 | 63 | pub fn toOwnedSlice(self: &Self) []align(A) T { |
| 64 | 64 | const allocator = self.allocator; |
| 65 | 65 | const result = allocator.alignedShrink(T, A, self.items, self.len); |
| 66 | *self = init(allocator); | |
| 66 | self.* = init(allocator); | |
| 67 | 67 | return result; |
| 68 | 68 | } |
| 69 | 69 | |
| ... | ... | @@ -71,21 +71,21 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ |
| 71 | 71 | try l.ensureCapacity(l.len + 1); |
| 72 | 72 | l.len += 1; |
| 73 | 73 | |
| 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.*; | |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | pub fn insertSlice(l: &Self, n: usize, items: []align(A) const T) !void { |
| 79 | 79 | try l.ensureCapacity(l.len + items.len); |
| 80 | 80 | l.len += items.len; |
| 81 | 81 | |
| 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); | |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | pub fn append(l: &Self, item: &const T) !void { |
| 87 | 87 | const new_item_ptr = try l.addOne(); |
| 88 | *new_item_ptr = *item; | |
| 88 | new_item_ptr.* = item.*; | |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | 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{ |
| 128 | 128 | } |
| 129 | 129 | |
| 130 | 130 | pub fn popOrNull(self: &Self) ?T { |
| 131 | if (self.len == 0) | |
| 132 | return null; | |
| 131 | if (self.len == 0) return null; | |
| 133 | 132 | return self.pop(); |
| 134 | 133 | } |
| 135 | 134 | |
| ... | ... | @@ -160,13 +159,19 @@ test "basic ArrayList test" { |
| 160 | 159 | var list = ArrayList(i32).init(debug.global_allocator); |
| 161 | 160 | defer list.deinit(); |
| 162 | 161 | |
| 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 | } | |
| 166 | 168 | |
| 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 | } | |
| 170 | 175 | |
| 171 | 176 | for (list.toSlice()) |v, i| { |
| 172 | 177 | assert(v == i32(i + 1)); |
| ... | ... | @@ -179,14 +184,18 @@ test "basic ArrayList test" { |
| 179 | 184 | assert(list.pop() == 10); |
| 180 | 185 | assert(list.len == 9); |
| 181 | 186 | |
| 182 | list.appendSlice([]const i32 { 1, 2, 3 }) catch unreachable; | |
| 187 | list.appendSlice([]const i32{ | |
| 188 | 1, | |
| 189 | 2, | |
| 190 | 3, | |
| 191 | }) catch unreachable; | |
| 183 | 192 | assert(list.len == 12); |
| 184 | 193 | assert(list.pop() == 3); |
| 185 | 194 | assert(list.pop() == 2); |
| 186 | 195 | assert(list.pop() == 1); |
| 187 | 196 | assert(list.len == 9); |
| 188 | 197 | |
| 189 | list.appendSlice([]const i32 {}) catch unreachable; | |
| 198 | list.appendSlice([]const i32{}) catch unreachable; | |
| 190 | 199 | assert(list.len == 9); |
| 191 | 200 | } |
| 192 | 201 | |
| ... | ... | @@ -228,12 +237,15 @@ test "insert ArrayList test" { |
| 228 | 237 | assert(list.items[0] == 5); |
| 229 | 238 | assert(list.items[1] == 1); |
| 230 | 239 | |
| 231 | try list.insertSlice(1, []const i32 { 9, 8 }); | |
| 240 | try list.insertSlice(1, []const i32{ | |
| 241 | 9, | |
| 242 | 8, | |
| 243 | }); | |
| 232 | 244 | assert(list.items[0] == 5); |
| 233 | 245 | assert(list.items[1] == 9); |
| 234 | 246 | assert(list.items[2] == 8); |
| 235 | 247 | |
| 236 | const items = []const i32 { 1 }; | |
| 248 | const items = []const i32{1}; | |
| 237 | 249 | try list.insertSlice(0, items[0..0]); |
| 238 | 250 | assert(list.items[0] == 5); |
| 239 | 251 | } |
std/atomic/queue.zig+7-5| ... | ... | @@ -70,7 +70,7 @@ test "std.atomic.queue" { |
| 70 | 70 | |
| 71 | 71 | var queue: Queue(i32) = undefined; |
| 72 | 72 | queue.init(); |
| 73 | var context = Context { | |
| 73 | var context = Context{ | |
| 74 | 74 | .allocator = a, |
| 75 | 75 | .queue = &queue, |
| 76 | 76 | .put_sum = 0, |
| ... | ... | @@ -81,16 +81,18 @@ test "std.atomic.queue" { |
| 81 | 81 | |
| 82 | 82 | var putters: [put_thread_count]&std.os.Thread = undefined; |
| 83 | 83 | for (putters) |*t| { |
| 84 | *t = try std.os.spawnThread(&context, startPuts); | |
| 84 | t.* = try std.os.spawnThread(&context, startPuts); | |
| 85 | 85 | } |
| 86 | 86 | var getters: [put_thread_count]&std.os.Thread = undefined; |
| 87 | 87 | for (getters) |*t| { |
| 88 | *t = try std.os.spawnThread(&context, startGets); | |
| 88 | t.* = try std.os.spawnThread(&context, startGets); | |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | for (putters) |t| t.wait(); | |
| 91 | for (putters) |t| | |
| 92 | t.wait(); | |
| 92 | 93 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); |
| 93 | for (getters) |t| t.wait(); | |
| 94 | for (getters) |t| | |
| 95 | t.wait(); | |
| 94 | 96 | |
| 95 | 97 | std.debug.assert(context.put_sum == context.get_sum); |
| 96 | 98 | 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 { |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | 16 | pub fn init() Self { |
| 17 | return Self { | |
| 18 | .root = null, | |
| 19 | }; | |
| 17 | return Self{ .root = null }; | |
| 20 | 18 | } |
| 21 | 19 | |
| 22 | 20 | /// 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" { |
| 75 | 73 | var a = &fixed_buffer_allocator.allocator; |
| 76 | 74 | |
| 77 | 75 | var stack = Stack(i32).init(); |
| 78 | var context = Context { | |
| 76 | var context = Context{ | |
| 79 | 77 | .allocator = a, |
| 80 | 78 | .stack = &stack, |
| 81 | 79 | .put_sum = 0, |
| ... | ... | @@ -86,16 +84,18 @@ test "std.atomic.stack" { |
| 86 | 84 | |
| 87 | 85 | var putters: [put_thread_count]&std.os.Thread = undefined; |
| 88 | 86 | for (putters) |*t| { |
| 89 | *t = try std.os.spawnThread(&context, startPuts); | |
| 87 | t.* = try std.os.spawnThread(&context, startPuts); | |
| 90 | 88 | } |
| 91 | 89 | var getters: [put_thread_count]&std.os.Thread = undefined; |
| 92 | 90 | for (getters) |*t| { |
| 93 | *t = try std.os.spawnThread(&context, startGets); | |
| 91 | t.* = try std.os.spawnThread(&context, startGets); | |
| 94 | 92 | } |
| 95 | 93 | |
| 96 | for (putters) |t| t.wait(); | |
| 94 | for (putters) |t| | |
| 95 | t.wait(); | |
| 97 | 96 | _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); |
| 98 | for (getters) |t| t.wait(); | |
| 97 | for (getters) |t| | |
| 98 | t.wait(); | |
| 99 | 99 | |
| 100 | 100 | std.debug.assert(context.put_sum == context.get_sum); |
| 101 | 101 | std.debug.assert(context.get_count == puts_per_thread * put_thread_count); |
std/buffer.zig+3-8| ... | ... | @@ -31,9 +31,7 @@ pub const Buffer = struct { |
| 31 | 31 | /// * ::replaceContentsBuffer |
| 32 | 32 | /// * ::resize |
| 33 | 33 | pub fn initNull(allocator: &Allocator) Buffer { |
| 34 | return Buffer { | |
| 35 | .list = ArrayList(u8).init(allocator), | |
| 36 | }; | |
| 34 | return Buffer{ .list = ArrayList(u8).init(allocator) }; | |
| 37 | 35 | } |
| 38 | 36 | |
| 39 | 37 | /// Must deinitialize with deinit. |
| ... | ... | @@ -45,9 +43,7 @@ pub const Buffer = struct { |
| 45 | 43 | /// allocated with `allocator`. |
| 46 | 44 | /// Must deinitialize with deinit. |
| 47 | 45 | 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) }; | |
| 51 | 47 | self.list.append(0); |
| 52 | 48 | return self; |
| 53 | 49 | } |
| ... | ... | @@ -57,11 +53,10 @@ pub const Buffer = struct { |
| 57 | 53 | pub fn toOwnedSlice(self: &Buffer) []u8 { |
| 58 | 54 | const allocator = self.list.allocator; |
| 59 | 55 | const result = allocator.shrink(u8, self.list.items, self.len()); |
| 60 | *self = initNull(allocator); | |
| 56 | self.* = initNull(allocator); | |
| 61 | 57 | return result; |
| 62 | 58 | } |
| 63 | 59 | |
| 64 | ||
| 65 | 60 | pub fn deinit(self: &Buffer) void { |
| 66 | 61 | self.list.deinit(); |
| 67 | 62 | } |
std/build.zig+86-121| ... | ... | @@ -82,10 +82,8 @@ pub const Builder = struct { |
| 82 | 82 | description: []const u8, |
| 83 | 83 | }; |
| 84 | 84 | |
| 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{ | |
| 89 | 87 | .zig_exe = zig_exe, |
| 90 | 88 | .build_root = build_root, |
| 91 | 89 | .cache_root = os.path.relative(allocator, build_root, cache_root) catch unreachable, |
| ... | ... | @@ -112,12 +110,12 @@ pub const Builder = struct { |
| 112 | 110 | .lib_dir = undefined, |
| 113 | 111 | .exe_dir = undefined, |
| 114 | 112 | .installed_files = ArrayList([]const u8).init(allocator), |
| 115 | .uninstall_tls = TopLevelStep { | |
| 113 | .uninstall_tls = TopLevelStep{ | |
| 116 | 114 | .step = Step.init("uninstall", allocator, makeUninstall), |
| 117 | 115 | .description = "Remove build artifacts from prefix path", |
| 118 | 116 | }, |
| 119 | 117 | .have_uninstall_step = false, |
| 120 | .install_tls = TopLevelStep { | |
| 118 | .install_tls = TopLevelStep{ | |
| 121 | 119 | .step = Step.initNoOp("install", allocator), |
| 122 | 120 | .description = "Copy build artifacts to prefix path", |
| 123 | 121 | }, |
| ... | ... | @@ -151,9 +149,7 @@ pub const Builder = struct { |
| 151 | 149 | return LibExeObjStep.createObject(self, name, root_src); |
| 152 | 150 | } |
| 153 | 151 | |
| 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 { | |
| 157 | 153 | return LibExeObjStep.createSharedLibrary(self, name, root_src, ver); |
| 158 | 154 | } |
| 159 | 155 | |
| ... | ... | @@ -163,7 +159,7 @@ pub const Builder = struct { |
| 163 | 159 | |
| 164 | 160 | pub fn addTest(self: &Builder, root_src: []const u8) &TestStep { |
| 165 | 161 | 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); | |
| 167 | 163 | return test_step; |
| 168 | 164 | } |
| 169 | 165 | |
| ... | ... | @@ -190,33 +186,31 @@ pub const Builder = struct { |
| 190 | 186 | } |
| 191 | 187 | |
| 192 | 188 | /// ::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 { | |
| 196 | 190 | return CommandStep.create(self, cwd, env_map, argv); |
| 197 | 191 | } |
| 198 | 192 | |
| 199 | 193 | pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep { |
| 200 | 194 | 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); | |
| 202 | 196 | return write_file_step; |
| 203 | 197 | } |
| 204 | 198 | |
| 205 | 199 | pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep { |
| 206 | 200 | const data = self.fmt(format, args); |
| 207 | 201 | const log_step = self.allocator.create(LogStep) catch unreachable; |
| 208 | *log_step = LogStep.init(self, data); | |
| 202 | log_step.* = LogStep.init(self, data); | |
| 209 | 203 | return log_step; |
| 210 | 204 | } |
| 211 | 205 | |
| 212 | 206 | pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep { |
| 213 | 207 | 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); | |
| 215 | 209 | return remove_dir_step; |
| 216 | 210 | } |
| 217 | 211 | |
| 218 | 212 | pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version { |
| 219 | return Version { | |
| 213 | return Version{ | |
| 220 | 214 | .major = major, |
| 221 | 215 | .minor = minor, |
| 222 | 216 | .patch = patch, |
| ... | ... | @@ -254,8 +248,7 @@ pub const Builder = struct { |
| 254 | 248 | } |
| 255 | 249 | |
| 256 | 250 | 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; | |
| 259 | 252 | |
| 260 | 253 | self.top_level_steps.append(&self.install_tls) catch unreachable; |
| 261 | 254 | self.have_install_step = true; |
| ... | ... | @@ -263,8 +256,7 @@ pub const Builder = struct { |
| 263 | 256 | } |
| 264 | 257 | |
| 265 | 258 | 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; | |
| 268 | 260 | |
| 269 | 261 | self.top_level_steps.append(&self.uninstall_tls) catch unreachable; |
| 270 | 262 | self.have_uninstall_step = true; |
| ... | ... | @@ -360,7 +352,7 @@ pub const Builder = struct { |
| 360 | 352 | |
| 361 | 353 | pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T { |
| 362 | 354 | const type_id = comptime typeToEnum(T); |
| 363 | const available_option = AvailableOption { | |
| 355 | const available_option = AvailableOption{ | |
| 364 | 356 | .name = name, |
| 365 | 357 | .type_id = type_id, |
| 366 | 358 | .description = description, |
| ... | ... | @@ -413,7 +405,7 @@ pub const Builder = struct { |
| 413 | 405 | |
| 414 | 406 | pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step { |
| 415 | 407 | const step_info = self.allocator.create(TopLevelStep) catch unreachable; |
| 416 | *step_info = TopLevelStep { | |
| 408 | step_info.* = TopLevelStep{ | |
| 417 | 409 | .step = Step.initNoOp(name, self.allocator), |
| 418 | 410 | .description = description, |
| 419 | 411 | }; |
| ... | ... | @@ -446,9 +438,9 @@ pub const Builder = struct { |
| 446 | 438 | } |
| 447 | 439 | |
| 448 | 440 | 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{ | |
| 450 | 442 | .name = name, |
| 451 | .value = UserValue { .Scalar = value }, | |
| 443 | .value = UserValue{ .Scalar = value }, | |
| 452 | 444 | .used = false, |
| 453 | 445 | }) catch unreachable) |*prev_value| { |
| 454 | 446 | // option already exists |
| ... | ... | @@ -458,18 +450,18 @@ pub const Builder = struct { |
| 458 | 450 | var list = ArrayList([]const u8).init(self.allocator); |
| 459 | 451 | list.append(s) catch unreachable; |
| 460 | 452 | list.append(value) catch unreachable; |
| 461 | _ = self.user_input_options.put(name, UserInputOption { | |
| 453 | _ = self.user_input_options.put(name, UserInputOption{ | |
| 462 | 454 | .name = name, |
| 463 | .value = UserValue { .List = list }, | |
| 455 | .value = UserValue{ .List = list }, | |
| 464 | 456 | .used = false, |
| 465 | 457 | }) catch unreachable; |
| 466 | 458 | }, |
| 467 | 459 | UserValue.List => |*list| { |
| 468 | 460 | // append to the list |
| 469 | 461 | list.append(value) catch unreachable; |
| 470 | _ = self.user_input_options.put(name, UserInputOption { | |
| 462 | _ = self.user_input_options.put(name, UserInputOption{ | |
| 471 | 463 | .name = name, |
| 472 | .value = UserValue { .List = *list }, | |
| 464 | .value = UserValue{ .List = list.* }, | |
| 473 | 465 | .used = false, |
| 474 | 466 | }) catch unreachable; |
| 475 | 467 | }, |
| ... | ... | @@ -483,9 +475,9 @@ pub const Builder = struct { |
| 483 | 475 | } |
| 484 | 476 | |
| 485 | 477 | 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{ | |
| 487 | 479 | .name = name, |
| 488 | .value = UserValue {.Flag = {} }, | |
| 480 | .value = UserValue{ .Flag = {} }, | |
| 489 | 481 | .used = false, |
| 490 | 482 | }) catch unreachable) |*prev_value| { |
| 491 | 483 | switch (prev_value.value) { |
| ... | ... | @@ -556,9 +548,7 @@ pub const Builder = struct { |
| 556 | 548 | warn("\n"); |
| 557 | 549 | } |
| 558 | 550 | |
| 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 { | |
| 562 | 552 | if (self.verbose) { |
| 563 | 553 | printCmd(cwd, argv); |
| 564 | 554 | } |
| ... | ... | @@ -617,7 +607,7 @@ pub const Builder = struct { |
| 617 | 607 | self.pushInstalledFile(full_dest_path); |
| 618 | 608 | |
| 619 | 609 | 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); | |
| 621 | 611 | return install_step; |
| 622 | 612 | } |
| 623 | 613 | |
| ... | ... | @@ -659,25 +649,23 @@ pub const Builder = struct { |
| 659 | 649 | if (builtin.environ == builtin.Environ.msvc) { |
| 660 | 650 | return "cl.exe"; |
| 661 | 651 | } else { |
| 662 | return os.getEnvVarOwned(self.allocator, "CC") catch |err| | |
| 652 | return os.getEnvVarOwned(self.allocator, "CC") catch |err| | |
| 663 | 653 | if (err == error.EnvironmentVariableNotFound) |
| 664 | 654 | ([]const u8)("cc") |
| 665 | 655 | else |
| 666 | debug.panic("Unable to get environment variable: {}", err) | |
| 667 | ; | |
| 656 | debug.panic("Unable to get environment variable: {}", err); | |
| 668 | 657 | } |
| 669 | 658 | } |
| 670 | 659 | |
| 671 | 660 | pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 { |
| 672 | 661 | // TODO report error for ambiguous situations |
| 673 | const exe_extension = (Target { .Native = {}}).exeFileExt(); | |
| 662 | const exe_extension = (Target{ .Native = {} }).exeFileExt(); | |
| 674 | 663 | for (self.search_prefixes.toSliceConst()) |search_prefix| { |
| 675 | 664 | for (names) |name| { |
| 676 | 665 | if (os.path.isAbsolute(name)) { |
| 677 | 666 | return name; |
| 678 | 667 | } |
| 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)); | |
| 681 | 669 | if (os.path.real(self.allocator, full_path)) |real_path| { |
| 682 | 670 | return real_path; |
| 683 | 671 | } else |_| { |
| ... | ... | @@ -761,7 +749,7 @@ pub const Target = union(enum) { |
| 761 | 749 | Cross: CrossTarget, |
| 762 | 750 | |
| 763 | 751 | pub fn oFileExt(self: &const Target) []const u8 { |
| 764 | const environ = switch (*self) { | |
| 752 | const environ = switch (self.*) { | |
| 765 | 753 | Target.Native => builtin.environ, |
| 766 | 754 | Target.Cross => |t| t.environ, |
| 767 | 755 | }; |
| ... | ... | @@ -786,7 +774,7 @@ pub const Target = union(enum) { |
| 786 | 774 | } |
| 787 | 775 | |
| 788 | 776 | pub fn getOs(self: &const Target) builtin.Os { |
| 789 | return switch (*self) { | |
| 777 | return switch (self.*) { | |
| 790 | 778 | Target.Native => builtin.os, |
| 791 | 779 | Target.Cross => |t| t.os, |
| 792 | 780 | }; |
| ... | ... | @@ -794,7 +782,8 @@ pub const Target = union(enum) { |
| 794 | 782 | |
| 795 | 783 | pub fn isDarwin(self: &const Target) bool { |
| 796 | 784 | return switch (self.getOs()) { |
| 797 | builtin.Os.ios, builtin.Os.macosx => true, | |
| 785 | builtin.Os.ios, | |
| 786 | builtin.Os.macosx => true, | |
| 798 | 787 | else => false, |
| 799 | 788 | }; |
| 800 | 789 | } |
| ... | ... | @@ -860,61 +849,57 @@ pub const LibExeObjStep = struct { |
| 860 | 849 | Obj, |
| 861 | 850 | }; |
| 862 | 851 | |
| 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 { | |
| 866 | 853 | 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); | |
| 868 | 855 | return self; |
| 869 | 856 | } |
| 870 | 857 | |
| 871 | 858 | pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep { |
| 872 | 859 | 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); | |
| 874 | 861 | return self; |
| 875 | 862 | } |
| 876 | 863 | |
| 877 | 864 | pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { |
| 878 | 865 | 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)); | |
| 880 | 867 | return self; |
| 881 | 868 | } |
| 882 | 869 | |
| 883 | 870 | pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep { |
| 884 | 871 | 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); | |
| 886 | 873 | return self; |
| 887 | 874 | } |
| 888 | 875 | |
| 889 | 876 | pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep { |
| 890 | 877 | 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)); | |
| 892 | 879 | return self; |
| 893 | 880 | } |
| 894 | 881 | |
| 895 | 882 | pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep { |
| 896 | 883 | 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); | |
| 898 | 885 | self.object_src = src; |
| 899 | 886 | return self; |
| 900 | 887 | } |
| 901 | 888 | |
| 902 | 889 | pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { |
| 903 | 890 | 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)); | |
| 905 | 892 | return self; |
| 906 | 893 | } |
| 907 | 894 | |
| 908 | 895 | pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep { |
| 909 | 896 | 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); | |
| 911 | 898 | return self; |
| 912 | 899 | } |
| 913 | 900 | |
| 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{ | |
| 918 | 903 | .strip = false, |
| 919 | 904 | .builder = builder, |
| 920 | 905 | .verbose_link = false, |
| ... | ... | @@ -930,7 +915,7 @@ pub const LibExeObjStep = struct { |
| 930 | 915 | .step = Step.init(name, builder.allocator, make), |
| 931 | 916 | .output_path = null, |
| 932 | 917 | .output_h_path = null, |
| 933 | .version = *ver, | |
| 918 | .version = ver.*, | |
| 934 | 919 | .out_filename = undefined, |
| 935 | 920 | .out_h_filename = builder.fmt("{}.h", name), |
| 936 | 921 | .major_only_filename = undefined, |
| ... | ... | @@ -953,11 +938,11 @@ pub const LibExeObjStep = struct { |
| 953 | 938 | } |
| 954 | 939 | |
| 955 | 940 | fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep { |
| 956 | var self = LibExeObjStep { | |
| 941 | var self = LibExeObjStep{ | |
| 957 | 942 | .builder = builder, |
| 958 | 943 | .name = name, |
| 959 | 944 | .kind = kind, |
| 960 | .version = *version, | |
| 945 | .version = version.*, | |
| 961 | 946 | .static = static, |
| 962 | 947 | .target = Target.Native, |
| 963 | 948 | .cflags = ArrayList([]const u8).init(builder.allocator), |
| ... | ... | @@ -1005,9 +990,9 @@ pub const LibExeObjStep = struct { |
| 1005 | 990 | self.out_filename = self.builder.fmt("lib{}.a", self.name); |
| 1006 | 991 | } else { |
| 1007 | 992 | 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); | |
| 1011 | 996 | self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major); |
| 1012 | 997 | self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name); |
| 1013 | 998 | }, |
| ... | ... | @@ -1015,8 +1000,7 @@ pub const LibExeObjStep = struct { |
| 1015 | 1000 | self.out_filename = self.builder.fmt("{}.dll", self.name); |
| 1016 | 1001 | }, |
| 1017 | 1002 | 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); | |
| 1020 | 1004 | self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major); |
| 1021 | 1005 | self.name_only_filename = self.builder.fmt("lib{}.so", self.name); |
| 1022 | 1006 | }, |
| ... | ... | @@ -1026,16 +1010,12 @@ pub const LibExeObjStep = struct { |
| 1026 | 1010 | } |
| 1027 | 1011 | } |
| 1028 | 1012 | |
| 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 | } }; | |
| 1039 | 1019 | self.computeOutFileNames(); |
| 1040 | 1020 | } |
| 1041 | 1021 | |
| ... | ... | @@ -1159,7 +1139,7 @@ pub const LibExeObjStep = struct { |
| 1159 | 1139 | pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { |
| 1160 | 1140 | assert(self.is_zig); |
| 1161 | 1141 | |
| 1162 | self.packages.append(Pkg { | |
| 1142 | self.packages.append(Pkg{ | |
| 1163 | 1143 | .name = name, |
| 1164 | 1144 | .path = pkg_index_path, |
| 1165 | 1145 | }) catch unreachable; |
| ... | ... | @@ -1343,8 +1323,7 @@ pub const LibExeObjStep = struct { |
| 1343 | 1323 | try builder.spawnChild(zig_args.toSliceConst()); |
| 1344 | 1324 | |
| 1345 | 1325 | 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); | |
| 1348 | 1327 | } |
| 1349 | 1328 | } |
| 1350 | 1329 | |
| ... | ... | @@ -1373,7 +1352,8 @@ pub const LibExeObjStep = struct { |
| 1373 | 1352 | args.append("ssp-buffer-size=4") catch unreachable; |
| 1374 | 1353 | } |
| 1375 | 1354 | }, |
| 1376 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => { | |
| 1355 | builtin.Mode.ReleaseFast, | |
| 1356 | builtin.Mode.ReleaseSmall => { | |
| 1377 | 1357 | args.append("-O2") catch unreachable; |
| 1378 | 1358 | args.append("-fno-stack-protector") catch unreachable; |
| 1379 | 1359 | }, |
| ... | ... | @@ -1505,8 +1485,7 @@ pub const LibExeObjStep = struct { |
| 1505 | 1485 | } |
| 1506 | 1486 | |
| 1507 | 1487 | 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); | |
| 1510 | 1489 | defer builder.allocator.free(rpath_arg); |
| 1511 | 1490 | cc_args.append(rpath_arg) catch unreachable; |
| 1512 | 1491 | |
| ... | ... | @@ -1535,8 +1514,7 @@ pub const LibExeObjStep = struct { |
| 1535 | 1514 | try builder.spawnChild(cc_args.toSliceConst()); |
| 1536 | 1515 | |
| 1537 | 1516 | 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); | |
| 1540 | 1518 | } |
| 1541 | 1519 | } |
| 1542 | 1520 | }, |
| ... | ... | @@ -1581,8 +1559,7 @@ pub const LibExeObjStep = struct { |
| 1581 | 1559 | cc_args.append("-o") catch unreachable; |
| 1582 | 1560 | cc_args.append(output_path) catch unreachable; |
| 1583 | 1561 | |
| 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); | |
| 1586 | 1563 | defer builder.allocator.free(rpath_arg); |
| 1587 | 1564 | cc_args.append(rpath_arg) catch unreachable; |
| 1588 | 1565 | |
| ... | ... | @@ -1635,7 +1612,7 @@ pub const TestStep = struct { |
| 1635 | 1612 | |
| 1636 | 1613 | pub fn init(builder: &Builder, root_src: []const u8) TestStep { |
| 1637 | 1614 | const step_name = builder.fmt("test {}", root_src); |
| 1638 | return TestStep { | |
| 1615 | return TestStep{ | |
| 1639 | 1616 | .step = Step.init(step_name, builder.allocator, make), |
| 1640 | 1617 | .builder = builder, |
| 1641 | 1618 | .root_src = root_src, |
| ... | ... | @@ -1644,7 +1621,7 @@ pub const TestStep = struct { |
| 1644 | 1621 | .name_prefix = "", |
| 1645 | 1622 | .filter = null, |
| 1646 | 1623 | .link_libs = BufSet.init(builder.allocator), |
| 1647 | .target = Target { .Native = {} }, | |
| 1624 | .target = Target{ .Native = {} }, | |
| 1648 | 1625 | .exec_cmd_args = null, |
| 1649 | 1626 | .include_dirs = ArrayList([]const u8).init(builder.allocator), |
| 1650 | 1627 | }; |
| ... | ... | @@ -1674,16 +1651,12 @@ pub const TestStep = struct { |
| 1674 | 1651 | self.filter = text; |
| 1675 | 1652 | } |
| 1676 | 1653 | |
| 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 | } }; | |
| 1687 | 1660 | } |
| 1688 | 1661 | |
| 1689 | 1662 | pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void { |
| ... | ... | @@ -1789,11 +1762,9 @@ pub const CommandStep = struct { |
| 1789 | 1762 | env_map: &const BufMap, |
| 1790 | 1763 | |
| 1791 | 1764 | /// ::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 { | |
| 1795 | 1766 | const self = builder.allocator.create(CommandStep) catch unreachable; |
| 1796 | *self = CommandStep { | |
| 1767 | self.* = CommandStep{ | |
| 1797 | 1768 | .builder = builder, |
| 1798 | 1769 | .step = Step.init(argv[0], builder.allocator, make), |
| 1799 | 1770 | .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable, |
| ... | ... | @@ -1828,7 +1799,7 @@ const InstallArtifactStep = struct { |
| 1828 | 1799 | LibExeObjStep.Kind.Exe => builder.exe_dir, |
| 1829 | 1800 | LibExeObjStep.Kind.Lib => builder.lib_dir, |
| 1830 | 1801 | }; |
| 1831 | *self = Self { | |
| 1802 | self.* = Self{ | |
| 1832 | 1803 | .builder = builder, |
| 1833 | 1804 | .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make), |
| 1834 | 1805 | .artifact = artifact, |
| ... | ... | @@ -1837,10 +1808,8 @@ const InstallArtifactStep = struct { |
| 1837 | 1808 | self.step.dependOn(&artifact.step); |
| 1838 | 1809 | builder.pushInstalledFile(self.dest_file); |
| 1839 | 1810 | 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); | |
| 1844 | 1813 | } |
| 1845 | 1814 | return self; |
| 1846 | 1815 | } |
| ... | ... | @@ -1859,8 +1828,7 @@ const InstallArtifactStep = struct { |
| 1859 | 1828 | }; |
| 1860 | 1829 | try builder.copyFileMode(self.artifact.getOutputPath(), self.dest_file, mode); |
| 1861 | 1830 | 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); | |
| 1864 | 1832 | } |
| 1865 | 1833 | } |
| 1866 | 1834 | }; |
| ... | ... | @@ -1872,7 +1840,7 @@ pub const InstallFileStep = struct { |
| 1872 | 1840 | dest_path: []const u8, |
| 1873 | 1841 | |
| 1874 | 1842 | pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep { |
| 1875 | return InstallFileStep { | |
| 1843 | return InstallFileStep{ | |
| 1876 | 1844 | .builder = builder, |
| 1877 | 1845 | .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make), |
| 1878 | 1846 | .src_path = src_path, |
| ... | ... | @@ -1893,7 +1861,7 @@ pub const WriteFileStep = struct { |
| 1893 | 1861 | data: []const u8, |
| 1894 | 1862 | |
| 1895 | 1863 | pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep { |
| 1896 | return WriteFileStep { | |
| 1864 | return WriteFileStep{ | |
| 1897 | 1865 | .builder = builder, |
| 1898 | 1866 | .step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make), |
| 1899 | 1867 | .file_path = file_path, |
| ... | ... | @@ -1922,7 +1890,7 @@ pub const LogStep = struct { |
| 1922 | 1890 | data: []const u8, |
| 1923 | 1891 | |
| 1924 | 1892 | pub fn init(builder: &Builder, data: []const u8) LogStep { |
| 1925 | return LogStep { | |
| 1893 | return LogStep{ | |
| 1926 | 1894 | .builder = builder, |
| 1927 | 1895 | .step = Step.init(builder.fmt("log {}", data), builder.allocator, make), |
| 1928 | 1896 | .data = data, |
| ... | ... | @@ -1941,7 +1909,7 @@ pub const RemoveDirStep = struct { |
| 1941 | 1909 | dir_path: []const u8, |
| 1942 | 1910 | |
| 1943 | 1911 | pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep { |
| 1944 | return RemoveDirStep { | |
| 1912 | return RemoveDirStep{ | |
| 1945 | 1913 | .builder = builder, |
| 1946 | 1914 | .step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make), |
| 1947 | 1915 | .dir_path = dir_path, |
| ... | ... | @@ -1966,8 +1934,8 @@ pub const Step = struct { |
| 1966 | 1934 | loop_flag: bool, |
| 1967 | 1935 | done_flag: bool, |
| 1968 | 1936 | |
| 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{ | |
| 1971 | 1939 | .name = name, |
| 1972 | 1940 | .makeFn = makeFn, |
| 1973 | 1941 | .dependencies = ArrayList(&Step).init(allocator), |
| ... | ... | @@ -1980,8 +1948,7 @@ pub const Step = struct { |
| 1980 | 1948 | } |
| 1981 | 1949 | |
| 1982 | 1950 | pub fn make(self: &Step) !void { |
| 1983 | if (self.done_flag) | |
| 1984 | return; | |
| 1951 | if (self.done_flag) return; | |
| 1985 | 1952 | |
| 1986 | 1953 | try self.makeFn(self); |
| 1987 | 1954 | self.done_flag = true; |
| ... | ... | @@ -1994,9 +1961,7 @@ pub const Step = struct { |
| 1994 | 1961 | fn makeNoOp(self: &Step) error!void {} |
| 1995 | 1962 | }; |
| 1996 | 1963 | |
| 1997 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, | |
| 1998 | filename_name_only: []const u8) !void | |
| 1999 | { | |
| 1964 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void { | |
| 2000 | 1965 | const out_dir = os.path.dirname(output_path); |
| 2001 | 1966 | const out_basename = os.path.basename(output_path); |
| 2002 | 1967 | // 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"); |
| 6 | 6 | const htest = @import("test.zig"); |
| 7 | 7 | |
| 8 | 8 | const 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, | |
| 10 | 15 | }; |
| 11 | 16 | |
| 12 | 17 | fn 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 | }; | |
| 14 | 26 | } |
| 15 | 27 | |
| 16 | 28 | ///////////////////// |
| ... | ... | @@ -19,145 +31,153 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { |
| 19 | 31 | pub const Blake2s224 = Blake2s(224); |
| 20 | 32 | pub const Blake2s256 = Blake2s(256); |
| 21 | 33 | |
| 22 | fn Blake2s(comptime out_len: usize) type { return struct { | |
| 23 | const Self = this; | |
| 24 | const block_size = 64; | |
| 25 | const digest_size = out_len / 8; | |
| 34 | fn 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 | }; | |
| 26 | 50 | |
| 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 | }; | |
| 31 | 63 | |
| 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, | |
| 44 | 69 | |
| 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; | |
| 84 | 76 | } |
| 85 | 77 | |
| 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; | |
| 90 | 85 | } |
| 91 | 86 | |
| 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 | } | |
| 96 | 92 | |
| 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; | |
| 99 | 95 | |
| 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 | } | |
| 103 | 104 | |
| 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 | } | |
| 105 | 110 | |
| 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); | |
| 108 | 114 | } |
| 109 | } | |
| 110 | 115 | |
| 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); | |
| 113 | 118 | |
| 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); | |
| 116 | 122 | |
| 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]; | |
| 120 | 124 | |
| 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 | } | |
| 125 | 128 | } |
| 126 | 129 | |
| 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); | |
| 141 | 132 | |
| 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]); | |
| 153 | 138 | } |
| 154 | } | |
| 155 | 139 | |
| 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 | } | |
| 158 | 178 | } |
| 159 | } | |
| 160 | };} | |
| 179 | }; | |
| 180 | } | |
| 161 | 181 | |
| 162 | 182 | test "blake2s224 single" { |
| 163 | 183 | const h1 = "1fa1291e65248b37b3433475b2a0dd63d54a11ecc4e3e034e7bc1ef4"; |
| ... | ... | @@ -230,7 +250,7 @@ test "blake2s256 streaming" { |
| 230 | 250 | } |
| 231 | 251 | |
| 232 | 252 | test "blake2s256 aligned final" { |
| 233 | var block = []u8 {0} ** Blake2s256.block_size; | |
| 253 | var block = []u8{0} ** Blake2s256.block_size; | |
| 234 | 254 | var out: [Blake2s256.digest_size]u8 = undefined; |
| 235 | 255 | |
| 236 | 256 | var h = Blake2s256.init(); |
| ... | ... | @@ -238,154 +258,363 @@ test "blake2s256 aligned final" { |
| 238 | 258 | h.final(out[0..]); |
| 239 | 259 | } |
| 240 | 260 | |
| 241 | ||
| 242 | 261 | ///////////////////// |
| 243 | 262 | // Blake2b |
| 244 | 263 | |
| 245 | 264 | pub const Blake2b384 = Blake2b(384); |
| 246 | 265 | pub const Blake2b512 = Blake2b(512); |
| 247 | 266 | |
| 248 | fn Blake2b(comptime out_len: usize) type { return struct { | |
| 249 | const Self = this; | |
| 250 | const block_size = 128; | |
| 251 | const digest_size = out_len / 8; | |
| 267 | fn 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 | }; | |
| 252 | 283 | |
| 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 | }; | |
| 259 | 502 | |
| 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, | |
| 274 | 508 | |
| 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; | |
| 313 | 523 | d.buf_len = 0; |
| 314 | 524 | } |
| 315 | 525 | |
| 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); | |
| 320 | 530 | } |
| 321 | 531 | |
| 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; | |
| 326 | 534 | |
| 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 | } | |
| 331 | 543 | |
| 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 | } | |
| 333 | 549 | |
| 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); | |
| 336 | 553 | } |
| 337 | } | |
| 338 | 554 | |
| 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); | |
| 341 | 559 | |
| 342 | var m: [16]u64 = undefined; | |
| 343 | var v: [16]u64 = undefined; | |
| 560 | const rr = d.h[0..out_len / 64]; | |
| 344 | 561 | |
| 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 | } | |
| 347 | 565 | } |
| 348 | 566 | |
| 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); | |
| 354 | 569 | |
| 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; | |
| 369 | 572 | |
| 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]; | |
| 381 | 581 | } |
| 382 | } | |
| 383 | 582 | |
| 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 | } | |
| 386 | 615 | } |
| 387 | } | |
| 388 | };} | |
| 616 | }; | |
| 617 | } | |
| 389 | 618 | |
| 390 | 619 | test "blake2b384 single" { |
| 391 | 620 | const h1 = "b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100"; |
| ... | ... | @@ -458,7 +687,7 @@ test "blake2b512 streaming" { |
| 458 | 687 | } |
| 459 | 688 | |
| 460 | 689 | test "blake2b512 aligned final" { |
| 461 | var block = []u8 {0} ** Blake2b512.block_size; | |
| 690 | var block = []u8{0} ** Blake2b512.block_size; | |
| 462 | 691 | var out: [Blake2b512.digest_size]u8 = undefined; |
| 463 | 692 | |
| 464 | 693 | var h = Blake2b512.init(); |
std/crypto/hmac.zig+2-2| ... | ... | @@ -29,12 +29,12 @@ pub fn Hmac(comptime H: type) type { |
| 29 | 29 | |
| 30 | 30 | var o_key_pad: [H.block_size]u8 = undefined; |
| 31 | 31 | for (o_key_pad) |*b, i| { |
| 32 | *b = scratch[i] ^ 0x5c; | |
| 32 | b.* = scratch[i] ^ 0x5c; | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | var i_key_pad: [H.block_size]u8 = undefined; |
| 36 | 36 | for (i_key_pad) |*b, i| { |
| 37 | *b = scratch[i] ^ 0x36; | |
| 37 | b.* = scratch[i] ^ 0x36; | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | // 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); |
| 10 | 10 | pub const Sha3_384 = Keccak(384, 0x06); |
| 11 | 11 | pub const Sha3_512 = Keccak(512, 0x06); |
| 12 | 12 | |
| 13 | fn 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 | } | |
| 13 | fn 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 | } | |
| 27 | 28 | |
| 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 | } | |
| 33 | 34 | |
| 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 | } | |
| 39 | 40 | |
| 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; | |
| 45 | 46 | |
| 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]; | |
| 50 | 51 | |
| 51 | keccak_f(1600, d.s[0..]); | |
| 52 | keccak_f(1600, d.s[0..]); | |
| 52 | 53 | |
| 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 | } | |
| 58 | 59 | |
| 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]; | |
| 61 | 62 | |
| 62 | d.offset = offset + len; | |
| 63 | } | |
| 63 | d.offset = offset + len; | |
| 64 | } | |
| 64 | 65 | |
| 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; | |
| 69 | 70 | |
| 70 | keccak_f(1600, d.s[0..]); | |
| 71 | keccak_f(1600, d.s[0..]); | |
| 71 | 72 | |
| 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; | |
| 75 | 76 | |
| 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]); | |
| 81 | 85 | } |
| 86 | }; | |
| 87 | } | |
| 82 | 88 | |
| 83 | mem.copy(u8, out[op..], d.s[0..len]); | |
| 84 | } | |
| 85 | };} | |
| 86 | ||
| 87 | const 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, | |
| 89 | const 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, | |
| 94 | 114 | }; |
| 95 | 115 | |
| 96 | const 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 | |
| 116 | const 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, | |
| 100 | 141 | }; |
| 101 | 142 | |
| 102 | const 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 | |
| 143 | const 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, | |
| 106 | 168 | }; |
| 107 | 169 | |
| 108 | const M5 = []const usize { | |
| 109 | 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 | |
| 170 | const M5 = []const usize{ | |
| 171 | 0, | |
| 172 | 1, | |
| 173 | 2, | |
| 174 | 3, | |
| 175 | 4, | |
| 176 | 0, | |
| 177 | 1, | |
| 178 | 2, | |
| 179 | 3, | |
| 180 | 4, | |
| 110 | 181 | }; |
| 111 | 182 | |
| 112 | 183 | fn keccak_f(comptime F: usize, d: []u8) void { |
| 113 | 184 | debug.assert(d.len == F / 8); |
| 114 | 185 | |
| 115 | 186 | 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 | }; | |
| 117 | 190 | |
| 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; | |
| 121 | 194 | |
| 122 | 195 | 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]); | |
| 124 | 197 | } |
| 125 | 198 | |
| 126 | 199 | comptime var x: usize = 0; |
| 127 | 200 | comptime var y: usize = 0; |
| 128 | 201 | for (RC[0..no_rounds]) |round| { |
| 129 | 202 | // 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]; | |
| 132 | 206 | } |
| 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]; | |
| 137 | 213 | } |
| 138 | 214 | } |
| 139 | 215 | |
| 140 | 216 | // rho+pi |
| 141 | 217 | t[0] = s[1]; |
| 142 | x = 0; inline while (x < 24) : (x += 1) { | |
| 218 | x = 0; | |
| 219 | inline while (x < 24) : (x += 1) { | |
| 143 | 220 | c[0] = s[PIL[x]]; |
| 144 | 221 | s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]); |
| 145 | 222 | t[0] = c[0]; |
| 146 | 223 | } |
| 147 | 224 | |
| 148 | 225 | // 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]; | |
| 152 | 231 | } |
| 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]]); | |
| 155 | 235 | } |
| 156 | 236 | } |
| 157 | 237 | |
| ... | ... | @@ -160,11 +240,10 @@ fn keccak_f(comptime F: usize, d: []u8) void { |
| 160 | 240 | } |
| 161 | 241 | |
| 162 | 242 | 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); | |
| 164 | 244 | } |
| 165 | 245 | } |
| 166 | 246 | |
| 167 | ||
| 168 | 247 | test "sha3-224 single" { |
| 169 | 248 | htest.assertEqualHash(Sha3_224, "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", ""); |
| 170 | 249 | htest.assertEqualHash(Sha3_224, "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf", "abc"); |
| ... | ... | @@ -192,7 +271,7 @@ test "sha3-224 streaming" { |
| 192 | 271 | } |
| 193 | 272 | |
| 194 | 273 | test "sha3-256 single" { |
| 195 | htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" , ""); | |
| 274 | htest.assertEqualHash(Sha3_256, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", ""); | |
| 196 | 275 | htest.assertEqualHash(Sha3_256, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532", "abc"); |
| 197 | 276 | htest.assertEqualHash(Sha3_256, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 198 | 277 | } |
| ... | ... | @@ -218,7 +297,7 @@ test "sha3-256 streaming" { |
| 218 | 297 | } |
| 219 | 298 | |
| 220 | 299 | test "sha3-256 aligned final" { |
| 221 | var block = []u8 {0} ** Sha3_256.block_size; | |
| 300 | var block = []u8{0} ** Sha3_256.block_size; | |
| 222 | 301 | var out: [Sha3_256.digest_size]u8 = undefined; |
| 223 | 302 | |
| 224 | 303 | var h = Sha3_256.init(); |
| ... | ... | @@ -228,7 +307,7 @@ test "sha3-256 aligned final" { |
| 228 | 307 | |
| 229 | 308 | test "sha3-384 single" { |
| 230 | 309 | const h1 = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; |
| 231 | htest.assertEqualHash(Sha3_384, h1 , ""); | |
| 310 | htest.assertEqualHash(Sha3_384, h1, ""); | |
| 232 | 311 | const h2 = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"; |
| 233 | 312 | htest.assertEqualHash(Sha3_384, h2, "abc"); |
| 234 | 313 | const h3 = "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"; |
| ... | ... | @@ -259,7 +338,7 @@ test "sha3-384 streaming" { |
| 259 | 338 | |
| 260 | 339 | test "sha3-512 single" { |
| 261 | 340 | const h1 = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; |
| 262 | htest.assertEqualHash(Sha3_512, h1 , ""); | |
| 341 | htest.assertEqualHash(Sha3_512, h1, ""); | |
| 263 | 342 | const h2 = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"; |
| 264 | 343 | htest.assertEqualHash(Sha3_512, h2, "abc"); |
| 265 | 344 | const h3 = "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"; |
| ... | ... | @@ -289,7 +368,7 @@ test "sha3-512 streaming" { |
| 289 | 368 | } |
| 290 | 369 | |
| 291 | 370 | test "sha3-512 aligned final" { |
| 292 | var block = []u8 {0} ** Sha3_512.block_size; | |
| 371 | var block = []u8{0} ** Sha3_512.block_size; | |
| 293 | 372 | var out: [Sha3_512.digest_size]u8 = undefined; |
| 294 | 373 | |
| 295 | 374 | 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 |
| 14 | 14 | pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { |
| 15 | 15 | var expected_bytes: [expected.len / 2]u8 = undefined; |
| 16 | 16 | 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; | |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | debug.assert(mem.eql(u8, expected_bytes, input)); |
| 21 | 21 | } |
| 22 |
std/debug/index.zig+98-135| ... | ... | @@ -104,9 +104,7 @@ pub fn panic(comptime format: []const u8, args: ...) noreturn { |
| 104 | 104 | |
| 105 | 105 | var panicking: u8 = 0; // TODO make this a bool |
| 106 | 106 | |
| 107 | pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize, | |
| 108 | comptime format: []const u8, args: ...) noreturn | |
| 109 | { | |
| 107 | pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn { | |
| 110 | 108 | @setCold(true); |
| 111 | 109 | |
| 112 | 110 | if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) { |
| ... | ... | @@ -132,9 +130,7 @@ const WHITE = "\x1b[37;1m"; |
| 132 | 130 | const DIM = "\x1b[2m"; |
| 133 | 131 | const RESET = "\x1b[0m"; |
| 134 | 132 | |
| 135 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator, | |
| 136 | debug_info: &ElfStackTrace, tty_color: bool) !void | |
| 137 | { | |
| 133 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool) !void { | |
| 138 | 134 | var frame_index: usize = undefined; |
| 139 | 135 | var frames_left: usize = undefined; |
| 140 | 136 | if (stack_trace.index < stack_trace.instruction_addresses.len) { |
| ... | ... | @@ -154,9 +150,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, |
| 154 | 150 | } |
| 155 | 151 | } |
| 156 | 152 | |
| 157 | pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, | |
| 158 | debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void | |
| 159 | { | |
| 153 | pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void { | |
| 160 | 154 | const AddressState = union(enum) { |
| 161 | 155 | NotLookingForStartAddress, |
| 162 | 156 | LookingForStartAddress: usize, |
| ... | ... | @@ -166,14 +160,14 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, |
| 166 | 160 | // else AddressState.NotLookingForStartAddress; |
| 167 | 161 | var addr_state: AddressState = undefined; |
| 168 | 162 | if (start_addr) |addr| { |
| 169 | addr_state = AddressState { .LookingForStartAddress = addr }; | |
| 163 | addr_state = AddressState{ .LookingForStartAddress = addr }; | |
| 170 | 164 | } else { |
| 171 | 165 | addr_state = AddressState.NotLookingForStartAddress; |
| 172 | 166 | } |
| 173 | 167 | |
| 174 | 168 | 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)).*; | |
| 177 | 171 | |
| 178 | 172 | switch (addr_state) { |
| 179 | 173 | AddressState.NotLookingForStartAddress => {}, |
| ... | ... | @@ -200,32 +194,32 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us |
| 200 | 194 | // in practice because the compiler dumps everything in a single |
| 201 | 195 | // object file. Future improvement: use external dSYM data when |
| 202 | 196 | // available. |
| 203 | const unknown = macho.Symbol { .name = "???", .address = address }; | |
| 197 | const unknown = macho.Symbol{ | |
| 198 | .name = "???", | |
| 199 | .address = address, | |
| 200 | }; | |
| 204 | 201 | 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); | |
| 208 | 203 | }, |
| 209 | 204 | else => { |
| 210 | 205 | 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); | |
| 213 | 207 | return; |
| 214 | 208 | }; |
| 215 | 209 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); |
| 216 | 210 | if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| { |
| 217 | 211 | 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); | |
| 222 | 213 | if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) { |
| 223 | 214 | if (line_info.column == 0) { |
| 224 | 215 | try out_stream.write("\n"); |
| 225 | 216 | } 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 | } | |
| 229 | 223 | try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); |
| 230 | 224 | } |
| 231 | 225 | } else |err| switch (err) { |
| ... | ... | @@ -233,7 +227,8 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us |
| 233 | 227 | else => return err, |
| 234 | 228 | } |
| 235 | 229 | } else |err| switch (err) { |
| 236 | error.MissingDebugInfo, error.InvalidDebugInfo => { | |
| 230 | error.MissingDebugInfo, | |
| 231 | error.InvalidDebugInfo => { | |
| 237 | 232 | try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name); |
| 238 | 233 | }, |
| 239 | 234 | else => return err, |
| ... | ... | @@ -247,7 +242,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace { |
| 247 | 242 | builtin.ObjectFormat.elf => { |
| 248 | 243 | const st = try allocator.create(ElfStackTrace); |
| 249 | 244 | errdefer allocator.destroy(st); |
| 250 | *st = ElfStackTrace { | |
| 245 | st.* = ElfStackTrace{ | |
| 251 | 246 | .self_exe_file = undefined, |
| 252 | 247 | .elf = undefined, |
| 253 | 248 | .debug_info = undefined, |
| ... | ... | @@ -279,9 +274,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace { |
| 279 | 274 | const st = try allocator.create(ElfStackTrace); |
| 280 | 275 | errdefer allocator.destroy(st); |
| 281 | 276 | |
| 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)) }; | |
| 285 | 278 | |
| 286 | 279 | return st; |
| 287 | 280 | }, |
| ... | ... | @@ -325,8 +318,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: var, line_info: &con |
| 325 | 318 | } |
| 326 | 319 | } |
| 327 | 320 | |
| 328 | if (amt_read < buf.len) | |
| 329 | return error.EndOfFile; | |
| 321 | if (amt_read < buf.len) return error.EndOfFile; | |
| 330 | 322 | } |
| 331 | 323 | } |
| 332 | 324 | |
| ... | ... | @@ -418,10 +410,8 @@ const Constant = struct { |
| 418 | 410 | signed: bool, |
| 419 | 411 | |
| 420 | 412 | 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; | |
| 425 | 415 | return mem.readInt(self.payload, u64, builtin.Endian.Little); |
| 426 | 416 | } |
| 427 | 417 | }; |
| ... | ... | @@ -438,15 +428,14 @@ const Die = struct { |
| 438 | 428 | |
| 439 | 429 | fn getAttr(self: &const Die, id: u64) ?&const FormValue { |
| 440 | 430 | for (self.attrs.toSliceConst()) |*attr| { |
| 441 | if (attr.id == id) | |
| 442 | return &attr.value; | |
| 431 | if (attr.id == id) return &attr.value; | |
| 443 | 432 | } |
| 444 | 433 | return null; |
| 445 | 434 | } |
| 446 | 435 | |
| 447 | 436 | fn getAttrAddr(self: &const Die, id: u64) !u64 { |
| 448 | 437 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 449 | return switch (*form_value) { | |
| 438 | return switch (form_value.*) { | |
| 450 | 439 | FormValue.Address => |value| value, |
| 451 | 440 | else => error.InvalidDebugInfo, |
| 452 | 441 | }; |
| ... | ... | @@ -454,7 +443,7 @@ const Die = struct { |
| 454 | 443 | |
| 455 | 444 | fn getAttrSecOffset(self: &const Die, id: u64) !u64 { |
| 456 | 445 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 457 | return switch (*form_value) { | |
| 446 | return switch (form_value.*) { | |
| 458 | 447 | FormValue.Const => |value| value.asUnsignedLe(), |
| 459 | 448 | FormValue.SecOffset => |value| value, |
| 460 | 449 | else => error.InvalidDebugInfo, |
| ... | ... | @@ -463,7 +452,7 @@ const Die = struct { |
| 463 | 452 | |
| 464 | 453 | fn getAttrUnsignedLe(self: &const Die, id: u64) !u64 { |
| 465 | 454 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 466 | return switch (*form_value) { | |
| 455 | return switch (form_value.*) { | |
| 467 | 456 | FormValue.Const => |value| value.asUnsignedLe(), |
| 468 | 457 | else => error.InvalidDebugInfo, |
| 469 | 458 | }; |
| ... | ... | @@ -471,7 +460,7 @@ const Die = struct { |
| 471 | 460 | |
| 472 | 461 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) ![]u8 { |
| 473 | 462 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 474 | return switch (*form_value) { | |
| 463 | return switch (form_value.*) { | |
| 475 | 464 | FormValue.String => |value| value, |
| 476 | 465 | FormValue.StrPtr => |offset| getString(st, offset), |
| 477 | 466 | else => error.InvalidDebugInfo, |
| ... | ... | @@ -518,10 +507,8 @@ const LineNumberProgram = struct { |
| 518 | 507 | prev_basic_block: bool, |
| 519 | 508 | prev_end_sequence: bool, |
| 520 | 509 | |
| 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{ | |
| 525 | 512 | .address = 0, |
| 526 | 513 | .file = 1, |
| 527 | 514 | .line = 1, |
| ... | ... | @@ -548,14 +535,16 @@ const LineNumberProgram = struct { |
| 548 | 535 | return error.MissingDebugInfo; |
| 549 | 536 | } else if (self.prev_file - 1 >= self.file_entries.len) { |
| 550 | 537 | return error.InvalidDebugInfo; |
| 551 | } else &self.file_entries.items[self.prev_file - 1]; | |
| 538 | } else | |
| 539 | &self.file_entries.items[self.prev_file - 1]; | |
| 552 | 540 | |
| 553 | 541 | const dir_name = if (file_entry.dir_index >= self.include_dirs.len) { |
| 554 | 542 | return error.InvalidDebugInfo; |
| 555 | } else self.include_dirs[file_entry.dir_index]; | |
| 543 | } else | |
| 544 | self.include_dirs[file_entry.dir_index]; | |
| 556 | 545 | const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); |
| 557 | 546 | errdefer self.file_entries.allocator.free(file_name); |
| 558 | return LineInfo { | |
| 547 | return LineInfo{ | |
| 559 | 548 | .line = if (self.prev_line >= 0) usize(self.prev_line) else 0, |
| 560 | 549 | .column = self.prev_column, |
| 561 | 550 | .file_name = file_name, |
| ... | ... | @@ -578,8 +567,7 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: var) ![]u8 { |
| 578 | 567 | var buf = ArrayList(u8).init(allocator); |
| 579 | 568 | while (true) { |
| 580 | 569 | const byte = try in_stream.readByte(); |
| 581 | if (byte == 0) | |
| 582 | break; | |
| 570 | if (byte == 0) break; | |
| 583 | 571 | try buf.append(byte); |
| 584 | 572 | } |
| 585 | 573 | return buf.toSlice(); |
| ... | ... | @@ -600,7 +588,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8 |
| 600 | 588 | |
| 601 | 589 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue { |
| 602 | 590 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 603 | return FormValue { .Block = buf }; | |
| 591 | return FormValue{ .Block = buf }; | |
| 604 | 592 | } |
| 605 | 593 | |
| 606 | 594 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue { |
| ... | ... | @@ -609,26 +597,23 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) ! |
| 609 | 597 | } |
| 610 | 598 | |
| 611 | 599 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue { |
| 612 | return FormValue { .Const = Constant { | |
| 600 | return FormValue{ .Const = Constant{ | |
| 613 | 601 | .signed = signed, |
| 614 | 602 | .payload = try readAllocBytes(allocator, in_stream, size), |
| 615 | }}; | |
| 603 | } }; | |
| 616 | 604 | } |
| 617 | 605 | |
| 618 | 606 | fn 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)); | |
| 621 | 608 | } |
| 622 | 609 | |
| 623 | 610 | fn 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; | |
| 627 | 612 | } |
| 628 | 613 | |
| 629 | 614 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue { |
| 630 | 615 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 631 | return FormValue { .Ref = buf }; | |
| 616 | return FormValue{ .Ref = buf }; | |
| 632 | 617 | } |
| 633 | 618 | |
| 634 | 619 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type) !FormValue { |
| ... | ... | @@ -646,11 +631,9 @@ const ParseFormValueError = error { |
| 646 | 631 | OutOfMemory, |
| 647 | 632 | }; |
| 648 | 633 | |
| 649 | fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool) | |
| 650 | ParseFormValueError!FormValue | |
| 651 | { | |
| 634 | fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue { | |
| 652 | 635 | return switch (form_id) { |
| 653 | DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) }, | |
| 636 | DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, | |
| 654 | 637 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| 655 | 638 | DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2), |
| 656 | 639 | 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 |
| 662 | 645 | DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2), |
| 663 | 646 | DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), |
| 664 | 647 | DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), |
| 665 | DW.FORM_udata, DW.FORM_sdata => { | |
| 648 | DW.FORM_udata, | |
| 649 | DW.FORM_sdata => { | |
| 666 | 650 | const block_len = try readULeb128(in_stream); |
| 667 | 651 | const signed = form_id == DW.FORM_sdata; |
| 668 | 652 | 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 |
| 670 | 654 | DW.FORM_exprloc => { |
| 671 | 655 | const size = try readULeb128(in_stream); |
| 672 | 656 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 673 | return FormValue { .ExprLoc = buf }; | |
| 657 | return FormValue{ .ExprLoc = buf }; | |
| 674 | 658 | }, |
| 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) }, | |
| 678 | 662 | |
| 679 | 663 | DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), |
| 680 | 664 | 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 |
| 685 | 669 | return parseFormValueRefLen(allocator, in_stream, ref_len); |
| 686 | 670 | }, |
| 687 | 671 | |
| 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) }, | |
| 690 | 674 | |
| 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) }, | |
| 693 | 677 | DW.FORM_indirect => { |
| 694 | 678 | const child_form_id = try readULeb128(in_stream); |
| 695 | 679 | return parseFormValue(allocator, in_stream, child_form_id, is_64); |
| ... | ... | @@ -705,9 +689,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable { |
| 705 | 689 | var result = AbbrevTable.init(st.allocator()); |
| 706 | 690 | while (true) { |
| 707 | 691 | 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{ | |
| 711 | 694 | .abbrev_code = abbrev_code, |
| 712 | 695 | .tag_id = try readULeb128(in_stream), |
| 713 | 696 | .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, |
| ... | ... | @@ -718,9 +701,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable { |
| 718 | 701 | while (true) { |
| 719 | 702 | const attr_id = try readULeb128(in_stream); |
| 720 | 703 | 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{ | |
| 724 | 706 | .attr_id = attr_id, |
| 725 | 707 | .form_id = form_id, |
| 726 | 708 | }); |
| ... | ... | @@ -737,7 +719,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable { |
| 737 | 719 | } |
| 738 | 720 | } |
| 739 | 721 | 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{ | |
| 741 | 723 | .offset = abbrev_offset, |
| 742 | 724 | .table = try parseAbbrevTable(st), |
| 743 | 725 | }); |
| ... | ... | @@ -746,8 +728,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable { |
| 746 | 728 | |
| 747 | 729 | fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&const AbbrevTableEntry { |
| 748 | 730 | 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; | |
| 751 | 732 | } |
| 752 | 733 | return null; |
| 753 | 734 | } |
| ... | ... | @@ -759,14 +740,14 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) ! |
| 759 | 740 | const abbrev_code = try readULeb128(in_stream); |
| 760 | 741 | const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo; |
| 761 | 742 | |
| 762 | var result = Die { | |
| 743 | var result = Die{ | |
| 763 | 744 | .tag_id = table_entry.tag_id, |
| 764 | 745 | .has_children = table_entry.has_children, |
| 765 | 746 | .attrs = ArrayList(Die.Attr).init(st.allocator()), |
| 766 | 747 | }; |
| 767 | 748 | try result.attrs.resize(table_entry.attrs.len); |
| 768 | 749 | for (table_entry.attrs.toSliceConst()) |attr, i| { |
| 769 | result.attrs.items[i] = Die.Attr { | |
| 750 | result.attrs.items[i] = Die.Attr{ | |
| 770 | 751 | .id = attr.attr_id, |
| 771 | 752 | .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), |
| 772 | 753 | }; |
| ... | ... | @@ -790,8 +771,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 790 | 771 | |
| 791 | 772 | var is_64: bool = undefined; |
| 792 | 773 | 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; | |
| 795 | 775 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 796 | 776 | |
| 797 | 777 | if (compile_unit.index != this_index) { |
| ... | ... | @@ -803,8 +783,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 803 | 783 | // TODO support 3 and 5 |
| 804 | 784 | if (version != 2 and version != 4) return error.InvalidDebugInfo; |
| 805 | 785 | |
| 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); | |
| 808 | 787 | const prog_start_offset = (try in_file.getPos()) + prologue_length; |
| 809 | 788 | |
| 810 | 789 | const minimum_instruction_length = try in_stream.readByte(); |
| ... | ... | @@ -819,38 +798,37 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 819 | 798 | const line_base = try in_stream.readByteSigned(); |
| 820 | 799 | |
| 821 | 800 | const line_range = try in_stream.readByte(); |
| 822 | if (line_range == 0) | |
| 823 | return error.InvalidDebugInfo; | |
| 801 | if (line_range == 0) return error.InvalidDebugInfo; | |
| 824 | 802 | |
| 825 | 803 | const opcode_base = try in_stream.readByte(); |
| 826 | 804 | |
| 827 | 805 | const standard_opcode_lengths = try st.allocator().alloc(u8, opcode_base - 1); |
| 828 | 806 | |
| 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 | } | |
| 832 | 813 | |
| 833 | 814 | var include_directories = ArrayList([]u8).init(st.allocator()); |
| 834 | 815 | try include_directories.append(compile_unit_cwd); |
| 835 | 816 | while (true) { |
| 836 | 817 | const dir = try st.readString(); |
| 837 | if (dir.len == 0) | |
| 838 | break; | |
| 818 | if (dir.len == 0) break; | |
| 839 | 819 | try include_directories.append(dir); |
| 840 | 820 | } |
| 841 | 821 | |
| 842 | 822 | 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); | |
| 845 | 824 | |
| 846 | 825 | while (true) { |
| 847 | 826 | const file_name = try st.readString(); |
| 848 | if (file_name.len == 0) | |
| 849 | break; | |
| 827 | if (file_name.len == 0) break; | |
| 850 | 828 | const dir_index = try readULeb128(in_stream); |
| 851 | 829 | const mtime = try readULeb128(in_stream); |
| 852 | 830 | const len_bytes = try readULeb128(in_stream); |
| 853 | try file_entries.append(FileEntry { | |
| 831 | try file_entries.append(FileEntry{ | |
| 854 | 832 | .file_name = file_name, |
| 855 | 833 | .dir_index = dir_index, |
| 856 | 834 | .mtime = mtime, |
| ... | ... | @@ -866,8 +844,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 866 | 844 | var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash |
| 867 | 845 | if (opcode == DW.LNS_extended_op) { |
| 868 | 846 | const op_size = try readULeb128(in_stream); |
| 869 | if (op_size < 1) | |
| 870 | return error.InvalidDebugInfo; | |
| 847 | if (op_size < 1) return error.InvalidDebugInfo; | |
| 871 | 848 | sub_op = try in_stream.readByte(); |
| 872 | 849 | switch (sub_op) { |
| 873 | 850 | DW.LNE_end_sequence => { |
| ... | ... | @@ -884,7 +861,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 884 | 861 | const dir_index = try readULeb128(in_stream); |
| 885 | 862 | const mtime = try readULeb128(in_stream); |
| 886 | 863 | const len_bytes = try readULeb128(in_stream); |
| 887 | try file_entries.append(FileEntry { | |
| 864 | try file_entries.append(FileEntry{ | |
| 888 | 865 | .file_name = file_name, |
| 889 | 866 | .dir_index = dir_index, |
| 890 | 867 | .mtime = mtime, |
| ... | ... | @@ -941,11 +918,9 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 941 | 918 | const arg = try in_stream.readInt(st.elf.endian, u16); |
| 942 | 919 | prog.address += arg; |
| 943 | 920 | }, |
| 944 | DW.LNS_set_prologue_end => { | |
| 945 | }, | |
| 921 | DW.LNS_set_prologue_end => {}, | |
| 946 | 922 | else => { |
| 947 | if (opcode - 1 >= standard_opcode_lengths.len) | |
| 948 | return error.InvalidDebugInfo; | |
| 923 | if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; | |
| 949 | 924 | const len_bytes = standard_opcode_lengths[opcode - 1]; |
| 950 | 925 | try in_file.seekForward(len_bytes); |
| 951 | 926 | }, |
| ... | ... | @@ -972,16 +947,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { |
| 972 | 947 | |
| 973 | 948 | var is_64: bool = undefined; |
| 974 | 949 | 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; | |
| 977 | 951 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 978 | 952 | |
| 979 | 953 | const version = try in_stream.readInt(st.elf.endian, u16); |
| 980 | 954 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 981 | 955 | |
| 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); | |
| 985 | 957 | |
| 986 | 958 | const address_size = try in_stream.readByte(); |
| 987 | 959 | if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; |
| ... | ... | @@ -992,15 +964,14 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { |
| 992 | 964 | try st.self_exe_file.seekTo(compile_unit_pos); |
| 993 | 965 | |
| 994 | 966 | 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); | |
| 996 | 968 | |
| 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; | |
| 999 | 970 | |
| 1000 | 971 | const pc_range = x: { |
| 1001 | 972 | if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| { |
| 1002 | 973 | 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.*) { | |
| 1004 | 975 | FormValue.Address => |value| value, |
| 1005 | 976 | FormValue.Const => |value| b: { |
| 1006 | 977 | const offset = try value.asUnsignedLe(); |
| ... | ... | @@ -1008,7 +979,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { |
| 1008 | 979 | }, |
| 1009 | 980 | else => return error.InvalidDebugInfo, |
| 1010 | 981 | }; |
| 1011 | break :x PcRange { | |
| 982 | break :x PcRange{ | |
| 1012 | 983 | .start = low_pc, |
| 1013 | 984 | .end = pc_end, |
| 1014 | 985 | }; |
| ... | ... | @@ -1016,13 +987,12 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void { |
| 1016 | 987 | break :x null; |
| 1017 | 988 | } |
| 1018 | 989 | } else |err| { |
| 1019 | if (err != error.MissingDebugInfo) | |
| 1020 | return err; | |
| 990 | if (err != error.MissingDebugInfo) return err; | |
| 1021 | 991 | break :x null; |
| 1022 | 992 | } |
| 1023 | 993 | }; |
| 1024 | 994 | |
| 1025 | try st.compile_unit_list.append(CompileUnit { | |
| 995 | try st.compile_unit_list.append(CompileUnit{ | |
| 1026 | 996 | .version = version, |
| 1027 | 997 | .is_64 = is_64, |
| 1028 | 998 | .pc_range = pc_range, |
| ... | ... | @@ -1040,8 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit |
| 1040 | 1010 | const in_stream = &in_file_stream.stream; |
| 1041 | 1011 | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| 1042 | 1012 | 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; | |
| 1045 | 1014 | } |
| 1046 | 1015 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { |
| 1047 | 1016 | var base_address: usize = 0; |
| ... | ... | @@ -1063,8 +1032,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit |
| 1063 | 1032 | } |
| 1064 | 1033 | } |
| 1065 | 1034 | } else |err| { |
| 1066 | if (err != error.MissingDebugInfo) | |
| 1067 | return err; | |
| 1035 | if (err != error.MissingDebugInfo) return err; | |
| 1068 | 1036 | continue; |
| 1069 | 1037 | } |
| 1070 | 1038 | } |
| ... | ... | @@ -1073,8 +1041,8 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit |
| 1073 | 1041 | |
| 1074 | 1042 | fn readInitialLength(comptime E: type, in_stream: &io.InStream(E), is_64: &bool) !u64 { |
| 1075 | 1043 | 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.*) { | |
| 1078 | 1046 | return in_stream.readIntLe(u64); |
| 1079 | 1047 | } else { |
| 1080 | 1048 | if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; |
| ... | ... | @@ -1091,13 +1059,11 @@ fn readULeb128(in_stream: var) !u64 { |
| 1091 | 1059 | |
| 1092 | 1060 | var operand: u64 = undefined; |
| 1093 | 1061 | |
| 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; | |
| 1096 | 1063 | |
| 1097 | 1064 | result |= operand; |
| 1098 | 1065 | |
| 1099 | if ((byte & 0b10000000) == 0) | |
| 1100 | return result; | |
| 1066 | if ((byte & 0b10000000) == 0) return result; | |
| 1101 | 1067 | |
| 1102 | 1068 | shift += 7; |
| 1103 | 1069 | } |
| ... | ... | @@ -1112,15 +1078,13 @@ fn readILeb128(in_stream: var) !i64 { |
| 1112 | 1078 | |
| 1113 | 1079 | var operand: i64 = undefined; |
| 1114 | 1080 | |
| 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; | |
| 1117 | 1082 | |
| 1118 | 1083 | result |= operand; |
| 1119 | 1084 | shift += 7; |
| 1120 | 1085 | |
| 1121 | 1086 | 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)); | |
| 1124 | 1088 | return result; |
| 1125 | 1089 | } |
| 1126 | 1090 | } |
| ... | ... | @@ -1131,7 +1095,6 @@ pub const global_allocator = &global_fixed_allocator.allocator; |
| 1131 | 1095 | var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]); |
| 1132 | 1096 | var global_allocator_mem: [100 * 1024]u8 = undefined; |
| 1133 | 1097 | |
| 1134 | ||
| 1135 | 1098 | // TODO make thread safe |
| 1136 | 1099 | var debug_info_allocator: ?&mem.Allocator = null; |
| 1137 | 1100 | var debug_info_direct_allocator: std.heap.DirectAllocator = undefined; |
std/event.zig+20-33| ... | ... | @@ -6,7 +6,7 @@ const mem = std.mem; |
| 6 | 6 | const posix = std.os.posix; |
| 7 | 7 | |
| 8 | 8 | pub 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, | |
| 10 | 10 | |
| 11 | 11 | loop: &Loop, |
| 12 | 12 | sockfd: i32, |
| ... | ... | @@ -18,13 +18,11 @@ pub const TcpServer = struct { |
| 18 | 18 | const PromiseNode = std.LinkedList(promise).Node; |
| 19 | 19 | |
| 20 | 20 | 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); | |
| 24 | 22 | errdefer std.os.close(sockfd); |
| 25 | 23 | |
| 26 | 24 | // TODO can't initialize handler coroutine here because we need well defined copy elision |
| 27 | return TcpServer { | |
| 25 | return TcpServer{ | |
| 28 | 26 | .loop = loop, |
| 29 | 27 | .sockfd = sockfd, |
| 30 | 28 | .accept_coro = null, |
| ... | ... | @@ -34,9 +32,7 @@ pub const TcpServer = struct { |
| 34 | 32 | }; |
| 35 | 33 | } |
| 36 | 34 | |
| 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 { | |
| 40 | 36 | self.handleRequestFn = handleRequestFn; |
| 41 | 37 | |
| 42 | 38 | try std.os.posixBind(self.sockfd, &address.os_addr); |
| ... | ... | @@ -48,7 +44,6 @@ pub const TcpServer = struct { |
| 48 | 44 | |
| 49 | 45 | try self.loop.addFd(self.sockfd, ??self.accept_coro); |
| 50 | 46 | errdefer self.loop.removeFd(self.sockfd); |
| 51 | ||
| 52 | 47 | } |
| 53 | 48 | |
| 54 | 49 | pub fn deinit(self: &TcpServer) void { |
| ... | ... | @@ -60,9 +55,7 @@ pub const TcpServer = struct { |
| 60 | 55 | pub async fn handler(self: &TcpServer) void { |
| 61 | 56 | while (true) { |
| 62 | 57 | 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| { | |
| 66 | 59 | var socket = std.os.File.openHandle(accepted_fd); |
| 67 | 60 | _ = async<self.loop.allocator> self.handleRequestFn(self, accepted_addr, socket) catch |err| switch (err) { |
| 68 | 61 | error.OutOfMemory => { |
| ... | ... | @@ -110,7 +103,7 @@ pub const Loop = struct { |
| 110 | 103 | |
| 111 | 104 | fn init(allocator: &mem.Allocator) !Loop { |
| 112 | 105 | const epollfd = try std.os.linuxEpollCreate(std.os.linux.EPOLL_CLOEXEC); |
| 113 | return Loop { | |
| 106 | return Loop{ | |
| 114 | 107 | .keep_running = true, |
| 115 | 108 | .allocator = allocator, |
| 116 | 109 | .epollfd = epollfd, |
| ... | ... | @@ -118,11 +111,9 @@ pub const Loop = struct { |
| 118 | 111 | } |
| 119 | 112 | |
| 120 | 113 | 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) }, | |
| 126 | 117 | }; |
| 127 | 118 | try std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev); |
| 128 | 119 | } |
| ... | ... | @@ -157,9 +148,9 @@ pub const Loop = struct { |
| 157 | 148 | }; |
| 158 | 149 | |
| 159 | 150 | pub 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/zig-lang/zig/issues/733 | |
| 161 | 152 | |
| 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); | |
| 163 | 154 | errdefer std.os.close(sockfd); |
| 164 | 155 | |
| 165 | 156 | try std.os.posixConnectAsync(sockfd, &address.os_addr); |
| ... | ... | @@ -179,11 +170,9 @@ test "listen on a port, send bytes, receive bytes" { |
| 179 | 170 | |
| 180 | 171 | const Self = this; |
| 181 | 172 | |
| 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 { | |
| 185 | 174 | 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/zig-lang/zig/issues/733 | |
| 187 | 176 | defer socket.close(); |
| 188 | 177 | const next_handler = async errorableHandler(self, _addr, socket) catch |err| switch (err) { |
| 189 | 178 | error.OutOfMemory => @panic("unable to handle connection: out of memory"), |
| ... | ... | @@ -191,14 +180,14 @@ test "listen on a port, send bytes, receive bytes" { |
| 191 | 180 | (await next_handler) catch |err| { |
| 192 | 181 | std.debug.panic("unable to handle connection: {}\n", err); |
| 193 | 182 | }; |
| 194 | suspend |p| { cancel p; } | |
| 183 | suspend |p| { | |
| 184 | cancel p; | |
| 185 | } | |
| 195 | 186 | } |
| 196 | 187 | |
| 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/zig-lang/zig/issues/733 | |
| 190 | var socket = _socket.*; // TODO https://github.com/zig-lang/zig/issues/733 | |
| 202 | 191 | |
| 203 | 192 | var adapter = std.io.FileOutStream.init(&socket); |
| 204 | 193 | var stream = &adapter.stream; |
| ... | ... | @@ -210,9 +199,7 @@ test "listen on a port, send bytes, receive bytes" { |
| 210 | 199 | const addr = std.net.Address.initIp4(ip4addr, 0); |
| 211 | 200 | |
| 212 | 201 | 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) }; | |
| 216 | 203 | defer server.tcp_server.deinit(); |
| 217 | 204 | try server.tcp_server.listen(addr, MyServer.handler); |
| 218 | 205 |
std/fmt/errol/index.zig+22-32| ... | ... | @@ -86,7 +86,7 @@ pub fn errol3(value: f64, buffer: []u8) FloatDecimal { |
| 86 | 86 | const data = enum3_data[i]; |
| 87 | 87 | const digits = buffer[1..data.str.len + 1]; |
| 88 | 88 | mem.copy(u8, digits, data.str); |
| 89 | return FloatDecimal { | |
| 89 | return FloatDecimal{ | |
| 90 | 90 | .digits = digits, |
| 91 | 91 | .exp = data.exp, |
| 92 | 92 | }; |
| ... | ... | @@ -105,7 +105,6 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { |
| 105 | 105 | return errolFixed(val, buffer); |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | ||
| 109 | 108 | // normalize the midpoint |
| 110 | 109 | |
| 111 | 110 | const e = math.frexp(val).exponent; |
| ... | ... | @@ -137,11 +136,11 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { |
| 137 | 136 | } |
| 138 | 137 | |
| 139 | 138 | // compute boundaries |
| 140 | var high = HP { | |
| 139 | var high = HP{ | |
| 141 | 140 | .val = mid.val, |
| 142 | 141 | .off = mid.off + (fpnext(val) - val) * lten * ten / 2.0, |
| 143 | 142 | }; |
| 144 | var low = HP { | |
| 143 | var low = HP{ | |
| 145 | 144 | .val = mid.val, |
| 146 | 145 | .off = mid.off + (fpprev(val) - val) * lten * ten / 2.0, |
| 147 | 146 | }; |
| ... | ... | @@ -171,15 +170,12 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { |
| 171 | 170 | var buf_index: usize = 1; |
| 172 | 171 | while (true) { |
| 173 | 172 | 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; | |
| 176 | 174 | |
| 177 | 175 | 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; | |
| 180 | 177 | |
| 181 | if (ldig != hdig) | |
| 182 | break; | |
| 178 | if (ldig != hdig) break; | |
| 183 | 179 | |
| 184 | 180 | buffer[buf_index] = hdig + '0'; |
| 185 | 181 | buf_index += 1; |
| ... | ... | @@ -191,13 +187,12 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal { |
| 191 | 187 | |
| 192 | 188 | const tmp = (high.val + low.val) / 2.0; |
| 193 | 189 | 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; | |
| 196 | 191 | |
| 197 | 192 | buffer[buf_index] = mdig + '0'; |
| 198 | 193 | buf_index += 1; |
| 199 | 194 | |
| 200 | return FloatDecimal { | |
| 195 | return FloatDecimal{ | |
| 201 | 196 | .digits = buffer[1..buf_index], |
| 202 | 197 | .exp = exp, |
| 203 | 198 | }; |
| ... | ... | @@ -235,7 +230,7 @@ fn hpProd(in: &const HP, val: f64) HP { |
| 235 | 230 | const p = in.val * val; |
| 236 | 231 | const e = ((hi * hi2 - p) + lo * hi2 + hi * lo2) + lo * lo2; |
| 237 | 232 | |
| 238 | return HP { | |
| 233 | return HP{ | |
| 239 | 234 | .val = p, |
| 240 | 235 | .off = in.off * val + e, |
| 241 | 236 | }; |
| ... | ... | @@ -246,8 +241,8 @@ fn hpProd(in: &const HP, val: f64) HP { |
| 246 | 241 | /// @hi: The high bits. |
| 247 | 242 | /// @lo: The low bits. |
| 248 | 243 | fn split(val: f64, hi: &f64, lo: &f64) void { |
| 249 | *hi = gethi(val); | |
| 250 | *lo = val - *hi; | |
| 244 | hi.* = gethi(val); | |
| 245 | lo.* = val - hi.*; | |
| 251 | 246 | } |
| 252 | 247 | |
| 253 | 248 | fn gethi(in: f64) f64 { |
| ... | ... | @@ -301,7 +296,6 @@ fn hpMul10(hp: &HP) void { |
| 301 | 296 | hpNormalize(hp); |
| 302 | 297 | } |
| 303 | 298 | |
| 304 | ||
| 305 | 299 | /// Integer conversion algorithm, guaranteed correct, optimal, and best. |
| 306 | 300 | /// @val: The val. |
| 307 | 301 | /// @buf: The output buffer. |
| ... | ... | @@ -343,8 +337,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal { |
| 343 | 337 | } |
| 344 | 338 | const m64 = @truncate(u64, @divTrunc(mid, x)); |
| 345 | 339 | |
| 346 | if (lf != hf) | |
| 347 | mi += 19; | |
| 340 | if (lf != hf) mi += 19; | |
| 348 | 341 | |
| 349 | 342 | var buf_index = u64toa(m64, buffer) - 1; |
| 350 | 343 | |
| ... | ... | @@ -354,7 +347,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal { |
| 354 | 347 | buf_index += 1; |
| 355 | 348 | } |
| 356 | 349 | |
| 357 | return FloatDecimal { | |
| 350 | return FloatDecimal{ | |
| 358 | 351 | .digits = buffer[0..buf_index], |
| 359 | 352 | .exp = i32(buf_index) + mi, |
| 360 | 353 | }; |
| ... | ... | @@ -396,25 +389,24 @@ fn errolFixed(val: f64, buffer: []u8) FloatDecimal { |
| 396 | 389 | buffer[j] = u8(mdig + '0'); |
| 397 | 390 | j += 1; |
| 398 | 391 | |
| 399 | if(hdig != ldig or j > 50) | |
| 400 | break; | |
| 392 | if (hdig != ldig or j > 50) break; | |
| 401 | 393 | } |
| 402 | 394 | |
| 403 | 395 | 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; | |
| 407 | 399 | } |
| 408 | 400 | } else { |
| 409 | while (buffer[j-1] == '0') { | |
| 410 | buffer[j-1] = 0; | |
| 401 | while (buffer[j - 1] == '0') { | |
| 402 | buffer[j - 1] = 0; | |
| 411 | 403 | j -= 1; |
| 412 | 404 | } |
| 413 | 405 | } |
| 414 | 406 | |
| 415 | 407 | buffer[j] = 0; |
| 416 | 408 | |
| 417 | return FloatDecimal { | |
| 409 | return FloatDecimal{ | |
| 418 | 410 | .digits = buffer[0..j], |
| 419 | 411 | .exp = exp, |
| 420 | 412 | }; |
| ... | ... | @@ -587,7 +579,7 @@ fn u64toa(value_param: u64, buffer: []u8) usize { |
| 587 | 579 | buffer[buf_index] = c_digits_lut[d8 + 1]; |
| 588 | 580 | buf_index += 1; |
| 589 | 581 | } else { |
| 590 | const a = u32(value / kTen16); // 1 to 1844 | |
| 582 | const a = u32(value / kTen16); // 1 to 1844 | |
| 591 | 583 | value %= kTen16; |
| 592 | 584 | |
| 593 | 585 | if (a < 10) { |
| ... | ... | @@ -686,7 +678,6 @@ fn fpeint(from: f64) u128 { |
| 686 | 678 | return u128(1) << @truncate(u7, (bits >> 52) -% 1023); |
| 687 | 679 | } |
| 688 | 680 | |
| 689 | ||
| 690 | 681 | /// Given two different integers with the same length in terms of the number |
| 691 | 682 | /// of decimal digits, index the digits from the right-most position starting |
| 692 | 683 | /// from zero, find the first index where the digits in the two integers |
| ... | ... | @@ -713,7 +704,6 @@ fn mismatch10(a: u64, b: u64) i32 { |
| 713 | 704 | a_copy /= 10; |
| 714 | 705 | b_copy /= 10; |
| 715 | 706 | |
| 716 | if (a_copy == b_copy) | |
| 717 | return i; | |
| 707 | if (a_copy == b_copy) return i; | |
| 718 | 708 | } |
| 719 | 709 | } |
std/fmt/index.zig+37-51| ... | ... | @@ -11,9 +11,7 @@ const max_int_digits = 65; |
| 11 | 11 | /// Renders fmt string with args, calling output with slices of bytes. |
| 12 | 12 | /// If `output` returns an error, the error is returned from `format` and |
| 13 | 13 | /// `output` is not called again. |
| 14 | pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void, | |
| 15 | comptime fmt: []const u8, args: ...) Errors!void | |
| 16 | { | |
| 14 | pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void, comptime fmt: []const u8, args: ...) Errors!void { | |
| 17 | 15 | const State = enum { |
| 18 | 16 | Start, |
| 19 | 17 | OpenBrace, |
| ... | ... | @@ -270,7 +268,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context), |
| 270 | 268 | } |
| 271 | 269 | } |
| 272 | 270 | |
| 273 | pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { | |
| 271 | pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 274 | 272 | const T = @typeOf(value); |
| 275 | 273 | switch (@typeId(T)) { |
| 276 | 274 | builtin.TypeId.Int => { |
| ... | ... | @@ -305,7 +303,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ |
| 305 | 303 | }, |
| 306 | 304 | builtin.TypeId.Pointer => { |
| 307 | 305 | if (@typeId(T.Child) == builtin.TypeId.Array and T.Child.Child == u8) { |
| 308 | return output(context, (*value)[0..]); | |
| 306 | return output(context, (value.*)[0..]); | |
| 309 | 307 | } else { |
| 310 | 308 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 311 | 309 | } |
| ... | ... | @@ -319,13 +317,11 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@ |
| 319 | 317 | } |
| 320 | 318 | } |
| 321 | 319 | |
| 322 | pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { | |
| 320 | pub fn formatAsciiChar(c: u8, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 323 | 321 | return output(context, (&c)[0..1]); |
| 324 | 322 | } |
| 325 | 323 | |
| 326 | pub fn formatBuf(buf: []const u8, width: usize, | |
| 327 | context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void | |
| 328 | { | |
| 324 | pub fn formatBuf(buf: []const u8, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 329 | 325 | try output(context, buf); |
| 330 | 326 | |
| 331 | 327 | var leftover_padding = if (width > buf.len) (width - buf.len) else return; |
| ... | ... | @@ -338,7 +334,7 @@ pub fn formatBuf(buf: []const u8, width: usize, |
| 338 | 334 | // Print a float in scientific notation to the specified precision. Null uses full precision. |
| 339 | 335 | // It should be the case that every full precision, printed value can be re-parsed back to the |
| 340 | 336 | // same type unambiguously. |
| 341 | pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { | |
| 337 | pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 342 | 338 | var x = f64(value); |
| 343 | 339 | |
| 344 | 340 | // Errol doesn't handle these special cases. |
| ... | ... | @@ -387,7 +383,7 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, |
| 387 | 383 | var printed: usize = 0; |
| 388 | 384 | if (float_decimal.digits.len > 1) { |
| 389 | 385 | const num_digits = math.min(float_decimal.digits.len, precision + 1); |
| 390 | try output(context, float_decimal.digits[1 .. num_digits]); | |
| 386 | try output(context, float_decimal.digits[1..num_digits]); | |
| 391 | 387 | printed += num_digits - 1; |
| 392 | 388 | } |
| 393 | 389 | |
| ... | ... | @@ -399,12 +395,9 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, |
| 399 | 395 | try output(context, float_decimal.digits[0..1]); |
| 400 | 396 | try output(context, "."); |
| 401 | 397 | if (float_decimal.digits.len > 1) { |
| 402 | const num_digits = if (@typeOf(value) == f32) | |
| 403 | math.min(usize(9), float_decimal.digits.len) | |
| 404 | else | |
| 405 | 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; | |
| 406 | 399 | |
| 407 | try output(context, float_decimal.digits[1 .. num_digits]); | |
| 400 | try output(context, float_decimal.digits[1..num_digits]); | |
| 408 | 401 | } else { |
| 409 | 402 | try output(context, "0"); |
| 410 | 403 | } |
| ... | ... | @@ -430,7 +423,7 @@ pub fn formatFloatScientific(value: var, maybe_precision: ?usize, context: var, |
| 430 | 423 | |
| 431 | 424 | // Print a float of the format x.yyyyy where the number of y is specified by the precision argument. |
| 432 | 425 | // By default floats are printed at full precision (no rounding). |
| 433 | pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void { | |
| 426 | pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 434 | 427 | var x = f64(value); |
| 435 | 428 | |
| 436 | 429 | // Errol doesn't handle these special cases. |
| ... | ... | @@ -480,14 +473,14 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com |
| 480 | 473 | |
| 481 | 474 | if (num_digits_whole > 0) { |
| 482 | 475 | // We may have to zero pad, for instance 1e4 requires zero padding. |
| 483 | 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]); | |
| 484 | 477 | |
| 485 | 478 | var i = num_digits_whole_no_pad; |
| 486 | 479 | while (i < num_digits_whole) : (i += 1) { |
| 487 | 480 | try output(context, "0"); |
| 488 | 481 | } |
| 489 | 482 | } else { |
| 490 | try output(context , "0"); | |
| 483 | try output(context, "0"); | |
| 491 | 484 | } |
| 492 | 485 | |
| 493 | 486 | // {.0} special case doesn't want a trailing '.' |
| ... | ... | @@ -519,10 +512,10 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com |
| 519 | 512 | // Remaining fractional portion, zero-padding if insufficient. |
| 520 | 513 | debug.assert(precision >= printed); |
| 521 | 514 | if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) { |
| 522 | 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]); | |
| 523 | 516 | return; |
| 524 | 517 | } else { |
| 525 | try output(context, float_decimal.digits[num_digits_whole_no_pad ..]); | |
| 518 | try output(context, float_decimal.digits[num_digits_whole_no_pad..]); | |
| 526 | 519 | printed += float_decimal.digits.len - num_digits_whole_no_pad; |
| 527 | 520 | |
| 528 | 521 | while (printed < precision) : (printed += 1) { |
| ... | ... | @@ -538,14 +531,14 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com |
| 538 | 531 | |
| 539 | 532 | if (num_digits_whole > 0) { |
| 540 | 533 | // We may have to zero pad, for instance 1e4 requires zero padding. |
| 541 | 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]); | |
| 542 | 535 | |
| 543 | 536 | var i = num_digits_whole_no_pad; |
| 544 | 537 | while (i < num_digits_whole) : (i += 1) { |
| 545 | 538 | try output(context, "0"); |
| 546 | 539 | } |
| 547 | 540 | } else { |
| 548 | try output(context , "0"); | |
| 541 | try output(context, "0"); | |
| 549 | 542 | } |
| 550 | 543 | |
| 551 | 544 | // Omit `.` if no fractional portion |
| ... | ... | @@ -565,7 +558,7 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com |
| 565 | 558 | } |
| 566 | 559 | } |
| 567 | 560 | |
| 568 | try output(context, float_decimal.digits[num_digits_whole_no_pad ..]); | |
| 561 | try output(context, float_decimal.digits[num_digits_whole_no_pad..]); | |
| 569 | 562 | } |
| 570 | 563 | } |
| 571 | 564 | |
| ... | ... | @@ -609,9 +602,7 @@ pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, |
| 609 | 602 | } |
| 610 | 603 | } |
| 611 | 604 | |
| 612 | fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, | |
| 613 | context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void | |
| 614 | { | |
| 605 | fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 615 | 606 | const uint = @IntType(false, @typeOf(value).bit_count); |
| 616 | 607 | if (value < 0) { |
| 617 | 608 | const minus_sign: u8 = '-'; |
| ... | ... | @@ -630,9 +621,7 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, |
| 630 | 621 | } |
| 631 | 622 | } |
| 632 | 623 | |
| 633 | fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, | |
| 634 | context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void | |
| 635 | { | |
| 624 | fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void { | |
| 636 | 625 | // max_int_digits accounts for the minus sign. when printing an unsigned |
| 637 | 626 | // number we don't need to do that. |
| 638 | 627 | var buf: [max_int_digits - 1]u8 = undefined; |
| ... | ... | @@ -644,8 +633,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, |
| 644 | 633 | index -= 1; |
| 645 | 634 | buf[index] = digitToChar(u8(digit), uppercase); |
| 646 | 635 | a /= base; |
| 647 | if (a == 0) | |
| 648 | break; | |
| 636 | if (a == 0) break; | |
| 649 | 637 | } |
| 650 | 638 | |
| 651 | 639 | const digits_buf = buf[index..]; |
| ... | ... | @@ -657,8 +645,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, |
| 657 | 645 | while (true) { |
| 658 | 646 | try output(context, (&zero_byte)[0..1]); |
| 659 | 647 | leftover_padding -= 1; |
| 660 | if (leftover_padding == 0) | |
| 661 | break; | |
| 648 | if (leftover_padding == 0) break; | |
| 662 | 649 | } |
| 663 | 650 | mem.set(u8, buf[0..index], '0'); |
| 664 | 651 | return output(context, buf); |
| ... | ... | @@ -670,7 +657,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, |
| 670 | 657 | } |
| 671 | 658 | |
| 672 | 659 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) usize { |
| 673 | var context = FormatIntBuf { | |
| 660 | var context = FormatIntBuf{ | |
| 674 | 661 | .out_buf = out_buf, |
| 675 | 662 | .index = 0, |
| 676 | 663 | }; |
| ... | ... | @@ -687,10 +674,8 @@ fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) (error{}!void) { |
| 687 | 674 | } |
| 688 | 675 | |
| 689 | 676 | pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { |
| 690 | if (!T.is_signed) | |
| 691 | return parseUnsigned(T, buf, radix); | |
| 692 | if (buf.len == 0) | |
| 693 | return T(0); | |
| 677 | if (!T.is_signed) return parseUnsigned(T, buf, radix); | |
| 678 | if (buf.len == 0) return T(0); | |
| 694 | 679 | if (buf[0] == '-') { |
| 695 | 680 | return math.negate(try parseUnsigned(T, buf[1..], radix)); |
| 696 | 681 | } else if (buf[0] == '+') { |
| ... | ... | @@ -710,9 +695,10 @@ test "fmt.parseInt" { |
| 710 | 695 | assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); |
| 711 | 696 | } |
| 712 | 697 | |
| 713 | const ParseUnsignedError = error { | |
| 698 | const ParseUnsignedError = error{ | |
| 714 | 699 | /// The result cannot fit in the type specified |
| 715 | 700 | Overflow, |
| 701 | ||
| 716 | 702 | /// The input had a byte that was not a digit |
| 717 | 703 | InvalidCharacter, |
| 718 | 704 | }; |
| ... | ... | @@ -737,8 +723,7 @@ pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { |
| 737 | 723 | else => return error.InvalidCharacter, |
| 738 | 724 | }; |
| 739 | 725 | |
| 740 | if (value >= radix) | |
| 741 | return error.InvalidCharacter; | |
| 726 | if (value >= radix) return error.InvalidCharacter; | |
| 742 | 727 | |
| 743 | 728 | return value; |
| 744 | 729 | } |
| ... | ... | @@ -762,20 +747,21 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void { |
| 762 | 747 | } |
| 763 | 748 | |
| 764 | 749 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { |
| 765 | var context = BufPrintContext { .remaining = buf, }; | |
| 750 | var context = BufPrintContext{ .remaining = buf }; | |
| 766 | 751 | try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args); |
| 767 | 752 | return buf[0..buf.len - context.remaining.len]; |
| 768 | 753 | } |
| 769 | 754 | |
| 770 | 755 | pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) ![]u8 { |
| 771 | 756 | var size: usize = 0; |
| 772 | format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; | |
| 757 | format(&size, error{}, countSize, fmt, args) catch |err| switch (err) { | |
| 758 | }; | |
| 773 | 759 | const buf = try allocator.alloc(u8, size); |
| 774 | 760 | return bufPrint(buf, fmt, args); |
| 775 | 761 | } |
| 776 | 762 | |
| 777 | 763 | fn countSize(size: &usize, bytes: []const u8) (error{}!void) { |
| 778 | *size += bytes.len; | |
| 764 | size.* += bytes.len; | |
| 779 | 765 | } |
| 780 | 766 | |
| 781 | 767 | test "buf print int" { |
| ... | ... | @@ -843,9 +829,7 @@ test "fmt.format" { |
| 843 | 829 | unused: u8, |
| 844 | 830 | }; |
| 845 | 831 | var buf1: [32]u8 = undefined; |
| 846 | const value = Struct { | |
| 847 | .unused = 42, | |
| 848 | }; | |
| 832 | const value = Struct{ .unused = 42 }; | |
| 849 | 833 | const result = try bufPrint(buf1[0..], "pointer: {}\n", &value); |
| 850 | 834 | assert(mem.startsWith(u8, result, "pointer: Struct@")); |
| 851 | 835 | } |
| ... | ... | @@ -1072,7 +1056,7 @@ fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void |
| 1072 | 1056 | |
| 1073 | 1057 | pub fn trim(buf: []const u8) []const u8 { |
| 1074 | 1058 | var start: usize = 0; |
| 1075 | while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { } | |
| 1059 | while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {} | |
| 1076 | 1060 | |
| 1077 | 1061 | var end: usize = buf.len; |
| 1078 | 1062 | while (true) { |
| ... | ... | @@ -1084,7 +1068,6 @@ pub fn trim(buf: []const u8) []const u8 { |
| 1084 | 1068 | } |
| 1085 | 1069 | } |
| 1086 | 1070 | break; |
| 1087 | ||
| 1088 | 1071 | } |
| 1089 | 1072 | return buf[start..end]; |
| 1090 | 1073 | } |
| ... | ... | @@ -1099,7 +1082,10 @@ test "fmt.trim" { |
| 1099 | 1082 | |
| 1100 | 1083 | pub fn isWhiteSpace(byte: u8) bool { |
| 1101 | 1084 | return switch (byte) { |
| 1102 | ' ', '\t', '\n', '\r' => true, | |
| 1085 | ' ', | |
| 1086 | '\t', | |
| 1087 | '\n', | |
| 1088 | '\r' => true, | |
| 1103 | 1089 | else => false, |
| 1104 | 1090 | }; |
| 1105 | 1091 | } |
std/hash/crc.zig+16-16| ... | ... | @@ -9,9 +9,9 @@ const std = @import("../index.zig"); |
| 9 | 9 | const debug = std.debug; |
| 10 | 10 | |
| 11 | 11 | pub const Polynomial = struct { |
| 12 | const IEEE = 0xedb88320; | |
| 12 | const IEEE = 0xedb88320; | |
| 13 | 13 | const Castagnoli = 0x82f63b78; |
| 14 | const Koopman = 0xeb31d82e; | |
| 14 | const Koopman = 0xeb31d82e; | |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | 17 | // 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 { |
| 27 | 27 | |
| 28 | 28 | for (tables[0]) |*e, i| { |
| 29 | 29 | 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) { | |
| 31 | 32 | if (crc & 1 == 1) { |
| 32 | 33 | crc = (crc >> 1) ^ poly; |
| 33 | 34 | } else { |
| 34 | 35 | crc = (crc >> 1); |
| 35 | 36 | } |
| 36 | 37 | } |
| 37 | *e = crc; | |
| 38 | e.* = crc; | |
| 38 | 39 | } |
| 39 | 40 | |
| 40 | 41 | var i: usize = 0; |
| 41 | 42 | while (i < 256) : (i += 1) { |
| 42 | 43 | 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) { | |
| 44 | 46 | const index = @truncate(u8, crc); |
| 45 | 47 | crc = tables[0][index] ^ (crc >> 8); |
| 46 | 48 | tables[j][i] = crc; |
| ... | ... | @@ -53,22 +55,21 @@ pub fn Crc32WithPoly(comptime poly: u32) type { |
| 53 | 55 | crc: u32, |
| 54 | 56 | |
| 55 | 57 | pub fn init() Self { |
| 56 | return Self { | |
| 57 | .crc = 0xffffffff, | |
| 58 | }; | |
| 58 | return Self{ .crc = 0xffffffff }; | |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | pub fn update(self: &Self, input: []const u8) void { |
| 62 | 62 | var i: usize = 0; |
| 63 | 63 | while (i + 8 <= input.len) : (i += 8) { |
| 64 | const p = input[i..i+8]; | |
| 64 | const p = input[i..i + 8]; | |
| 65 | 65 | |
| 66 | 66 | // 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); | |
| 69 | 69 | self.crc ^= (u32(p[2]) << 16); |
| 70 | 70 | self.crc ^= (u32(p[3]) << 24); |
| 71 | 71 | |
| 72 | ||
| 72 | 73 | self.crc = |
| 73 | 74 | lookup_tables[0][p[7]] ^ |
| 74 | 75 | lookup_tables[1][p[6]] ^ |
| ... | ... | @@ -123,14 +124,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 123 | 124 | |
| 124 | 125 | for (table) |*e, i| { |
| 125 | 126 | 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) { | |
| 127 | 129 | if (crc & 1 == 1) { |
| 128 | 130 | crc = (crc >> 1) ^ poly; |
| 129 | 131 | } else { |
| 130 | 132 | crc = (crc >> 1); |
| 131 | 133 | } |
| 132 | 134 | } |
| 133 | *e = crc; | |
| 135 | e.* = crc; | |
| 134 | 136 | } |
| 135 | 137 | |
| 136 | 138 | break :block table; |
| ... | ... | @@ -139,9 +141,7 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type { |
| 139 | 141 | crc: u32, |
| 140 | 142 | |
| 141 | 143 | pub fn init() Self { |
| 142 | return Self { | |
| 143 | .crc = 0xffffffff, | |
| 144 | }; | |
| 144 | return Self{ .crc = 0xffffffff }; | |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | pub fn update(self: &Self, input: []const u8) void { |
std/hash_map.zig+57-45| ... | ... | @@ -9,10 +9,7 @@ const builtin = @import("builtin"); |
| 9 | 9 | const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast; |
| 10 | 10 | const debug_u32 = if (want_modification_safety) u32 else void; |
| 11 | 11 | |
| 12 | pub 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 | { | |
| 12 | pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn(key: K) u32, comptime eql: fn(a: K, b: K) bool) type { | |
| 16 | 13 | return struct { |
| 17 | 14 | entries: []Entry, |
| 18 | 15 | size: usize, |
| ... | ... | @@ -65,7 +62,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 65 | 62 | }; |
| 66 | 63 | |
| 67 | 64 | pub fn init(allocator: &Allocator) Self { |
| 68 | return Self { | |
| 65 | return Self{ | |
| 69 | 66 | .entries = []Entry{}, |
| 70 | 67 | .allocator = allocator, |
| 71 | 68 | .size = 0, |
| ... | ... | @@ -129,34 +126,36 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 129 | 126 | if (hm.entries.len == 0) return null; |
| 130 | 127 | hm.incrementModificationCount(); |
| 131 | 128 | 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; | |
| 148 | 150 | } |
| 149 | *entry = *next_entry; | |
| 150 | entry.distance_from_start_index -= 1; | |
| 151 | entry = next_entry; | |
| 151 | unreachable; // shifting everything in the table | |
| 152 | 152 | } |
| 153 | unreachable; // shifting everything in the table | |
| 154 | }} | |
| 153 | } | |
| 155 | 154 | return null; |
| 156 | 155 | } |
| 157 | 156 | |
| 158 | 157 | pub fn iterator(hm: &const Self) Iterator { |
| 159 | return Iterator { | |
| 158 | return Iterator{ | |
| 160 | 159 | .hm = hm, |
| 161 | 160 | .count = 0, |
| 162 | 161 | .index = 0, |
| ... | ... | @@ -182,21 +181,23 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 182 | 181 | /// Returns the value that was already there. |
| 183 | 182 | fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V { |
| 184 | 183 | var key = orig_key; |
| 185 | var value = *orig_value; | |
| 184 | var value = orig_value.*; | |
| 186 | 185 | const start_index = hm.keyToIndex(key); |
| 187 | 186 | var roll_over: usize = 0; |
| 188 | 187 | 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 | }) { | |
| 190 | 192 | const index = (start_index + roll_over) % hm.entries.len; |
| 191 | 193 | const entry = &hm.entries[index]; |
| 192 | 194 | |
| 193 | 195 | if (entry.used and !eql(entry.key, key)) { |
| 194 | 196 | if (entry.distance_from_start_index < distance_from_start_index) { |
| 195 | 197 | // 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{ | |
| 200 | 201 | .used = true, |
| 201 | 202 | .distance_from_start_index = distance_from_start_index, |
| 202 | 203 | .key = key, |
| ... | ... | @@ -219,7 +220,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 219 | 220 | } |
| 220 | 221 | |
| 221 | 222 | hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index); |
| 222 | *entry = Entry { | |
| 223 | entry.* = Entry{ | |
| 223 | 224 | .used = true, |
| 224 | 225 | .distance_from_start_index = distance_from_start_index, |
| 225 | 226 | .key = key, |
| ... | ... | @@ -232,13 +233,16 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 232 | 233 | |
| 233 | 234 | fn internalGet(hm: &const Self, key: K) ?&Entry { |
| 234 | 235 | 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 | } | |
| 242 | 246 | return null; |
| 243 | 247 | } |
| 244 | 248 | |
| ... | ... | @@ -282,11 +286,19 @@ test "iterator hash map" { |
| 282 | 286 | assert((reset_map.put(2, 22) catch unreachable) == null); |
| 283 | 287 | assert((reset_map.put(3, 33) catch unreachable) == null); |
| 284 | 288 | |
| 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 | }; | |
| 287 | 299 | |
| 288 | 300 | var it = reset_map.iterator(); |
| 289 | var count : usize = 0; | |
| 301 | var count: usize = 0; | |
| 290 | 302 | while (it.next()) |next| { |
| 291 | 303 | assert(next.key == keys[count]); |
| 292 | 304 | assert(next.value == values[count]); |
| ... | ... | @@ -305,7 +317,7 @@ test "iterator hash map" { |
| 305 | 317 | } |
| 306 | 318 | |
| 307 | 319 | it.reset(); |
| 308 | var entry = ?? it.next(); | |
| 320 | var entry = ??it.next(); | |
| 309 | 321 | assert(entry.key == keys[0]); |
| 310 | 322 | assert(entry.value == values[0]); |
| 311 | 323 | } |
std/heap.zig+52-54| ... | ... | @@ -10,7 +10,7 @@ const c = std.c; |
| 10 | 10 | const Allocator = mem.Allocator; |
| 11 | 11 | |
| 12 | 12 | pub const c_allocator = &c_allocator_state; |
| 13 | var c_allocator_state = Allocator { | |
| 13 | var c_allocator_state = Allocator{ | |
| 14 | 14 | .allocFn = cAlloc, |
| 15 | 15 | .reallocFn = cRealloc, |
| 16 | 16 | .freeFn = cFree, |
| ... | ... | @@ -18,10 +18,7 @@ var c_allocator_state = Allocator { |
| 18 | 18 | |
| 19 | 19 | fn cAlloc(self: &Allocator, n: usize, alignment: u29) ![]u8 { |
| 20 | 20 | 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; | |
| 25 | 22 | } |
| 26 | 23 | |
| 27 | 24 | fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { |
| ... | ... | @@ -48,8 +45,8 @@ pub const DirectAllocator = struct { |
| 48 | 45 | const HeapHandle = if (builtin.os == Os.windows) os.windows.HANDLE else void; |
| 49 | 46 | |
| 50 | 47 | pub fn init() DirectAllocator { |
| 51 | return DirectAllocator { | |
| 52 | .allocator = Allocator { | |
| 48 | return DirectAllocator{ | |
| 49 | .allocator = Allocator{ | |
| 53 | 50 | .allocFn = alloc, |
| 54 | 51 | .reallocFn = realloc, |
| 55 | 52 | .freeFn = free, |
| ... | ... | @@ -71,39 +68,39 @@ pub const DirectAllocator = struct { |
| 71 | 68 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 72 | 69 | |
| 73 | 70 | switch (builtin.os) { |
| 74 | Os.linux, Os.macosx, Os.ios => { | |
| 71 | Os.linux, | |
| 72 | Os.macosx, | |
| 73 | Os.ios => { | |
| 75 | 74 | 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 | ||
| 83 | 81 | var aligned_addr = addr & ~usize(alignment - 1); |
| 84 | 82 | aligned_addr += alignment; |
| 85 | ||
| 83 | ||
| 86 | 84 | //We can unmap the unused portions of our mmap, but we must only |
| 87 | 85 | // pass munmap bytes that exist outside our allocated pages or it |
| 88 | 86 | // will happily eat us too |
| 89 | ||
| 87 | ||
| 90 | 88 | //Since alignment > page_size, we are by definition on a page boundry |
| 91 | 89 | const unused_start = addr; |
| 92 | 90 | const unused_len = aligned_addr - 1 - unused_start; |
| 93 | 91 | |
| 94 | 92 | var err = p.munmap(unused_start, unused_len); |
| 95 | 93 | debug.assert(p.getErrno(err) == 0); |
| 96 | ||
| 94 | ||
| 97 | 95 | //It is impossible that there is an unoccupied page at the top of our |
| 98 | 96 | // mmap. |
| 99 | ||
| 97 | ||
| 100 | 98 | return @intToPtr(&u8, aligned_addr)[0..n]; |
| 101 | 99 | }, |
| 102 | 100 | Os.windows => { |
| 103 | 101 | const amt = n + alignment + @sizeOf(usize); |
| 104 | 102 | 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; | |
| 107 | 104 | self.heap_handle = hh; |
| 108 | 105 | break :blk hh; |
| 109 | 106 | }; |
| ... | ... | @@ -113,7 +110,7 @@ pub const DirectAllocator = struct { |
| 113 | 110 | const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); |
| 114 | 111 | const adjusted_addr = root_addr + march_forward_bytes; |
| 115 | 112 | const record_addr = adjusted_addr + n; |
| 116 | *@intToPtr(&align(1) usize, record_addr) = root_addr; | |
| 113 | @intToPtr(&align(1) usize, record_addr).* = root_addr; | |
| 117 | 114 | return @intToPtr(&u8, adjusted_addr)[0..n]; |
| 118 | 115 | }, |
| 119 | 116 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -124,7 +121,9 @@ pub const DirectAllocator = struct { |
| 124 | 121 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 125 | 122 | |
| 126 | 123 | switch (builtin.os) { |
| 127 | Os.linux, Os.macosx, Os.ios => { | |
| 124 | Os.linux, | |
| 125 | Os.macosx, | |
| 126 | Os.ios => { | |
| 128 | 127 | if (new_size <= old_mem.len) { |
| 129 | 128 | const base_addr = @ptrToInt(old_mem.ptr); |
| 130 | 129 | const old_addr_end = base_addr + old_mem.len; |
| ... | ... | @@ -144,13 +143,13 @@ pub const DirectAllocator = struct { |
| 144 | 143 | Os.windows => { |
| 145 | 144 | const old_adjusted_addr = @ptrToInt(old_mem.ptr); |
| 146 | 145 | 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).*; | |
| 148 | 147 | const old_ptr = @intToPtr(os.windows.LPVOID, root_addr); |
| 149 | 148 | const amt = new_size + alignment + @sizeOf(usize); |
| 150 | 149 | const new_ptr = os.windows.HeapReAlloc(??self.heap_handle, 0, old_ptr, amt) ?? blk: { |
| 151 | 150 | if (new_size > old_mem.len) return error.OutOfMemory; |
| 152 | 151 | 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; | |
| 154 | 153 | return old_mem[0..new_size]; |
| 155 | 154 | }; |
| 156 | 155 | const offset = old_adjusted_addr - root_addr; |
| ... | ... | @@ -158,7 +157,7 @@ pub const DirectAllocator = struct { |
| 158 | 157 | const new_adjusted_addr = new_root_addr + offset; |
| 159 | 158 | assert(new_adjusted_addr % alignment == 0); |
| 160 | 159 | 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; | |
| 162 | 161 | return @intToPtr(&u8, new_adjusted_addr)[0..new_size]; |
| 163 | 162 | }, |
| 164 | 163 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -169,12 +168,14 @@ pub const DirectAllocator = struct { |
| 169 | 168 | const self = @fieldParentPtr(DirectAllocator, "allocator", allocator); |
| 170 | 169 | |
| 171 | 170 | switch (builtin.os) { |
| 172 | Os.linux, Os.macosx, Os.ios => { | |
| 171 | Os.linux, | |
| 172 | Os.macosx, | |
| 173 | Os.ios => { | |
| 173 | 174 | _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len); |
| 174 | 175 | }, |
| 175 | 176 | Os.windows => { |
| 176 | 177 | 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).*; | |
| 178 | 179 | const ptr = @intToPtr(os.windows.LPVOID, root_addr); |
| 179 | 180 | _ = os.windows.HeapFree(??self.heap_handle, 0, ptr); |
| 180 | 181 | }, |
| ... | ... | @@ -195,8 +196,8 @@ pub const ArenaAllocator = struct { |
| 195 | 196 | const BufNode = std.LinkedList([]u8).Node; |
| 196 | 197 | |
| 197 | 198 | pub fn init(child_allocator: &Allocator) ArenaAllocator { |
| 198 | return ArenaAllocator { | |
| 199 | .allocator = Allocator { | |
| 199 | return ArenaAllocator{ | |
| 200 | .allocator = Allocator{ | |
| 200 | 201 | .allocFn = alloc, |
| 201 | 202 | .reallocFn = realloc, |
| 202 | 203 | .freeFn = free, |
| ... | ... | @@ -228,7 +229,7 @@ pub const ArenaAllocator = struct { |
| 228 | 229 | const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len); |
| 229 | 230 | const buf_node_slice = ([]BufNode)(buf[0..@sizeOf(BufNode)]); |
| 230 | 231 | const buf_node = &buf_node_slice[0]; |
| 231 | *buf_node = BufNode { | |
| 232 | buf_node.* = BufNode{ | |
| 232 | 233 | .data = buf, |
| 233 | 234 | .prev = null, |
| 234 | 235 | .next = null, |
| ... | ... | @@ -253,7 +254,7 @@ pub const ArenaAllocator = struct { |
| 253 | 254 | cur_node = try self.createNode(cur_buf.len, n + alignment); |
| 254 | 255 | continue; |
| 255 | 256 | } |
| 256 | const result = cur_buf[adjusted_index .. new_end_index]; | |
| 257 | const result = cur_buf[adjusted_index..new_end_index]; | |
| 257 | 258 | self.end_index = new_end_index; |
| 258 | 259 | return result; |
| 259 | 260 | } |
| ... | ... | @@ -269,7 +270,7 @@ pub const ArenaAllocator = struct { |
| 269 | 270 | } |
| 270 | 271 | } |
| 271 | 272 | |
| 272 | fn free(allocator: &Allocator, bytes: []u8) void { } | |
| 273 | fn free(allocator: &Allocator, bytes: []u8) void {} | |
| 273 | 274 | }; |
| 274 | 275 | |
| 275 | 276 | pub const FixedBufferAllocator = struct { |
| ... | ... | @@ -278,8 +279,8 @@ pub const FixedBufferAllocator = struct { |
| 278 | 279 | buffer: []u8, |
| 279 | 280 | |
| 280 | 281 | pub fn init(buffer: []u8) FixedBufferAllocator { |
| 281 | return FixedBufferAllocator { | |
| 282 | .allocator = Allocator { | |
| 282 | return FixedBufferAllocator{ | |
| 283 | .allocator = Allocator{ | |
| 283 | 284 | .allocFn = alloc, |
| 284 | 285 | .reallocFn = realloc, |
| 285 | 286 | .freeFn = free, |
| ... | ... | @@ -299,7 +300,7 @@ pub const FixedBufferAllocator = struct { |
| 299 | 300 | if (new_end_index > self.buffer.len) { |
| 300 | 301 | return error.OutOfMemory; |
| 301 | 302 | } |
| 302 | const result = self.buffer[adjusted_index .. new_end_index]; | |
| 303 | const result = self.buffer[adjusted_index..new_end_index]; | |
| 303 | 304 | self.end_index = new_end_index; |
| 304 | 305 | |
| 305 | 306 | return result; |
| ... | ... | @@ -315,7 +316,7 @@ pub const FixedBufferAllocator = struct { |
| 315 | 316 | } |
| 316 | 317 | } |
| 317 | 318 | |
| 318 | fn free(allocator: &Allocator, bytes: []u8) void { } | |
| 319 | fn free(allocator: &Allocator, bytes: []u8) void {} | |
| 319 | 320 | }; |
| 320 | 321 | |
| 321 | 322 | /// lock free |
| ... | ... | @@ -325,8 +326,8 @@ pub const ThreadSafeFixedBufferAllocator = struct { |
| 325 | 326 | buffer: []u8, |
| 326 | 327 | |
| 327 | 328 | pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator { |
| 328 | return ThreadSafeFixedBufferAllocator { | |
| 329 | .allocator = Allocator { | |
| 329 | return ThreadSafeFixedBufferAllocator{ | |
| 330 | .allocator = Allocator{ | |
| 330 | 331 | .allocFn = alloc, |
| 331 | 332 | .reallocFn = realloc, |
| 332 | 333 | .freeFn = free, |
| ... | ... | @@ -348,8 +349,7 @@ pub const ThreadSafeFixedBufferAllocator = struct { |
| 348 | 349 | if (new_end_index > self.buffer.len) { |
| 349 | 350 | return error.OutOfMemory; |
| 350 | 351 | } |
| 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]; | |
| 353 | 353 | } |
| 354 | 354 | } |
| 355 | 355 | |
| ... | ... | @@ -363,11 +363,9 @@ pub const ThreadSafeFixedBufferAllocator = struct { |
| 363 | 363 | } |
| 364 | 364 | } |
| 365 | 365 | |
| 366 | fn free(allocator: &Allocator, bytes: []u8) void { } | |
| 366 | fn free(allocator: &Allocator, bytes: []u8) void {} | |
| 367 | 367 | }; |
| 368 | 368 | |
| 369 | ||
| 370 | ||
| 371 | 369 | test "c_allocator" { |
| 372 | 370 | if (builtin.link_libc) { |
| 373 | 371 | var slice = c_allocator.alloc(u8, 50) catch return; |
| ... | ... | @@ -415,8 +413,8 @@ fn testAllocator(allocator: &mem.Allocator) !void { |
| 415 | 413 | var slice = try allocator.alloc(&i32, 100); |
| 416 | 414 | |
| 417 | 415 | for (slice) |*item, i| { |
| 418 | *item = try allocator.create(i32); | |
| 419 | **item = i32(i); | |
| 416 | item.* = try allocator.create(i32); | |
| 417 | item.*.* = i32(i); | |
| 420 | 418 | } |
| 421 | 419 | |
| 422 | 420 | for (slice) |item, i| { |
| ... | ... | @@ -434,26 +432,26 @@ fn testAllocator(allocator: &mem.Allocator) !void { |
| 434 | 432 | fn testAllocatorLargeAlignment(allocator: &mem.Allocator) mem.Allocator.Error!void { |
| 435 | 433 | //Maybe a platform's page_size is actually the same as or |
| 436 | 434 | // very near usize? |
| 437 | if(os.page_size << 2 > @maxValue(usize)) return; | |
| 438 | ||
| 435 | if (os.page_size << 2 > @maxValue(usize)) return; | |
| 436 | ||
| 439 | 437 | const USizeShift = @IntType(false, std.math.log2(usize.bit_count)); |
| 440 | 438 | const large_align = u29(os.page_size << 2); |
| 441 | ||
| 439 | ||
| 442 | 440 | var align_mask: usize = undefined; |
| 443 | 441 | _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask); |
| 444 | ||
| 442 | ||
| 445 | 443 | var slice = try allocator.allocFn(allocator, 500, large_align); |
| 446 | 444 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 447 | ||
| 445 | ||
| 448 | 446 | slice = try allocator.reallocFn(allocator, slice, 100, large_align); |
| 449 | 447 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 450 | ||
| 448 | ||
| 451 | 449 | slice = try allocator.reallocFn(allocator, slice, 5000, large_align); |
| 452 | 450 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 453 | ||
| 451 | ||
| 454 | 452 | slice = try allocator.reallocFn(allocator, slice, 10, large_align); |
| 455 | 453 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 456 | ||
| 454 | ||
| 457 | 455 | slice = try allocator.reallocFn(allocator, slice, 20000, large_align); |
| 458 | 456 | debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); |
| 459 | 457 |
std/io.zig+18-47| ... | ... | @@ -18,32 +18,17 @@ const is_windows = builtin.os == builtin.Os.windows; |
| 18 | 18 | const GetStdIoErrs = os.WindowsGetStdHandleErrs; |
| 19 | 19 | |
| 20 | 20 | pub 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; | |
| 27 | 22 | return File.openHandle(handle); |
| 28 | 23 | } |
| 29 | 24 | |
| 30 | 25 | pub 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; | |
| 37 | 27 | return File.openHandle(handle); |
| 38 | 28 | } |
| 39 | 29 | |
| 40 | 30 | pub 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; | |
| 47 | 32 | return File.openHandle(handle); |
| 48 | 33 | } |
| 49 | 34 | |
| ... | ... | @@ -56,11 +41,9 @@ pub const FileInStream = struct { |
| 56 | 41 | pub const Stream = InStream(Error); |
| 57 | 42 | |
| 58 | 43 | pub fn init(file: &File) FileInStream { |
| 59 | return FileInStream { | |
| 44 | return FileInStream{ | |
| 60 | 45 | .file = file, |
| 61 | .stream = Stream { | |
| 62 | .readFn = readFn, | |
| 63 | }, | |
| 46 | .stream = Stream{ .readFn = readFn }, | |
| 64 | 47 | }; |
| 65 | 48 | } |
| 66 | 49 | |
| ... | ... | @@ -79,11 +62,9 @@ pub const FileOutStream = struct { |
| 79 | 62 | pub const Stream = OutStream(Error); |
| 80 | 63 | |
| 81 | 64 | pub fn init(file: &File) FileOutStream { |
| 82 | return FileOutStream { | |
| 65 | return FileOutStream{ | |
| 83 | 66 | .file = file, |
| 84 | .stream = Stream { | |
| 85 | .writeFn = writeFn, | |
| 86 | }, | |
| 67 | .stream = Stream{ .writeFn = writeFn }, | |
| 87 | 68 | }; |
| 88 | 69 | } |
| 89 | 70 | |
| ... | ... | @@ -121,8 +102,7 @@ pub fn InStream(comptime ReadError: type) type { |
| 121 | 102 | } |
| 122 | 103 | |
| 123 | 104 | 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; | |
| 126 | 106 | try buffer.resize(new_buf_size); |
| 127 | 107 | } |
| 128 | 108 | } |
| ... | ... | @@ -165,9 +145,7 @@ pub fn InStream(comptime ReadError: type) type { |
| 165 | 145 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. |
| 166 | 146 | /// Caller owns returned memory. |
| 167 | 147 | /// 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 { | |
| 171 | 149 | var buf = Buffer.initNull(allocator); |
| 172 | 150 | defer buf.deinit(); |
| 173 | 151 | |
| ... | ... | @@ -283,7 +261,7 @@ pub fn BufferedInStream(comptime Error: type) type { |
| 283 | 261 | pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) type { |
| 284 | 262 | return struct { |
| 285 | 263 | const Self = this; |
| 286 | const Stream = InStream(Error); | |
| 264 | const Stream = InStream(Error); | |
| 287 | 265 | |
| 288 | 266 | pub stream: Stream, |
| 289 | 267 | |
| ... | ... | @@ -294,7 +272,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) |
| 294 | 272 | end_index: usize, |
| 295 | 273 | |
| 296 | 274 | pub fn init(unbuffered_in_stream: &Stream) Self { |
| 297 | return Self { | |
| 275 | return Self{ | |
| 298 | 276 | .unbuffered_in_stream = unbuffered_in_stream, |
| 299 | 277 | .buffer = undefined, |
| 300 | 278 | |
| ... | ... | @@ -305,9 +283,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type) |
| 305 | 283 | .start_index = buffer_size, |
| 306 | 284 | .end_index = buffer_size, |
| 307 | 285 | |
| 308 | .stream = Stream { | |
| 309 | .readFn = readFn, | |
| 310 | }, | |
| 286 | .stream = Stream{ .readFn = readFn }, | |
| 311 | 287 | }; |
| 312 | 288 | } |
| 313 | 289 | |
| ... | ... | @@ -368,13 +344,11 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamEr |
| 368 | 344 | index: usize, |
| 369 | 345 | |
| 370 | 346 | pub fn init(unbuffered_out_stream: &Stream) Self { |
| 371 | return Self { | |
| 347 | return Self{ | |
| 372 | 348 | .unbuffered_out_stream = unbuffered_out_stream, |
| 373 | 349 | .buffer = undefined, |
| 374 | 350 | .index = 0, |
| 375 | .stream = Stream { | |
| 376 | .writeFn = writeFn, | |
| 377 | }, | |
| 351 | .stream = Stream{ .writeFn = writeFn }, | |
| 378 | 352 | }; |
| 379 | 353 | } |
| 380 | 354 | |
| ... | ... | @@ -416,11 +390,9 @@ pub const BufferOutStream = struct { |
| 416 | 390 | pub const Stream = OutStream(Error); |
| 417 | 391 | |
| 418 | 392 | pub fn init(buffer: &Buffer) BufferOutStream { |
| 419 | return BufferOutStream { | |
| 393 | return BufferOutStream{ | |
| 420 | 394 | .buffer = buffer, |
| 421 | .stream = Stream { | |
| 422 | .writeFn = writeFn, | |
| 423 | }, | |
| 395 | .stream = Stream{ .writeFn = writeFn }, | |
| 424 | 396 | }; |
| 425 | 397 | } |
| 426 | 398 | |
| ... | ... | @@ -430,7 +402,6 @@ pub const BufferOutStream = struct { |
| 430 | 402 | } |
| 431 | 403 | }; |
| 432 | 404 | |
| 433 | ||
| 434 | 405 | pub const BufferedAtomicFile = struct { |
| 435 | 406 | atomic_file: os.AtomicFile, |
| 436 | 407 | file_stream: FileOutStream, |
| ... | ... | @@ -441,7 +412,7 @@ pub const BufferedAtomicFile = struct { |
| 441 | 412 | var self = try allocator.create(BufferedAtomicFile); |
| 442 | 413 | errdefer allocator.destroy(self); |
| 443 | 414 | |
| 444 | *self = BufferedAtomicFile { | |
| 415 | self.* = BufferedAtomicFile{ | |
| 445 | 416 | .atomic_file = undefined, |
| 446 | 417 | .file_stream = undefined, |
| 447 | 418 | .buffered_stream = undefined, |
| ... | ... | @@ -489,7 +460,7 @@ pub fn readLine(buf: []u8) !usize { |
| 489 | 460 | '\r' => { |
| 490 | 461 | // trash the following \n |
| 491 | 462 | _ = stream.readByte() catch return error.EndOfFile; |
| 492 | return index; | |
| 463 | return index; | |
| 493 | 464 | }, |
| 494 | 465 | '\n' => return index, |
| 495 | 466 | else => { |
std/json.zig+124-83| ... | ... | @@ -35,7 +35,7 @@ pub const Token = struct { |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | 37 | pub fn init(id: Id, count: usize, offset: u1) Token { |
| 38 | return Token { | |
| 38 | return Token{ | |
| 39 | 39 | .id = id, |
| 40 | 40 | .offset = offset, |
| 41 | 41 | .string_has_escape = false, |
| ... | ... | @@ -45,7 +45,7 @@ pub const Token = struct { |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | 47 | pub fn initString(count: usize, has_unicode_escape: bool) Token { |
| 48 | return Token { | |
| 48 | return Token{ | |
| 49 | 49 | .id = Id.String, |
| 50 | 50 | .offset = 0, |
| 51 | 51 | .string_has_escape = has_unicode_escape, |
| ... | ... | @@ -55,7 +55,7 @@ pub const Token = struct { |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | pub fn initNumber(count: usize, number_is_integer: bool) Token { |
| 58 | return Token { | |
| 58 | return Token{ | |
| 59 | 59 | .id = Id.Number, |
| 60 | 60 | .offset = 0, |
| 61 | 61 | .string_has_escape = false, |
| ... | ... | @@ -66,7 +66,7 @@ pub const Token = struct { |
| 66 | 66 | |
| 67 | 67 | // A marker token is a zero-length |
| 68 | 68 | pub fn initMarker(id: Id) Token { |
| 69 | return Token { | |
| 69 | return Token{ | |
| 70 | 70 | .id = id, |
| 71 | 71 | .offset = 0, |
| 72 | 72 | .string_has_escape = false, |
| ... | ... | @@ -77,7 +77,7 @@ pub const Token = struct { |
| 77 | 77 | |
| 78 | 78 | // Slice into the underlying input string. |
| 79 | 79 | 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]; | |
| 81 | 81 | } |
| 82 | 82 | }; |
| 83 | 83 | |
| ... | ... | @@ -105,8 +105,8 @@ const StreamingJsonParser = struct { |
| 105 | 105 | stack: u256, |
| 106 | 106 | stack_used: u8, |
| 107 | 107 | |
| 108 | const object_bit = 0; | |
| 109 | const array_bit = 1; | |
| 108 | const object_bit = 0; | |
| 109 | const array_bit = 1; | |
| 110 | 110 | const max_stack_size = @maxValue(u8); |
| 111 | 111 | |
| 112 | 112 | pub fn init() StreamingJsonParser { |
| ... | ... | @@ -120,7 +120,7 @@ const StreamingJsonParser = struct { |
| 120 | 120 | p.count = 0; |
| 121 | 121 | // Set before ever read in main transition function |
| 122 | 122 | 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 | |
| 124 | 124 | p.stack = 0; |
| 125 | 125 | p.stack_used = 0; |
| 126 | 126 | p.complete = false; |
| ... | ... | @@ -181,7 +181,7 @@ const StreamingJsonParser = struct { |
| 181 | 181 | } |
| 182 | 182 | }; |
| 183 | 183 | |
| 184 | pub const Error = error { | |
| 184 | pub const Error = error{ | |
| 185 | 185 | InvalidTopLevel, |
| 186 | 186 | TooManyNestedItems, |
| 187 | 187 | TooManyClosingItems, |
| ... | ... | @@ -206,8 +206,8 @@ const StreamingJsonParser = struct { |
| 206 | 206 | // |
| 207 | 207 | // There is currently no error recovery on a bad stream. |
| 208 | 208 | 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; | |
| 211 | 211 | p.count += 1; |
| 212 | 212 | |
| 213 | 213 | // unlikely |
| ... | ... | @@ -228,7 +228,7 @@ const StreamingJsonParser = struct { |
| 228 | 228 | p.state = State.ValueBegin; |
| 229 | 229 | p.after_string_state = State.ObjectSeparator; |
| 230 | 230 | |
| 231 | *token = Token.initMarker(Token.Id.ObjectBegin); | |
| 231 | token.* = Token.initMarker(Token.Id.ObjectBegin); | |
| 232 | 232 | }, |
| 233 | 233 | '[' => { |
| 234 | 234 | p.stack <<= 1; |
| ... | ... | @@ -238,7 +238,7 @@ const StreamingJsonParser = struct { |
| 238 | 238 | p.state = State.ValueBegin; |
| 239 | 239 | p.after_string_state = State.ValueEnd; |
| 240 | 240 | |
| 241 | *token = Token.initMarker(Token.Id.ArrayBegin); | |
| 241 | token.* = Token.initMarker(Token.Id.ArrayBegin); | |
| 242 | 242 | }, |
| 243 | 243 | '-' => { |
| 244 | 244 | p.number_is_integer = true; |
| ... | ... | @@ -281,7 +281,10 @@ const StreamingJsonParser = struct { |
| 281 | 281 | p.after_value_state = State.TopLevelEnd; |
| 282 | 282 | p.count = 0; |
| 283 | 283 | }, |
| 284 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 284 | 0x09, | |
| 285 | 0x0A, | |
| 286 | 0x0D, | |
| 287 | 0x20 => { | |
| 285 | 288 | // whitespace |
| 286 | 289 | }, |
| 287 | 290 | else => { |
| ... | ... | @@ -290,7 +293,10 @@ const StreamingJsonParser = struct { |
| 290 | 293 | }, |
| 291 | 294 | |
| 292 | 295 | State.TopLevelEnd => switch (c) { |
| 293 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 296 | 0x09, | |
| 297 | 0x0A, | |
| 298 | 0x0D, | |
| 299 | 0x20 => { | |
| 294 | 300 | // whitespace |
| 295 | 301 | }, |
| 296 | 302 | else => { |
| ... | ... | @@ -324,7 +330,7 @@ const StreamingJsonParser = struct { |
| 324 | 330 | else => {}, |
| 325 | 331 | } |
| 326 | 332 | |
| 327 | *token = Token.initMarker(Token.Id.ObjectEnd); | |
| 333 | token.* = Token.initMarker(Token.Id.ObjectEnd); | |
| 328 | 334 | }, |
| 329 | 335 | ']' => { |
| 330 | 336 | if (p.stack & 1 != array_bit) { |
| ... | ... | @@ -348,7 +354,7 @@ const StreamingJsonParser = struct { |
| 348 | 354 | else => {}, |
| 349 | 355 | } |
| 350 | 356 | |
| 351 | *token = Token.initMarker(Token.Id.ArrayEnd); | |
| 357 | token.* = Token.initMarker(Token.Id.ArrayEnd); | |
| 352 | 358 | }, |
| 353 | 359 | '{' => { |
| 354 | 360 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -362,7 +368,7 @@ const StreamingJsonParser = struct { |
| 362 | 368 | p.state = State.ValueBegin; |
| 363 | 369 | p.after_string_state = State.ObjectSeparator; |
| 364 | 370 | |
| 365 | *token = Token.initMarker(Token.Id.ObjectBegin); | |
| 371 | token.* = Token.initMarker(Token.Id.ObjectBegin); | |
| 366 | 372 | }, |
| 367 | 373 | '[' => { |
| 368 | 374 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -376,7 +382,7 @@ const StreamingJsonParser = struct { |
| 376 | 382 | p.state = State.ValueBegin; |
| 377 | 383 | p.after_string_state = State.ValueEnd; |
| 378 | 384 | |
| 379 | *token = Token.initMarker(Token.Id.ArrayBegin); | |
| 385 | token.* = Token.initMarker(Token.Id.ArrayBegin); | |
| 380 | 386 | }, |
| 381 | 387 | '-' => { |
| 382 | 388 | p.state = State.Number; |
| ... | ... | @@ -406,7 +412,10 @@ const StreamingJsonParser = struct { |
| 406 | 412 | p.state = State.NullLiteral1; |
| 407 | 413 | p.count = 0; |
| 408 | 414 | }, |
| 409 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 415 | 0x09, | |
| 416 | 0x0A, | |
| 417 | 0x0D, | |
| 418 | 0x20 => { | |
| 410 | 419 | // whitespace |
| 411 | 420 | }, |
| 412 | 421 | else => { |
| ... | ... | @@ -428,7 +437,7 @@ const StreamingJsonParser = struct { |
| 428 | 437 | p.state = State.ValueBegin; |
| 429 | 438 | p.after_string_state = State.ObjectSeparator; |
| 430 | 439 | |
| 431 | *token = Token.initMarker(Token.Id.ObjectBegin); | |
| 440 | token.* = Token.initMarker(Token.Id.ObjectBegin); | |
| 432 | 441 | }, |
| 433 | 442 | '[' => { |
| 434 | 443 | if (p.stack_used == max_stack_size) { |
| ... | ... | @@ -442,7 +451,7 @@ const StreamingJsonParser = struct { |
| 442 | 451 | p.state = State.ValueBegin; |
| 443 | 452 | p.after_string_state = State.ValueEnd; |
| 444 | 453 | |
| 445 | *token = Token.initMarker(Token.Id.ArrayBegin); | |
| 454 | token.* = Token.initMarker(Token.Id.ArrayBegin); | |
| 446 | 455 | }, |
| 447 | 456 | '-' => { |
| 448 | 457 | p.state = State.Number; |
| ... | ... | @@ -472,7 +481,10 @@ const StreamingJsonParser = struct { |
| 472 | 481 | p.state = State.NullLiteral1; |
| 473 | 482 | p.count = 0; |
| 474 | 483 | }, |
| 475 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 484 | 0x09, | |
| 485 | 0x0A, | |
| 486 | 0x0D, | |
| 487 | 0x20 => { | |
| 476 | 488 | // whitespace |
| 477 | 489 | }, |
| 478 | 490 | else => { |
| ... | ... | @@ -501,7 +513,7 @@ const StreamingJsonParser = struct { |
| 501 | 513 | p.state = State.TopLevelEnd; |
| 502 | 514 | } |
| 503 | 515 | |
| 504 | *token = Token.initMarker(Token.Id.ArrayEnd); | |
| 516 | token.* = Token.initMarker(Token.Id.ArrayEnd); | |
| 505 | 517 | }, |
| 506 | 518 | '}' => { |
| 507 | 519 | if (p.stack_used == 0) { |
| ... | ... | @@ -519,9 +531,12 @@ const StreamingJsonParser = struct { |
| 519 | 531 | p.state = State.TopLevelEnd; |
| 520 | 532 | } |
| 521 | 533 | |
| 522 | *token = Token.initMarker(Token.Id.ObjectEnd); | |
| 534 | token.* = Token.initMarker(Token.Id.ObjectEnd); | |
| 523 | 535 | }, |
| 524 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 536 | 0x09, | |
| 537 | 0x0A, | |
| 538 | 0x0D, | |
| 539 | 0x20 => { | |
| 525 | 540 | // whitespace |
| 526 | 541 | }, |
| 527 | 542 | else => { |
| ... | ... | @@ -534,7 +549,10 @@ const StreamingJsonParser = struct { |
| 534 | 549 | p.state = State.ValueBegin; |
| 535 | 550 | p.after_string_state = State.ValueEnd; |
| 536 | 551 | }, |
| 537 | 0x09, 0x0A, 0x0D, 0x20 => { | |
| 552 | 0x09, | |
| 553 | 0x0A, | |
| 554 | 0x0D, | |
| 555 | 0x20 => { | |
| 538 | 556 | // whitespace |
| 539 | 557 | }, |
| 540 | 558 | else => { |
| ... | ... | @@ -553,12 +571,15 @@ const StreamingJsonParser = struct { |
| 553 | 571 | p.complete = true; |
| 554 | 572 | } |
| 555 | 573 | |
| 556 | *token = Token.initString(p.count - 1, p.string_has_escape); | |
| 574 | token.* = Token.initString(p.count - 1, p.string_has_escape); | |
| 557 | 575 | }, |
| 558 | 576 | '\\' => { |
| 559 | 577 | p.state = State.StringEscapeCharacter; |
| 560 | 578 | }, |
| 561 | 0x20, 0x21, 0x23 ... 0x5B, 0x5D ... 0x7F => { | |
| 579 | 0x20, | |
| 580 | 0x21, | |
| 581 | 0x23 ... 0x5B, | |
| 582 | 0x5D ... 0x7F => { | |
| 562 | 583 | // non-control ascii |
| 563 | 584 | }, |
| 564 | 585 | 0xC0 ... 0xDF => { |
| ... | ... | @@ -599,7 +620,14 @@ const StreamingJsonParser = struct { |
| 599 | 620 | // The current JSONTestSuite tests rely on both of this behaviour being present |
| 600 | 621 | // however, so we default to the status quo where both are accepted until this |
| 601 | 622 | // is further clarified. |
| 602 | '"', '\\', '/', 'b', 'f', 'n', 'r', 't' => { | |
| 623 | '"', | |
| 624 | '\\', | |
| 625 | '/', | |
| 626 | 'b', | |
| 627 | 'f', | |
| 628 | 'n', | |
| 629 | 'r', | |
| 630 | 't' => { | |
| 603 | 631 | p.string_has_escape = true; |
| 604 | 632 | p.state = State.String; |
| 605 | 633 | }, |
| ... | ... | @@ -613,28 +641,36 @@ const StreamingJsonParser = struct { |
| 613 | 641 | }, |
| 614 | 642 | |
| 615 | 643 | State.StringEscapeHexUnicode4 => switch (c) { |
| 616 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 644 | '0' ... '9', | |
| 645 | 'A' ... 'F', | |
| 646 | 'a' ... 'f' => { | |
| 617 | 647 | p.state = State.StringEscapeHexUnicode3; |
| 618 | 648 | }, |
| 619 | 649 | else => return error.InvalidUnicodeHexSymbol, |
| 620 | 650 | }, |
| 621 | 651 | |
| 622 | 652 | State.StringEscapeHexUnicode3 => switch (c) { |
| 623 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 653 | '0' ... '9', | |
| 654 | 'A' ... 'F', | |
| 655 | 'a' ... 'f' => { | |
| 624 | 656 | p.state = State.StringEscapeHexUnicode2; |
| 625 | 657 | }, |
| 626 | 658 | else => return error.InvalidUnicodeHexSymbol, |
| 627 | 659 | }, |
| 628 | 660 | |
| 629 | 661 | State.StringEscapeHexUnicode2 => switch (c) { |
| 630 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 662 | '0' ... '9', | |
| 663 | 'A' ... 'F', | |
| 664 | 'a' ... 'f' => { | |
| 631 | 665 | p.state = State.StringEscapeHexUnicode1; |
| 632 | 666 | }, |
| 633 | 667 | else => return error.InvalidUnicodeHexSymbol, |
| 634 | 668 | }, |
| 635 | 669 | |
| 636 | 670 | State.StringEscapeHexUnicode1 => switch (c) { |
| 637 | '0' ... '9', 'A' ... 'F', 'a' ... 'f' => { | |
| 671 | '0' ... '9', | |
| 672 | 'A' ... 'F', | |
| 673 | 'a' ... 'f' => { | |
| 638 | 674 | p.state = State.String; |
| 639 | 675 | }, |
| 640 | 676 | else => return error.InvalidUnicodeHexSymbol, |
| ... | ... | @@ -662,13 +698,14 @@ const StreamingJsonParser = struct { |
| 662 | 698 | p.number_is_integer = false; |
| 663 | 699 | p.state = State.NumberFractionalRequired; |
| 664 | 700 | }, |
| 665 | 'e', 'E' => { | |
| 701 | 'e', | |
| 702 | 'E' => { | |
| 666 | 703 | p.number_is_integer = false; |
| 667 | 704 | p.state = State.NumberExponent; |
| 668 | 705 | }, |
| 669 | 706 | else => { |
| 670 | 707 | 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); | |
| 672 | 709 | return true; |
| 673 | 710 | }, |
| 674 | 711 | } |
| ... | ... | @@ -681,7 +718,8 @@ const StreamingJsonParser = struct { |
| 681 | 718 | p.number_is_integer = false; |
| 682 | 719 | p.state = State.NumberFractionalRequired; |
| 683 | 720 | }, |
| 684 | 'e', 'E' => { | |
| 721 | 'e', | |
| 722 | 'E' => { | |
| 685 | 723 | p.number_is_integer = false; |
| 686 | 724 | p.state = State.NumberExponent; |
| 687 | 725 | }, |
| ... | ... | @@ -690,7 +728,7 @@ const StreamingJsonParser = struct { |
| 690 | 728 | }, |
| 691 | 729 | else => { |
| 692 | 730 | 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); | |
| 694 | 732 | return true; |
| 695 | 733 | }, |
| 696 | 734 | } |
| ... | ... | @@ -714,13 +752,14 @@ const StreamingJsonParser = struct { |
| 714 | 752 | '0' ... '9' => { |
| 715 | 753 | // another digit |
| 716 | 754 | }, |
| 717 | 'e', 'E' => { | |
| 755 | 'e', | |
| 756 | 'E' => { | |
| 718 | 757 | p.number_is_integer = false; |
| 719 | 758 | p.state = State.NumberExponent; |
| 720 | 759 | }, |
| 721 | 760 | else => { |
| 722 | 761 | 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); | |
| 724 | 763 | return true; |
| 725 | 764 | }, |
| 726 | 765 | } |
| ... | ... | @@ -729,20 +768,22 @@ const StreamingJsonParser = struct { |
| 729 | 768 | State.NumberMaybeExponent => { |
| 730 | 769 | p.complete = p.after_value_state == State.TopLevelEnd; |
| 731 | 770 | switch (c) { |
| 732 | 'e', 'E' => { | |
| 771 | 'e', | |
| 772 | 'E' => { | |
| 733 | 773 | p.number_is_integer = false; |
| 734 | 774 | p.state = State.NumberExponent; |
| 735 | 775 | }, |
| 736 | 776 | else => { |
| 737 | 777 | 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); | |
| 739 | 779 | return true; |
| 740 | 780 | }, |
| 741 | 781 | } |
| 742 | 782 | }, |
| 743 | 783 | |
| 744 | 784 | State.NumberExponent => switch (c) { |
| 745 | '-', '+', => { | |
| 785 | '-', | |
| 786 | '+' => { | |
| 746 | 787 | p.complete = false; |
| 747 | 788 | p.state = State.NumberExponentDigitsRequired; |
| 748 | 789 | }, |
| ... | ... | @@ -773,7 +814,7 @@ const StreamingJsonParser = struct { |
| 773 | 814 | }, |
| 774 | 815 | else => { |
| 775 | 816 | 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); | |
| 777 | 818 | return true; |
| 778 | 819 | }, |
| 779 | 820 | } |
| ... | ... | @@ -793,7 +834,7 @@ const StreamingJsonParser = struct { |
| 793 | 834 | 'e' => { |
| 794 | 835 | p.state = p.after_value_state; |
| 795 | 836 | 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); | |
| 797 | 838 | }, |
| 798 | 839 | else => { |
| 799 | 840 | return error.InvalidLiteral; |
| ... | ... | @@ -819,7 +860,7 @@ const StreamingJsonParser = struct { |
| 819 | 860 | 'e' => { |
| 820 | 861 | p.state = p.after_value_state; |
| 821 | 862 | 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); | |
| 823 | 864 | }, |
| 824 | 865 | else => { |
| 825 | 866 | return error.InvalidLiteral; |
| ... | ... | @@ -840,7 +881,7 @@ const StreamingJsonParser = struct { |
| 840 | 881 | 'l' => { |
| 841 | 882 | p.state = p.after_value_state; |
| 842 | 883 | 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); | |
| 844 | 885 | }, |
| 845 | 886 | else => { |
| 846 | 887 | return error.InvalidLiteral; |
| ... | ... | @@ -895,7 +936,7 @@ pub const Value = union(enum) { |
| 895 | 936 | Object: ObjectMap, |
| 896 | 937 | |
| 897 | 938 | pub fn dump(self: &const Value) void { |
| 898 | switch (*self) { | |
| 939 | switch (self.*) { | |
| 899 | 940 | Value.Null => { |
| 900 | 941 | std.debug.warn("null"); |
| 901 | 942 | }, |
| ... | ... | @@ -950,7 +991,7 @@ pub const Value = union(enum) { |
| 950 | 991 | } |
| 951 | 992 | |
| 952 | 993 | fn dumpIndentLevel(self: &const Value, indent: usize, level: usize) void { |
| 953 | switch (*self) { | |
| 994 | switch (self.*) { | |
| 954 | 995 | Value.Null => { |
| 955 | 996 | std.debug.warn("null"); |
| 956 | 997 | }, |
| ... | ... | @@ -1027,7 +1068,7 @@ const JsonParser = struct { |
| 1027 | 1068 | }; |
| 1028 | 1069 | |
| 1029 | 1070 | pub fn init(allocator: &Allocator, copy_strings: bool) JsonParser { |
| 1030 | return JsonParser { | |
| 1071 | return JsonParser{ | |
| 1031 | 1072 | .allocator = allocator, |
| 1032 | 1073 | .state = State.Simple, |
| 1033 | 1074 | .copy_strings = copy_strings, |
| ... | ... | @@ -1082,7 +1123,7 @@ const JsonParser = struct { |
| 1082 | 1123 | |
| 1083 | 1124 | std.debug.assert(p.stack.len == 1); |
| 1084 | 1125 | |
| 1085 | return ValueTree { | |
| 1126 | return ValueTree{ | |
| 1086 | 1127 | .arena = arena, |
| 1087 | 1128 | .root = p.stack.at(0), |
| 1088 | 1129 | }; |
| ... | ... | @@ -1115,11 +1156,11 @@ const JsonParser = struct { |
| 1115 | 1156 | |
| 1116 | 1157 | switch (token.id) { |
| 1117 | 1158 | Token.Id.ObjectBegin => { |
| 1118 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); | |
| 1159 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | |
| 1119 | 1160 | p.state = State.ObjectKey; |
| 1120 | 1161 | }, |
| 1121 | 1162 | 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) }); | |
| 1123 | 1164 | p.state = State.ArrayValue; |
| 1124 | 1165 | }, |
| 1125 | 1166 | Token.Id.String => { |
| ... | ... | @@ -1133,12 +1174,12 @@ const JsonParser = struct { |
| 1133 | 1174 | p.state = State.ObjectKey; |
| 1134 | 1175 | }, |
| 1135 | 1176 | Token.Id.True => { |
| 1136 | _ = try object.put(key, Value { .Bool = true }); | |
| 1177 | _ = try object.put(key, Value{ .Bool = true }); | |
| 1137 | 1178 | _ = p.stack.pop(); |
| 1138 | 1179 | p.state = State.ObjectKey; |
| 1139 | 1180 | }, |
| 1140 | 1181 | Token.Id.False => { |
| 1141 | _ = try object.put(key, Value { .Bool = false }); | |
| 1182 | _ = try object.put(key, Value{ .Bool = false }); | |
| 1142 | 1183 | _ = p.stack.pop(); |
| 1143 | 1184 | p.state = State.ObjectKey; |
| 1144 | 1185 | }, |
| ... | ... | @@ -1165,11 +1206,11 @@ const JsonParser = struct { |
| 1165 | 1206 | try p.pushToParent(value); |
| 1166 | 1207 | }, |
| 1167 | 1208 | Token.Id.ObjectBegin => { |
| 1168 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); | |
| 1209 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | |
| 1169 | 1210 | p.state = State.ObjectKey; |
| 1170 | 1211 | }, |
| 1171 | 1212 | 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) }); | |
| 1173 | 1214 | p.state = State.ArrayValue; |
| 1174 | 1215 | }, |
| 1175 | 1216 | Token.Id.String => { |
| ... | ... | @@ -1179,10 +1220,10 @@ const JsonParser = struct { |
| 1179 | 1220 | try array.append(try p.parseNumber(token, input, i)); |
| 1180 | 1221 | }, |
| 1181 | 1222 | Token.Id.True => { |
| 1182 | try array.append(Value { .Bool = true }); | |
| 1223 | try array.append(Value{ .Bool = true }); | |
| 1183 | 1224 | }, |
| 1184 | 1225 | Token.Id.False => { |
| 1185 | try array.append(Value { .Bool = false }); | |
| 1226 | try array.append(Value{ .Bool = false }); | |
| 1186 | 1227 | }, |
| 1187 | 1228 | Token.Id.Null => { |
| 1188 | 1229 | try array.append(Value.Null); |
| ... | ... | @@ -1194,11 +1235,11 @@ const JsonParser = struct { |
| 1194 | 1235 | }, |
| 1195 | 1236 | State.Simple => switch (token.id) { |
| 1196 | 1237 | Token.Id.ObjectBegin => { |
| 1197 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); | |
| 1238 | try p.stack.append(Value{ .Object = ObjectMap.init(allocator) }); | |
| 1198 | 1239 | p.state = State.ObjectKey; |
| 1199 | 1240 | }, |
| 1200 | 1241 | 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) }); | |
| 1202 | 1243 | p.state = State.ArrayValue; |
| 1203 | 1244 | }, |
| 1204 | 1245 | Token.Id.String => { |
| ... | ... | @@ -1208,15 +1249,16 @@ const JsonParser = struct { |
| 1208 | 1249 | try p.stack.append(try p.parseNumber(token, input, i)); |
| 1209 | 1250 | }, |
| 1210 | 1251 | Token.Id.True => { |
| 1211 | try p.stack.append(Value { .Bool = true }); | |
| 1252 | try p.stack.append(Value{ .Bool = true }); | |
| 1212 | 1253 | }, |
| 1213 | 1254 | Token.Id.False => { |
| 1214 | try p.stack.append(Value { .Bool = false }); | |
| 1255 | try p.stack.append(Value{ .Bool = false }); | |
| 1215 | 1256 | }, |
| 1216 | 1257 | Token.Id.Null => { |
| 1217 | 1258 | try p.stack.append(Value.Null); |
| 1218 | 1259 | }, |
| 1219 | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { | |
| 1260 | Token.Id.ObjectEnd, | |
| 1261 | Token.Id.ArrayEnd => { | |
| 1220 | 1262 | unreachable; |
| 1221 | 1263 | }, |
| 1222 | 1264 | }, |
| ... | ... | @@ -1248,15 +1290,14 @@ const JsonParser = struct { |
| 1248 | 1290 | // TODO: We don't strictly have to copy values which do not contain any escape |
| 1249 | 1291 | // characters if flagged with the option. |
| 1250 | 1292 | 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) }; | |
| 1252 | 1294 | } |
| 1253 | 1295 | |
| 1254 | 1296 | fn parseNumber(p: &JsonParser, token: &const Token, input: []const u8, i: usize) !Value { |
| 1255 | 1297 | 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) } | |
| 1257 | 1299 | else |
| 1258 | @panic("TODO: fmt.parseFloat not yet implemented") | |
| 1259 | ; | |
| 1300 | @panic("TODO: fmt.parseFloat not yet implemented"); | |
| 1260 | 1301 | } |
| 1261 | 1302 | }; |
| 1262 | 1303 | |
| ... | ... | @@ -1267,21 +1308,21 @@ test "json parser dynamic" { |
| 1267 | 1308 | defer p.deinit(); |
| 1268 | 1309 | |
| 1269 | 1310 | 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 | ; | |
| 1285 | 1326 | |
| 1286 | 1327 | var tree = try p.parse(s); |
| 1287 | 1328 | defer tree.deinit(); |
std/linked_list.zig+55-40| ... | ... | @@ -26,10 +26,10 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 26 | 26 | data: T, |
| 27 | 27 | |
| 28 | 28 | pub fn init(value: &const T) Node { |
| 29 | return Node { | |
| 29 | return Node{ | |
| 30 | 30 | .prev = null, |
| 31 | 31 | .next = null, |
| 32 | .data = *value, | |
| 32 | .data = value.*, | |
| 33 | 33 | }; |
| 34 | 34 | } |
| 35 | 35 | |
| ... | ... | @@ -45,18 +45,18 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 45 | 45 | }; |
| 46 | 46 | |
| 47 | 47 | first: ?&Node, |
| 48 | last: ?&Node, | |
| 49 | len: usize, | |
| 48 | last: ?&Node, | |
| 49 | len: usize, | |
| 50 | 50 | |
| 51 | 51 | /// Initialize a linked list. |
| 52 | 52 | /// |
| 53 | 53 | /// Returns: |
| 54 | 54 | /// An empty linked list. |
| 55 | 55 | pub fn init() Self { |
| 56 | return Self { | |
| 56 | return Self{ | |
| 57 | 57 | .first = null, |
| 58 | .last = null, | |
| 59 | .len = 0, | |
| 58 | .last = null, | |
| 59 | .len = 0, | |
| 60 | 60 | }; |
| 61 | 61 | } |
| 62 | 62 | |
| ... | ... | @@ -131,7 +131,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 131 | 131 | } else { |
| 132 | 132 | // Empty list. |
| 133 | 133 | list.first = new_node; |
| 134 | list.last = new_node; | |
| 134 | list.last = new_node; | |
| 135 | 135 | new_node.prev = null; |
| 136 | 136 | new_node.next = null; |
| 137 | 137 | |
| ... | ... | @@ -217,7 +217,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 217 | 217 | pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) !&Node { |
| 218 | 218 | comptime assert(!isIntrusive()); |
| 219 | 219 | var node = try list.allocateNode(allocator); |
| 220 | *node = Node.init(data); | |
| 220 | node.* = Node.init(data); | |
| 221 | 221 | return node; |
| 222 | 222 | } |
| 223 | 223 | }; |
| ... | ... | @@ -227,11 +227,11 @@ test "basic linked list test" { |
| 227 | 227 | const allocator = debug.global_allocator; |
| 228 | 228 | var list = LinkedList(u32).init(); |
| 229 | 229 | |
| 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); | |
| 232 | 232 | 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); | |
| 235 | 235 | defer { |
| 236 | 236 | list.destroyNode(one, allocator); |
| 237 | 237 | list.destroyNode(two, allocator); |
| ... | ... | @@ -240,11 +240,11 @@ test "basic linked list test" { |
| 240 | 240 | list.destroyNode(five, allocator); |
| 241 | 241 | } |
| 242 | 242 | |
| 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} | |
| 248 | 248 | |
| 249 | 249 | // Traverse forwards. |
| 250 | 250 | { |
| ... | ... | @@ -266,13 +266,13 @@ test "basic linked list test" { |
| 266 | 266 | } |
| 267 | 267 | } |
| 268 | 268 | |
| 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} | |
| 272 | 272 | |
| 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); | |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | 278 | const ElementList = IntrusiveLinkedList(Element, "link"); |
| ... | ... | @@ -285,17 +285,32 @@ test "basic intrusive linked list test" { |
| 285 | 285 | const allocator = debug.global_allocator; |
| 286 | 286 | var list = ElementList.init(); |
| 287 | 287 | |
| 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 | }; | |
| 293 | 308 | |
| 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} | |
| 299 | 314 | |
| 300 | 315 | // Traverse forwards. |
| 301 | 316 | { |
| ... | ... | @@ -317,11 +332,11 @@ test "basic intrusive linked list test" { |
| 317 | 332 | } |
| 318 | 333 | } |
| 319 | 334 | |
| 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} | |
| 323 | 338 | |
| 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); | |
| 327 | 342 | } |
std/math/acos.zig+7-7| ... | ... | @@ -16,7 +16,7 @@ pub fn acos(x: var) @typeOf(x) { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | fn r32(z: f32) f32 { |
| 19 | const pS0 = 1.6666586697e-01; | |
| 19 | const pS0 = 1.6666586697e-01; | |
| 20 | 20 | const pS1 = -4.2743422091e-02; |
| 21 | 21 | const pS2 = -8.6563630030e-03; |
| 22 | 22 | const qS1 = -7.0662963390e-01; |
| ... | ... | @@ -74,16 +74,16 @@ fn acos32(x: f32) f32 { |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | 76 | fn r64(z: f64) f64 { |
| 77 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 77 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 78 | 78 | const pS1: f64 = -3.25565818622400915405e-01; |
| 79 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 79 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 80 | 80 | 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; | |
| 83 | 83 | const qS1: f64 = -2.40339491173441421878e+00; |
| 84 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 84 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 85 | 85 | const qS3: f64 = -6.88283971605453293030e-01; |
| 86 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 86 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 87 | 87 | |
| 88 | 88 | const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); |
| 89 | 89 | 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) { |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | fn r32(z: f32) f32 { |
| 20 | const pS0 = 1.6666586697e-01; | |
| 20 | const pS0 = 1.6666586697e-01; | |
| 21 | 21 | const pS1 = -4.2743422091e-02; |
| 22 | 22 | const pS2 = -8.6563630030e-03; |
| 23 | 23 | const qS1 = -7.0662963390e-01; |
| ... | ... | @@ -37,9 +37,9 @@ fn asin32(x: f32) f32 { |
| 37 | 37 | if (ix >= 0x3F800000) { |
| 38 | 38 | // |x| >= 1 |
| 39 | 39 | 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 | |
| 41 | 41 | } else { |
| 42 | return math.nan(f32); // asin(|x| > 1) is nan | |
| 42 | return math.nan(f32); // asin(|x| > 1) is nan | |
| 43 | 43 | } |
| 44 | 44 | } |
| 45 | 45 | |
| ... | ... | @@ -66,16 +66,16 @@ fn asin32(x: f32) f32 { |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | fn r64(z: f64) f64 { |
| 69 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 69 | const pS0: f64 = 1.66666666666666657415e-01; | |
| 70 | 70 | const pS1: f64 = -3.25565818622400915405e-01; |
| 71 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 71 | const pS2: f64 = 2.01212532134862925881e-01; | |
| 72 | 72 | 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; | |
| 75 | 75 | const qS1: f64 = -2.40339491173441421878e+00; |
| 76 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 76 | const qS2: f64 = 2.02094576023350569471e+00; | |
| 77 | 77 | const qS3: f64 = -6.88283971605453293030e-01; |
| 78 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 78 | const qS4: f64 = 7.70381505559019352791e-02; | |
| 79 | 79 | |
| 80 | 80 | const p = z * (pS0 + z * (pS1 + z * (pS2 + z * (pS3 + z * (pS4 + z * pS5))))); |
| 81 | 81 | 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 { |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | 33 | fn atan2_32(y: f32, x: f32) f32 { |
| 34 | const pi: f32 = 3.1415927410e+00; | |
| 34 | const pi: f32 = 3.1415927410e+00; | |
| 35 | 35 | const pi_lo: f32 = -8.7422776573e-08; |
| 36 | 36 | |
| 37 | 37 | if (math.isNan(x) or math.isNan(y)) { |
| ... | ... | @@ -53,9 +53,10 @@ fn atan2_32(y: f32, x: f32) f32 { |
| 53 | 53 | |
| 54 | 54 | if (iy == 0) { |
| 55 | 55 | 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, -...) | |
| 59 | 60 | else => unreachable, |
| 60 | 61 | } |
| 61 | 62 | } |
| ... | ... | @@ -71,18 +72,18 @@ fn atan2_32(y: f32, x: f32) f32 { |
| 71 | 72 | if (ix == 0x7F800000) { |
| 72 | 73 | if (iy == 0x7F800000) { |
| 73 | 74 | 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) | |
| 78 | 79 | else => unreachable, |
| 79 | 80 | } |
| 80 | 81 | } else { |
| 81 | 82 | 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) | |
| 86 | 87 | else => unreachable, |
| 87 | 88 | } |
| 88 | 89 | } |
| ... | ... | @@ -107,16 +108,16 @@ fn atan2_32(y: f32, x: f32) f32 { |
| 107 | 108 | }; |
| 108 | 109 | |
| 109 | 110 | 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(-, -) | |
| 114 | 115 | else => unreachable, |
| 115 | 116 | } |
| 116 | 117 | } |
| 117 | 118 | |
| 118 | 119 | fn atan2_64(y: f64, x: f64) f64 { |
| 119 | const pi: f64 = 3.1415926535897931160E+00; | |
| 120 | const pi: f64 = 3.1415926535897931160E+00; | |
| 120 | 121 | const pi_lo: f64 = 1.2246467991473531772E-16; |
| 121 | 122 | |
| 122 | 123 | if (math.isNan(x) or math.isNan(y)) { |
| ... | ... | @@ -143,9 +144,10 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 143 | 144 | |
| 144 | 145 | if (iy | ly == 0) { |
| 145 | 146 | 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, -...) | |
| 149 | 151 | else => unreachable, |
| 150 | 152 | } |
| 151 | 153 | } |
| ... | ... | @@ -161,18 +163,18 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 161 | 163 | if (ix == 0x7FF00000) { |
| 162 | 164 | if (iy == 0x7FF00000) { |
| 163 | 165 | 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) | |
| 168 | 170 | else => unreachable, |
| 169 | 171 | } |
| 170 | 172 | } else { |
| 171 | 173 | 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) | |
| 176 | 178 | else => unreachable, |
| 177 | 179 | } |
| 178 | 180 | } |
| ... | ... | @@ -197,10 +199,10 @@ fn atan2_64(y: f64, x: f64) f64 { |
| 197 | 199 | }; |
| 198 | 200 | |
| 199 | 201 | 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(-, -) | |
| 204 | 206 | else => unreachable, |
| 205 | 207 | } |
| 206 | 208 | } |
std/math/cbrt.zig+5-5| ... | ... | @@ -58,15 +58,15 @@ fn cbrt32(x: f32) f32 { |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | fn 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 | |
| 63 | 63 | |
| 64 | 64 | // |1 / cbrt(x) - p(x)| < 2^(23.5) |
| 65 | const P0: f64 = 1.87595182427177009643; | |
| 65 | const P0: f64 = 1.87595182427177009643; | |
| 66 | 66 | const P1: f64 = -1.88497979543377169875; |
| 67 | const P2: f64 = 1.621429720105354466140; | |
| 67 | const P2: f64 = 1.621429720105354466140; | |
| 68 | 68 | const P3: f64 = -0.758397934778766047437; |
| 69 | const P4: f64 = 0.145996192886612446982; | |
| 69 | const P4: f64 = 0.145996192886612446982; | |
| 70 | 70 | |
| 71 | 71 | var u = @bitCast(u64, x); |
| 72 | 72 | var hx = u32(u >> 32) & 0x7FFFFFFF; |
std/math/ceil.zig+2-2| ... | ... | @@ -56,7 +56,7 @@ fn ceil64(x: f64) f64 { |
| 56 | 56 | const e = (u >> 52) & 0x7FF; |
| 57 | 57 | var y: f64 = undefined; |
| 58 | 58 | |
| 59 | if (e >= 0x3FF+52 or x == 0) { | |
| 59 | if (e >= 0x3FF + 52 or x == 0) { | |
| 60 | 60 | return x; |
| 61 | 61 | } |
| 62 | 62 | |
| ... | ... | @@ -68,7 +68,7 @@ fn ceil64(x: f64) f64 { |
| 68 | 68 | y = x + math.f64_toint - math.f64_toint - x; |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | if (e <= 0x3FF-1) { | |
| 71 | if (e <= 0x3FF - 1) { | |
| 72 | 72 | math.forceEval(y); |
| 73 | 73 | if (u >> 63 != 0) { |
| 74 | 74 | return -0.0; |
std/math/complex/exp.zig+11-17| ... | ... | @@ -19,8 +19,8 @@ pub fn exp(z: var) Complex(@typeOf(z.re)) { |
| 19 | 19 | fn exp32(z: &const Complex(f32)) Complex(f32) { |
| 20 | 20 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 21 | 21 | |
| 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 | |
| 24 | 24 | |
| 25 | 25 | const x = z.re; |
| 26 | 26 | const y = z.im; |
| ... | ... | @@ -41,12 +41,10 @@ fn exp32(z: &const Complex(f32)) Complex(f32) { |
| 41 | 41 | // cexp(finite|nan +- i inf|nan) = nan + i nan |
| 42 | 42 | if ((hx & 0x7fffffff) != 0x7f800000) { |
| 43 | 43 | 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 | |
| 46 | 45 | else if (hx & 0x80000000 != 0) { |
| 47 | 46 | 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 | |
| 50 | 48 | else { |
| 51 | 49 | return Complex(f32).new(x, y - y); |
| 52 | 50 | } |
| ... | ... | @@ -55,8 +53,7 @@ fn exp32(z: &const Complex(f32)) Complex(f32) { |
| 55 | 53 | // 88.7 <= x <= 192 so must scale |
| 56 | 54 | if (hx >= exp_overflow and hx <= cexp_overflow) { |
| 57 | 55 | 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) | |
| 60 | 57 | // - x > cexp_overflow, so exp(x) * s overflows for s > 0 |
| 61 | 58 | // - x = +-inf |
| 62 | 59 | // - x = nan |
| ... | ... | @@ -67,8 +64,8 @@ fn exp32(z: &const Complex(f32)) Complex(f32) { |
| 67 | 64 | } |
| 68 | 65 | |
| 69 | 66 | fn 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 | |
| 72 | 69 | |
| 73 | 70 | const x = z.re; |
| 74 | 71 | const y = z.im; |
| ... | ... | @@ -95,12 +92,10 @@ fn exp64(z: &const Complex(f64)) Complex(f64) { |
| 95 | 92 | // cexp(finite|nan +- i inf|nan) = nan + i nan |
| 96 | 93 | if (lx != 0 or (hx & 0x7fffffff) != 0x7ff00000) { |
| 97 | 94 | 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 | |
| 100 | 96 | else if (hx & 0x80000000 != 0) { |
| 101 | 97 | 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 | |
| 104 | 99 | else { |
| 105 | 100 | return Complex(f64).new(x, y - y); |
| 106 | 101 | } |
| ... | ... | @@ -109,9 +104,8 @@ fn exp64(z: &const Complex(f64)) Complex(f64) { |
| 109 | 104 | // 709.7 <= x <= 1454.3 so must scale |
| 110 | 105 | if (hx >= exp_overflow and hx <= cexp_overflow) { |
| 111 | 106 | 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) | |
| 115 | 109 | // - x > cexp_overflow, so exp(x) * s overflows for s > 0 |
| 116 | 110 | // - x = +-inf |
| 117 | 111 | // - 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)) { |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | 17 | fn 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 | |
| 20 | 20 | |
| 21 | 21 | const exp_x = math.exp(x - kln2); |
| 22 | 22 | const hx = @bitCast(u32, exp_x); |
| 23 | *expt = i32(hx >> 23) - (0x7f + 127) + k; | |
| 23 | expt.* = i32(hx >> 23) - (0x7f + 127) + k; | |
| 24 | 24 | return @bitCast(f32, (hx & 0x7fffff) | ((0x7f + 127) << 23)); |
| 25 | 25 | } |
| 26 | 26 | |
| ... | ... | @@ -35,15 +35,12 @@ fn ldexp_cexp32(z: &const Complex(f32), expt: i32) Complex(f32) { |
| 35 | 35 | const half_expt2 = exptf - half_expt1; |
| 36 | 36 | const scale2 = @bitCast(f32, (0x7f + half_expt2) << 23); |
| 37 | 37 | |
| 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); | |
| 42 | 39 | } |
| 43 | 40 | |
| 44 | 41 | fn 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 | |
| 47 | 44 | |
| 48 | 45 | const exp_x = math.exp(x - kln2); |
| 49 | 46 | |
| ... | ... | @@ -51,7 +48,7 @@ fn frexp_exp64(x: f64, expt: &i32) f64 { |
| 51 | 48 | const hx = u32(fx >> 32); |
| 52 | 49 | const lx = @truncate(u32, fx); |
| 53 | 50 | |
| 54 | *expt = i32(hx >> 20) - (0x3ff + 1023) + k; | |
| 51 | expt.* = i32(hx >> 20) - (0x3ff + 1023) + k; | |
| 55 | 52 | |
| 56 | 53 | const high_word = (hx & 0xfffff) | ((0x3ff + 1023) << 20); |
| 57 | 54 | 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) { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | // sin polynomial coefficients |
| 21 | const S0 = 1.58962301576546568060E-10; | |
| 21 | const S0 = 1.58962301576546568060E-10; | |
| 22 | 22 | const S1 = -2.50507477628578072866E-8; |
| 23 | const S2 = 2.75573136213857245213E-6; | |
| 23 | const S2 = 2.75573136213857245213E-6; | |
| 24 | 24 | const S3 = -1.98412698295895385996E-4; |
| 25 | const S4 = 8.33333333332211858878E-3; | |
| 25 | const S4 = 8.33333333332211858878E-3; | |
| 26 | 26 | const S5 = -1.66666666666666307295E-1; |
| 27 | 27 | |
| 28 | 28 | // cos polynomial coeffiecients |
| 29 | 29 | const C0 = -1.13585365213876817300E-11; |
| 30 | const C1 = 2.08757008419747316778E-9; | |
| 30 | const C1 = 2.08757008419747316778E-9; | |
| 31 | 31 | const C2 = -2.75573141792967388112E-7; |
| 32 | const C3 = 2.48015872888517045348E-5; | |
| 32 | const C3 = 2.48015872888517045348E-5; | |
| 33 | 33 | const C4 = -1.38888888888730564116E-3; |
| 34 | const C5 = 4.16666666666665929218E-2; | |
| 34 | const C5 = 4.16666666666665929218E-2; | |
| 35 | 35 | |
| 36 | 36 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 37 | 37 | // |
std/math/floor.zig+2-2| ... | ... | @@ -57,7 +57,7 @@ fn floor64(x: f64) f64 { |
| 57 | 57 | const e = (u >> 52) & 0x7FF; |
| 58 | 58 | var y: f64 = undefined; |
| 59 | 59 | |
| 60 | if (e >= 0x3FF+52 or x == 0) { | |
| 60 | if (e >= 0x3FF + 52 or x == 0) { | |
| 61 | 61 | return x; |
| 62 | 62 | } |
| 63 | 63 | |
| ... | ... | @@ -69,7 +69,7 @@ fn floor64(x: f64) f64 { |
| 69 | 69 | y = x + math.f64_toint - math.f64_toint - x; |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | if (e <= 0x3FF-1) { | |
| 72 | if (e <= 0x3FF - 1) { | |
| 73 | 73 | math.forceEval(y); |
| 74 | 74 | if (u >> 63 != 0) { |
| 75 | 75 | return -1.0; |
std/math/fma.zig+5-2| ... | ... | @@ -5,7 +5,7 @@ const assert = std.debug.assert; |
| 5 | 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) T { |
| 6 | 6 | return switch (T) { |
| 7 | 7 | f32 => fma32(x, y, z), |
| 8 | f64 => fma64(x, y ,z), | |
| 8 | f64 => fma64(x, y, z), | |
| 9 | 9 | else => @compileError("fma not implemented for " ++ @typeName(T)), |
| 10 | 10 | }; |
| 11 | 11 | } |
| ... | ... | @@ -71,7 +71,10 @@ fn fma64(x: f64, y: f64, z: f64) f64 { |
| 71 | 71 | } |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | const dd = struct { hi: f64, lo: f64, }; | |
| 74 | const dd = struct { | |
| 75 | hi: f64, | |
| 76 | lo: f64, | |
| 77 | }; | |
| 75 | 78 | |
| 76 | 79 | fn dd_add(a: f64, b: f64) dd { |
| 77 | 80 | var ret: dd = undefined; |
std/math/hypot.zig+4-4| ... | ... | @@ -39,11 +39,11 @@ fn hypot32(x: f32, y: f32) f32 { |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | var z: f32 = 1.0; |
| 42 | if (ux >= (0x7F+60) << 23) { | |
| 42 | if (ux >= (0x7F + 60) << 23) { | |
| 43 | 43 | z = 0x1.0p90; |
| 44 | 44 | xx *= 0x1.0p-90; |
| 45 | 45 | yy *= 0x1.0p-90; |
| 46 | } else if (uy < (0x7F-60) << 23) { | |
| 46 | } else if (uy < (0x7F - 60) << 23) { | |
| 47 | 47 | z = 0x1.0p-90; |
| 48 | 48 | xx *= 0x1.0p-90; |
| 49 | 49 | yy *= 0x1.0p-90; |
| ... | ... | @@ -57,8 +57,8 @@ fn sq(hi: &f64, lo: &f64, x: f64) void { |
| 57 | 57 | const xc = x * split; |
| 58 | 58 | const xh = x - xc + xc; |
| 59 | 59 | 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; | |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | fn hypot64(x: f64, y: f64) f64 { |
std/math/index.zig+29-46| ... | ... | @@ -47,12 +47,12 @@ pub fn forceEval(value: var) void { |
| 47 | 47 | f32 => { |
| 48 | 48 | var x: f32 = undefined; |
| 49 | 49 | const p = @ptrCast(&volatile f32, &x); |
| 50 | *p = x; | |
| 50 | p.* = x; | |
| 51 | 51 | }, |
| 52 | 52 | f64 => { |
| 53 | 53 | var x: f64 = undefined; |
| 54 | 54 | const p = @ptrCast(&volatile f64, &x); |
| 55 | *p = x; | |
| 55 | p.* = x; | |
| 56 | 56 | }, |
| 57 | 57 | else => { |
| 58 | 58 | @compileError("forceEval not implemented for " ++ @typeName(T)); |
| ... | ... | @@ -179,7 +179,6 @@ test "math" { |
| 179 | 179 | _ = @import("complex/index.zig"); |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | ||
| 183 | 182 | pub fn min(x: var, y: var) @typeOf(x + y) { |
| 184 | 183 | return if (x < y) x else y; |
| 185 | 184 | } |
| ... | ... | @@ -280,10 +279,10 @@ pub fn rotr(comptime T: type, x: T, r: var) T { |
| 280 | 279 | } |
| 281 | 280 | |
| 282 | 281 | test "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); | |
| 287 | 286 | assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010); |
| 288 | 287 | } |
| 289 | 288 | |
| ... | ... | @@ -299,14 +298,13 @@ pub fn rotl(comptime T: type, x: T, r: var) T { |
| 299 | 298 | } |
| 300 | 299 | |
| 301 | 300 | test "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); | |
| 306 | 305 | assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000); |
| 307 | 306 | } |
| 308 | 307 | |
| 309 | ||
| 310 | 308 | pub fn Log2Int(comptime T: type) type { |
| 311 | 309 | return @IntType(false, log2(T.bit_count)); |
| 312 | 310 | } |
| ... | ... | @@ -323,14 +321,14 @@ fn testOverflow() void { |
| 323 | 321 | assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000); |
| 324 | 322 | } |
| 325 | 323 | |
| 326 | ||
| 327 | 324 | pub fn absInt(x: var) !@typeOf(x) { |
| 328 | 325 | const T = @typeOf(x); |
| 329 | 326 | comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt |
| 330 | 327 | 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))) { | |
| 332 | 330 | return error.Overflow; |
| 333 | { | |
| 331 | } else { | |
| 334 | 332 | @setRuntimeSafety(false); |
| 335 | 333 | return if (x < 0) -x else x; |
| 336 | 334 | } |
| ... | ... | @@ -349,10 +347,8 @@ pub const absFloat = @import("fabs.zig").fabs; |
| 349 | 347 | |
| 350 | 348 | pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { |
| 351 | 349 | @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; | |
| 356 | 352 | return @divTrunc(numerator, denominator); |
| 357 | 353 | } |
| 358 | 354 | |
| ... | ... | @@ -372,10 +368,8 @@ fn testDivTrunc() void { |
| 372 | 368 | |
| 373 | 369 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T { |
| 374 | 370 | @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; | |
| 379 | 373 | return @divFloor(numerator, denominator); |
| 380 | 374 | } |
| 381 | 375 | |
| ... | ... | @@ -395,13 +389,10 @@ fn testDivFloor() void { |
| 395 | 389 | |
| 396 | 390 | pub fn divExact(comptime T: type, numerator: T, denominator: T) !T { |
| 397 | 391 | @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; | |
| 402 | 394 | const result = @divTrunc(numerator, denominator); |
| 403 | if (result * denominator != numerator) | |
| 404 | return error.UnexpectedRemainder; | |
| 395 | if (result * denominator != numerator) return error.UnexpectedRemainder; | |
| 405 | 396 | return result; |
| 406 | 397 | } |
| 407 | 398 | |
| ... | ... | @@ -423,10 +414,8 @@ fn testDivExact() void { |
| 423 | 414 | |
| 424 | 415 | pub fn mod(comptime T: type, numerator: T, denominator: T) !T { |
| 425 | 416 | @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; | |
| 430 | 419 | return @mod(numerator, denominator); |
| 431 | 420 | } |
| 432 | 421 | |
| ... | ... | @@ -448,10 +437,8 @@ fn testMod() void { |
| 448 | 437 | |
| 449 | 438 | pub fn rem(comptime T: type, numerator: T, denominator: T) !T { |
| 450 | 439 | @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; | |
| 455 | 442 | return @rem(numerator, denominator); |
| 456 | 443 | } |
| 457 | 444 | |
| ... | ... | @@ -475,8 +462,7 @@ fn testRem() void { |
| 475 | 462 | /// Result is an unsigned integer. |
| 476 | 463 | pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) { |
| 477 | 464 | const uint = @IntType(false, @typeOf(x).bit_count); |
| 478 | if (x >= 0) | |
| 479 | return uint(x); | |
| 465 | if (x >= 0) return uint(x); | |
| 480 | 466 | |
| 481 | 467 | return uint(-(x + 1)) + 1; |
| 482 | 468 | } |
| ... | ... | @@ -495,15 +481,12 @@ test "math.absCast" { |
| 495 | 481 | /// Returns the negation of the integer parameter. |
| 496 | 482 | /// Result is a signed integer. |
| 497 | 483 | pub 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); | |
| 500 | 485 | |
| 501 | 486 | 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; | |
| 504 | 488 | |
| 505 | if (x == -@minValue(int)) | |
| 506 | return @minValue(int); | |
| 489 | if (x == -@minValue(int)) return @minValue(int); | |
| 507 | 490 | |
| 508 | 491 | return -int(x); |
| 509 | 492 | } |
| ... | ... | @@ -546,7 +529,7 @@ pub fn floorPowerOfTwo(comptime T: type, value: T) T { |
| 546 | 529 | var x = value; |
| 547 | 530 | |
| 548 | 531 | comptime var i = 1; |
| 549 | inline while(T.bit_count > i) : (i *= 2) { | |
| 532 | inline while (T.bit_count > i) : (i *= 2) { | |
| 550 | 533 | x |= (x >> i); |
| 551 | 534 | } |
| 552 | 535 |
std/math/ln.zig+2-4| ... | ... | @@ -120,11 +120,9 @@ pub fn ln_64(x_: f64) f64 { |
| 120 | 120 | k -= 54; |
| 121 | 121 | x *= 0x1.0p54; |
| 122 | 122 | hx = u32(@bitCast(u64, ix) >> 32); |
| 123 | } | |
| 124 | else if (hx >= 0x7FF00000) { | |
| 123 | } else if (hx >= 0x7FF00000) { | |
| 125 | 124 | return x; |
| 126 | } | |
| 127 | else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 125 | } else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 128 | 126 | return 0; |
| 129 | 127 | } |
| 130 | 128 |
std/math/log10.zig+8-10| ... | ... | @@ -35,10 +35,10 @@ pub fn log10(x: var) @typeOf(x) { |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | pub 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; | |
| 42 | 42 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| 43 | 43 | const Lg2: f32 = 0xccce13.0p-25; |
| 44 | 44 | const Lg3: f32 = 0x91e9ee.0p-25; |
| ... | ... | @@ -95,8 +95,8 @@ pub fn log10_32(x_: f32) f32 { |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | pub 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; | |
| 100 | 100 | const log10_2hi: f64 = 3.01029995663611771306e-01; |
| 101 | 101 | const log10_2lo: f64 = 3.69423907715893078616e-13; |
| 102 | 102 | const Lg1: f64 = 6.666666666666735130e-01; |
| ... | ... | @@ -126,11 +126,9 @@ pub fn log10_64(x_: f64) f64 { |
| 126 | 126 | k -= 54; |
| 127 | 127 | x *= 0x1.0p54; |
| 128 | 128 | hx = u32(@bitCast(u64, x) >> 32); |
| 129 | } | |
| 130 | else if (hx >= 0x7FF00000) { | |
| 129 | } else if (hx >= 0x7FF00000) { | |
| 131 | 130 | return x; |
| 132 | } | |
| 133 | else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 131 | } else if (hx == 0x3FF00000 and ix << 32 == 0) { | |
| 134 | 132 | return 0; |
| 135 | 133 | } |
| 136 | 134 |
std/math/log2.zig+5-2| ... | ... | @@ -27,7 +27,10 @@ pub fn log2(x: var) @typeOf(x) { |
| 27 | 27 | TypeId.IntLiteral => comptime { |
| 28 | 28 | var result = 0; |
| 29 | 29 | 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) {} | |
| 31 | 34 | return result; |
| 32 | 35 | }, |
| 33 | 36 | TypeId.Int => { |
| ... | ... | @@ -38,7 +41,7 @@ pub fn log2(x: var) @typeOf(x) { |
| 38 | 41 | } |
| 39 | 42 | |
| 40 | 43 | pub fn log2_32(x_: f32) f32 { |
| 41 | const ivln2hi: f32 = 1.4428710938e+00; | |
| 44 | const ivln2hi: f32 = 1.4428710938e+00; | |
| 42 | 45 | const ivln2lo: f32 = -1.7605285393e-04; |
| 43 | 46 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| 44 | 47 | const Lg2: f32 = 0xccce13.0p-25; |
std/math/round.zig+4-4| ... | ... | @@ -24,13 +24,13 @@ fn round32(x_: f32) f32 { |
| 24 | 24 | const e = (u >> 23) & 0xFF; |
| 25 | 25 | var y: f32 = undefined; |
| 26 | 26 | |
| 27 | if (e >= 0x7F+23) { | |
| 27 | if (e >= 0x7F + 23) { | |
| 28 | 28 | return x; |
| 29 | 29 | } |
| 30 | 30 | if (u >> 31 != 0) { |
| 31 | 31 | x = -x; |
| 32 | 32 | } |
| 33 | if (e < 0x7F-1) { | |
| 33 | if (e < 0x7F - 1) { | |
| 34 | 34 | math.forceEval(x + math.f32_toint); |
| 35 | 35 | return 0 * @bitCast(f32, u); |
| 36 | 36 | } |
| ... | ... | @@ -61,13 +61,13 @@ fn round64(x_: f64) f64 { |
| 61 | 61 | const e = (u >> 52) & 0x7FF; |
| 62 | 62 | var y: f64 = undefined; |
| 63 | 63 | |
| 64 | if (e >= 0x3FF+52) { | |
| 64 | if (e >= 0x3FF + 52) { | |
| 65 | 65 | return x; |
| 66 | 66 | } |
| 67 | 67 | if (u >> 63 != 0) { |
| 68 | 68 | x = -x; |
| 69 | 69 | } |
| 70 | if (e < 0x3ff-1) { | |
| 70 | if (e < 0x3ff - 1) { | |
| 71 | 71 | math.forceEval(x + math.f64_toint); |
| 72 | 72 | return 0 * @bitCast(f64, u); |
| 73 | 73 | } |
std/math/sin.zig+6-6| ... | ... | @@ -19,20 +19,20 @@ pub fn sin(x: var) @typeOf(x) { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | // sin polynomial coefficients |
| 22 | const S0 = 1.58962301576546568060E-10; | |
| 22 | const S0 = 1.58962301576546568060E-10; | |
| 23 | 23 | const S1 = -2.50507477628578072866E-8; |
| 24 | const S2 = 2.75573136213857245213E-6; | |
| 24 | const S2 = 2.75573136213857245213E-6; | |
| 25 | 25 | const S3 = -1.98412698295895385996E-4; |
| 26 | const S4 = 8.33333333332211858878E-3; | |
| 26 | const S4 = 8.33333333332211858878E-3; | |
| 27 | 27 | const S5 = -1.66666666666666307295E-1; |
| 28 | 28 | |
| 29 | 29 | // cos polynomial coeffiecients |
| 30 | 30 | const C0 = -1.13585365213876817300E-11; |
| 31 | const C1 = 2.08757008419747316778E-9; | |
| 31 | const C1 = 2.08757008419747316778E-9; | |
| 32 | 32 | const C2 = -2.75573141792967388112E-7; |
| 33 | const C3 = 2.48015872888517045348E-5; | |
| 33 | const C3 = 2.48015872888517045348E-5; | |
| 34 | 34 | const C4 = -1.38888888888730564116E-3; |
| 35 | const C5 = 4.16666666666665929218E-2; | |
| 35 | const C5 = 4.16666666666665929218E-2; | |
| 36 | 36 | |
| 37 | 37 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 38 | 38 | // |
std/math/tan.zig+3-3| ... | ... | @@ -19,12 +19,12 @@ pub fn tan(x: var) @typeOf(x) { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | const Tp0 = -1.30936939181383777646E4; |
| 22 | const Tp1 = 1.15351664838587416140E6; | |
| 22 | const Tp1 = 1.15351664838587416140E6; | |
| 23 | 23 | const Tp2 = -1.79565251976484877988E7; |
| 24 | 24 | |
| 25 | const Tq1 = 1.36812963470692954678E4; | |
| 25 | const Tq1 = 1.36812963470692954678E4; | |
| 26 | 26 | const Tq2 = -1.32089234440210967447E6; |
| 27 | const Tq3 = 2.50083801823357915839E7; | |
| 27 | const Tq3 = 2.50083801823357915839E7; | |
| 28 | 28 | const Tq4 = -5.38695755929454629881E7; |
| 29 | 29 | |
| 30 | 30 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
std/mem.zig+124-73| ... | ... | @@ -6,14 +6,14 @@ const builtin = @import("builtin"); |
| 6 | 6 | const mem = this; |
| 7 | 7 | |
| 8 | 8 | pub const Allocator = struct { |
| 9 | const Error = error {OutOfMemory}; | |
| 9 | const Error = error{OutOfMemory}; | |
| 10 | 10 | |
| 11 | 11 | /// Allocate byte_count bytes and return them in a slice, with the |
| 12 | 12 | /// slice's pointer aligned at least to alignment bytes. |
| 13 | 13 | /// The returned newly allocated memory is undefined. |
| 14 | 14 | /// `alignment` is guaranteed to be >= 1 |
| 15 | 15 | /// `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, | |
| 17 | 17 | |
| 18 | 18 | /// If `new_byte_count > old_mem.len`: |
| 19 | 19 | /// * `old_mem.len` is the same as what was returned from allocFn or reallocFn. |
| ... | ... | @@ -26,10 +26,10 @@ pub const Allocator = struct { |
| 26 | 26 | /// The returned newly allocated memory is undefined. |
| 27 | 27 | /// `alignment` is guaranteed to be >= 1 |
| 28 | 28 | /// `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, | |
| 30 | 30 | |
| 31 | 31 | /// 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, | |
| 33 | 33 | |
| 34 | 34 | fn create(self: &Allocator, comptime T: type) !&T { |
| 35 | 35 | if (@sizeOf(T) == 0) return &{}; |
| ... | ... | @@ -47,7 +47,7 @@ pub const Allocator = struct { |
| 47 | 47 | if (@sizeOf(T) == 0) return &{}; |
| 48 | 48 | const slice = try self.alloc(T, 1); |
| 49 | 49 | const ptr = &slice[0]; |
| 50 | *ptr = *init; | |
| 50 | ptr.* = init.*; | |
| 51 | 51 | return ptr; |
| 52 | 52 | } |
| 53 | 53 | |
| ... | ... | @@ -59,9 +59,7 @@ pub const Allocator = struct { |
| 59 | 59 | return self.alignedAlloc(T, @alignOf(T), n); |
| 60 | 60 | } |
| 61 | 61 | |
| 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 { | |
| 65 | 63 | if (n == 0) { |
| 66 | 64 | return (&align(alignment) T)(undefined)[0..0]; |
| 67 | 65 | } |
| ... | ... | @@ -70,7 +68,7 @@ pub const Allocator = struct { |
| 70 | 68 | assert(byte_slice.len == byte_count); |
| 71 | 69 | // This loop gets optimized out in ReleaseFast mode |
| 72 | 70 | for (byte_slice) |*byte| { |
| 73 | *byte = undefined; | |
| 71 | byte.* = undefined; | |
| 74 | 72 | } |
| 75 | 73 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); |
| 76 | 74 | } |
| ... | ... | @@ -79,9 +77,7 @@ pub const Allocator = struct { |
| 79 | 77 | return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); |
| 80 | 78 | } |
| 81 | 79 | |
| 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 { | |
| 85 | 81 | if (old_mem.len == 0) { |
| 86 | 82 | return self.alloc(T, n); |
| 87 | 83 | } |
| ... | ... | @@ -97,7 +93,7 @@ pub const Allocator = struct { |
| 97 | 93 | if (n > old_mem.len) { |
| 98 | 94 | // This loop gets optimized out in ReleaseFast mode |
| 99 | 95 | for (byte_slice[old_byte_slice.len..]) |*byte| { |
| 100 | *byte = undefined; | |
| 96 | byte.* = undefined; | |
| 101 | 97 | } |
| 102 | 98 | } |
| 103 | 99 | return ([]T)(@alignCast(alignment, byte_slice)); |
| ... | ... | @@ -110,9 +106,7 @@ pub const Allocator = struct { |
| 110 | 106 | return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); |
| 111 | 107 | } |
| 112 | 108 | |
| 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 { | |
| 116 | 110 | if (n == 0) { |
| 117 | 111 | self.free(old_mem); |
| 118 | 112 | return old_mem[0..0]; |
| ... | ... | @@ -131,8 +125,7 @@ pub const Allocator = struct { |
| 131 | 125 | |
| 132 | 126 | fn free(self: &Allocator, memory: var) void { |
| 133 | 127 | const bytes = ([]const u8)(memory); |
| 134 | if (bytes.len == 0) | |
| 135 | return; | |
| 128 | if (bytes.len == 0) return; | |
| 136 | 129 | const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr)); |
| 137 | 130 | self.freeFn(self, non_const_ptr[0..bytes.len]); |
| 138 | 131 | } |
| ... | ... | @@ -146,11 +139,13 @@ pub fn copy(comptime T: type, dest: []T, source: []const T) void { |
| 146 | 139 | // this and automatically omit safety checks for loops |
| 147 | 140 | @setRuntimeSafety(false); |
| 148 | 141 | assert(dest.len >= source.len); |
| 149 | for (source) |s, i| dest[i] = s; | |
| 142 | for (source) |s, i| | |
| 143 | dest[i] = s; | |
| 150 | 144 | } |
| 151 | 145 | |
| 152 | 146 | pub fn set(comptime T: type, dest: []T, value: T) void { |
| 153 | for (dest) |*d| *d = value; | |
| 147 | for (dest) |*d| | |
| 148 | d.* = value; | |
| 154 | 149 | } |
| 155 | 150 | |
| 156 | 151 | /// Returns true if lhs < rhs, false otherwise |
| ... | ... | @@ -229,8 +224,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { |
| 229 | 224 | var i: usize = slice.len; |
| 230 | 225 | while (i != 0) { |
| 231 | 226 | i -= 1; |
| 232 | if (slice[i] == value) | |
| 233 | return i; | |
| 227 | if (slice[i] == value) return i; | |
| 234 | 228 | } |
| 235 | 229 | return null; |
| 236 | 230 | } |
| ... | ... | @@ -238,8 +232,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { |
| 238 | 232 | pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize { |
| 239 | 233 | var i: usize = start_index; |
| 240 | 234 | while (i < slice.len) : (i += 1) { |
| 241 | if (slice[i] == value) | |
| 242 | return i; | |
| 235 | if (slice[i] == value) return i; | |
| 243 | 236 | } |
| 244 | 237 | return null; |
| 245 | 238 | } |
| ... | ... | @@ -253,8 +246,7 @@ pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?us |
| 253 | 246 | while (i != 0) { |
| 254 | 247 | i -= 1; |
| 255 | 248 | for (values) |value| { |
| 256 | if (slice[i] == value) | |
| 257 | return i; | |
| 249 | if (slice[i] == value) return i; | |
| 258 | 250 | } |
| 259 | 251 | } |
| 260 | 252 | return null; |
| ... | ... | @@ -264,8 +256,7 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val |
| 264 | 256 | var i: usize = start_index; |
| 265 | 257 | while (i < slice.len) : (i += 1) { |
| 266 | 258 | for (values) |value| { |
| 267 | if (slice[i] == value) | |
| 268 | return i; | |
| 259 | if (slice[i] == value) return i; | |
| 269 | 260 | } |
| 270 | 261 | } |
| 271 | 262 | return null; |
| ... | ... | @@ -279,28 +270,23 @@ pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize |
| 279 | 270 | /// To start looking at a different index, slice the haystack first. |
| 280 | 271 | /// TODO is there even a better algorithm for this? |
| 281 | 272 | pub 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; | |
| 284 | 274 | |
| 285 | 275 | var i: usize = haystack.len - needle.len; |
| 286 | 276 | 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; | |
| 291 | 279 | } |
| 292 | 280 | } |
| 293 | 281 | |
| 294 | 282 | // TODO boyer-moore algorithm |
| 295 | 283 | pub 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; | |
| 298 | 285 | |
| 299 | 286 | var i: usize = start_index; |
| 300 | 287 | const end = haystack.len - needle.len; |
| 301 | 288 | 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; | |
| 304 | 290 | } |
| 305 | 291 | return null; |
| 306 | 292 | } |
| ... | ... | @@ -355,9 +341,12 @@ pub fn readIntBE(comptime T: type, bytes: []const u8) T { |
| 355 | 341 | } |
| 356 | 342 | assert(bytes.len == @sizeOf(T)); |
| 357 | 343 | 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 | } | |
| 361 | 350 | return result; |
| 362 | 351 | } |
| 363 | 352 | |
| ... | ... | @@ -369,9 +358,12 @@ pub fn readIntLE(comptime T: type, bytes: []const u8) T { |
| 369 | 358 | } |
| 370 | 359 | assert(bytes.len == @sizeOf(T)); |
| 371 | 360 | 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 | } | |
| 375 | 367 | return result; |
| 376 | 368 | } |
| 377 | 369 | |
| ... | ... | @@ -393,7 +385,7 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { |
| 393 | 385 | }, |
| 394 | 386 | builtin.Endian.Little => { |
| 395 | 387 | for (buf) |*b| { |
| 396 | *b = @truncate(u8, bits); | |
| 388 | b.* = @truncate(u8, bits); | |
| 397 | 389 | bits >>= 8; |
| 398 | 390 | } |
| 399 | 391 | }, |
| ... | ... | @@ -401,7 +393,6 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { |
| 401 | 393 | assert(bits == 0); |
| 402 | 394 | } |
| 403 | 395 | |
| 404 | ||
| 405 | 396 | pub fn hash_slice_u8(k: []const u8) u32 { |
| 406 | 397 | // FNV 32-bit hash |
| 407 | 398 | var h: u32 = 2166136261; |
| ... | ... | @@ -420,7 +411,7 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { |
| 420 | 411 | /// split(" abc def ghi ", " ") |
| 421 | 412 | /// Will return slices for "abc", "def", "ghi", null, in that order. |
| 422 | 413 | pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator { |
| 423 | return SplitIterator { | |
| 414 | return SplitIterator{ | |
| 424 | 415 | .index = 0, |
| 425 | 416 | .buffer = buffer, |
| 426 | 417 | .split_bytes = split_bytes, |
| ... | ... | @@ -436,7 +427,7 @@ test "mem.split" { |
| 436 | 427 | } |
| 437 | 428 | |
| 438 | 429 | pub 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); | |
| 440 | 431 | } |
| 441 | 432 | |
| 442 | 433 | test "mem.startsWith" { |
| ... | ... | @@ -445,10 +436,9 @@ test "mem.startsWith" { |
| 445 | 436 | } |
| 446 | 437 | |
| 447 | 438 | pub 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); | |
| 449 | 440 | } |
| 450 | 441 | |
| 451 | ||
| 452 | 442 | test "mem.endsWith" { |
| 453 | 443 | assert(endsWith(u8, "Needle in haystack", "haystack")); |
| 454 | 444 | assert(!endsWith(u8, "Bob", "Bo")); |
| ... | ... | @@ -542,29 +532,47 @@ test "testReadInt" { |
| 542 | 532 | } |
| 543 | 533 | fn testReadIntImpl() void { |
| 544 | 534 | { |
| 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); | |
| 549 | 544 | 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); | |
| 552 | 547 | } |
| 553 | 548 | { |
| 554 | const buf = []u8{0x00, 0x00, 0x12, 0x34}; | |
| 549 | const buf = []u8{ | |
| 550 | 0x00, | |
| 551 | 0x00, | |
| 552 | 0x12, | |
| 553 | 0x34, | |
| 554 | }; | |
| 555 | 555 | const answer = readInt(buf, u64, builtin.Endian.Big); |
| 556 | 556 | assert(answer == 0x00001234); |
| 557 | 557 | } |
| 558 | 558 | { |
| 559 | const buf = []u8{0x12, 0x34, 0x00, 0x00}; | |
| 559 | const buf = []u8{ | |
| 560 | 0x12, | |
| 561 | 0x34, | |
| 562 | 0x00, | |
| 563 | 0x00, | |
| 564 | }; | |
| 560 | 565 | const answer = readInt(buf, u64, builtin.Endian.Little); |
| 561 | 566 | assert(answer == 0x00003412); |
| 562 | 567 | } |
| 563 | 568 | { |
| 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); | |
| 566 | 574 | assert(readIntBE(i16, bytes) == -0x0002); |
| 567 | assert(readIntLE(u16, bytes) == 0xfeff); | |
| 575 | assert(readIntLE(u16, bytes) == 0xfeff); | |
| 568 | 576 | assert(readIntLE(i16, bytes) == -0x0101); |
| 569 | 577 | } |
| 570 | 578 | } |
| ... | ... | @@ -577,19 +585,38 @@ fn testWriteIntImpl() void { |
| 577 | 585 | var bytes: [4]u8 = undefined; |
| 578 | 586 | |
| 579 | 587 | 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 | })); | |
| 581 | 594 | |
| 582 | 595 | 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 | })); | |
| 584 | 602 | |
| 585 | 603 | 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 | })); | |
| 587 | 610 | |
| 588 | 611 | 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 | })); | |
| 590 | 618 | } |
| 591 | 619 | |
| 592 | ||
| 593 | 620 | pub fn min(comptime T: type, slice: []const T) T { |
| 594 | 621 | var best = slice[0]; |
| 595 | 622 | for (slice[1..]) |item| { |
| ... | ... | @@ -615,9 +642,9 @@ test "mem.max" { |
| 615 | 642 | } |
| 616 | 643 | |
| 617 | 644 | pub 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; | |
| 621 | 648 | } |
| 622 | 649 | |
| 623 | 650 | /// In-place order reversal of a slice |
| ... | ... | @@ -630,10 +657,22 @@ pub fn reverse(comptime T: type, items: []T) void { |
| 630 | 657 | } |
| 631 | 658 | |
| 632 | 659 | test "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 | }; | |
| 634 | 667 | reverse(i32, arr[0..]); |
| 635 | 668 | |
| 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 | })); | |
| 637 | 676 | } |
| 638 | 677 | |
| 639 | 678 | /// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1) |
| ... | ... | @@ -645,10 +684,22 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void { |
| 645 | 684 | } |
| 646 | 685 | |
| 647 | 686 | test "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 | }; | |
| 649 | 694 | rotate(i32, arr[0..], 2); |
| 650 | 695 | |
| 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 | })); | |
| 652 | 703 | } |
| 653 | 704 | |
| 654 | 705 | // TODO: When https://github.com/zig-lang/zig/issues/649 is solved these can be done by |
std/net.zig+16-24| ... | ... | @@ -19,37 +19,29 @@ pub const Address = struct { |
| 19 | 19 | os_addr: OsAddress, |
| 20 | 20 | |
| 21 | 21 | 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 | } } }; | |
| 32 | 28 | } |
| 33 | 29 | |
| 34 | 30 | pub fn initIp6(ip6: &const Ip6Addr, port: u16) Address { |
| 35 | return Address { | |
| 31 | return Address{ | |
| 36 | 32 | .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 | } }, | |
| 46 | 40 | }; |
| 47 | 41 | } |
| 48 | 42 | |
| 49 | 43 | pub fn initPosix(addr: &const posix.sockaddr) Address { |
| 50 | return Address { | |
| 51 | .os_addr = *addr, | |
| 52 | }; | |
| 44 | return Address{ .os_addr = addr.* }; | |
| 53 | 45 | } |
| 54 | 46 | |
| 55 | 47 | pub fn format(self: &const Address, out_stream: var) !void { |
| ... | ... | @@ -98,7 +90,7 @@ pub fn parseIp4(buf: []const u8) !u32 { |
| 98 | 90 | } |
| 99 | 91 | } else { |
| 100 | 92 | return error.InvalidCharacter; |
| 101 | } | |
| 93 | } | |
| 102 | 94 | } |
| 103 | 95 | if (index == 3 and saw_any_digits) { |
| 104 | 96 | out_ptr[index] = x; |
std/os/child_process.zig+101-91| ... | ... | @@ -49,7 +49,7 @@ pub const ChildProcess = struct { |
| 49 | 49 | err_pipe: if (is_windows) void else [2]i32, |
| 50 | 50 | llnode: if (is_windows) void else LinkedList(&ChildProcess).Node, |
| 51 | 51 | |
| 52 | pub const SpawnError = error { | |
| 52 | pub const SpawnError = error{ | |
| 53 | 53 | ProcessFdQuotaExceeded, |
| 54 | 54 | Unexpected, |
| 55 | 55 | NotDir, |
| ... | ... | @@ -88,7 +88,7 @@ pub const ChildProcess = struct { |
| 88 | 88 | const child = try allocator.create(ChildProcess); |
| 89 | 89 | errdefer allocator.destroy(child); |
| 90 | 90 | |
| 91 | *child = ChildProcess { | |
| 91 | child.* = ChildProcess{ | |
| 92 | 92 | .allocator = allocator, |
| 93 | 93 | .argv = argv, |
| 94 | 94 | .pid = undefined, |
| ... | ... | @@ -99,8 +99,10 @@ pub const ChildProcess = struct { |
| 99 | 99 | .term = null, |
| 100 | 100 | .env_map = null, |
| 101 | 101 | .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, | |
| 104 | 106 | .stdin = null, |
| 105 | 107 | .stdout = null, |
| 106 | 108 | .stderr = null, |
| ... | ... | @@ -193,9 +195,7 @@ pub const ChildProcess = struct { |
| 193 | 195 | |
| 194 | 196 | /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. |
| 195 | 197 | /// 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 { | |
| 199 | 199 | const child = try ChildProcess.init(argv, allocator); |
| 200 | 200 | defer child.deinit(); |
| 201 | 201 | |
| ... | ... | @@ -218,7 +218,7 @@ pub const ChildProcess = struct { |
| 218 | 218 | try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); |
| 219 | 219 | try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size); |
| 220 | 220 | |
| 221 | return ExecResult { | |
| 221 | return ExecResult{ | |
| 222 | 222 | .term = try child.wait(), |
| 223 | 223 | .stdout = stdout.toOwnedSlice(), |
| 224 | 224 | .stderr = stderr.toOwnedSlice(), |
| ... | ... | @@ -255,9 +255,9 @@ pub const ChildProcess = struct { |
| 255 | 255 | self.term = (SpawnError!Term)(x: { |
| 256 | 256 | var exit_code: windows.DWORD = undefined; |
| 257 | 257 | if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) { |
| 258 | break :x Term { .Unknown = 0 }; | |
| 258 | break :x Term{ .Unknown = 0 }; | |
| 259 | 259 | } else { |
| 260 | break :x Term { .Exited = @bitCast(i32, exit_code)}; | |
| 260 | break :x Term{ .Exited = @bitCast(i32, exit_code) }; | |
| 261 | 261 | } |
| 262 | 262 | }); |
| 263 | 263 | |
| ... | ... | @@ -288,9 +288,18 @@ pub const ChildProcess = struct { |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | 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 | } | |
| 294 | 303 | } |
| 295 | 304 | |
| 296 | 305 | fn cleanupAfterWait(self: &ChildProcess, status: i32) !Term { |
| ... | ... | @@ -317,25 +326,30 @@ pub const ChildProcess = struct { |
| 317 | 326 | |
| 318 | 327 | fn statusToTerm(status: i32) Term { |
| 319 | 328 | return if (posix.WIFEXITED(status)) |
| 320 | Term { .Exited = posix.WEXITSTATUS(status) } | |
| 329 | Term{ .Exited = posix.WEXITSTATUS(status) } | |
| 321 | 330 | else if (posix.WIFSIGNALED(status)) |
| 322 | Term { .Signal = posix.WTERMSIG(status) } | |
| 331 | Term{ .Signal = posix.WTERMSIG(status) } | |
| 323 | 332 | else if (posix.WIFSTOPPED(status)) |
| 324 | Term { .Stopped = posix.WSTOPSIG(status) } | |
| 333 | Term{ .Stopped = posix.WSTOPSIG(status) } | |
| 325 | 334 | else |
| 326 | Term { .Unknown = status } | |
| 327 | ; | |
| 335 | Term{ .Unknown = status }; | |
| 328 | 336 | } |
| 329 | 337 | |
| 330 | 338 | fn spawnPosix(self: &ChildProcess) !void { |
| 331 | 339 | 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 | }; | |
| 333 | 343 | |
| 334 | 344 | 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 | }; | |
| 336 | 348 | |
| 337 | 349 | 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 | }; | |
| 339 | 353 | |
| 340 | 354 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); |
| 341 | 355 | const dev_null_fd = if (any_ignore) blk: { |
| ... | ... | @@ -346,7 +360,9 @@ pub const ChildProcess = struct { |
| 346 | 360 | } else blk: { |
| 347 | 361 | break :blk undefined; |
| 348 | 362 | }; |
| 349 | defer { if (any_ignore) os.close(dev_null_fd); } | |
| 363 | defer { | |
| 364 | if (any_ignore) os.close(dev_null_fd); | |
| 365 | } | |
| 350 | 366 | |
| 351 | 367 | var env_map_owned: BufMap = undefined; |
| 352 | 368 | var we_own_env_map: bool = undefined; |
| ... | ... | @@ -358,7 +374,9 @@ pub const ChildProcess = struct { |
| 358 | 374 | env_map_owned = try os.getEnvMap(self.allocator); |
| 359 | 375 | break :x &env_map_owned; |
| 360 | 376 | }; |
| 361 | defer { if (we_own_env_map) env_map_owned.deinit(); } | |
| 377 | defer { | |
| 378 | if (we_own_env_map) env_map_owned.deinit(); | |
| 379 | } | |
| 362 | 380 | |
| 363 | 381 | // This pipe is used to communicate errors between the time of fork |
| 364 | 382 | // and execve from the child process to the parent process. |
| ... | ... | @@ -369,23 +387,21 @@ pub const ChildProcess = struct { |
| 369 | 387 | const pid_err = posix.getErrno(pid_result); |
| 370 | 388 | if (pid_err > 0) { |
| 371 | 389 | return switch (pid_err) { |
| 372 | posix.EAGAIN, posix.ENOMEM, posix.ENOSYS => error.SystemResources, | |
| 390 | posix.EAGAIN, | |
| 391 | posix.ENOMEM, | |
| 392 | posix.ENOSYS => error.SystemResources, | |
| 373 | 393 | else => os.unexpectedErrorPosix(pid_err), |
| 374 | 394 | }; |
| 375 | 395 | } |
| 376 | 396 | if (pid_result == 0) { |
| 377 | 397 | // we are the child |
| 378 | 398 | |
| 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); | |
| 385 | 402 | |
| 386 | 403 | 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); | |
| 389 | 405 | } |
| 390 | 406 | |
| 391 | 407 | if (self.gid) |gid| { |
| ... | ... | @@ -396,8 +412,7 @@ pub const ChildProcess = struct { |
| 396 | 412 | os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err); |
| 397 | 413 | } |
| 398 | 414 | |
| 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); | |
| 401 | 416 | } |
| 402 | 417 | |
| 403 | 418 | // we are the parent |
| ... | ... | @@ -423,37 +438,41 @@ pub const ChildProcess = struct { |
| 423 | 438 | self.llnode = LinkedList(&ChildProcess).Node.init(self); |
| 424 | 439 | self.term = null; |
| 425 | 440 | |
| 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 | } | |
| 429 | 450 | } |
| 430 | 451 | |
| 431 | 452 | fn spawnWindows(self: &ChildProcess) !void { |
| 432 | const saAttr = windows.SECURITY_ATTRIBUTES { | |
| 453 | const saAttr = windows.SECURITY_ATTRIBUTES{ | |
| 433 | 454 | .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), |
| 434 | 455 | .bInheritHandle = windows.TRUE, |
| 435 | 456 | .lpSecurityDescriptor = null, |
| 436 | 457 | }; |
| 437 | 458 | |
| 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); | |
| 441 | 460 | |
| 442 | 461 | const nul_handle = if (any_ignore) blk: { |
| 443 | 462 | const nul_file_path = "NUL"; |
| 444 | 463 | var fixed_buffer_mem: [nul_file_path.len + 1]u8 = undefined; |
| 445 | 464 | 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); | |
| 448 | 466 | } else blk: { |
| 449 | 467 | break :blk undefined; |
| 450 | 468 | }; |
| 451 | defer { if (any_ignore) os.close(nul_handle); } | |
| 469 | defer { | |
| 470 | if (any_ignore) os.close(nul_handle); | |
| 471 | } | |
| 452 | 472 | if (any_ignore) { |
| 453 | 473 | try windowsSetHandleInfo(nul_handle, windows.HANDLE_FLAG_INHERIT, 0); |
| 454 | 474 | } |
| 455 | 475 | |
| 456 | ||
| 457 | 476 | var g_hChildStd_IN_Rd: ?windows.HANDLE = null; |
| 458 | 477 | var g_hChildStd_IN_Wr: ?windows.HANDLE = null; |
| 459 | 478 | switch (self.stdin_behavior) { |
| ... | ... | @@ -470,7 +489,9 @@ pub const ChildProcess = struct { |
| 470 | 489 | g_hChildStd_IN_Rd = null; |
| 471 | 490 | }, |
| 472 | 491 | } |
| 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 | }; | |
| 474 | 495 | |
| 475 | 496 | var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; |
| 476 | 497 | var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; |
| ... | ... | @@ -488,7 +509,9 @@ pub const ChildProcess = struct { |
| 488 | 509 | g_hChildStd_OUT_Wr = null; |
| 489 | 510 | }, |
| 490 | 511 | } |
| 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 | }; | |
| 492 | 515 | |
| 493 | 516 | var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; |
| 494 | 517 | var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; |
| ... | ... | @@ -506,12 +529,14 @@ pub const ChildProcess = struct { |
| 506 | 529 | g_hChildStd_ERR_Wr = null; |
| 507 | 530 | }, |
| 508 | 531 | } |
| 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 | }; | |
| 510 | 535 | |
| 511 | 536 | const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv); |
| 512 | 537 | defer self.allocator.free(cmd_line); |
| 513 | 538 | |
| 514 | var siStartInfo = windows.STARTUPINFOA { | |
| 539 | var siStartInfo = windows.STARTUPINFOA{ | |
| 515 | 540 | .cb = @sizeOf(windows.STARTUPINFOA), |
| 516 | 541 | .hStdError = g_hChildStd_ERR_Wr, |
| 517 | 542 | .hStdOutput = g_hChildStd_OUT_Wr, |
| ... | ... | @@ -534,19 +559,11 @@ pub const ChildProcess = struct { |
| 534 | 559 | }; |
| 535 | 560 | var piProcInfo: windows.PROCESS_INFORMATION = undefined; |
| 536 | 561 | |
| 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; | |
| 542 | 563 | defer if (cwd_slice) |cwd| self.allocator.free(cwd); |
| 543 | 564 | const cwd_ptr = if (cwd_slice) |cwd| cwd.ptr else null; |
| 544 | 565 | |
| 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; | |
| 550 | 567 | defer if (maybe_envp_buf) |envp_buf| self.allocator.free(envp_buf); |
| 551 | 568 | const envp_ptr = if (maybe_envp_buf) |envp_buf| envp_buf.ptr else null; |
| 552 | 569 | |
| ... | ... | @@ -563,11 +580,8 @@ pub const ChildProcess = struct { |
| 563 | 580 | }; |
| 564 | 581 | defer self.allocator.free(app_name); |
| 565 | 582 | |
| 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; | |
| 571 | 585 | |
| 572 | 586 | const PATH = try os.getEnvVarOwned(self.allocator, "PATH"); |
| 573 | 587 | defer self.allocator.free(PATH); |
| ... | ... | @@ -577,9 +591,7 @@ pub const ChildProcess = struct { |
| 577 | 591 | const joined_path = try os.path.join(self.allocator, search_path, app_name); |
| 578 | 592 | defer self.allocator.free(joined_path); |
| 579 | 593 | |
| 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)) |_| { | |
| 583 | 595 | break; |
| 584 | 596 | } else |err| if (err == error.FileNotFound) { |
| 585 | 597 | continue; |
| ... | ... | @@ -609,9 +621,15 @@ pub const ChildProcess = struct { |
| 609 | 621 | self.thread_handle = piProcInfo.hThread; |
| 610 | 622 | self.term = null; |
| 611 | 623 | |
| 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 | } | |
| 615 | 633 | } |
| 616 | 634 | |
| 617 | 635 | fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) !void { |
| ... | ... | @@ -622,18 +640,14 @@ pub const ChildProcess = struct { |
| 622 | 640 | StdIo.Ignore => try os.posixDup2(dev_null_fd, std_fileno), |
| 623 | 641 | } |
| 624 | 642 | } |
| 625 | ||
| 626 | 643 | }; |
| 627 | 644 | |
| 628 | fn 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 | { | |
| 645 | fn 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) { | |
| 634 | 647 | const err = windows.GetLastError(); |
| 635 | 648 | 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, | |
| 637 | 651 | windows.ERROR.INVALID_PARAMETER => unreachable, |
| 638 | 652 | windows.ERROR.INVALID_NAME => error.InvalidName, |
| 639 | 653 | else => os.unexpectedErrorWindows(err), |
| ... | ... | @@ -641,9 +655,6 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ? |
| 641 | 655 | } |
| 642 | 656 | } |
| 643 | 657 | |
| 644 | ||
| 645 | ||
| 646 | ||
| 647 | 658 | /// Caller must dealloc. |
| 648 | 659 | /// Guarantees a null byte at result[result.len]. |
| 649 | 660 | fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) ![]u8 { |
| ... | ... | @@ -653,8 +664,7 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) |
| 653 | 664 | var buf_stream = &io.BufferOutStream.init(&buf).stream; |
| 654 | 665 | |
| 655 | 666 | for (argv) |arg, arg_i| { |
| 656 | if (arg_i != 0) | |
| 657 | try buf.appendByte(' '); | |
| 667 | if (arg_i != 0) try buf.appendByte(' '); | |
| 658 | 668 | if (mem.indexOfAny(u8, arg, " \t\n\"") == null) { |
| 659 | 669 | try buf.append(arg); |
| 660 | 670 | continue; |
| ... | ... | @@ -688,7 +698,6 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void { |
| 688 | 698 | if (wr) |h| os.close(h); |
| 689 | 699 | } |
| 690 | 700 | |
| 691 | ||
| 692 | 701 | // TODO: workaround for bug where the `const` from `&const` is dropped when the type is |
| 693 | 702 | // a namespace field lookup |
| 694 | 703 | const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES; |
| ... | ... | @@ -717,8 +726,8 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S |
| 717 | 726 | try windowsMakePipe(&rd_h, &wr_h, sattr); |
| 718 | 727 | errdefer windowsDestroyPipe(rd_h, wr_h); |
| 719 | 728 | try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0); |
| 720 | *rd = rd_h; | |
| 721 | *wr = wr_h; | |
| 729 | rd.* = rd_h; | |
| 730 | wr.* = wr_h; | |
| 722 | 731 | } |
| 723 | 732 | |
| 724 | 733 | fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) !void { |
| ... | ... | @@ -727,8 +736,8 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const |
| 727 | 736 | try windowsMakePipe(&rd_h, &wr_h, sattr); |
| 728 | 737 | errdefer windowsDestroyPipe(rd_h, wr_h); |
| 729 | 738 | try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0); |
| 730 | *rd = rd_h; | |
| 731 | *wr = wr_h; | |
| 739 | rd.* = rd_h; | |
| 740 | wr.* = wr_h; | |
| 732 | 741 | } |
| 733 | 742 | |
| 734 | 743 | fn makePipe() ![2]i32 { |
| ... | ... | @@ -736,7 +745,8 @@ fn makePipe() ![2]i32 { |
| 736 | 745 | const err = posix.getErrno(posix.pipe(&fds)); |
| 737 | 746 | if (err > 0) { |
| 738 | 747 | return switch (err) { |
| 739 | posix.EMFILE, posix.ENFILE => error.SystemResources, | |
| 748 | posix.EMFILE, | |
| 749 | posix.ENFILE => error.SystemResources, | |
| 740 | 750 | else => os.unexpectedErrorPosix(err), |
| 741 | 751 | }; |
| 742 | 752 | } |
| ... | ... | @@ -744,8 +754,8 @@ fn makePipe() ![2]i32 { |
| 744 | 754 | } |
| 745 | 755 | |
| 746 | 756 | fn destroyPipe(pipe: &const [2]i32) void { |
| 747 | os.close((*pipe)[0]); | |
| 748 | os.close((*pipe)[1]); | |
| 757 | os.close((pipe.*)[0]); | |
| 758 | os.close((pipe.*)[1]); | |
| 749 | 759 | } |
| 750 | 760 | |
| 751 | 761 | // 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; |
| 10 | 10 | pub const STDOUT_FILENO = 1; |
| 11 | 11 | pub const STDERR_FILENO = 2; |
| 12 | 12 | |
| 13 | pub const PROT_NONE = 0x00; /// [MC2] no permissions | |
| 14 | pub const PROT_READ = 0x01; /// [MC2] pages can be read | |
| 15 | pub const PROT_WRITE = 0x02; /// [MC2] pages can be written | |
| 16 | pub const PROT_EXEC = 0x04; /// [MC2] pages can be executed | |
| 17 | ||
| 18 | pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space | |
| 19 | pub const MAP_FILE = 0x0000; /// map from file (default) | |
| 20 | pub const MAP_FIXED = 0x0010; /// interpret addr exactly | |
| 21 | pub const MAP_HASSEMAPHORE = 0x0200; /// region may contain semaphores | |
| 22 | pub const MAP_PRIVATE = 0x0002; /// changes are private | |
| 23 | pub const MAP_SHARED = 0x0001; /// share changes | |
| 24 | pub const MAP_NOCACHE = 0x0400; /// don't cache pages for this mapping | |
| 25 | pub const MAP_NORESERVE = 0x0040; /// don't reserve needed swap area | |
| 13 | /// [MC2] no permissions | |
| 14 | pub const PROT_NONE = 0x00; | |
| 15 | /// [MC2] pages can be read | |
| 16 | pub const PROT_READ = 0x01; | |
| 17 | /// [MC2] pages can be written | |
| 18 | pub const PROT_WRITE = 0x02; | |
| 19 | /// [MC2] pages can be executed | |
| 20 | pub const PROT_EXEC = 0x04; | |
| 21 | ||
| 22 | /// allocated from memory, swap space | |
| 23 | pub const MAP_ANONYMOUS = 0x1000; | |
| 24 | /// map from file (default) | |
| 25 | pub const MAP_FILE = 0x0000; | |
| 26 | /// interpret addr exactly | |
| 27 | pub const MAP_FIXED = 0x0010; | |
| 28 | /// region may contain semaphores | |
| 29 | pub const MAP_HASSEMAPHORE = 0x0200; | |
| 30 | /// changes are private | |
| 31 | pub const MAP_PRIVATE = 0x0002; | |
| 32 | /// share changes | |
| 33 | pub const MAP_SHARED = 0x0001; | |
| 34 | /// don't cache pages for this mapping | |
| 35 | pub const MAP_NOCACHE = 0x0400; | |
| 36 | /// don't reserve needed swap area | |
| 37 | pub const MAP_NORESERVE = 0x0040; | |
| 26 | 38 | pub const MAP_FAILED = @maxValue(usize); |
| 27 | 39 | |
| 28 | pub const WNOHANG = 0x00000001; /// [XSI] no hang in wait/no child to reap | |
| 29 | pub const WUNTRACED = 0x00000002; /// [XSI] notify on stop, untraced child | |
| 30 | ||
| 31 | pub const SA_ONSTACK = 0x0001; /// take signal on signal stack | |
| 32 | pub const SA_RESTART = 0x0002; /// restart system on signal return | |
| 33 | pub const SA_RESETHAND = 0x0004; /// reset to SIG_DFL when taking signal | |
| 34 | pub const SA_NOCLDSTOP = 0x0008; /// do not generate SIGCHLD on child stop | |
| 35 | pub const SA_NODEFER = 0x0010; /// don't mask the signal we're delivering | |
| 36 | pub const SA_NOCLDWAIT = 0x0020; /// don't keep zombies around | |
| 37 | pub const SA_SIGINFO = 0x0040; /// signal handler with SA_SIGINFO args | |
| 38 | pub const SA_USERTRAMP = 0x0100; /// do not bounce off kernel's sigtramp | |
| 39 | pub const SA_64REGSET = 0x0200; /// signal handler with SA_SIGINFO args with 64bit regs information | |
| 40 | /// [XSI] no hang in wait/no child to reap | |
| 41 | pub const WNOHANG = 0x00000001; | |
| 42 | /// [XSI] notify on stop, untraced child | |
| 43 | pub const WUNTRACED = 0x00000002; | |
| 44 | ||
| 45 | /// take signal on signal stack | |
| 46 | pub const SA_ONSTACK = 0x0001; | |
| 47 | /// restart system on signal return | |
| 48 | pub const SA_RESTART = 0x0002; | |
| 49 | /// reset to SIG_DFL when taking signal | |
| 50 | pub const SA_RESETHAND = 0x0004; | |
| 51 | /// do not generate SIGCHLD on child stop | |
| 52 | pub const SA_NOCLDSTOP = 0x0008; | |
| 53 | /// don't mask the signal we're delivering | |
| 54 | pub const SA_NODEFER = 0x0010; | |
| 55 | /// don't keep zombies around | |
| 56 | pub const SA_NOCLDWAIT = 0x0020; | |
| 57 | /// signal handler with SA_SIGINFO args | |
| 58 | pub const SA_SIGINFO = 0x0040; | |
| 59 | /// do not bounce off kernel's sigtramp | |
| 60 | pub const SA_USERTRAMP = 0x0100; | |
| 61 | /// signal handler with SA_SIGINFO args with 64bit regs information | |
| 62 | pub const SA_64REGSET = 0x0200; | |
| 40 | 63 | |
| 41 | 64 | pub const O_LARGEFILE = 0x0000; |
| 42 | 65 | pub const O_PATH = 0x0000; |
| ... | ... | @@ -46,20 +69,34 @@ pub const X_OK = 1; |
| 46 | 69 | pub const W_OK = 2; |
| 47 | 70 | pub const R_OK = 4; |
| 48 | 71 | |
| 49 | pub const O_RDONLY = 0x0000; /// open for reading only | |
| 50 | pub const O_WRONLY = 0x0001; /// open for writing only | |
| 51 | pub const O_RDWR = 0x0002; /// open for reading and writing | |
| 52 | pub const O_NONBLOCK = 0x0004; /// do not block on open or for data to become available | |
| 53 | pub const O_APPEND = 0x0008; /// append on each write | |
| 54 | pub const O_CREAT = 0x0200; /// create file if it does not exist | |
| 55 | pub const O_TRUNC = 0x0400; /// truncate size to 0 | |
| 56 | pub const O_EXCL = 0x0800; /// error if O_CREAT and the file exists | |
| 57 | pub const O_SHLOCK = 0x0010; /// atomically obtain a shared lock | |
| 58 | pub const O_EXLOCK = 0x0020; /// atomically obtain an exclusive lock | |
| 59 | pub const O_NOFOLLOW = 0x0100; /// do not follow symlinks | |
| 60 | pub const O_SYMLINK = 0x200000; /// allow open of symlinks | |
| 61 | pub const O_EVTONLY = 0x8000; /// descriptor requested for event notifications only | |
| 62 | pub const O_CLOEXEC = 0x1000000; /// mark as close-on-exec | |
| 72 | /// open for reading only | |
| 73 | pub const O_RDONLY = 0x0000; | |
| 74 | /// open for writing only | |
| 75 | pub const O_WRONLY = 0x0001; | |
| 76 | /// open for reading and writing | |
| 77 | pub const O_RDWR = 0x0002; | |
| 78 | /// do not block on open or for data to become available | |
| 79 | pub const O_NONBLOCK = 0x0004; | |
| 80 | /// append on each write | |
| 81 | pub const O_APPEND = 0x0008; | |
| 82 | /// create file if it does not exist | |
| 83 | pub const O_CREAT = 0x0200; | |
| 84 | /// truncate size to 0 | |
| 85 | pub const O_TRUNC = 0x0400; | |
| 86 | /// error if O_CREAT and the file exists | |
| 87 | pub const O_EXCL = 0x0800; | |
| 88 | /// atomically obtain a shared lock | |
| 89 | pub const O_SHLOCK = 0x0010; | |
| 90 | /// atomically obtain an exclusive lock | |
| 91 | pub const O_EXLOCK = 0x0020; | |
| 92 | /// do not follow symlinks | |
| 93 | pub const O_NOFOLLOW = 0x0100; | |
| 94 | /// allow open of symlinks | |
| 95 | pub const O_SYMLINK = 0x200000; | |
| 96 | /// descriptor requested for event notifications only | |
| 97 | pub const O_EVTONLY = 0x8000; | |
| 98 | /// mark as close-on-exec | |
| 99 | pub const O_CLOEXEC = 0x1000000; | |
| 63 | 100 | |
| 64 | 101 | pub const O_ACCMODE = 3; |
| 65 | 102 | pub const O_ALERT = 536870912; |
| ... | ... | @@ -87,52 +124,102 @@ pub const DT_LNK = 10; |
| 87 | 124 | pub const DT_SOCK = 12; |
| 88 | 125 | pub const DT_WHT = 14; |
| 89 | 126 | |
| 90 | pub const SIG_BLOCK = 1; /// block specified signal set | |
| 91 | pub const SIG_UNBLOCK = 2; /// unblock specified signal set | |
| 92 | pub const SIG_SETMASK = 3; /// set specified signal set | |
| 93 | ||
| 94 | pub const SIGHUP = 1; /// hangup | |
| 95 | pub const SIGINT = 2; /// interrupt | |
| 96 | pub const SIGQUIT = 3; /// quit | |
| 97 | pub const SIGILL = 4; /// illegal instruction (not reset when caught) | |
| 98 | pub const SIGTRAP = 5; /// trace trap (not reset when caught) | |
| 99 | pub const SIGABRT = 6; /// abort() | |
| 100 | pub const SIGPOLL = 7; /// pollable event ([XSR] generated, not supported) | |
| 101 | pub const SIGIOT = SIGABRT; /// compatibility | |
| 102 | pub const SIGEMT = 7; /// EMT instruction | |
| 103 | pub const SIGFPE = 8; /// floating point exception | |
| 104 | pub const SIGKILL = 9; /// kill (cannot be caught or ignored) | |
| 105 | pub const SIGBUS = 10; /// bus error | |
| 106 | pub const SIGSEGV = 11; /// segmentation violation | |
| 107 | pub const SIGSYS = 12; /// bad argument to system call | |
| 108 | pub const SIGPIPE = 13; /// write on a pipe with no one to read it | |
| 109 | pub const SIGALRM = 14; /// alarm clock | |
| 110 | pub const SIGTERM = 15; /// software termination signal from kill | |
| 111 | pub const SIGURG = 16; /// urgent condition on IO channel | |
| 112 | pub const SIGSTOP = 17; /// sendable stop signal not from tty | |
| 113 | pub const SIGTSTP = 18; /// stop signal from tty | |
| 114 | pub const SIGCONT = 19; /// continue a stopped process | |
| 115 | pub const SIGCHLD = 20; /// to parent on child stop or exit | |
| 116 | pub const SIGTTIN = 21; /// to readers pgrp upon background tty read | |
| 117 | pub const SIGTTOU = 22; /// like TTIN for output if (tp->t_local&LTOSTOP) | |
| 118 | pub const SIGIO = 23; /// input/output possible signal | |
| 119 | pub const SIGXCPU = 24; /// exceeded CPU time limit | |
| 120 | pub const SIGXFSZ = 25; /// exceeded file size limit | |
| 121 | pub const SIGVTALRM = 26; /// virtual time alarm | |
| 122 | pub const SIGPROF = 27; /// profiling time alarm | |
| 123 | pub const SIGWINCH = 28; /// window size changes | |
| 124 | pub const SIGINFO = 29; /// information request | |
| 125 | pub const SIGUSR1 = 30; /// user defined signal 1 | |
| 126 | pub const SIGUSR2 = 31; /// user defined signal 2 | |
| 127 | ||
| 128 | fn wstatus(x: i32) i32 { return x & 0o177; } | |
| 127 | /// block specified signal set | |
| 128 | pub const SIG_BLOCK = 1; | |
| 129 | /// unblock specified signal set | |
| 130 | pub const SIG_UNBLOCK = 2; | |
| 131 | /// set specified signal set | |
| 132 | pub const SIG_SETMASK = 3; | |
| 133 | ||
| 134 | /// hangup | |
| 135 | pub const SIGHUP = 1; | |
| 136 | /// interrupt | |
| 137 | pub const SIGINT = 2; | |
| 138 | /// quit | |
| 139 | pub const SIGQUIT = 3; | |
| 140 | /// illegal instruction (not reset when caught) | |
| 141 | pub const SIGILL = 4; | |
| 142 | /// trace trap (not reset when caught) | |
| 143 | pub const SIGTRAP = 5; | |
| 144 | /// abort() | |
| 145 | pub const SIGABRT = 6; | |
| 146 | /// pollable event ([XSR] generated, not supported) | |
| 147 | pub const SIGPOLL = 7; | |
| 148 | /// compatibility | |
| 149 | pub const SIGIOT = SIGABRT; | |
| 150 | /// EMT instruction | |
| 151 | pub const SIGEMT = 7; | |
| 152 | /// floating point exception | |
| 153 | pub const SIGFPE = 8; | |
| 154 | /// kill (cannot be caught or ignored) | |
| 155 | pub const SIGKILL = 9; | |
| 156 | /// bus error | |
| 157 | pub const SIGBUS = 10; | |
| 158 | /// segmentation violation | |
| 159 | pub const SIGSEGV = 11; | |
| 160 | /// bad argument to system call | |
| 161 | pub const SIGSYS = 12; | |
| 162 | /// write on a pipe with no one to read it | |
| 163 | pub const SIGPIPE = 13; | |
| 164 | /// alarm clock | |
| 165 | pub const SIGALRM = 14; | |
| 166 | /// software termination signal from kill | |
| 167 | pub const SIGTERM = 15; | |
| 168 | /// urgent condition on IO channel | |
| 169 | pub const SIGURG = 16; | |
| 170 | /// sendable stop signal not from tty | |
| 171 | pub const SIGSTOP = 17; | |
| 172 | /// stop signal from tty | |
| 173 | pub const SIGTSTP = 18; | |
| 174 | /// continue a stopped process | |
| 175 | pub const SIGCONT = 19; | |
| 176 | /// to parent on child stop or exit | |
| 177 | pub const SIGCHLD = 20; | |
| 178 | /// to readers pgrp upon background tty read | |
| 179 | pub const SIGTTIN = 21; | |
| 180 | /// like TTIN for output if (tp->t_local&LTOSTOP) | |
| 181 | pub const SIGTTOU = 22; | |
| 182 | /// input/output possible signal | |
| 183 | pub const SIGIO = 23; | |
| 184 | /// exceeded CPU time limit | |
| 185 | pub const SIGXCPU = 24; | |
| 186 | /// exceeded file size limit | |
| 187 | pub const SIGXFSZ = 25; | |
| 188 | /// virtual time alarm | |
| 189 | pub const SIGVTALRM = 26; | |
| 190 | /// profiling time alarm | |
| 191 | pub const SIGPROF = 27; | |
| 192 | /// window size changes | |
| 193 | pub const SIGWINCH = 28; | |
| 194 | /// information request | |
| 195 | pub const SIGINFO = 29; | |
| 196 | /// user defined signal 1 | |
| 197 | pub const SIGUSR1 = 30; | |
| 198 | /// user defined signal 2 | |
| 199 | pub const SIGUSR2 = 31; | |
| 200 | ||
| 201 | fn wstatus(x: i32) i32 { | |
| 202 | return x & 0o177; | |
| 203 | } | |
| 129 | 204 | const wstopped = 0o177; |
| 130 | pub fn WEXITSTATUS(x: i32) i32 { return x >> 8; } | |
| 131 | pub fn WTERMSIG(x: i32) i32 { return wstatus(x); } | |
| 132 | pub fn WSTOPSIG(x: i32) i32 { return x >> 8; } | |
| 133 | pub fn WIFEXITED(x: i32) bool { return wstatus(x) == 0; } | |
| 134 | pub fn WIFSTOPPED(x: i32) bool { return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; } | |
| 135 | pub fn WIFSIGNALED(x: i32) bool { return wstatus(x) != wstopped and wstatus(x) != 0; } | |
| 205 | pub fn WEXITSTATUS(x: i32) i32 { | |
| 206 | return x >> 8; | |
| 207 | } | |
| 208 | pub fn WTERMSIG(x: i32) i32 { | |
| 209 | return wstatus(x); | |
| 210 | } | |
| 211 | pub fn WSTOPSIG(x: i32) i32 { | |
| 212 | return x >> 8; | |
| 213 | } | |
| 214 | pub fn WIFEXITED(x: i32) bool { | |
| 215 | return wstatus(x) == 0; | |
| 216 | } | |
| 217 | pub fn WIFSTOPPED(x: i32) bool { | |
| 218 | return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; | |
| 219 | } | |
| 220 | pub fn WIFSIGNALED(x: i32) bool { | |
| 221 | return wstatus(x) != wstopped and wstatus(x) != 0; | |
| 222 | } | |
| 136 | 223 | |
| 137 | 224 | /// Get the errno from a syscall return value, or 0 for no error. |
| 138 | 225 | pub fn getErrno(r: usize) usize { |
| ... | ... | @@ -184,11 +271,8 @@ pub fn write(fd: i32, buf: &const u8, nbyte: usize) usize { |
| 184 | 271 | return errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte)); |
| 185 | 272 | } |
| 186 | 273 | |
| 187 | pub 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); | |
| 274 | pub 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); | |
| 192 | 276 | const isize_result = @bitCast(isize, @ptrToInt(ptr_result)); |
| 193 | 277 | return errnoWrap(isize_result); |
| 194 | 278 | } |
| ... | ... | @@ -202,7 +286,7 @@ pub fn unlink(path: &const u8) usize { |
| 202 | 286 | } |
| 203 | 287 | |
| 204 | 288 | pub 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; | |
| 206 | 290 | } |
| 207 | 291 | |
| 208 | 292 | pub fn waitpid(pid: i32, status: &i32, options: u32) usize { |
| ... | ... | @@ -223,7 +307,6 @@ pub fn pipe(fds: &[2]i32) usize { |
| 223 | 307 | return errnoWrap(c.pipe(@ptrCast(&c_int, fds))); |
| 224 | 308 | } |
| 225 | 309 | |
| 226 | ||
| 227 | 310 | pub fn getdirentries64(fd: i32, buf_ptr: &u8, buf_len: usize, basep: &i64) usize { |
| 228 | 311 | return errnoWrap(@bitCast(isize, c.__getdirentries64(fd, buf_ptr, buf_len, basep))); |
| 229 | 312 | } |
| ... | ... | @@ -269,7 +352,7 @@ pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { |
| 269 | 352 | } |
| 270 | 353 | |
| 271 | 354 | pub 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; | |
| 273 | 356 | } |
| 274 | 357 | |
| 275 | 358 | pub fn setreuid(ruid: u32, euid: u32) usize { |
| ... | ... | @@ -287,8 +370,8 @@ pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&s |
| 287 | 370 | pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize { |
| 288 | 371 | assert(sig != SIGKILL); |
| 289 | 372 | 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), | |
| 292 | 375 | .sa_flags = @bitCast(c_int, act.flags), |
| 293 | 376 | .sa_mask = act.mask, |
| 294 | 377 | }; |
| ... | ... | @@ -298,8 +381,8 @@ pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigacti |
| 298 | 381 | return result; |
| 299 | 382 | } |
| 300 | 383 | 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), | |
| 303 | 386 | .flags = @bitCast(u32, coact.sa_flags), |
| 304 | 387 | .mask = coact.sa_mask, |
| 305 | 388 | }; |
| ... | ... | @@ -319,23 +402,22 @@ pub const sockaddr = c.sockaddr; |
| 319 | 402 | |
| 320 | 403 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 321 | 404 | pub const Sigaction = struct { |
| 322 | handler: extern fn(i32)void, | |
| 405 | handler: extern fn(i32) void, | |
| 323 | 406 | mask: sigset_t, |
| 324 | 407 | flags: u32, |
| 325 | 408 | }; |
| 326 | 409 | |
| 327 | 410 | pub fn sigaddset(set: &sigset_t, signo: u5) void { |
| 328 | *set |= u32(1) << (signo - 1); | |
| 411 | set.* |= u32(1) << (signo - 1); | |
| 329 | 412 | } |
| 330 | 413 | |
| 331 | 414 | /// Takes the return value from a syscall and formats it back in the way |
| 332 | 415 | /// that the kernel represents it to libc. Errno was a mistake, let's make |
| 333 | 416 | /// it go away forever. |
| 334 | 417 | fn 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); | |
| 336 | 419 | } |
| 337 | 420 | |
| 338 | ||
| 339 | 421 | pub const timezone = c.timezone; |
| 340 | 422 | pub const timeval = c.timeval; |
| 341 | 423 | pub const mach_timebase_info_data = c.mach_timebase_info_data; |
std/os/index.zig+38-42| ... | ... | @@ -137,7 +137,7 @@ pub fn getRandomBytes(buf: []u8) !void { |
| 137 | 137 | } |
| 138 | 138 | }, |
| 139 | 139 | Os.zen => { |
| 140 | const randomness = []u8 { | |
| 140 | const randomness = []u8{ | |
| 141 | 141 | 42, |
| 142 | 142 | 1, |
| 143 | 143 | 7, |
| ... | ... | @@ -265,7 +265,7 @@ pub fn posixRead(fd: i32, buf: []u8) !void { |
| 265 | 265 | } |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | pub const PosixWriteError = error { | |
| 268 | pub const PosixWriteError = error{ | |
| 269 | 269 | WouldBlock, |
| 270 | 270 | FileClosed, |
| 271 | 271 | DestinationAddressRequired, |
| ... | ... | @@ -310,7 +310,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void { |
| 310 | 310 | } |
| 311 | 311 | } |
| 312 | 312 | |
| 313 | pub const PosixOpenError = error { | |
| 313 | pub const PosixOpenError = error{ | |
| 314 | 314 | OutOfMemory, |
| 315 | 315 | AccessDenied, |
| 316 | 316 | FileTooBig, |
| ... | ... | @@ -477,7 +477,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, allocator: |
| 477 | 477 | return posixExecveErrnoToErr(err); |
| 478 | 478 | } |
| 479 | 479 | |
| 480 | pub const PosixExecveError = error { | |
| 480 | pub const PosixExecveError = error{ | |
| 481 | 481 | SystemResources, |
| 482 | 482 | AccessDenied, |
| 483 | 483 | InvalidExe, |
| ... | ... | @@ -512,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { |
| 512 | 512 | }; |
| 513 | 513 | } |
| 514 | 514 | |
| 515 | pub var linux_aux_raw = []usize {0} ** 38; | |
| 515 | pub var linux_aux_raw = []usize{0} ** 38; | |
| 516 | 516 | pub var posix_environ_raw: []&u8 = undefined; |
| 517 | 517 | |
| 518 | 518 | /// Caller must free result when done. |
| ... | ... | @@ -667,7 +667,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con |
| 667 | 667 | } |
| 668 | 668 | } |
| 669 | 669 | |
| 670 | pub const WindowsSymLinkError = error { | |
| 670 | pub const WindowsSymLinkError = error{ | |
| 671 | 671 | OutOfMemory, |
| 672 | 672 | Unexpected, |
| 673 | 673 | }; |
| ... | ... | @@ -686,7 +686,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path |
| 686 | 686 | } |
| 687 | 687 | } |
| 688 | 688 | |
| 689 | pub const PosixSymLinkError = error { | |
| 689 | pub const PosixSymLinkError = error{ | |
| 690 | 690 | OutOfMemory, |
| 691 | 691 | AccessDenied, |
| 692 | 692 | DiskQuota, |
| ... | ... | @@ -895,7 +895,7 @@ pub const AtomicFile = struct { |
| 895 | 895 | else => return err, |
| 896 | 896 | }; |
| 897 | 897 | |
| 898 | return AtomicFile { | |
| 898 | return AtomicFile{ | |
| 899 | 899 | .allocator = allocator, |
| 900 | 900 | .file = file, |
| 901 | 901 | .tmp_path = tmp_path, |
| ... | ... | @@ -1087,7 +1087,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 1087 | 1087 | /// removes it. If it cannot be removed because it is a non-empty directory, |
| 1088 | 1088 | /// this function recursively removes its entries and then tries again. |
| 1089 | 1089 | /// TODO non-recursive implementation |
| 1090 | const DeleteTreeError = error { | |
| 1090 | const DeleteTreeError = error{ | |
| 1091 | 1091 | OutOfMemory, |
| 1092 | 1092 | AccessDenied, |
| 1093 | 1093 | FileTooBig, |
| ... | ... | @@ -1217,7 +1217,7 @@ pub const Dir = struct { |
| 1217 | 1217 | Os.ios => 0, |
| 1218 | 1218 | else => {}, |
| 1219 | 1219 | }; |
| 1220 | return Dir { | |
| 1220 | return Dir{ | |
| 1221 | 1221 | .allocator = allocator, |
| 1222 | 1222 | .fd = fd, |
| 1223 | 1223 | .darwin_seek = darwin_seek_init, |
| ... | ... | @@ -1294,7 +1294,7 @@ pub const Dir = struct { |
| 1294 | 1294 | posix.DT_WHT => Entry.Kind.Whiteout, |
| 1295 | 1295 | else => Entry.Kind.Unknown, |
| 1296 | 1296 | }; |
| 1297 | return Entry { | |
| 1297 | return Entry{ | |
| 1298 | 1298 | .name = name, |
| 1299 | 1299 | .kind = entry_kind, |
| 1300 | 1300 | }; |
| ... | ... | @@ -1355,7 +1355,7 @@ pub const Dir = struct { |
| 1355 | 1355 | posix.DT_SOCK => Entry.Kind.UnixDomainSocket, |
| 1356 | 1356 | else => Entry.Kind.Unknown, |
| 1357 | 1357 | }; |
| 1358 | return Entry { | |
| 1358 | return Entry{ | |
| 1359 | 1359 | .name = name, |
| 1360 | 1360 | .kind = entry_kind, |
| 1361 | 1361 | }; |
| ... | ... | @@ -1465,7 +1465,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) !void { |
| 1465 | 1465 | }; |
| 1466 | 1466 | } |
| 1467 | 1467 | |
| 1468 | pub const WindowsGetStdHandleErrs = error { | |
| 1468 | pub const WindowsGetStdHandleErrs = error{ | |
| 1469 | 1469 | NoStdHandles, |
| 1470 | 1470 | Unexpected, |
| 1471 | 1471 | }; |
| ... | ... | @@ -1489,7 +1489,7 @@ pub const ArgIteratorPosix = struct { |
| 1489 | 1489 | count: usize, |
| 1490 | 1490 | |
| 1491 | 1491 | pub fn init() ArgIteratorPosix { |
| 1492 | return ArgIteratorPosix { | |
| 1492 | return ArgIteratorPosix{ | |
| 1493 | 1493 | .index = 0, |
| 1494 | 1494 | .count = raw.len, |
| 1495 | 1495 | }; |
| ... | ... | @@ -1522,16 +1522,14 @@ pub const ArgIteratorWindows = struct { |
| 1522 | 1522 | quote_count: usize, |
| 1523 | 1523 | seen_quote_count: usize, |
| 1524 | 1524 | |
| 1525 | pub const NextError = error { | |
| 1526 | OutOfMemory, | |
| 1527 | }; | |
| 1525 | pub const NextError = error{OutOfMemory}; | |
| 1528 | 1526 | |
| 1529 | 1527 | pub fn init() ArgIteratorWindows { |
| 1530 | 1528 | return initWithCmdLine(windows.GetCommandLineA()); |
| 1531 | 1529 | } |
| 1532 | 1530 | |
| 1533 | 1531 | pub fn initWithCmdLine(cmd_line: &const u8) ArgIteratorWindows { |
| 1534 | return ArgIteratorWindows { | |
| 1532 | return ArgIteratorWindows{ | |
| 1535 | 1533 | .index = 0, |
| 1536 | 1534 | .cmd_line = cmd_line, |
| 1537 | 1535 | .in_quote = false, |
| ... | ... | @@ -1676,9 +1674,7 @@ pub const ArgIterator = struct { |
| 1676 | 1674 | inner: InnerType, |
| 1677 | 1675 | |
| 1678 | 1676 | pub fn init() ArgIterator { |
| 1679 | return ArgIterator { | |
| 1680 | .inner = InnerType.init(), | |
| 1681 | }; | |
| 1677 | return ArgIterator{ .inner = InnerType.init() }; | |
| 1682 | 1678 | } |
| 1683 | 1679 | |
| 1684 | 1680 | pub const NextError = ArgIteratorWindows.NextError; |
| ... | ... | @@ -1757,33 +1753,33 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { |
| 1757 | 1753 | } |
| 1758 | 1754 | |
| 1759 | 1755 | test "windows arg parsing" { |
| 1760 | testWindowsCmdLine(c"a b\tc d", [][]const u8 { | |
| 1756 | testWindowsCmdLine(c"a b\tc d", [][]const u8{ | |
| 1761 | 1757 | "a", |
| 1762 | 1758 | "b", |
| 1763 | 1759 | "c", |
| 1764 | 1760 | "d", |
| 1765 | 1761 | }); |
| 1766 | testWindowsCmdLine(c"\"abc\" d e", [][]const u8 { | |
| 1762 | testWindowsCmdLine(c"\"abc\" d e", [][]const u8{ | |
| 1767 | 1763 | "abc", |
| 1768 | 1764 | "d", |
| 1769 | 1765 | "e", |
| 1770 | 1766 | }); |
| 1771 | testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8 { | |
| 1767 | testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{ | |
| 1772 | 1768 | "a\\\\\\b", |
| 1773 | 1769 | "de fg", |
| 1774 | 1770 | "h", |
| 1775 | 1771 | }); |
| 1776 | testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8 { | |
| 1772 | testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{ | |
| 1777 | 1773 | "a\\\"b", |
| 1778 | 1774 | "c", |
| 1779 | 1775 | "d", |
| 1780 | 1776 | }); |
| 1781 | testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8 { | |
| 1777 | testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{ | |
| 1782 | 1778 | "a\\\\b c", |
| 1783 | 1779 | "d", |
| 1784 | 1780 | "e", |
| 1785 | 1781 | }); |
| 1786 | testWindowsCmdLine(c"a b\tc \"d f", [][]const u8 { | |
| 1782 | testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{ | |
| 1787 | 1783 | "a", |
| 1788 | 1784 | "b", |
| 1789 | 1785 | "c", |
| ... | ... | @@ -1791,7 +1787,7 @@ test "windows arg parsing" { |
| 1791 | 1787 | "f", |
| 1792 | 1788 | }); |
| 1793 | 1789 | |
| 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{ | |
| 1795 | 1791 | ".\\..\\zig-cache\\build", |
| 1796 | 1792 | "bin\\zig.exe", |
| 1797 | 1793 | ".\\..", |
| ... | ... | @@ -1811,7 +1807,7 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const |
| 1811 | 1807 | |
| 1812 | 1808 | // TODO make this a build variable that you can set |
| 1813 | 1809 | const unexpected_error_tracing = false; |
| 1814 | const UnexpectedError = error { | |
| 1810 | const UnexpectedError = error{ | |
| 1815 | 1811 | /// The Operating System returned an undocumented error code. |
| 1816 | 1812 | Unexpected, |
| 1817 | 1813 | }; |
| ... | ... | @@ -1950,7 +1946,7 @@ pub fn isTty(handle: FileHandle) bool { |
| 1950 | 1946 | } |
| 1951 | 1947 | } |
| 1952 | 1948 | |
| 1953 | pub const PosixSocketError = error { | |
| 1949 | pub const PosixSocketError = error{ | |
| 1954 | 1950 | /// Permission to create a socket of the specified type and/or |
| 1955 | 1951 | /// pro‐tocol is denied. |
| 1956 | 1952 | PermissionDenied, |
| ... | ... | @@ -1992,7 +1988,7 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 { |
| 1992 | 1988 | } |
| 1993 | 1989 | } |
| 1994 | 1990 | |
| 1995 | pub const PosixBindError = error { | |
| 1991 | pub const PosixBindError = error{ | |
| 1996 | 1992 | /// The address is protected, and the user is not the superuser. |
| 1997 | 1993 | /// For UNIX domain sockets: Search permission is denied on a component |
| 1998 | 1994 | /// of the path prefix. |
| ... | ... | @@ -2065,7 +2061,7 @@ pub fn posixBind(fd: i32, addr: &const posix.sockaddr) PosixBindError!void { |
| 2065 | 2061 | } |
| 2066 | 2062 | } |
| 2067 | 2063 | |
| 2068 | const PosixListenError = error { | |
| 2064 | const PosixListenError = error{ | |
| 2069 | 2065 | /// Another socket is already listening on the same port. |
| 2070 | 2066 | /// For Internet domain sockets, the socket referred to by sockfd had not previously |
| 2071 | 2067 | /// 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 { |
| 2098 | 2094 | } |
| 2099 | 2095 | } |
| 2100 | 2096 | |
| 2101 | pub const PosixAcceptError = error { | |
| 2097 | pub const PosixAcceptError = error{ | |
| 2102 | 2098 | /// The socket is marked nonblocking and no connections are present to be accepted. |
| 2103 | 2099 | WouldBlock, |
| 2104 | 2100 | |
| ... | ... | @@ -2165,7 +2161,7 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError! |
| 2165 | 2161 | } |
| 2166 | 2162 | } |
| 2167 | 2163 | |
| 2168 | pub const LinuxEpollCreateError = error { | |
| 2164 | pub const LinuxEpollCreateError = error{ | |
| 2169 | 2165 | /// Invalid value specified in flags. |
| 2170 | 2166 | InvalidSyscall, |
| 2171 | 2167 | |
| ... | ... | @@ -2198,7 +2194,7 @@ pub fn linuxEpollCreate(flags: u32) LinuxEpollCreateError!i32 { |
| 2198 | 2194 | } |
| 2199 | 2195 | } |
| 2200 | 2196 | |
| 2201 | pub const LinuxEpollCtlError = error { | |
| 2197 | pub const LinuxEpollCtlError = error{ | |
| 2202 | 2198 | /// epfd or fd is not a valid file descriptor. |
| 2203 | 2199 | InvalidFileDescriptor, |
| 2204 | 2200 | |
| ... | ... | @@ -2271,7 +2267,7 @@ pub fn linuxEpollWait(epfd: i32, events: []linux.epoll_event, timeout: i32) usiz |
| 2271 | 2267 | } |
| 2272 | 2268 | } |
| 2273 | 2269 | |
| 2274 | pub const PosixGetSockNameError = error { | |
| 2270 | pub const PosixGetSockNameError = error{ | |
| 2275 | 2271 | /// Insufficient resources were available in the system to perform the operation. |
| 2276 | 2272 | SystemResources, |
| 2277 | 2273 | |
| ... | ... | @@ -2295,7 +2291,7 @@ pub fn posixGetSockName(sockfd: i32) PosixGetSockNameError!posix.sockaddr { |
| 2295 | 2291 | } |
| 2296 | 2292 | } |
| 2297 | 2293 | |
| 2298 | pub const PosixConnectError = error { | |
| 2294 | pub const PosixConnectError = error{ | |
| 2299 | 2295 | /// For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket |
| 2300 | 2296 | /// file, or search permission is denied for one of the directories in the path prefix. |
| 2301 | 2297 | /// or |
| ... | ... | @@ -2485,7 +2481,7 @@ pub const Thread = struct { |
| 2485 | 2481 | } |
| 2486 | 2482 | }; |
| 2487 | 2483 | |
| 2488 | pub const SpawnThreadError = error { | |
| 2484 | pub const SpawnThreadError = error{ | |
| 2489 | 2485 | /// A system-imposed limit on the number of threads was encountered. |
| 2490 | 2486 | /// There are a number of limits that may trigger this error: |
| 2491 | 2487 | /// * the RLIMIT_NPROC soft resource limit (set via setrlimit(2)), |
| ... | ... | @@ -2533,7 +2529,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2533 | 2529 | if (@sizeOf(Context) == 0) { |
| 2534 | 2530 | return startFn({}); |
| 2535 | 2531 | } else { |
| 2536 | return startFn(*@ptrCast(&Context, @alignCast(@alignOf(Context), arg))); | |
| 2532 | return startFn(@ptrCast(&Context, @alignCast(@alignOf(Context), arg)).*); | |
| 2537 | 2533 | } |
| 2538 | 2534 | } |
| 2539 | 2535 | }; |
| ... | ... | @@ -2563,7 +2559,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2563 | 2559 | if (@sizeOf(Context) == 0) { |
| 2564 | 2560 | return startFn({}); |
| 2565 | 2561 | } else { |
| 2566 | return startFn(*@intToPtr(&const Context, ctx_addr)); | |
| 2562 | return startFn(@intToPtr(&const Context, ctx_addr).*); | |
| 2567 | 2563 | } |
| 2568 | 2564 | } |
| 2569 | 2565 | extern fn posixThreadMain(ctx: ?&c_void) ?&c_void { |
| ... | ... | @@ -2571,7 +2567,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2571 | 2567 | _ = startFn({}); |
| 2572 | 2568 | return null; |
| 2573 | 2569 | } else { |
| 2574 | _ = startFn(*@ptrCast(&const Context, @alignCast(@alignOf(Context), ctx))); | |
| 2570 | _ = startFn(@ptrCast(&const Context, @alignCast(@alignOf(Context), ctx)).*); | |
| 2575 | 2571 | return null; |
| 2576 | 2572 | } |
| 2577 | 2573 | } |
| ... | ... | @@ -2591,7 +2587,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2591 | 2587 | stack_end -= stack_end % @alignOf(Context); |
| 2592 | 2588 | assert(stack_end >= stack_addr); |
| 2593 | 2589 | const context_ptr = @alignCast(@alignOf(Context), @intToPtr(&Context, stack_end)); |
| 2594 | *context_ptr = context; | |
| 2590 | context_ptr.* = context; | |
| 2595 | 2591 | arg = stack_end; |
| 2596 | 2592 | } |
| 2597 | 2593 |
std/os/linux/index.zig+189-190| ... | ... | @@ -30,96 +30,95 @@ pub const FUTEX_PRIVATE_FLAG = 128; |
| 30 | 30 | |
| 31 | 31 | pub const FUTEX_CLOCK_REALTIME = 256; |
| 32 | 32 | |
| 33 | ||
| 34 | pub const PROT_NONE = 0; | |
| 35 | pub const PROT_READ = 1; | |
| 36 | pub const PROT_WRITE = 2; | |
| 37 | pub const PROT_EXEC = 4; | |
| 33 | pub const PROT_NONE = 0; | |
| 34 | pub const PROT_READ = 1; | |
| 35 | pub const PROT_WRITE = 2; | |
| 36 | pub const PROT_EXEC = 4; | |
| 38 | 37 | pub const PROT_GROWSDOWN = 0x01000000; |
| 39 | pub const PROT_GROWSUP = 0x02000000; | |
| 40 | ||
| 41 | pub const MAP_FAILED = @maxValue(usize); | |
| 42 | pub const MAP_SHARED = 0x01; | |
| 43 | pub const MAP_PRIVATE = 0x02; | |
| 44 | pub const MAP_TYPE = 0x0f; | |
| 45 | pub const MAP_FIXED = 0x10; | |
| 46 | pub const MAP_ANONYMOUS = 0x20; | |
| 47 | pub const MAP_NORESERVE = 0x4000; | |
| 48 | pub const MAP_GROWSDOWN = 0x0100; | |
| 49 | pub const MAP_DENYWRITE = 0x0800; | |
| 38 | pub const PROT_GROWSUP = 0x02000000; | |
| 39 | ||
| 40 | pub const MAP_FAILED = @maxValue(usize); | |
| 41 | pub const MAP_SHARED = 0x01; | |
| 42 | pub const MAP_PRIVATE = 0x02; | |
| 43 | pub const MAP_TYPE = 0x0f; | |
| 44 | pub const MAP_FIXED = 0x10; | |
| 45 | pub const MAP_ANONYMOUS = 0x20; | |
| 46 | pub const MAP_NORESERVE = 0x4000; | |
| 47 | pub const MAP_GROWSDOWN = 0x0100; | |
| 48 | pub const MAP_DENYWRITE = 0x0800; | |
| 50 | 49 | pub const MAP_EXECUTABLE = 0x1000; |
| 51 | pub const MAP_LOCKED = 0x2000; | |
| 52 | pub const MAP_POPULATE = 0x8000; | |
| 53 | pub const MAP_NONBLOCK = 0x10000; | |
| 54 | pub const MAP_STACK = 0x20000; | |
| 55 | pub const MAP_HUGETLB = 0x40000; | |
| 56 | pub const MAP_FILE = 0; | |
| 50 | pub const MAP_LOCKED = 0x2000; | |
| 51 | pub const MAP_POPULATE = 0x8000; | |
| 52 | pub const MAP_NONBLOCK = 0x10000; | |
| 53 | pub const MAP_STACK = 0x20000; | |
| 54 | pub const MAP_HUGETLB = 0x40000; | |
| 55 | pub const MAP_FILE = 0; | |
| 57 | 56 | |
| 58 | 57 | pub const F_OK = 0; |
| 59 | 58 | pub const X_OK = 1; |
| 60 | 59 | pub const W_OK = 2; |
| 61 | 60 | pub const R_OK = 4; |
| 62 | 61 | |
| 63 | pub const WNOHANG = 1; | |
| 64 | pub const WUNTRACED = 2; | |
| 65 | pub const WSTOPPED = 2; | |
| 66 | pub const WEXITED = 4; | |
| 62 | pub const WNOHANG = 1; | |
| 63 | pub const WUNTRACED = 2; | |
| 64 | pub const WSTOPPED = 2; | |
| 65 | pub const WEXITED = 4; | |
| 67 | 66 | pub const WCONTINUED = 8; |
| 68 | pub const WNOWAIT = 0x1000000; | |
| 69 | ||
| 70 | pub const SA_NOCLDSTOP = 1; | |
| 71 | pub const SA_NOCLDWAIT = 2; | |
| 72 | pub const SA_SIGINFO = 4; | |
| 73 | pub const SA_ONSTACK = 0x08000000; | |
| 74 | pub const SA_RESTART = 0x10000000; | |
| 75 | pub const SA_NODEFER = 0x40000000; | |
| 76 | pub const SA_RESETHAND = 0x80000000; | |
| 77 | pub const SA_RESTORER = 0x04000000; | |
| 78 | ||
| 79 | pub const SIGHUP = 1; | |
| 80 | pub const SIGINT = 2; | |
| 81 | pub const SIGQUIT = 3; | |
| 82 | pub const SIGILL = 4; | |
| 83 | pub const SIGTRAP = 5; | |
| 84 | pub const SIGABRT = 6; | |
| 85 | pub const SIGIOT = SIGABRT; | |
| 86 | pub const SIGBUS = 7; | |
| 87 | pub const SIGFPE = 8; | |
| 88 | pub const SIGKILL = 9; | |
| 89 | pub const SIGUSR1 = 10; | |
| 90 | pub const SIGSEGV = 11; | |
| 91 | pub const SIGUSR2 = 12; | |
| 92 | pub const SIGPIPE = 13; | |
| 93 | pub const SIGALRM = 14; | |
| 94 | pub const SIGTERM = 15; | |
| 67 | pub const WNOWAIT = 0x1000000; | |
| 68 | ||
| 69 | pub const SA_NOCLDSTOP = 1; | |
| 70 | pub const SA_NOCLDWAIT = 2; | |
| 71 | pub const SA_SIGINFO = 4; | |
| 72 | pub const SA_ONSTACK = 0x08000000; | |
| 73 | pub const SA_RESTART = 0x10000000; | |
| 74 | pub const SA_NODEFER = 0x40000000; | |
| 75 | pub const SA_RESETHAND = 0x80000000; | |
| 76 | pub const SA_RESTORER = 0x04000000; | |
| 77 | ||
| 78 | pub const SIGHUP = 1; | |
| 79 | pub const SIGINT = 2; | |
| 80 | pub const SIGQUIT = 3; | |
| 81 | pub const SIGILL = 4; | |
| 82 | pub const SIGTRAP = 5; | |
| 83 | pub const SIGABRT = 6; | |
| 84 | pub const SIGIOT = SIGABRT; | |
| 85 | pub const SIGBUS = 7; | |
| 86 | pub const SIGFPE = 8; | |
| 87 | pub const SIGKILL = 9; | |
| 88 | pub const SIGUSR1 = 10; | |
| 89 | pub const SIGSEGV = 11; | |
| 90 | pub const SIGUSR2 = 12; | |
| 91 | pub const SIGPIPE = 13; | |
| 92 | pub const SIGALRM = 14; | |
| 93 | pub const SIGTERM = 15; | |
| 95 | 94 | pub const SIGSTKFLT = 16; |
| 96 | pub const SIGCHLD = 17; | |
| 97 | pub const SIGCONT = 18; | |
| 98 | pub const SIGSTOP = 19; | |
| 99 | pub const SIGTSTP = 20; | |
| 100 | pub const SIGTTIN = 21; | |
| 101 | pub const SIGTTOU = 22; | |
| 102 | pub const SIGURG = 23; | |
| 103 | pub const SIGXCPU = 24; | |
| 104 | pub const SIGXFSZ = 25; | |
| 95 | pub const SIGCHLD = 17; | |
| 96 | pub const SIGCONT = 18; | |
| 97 | pub const SIGSTOP = 19; | |
| 98 | pub const SIGTSTP = 20; | |
| 99 | pub const SIGTTIN = 21; | |
| 100 | pub const SIGTTOU = 22; | |
| 101 | pub const SIGURG = 23; | |
| 102 | pub const SIGXCPU = 24; | |
| 103 | pub const SIGXFSZ = 25; | |
| 105 | 104 | pub const SIGVTALRM = 26; |
| 106 | pub const SIGPROF = 27; | |
| 107 | pub const SIGWINCH = 28; | |
| 108 | pub const SIGIO = 29; | |
| 109 | pub const SIGPOLL = 29; | |
| 110 | pub const SIGPWR = 30; | |
| 111 | pub const SIGSYS = 31; | |
| 105 | pub const SIGPROF = 27; | |
| 106 | pub const SIGWINCH = 28; | |
| 107 | pub const SIGIO = 29; | |
| 108 | pub const SIGPOLL = 29; | |
| 109 | pub const SIGPWR = 30; | |
| 110 | pub const SIGSYS = 31; | |
| 112 | 111 | pub const SIGUNUSED = SIGSYS; |
| 113 | 112 | |
| 114 | 113 | pub const O_RDONLY = 0o0; |
| 115 | 114 | pub const O_WRONLY = 0o1; |
| 116 | pub const O_RDWR = 0o2; | |
| 115 | pub const O_RDWR = 0o2; | |
| 117 | 116 | |
| 118 | 117 | pub const SEEK_SET = 0; |
| 119 | 118 | pub const SEEK_CUR = 1; |
| 120 | 119 | pub const SEEK_END = 2; |
| 121 | 120 | |
| 122 | pub const SIG_BLOCK = 0; | |
| 121 | pub const SIG_BLOCK = 0; | |
| 123 | 122 | pub const SIG_UNBLOCK = 1; |
| 124 | 123 | pub const SIG_SETMASK = 2; |
| 125 | 124 | |
| ... | ... | @@ -408,7 +407,6 @@ pub const DT_LNK = 10; |
| 408 | 407 | pub const DT_SOCK = 12; |
| 409 | 408 | pub const DT_WHT = 14; |
| 410 | 409 | |
| 411 | ||
| 412 | 410 | pub const TCGETS = 0x5401; |
| 413 | 411 | pub const TCSETS = 0x5402; |
| 414 | 412 | pub const TCSETSW = 0x5403; |
| ... | ... | @@ -539,23 +537,23 @@ pub const MS_BIND = 4096; |
| 539 | 537 | pub const MS_MOVE = 8192; |
| 540 | 538 | pub const MS_REC = 16384; |
| 541 | 539 | pub const MS_SILENT = 32768; |
| 542 | pub const MS_POSIXACL = (1<<16); | |
| 543 | pub const MS_UNBINDABLE = (1<<17); | |
| 544 | pub const MS_PRIVATE = (1<<18); | |
| 545 | pub const MS_SLAVE = (1<<19); | |
| 546 | pub const MS_SHARED = (1<<20); | |
| 547 | pub const MS_RELATIME = (1<<21); | |
| 548 | pub const MS_KERNMOUNT = (1<<22); | |
| 549 | pub const MS_I_VERSION = (1<<23); | |
| 550 | pub const MS_STRICTATIME = (1<<24); | |
| 551 | pub const MS_LAZYTIME = (1<<25); | |
| 552 | pub const MS_NOREMOTELOCK = (1<<27); | |
| 553 | pub const MS_NOSEC = (1<<28); | |
| 554 | pub const MS_BORN = (1<<29); | |
| 555 | pub const MS_ACTIVE = (1<<30); | |
| 556 | pub const MS_NOUSER = (1<<31); | |
| 557 | ||
| 558 | pub const MS_RMT_MASK = (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|MS_LAZYTIME); | |
| 540 | pub const MS_POSIXACL = (1 << 16); | |
| 541 | pub const MS_UNBINDABLE = (1 << 17); | |
| 542 | pub const MS_PRIVATE = (1 << 18); | |
| 543 | pub const MS_SLAVE = (1 << 19); | |
| 544 | pub const MS_SHARED = (1 << 20); | |
| 545 | pub const MS_RELATIME = (1 << 21); | |
| 546 | pub const MS_KERNMOUNT = (1 << 22); | |
| 547 | pub const MS_I_VERSION = (1 << 23); | |
| 548 | pub const MS_STRICTATIME = (1 << 24); | |
| 549 | pub const MS_LAZYTIME = (1 << 25); | |
| 550 | pub const MS_NOREMOTELOCK = (1 << 27); | |
| 551 | pub const MS_NOSEC = (1 << 28); | |
| 552 | pub const MS_BORN = (1 << 29); | |
| 553 | pub const MS_ACTIVE = (1 << 30); | |
| 554 | pub const MS_NOUSER = (1 << 31); | |
| 555 | ||
| 556 | pub const MS_RMT_MASK = (MS_RDONLY | MS_SYNCHRONOUS | MS_MANDLOCK | MS_I_VERSION | MS_LAZYTIME); | |
| 559 | 557 | |
| 560 | 558 | pub const MS_MGC_VAL = 0xc0ed0000; |
| 561 | 559 | pub const MS_MGC_MSK = 0xffff0000; |
| ... | ... | @@ -565,7 +563,6 @@ pub const MNT_DETACH = 2; |
| 565 | 563 | pub const MNT_EXPIRE = 4; |
| 566 | 564 | pub const UMOUNT_NOFOLLOW = 8; |
| 567 | 565 | |
| 568 | ||
| 569 | 566 | pub const S_IFMT = 0o170000; |
| 570 | 567 | |
| 571 | 568 | pub const S_IFDIR = 0o040000; |
| ... | ... | @@ -626,15 +623,30 @@ pub const TFD_CLOEXEC = O_CLOEXEC; |
| 626 | 623 | pub const TFD_TIMER_ABSTIME = 1; |
| 627 | 624 | pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1); |
| 628 | 625 | |
| 629 | fn unsigned(s: i32) u32 { return @bitCast(u32, s); } | |
| 630 | fn signed(s: u32) i32 { return @bitCast(i32, s); } | |
| 631 | pub fn WEXITSTATUS(s: i32) i32 { return signed((unsigned(s) & 0xff00) >> 8); } | |
| 632 | pub fn WTERMSIG(s: i32) i32 { return signed(unsigned(s) & 0x7f); } | |
| 633 | pub fn WSTOPSIG(s: i32) i32 { return WEXITSTATUS(s); } | |
| 634 | pub fn WIFEXITED(s: i32) bool { return WTERMSIG(s) == 0; } | |
| 635 | pub fn WIFSTOPPED(s: i32) bool { return (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00; } | |
| 636 | pub fn WIFSIGNALED(s: i32) bool { return (unsigned(s)&0xffff)-%1 < 0xff; } | |
| 637 | ||
| 626 | fn unsigned(s: i32) u32 { | |
| 627 | return @bitCast(u32, s); | |
| 628 | } | |
| 629 | fn signed(s: u32) i32 { | |
| 630 | return @bitCast(i32, s); | |
| 631 | } | |
| 632 | pub fn WEXITSTATUS(s: i32) i32 { | |
| 633 | return signed((unsigned(s) & 0xff00) >> 8); | |
| 634 | } | |
| 635 | pub fn WTERMSIG(s: i32) i32 { | |
| 636 | return signed(unsigned(s) & 0x7f); | |
| 637 | } | |
| 638 | pub fn WSTOPSIG(s: i32) i32 { | |
| 639 | return WEXITSTATUS(s); | |
| 640 | } | |
| 641 | pub fn WIFEXITED(s: i32) bool { | |
| 642 | return WTERMSIG(s) == 0; | |
| 643 | } | |
| 644 | pub fn WIFSTOPPED(s: i32) bool { | |
| 645 | return (u16)(((unsigned(s) & 0xffff) *% 0x10001) >> 8) > 0x7f00; | |
| 646 | } | |
| 647 | pub fn WIFSIGNALED(s: i32) bool { | |
| 648 | return (unsigned(s) & 0xffff) -% 1 < 0xff; | |
| 649 | } | |
| 638 | 650 | |
| 639 | 651 | pub const winsize = extern struct { |
| 640 | 652 | ws_row: u16, |
| ... | ... | @@ -707,8 +719,7 @@ pub fn umount2(special: &const u8, flags: u32) usize { |
| 707 | 719 | } |
| 708 | 720 | |
| 709 | 721 | pub 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)); | |
| 712 | 723 | } |
| 713 | 724 | |
| 714 | 725 | pub fn munmap(address: usize, length: usize) usize { |
| ... | ... | @@ -812,7 +823,8 @@ pub fn clock_gettime(clk_id: i32, tp: &timespec) usize { |
| 812 | 823 | if (@ptrToInt(f) != 0) { |
| 813 | 824 | const rc = f(clk_id, tp); |
| 814 | 825 | switch (rc) { |
| 815 | 0, @bitCast(usize, isize(-EINVAL)) => return rc, | |
| 826 | 0, | |
| 827 | @bitCast(usize, isize(-EINVAL)) => return rc, | |
| 816 | 828 | else => {}, |
| 817 | 829 | } |
| 818 | 830 | } |
| ... | ... | @@ -823,8 +835,7 @@ var vdso_clock_gettime = init_vdso_clock_gettime; |
| 823 | 835 | extern fn init_vdso_clock_gettime(clk: i32, ts: &timespec) usize { |
| 824 | 836 | const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM); |
| 825 | 837 | 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); | |
| 828 | 839 | if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS)); |
| 829 | 840 | return f(clk, ts); |
| 830 | 841 | } |
| ... | ... | @@ -918,18 +929,18 @@ pub fn getpid() i32 { |
| 918 | 929 | } |
| 919 | 930 | |
| 920 | 931 | pub 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); | |
| 922 | 933 | } |
| 923 | 934 | |
| 924 | 935 | pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize { |
| 925 | 936 | assert(sig >= 1); |
| 926 | 937 | assert(sig != SIGKILL); |
| 927 | 938 | assert(sig != SIGSTOP); |
| 928 | var ksa = k_sigaction { | |
| 939 | var ksa = k_sigaction{ | |
| 929 | 940 | .handler = act.handler, |
| 930 | 941 | .flags = act.flags | SA_RESTORER, |
| 931 | 942 | .mask = undefined, |
| 932 | .restorer = @ptrCast(extern fn()void, restore_rt), | |
| 943 | .restorer = @ptrCast(extern fn() void, restore_rt), | |
| 933 | 944 | }; |
| 934 | 945 | var ksa_old: k_sigaction = undefined; |
| 935 | 946 | @memcpy(@ptrCast(&u8, &ksa.mask), @ptrCast(&const u8, &act.mask), 8); |
| ... | ... | @@ -952,22 +963,22 @@ const all_mask = []usize{@maxValue(usize)}; |
| 952 | 963 | const app_mask = []usize{0xfffffffc7fffffff}; |
| 953 | 964 | |
| 954 | 965 | const k_sigaction = extern struct { |
| 955 | handler: extern fn(i32)void, | |
| 966 | handler: extern fn(i32) void, | |
| 956 | 967 | flags: usize, |
| 957 | restorer: extern fn()void, | |
| 968 | restorer: extern fn() void, | |
| 958 | 969 | mask: [2]u32, |
| 959 | 970 | }; |
| 960 | 971 | |
| 961 | 972 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 962 | 973 | pub const Sigaction = struct { |
| 963 | handler: extern fn(i32)void, | |
| 974 | handler: extern fn(i32) void, | |
| 964 | 975 | mask: sigset_t, |
| 965 | 976 | flags: u32, |
| 966 | 977 | }; |
| 967 | 978 | |
| 968 | pub const SIG_ERR = @intToPtr(extern fn(i32)void, @maxValue(usize)); | |
| 969 | pub const SIG_DFL = @intToPtr(extern fn(i32)void, 0); | |
| 970 | pub const SIG_IGN = @intToPtr(extern fn(i32)void, 1); | |
| 979 | pub const SIG_ERR = @intToPtr(extern fn(i32) void, @maxValue(usize)); | |
| 980 | pub const SIG_DFL = @intToPtr(extern fn(i32) void, 0); | |
| 981 | pub const SIG_IGN = @intToPtr(extern fn(i32) void, 1); | |
| 971 | 982 | pub const empty_sigset = []usize{0} ** sigset_t.len; |
| 972 | 983 | |
| 973 | 984 | pub fn raise(sig: i32) usize { |
| ... | ... | @@ -980,25 +991,25 @@ pub fn raise(sig: i32) usize { |
| 980 | 991 | } |
| 981 | 992 | |
| 982 | 993 | fn 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); | |
| 984 | 995 | } |
| 985 | 996 | |
| 986 | 997 | fn 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); | |
| 988 | 999 | } |
| 989 | 1000 | |
| 990 | 1001 | fn 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); | |
| 992 | 1003 | } |
| 993 | 1004 | |
| 994 | 1005 | pub fn sigaddset(set: &sigset_t, sig: u6) void { |
| 995 | 1006 | 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)); | |
| 997 | 1008 | } |
| 998 | 1009 | |
| 999 | 1010 | pub fn sigismember(set: &const sigset_t, sig: u6) bool { |
| 1000 | 1011 | 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; | |
| 1002 | 1013 | } |
| 1003 | 1014 | |
| 1004 | 1015 | pub const in_port_t = u16; |
| ... | ... | @@ -1062,9 +1073,7 @@ pub fn recvmsg(fd: i32, msg: &msghdr, flags: u32) usize { |
| 1062 | 1073 | return syscall3(SYS_recvmsg, usize(fd), @ptrToInt(msg), flags); |
| 1063 | 1074 | } |
| 1064 | 1075 | |
| 1065 | pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, | |
| 1066 | noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize | |
| 1067 | { | |
| 1076 | pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize { | |
| 1068 | 1077 | return syscall6(SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); |
| 1069 | 1078 | } |
| 1070 | 1079 | |
| ... | ... | @@ -1132,25 +1141,16 @@ pub fn fgetxattr(fd: usize, name: &const u8, value: &void, size: usize) usize { |
| 1132 | 1141 | return syscall4(SYS_lgetxattr, fd, @ptrToInt(name), @ptrToInt(value), size); |
| 1133 | 1142 | } |
| 1134 | 1143 | |
| 1135 | pub 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); | |
| 1144 | pub 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); | |
| 1140 | 1146 | } |
| 1141 | 1147 | |
| 1142 | pub 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); | |
| 1148 | pub 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); | |
| 1147 | 1150 | } |
| 1148 | 1151 | |
| 1149 | pub 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); | |
| 1152 | pub 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); | |
| 1154 | 1154 | } |
| 1155 | 1155 | |
| 1156 | 1156 | pub fn removexattr(path: &const u8, name: &const u8) usize { |
| ... | ... | @@ -1199,7 +1199,7 @@ pub fn timerfd_create(clockid: i32, flags: u32) usize { |
| 1199 | 1199 | |
| 1200 | 1200 | pub const itimerspec = extern struct { |
| 1201 | 1201 | it_interval: timespec, |
| 1202 | it_value: timespec | |
| 1202 | it_value: timespec, | |
| 1203 | 1203 | }; |
| 1204 | 1204 | |
| 1205 | 1205 | pub 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 |
| 1211 | 1211 | } |
| 1212 | 1212 | |
| 1213 | 1213 | pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330; |
| 1214 | pub const _LINUX_CAPABILITY_U32S_1 = 1; | |
| 1214 | pub const _LINUX_CAPABILITY_U32S_1 = 1; | |
| 1215 | 1215 | |
| 1216 | 1216 | pub const _LINUX_CAPABILITY_VERSION_2 = 0x20071026; |
| 1217 | pub const _LINUX_CAPABILITY_U32S_2 = 2; | |
| 1217 | pub const _LINUX_CAPABILITY_U32S_2 = 2; | |
| 1218 | 1218 | |
| 1219 | 1219 | pub const _LINUX_CAPABILITY_VERSION_3 = 0x20080522; |
| 1220 | pub const _LINUX_CAPABILITY_U32S_3 = 2; | |
| 1220 | pub const _LINUX_CAPABILITY_U32S_3 = 2; | |
| 1221 | 1221 | |
| 1222 | pub const VFS_CAP_REVISION_MASK = 0xFF000000; | |
| 1223 | pub const VFS_CAP_REVISION_SHIFT = 24; | |
| 1224 | pub const VFS_CAP_FLAGS_MASK = ~VFS_CAP_REVISION_MASK; | |
| 1222 | pub const VFS_CAP_REVISION_MASK = 0xFF000000; | |
| 1223 | pub const VFS_CAP_REVISION_SHIFT = 24; | |
| 1224 | pub const VFS_CAP_FLAGS_MASK = ~VFS_CAP_REVISION_MASK; | |
| 1225 | 1225 | pub const VFS_CAP_FLAGS_EFFECTIVE = 0x000001; |
| 1226 | 1226 | |
| 1227 | 1227 | pub const VFS_CAP_REVISION_1 = 0x01000000; |
| 1228 | pub const VFS_CAP_U32_1 = 1; | |
| 1229 | pub const XATTR_CAPS_SZ_1 = @sizeOf(u32)*(1 + 2*VFS_CAP_U32_1); | |
| 1228 | pub const VFS_CAP_U32_1 = 1; | |
| 1229 | pub const XATTR_CAPS_SZ_1 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_1); | |
| 1230 | 1230 | |
| 1231 | 1231 | pub const VFS_CAP_REVISION_2 = 0x02000000; |
| 1232 | pub const VFS_CAP_U32_2 = 2; | |
| 1233 | pub const XATTR_CAPS_SZ_2 = @sizeOf(u32)*(1 + 2*VFS_CAP_U32_2); | |
| 1232 | pub const VFS_CAP_U32_2 = 2; | |
| 1233 | pub const XATTR_CAPS_SZ_2 = @sizeOf(u32) * (1 + 2 * VFS_CAP_U32_2); | |
| 1234 | 1234 | |
| 1235 | pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2; | |
| 1236 | pub const VFS_CAP_U32 = VFS_CAP_U32_2; | |
| 1237 | pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2; | |
| 1235 | pub const XATTR_CAPS_SZ = XATTR_CAPS_SZ_2; | |
| 1236 | pub const VFS_CAP_U32 = VFS_CAP_U32_2; | |
| 1237 | pub const VFS_CAP_REVISION = VFS_CAP_REVISION_2; | |
| 1238 | 1238 | |
| 1239 | 1239 | pub const vfs_cap_data = extern struct { |
| 1240 | 1240 | //all of these are mandated as little endian |
| ... | ... | @@ -1245,49 +1245,48 @@ pub const vfs_cap_data = extern struct { |
| 1245 | 1245 | }; |
| 1246 | 1246 | |
| 1247 | 1247 | magic_etc: u32, |
| 1248 | data: [VFS_CAP_U32]Data, | |
| 1248 | data: [VFS_CAP_U32]Data, | |
| 1249 | 1249 | }; |
| 1250 | 1250 | |
| 1251 | ||
| 1252 | pub const CAP_CHOWN = 0; | |
| 1253 | pub const CAP_DAC_OVERRIDE = 1; | |
| 1254 | pub const CAP_DAC_READ_SEARCH = 2; | |
| 1255 | pub const CAP_FOWNER = 3; | |
| 1256 | pub const CAP_FSETID = 4; | |
| 1257 | pub const CAP_KILL = 5; | |
| 1258 | pub const CAP_SETGID = 6; | |
| 1259 | pub const CAP_SETUID = 7; | |
| 1260 | pub const CAP_SETPCAP = 8; | |
| 1261 | pub const CAP_LINUX_IMMUTABLE = 9; | |
| 1262 | pub const CAP_NET_BIND_SERVICE = 10; | |
| 1263 | pub const CAP_NET_BROADCAST = 11; | |
| 1264 | pub const CAP_NET_ADMIN = 12; | |
| 1265 | pub const CAP_NET_RAW = 13; | |
| 1266 | pub const CAP_IPC_LOCK = 14; | |
| 1267 | pub const CAP_IPC_OWNER = 15; | |
| 1268 | pub const CAP_SYS_MODULE = 16; | |
| 1269 | pub const CAP_SYS_RAWIO = 17; | |
| 1270 | pub const CAP_SYS_CHROOT = 18; | |
| 1271 | pub const CAP_SYS_PTRACE = 19; | |
| 1272 | pub const CAP_SYS_PACCT = 20; | |
| 1273 | pub const CAP_SYS_ADMIN = 21; | |
| 1274 | pub const CAP_SYS_BOOT = 22; | |
| 1275 | pub const CAP_SYS_NICE = 23; | |
| 1276 | pub const CAP_SYS_RESOURCE = 24; | |
| 1277 | pub const CAP_SYS_TIME = 25; | |
| 1278 | pub const CAP_SYS_TTY_CONFIG = 26; | |
| 1279 | pub const CAP_MKNOD = 27; | |
| 1280 | pub const CAP_LEASE = 28; | |
| 1281 | pub const CAP_AUDIT_WRITE = 29; | |
| 1282 | pub const CAP_AUDIT_CONTROL = 30; | |
| 1283 | pub const CAP_SETFCAP = 31; | |
| 1284 | pub const CAP_MAC_OVERRIDE = 32; | |
| 1285 | pub const CAP_MAC_ADMIN = 33; | |
| 1286 | pub const CAP_SYSLOG = 34; | |
| 1287 | pub const CAP_WAKE_ALARM = 35; | |
| 1288 | pub const CAP_BLOCK_SUSPEND = 36; | |
| 1289 | pub const CAP_AUDIT_READ = 37; | |
| 1290 | pub const CAP_LAST_CAP = CAP_AUDIT_READ; | |
| 1251 | pub const CAP_CHOWN = 0; | |
| 1252 | pub const CAP_DAC_OVERRIDE = 1; | |
| 1253 | pub const CAP_DAC_READ_SEARCH = 2; | |
| 1254 | pub const CAP_FOWNER = 3; | |
| 1255 | pub const CAP_FSETID = 4; | |
| 1256 | pub const CAP_KILL = 5; | |
| 1257 | pub const CAP_SETGID = 6; | |
| 1258 | pub const CAP_SETUID = 7; | |
| 1259 | pub const CAP_SETPCAP = 8; | |
| 1260 | pub const CAP_LINUX_IMMUTABLE = 9; | |
| 1261 | pub const CAP_NET_BIND_SERVICE = 10; | |
| 1262 | pub const CAP_NET_BROADCAST = 11; | |
| 1263 | pub const CAP_NET_ADMIN = 12; | |
| 1264 | pub const CAP_NET_RAW = 13; | |
| 1265 | pub const CAP_IPC_LOCK = 14; | |
| 1266 | pub const CAP_IPC_OWNER = 15; | |
| 1267 | pub const CAP_SYS_MODULE = 16; | |
| 1268 | pub const CAP_SYS_RAWIO = 17; | |
| 1269 | pub const CAP_SYS_CHROOT = 18; | |
| 1270 | pub const CAP_SYS_PTRACE = 19; | |
| 1271 | pub const CAP_SYS_PACCT = 20; | |
| 1272 | pub const CAP_SYS_ADMIN = 21; | |
| 1273 | pub const CAP_SYS_BOOT = 22; | |
| 1274 | pub const CAP_SYS_NICE = 23; | |
| 1275 | pub const CAP_SYS_RESOURCE = 24; | |
| 1276 | pub const CAP_SYS_TIME = 25; | |
| 1277 | pub const CAP_SYS_TTY_CONFIG = 26; | |
| 1278 | pub const CAP_MKNOD = 27; | |
| 1279 | pub const CAP_LEASE = 28; | |
| 1280 | pub const CAP_AUDIT_WRITE = 29; | |
| 1281 | pub const CAP_AUDIT_CONTROL = 30; | |
| 1282 | pub const CAP_SETFCAP = 31; | |
| 1283 | pub const CAP_MAC_OVERRIDE = 32; | |
| 1284 | pub const CAP_MAC_ADMIN = 33; | |
| 1285 | pub const CAP_SYSLOG = 34; | |
| 1286 | pub const CAP_WAKE_ALARM = 35; | |
| 1287 | pub const CAP_BLOCK_SUSPEND = 36; | |
| 1288 | pub const CAP_AUDIT_READ = 37; | |
| 1289 | pub const CAP_LAST_CAP = CAP_AUDIT_READ; | |
| 1291 | 1290 | |
| 1292 | 1291 | pub fn cap_valid(u8: x) bool { |
| 1293 | 1292 | return x >= 0 and x <= CAP_LAST_CAP; |
std/segmented_list.zig+30-24| ... | ... | @@ -95,7 +95,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 95 | 95 | |
| 96 | 96 | /// Deinitialize with `deinit` |
| 97 | 97 | pub fn init(allocator: &Allocator) Self { |
| 98 | return Self { | |
| 98 | return Self{ | |
| 99 | 99 | .allocator = allocator, |
| 100 | 100 | .len = 0, |
| 101 | 101 | .prealloc_segment = undefined, |
| ... | ... | @@ -106,7 +106,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 106 | 106 | pub fn deinit(self: &Self) void { |
| 107 | 107 | self.freeShelves(ShelfIndex(self.dynamic_segments.len), 0); |
| 108 | 108 | self.allocator.free(self.dynamic_segments); |
| 109 | *self = undefined; | |
| 109 | self.* = undefined; | |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | pub fn at(self: &Self, i: usize) &T { |
| ... | ... | @@ -120,7 +120,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 120 | 120 | |
| 121 | 121 | pub fn push(self: &Self, item: &const T) !void { |
| 122 | 122 | const new_item_ptr = try self.addOne(); |
| 123 | *new_item_ptr = *item; | |
| 123 | new_item_ptr.* = item.*; | |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | 126 | 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 |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | pub fn pop(self: &Self) ?T { |
| 133 | if (self.len == 0) | |
| 134 | return null; | |
| 133 | if (self.len == 0) return null; | |
| 135 | 134 | |
| 136 | 135 | const index = self.len - 1; |
| 137 | const result = *self.uncheckedAt(index); | |
| 136 | const result = self.uncheckedAt(index).*; | |
| 138 | 137 | self.len = index; |
| 139 | 138 | return result; |
| 140 | 139 | } |
| ... | ... | @@ -247,8 +246,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 247 | 246 | shelf_size: usize, |
| 248 | 247 | |
| 249 | 248 | 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; | |
| 252 | 250 | if (it.index < prealloc_item_count) { |
| 253 | 251 | const ptr = &it.list.prealloc_segment[it.index]; |
| 254 | 252 | it.index += 1; |
| ... | ... | @@ -272,12 +270,10 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 272 | 270 | } |
| 273 | 271 | |
| 274 | 272 | pub fn prev(it: &Iterator) ?&T { |
| 275 | if (it.index == 0) | |
| 276 | return null; | |
| 273 | if (it.index == 0) return null; | |
| 277 | 274 | |
| 278 | 275 | 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]; | |
| 281 | 277 | |
| 282 | 278 | if (it.box_index == 0) { |
| 283 | 279 | it.shelf_index -= 1; |
| ... | ... | @@ -309,7 +305,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 309 | 305 | }; |
| 310 | 306 | |
| 311 | 307 | pub fn iterator(self: &Self, start_index: usize) Iterator { |
| 312 | var it = Iterator { | |
| 308 | var it = Iterator{ | |
| 313 | 309 | .list = self, |
| 314 | 310 | .index = undefined, |
| 315 | 311 | .shelf_index = undefined, |
| ... | ... | @@ -339,25 +335,31 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void { |
| 339 | 335 | var list = SegmentedList(i32, prealloc).init(allocator); |
| 340 | 336 | defer list.deinit(); |
| 341 | 337 | |
| 342 | {var i: usize = 0; while (i < 100) : (i += 1) { | |
| 343 | try list.push(i32(i + 1)); | |
| 344 | assert(list.len == i + 1); | |
| 345 | }} | |
| 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 | } | |
| 346 | 345 | |
| 347 | {var i: usize = 0; while (i < 100) : (i += 1) { | |
| 348 | assert(*list.at(i) == i32(i + 1)); | |
| 349 | }} | |
| 346 | { | |
| 347 | var i: usize = 0; | |
| 348 | while (i < 100) : (i += 1) { | |
| 349 | assert(list.at(i).* == i32(i + 1)); | |
| 350 | } | |
| 351 | } | |
| 350 | 352 | |
| 351 | 353 | { |
| 352 | 354 | var it = list.iterator(0); |
| 353 | 355 | var x: i32 = 0; |
| 354 | 356 | while (it.next()) |item| { |
| 355 | 357 | x += 1; |
| 356 | assert(*item == x); | |
| 358 | assert(item.* == x); | |
| 357 | 359 | } |
| 358 | 360 | assert(x == 100); |
| 359 | 361 | while (it.prev()) |item| : (x -= 1) { |
| 360 | assert(*item == x); | |
| 362 | assert(item.* == x); | |
| 361 | 363 | } |
| 362 | 364 | assert(x == 0); |
| 363 | 365 | } |
| ... | ... | @@ -365,14 +367,18 @@ fn testSegmentedList(comptime prealloc: usize, allocator: &Allocator) !void { |
| 365 | 367 | assert(??list.pop() == 100); |
| 366 | 368 | assert(list.len == 99); |
| 367 | 369 | |
| 368 | try list.pushMany([]i32 { 1, 2, 3 }); | |
| 370 | try list.pushMany([]i32{ | |
| 371 | 1, | |
| 372 | 2, | |
| 373 | 3, | |
| 374 | }); | |
| 369 | 375 | assert(list.len == 102); |
| 370 | 376 | assert(??list.pop() == 3); |
| 371 | 377 | assert(??list.pop() == 2); |
| 372 | 378 | assert(??list.pop() == 1); |
| 373 | 379 | assert(list.len == 99); |
| 374 | 380 | |
| 375 | try list.pushMany([]const i32 {}); | |
| 381 | try list.pushMany([]const i32{}); | |
| 376 | 382 | assert(list.len == 99); |
| 377 | 383 | |
| 378 | 384 | var i: i32 = 99; |
std/sort.zig+398-164| ... | ... | @@ -5,15 +5,18 @@ const math = std.math; |
| 5 | 5 | const builtin = @import("builtin"); |
| 6 | 6 | |
| 7 | 7 | /// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required). |
| 8 | pub 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]; | |
| 8 | pub 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; | |
| 14 | 18 | } |
| 15 | items[j] = x; | |
| 16 | }} | |
| 19 | } | |
| 17 | 20 | } |
| 18 | 21 | |
| 19 | 22 | const Range = struct { |
| ... | ... | @@ -21,7 +24,10 @@ const Range = struct { |
| 21 | 24 | end: usize, |
| 22 | 25 | |
| 23 | 26 | fn init(start: usize, end: usize) Range { |
| 24 | return Range { .start = start, .end = end }; | |
| 27 | return Range{ | |
| 28 | .start = start, | |
| 29 | .end = end, | |
| 30 | }; | |
| 25 | 31 | } |
| 26 | 32 | |
| 27 | 33 | fn length(self: &const Range) usize { |
| ... | ... | @@ -29,7 +35,6 @@ const Range = struct { |
| 29 | 35 | } |
| 30 | 36 | }; |
| 31 | 37 | |
| 32 | ||
| 33 | 38 | const Iterator = struct { |
| 34 | 39 | size: usize, |
| 35 | 40 | power_of_two: usize, |
| ... | ... | @@ -42,7 +47,7 @@ const Iterator = struct { |
| 42 | 47 | fn init(size2: usize, min_level: usize) Iterator { |
| 43 | 48 | const power_of_two = math.floorPowerOfTwo(usize, size2); |
| 44 | 49 | const denominator = power_of_two / min_level; |
| 45 | return Iterator { | |
| 50 | return Iterator{ | |
| 46 | 51 | .numerator = 0, |
| 47 | 52 | .decimal = 0, |
| 48 | 53 | .size = size2, |
| ... | ... | @@ -68,7 +73,10 @@ const Iterator = struct { |
| 68 | 73 | self.decimal += 1; |
| 69 | 74 | } |
| 70 | 75 | |
| 71 | return Range {.start = start, .end = self.decimal}; | |
| 76 | return Range{ | |
| 77 | .start = start, | |
| 78 | .end = self.decimal, | |
| 79 | }; | |
| 72 | 80 | } |
| 73 | 81 | |
| 74 | 82 | fn finished(self: &Iterator) bool { |
| ... | ... | @@ -100,7 +108,7 @@ const Pull = struct { |
| 100 | 108 | |
| 101 | 109 | /// Stable in-place sort. O(n) best case, O(n*log(n)) worst case and average case. O(1) memory (no allocator required). |
| 102 | 110 | /// Currently implemented as block sort. |
| 103 | pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { | |
| 111 | pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) void { | |
| 104 | 112 | // Implementation ported from https://github.com/BonzaiThePenguin/WikiSort/blob/master/WikiSort.c |
| 105 | 113 | var cache: [512]T = undefined; |
| 106 | 114 | |
| ... | ... | @@ -123,7 +131,16 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 123 | 131 | // http://pages.ripco.net/~jgamble/nw.html |
| 124 | 132 | var iterator = Iterator.init(items.len, 4); |
| 125 | 133 | 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 | }; | |
| 127 | 144 | const range = iterator.nextRange(); |
| 128 | 145 | |
| 129 | 146 | 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 |
| 149 | 166 | swap(T, sliced_items, lessThan, &order, 3, 5); |
| 150 | 167 | swap(T, sliced_items, lessThan, &order, 3, 4); |
| 151 | 168 | }, |
| 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 | }, | |
| 202 | 219 | else => {}, |
| 203 | 220 | } |
| 204 | 221 | } |
| ... | ... | @@ -273,7 +290,6 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 273 | 290 | // we merged two levels at the same time, so we're done with this level already |
| 274 | 291 | // (iterator.nextLevel() is called again at the bottom of this outer merge loop) |
| 275 | 292 | _ = iterator.nextLevel(); |
| 276 | ||
| 277 | 293 | } else { |
| 278 | 294 | iterator.begin(); |
| 279 | 295 | while (!iterator.finished()) { |
| ... | ... | @@ -303,7 +319,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 303 | 319 | // 8. redistribute the two internal buffers back into the items |
| 304 | 320 | |
| 305 | 321 | 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; | |
| 307 | 323 | |
| 308 | 324 | // as an optimization, we really only need to pull out the internal buffers once for each level of merges |
| 309 | 325 | // 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 |
| 316 | 332 | var start: usize = 0; |
| 317 | 333 | var pull_index: usize = 0; |
| 318 | 334 | 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 | }, | |
| 321 | 347 | }; |
| 322 | 348 | |
| 323 | 349 | 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 |
| 355 | 381 | // these values will be pulled out to the start of A |
| 356 | 382 | last = A.start; |
| 357 | 383 | count = 1; |
| 358 | while (count < find) : ({last = index; count += 1;}) { | |
| 384 | while (count < find) : ({ | |
| 385 | last = index; | |
| 386 | count += 1; | |
| 387 | }) { | |
| 359 | 388 | index = findLastForward(T, items, items[last], Range.init(last + 1, A.end), lessThan, find - count); |
| 360 | 389 | if (index == A.end) break; |
| 361 | 390 | } |
| ... | ... | @@ -363,7 +392,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 363 | 392 | |
| 364 | 393 | if (count >= buffer_size) { |
| 365 | 394 | // 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{ | |
| 367 | 396 | .range = Range.init(A.start, B.end), |
| 368 | 397 | .count = count, |
| 369 | 398 | .from = index, |
| ... | ... | @@ -398,7 +427,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 398 | 427 | } else if (pull_index == 0 and count > buffer1.length()) { |
| 399 | 428 | // keep track of the largest buffer we were able to find |
| 400 | 429 | buffer1 = Range.init(A.start, A.start + count); |
| 401 | pull[pull_index] = Pull { | |
| 430 | pull[pull_index] = Pull{ | |
| 402 | 431 | .range = Range.init(A.start, B.end), |
| 403 | 432 | .count = count, |
| 404 | 433 | .from = index, |
| ... | ... | @@ -410,7 +439,10 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 410 | 439 | // these values will be pulled out to the end of B |
| 411 | 440 | last = B.end - 1; |
| 412 | 441 | count = 1; |
| 413 | while (count < find) : ({last = index - 1; count += 1;}) { | |
| 442 | while (count < find) : ({ | |
| 443 | last = index - 1; | |
| 444 | count += 1; | |
| 445 | }) { | |
| 414 | 446 | index = findFirstBackward(T, items, items[last], Range.init(B.start, last), lessThan, find - count); |
| 415 | 447 | if (index == B.start) break; |
| 416 | 448 | } |
| ... | ... | @@ -418,7 +450,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 418 | 450 | |
| 419 | 451 | if (count >= buffer_size) { |
| 420 | 452 | // 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{ | |
| 422 | 454 | .range = Range.init(A.start, B.end), |
| 423 | 455 | .count = count, |
| 424 | 456 | .from = index, |
| ... | ... | @@ -457,7 +489,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 457 | 489 | } else if (pull_index == 0 and count > buffer1.length()) { |
| 458 | 490 | // keep track of the largest buffer we were able to find |
| 459 | 491 | buffer1 = Range.init(B.end - count, B.end); |
| 460 | pull[pull_index] = Pull { | |
| 492 | pull[pull_index] = Pull{ | |
| 461 | 493 | .range = Range.init(A.start, B.end), |
| 462 | 494 | .count = count, |
| 463 | 495 | .from = index, |
| ... | ... | @@ -496,7 +528,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 496 | 528 | |
| 497 | 529 | // adjust block_size and buffer_size based on the values we were able to pull out |
| 498 | 530 | buffer_size = buffer1.length(); |
| 499 | block_size = iterator.length()/buffer_size + 1; | |
| 531 | block_size = iterator.length() / buffer_size + 1; | |
| 500 | 532 | |
| 501 | 533 | // the first buffer NEEDS to be large enough to tag each of the evenly sized A blocks, |
| 502 | 534 | // 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 |
| 547 | 579 | // swap the first value of each A block with the value in buffer1 |
| 548 | 580 | var indexA = buffer1.start; |
| 549 | 581 | 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 | }) { | |
| 551 | 586 | mem.swap(T, &items[indexA], &items[index]); |
| 552 | 587 | } |
| 553 | 588 | |
| ... | ... | @@ -626,9 +661,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 626 | 661 | |
| 627 | 662 | // if there are no more A blocks remaining, this step is finished! |
| 628 | 663 | blockA.start += block_size; |
| 629 | if (blockA.length() == 0) | |
| 630 | break; | |
| 631 | ||
| 664 | if (blockA.length() == 0) break; | |
| 632 | 665 | } else if (blockB.length() < block_size) { |
| 633 | 666 | // move the last B block, which is unevenly sized, to before the remaining A blocks, by using a rotation |
| 634 | 667 | // 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 |
| 709 | 742 | } |
| 710 | 743 | |
| 711 | 744 | // merge operation without a buffer |
| 712 | fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)bool) void { | |
| 745 | fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T, &const T) bool) void { | |
| 713 | 746 | if (A_arg.length() == 0 or B_arg.length() == 0) return; |
| 714 | 747 | |
| 715 | 748 | // 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 |
| 730 | 763 | // again, this is NOT a general-purpose solution – it only works well in this case! |
| 731 | 764 | // kind of like how the O(n^2) insertion sort is used in some places |
| 732 | 765 | |
| 733 | var A = *A_arg; | |
| 734 | var B = *B_arg; | |
| 766 | var A = A_arg.*; | |
| 767 | var B = B_arg.*; | |
| 735 | 768 | |
| 736 | 769 | while (true) { |
| 737 | 770 | // 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 |
| 751 | 784 | } |
| 752 | 785 | |
| 753 | 786 | // merge operation using an internal buffer |
| 754 | fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, buffer: &const Range) void { | |
| 787 | fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, buffer: &const Range) void { | |
| 755 | 788 | // whenever we find a value to add to the final array, swap it with the value that's already in that spot |
| 756 | 789 | // when this algorithm is finished, 'buffer' will contain its original contents, but in a different order |
| 757 | 790 | var A_count: usize = 0; |
| ... | ... | @@ -787,9 +820,9 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s |
| 787 | 820 | |
| 788 | 821 | // combine a linear search with a binary search to reduce the number of comparisons in situations |
| 789 | 822 | // where have some idea as to how many unique values there are and where the next value might be |
| 790 | fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 823 | fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 791 | 824 | 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)); | |
| 793 | 826 | |
| 794 | 827 | var index = range.start + skip; |
| 795 | 828 | while (lessThan(items[index - 1], value)) : (index += skip) { |
| ... | ... | @@ -801,9 +834,9 @@ fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const |
| 801 | 834 | return binaryFirst(T, items, value, Range.init(index - skip, index), lessThan); |
| 802 | 835 | } |
| 803 | 836 | |
| 804 | fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 837 | fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 805 | 838 | 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)); | |
| 807 | 840 | |
| 808 | 841 | var index = range.end - skip; |
| 809 | 842 | 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 |
| 815 | 848 | return binaryFirst(T, items, value, Range.init(index, index + skip), lessThan); |
| 816 | 849 | } |
| 817 | 850 | |
| 818 | fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 851 | fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 819 | 852 | 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)); | |
| 821 | 854 | |
| 822 | 855 | var index = range.start + skip; |
| 823 | 856 | while (!lessThan(value, items[index - 1])) : (index += skip) { |
| ... | ... | @@ -829,9 +862,9 @@ fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const |
| 829 | 862 | return binaryLast(T, items, value, Range.init(index - skip, index), lessThan); |
| 830 | 863 | } |
| 831 | 864 | |
| 832 | fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 865 | fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool, unique: usize) usize { | |
| 833 | 866 | 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)); | |
| 835 | 868 | |
| 836 | 869 | var index = range.end - skip; |
| 837 | 870 | 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 |
| 843 | 876 | return binaryLast(T, items, value, Range.init(index, index + skip), lessThan); |
| 844 | 877 | } |
| 845 | 878 | |
| 846 | fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { | |
| 879 | fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize { | |
| 847 | 880 | var start = range.start; |
| 848 | 881 | var end = range.end - 1; |
| 849 | 882 | if (range.start >= range.end) return range.end; |
| 850 | 883 | while (start < end) { |
| 851 | const mid = start + (end - start)/2; | |
| 884 | const mid = start + (end - start) / 2; | |
| 852 | 885 | if (lessThan(items[mid], value)) { |
| 853 | 886 | start = mid + 1; |
| 854 | 887 | } else { |
| ... | ... | @@ -861,12 +894,12 @@ fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Rang |
| 861 | 894 | return start; |
| 862 | 895 | } |
| 863 | 896 | |
| 864 | fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { | |
| 897 | fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T, &const T) bool) usize { | |
| 865 | 898 | var start = range.start; |
| 866 | 899 | var end = range.end - 1; |
| 867 | 900 | if (range.start >= range.end) return range.end; |
| 868 | 901 | while (start < end) { |
| 869 | const mid = start + (end - start)/2; | |
| 902 | const mid = start + (end - start) / 2; | |
| 870 | 903 | if (!lessThan(value, items[mid])) { |
| 871 | 904 | start = mid + 1; |
| 872 | 905 | } else { |
| ... | ... | @@ -879,7 +912,7 @@ fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range |
| 879 | 912 | return start; |
| 880 | 913 | } |
| 881 | 914 | |
| 882 | fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, into: []T) void { | |
| 915 | fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, into: []T) void { | |
| 883 | 916 | var A_index: usize = A.start; |
| 884 | 917 | var B_index: usize = B.start; |
| 885 | 918 | const A_last = A.end; |
| ... | ... | @@ -909,7 +942,7 @@ fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, less |
| 909 | 942 | } |
| 910 | 943 | } |
| 911 | 944 | |
| 912 | fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, cache: []T) void { | |
| 945 | fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T, &const T) bool, cache: []T) void { | |
| 913 | 946 | // A fits into the cache, so use that instead of the internal buffer |
| 914 | 947 | var A_index: usize = 0; |
| 915 | 948 | var B_index: usize = B.start; |
| ... | ... | @@ -937,29 +970,27 @@ fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, |
| 937 | 970 | mem.copy(T, items[insert_index..], cache[A_index..A_last]); |
| 938 | 971 | } |
| 939 | 972 | |
| 940 | fn 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 | { | |
| 973 | fn 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]))) { | |
| 944 | 975 | mem.swap(T, &items[x], &items[y]); |
| 945 | mem.swap(u8, &(*order)[x], &(*order)[y]); | |
| 976 | mem.swap(u8, &(order.*)[x], &(order.*)[y]); | |
| 946 | 977 | } |
| 947 | 978 | } |
| 948 | 979 | |
| 949 | 980 | fn i32asc(lhs: &const i32, rhs: &const i32) bool { |
| 950 | return *lhs < *rhs; | |
| 981 | return lhs.* < rhs.*; | |
| 951 | 982 | } |
| 952 | 983 | |
| 953 | 984 | fn i32desc(lhs: &const i32, rhs: &const i32) bool { |
| 954 | return *rhs < *lhs; | |
| 985 | return rhs.* < lhs.*; | |
| 955 | 986 | } |
| 956 | 987 | |
| 957 | 988 | fn u8asc(lhs: &const u8, rhs: &const u8) bool { |
| 958 | return *lhs < *rhs; | |
| 989 | return lhs.* < rhs.*; | |
| 959 | 990 | } |
| 960 | 991 | |
| 961 | 992 | fn u8desc(lhs: &const u8, rhs: &const u8) bool { |
| 962 | return *rhs < *lhs; | |
| 993 | return rhs.* < lhs.*; | |
| 963 | 994 | } |
| 964 | 995 | |
| 965 | 996 | test "stable sort" { |
| ... | ... | @@ -967,44 +998,125 @@ test "stable sort" { |
| 967 | 998 | comptime testStableSort(); |
| 968 | 999 | } |
| 969 | 1000 | fn 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 | }, | |
| 980 | 1038 | }; |
| 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 | }, | |
| 992 | 1077 | }, |
| 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 | }, | |
| 1003 | 1115 | }, |
| 1004 | 1116 | }; |
| 1005 | 1117 | 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| { | |
| 1008 | 1120 | assert(item.id == expected[i].id); |
| 1009 | 1121 | assert(item.value == expected[i].value); |
| 1010 | 1122 | } |
| ... | ... | @@ -1019,13 +1131,31 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) bool { |
| 1019 | 1131 | } |
| 1020 | 1132 | |
| 1021 | 1133 | test "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 | }, | |
| 1029 | 1159 | }; |
| 1030 | 1160 | |
| 1031 | 1161 | for (u8cases) |case| { |
| ... | ... | @@ -1036,13 +1166,59 @@ test "std.sort" { |
| 1036 | 1166 | assert(mem.eql(u8, slice, case[1])); |
| 1037 | 1167 | } |
| 1038 | 1168 | |
| 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 | }, | |
| 1046 | 1222 | }; |
| 1047 | 1223 | |
| 1048 | 1224 | for (i32cases) |case| { |
| ... | ... | @@ -1055,13 +1231,59 @@ test "std.sort" { |
| 1055 | 1231 | } |
| 1056 | 1232 | |
| 1057 | 1233 | test "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 | }, | |
| 1065 | 1287 | }; |
| 1066 | 1288 | |
| 1067 | 1289 | for (rev_cases) |case| { |
| ... | ... | @@ -1074,10 +1296,22 @@ test "std.sort descending" { |
| 1074 | 1296 | } |
| 1075 | 1297 | |
| 1076 | 1298 | test "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 | }; | |
| 1078 | 1306 | sort(i32, arr[0..], i32asc); |
| 1079 | 1307 | |
| 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 | })); | |
| 1081 | 1315 | } |
| 1082 | 1316 | |
| 1083 | 1317 | test "sort fuzz testing" { |
| ... | ... | @@ -1112,7 +1346,7 @@ fn fuzzTest(rng: &std.rand.Random) void { |
| 1112 | 1346 | } |
| 1113 | 1347 | } |
| 1114 | 1348 | |
| 1115 | pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { | |
| 1349 | pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T { | |
| 1116 | 1350 | var i: usize = 0; |
| 1117 | 1351 | var smallest = items[0]; |
| 1118 | 1352 | for (items[1..]) |item| { |
| ... | ... | @@ -1123,7 +1357,7 @@ pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const |
| 1123 | 1357 | return smallest; |
| 1124 | 1358 | } |
| 1125 | 1359 | |
| 1126 | pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { | |
| 1360 | pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) bool) T { | |
| 1127 | 1361 | var i: usize = 0; |
| 1128 | 1362 | var biggest = items[0]; |
| 1129 | 1363 | for (items[1..]) |item| { |
std/special/bootstrap.zig+4-4| ... | ... | @@ -27,10 +27,10 @@ extern fn zen_start() noreturn { |
| 27 | 27 | nakedcc fn _start() noreturn { |
| 28 | 28 | switch (builtin.arch) { |
| 29 | 29 | builtin.Arch.x86_64 => { |
| 30 | argc_ptr = asm("lea (%%rsp), %[argc]": [argc] "=r" (-> &usize)); | |
| 30 | argc_ptr = asm ("lea (%%rsp), %[argc]" : [argc] "=r" (-> &usize)); | |
| 31 | 31 | }, |
| 32 | 32 | builtin.Arch.i386 => { |
| 33 | argc_ptr = asm("lea (%%esp), %[argc]": [argc] "=r" (-> &usize)); | |
| 33 | argc_ptr = asm ("lea (%%esp), %[argc]" : [argc] "=r" (-> &usize)); | |
| 34 | 34 | }, |
| 35 | 35 | else => @compileError("unsupported arch"), |
| 36 | 36 | } |
| ... | ... | @@ -46,7 +46,7 @@ extern fn WinMainCRTStartup() noreturn { |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | fn posixCallMainAndExit() noreturn { |
| 49 | const argc = *argc_ptr; | |
| 49 | const argc = argc_ptr.*; | |
| 50 | 50 | const argv = @ptrCast(&&u8, &argc_ptr[1]); |
| 51 | 51 | const envp_nullable = @ptrCast(&?&u8, &argv[argc + 1]); |
| 52 | 52 | var envp_count: usize = 0; |
| ... | ... | @@ -56,7 +56,7 @@ fn posixCallMainAndExit() noreturn { |
| 56 | 56 | const auxv = &@ptrCast(&usize, envp.ptr)[envp_count + 1]; |
| 57 | 57 | var i: usize = 0; |
| 58 | 58 | 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]; | |
| 60 | 60 | } |
| 61 | 61 | std.debug.assert(std.os.linux_aux_raw[std.elf.AT_PAGESZ] == std.os.page_size); |
| 62 | 62 | } |
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 |
| 36 | 36 | const significand: rep_t = (aAbs & significandMask) | implicitBit; |
| 37 | 37 | |
| 38 | 38 | // 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; | |
| 41 | 40 | |
| 42 | 41 | // 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); | |
| 45 | 43 | |
| 46 | 44 | // If 0 <= exponent < significandBits, right shift to get the result. |
| 47 | 45 | // Otherwise, shift left. |
std/special/compiler_rt/fixunsdfdi.zig-1| ... | ... | @@ -9,4 +9,3 @@ pub extern fn __fixunsdfdi(a: f64) u64 { |
| 9 | 9 | test "import fixunsdfdi" { |
| 10 | 10 | _ = @import("fixunsdfdi_test.zig"); |
| 11 | 11 | } |
| 12 |
std/special/compiler_rt/fixunsdfsi.zig-1| ... | ... | @@ -9,4 +9,3 @@ pub extern fn __fixunsdfsi(a: f64) u32 { |
| 9 | 9 | test "import fixunsdfsi" { |
| 10 | 10 | _ = @import("fixunsdfsi_test.zig"); |
| 11 | 11 | } |
| 12 |
std/special/compiler_rt/fixunssfti.zig-1| ... | ... | @@ -9,4 +9,3 @@ pub extern fn __fixunssfti(a: f32) u128 { |
| 9 | 9 | test "import fixunssfti" { |
| 10 | 10 | _ = @import("fixunssfti_test.zig"); |
| 11 | 11 | } |
| 12 |
std/special/compiler_rt/fixunstfti.zig-1| ... | ... | @@ -9,4 +9,3 @@ pub extern fn __fixunstfti(a: f128) u128 { |
| 9 | 9 | test "import fixunstfti" { |
| 10 | 10 | _ = @import("fixunstfti_test.zig"); |
| 11 | 11 | } |
| 12 |
std/special/compiler_rt/index.zig+674-144| ... | ... | @@ -92,9 +92,10 @@ pub fn setXmm0(comptime T: type, value: T) void { |
| 92 | 92 | const aligned_value: T align(16) = value; |
| 93 | 93 | asm volatile ( |
| 94 | 94 | \\movaps (%[ptr]), %%xmm0 |
| 95 | : | |
| 96 | : [ptr] "r" (&aligned_value) | |
| 97 | : "xmm0"); | |
| 95 | ||
| 96 | : | |
| 97 | : [ptr] "r" (&aligned_value) | |
| 98 | : "xmm0"); | |
| 98 | 99 | } |
| 99 | 100 | |
| 100 | 101 | extern fn __udivdi3(a: u64, b: u64) u64 { |
| ... | ... | @@ -283,26 +284,27 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) u32 { |
| 283 | 284 | @setRuntimeSafety(is_test); |
| 284 | 285 | |
| 285 | 286 | const d = __udivsi3(a, b); |
| 286 | *rem = u32(i32(a) -% (i32(d) * i32(b))); | |
| 287 | rem.* = u32(i32(a) -% (i32(d) * i32(b))); | |
| 287 | 288 | return d; |
| 288 | 289 | } |
| 289 | 290 | |
| 290 | ||
| 291 | 291 | extern fn __udivsi3(n: u32, d: u32) u32 { |
| 292 | 292 | @setRuntimeSafety(is_test); |
| 293 | 293 | |
| 294 | 294 | const n_uword_bits: c_uint = u32.bit_count; |
| 295 | 295 | // 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; | |
| 300 | 298 | var sr = @bitCast(c_uint, c_int(@clz(d)) - c_int(@clz(n))); |
| 301 | 299 | // 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 | |
| 303 | 302 | return 0; |
| 304 | if (sr == n_uword_bits - 1) // d == 1 | |
| 303 | } | |
| 304 | if (sr == n_uword_bits - 1) { | |
| 305 | // d == 1 | |
| 305 | 306 | return n; |
| 307 | } | |
| 306 | 308 | sr += 1; |
| 307 | 309 | // 1 <= sr <= n_uword_bits - 1 |
| 308 | 310 | // Not a special case |
| ... | ... | @@ -341,139 +343,667 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { |
| 341 | 343 | } |
| 342 | 344 | |
| 343 | 345 | test "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 | }, | |
| 477 | 1007 | }; |
| 478 | 1008 | |
| 479 | 1009 | for (cases) |case| { |
std/special/compiler_rt/udivmod.zig+23-20| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const is_test = builtin.is_test; |
| 3 | 3 | |
| 4 | const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 }; | |
| 4 | const low = switch (builtin.endian) { | |
| 5 | builtin.Endian.Big => 1, | |
| 6 | builtin.Endian.Little => 0, | |
| 7 | }; | |
| 5 | 8 | const high = 1 - low; |
| 6 | 9 | |
| 7 | 10 | pub 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: |
| 11 | 14 | const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); |
| 12 | 15 | const Log2SingleInt = @import("std").math.Log2Int(SingleInt); |
| 13 | 16 | |
| 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 | |
| 16 | 19 | var q: [2]SingleInt = undefined; |
| 17 | 20 | var r: [2]SingleInt = undefined; |
| 18 | 21 | var sr: c_uint = undefined; |
| ... | ... | @@ -23,7 +26,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 23 | 26 | // --- |
| 24 | 27 | // 0 X |
| 25 | 28 | if (maybe_rem) |rem| { |
| 26 | *rem = n[low] % d[low]; | |
| 29 | rem.* = n[low] % d[low]; | |
| 27 | 30 | } |
| 28 | 31 | return n[low] / d[low]; |
| 29 | 32 | } |
| ... | ... | @@ -31,7 +34,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 31 | 34 | // --- |
| 32 | 35 | // K X |
| 33 | 36 | if (maybe_rem) |rem| { |
| 34 | *rem = n[low]; | |
| 37 | rem.* = n[low]; | |
| 35 | 38 | } |
| 36 | 39 | return 0; |
| 37 | 40 | } |
| ... | ... | @@ -42,7 +45,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 42 | 45 | // --- |
| 43 | 46 | // 0 0 |
| 44 | 47 | if (maybe_rem) |rem| { |
| 45 | *rem = n[high] % d[low]; | |
| 48 | rem.* = n[high] % d[low]; | |
| 46 | 49 | } |
| 47 | 50 | return n[high] / d[low]; |
| 48 | 51 | } |
| ... | ... | @@ -54,7 +57,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 54 | 57 | if (maybe_rem) |rem| { |
| 55 | 58 | r[high] = n[high] % d[high]; |
| 56 | 59 | 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 | |
| 58 | 61 | } |
| 59 | 62 | return n[high] / d[high]; |
| 60 | 63 | } |
| ... | ... | @@ -66,7 +69,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 66 | 69 | if (maybe_rem) |rem| { |
| 67 | 70 | r[low] = n[low]; |
| 68 | 71 | 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 | |
| 70 | 73 | } |
| 71 | 74 | return n[high] >> Log2SingleInt(@ctz(d[high])); |
| 72 | 75 | } |
| ... | ... | @@ -77,7 +80,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 77 | 80 | // 0 <= sr <= SingleInt.bit_count - 2 or sr large |
| 78 | 81 | if (sr > SingleInt.bit_count - 2) { |
| 79 | 82 | if (maybe_rem) |rem| { |
| 80 | *rem = a; | |
| 83 | rem.* = a; | |
| 81 | 84 | } |
| 82 | 85 | return 0; |
| 83 | 86 | } |
| ... | ... | @@ -98,7 +101,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 98 | 101 | if ((d[low] & (d[low] - 1)) == 0) { |
| 99 | 102 | // d is a power of 2 |
| 100 | 103 | if (maybe_rem) |rem| { |
| 101 | *rem = n[low] & (d[low] - 1); | |
| 104 | rem.* = n[low] & (d[low] - 1); | |
| 102 | 105 | } |
| 103 | 106 | if (d[low] == 1) { |
| 104 | 107 | return a; |
| ... | ... | @@ -106,7 +109,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 106 | 109 | sr = @ctz(d[low]); |
| 107 | 110 | q[high] = n[high] >> Log2SingleInt(sr); |
| 108 | 111 | 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 | |
| 110 | 113 | } |
| 111 | 114 | // K X |
| 112 | 115 | // --- |
| ... | ... | @@ -141,7 +144,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 141 | 144 | // 0 <= sr <= SingleInt.bit_count - 1 or sr large |
| 142 | 145 | if (sr > SingleInt.bit_count - 1) { |
| 143 | 146 | if (maybe_rem) |rem| { |
| 144 | *rem = a; | |
| 147 | rem.* = a; | |
| 145 | 148 | } |
| 146 | 149 | return 0; |
| 147 | 150 | } |
| ... | ... | @@ -170,25 +173,25 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: |
| 170 | 173 | var r_all: DoubleInt = undefined; |
| 171 | 174 | while (sr > 0) : (sr -= 1) { |
| 172 | 175 | // 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; | |
| 177 | 180 | // carry = 0; |
| 178 | 181 | // if (r.all >= b) |
| 179 | 182 | // { |
| 180 | 183 | // r.all -= b; |
| 181 | 184 | // carry = 1; |
| 182 | 185 | // } |
| 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 | |
| 184 | 187 | const s: SignedDoubleInt = SignedDoubleInt(b -% r_all -% 1) >> (DoubleInt.bit_count - 1); |
| 185 | 188 | carry = u32(s & 1); |
| 186 | 189 | 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 | |
| 188 | 191 | } |
| 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 | |
| 190 | 193 | if (maybe_rem) |rem| { |
| 191 | *rem = r_all; | |
| 194 | rem.* = r_all; | |
| 192 | 195 | } |
| 193 | 196 | return q_all; |
| 194 | 197 | } |
std/special/compiler_rt/udivmodti4.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) u128 { |
| 9 | 9 | |
| 10 | 10 | pub extern fn __udivmodti4_windows_x86_64(a: &const u128, b: &const u128, maybe_rem: ?&u128) void { |
| 11 | 11 | @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)); | |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | test "import udivmodti4" { |
std/special/compiler_rt/umodti3.zig+1-1| ... | ... | @@ -11,5 +11,5 @@ pub extern fn __umodti3(a: u128, b: u128) u128 { |
| 11 | 11 | |
| 12 | 12 | pub extern fn __umodti3_windows_x86_64(a: &const u128, b: &const u128) void { |
| 13 | 13 | @setRuntimeSafety(builtin.is_test); |
| 14 | compiler_rt.setXmm0(u128, __umodti3(*a, *b)); | |
| 14 | compiler_rt.setXmm0(u128, __umodti3(a.*, b.*)); | |
| 15 | 15 | } |
std/zig/ast.zig+34-41| ... | ... | @@ -40,7 +40,7 @@ pub const Tree = struct { |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | 42 | pub fn tokenLocationPtr(self: &Tree, start_index: usize, token: &const Token) Location { |
| 43 | var loc = Location { | |
| 43 | var loc = Location{ | |
| 44 | 44 | .line = 0, |
| 45 | 45 | .column = 0, |
| 46 | 46 | .line_start = start_index, |
| ... | ... | @@ -71,7 +71,6 @@ pub const Tree = struct { |
| 71 | 71 | pub fn dump(self: &Tree) void { |
| 72 | 72 | self.root_node.base.dump(0); |
| 73 | 73 | } |
| 74 | ||
| 75 | 74 | }; |
| 76 | 75 | |
| 77 | 76 | pub const Error = union(enum) { |
| ... | ... | @@ -95,7 +94,7 @@ pub const Error = union(enum) { |
| 95 | 94 | ExpectedCommaOrEnd: ExpectedCommaOrEnd, |
| 96 | 95 | |
| 97 | 96 | pub fn render(self: &Error, tokens: &Tree.TokenList, stream: var) !void { |
| 98 | switch (*self) { | |
| 97 | switch (self.*) { | |
| 99 | 98 | // TODO https://github.com/zig-lang/zig/issues/683 |
| 100 | 99 | @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream), |
| 101 | 100 | @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), |
| ... | ... | @@ -119,7 +118,7 @@ pub const Error = union(enum) { |
| 119 | 118 | } |
| 120 | 119 | |
| 121 | 120 | pub fn loc(self: &Error) TokenIndex { |
| 122 | switch (*self) { | |
| 121 | switch (self.*) { | |
| 123 | 122 | // TODO https://github.com/zig-lang/zig/issues/683 |
| 124 | 123 | @TagType(Error).InvalidToken => |x| return x.token, |
| 125 | 124 | @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token, |
| ... | ... | @@ -144,15 +143,12 @@ pub const Error = union(enum) { |
| 144 | 143 | |
| 145 | 144 | pub const InvalidToken = SingleTokenError("Invalid token {}"); |
| 146 | 145 | pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}"); |
| 147 | pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ | |
| 148 | @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ | |
| 149 | @tagName(Token.Id.Keyword_enum) ++ ", found {}"); | |
| 146 | pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}"); | |
| 150 | 147 | pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}"); |
| 151 | 148 | pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}"); |
| 152 | 149 | pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found {}"); |
| 153 | 150 | pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found {}"); |
| 154 | pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ | |
| 155 | @tagName(Token.Id.Identifier) ++ ", found {}"); | |
| 151 | pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or " ++ @tagName(Token.Id.Identifier) ++ ", found {}"); | |
| 156 | 152 | pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found {}"); |
| 157 | 153 | pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found {}"); |
| 158 | 154 | |
| ... | ... | @@ -165,8 +161,7 @@ pub const Error = union(enum) { |
| 165 | 161 | node: &Node, |
| 166 | 162 | |
| 167 | 163 | pub fn render(self: &ExpectedCall, tokens: &Tree.TokenList, stream: var) !void { |
| 168 | return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ ", found {}", | |
| 169 | @tagName(self.node.id)); | |
| 164 | return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ ", found {}", @tagName(self.node.id)); | |
| 170 | 165 | } |
| 171 | 166 | }; |
| 172 | 167 | |
| ... | ... | @@ -174,8 +169,7 @@ pub const Error = union(enum) { |
| 174 | 169 | node: &Node, |
| 175 | 170 | |
| 176 | 171 | pub fn render(self: &ExpectedCallOrFnProto, tokens: &Tree.TokenList, stream: var) !void { |
| 177 | return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ " or " ++ | |
| 178 | @tagName(Node.Id.FnProto) ++ ", found {}", @tagName(self.node.id)); | |
| 172 | return stream.print("expected " ++ @tagName(@TagType(Node.SuffixOp.Op).Call) ++ " or " ++ @tagName(Node.Id.FnProto) ++ ", found {}", @tagName(self.node.id)); | |
| 179 | 173 | } |
| 180 | 174 | }; |
| 181 | 175 | |
| ... | ... | @@ -445,17 +439,17 @@ pub const Node = struct { |
| 445 | 439 | |
| 446 | 440 | pub fn iterate(self: &Root, index: usize) ?&Node { |
| 447 | 441 | if (index < self.decls.len) { |
| 448 | return *self.decls.at(index); | |
| 442 | return self.decls.at(index).*; | |
| 449 | 443 | } |
| 450 | 444 | return null; |
| 451 | 445 | } |
| 452 | 446 | |
| 453 | 447 | pub fn firstToken(self: &Root) TokenIndex { |
| 454 | return if (self.decls.len == 0) self.eof_token else (*self.decls.at(0)).firstToken(); | |
| 448 | return if (self.decls.len == 0) self.eof_token else (self.decls.at(0).*).firstToken(); | |
| 455 | 449 | } |
| 456 | 450 | |
| 457 | 451 | pub fn lastToken(self: &Root) TokenIndex { |
| 458 | return if (self.decls.len == 0) self.eof_token else (*self.decls.at(self.decls.len - 1)).lastToken(); | |
| 452 | return if (self.decls.len == 0) self.eof_token else (self.decls.at(self.decls.len - 1).*).lastToken(); | |
| 459 | 453 | } |
| 460 | 454 | }; |
| 461 | 455 | |
| ... | ... | @@ -545,7 +539,7 @@ pub const Node = struct { |
| 545 | 539 | pub fn iterate(self: &ErrorSetDecl, index: usize) ?&Node { |
| 546 | 540 | var i = index; |
| 547 | 541 | |
| 548 | if (i < self.decls.len) return *self.decls.at(i); | |
| 542 | if (i < self.decls.len) return self.decls.at(i).*; | |
| 549 | 543 | i -= self.decls.len; |
| 550 | 544 | |
| 551 | 545 | return null; |
| ... | ... | @@ -598,10 +592,10 @@ pub const Node = struct { |
| 598 | 592 | i -= 1; |
| 599 | 593 | }, |
| 600 | 594 | InitArg.None, |
| 601 | InitArg.Enum => { } | |
| 595 | InitArg.Enum => {}, | |
| 602 | 596 | } |
| 603 | 597 | |
| 604 | if (i < self.fields_and_decls.len) return *self.fields_and_decls.at(i); | |
| 598 | if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i).*; | |
| 605 | 599 | i -= self.fields_and_decls.len; |
| 606 | 600 | |
| 607 | 601 | return null; |
| ... | ... | @@ -814,7 +808,7 @@ pub const Node = struct { |
| 814 | 808 | i -= 1; |
| 815 | 809 | } |
| 816 | 810 | |
| 817 | if (i < self.params.len) return *self.params.at(self.params.len - i - 1); | |
| 811 | if (i < self.params.len) return self.params.at(self.params.len - i - 1).*; | |
| 818 | 812 | i -= self.params.len; |
| 819 | 813 | |
| 820 | 814 | if (self.align_expr) |align_expr| { |
| ... | ... | @@ -839,7 +833,6 @@ pub const Node = struct { |
| 839 | 833 | i -= 1; |
| 840 | 834 | } |
| 841 | 835 | |
| 842 | ||
| 843 | 836 | return null; |
| 844 | 837 | } |
| 845 | 838 | |
| ... | ... | @@ -934,7 +927,7 @@ pub const Node = struct { |
| 934 | 927 | pub fn iterate(self: &Block, index: usize) ?&Node { |
| 935 | 928 | var i = index; |
| 936 | 929 | |
| 937 | if (i < self.statements.len) return *self.statements.at(i); | |
| 930 | if (i < self.statements.len) return self.statements.at(i).*; | |
| 938 | 931 | i -= self.statements.len; |
| 939 | 932 | |
| 940 | 933 | return null; |
| ... | ... | @@ -1119,6 +1112,7 @@ pub const Node = struct { |
| 1119 | 1112 | base: Node, |
| 1120 | 1113 | switch_token: TokenIndex, |
| 1121 | 1114 | expr: &Node, |
| 1115 | ||
| 1122 | 1116 | /// these can be SwitchCase nodes or LineComment nodes |
| 1123 | 1117 | cases: CaseList, |
| 1124 | 1118 | rbrace: TokenIndex, |
| ... | ... | @@ -1131,7 +1125,7 @@ pub const Node = struct { |
| 1131 | 1125 | if (i < 1) return self.expr; |
| 1132 | 1126 | i -= 1; |
| 1133 | 1127 | |
| 1134 | if (i < self.cases.len) return *self.cases.at(i); | |
| 1128 | if (i < self.cases.len) return self.cases.at(i).*; | |
| 1135 | 1129 | i -= self.cases.len; |
| 1136 | 1130 | |
| 1137 | 1131 | return null; |
| ... | ... | @@ -1157,7 +1151,7 @@ pub const Node = struct { |
| 1157 | 1151 | pub fn iterate(self: &SwitchCase, index: usize) ?&Node { |
| 1158 | 1152 | var i = index; |
| 1159 | 1153 | |
| 1160 | if (i < self.items.len) return *self.items.at(i); | |
| 1154 | if (i < self.items.len) return self.items.at(i).*; | |
| 1161 | 1155 | i -= self.items.len; |
| 1162 | 1156 | |
| 1163 | 1157 | if (self.payload) |payload| { |
| ... | ... | @@ -1172,7 +1166,7 @@ pub const Node = struct { |
| 1172 | 1166 | } |
| 1173 | 1167 | |
| 1174 | 1168 | pub fn firstToken(self: &SwitchCase) TokenIndex { |
| 1175 | return (*self.items.at(0)).firstToken(); | |
| 1169 | return (self.items.at(0).*).firstToken(); | |
| 1176 | 1170 | } |
| 1177 | 1171 | |
| 1178 | 1172 | pub fn lastToken(self: &SwitchCase) TokenIndex { |
| ... | ... | @@ -1491,7 +1485,7 @@ pub const Node = struct { |
| 1491 | 1485 | BitNot, |
| 1492 | 1486 | BoolNot, |
| 1493 | 1487 | Cancel, |
| 1494 | Deref, | |
| 1488 | PointerType, | |
| 1495 | 1489 | MaybeType, |
| 1496 | 1490 | Negation, |
| 1497 | 1491 | NegationWrap, |
| ... | ... | @@ -1533,7 +1527,6 @@ pub const Node = struct { |
| 1533 | 1527 | Op.BitNot, |
| 1534 | 1528 | Op.BoolNot, |
| 1535 | 1529 | Op.Cancel, |
| 1536 | Op.Deref, | |
| 1537 | 1530 | Op.MaybeType, |
| 1538 | 1531 | Op.Negation, |
| 1539 | 1532 | Op.NegationWrap, |
| ... | ... | @@ -1593,6 +1586,7 @@ pub const Node = struct { |
| 1593 | 1586 | Slice: Slice, |
| 1594 | 1587 | ArrayInitializer: InitList, |
| 1595 | 1588 | StructInitializer: InitList, |
| 1589 | Deref, | |
| 1596 | 1590 | |
| 1597 | 1591 | pub const InitList = SegmentedList(&Node, 2); |
| 1598 | 1592 | |
| ... | ... | @@ -1617,7 +1611,7 @@ pub const Node = struct { |
| 1617 | 1611 | |
| 1618 | 1612 | switch (self.op) { |
| 1619 | 1613 | @TagType(Op).Call => |*call_info| { |
| 1620 | if (i < call_info.params.len) return *call_info.params.at(i); | |
| 1614 | if (i < call_info.params.len) return call_info.params.at(i).*; | |
| 1621 | 1615 | i -= call_info.params.len; |
| 1622 | 1616 | }, |
| 1623 | 1617 | Op.ArrayAccess => |index_expr| { |
| ... | ... | @@ -1634,11 +1628,11 @@ pub const Node = struct { |
| 1634 | 1628 | } |
| 1635 | 1629 | }, |
| 1636 | 1630 | Op.ArrayInitializer => |*exprs| { |
| 1637 | if (i < exprs.len) return *exprs.at(i); | |
| 1631 | if (i < exprs.len) return exprs.at(i).*; | |
| 1638 | 1632 | i -= exprs.len; |
| 1639 | 1633 | }, |
| 1640 | 1634 | Op.StructInitializer => |*fields| { |
| 1641 | if (i < fields.len) return *fields.at(i); | |
| 1635 | if (i < fields.len) return fields.at(i).*; | |
| 1642 | 1636 | i -= fields.len; |
| 1643 | 1637 | }, |
| 1644 | 1638 | } |
| ... | ... | @@ -1831,7 +1825,7 @@ pub const Node = struct { |
| 1831 | 1825 | pub fn iterate(self: &BuiltinCall, index: usize) ?&Node { |
| 1832 | 1826 | var i = index; |
| 1833 | 1827 | |
| 1834 | if (i < self.params.len) return *self.params.at(i); | |
| 1828 | if (i < self.params.len) return self.params.at(i).*; | |
| 1835 | 1829 | i -= self.params.len; |
| 1836 | 1830 | |
| 1837 | 1831 | return null; |
| ... | ... | @@ -1874,11 +1868,11 @@ pub const Node = struct { |
| 1874 | 1868 | } |
| 1875 | 1869 | |
| 1876 | 1870 | pub fn firstToken(self: &MultilineStringLiteral) TokenIndex { |
| 1877 | return *self.lines.at(0); | |
| 1871 | return self.lines.at(0).*; | |
| 1878 | 1872 | } |
| 1879 | 1873 | |
| 1880 | 1874 | pub fn lastToken(self: &MultilineStringLiteral) TokenIndex { |
| 1881 | return *self.lines.at(self.lines.len - 1); | |
| 1875 | return self.lines.at(self.lines.len - 1).*; | |
| 1882 | 1876 | } |
| 1883 | 1877 | }; |
| 1884 | 1878 | |
| ... | ... | @@ -1975,7 +1969,7 @@ pub const Node = struct { |
| 1975 | 1969 | |
| 1976 | 1970 | const Kind = union(enum) { |
| 1977 | 1971 | Variable: &Identifier, |
| 1978 | Return: &Node | |
| 1972 | Return: &Node, | |
| 1979 | 1973 | }; |
| 1980 | 1974 | |
| 1981 | 1975 | pub fn iterate(self: &AsmOutput, index: usize) ?&Node { |
| ... | ... | @@ -1995,7 +1989,7 @@ pub const Node = struct { |
| 1995 | 1989 | Kind.Return => |return_type| { |
| 1996 | 1990 | if (i < 1) return return_type; |
| 1997 | 1991 | i -= 1; |
| 1998 | } | |
| 1992 | }, | |
| 1999 | 1993 | } |
| 2000 | 1994 | |
| 2001 | 1995 | return null; |
| ... | ... | @@ -2060,13 +2054,13 @@ pub const Node = struct { |
| 2060 | 2054 | pub fn iterate(self: &Asm, index: usize) ?&Node { |
| 2061 | 2055 | var i = index; |
| 2062 | 2056 | |
| 2063 | if (i < self.outputs.len) return &(*self.outputs.at(index)).base; | |
| 2057 | if (i < self.outputs.len) return &(self.outputs.at(index).*).base; | |
| 2064 | 2058 | i -= self.outputs.len; |
| 2065 | 2059 | |
| 2066 | if (i < self.inputs.len) return &(*self.inputs.at(index)).base; | |
| 2060 | if (i < self.inputs.len) return &(self.inputs.at(index).*).base; | |
| 2067 | 2061 | i -= self.inputs.len; |
| 2068 | 2062 | |
| 2069 | if (i < self.clobbers.len) return *self.clobbers.at(index); | |
| 2063 | if (i < self.clobbers.len) return self.clobbers.at(index).*; | |
| 2070 | 2064 | i -= self.clobbers.len; |
| 2071 | 2065 | |
| 2072 | 2066 | return null; |
| ... | ... | @@ -2160,11 +2154,11 @@ pub const Node = struct { |
| 2160 | 2154 | } |
| 2161 | 2155 | |
| 2162 | 2156 | pub fn firstToken(self: &DocComment) TokenIndex { |
| 2163 | return *self.lines.at(0); | |
| 2157 | return self.lines.at(0).*; | |
| 2164 | 2158 | } |
| 2165 | 2159 | |
| 2166 | 2160 | pub fn lastToken(self: &DocComment) TokenIndex { |
| 2167 | return *self.lines.at(self.lines.len - 1); | |
| 2161 | return self.lines.at(self.lines.len - 1).*; | |
| 2168 | 2162 | } |
| 2169 | 2163 | }; |
| 2170 | 2164 | |
| ... | ... | @@ -2193,4 +2187,3 @@ pub const Node = struct { |
| 2193 | 2187 | } |
| 2194 | 2188 | }; |
| 2195 | 2189 | }; |
| 2196 |
std/zig/parse.zig+930-1161| ... | ... | @@ -17,15 +17,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 17 | 17 | defer stack.deinit(); |
| 18 | 18 | |
| 19 | 19 | const arena = &tree_arena.allocator; |
| 20 | const root_node = try arena.construct(ast.Node.Root { | |
| 21 | .base = ast.Node { .id = ast.Node.Id.Root }, | |
| 20 | const root_node = try arena.construct(ast.Node.Root{ | |
| 21 | .base = ast.Node{ .id = ast.Node.Id.Root }, | |
| 22 | 22 | .decls = ast.Node.Root.DeclList.init(arena), |
| 23 | 23 | .doc_comments = null, |
| 24 | 24 | // initialized when we get the eof token |
| 25 | 25 | .eof_token = undefined, |
| 26 | 26 | }); |
| 27 | 27 | |
| 28 | var tree = ast.Tree { | |
| 28 | var tree = ast.Tree{ | |
| 29 | 29 | .source = source, |
| 30 | 30 | .root_node = root_node, |
| 31 | 31 | .arena_allocator = tree_arena, |
| ... | ... | @@ -36,9 +36,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 36 | 36 | var tokenizer = Tokenizer.init(tree.source); |
| 37 | 37 | while (true) { |
| 38 | 38 | const token_ptr = try tree.tokens.addOne(); |
| 39 | *token_ptr = tokenizer.next(); | |
| 40 | if (token_ptr.id == Token.Id.Eof) | |
| 41 | break; | |
| 39 | token_ptr.* = tokenizer.next(); | |
| 40 | if (token_ptr.id == Token.Id.Eof) break; | |
| 42 | 41 | } |
| 43 | 42 | var tok_it = tree.tokens.iterator(0); |
| 44 | 43 | |
| ... | ... | @@ -63,33 +62,27 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 63 | 62 | Token.Id.Keyword_test => { |
| 64 | 63 | stack.append(State.TopLevel) catch unreachable; |
| 65 | 64 | |
| 66 | const block = try arena.construct(ast.Node.Block { | |
| 67 | .base = ast.Node { | |
| 68 | .id = ast.Node.Id.Block, | |
| 69 | }, | |
| 65 | const block = try arena.construct(ast.Node.Block{ | |
| 66 | .base = ast.Node{ .id = ast.Node.Id.Block }, | |
| 70 | 67 | .label = null, |
| 71 | 68 | .lbrace = undefined, |
| 72 | 69 | .statements = ast.Node.Block.StatementList.init(arena), |
| 73 | 70 | .rbrace = undefined, |
| 74 | 71 | }); |
| 75 | const test_node = try arena.construct(ast.Node.TestDecl { | |
| 76 | .base = ast.Node { | |
| 77 | .id = ast.Node.Id.TestDecl, | |
| 78 | }, | |
| 72 | const test_node = try arena.construct(ast.Node.TestDecl{ | |
| 73 | .base = ast.Node{ .id = ast.Node.Id.TestDecl }, | |
| 79 | 74 | .doc_comments = comments, |
| 80 | 75 | .test_token = token_index, |
| 81 | 76 | .name = undefined, |
| 82 | 77 | .body_node = &block.base, |
| 83 | 78 | }); |
| 84 | 79 | try root_node.decls.push(&test_node.base); |
| 85 | try stack.append(State { .Block = block }); | |
| 86 | try stack.append(State { | |
| 87 | .ExpectTokenSave = ExpectTokenSave { | |
| 88 | .id = Token.Id.LBrace, | |
| 89 | .ptr = &block.rbrace, | |
| 90 | } | |
| 91 | }); | |
| 92 | try stack.append(State { .StringLiteral = OptionalCtx { .Required = &test_node.name } }); | |
| 80 | try stack.append(State{ .Block = block }); | |
| 81 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 82 | .id = Token.Id.LBrace, | |
| 83 | .ptr = &block.rbrace, | |
| 84 | } }); | |
| 85 | try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &test_node.name } }); | |
| 93 | 86 | continue; |
| 94 | 87 | }, |
| 95 | 88 | Token.Id.Eof => { |
| ... | ... | @@ -99,29 +92,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 99 | 92 | }, |
| 100 | 93 | Token.Id.Keyword_pub => { |
| 101 | 94 | stack.append(State.TopLevel) catch unreachable; |
| 102 | try stack.append(State { | |
| 103 | .TopLevelExtern = TopLevelDeclCtx { | |
| 104 | .decls = &root_node.decls, | |
| 105 | .visib_token = token_index, | |
| 106 | .extern_export_inline_token = null, | |
| 107 | .lib_name = null, | |
| 108 | .comments = comments, | |
| 109 | } | |
| 110 | }); | |
| 95 | try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ | |
| 96 | .decls = &root_node.decls, | |
| 97 | .visib_token = token_index, | |
| 98 | .extern_export_inline_token = null, | |
| 99 | .lib_name = null, | |
| 100 | .comments = comments, | |
| 101 | } }); | |
| 111 | 102 | continue; |
| 112 | 103 | }, |
| 113 | 104 | Token.Id.Keyword_comptime => { |
| 114 | const block = try arena.construct(ast.Node.Block { | |
| 115 | .base = ast.Node {.id = ast.Node.Id.Block }, | |
| 105 | const block = try arena.construct(ast.Node.Block{ | |
| 106 | .base = ast.Node{ .id = ast.Node.Id.Block }, | |
| 116 | 107 | .label = null, |
| 117 | 108 | .lbrace = undefined, |
| 118 | 109 | .statements = ast.Node.Block.StatementList.init(arena), |
| 119 | 110 | .rbrace = undefined, |
| 120 | 111 | }); |
| 121 | const node = try arena.construct(ast.Node.Comptime { | |
| 122 | .base = ast.Node { | |
| 123 | .id = ast.Node.Id.Comptime, | |
| 124 | }, | |
| 112 | const node = try arena.construct(ast.Node.Comptime{ | |
| 113 | .base = ast.Node{ .id = ast.Node.Id.Comptime }, | |
| 125 | 114 | .comptime_token = token_index, |
| 126 | 115 | .expr = &block.base, |
| 127 | 116 | .doc_comments = comments, |
| ... | ... | @@ -129,27 +118,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 129 | 118 | try root_node.decls.push(&node.base); |
| 130 | 119 | |
| 131 | 120 | stack.append(State.TopLevel) catch unreachable; |
| 132 | try stack.append(State { .Block = block }); | |
| 133 | try stack.append(State { | |
| 134 | .ExpectTokenSave = ExpectTokenSave { | |
| 135 | .id = Token.Id.LBrace, | |
| 136 | .ptr = &block.rbrace, | |
| 137 | } | |
| 138 | }); | |
| 121 | try stack.append(State{ .Block = block }); | |
| 122 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 123 | .id = Token.Id.LBrace, | |
| 124 | .ptr = &block.rbrace, | |
| 125 | } }); | |
| 139 | 126 | continue; |
| 140 | 127 | }, |
| 141 | 128 | else => { |
| 142 | 129 | putBackToken(&tok_it, &tree); |
| 143 | 130 | stack.append(State.TopLevel) catch unreachable; |
| 144 | try stack.append(State { | |
| 145 | .TopLevelExtern = TopLevelDeclCtx { | |
| 146 | .decls = &root_node.decls, | |
| 147 | .visib_token = null, | |
| 148 | .extern_export_inline_token = null, | |
| 149 | .lib_name = null, | |
| 150 | .comments = comments, | |
| 151 | } | |
| 152 | }); | |
| 131 | try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ | |
| 132 | .decls = &root_node.decls, | |
| 133 | .visib_token = null, | |
| 134 | .extern_export_inline_token = null, | |
| 135 | .lib_name = null, | |
| 136 | .comments = comments, | |
| 137 | } }); | |
| 153 | 138 | continue; |
| 154 | 139 | }, |
| 155 | 140 | } |
| ... | ... | @@ -159,41 +144,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 159 | 144 | const token_index = token.index; |
| 160 | 145 | const token_ptr = token.ptr; |
| 161 | 146 | switch (token_ptr.id) { |
| 162 | Token.Id.Keyword_export, Token.Id.Keyword_inline => { | |
| 163 | stack.append(State { | |
| 164 | .TopLevelDecl = TopLevelDeclCtx { | |
| 165 | .decls = ctx.decls, | |
| 166 | .visib_token = ctx.visib_token, | |
| 167 | .extern_export_inline_token = AnnotatedToken { | |
| 168 | .index = token_index, | |
| 169 | .ptr = token_ptr, | |
| 170 | }, | |
| 171 | .lib_name = null, | |
| 172 | .comments = ctx.comments, | |
| 147 | Token.Id.Keyword_export, | |
| 148 | Token.Id.Keyword_inline => { | |
| 149 | stack.append(State{ .TopLevelDecl = TopLevelDeclCtx{ | |
| 150 | .decls = ctx.decls, | |
| 151 | .visib_token = ctx.visib_token, | |
| 152 | .extern_export_inline_token = AnnotatedToken{ | |
| 153 | .index = token_index, | |
| 154 | .ptr = token_ptr, | |
| 173 | 155 | }, |
| 174 | }) catch unreachable; | |
| 156 | .lib_name = null, | |
| 157 | .comments = ctx.comments, | |
| 158 | } }) catch unreachable; | |
| 175 | 159 | continue; |
| 176 | 160 | }, |
| 177 | 161 | Token.Id.Keyword_extern => { |
| 178 | stack.append(State { | |
| 179 | .TopLevelLibname = TopLevelDeclCtx { | |
| 180 | .decls = ctx.decls, | |
| 181 | .visib_token = ctx.visib_token, | |
| 182 | .extern_export_inline_token = AnnotatedToken { | |
| 183 | .index = token_index, | |
| 184 | .ptr = token_ptr, | |
| 185 | }, | |
| 186 | .lib_name = null, | |
| 187 | .comments = ctx.comments, | |
| 162 | stack.append(State{ .TopLevelLibname = TopLevelDeclCtx{ | |
| 163 | .decls = ctx.decls, | |
| 164 | .visib_token = ctx.visib_token, | |
| 165 | .extern_export_inline_token = AnnotatedToken{ | |
| 166 | .index = token_index, | |
| 167 | .ptr = token_ptr, | |
| 188 | 168 | }, |
| 189 | }) catch unreachable; | |
| 169 | .lib_name = null, | |
| 170 | .comments = ctx.comments, | |
| 171 | } }) catch unreachable; | |
| 190 | 172 | continue; |
| 191 | 173 | }, |
| 192 | 174 | else => { |
| 193 | 175 | putBackToken(&tok_it, &tree); |
| 194 | stack.append(State { .TopLevelDecl = ctx }) catch unreachable; | |
| 176 | stack.append(State{ .TopLevelDecl = ctx }) catch unreachable; | |
| 195 | 177 | continue; |
| 196 | } | |
| 178 | }, | |
| 197 | 179 | } |
| 198 | 180 | }, |
| 199 | 181 | State.TopLevelLibname => |ctx| { |
| ... | ... | @@ -207,15 +189,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 207 | 189 | }; |
| 208 | 190 | }; |
| 209 | 191 | |
| 210 | stack.append(State { | |
| 211 | .TopLevelDecl = TopLevelDeclCtx { | |
| 212 | .decls = ctx.decls, | |
| 213 | .visib_token = ctx.visib_token, | |
| 214 | .extern_export_inline_token = ctx.extern_export_inline_token, | |
| 215 | .lib_name = lib_name, | |
| 216 | .comments = ctx.comments, | |
| 217 | }, | |
| 218 | }) catch unreachable; | |
| 192 | stack.append(State{ .TopLevelDecl = TopLevelDeclCtx{ | |
| 193 | .decls = ctx.decls, | |
| 194 | .visib_token = ctx.visib_token, | |
| 195 | .extern_export_inline_token = ctx.extern_export_inline_token, | |
| 196 | .lib_name = lib_name, | |
| 197 | .comments = ctx.comments, | |
| 198 | } }) catch unreachable; | |
| 219 | 199 | continue; |
| 220 | 200 | }, |
| 221 | 201 | State.TopLevelDecl => |ctx| { |
| ... | ... | @@ -225,14 +205,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 225 | 205 | switch (token_ptr.id) { |
| 226 | 206 | Token.Id.Keyword_use => { |
| 227 | 207 | if (ctx.extern_export_inline_token) |annotated_token| { |
| 228 | *(try tree.errors.addOne()) = Error { | |
| 229 | .InvalidToken = Error.InvalidToken { .token = annotated_token.index }, | |
| 230 | }; | |
| 208 | ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } }; | |
| 231 | 209 | return tree; |
| 232 | 210 | } |
| 233 | 211 | |
| 234 | const node = try arena.construct(ast.Node.Use { | |
| 235 | .base = ast.Node {.id = ast.Node.Id.Use }, | |
| 212 | const node = try arena.construct(ast.Node.Use{ | |
| 213 | .base = ast.Node{ .id = ast.Node.Id.Use }, | |
| 236 | 214 | .visib_token = ctx.visib_token, |
| 237 | 215 | .expr = undefined, |
| 238 | 216 | .semicolon_token = undefined, |
| ... | ... | @@ -240,44 +218,39 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 240 | 218 | }); |
| 241 | 219 | try ctx.decls.push(&node.base); |
| 242 | 220 | |
| 243 | stack.append(State { | |
| 244 | .ExpectTokenSave = ExpectTokenSave { | |
| 245 | .id = Token.Id.Semicolon, | |
| 246 | .ptr = &node.semicolon_token, | |
| 247 | } | |
| 248 | }) catch unreachable; | |
| 249 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); | |
| 221 | stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 222 | .id = Token.Id.Semicolon, | |
| 223 | .ptr = &node.semicolon_token, | |
| 224 | } }) catch unreachable; | |
| 225 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 250 | 226 | continue; |
| 251 | 227 | }, |
| 252 | Token.Id.Keyword_var, Token.Id.Keyword_const => { | |
| 228 | Token.Id.Keyword_var, | |
| 229 | Token.Id.Keyword_const => { | |
| 253 | 230 | if (ctx.extern_export_inline_token) |annotated_token| { |
| 254 | 231 | if (annotated_token.ptr.id == Token.Id.Keyword_inline) { |
| 255 | *(try tree.errors.addOne()) = Error { | |
| 256 | .InvalidToken = Error.InvalidToken { .token = annotated_token.index }, | |
| 257 | }; | |
| 232 | ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } }; | |
| 258 | 233 | return tree; |
| 259 | 234 | } |
| 260 | 235 | } |
| 261 | 236 | |
| 262 | try stack.append(State { | |
| 263 | .VarDecl = VarDeclCtx { | |
| 264 | .comments = ctx.comments, | |
| 265 | .visib_token = ctx.visib_token, | |
| 266 | .lib_name = ctx.lib_name, | |
| 267 | .comptime_token = null, | |
| 268 | .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, | |
| 269 | .mut_token = token_index, | |
| 270 | .list = ctx.decls | |
| 271 | } | |
| 272 | }); | |
| 273 | continue; | |
| 274 | }, | |
| 275 | Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, | |
| 276 | Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => { | |
| 277 | const fn_proto = try arena.construct(ast.Node.FnProto { | |
| 278 | .base = ast.Node { | |
| 279 | .id = ast.Node.Id.FnProto, | |
| 280 | }, | |
| 237 | try stack.append(State{ .VarDecl = VarDeclCtx{ | |
| 238 | .comments = ctx.comments, | |
| 239 | .visib_token = ctx.visib_token, | |
| 240 | .lib_name = ctx.lib_name, | |
| 241 | .comptime_token = null, | |
| 242 | .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null, | |
| 243 | .mut_token = token_index, | |
| 244 | .list = ctx.decls, | |
| 245 | } }); | |
| 246 | continue; | |
| 247 | }, | |
| 248 | Token.Id.Keyword_fn, | |
| 249 | Token.Id.Keyword_nakedcc, | |
| 250 | Token.Id.Keyword_stdcallcc, | |
| 251 | Token.Id.Keyword_async => { | |
| 252 | const fn_proto = try arena.construct(ast.Node.FnProto{ | |
| 253 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | |
| 281 | 254 | .doc_comments = ctx.comments, |
| 282 | 255 | .visib_token = ctx.visib_token, |
| 283 | 256 | .name_token = null, |
| ... | ... | @@ -293,36 +266,33 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 293 | 266 | .align_expr = null, |
| 294 | 267 | }); |
| 295 | 268 | try ctx.decls.push(&fn_proto.base); |
| 296 | stack.append(State { .FnDef = fn_proto }) catch unreachable; | |
| 297 | try stack.append(State { .FnProto = fn_proto }); | |
| 269 | stack.append(State{ .FnDef = fn_proto }) catch unreachable; | |
| 270 | try stack.append(State{ .FnProto = fn_proto }); | |
| 298 | 271 | |
| 299 | 272 | switch (token_ptr.id) { |
| 300 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { | |
| 273 | Token.Id.Keyword_nakedcc, | |
| 274 | Token.Id.Keyword_stdcallcc => { | |
| 301 | 275 | fn_proto.cc_token = token_index; |
| 302 | try stack.append(State { | |
| 303 | .ExpectTokenSave = ExpectTokenSave { | |
| 304 | .id = Token.Id.Keyword_fn, | |
| 305 | .ptr = &fn_proto.fn_token, | |
| 306 | } | |
| 307 | }); | |
| 276 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 277 | .id = Token.Id.Keyword_fn, | |
| 278 | .ptr = &fn_proto.fn_token, | |
| 279 | } }); | |
| 308 | 280 | continue; |
| 309 | 281 | }, |
| 310 | 282 | Token.Id.Keyword_async => { |
| 311 | const async_node = try arena.construct(ast.Node.AsyncAttribute { | |
| 312 | .base = ast.Node {.id = ast.Node.Id.AsyncAttribute }, | |
| 283 | const async_node = try arena.construct(ast.Node.AsyncAttribute{ | |
| 284 | .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, | |
| 313 | 285 | .async_token = token_index, |
| 314 | 286 | .allocator_type = null, |
| 315 | 287 | .rangle_bracket = null, |
| 316 | 288 | }); |
| 317 | 289 | fn_proto.async_attr = async_node; |
| 318 | 290 | |
| 319 | try stack.append(State { | |
| 320 | .ExpectTokenSave = ExpectTokenSave { | |
| 321 | .id = Token.Id.Keyword_fn, | |
| 322 | .ptr = &fn_proto.fn_token, | |
| 323 | } | |
| 324 | }); | |
| 325 | try stack.append(State { .AsyncAllocator = async_node }); | |
| 291 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 292 | .id = Token.Id.Keyword_fn, | |
| 293 | .ptr = &fn_proto.fn_token, | |
| 294 | } }); | |
| 295 | try stack.append(State{ .AsyncAllocator = async_node }); | |
| 326 | 296 | continue; |
| 327 | 297 | }, |
| 328 | 298 | Token.Id.Keyword_fn => { |
| ... | ... | @@ -333,9 +303,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 333 | 303 | } |
| 334 | 304 | }, |
| 335 | 305 | else => { |
| 336 | *(try tree.errors.addOne()) = Error { | |
| 337 | .ExpectedVarDeclOrFn = Error.ExpectedVarDeclOrFn { .token = token_index }, | |
| 338 | }; | |
| 306 | ((try tree.errors.addOne())).* = Error{ .ExpectedVarDeclOrFn = Error.ExpectedVarDeclOrFn{ .token = token_index } }; | |
| 339 | 307 | return tree; |
| 340 | 308 | }, |
| 341 | 309 | } |
| ... | ... | @@ -343,34 +311,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 343 | 311 | State.TopLevelExternOrField => |ctx| { |
| 344 | 312 | if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| { |
| 345 | 313 | std.debug.assert(ctx.container_decl.kind == ast.Node.ContainerDecl.Kind.Struct); |
| 346 | const node = try arena.construct(ast.Node.StructField { | |
| 347 | .base = ast.Node { | |
| 348 | .id = ast.Node.Id.StructField, | |
| 349 | }, | |
| 314 | const node = try arena.construct(ast.Node.StructField{ | |
| 315 | .base = ast.Node{ .id = ast.Node.Id.StructField }, | |
| 350 | 316 | .doc_comments = ctx.comments, |
| 351 | 317 | .visib_token = ctx.visib_token, |
| 352 | 318 | .name_token = identifier, |
| 353 | 319 | .type_expr = undefined, |
| 354 | 320 | }); |
| 355 | 321 | const node_ptr = try ctx.container_decl.fields_and_decls.addOne(); |
| 356 | *node_ptr = &node.base; | |
| 322 | node_ptr.* = &node.base; | |
| 357 | 323 | |
| 358 | stack.append(State { .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable; | |
| 359 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.type_expr } }); | |
| 360 | try stack.append(State { .ExpectToken = Token.Id.Colon }); | |
| 324 | stack.append(State{ .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable; | |
| 325 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.type_expr } }); | |
| 326 | try stack.append(State{ .ExpectToken = Token.Id.Colon }); | |
| 361 | 327 | continue; |
| 362 | 328 | } |
| 363 | 329 | |
| 364 | 330 | stack.append(State{ .ContainerDecl = ctx.container_decl }) catch unreachable; |
| 365 | try stack.append(State { | |
| 366 | .TopLevelExtern = TopLevelDeclCtx { | |
| 367 | .decls = &ctx.container_decl.fields_and_decls, | |
| 368 | .visib_token = ctx.visib_token, | |
| 369 | .extern_export_inline_token = null, | |
| 370 | .lib_name = null, | |
| 371 | .comments = ctx.comments, | |
| 372 | } | |
| 373 | }); | |
| 331 | try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ | |
| 332 | .decls = &ctx.container_decl.fields_and_decls, | |
| 333 | .visib_token = ctx.visib_token, | |
| 334 | .extern_export_inline_token = null, | |
| 335 | .lib_name = null, | |
| 336 | .comments = ctx.comments, | |
| 337 | } }); | |
| 374 | 338 | continue; |
| 375 | 339 | }, |
| 376 | 340 | |
| ... | ... | @@ -382,7 +346,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 382 | 346 | putBackToken(&tok_it, &tree); |
| 383 | 347 | continue; |
| 384 | 348 | } |
| 385 | stack.append(State { .Expression = ctx }) catch unreachable; | |
| 349 | stack.append(State{ .Expression = ctx }) catch unreachable; | |
| 386 | 350 | continue; |
| 387 | 351 | }, |
| 388 | 352 | |
| ... | ... | @@ -390,8 +354,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 390 | 354 | const token = nextToken(&tok_it, &tree); |
| 391 | 355 | const token_index = token.index; |
| 392 | 356 | const token_ptr = token.ptr; |
| 393 | const node = try arena.construct(ast.Node.ContainerDecl { | |
| 394 | .base = ast.Node {.id = ast.Node.Id.ContainerDecl }, | |
| 357 | const node = try arena.construct(ast.Node.ContainerDecl{ | |
| 358 | .base = ast.Node{ .id = ast.Node.Id.ContainerDecl }, | |
| 395 | 359 | .ltoken = ctx.ltoken, |
| 396 | 360 | .layout = ctx.layout, |
| 397 | 361 | .kind = switch (token_ptr.id) { |
| ... | ... | @@ -399,9 +363,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 399 | 363 | Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union, |
| 400 | 364 | Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum, |
| 401 | 365 | else => { |
| 402 | *(try tree.errors.addOne()) = Error { | |
| 403 | .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index }, | |
| 404 | }; | |
| 366 | ((try tree.errors.addOne())).* = Error{ .ExpectedAggregateKw = Error.ExpectedAggregateKw{ .token = token_index } }; | |
| 405 | 367 | return tree; |
| 406 | 368 | }, |
| 407 | 369 | }, |
| ... | ... | @@ -411,9 +373,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 411 | 373 | }); |
| 412 | 374 | ctx.opt_ctx.store(&node.base); |
| 413 | 375 | |
| 414 | stack.append(State { .ContainerDecl = node }) catch unreachable; | |
| 415 | try stack.append(State { .ExpectToken = Token.Id.LBrace }); | |
| 416 | try stack.append(State { .ContainerInitArgStart = node }); | |
| 376 | stack.append(State{ .ContainerDecl = node }) catch unreachable; | |
| 377 | try stack.append(State{ .ExpectToken = Token.Id.LBrace }); | |
| 378 | try stack.append(State{ .ContainerInitArgStart = node }); | |
| 417 | 379 | continue; |
| 418 | 380 | }, |
| 419 | 381 | |
| ... | ... | @@ -422,8 +384,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 422 | 384 | continue; |
| 423 | 385 | } |
| 424 | 386 | |
| 425 | stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; | |
| 426 | try stack.append(State { .ContainerInitArg = container_decl }); | |
| 387 | stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable; | |
| 388 | try stack.append(State{ .ContainerInitArg = container_decl }); | |
| 427 | 389 | continue; |
| 428 | 390 | }, |
| 429 | 391 | |
| ... | ... | @@ -433,23 +395,21 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 433 | 395 | const init_arg_token_ptr = init_arg_token.ptr; |
| 434 | 396 | switch (init_arg_token_ptr.id) { |
| 435 | 397 | Token.Id.Keyword_enum => { |
| 436 | container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg {.Enum = null}; | |
| 398 | container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Enum = null }; | |
| 437 | 399 | const lparen_tok = nextToken(&tok_it, &tree); |
| 438 | 400 | const lparen_tok_index = lparen_tok.index; |
| 439 | 401 | const lparen_tok_ptr = lparen_tok.ptr; |
| 440 | 402 | if (lparen_tok_ptr.id == Token.Id.LParen) { |
| 441 | try stack.append(State { .ExpectToken = Token.Id.RParen } ); | |
| 442 | try stack.append(State { .Expression = OptionalCtx { | |
| 443 | .RequiredNull = &container_decl.init_arg_expr.Enum, | |
| 444 | } }); | |
| 403 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 404 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &container_decl.init_arg_expr.Enum } }); | |
| 445 | 405 | } else { |
| 446 | 406 | putBackToken(&tok_it, &tree); |
| 447 | 407 | } |
| 448 | 408 | }, |
| 449 | 409 | else => { |
| 450 | 410 | putBackToken(&tok_it, &tree); |
| 451 | container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg { .Type = undefined }; | |
| 452 | stack.append(State { .Expression = OptionalCtx { .Required = &container_decl.init_arg_expr.Type } }) catch unreachable; | |
| 411 | container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg{ .Type = undefined }; | |
| 412 | stack.append(State{ .Expression = OptionalCtx{ .Required = &container_decl.init_arg_expr.Type } }) catch unreachable; | |
| 453 | 413 | }, |
| 454 | 414 | } |
| 455 | 415 | continue; |
| ... | ... | @@ -468,26 +428,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 468 | 428 | Token.Id.Identifier => { |
| 469 | 429 | switch (container_decl.kind) { |
| 470 | 430 | ast.Node.ContainerDecl.Kind.Struct => { |
| 471 | const node = try arena.construct(ast.Node.StructField { | |
| 472 | .base = ast.Node { | |
| 473 | .id = ast.Node.Id.StructField, | |
| 474 | }, | |
| 431 | const node = try arena.construct(ast.Node.StructField{ | |
| 432 | .base = ast.Node{ .id = ast.Node.Id.StructField }, | |
| 475 | 433 | .doc_comments = comments, |
| 476 | 434 | .visib_token = null, |
| 477 | 435 | .name_token = token_index, |
| 478 | 436 | .type_expr = undefined, |
| 479 | 437 | }); |
| 480 | 438 | const node_ptr = try container_decl.fields_and_decls.addOne(); |
| 481 | *node_ptr = &node.base; | |
| 439 | node_ptr.* = &node.base; | |
| 482 | 440 | |
| 483 | try stack.append(State { .FieldListCommaOrEnd = container_decl }); | |
| 484 | try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.type_expr } }); | |
| 485 | try stack.append(State { .ExpectToken = Token.Id.Colon }); | |
| 441 | try stack.append(State{ .FieldListCommaOrEnd = container_decl }); | |
| 442 | try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.type_expr } }); | |
| 443 | try stack.append(State{ .ExpectToken = Token.Id.Colon }); | |
| 486 | 444 | continue; |
| 487 | 445 | }, |
| 488 | 446 | ast.Node.ContainerDecl.Kind.Union => { |
| 489 | const node = try arena.construct(ast.Node.UnionTag { | |
| 490 | .base = ast.Node {.id = ast.Node.Id.UnionTag }, | |
| 447 | const node = try arena.construct(ast.Node.UnionTag{ | |
| 448 | .base = ast.Node{ .id = ast.Node.Id.UnionTag }, | |
| 491 | 449 | .name_token = token_index, |
| 492 | 450 | .type_expr = null, |
| 493 | 451 | .value_expr = null, |
| ... | ... | @@ -495,24 +453,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 495 | 453 | }); |
| 496 | 454 | try container_decl.fields_and_decls.push(&node.base); |
| 497 | 455 | |
| 498 | stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable; | |
| 499 | try stack.append(State { .FieldInitValue = OptionalCtx { .RequiredNull = &node.value_expr } }); | |
| 500 | try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &node.type_expr } }); | |
| 501 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 456 | stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable; | |
| 457 | try stack.append(State{ .FieldInitValue = OptionalCtx{ .RequiredNull = &node.value_expr } }); | |
| 458 | try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &node.type_expr } }); | |
| 459 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 502 | 460 | continue; |
| 503 | 461 | }, |
| 504 | 462 | ast.Node.ContainerDecl.Kind.Enum => { |
| 505 | const node = try arena.construct(ast.Node.EnumTag { | |
| 506 | .base = ast.Node { .id = ast.Node.Id.EnumTag }, | |
| 463 | const node = try arena.construct(ast.Node.EnumTag{ | |
| 464 | .base = ast.Node{ .id = ast.Node.Id.EnumTag }, | |
| 507 | 465 | .name_token = token_index, |
| 508 | 466 | .value = null, |
| 509 | 467 | .doc_comments = comments, |
| 510 | 468 | }); |
| 511 | 469 | try container_decl.fields_and_decls.push(&node.base); |
| 512 | 470 | |
| 513 | stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable; | |
| 514 | try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &node.value } }); | |
| 515 | try stack.append(State { .IfToken = Token.Id.Equal }); | |
| 471 | stack.append(State{ .FieldListCommaOrEnd = container_decl }) catch unreachable; | |
| 472 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &node.value } }); | |
| 473 | try stack.append(State{ .IfToken = Token.Id.Equal }); | |
| 516 | 474 | continue; |
| 517 | 475 | }, |
| 518 | 476 | } |
| ... | ... | @@ -520,48 +478,40 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 520 | 478 | Token.Id.Keyword_pub => { |
| 521 | 479 | switch (container_decl.kind) { |
| 522 | 480 | ast.Node.ContainerDecl.Kind.Struct => { |
| 523 | try stack.append(State { | |
| 524 | .TopLevelExternOrField = TopLevelExternOrFieldCtx { | |
| 525 | .visib_token = token_index, | |
| 526 | .container_decl = container_decl, | |
| 527 | .comments = comments, | |
| 528 | } | |
| 529 | }); | |
| 481 | try stack.append(State{ .TopLevelExternOrField = TopLevelExternOrFieldCtx{ | |
| 482 | .visib_token = token_index, | |
| 483 | .container_decl = container_decl, | |
| 484 | .comments = comments, | |
| 485 | } }); | |
| 530 | 486 | continue; |
| 531 | 487 | }, |
| 532 | 488 | else => { |
| 533 | 489 | stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; |
| 534 | try stack.append(State { | |
| 535 | .TopLevelExtern = TopLevelDeclCtx { | |
| 536 | .decls = &container_decl.fields_and_decls, | |
| 537 | .visib_token = token_index, | |
| 538 | .extern_export_inline_token = null, | |
| 539 | .lib_name = null, | |
| 540 | .comments = comments, | |
| 541 | } | |
| 542 | }); | |
| 490 | try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ | |
| 491 | .decls = &container_decl.fields_and_decls, | |
| 492 | .visib_token = token_index, | |
| 493 | .extern_export_inline_token = null, | |
| 494 | .lib_name = null, | |
| 495 | .comments = comments, | |
| 496 | } }); | |
| 543 | 497 | continue; |
| 544 | } | |
| 498 | }, | |
| 545 | 499 | } |
| 546 | 500 | }, |
| 547 | 501 | Token.Id.Keyword_export => { |
| 548 | 502 | stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; |
| 549 | try stack.append(State { | |
| 550 | .TopLevelExtern = TopLevelDeclCtx { | |
| 551 | .decls = &container_decl.fields_and_decls, | |
| 552 | .visib_token = token_index, | |
| 553 | .extern_export_inline_token = null, | |
| 554 | .lib_name = null, | |
| 555 | .comments = comments, | |
| 556 | } | |
| 557 | }); | |
| 503 | try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ | |
| 504 | .decls = &container_decl.fields_and_decls, | |
| 505 | .visib_token = token_index, | |
| 506 | .extern_export_inline_token = null, | |
| 507 | .lib_name = null, | |
| 508 | .comments = comments, | |
| 509 | } }); | |
| 558 | 510 | continue; |
| 559 | 511 | }, |
| 560 | 512 | Token.Id.RBrace => { |
| 561 | 513 | if (comments != null) { |
| 562 | *(try tree.errors.addOne()) = Error { | |
| 563 | .UnattachedDocComment = Error.UnattachedDocComment { .token = token_index }, | |
| 564 | }; | |
| 514 | ((try tree.errors.addOne())).* = Error{ .UnattachedDocComment = Error.UnattachedDocComment{ .token = token_index } }; | |
| 565 | 515 | return tree; |
| 566 | 516 | } |
| 567 | 517 | container_decl.rbrace_token = token_index; |
| ... | ... | @@ -570,26 +520,21 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 570 | 520 | else => { |
| 571 | 521 | putBackToken(&tok_it, &tree); |
| 572 | 522 | stack.append(State{ .ContainerDecl = container_decl }) catch unreachable; |
| 573 | try stack.append(State { | |
| 574 | .TopLevelExtern = TopLevelDeclCtx { | |
| 575 | .decls = &container_decl.fields_and_decls, | |
| 576 | .visib_token = null, | |
| 577 | .extern_export_inline_token = null, | |
| 578 | .lib_name = null, | |
| 579 | .comments = comments, | |
| 580 | } | |
| 581 | }); | |
| 523 | try stack.append(State{ .TopLevelExtern = TopLevelDeclCtx{ | |
| 524 | .decls = &container_decl.fields_and_decls, | |
| 525 | .visib_token = null, | |
| 526 | .extern_export_inline_token = null, | |
| 527 | .lib_name = null, | |
| 528 | .comments = comments, | |
| 529 | } }); | |
| 582 | 530 | continue; |
| 583 | } | |
| 531 | }, | |
| 584 | 532 | } |
| 585 | 533 | }, |
| 586 | 534 | |
| 587 | ||
| 588 | 535 | State.VarDecl => |ctx| { |
| 589 | const var_decl = try arena.construct(ast.Node.VarDecl { | |
| 590 | .base = ast.Node { | |
| 591 | .id = ast.Node.Id.VarDecl, | |
| 592 | }, | |
| 536 | const var_decl = try arena.construct(ast.Node.VarDecl{ | |
| 537 | .base = ast.Node{ .id = ast.Node.Id.VarDecl }, | |
| 593 | 538 | .doc_comments = ctx.comments, |
| 594 | 539 | .visib_token = ctx.visib_token, |
| 595 | 540 | .mut_token = ctx.mut_token, |
| ... | ... | @@ -606,27 +551,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 606 | 551 | }); |
| 607 | 552 | try ctx.list.push(&var_decl.base); |
| 608 | 553 | |
| 609 | try stack.append(State { .VarDeclAlign = var_decl }); | |
| 610 | try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} }); | |
| 611 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 612 | try stack.append(State { | |
| 613 | .ExpectTokenSave = ExpectTokenSave { | |
| 614 | .id = Token.Id.Identifier, | |
| 615 | .ptr = &var_decl.name_token, | |
| 616 | } | |
| 617 | }); | |
| 554 | try stack.append(State{ .VarDeclAlign = var_decl }); | |
| 555 | try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &var_decl.type_node } }); | |
| 556 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 557 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 558 | .id = Token.Id.Identifier, | |
| 559 | .ptr = &var_decl.name_token, | |
| 560 | } }); | |
| 618 | 561 | continue; |
| 619 | 562 | }, |
| 620 | 563 | State.VarDeclAlign => |var_decl| { |
| 621 | try stack.append(State { .VarDeclEq = var_decl }); | |
| 564 | try stack.append(State{ .VarDeclEq = var_decl }); | |
| 622 | 565 | |
| 623 | 566 | const next_token = nextToken(&tok_it, &tree); |
| 624 | 567 | const next_token_index = next_token.index; |
| 625 | 568 | const next_token_ptr = next_token.ptr; |
| 626 | 569 | if (next_token_ptr.id == Token.Id.Keyword_align) { |
| 627 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 628 | try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.align_node} }); | |
| 629 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 570 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 571 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.align_node } }); | |
| 572 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 630 | 573 | continue; |
| 631 | 574 | } |
| 632 | 575 | |
| ... | ... | @@ -640,8 +583,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 640 | 583 | switch (token_ptr.id) { |
| 641 | 584 | Token.Id.Equal => { |
| 642 | 585 | var_decl.eq_token = token_index; |
| 643 | stack.append(State { .VarDeclSemiColon = var_decl }) catch unreachable; | |
| 644 | try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } }); | |
| 586 | stack.append(State{ .VarDeclSemiColon = var_decl }) catch unreachable; | |
| 587 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &var_decl.init_node } }); | |
| 645 | 588 | continue; |
| 646 | 589 | }, |
| 647 | 590 | Token.Id.Semicolon => { |
| ... | ... | @@ -649,11 +592,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 649 | 592 | continue; |
| 650 | 593 | }, |
| 651 | 594 | else => { |
| 652 | *(try tree.errors.addOne()) = Error { | |
| 653 | .ExpectedEqOrSemi = Error.ExpectedEqOrSemi { .token = token_index }, | |
| 654 | }; | |
| 595 | ((try tree.errors.addOne())).* = Error{ .ExpectedEqOrSemi = Error.ExpectedEqOrSemi{ .token = token_index } }; | |
| 655 | 596 | return tree; |
| 656 | } | |
| 597 | }, | |
| 657 | 598 | } |
| 658 | 599 | }, |
| 659 | 600 | |
| ... | ... | @@ -661,12 +602,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 661 | 602 | const semicolon_token = nextToken(&tok_it, &tree); |
| 662 | 603 | |
| 663 | 604 | if (semicolon_token.ptr.id != Token.Id.Semicolon) { |
| 664 | *(try tree.errors.addOne()) = Error { | |
| 665 | .ExpectedToken = Error.ExpectedToken { | |
| 666 | .token = semicolon_token.index, | |
| 667 | .expected_id = Token.Id.Semicolon, | |
| 668 | }, | |
| 669 | }; | |
| 605 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 606 | .token = semicolon_token.index, | |
| 607 | .expected_id = Token.Id.Semicolon, | |
| 608 | } }; | |
| 670 | 609 | return tree; |
| 671 | 610 | } |
| 672 | 611 | |
| ... | ... | @@ -686,32 +625,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 686 | 625 | const token = nextToken(&tok_it, &tree); |
| 687 | 626 | const token_index = token.index; |
| 688 | 627 | const token_ptr = token.ptr; |
| 689 | switch(token_ptr.id) { | |
| 628 | switch (token_ptr.id) { | |
| 690 | 629 | Token.Id.LBrace => { |
| 691 | const block = try arena.construct(ast.Node.Block { | |
| 692 | .base = ast.Node { .id = ast.Node.Id.Block }, | |
| 630 | const block = try arena.construct(ast.Node.Block{ | |
| 631 | .base = ast.Node{ .id = ast.Node.Id.Block }, | |
| 693 | 632 | .label = null, |
| 694 | 633 | .lbrace = token_index, |
| 695 | 634 | .statements = ast.Node.Block.StatementList.init(arena), |
| 696 | 635 | .rbrace = undefined, |
| 697 | 636 | }); |
| 698 | 637 | fn_proto.body_node = &block.base; |
| 699 | stack.append(State { .Block = block }) catch unreachable; | |
| 638 | stack.append(State{ .Block = block }) catch unreachable; | |
| 700 | 639 | continue; |
| 701 | 640 | }, |
| 702 | 641 | Token.Id.Semicolon => continue, |
| 703 | 642 | else => { |
| 704 | *(try tree.errors.addOne()) = Error { | |
| 705 | .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace { .token = token_index }, | |
| 706 | }; | |
| 643 | ((try tree.errors.addOne())).* = Error{ .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace{ .token = token_index } }; | |
| 707 | 644 | return tree; |
| 708 | 645 | }, |
| 709 | 646 | } |
| 710 | 647 | }, |
| 711 | 648 | State.FnProto => |fn_proto| { |
| 712 | stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable; | |
| 713 | try stack.append(State { .ParamDecl = fn_proto }); | |
| 714 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 649 | stack.append(State{ .FnProtoAlign = fn_proto }) catch unreachable; | |
| 650 | try stack.append(State{ .ParamDecl = fn_proto }); | |
| 651 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 715 | 652 | |
| 716 | 653 | if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |name_token| { |
| 717 | 654 | fn_proto.name_token = name_token; |
| ... | ... | @@ -719,12 +656,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 719 | 656 | continue; |
| 720 | 657 | }, |
| 721 | 658 | State.FnProtoAlign => |fn_proto| { |
| 722 | stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable; | |
| 659 | stack.append(State{ .FnProtoReturnType = fn_proto }) catch unreachable; | |
| 723 | 660 | |
| 724 | 661 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_align)) |align_token| { |
| 725 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 726 | try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } }); | |
| 727 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 662 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 663 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &fn_proto.align_expr } }); | |
| 664 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 728 | 665 | } |
| 729 | 666 | continue; |
| 730 | 667 | }, |
| ... | ... | @@ -734,42 +671,37 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 734 | 671 | const token_ptr = token.ptr; |
| 735 | 672 | switch (token_ptr.id) { |
| 736 | 673 | Token.Id.Bang => { |
| 737 | fn_proto.return_type = ast.Node.FnProto.ReturnType { .InferErrorSet = undefined }; | |
| 738 | stack.append(State { | |
| 739 | .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.InferErrorSet }, | |
| 740 | }) catch unreachable; | |
| 674 | fn_proto.return_type = ast.Node.FnProto.ReturnType{ .InferErrorSet = undefined }; | |
| 675 | stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.InferErrorSet } }) catch unreachable; | |
| 741 | 676 | continue; |
| 742 | 677 | }, |
| 743 | 678 | else => { |
| 744 | 679 | // TODO: this is a special case. Remove this when #760 is fixed |
| 745 | 680 | if (token_ptr.id == Token.Id.Keyword_error) { |
| 746 | 681 | if ((??tok_it.peek()).id == Token.Id.LBrace) { |
| 747 | const error_type_node = try arena.construct(ast.Node.ErrorType { | |
| 748 | .base = ast.Node { .id = ast.Node.Id.ErrorType }, | |
| 682 | const error_type_node = try arena.construct(ast.Node.ErrorType{ | |
| 683 | .base = ast.Node{ .id = ast.Node.Id.ErrorType }, | |
| 749 | 684 | .token = token_index, |
| 750 | 685 | }); |
| 751 | fn_proto.return_type = ast.Node.FnProto.ReturnType { | |
| 752 | .Explicit = &error_type_node.base, | |
| 753 | }; | |
| 686 | fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base }; | |
| 754 | 687 | continue; |
| 755 | 688 | } |
| 756 | 689 | } |
| 757 | 690 | |
| 758 | 691 | putBackToken(&tok_it, &tree); |
| 759 | fn_proto.return_type = ast.Node.FnProto.ReturnType { .Explicit = undefined }; | |
| 760 | stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.Explicit }, }) catch unreachable; | |
| 692 | fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = undefined }; | |
| 693 | stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &fn_proto.return_type.Explicit } }) catch unreachable; | |
| 761 | 694 | continue; |
| 762 | 695 | }, |
| 763 | 696 | } |
| 764 | 697 | }, |
| 765 | 698 | |
| 766 | ||
| 767 | 699 | State.ParamDecl => |fn_proto| { |
| 768 | 700 | if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| { |
| 769 | 701 | continue; |
| 770 | 702 | } |
| 771 | const param_decl = try arena.construct(ast.Node.ParamDecl { | |
| 772 | .base = ast.Node {.id = ast.Node.Id.ParamDecl }, | |
| 703 | const param_decl = try arena.construct(ast.Node.ParamDecl{ | |
| 704 | .base = ast.Node{ .id = ast.Node.Id.ParamDecl }, | |
| 773 | 705 | .comptime_token = null, |
| 774 | 706 | .noalias_token = null, |
| 775 | 707 | .name_token = null, |
| ... | ... | @@ -778,14 +710,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 778 | 710 | }); |
| 779 | 711 | try fn_proto.params.push(&param_decl.base); |
| 780 | 712 | |
| 781 | stack.append(State { | |
| 782 | .ParamDeclEnd = ParamDeclEndCtx { | |
| 783 | .param_decl = param_decl, | |
| 784 | .fn_proto = fn_proto, | |
| 785 | } | |
| 786 | }) catch unreachable; | |
| 787 | try stack.append(State { .ParamDeclName = param_decl }); | |
| 788 | try stack.append(State { .ParamDeclAliasOrComptime = param_decl }); | |
| 713 | stack.append(State{ .ParamDeclEnd = ParamDeclEndCtx{ | |
| 714 | .param_decl = param_decl, | |
| 715 | .fn_proto = fn_proto, | |
| 716 | } }) catch unreachable; | |
| 717 | try stack.append(State{ .ParamDeclName = param_decl }); | |
| 718 | try stack.append(State{ .ParamDeclAliasOrComptime = param_decl }); | |
| 789 | 719 | continue; |
| 790 | 720 | }, |
| 791 | 721 | State.ParamDeclAliasOrComptime => |param_decl| { |
| ... | ... | @@ -811,21 +741,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 811 | 741 | State.ParamDeclEnd => |ctx| { |
| 812 | 742 | if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { |
| 813 | 743 | ctx.param_decl.var_args_token = ellipsis3; |
| 814 | stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; | |
| 744 | stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable; | |
| 815 | 745 | continue; |
| 816 | 746 | } |
| 817 | 747 | |
| 818 | try stack.append(State { .ParamDeclComma = ctx.fn_proto }); | |
| 819 | try stack.append(State { | |
| 820 | .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node } | |
| 821 | }); | |
| 748 | try stack.append(State{ .ParamDeclComma = ctx.fn_proto }); | |
| 749 | try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &ctx.param_decl.type_node } }); | |
| 822 | 750 | continue; |
| 823 | 751 | }, |
| 824 | 752 | State.ParamDeclComma => |fn_proto| { |
| 825 | 753 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) { |
| 826 | 754 | ExpectCommaOrEndResult.end_token => |t| { |
| 827 | 755 | if (t == null) { |
| 828 | stack.append(State { .ParamDecl = fn_proto }) catch unreachable; | |
| 756 | stack.append(State{ .ParamDecl = fn_proto }) catch unreachable; | |
| 829 | 757 | } |
| 830 | 758 | continue; |
| 831 | 759 | }, |
| ... | ... | @@ -838,12 +766,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 838 | 766 | |
| 839 | 767 | State.MaybeLabeledExpression => |ctx| { |
| 840 | 768 | if (eatToken(&tok_it, &tree, Token.Id.Colon)) |_| { |
| 841 | stack.append(State { | |
| 842 | .LabeledExpression = LabelCtx { | |
| 843 | .label = ctx.label, | |
| 844 | .opt_ctx = ctx.opt_ctx, | |
| 845 | } | |
| 846 | }) catch unreachable; | |
| 769 | stack.append(State{ .LabeledExpression = LabelCtx{ | |
| 770 | .label = ctx.label, | |
| 771 | .opt_ctx = ctx.opt_ctx, | |
| 772 | } }) catch unreachable; | |
| 847 | 773 | continue; |
| 848 | 774 | } |
| 849 | 775 | |
| ... | ... | @@ -856,69 +782,59 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 856 | 782 | const token_ptr = token.ptr; |
| 857 | 783 | switch (token_ptr.id) { |
| 858 | 784 | Token.Id.LBrace => { |
| 859 | const block = try arena.construct(ast.Node.Block { | |
| 860 | .base = ast.Node {.id = ast.Node.Id.Block}, | |
| 785 | const block = try arena.construct(ast.Node.Block{ | |
| 786 | .base = ast.Node{ .id = ast.Node.Id.Block }, | |
| 861 | 787 | .label = ctx.label, |
| 862 | 788 | .lbrace = token_index, |
| 863 | 789 | .statements = ast.Node.Block.StatementList.init(arena), |
| 864 | 790 | .rbrace = undefined, |
| 865 | 791 | }); |
| 866 | 792 | ctx.opt_ctx.store(&block.base); |
| 867 | stack.append(State { .Block = block }) catch unreachable; | |
| 793 | stack.append(State{ .Block = block }) catch unreachable; | |
| 868 | 794 | continue; |
| 869 | 795 | }, |
| 870 | 796 | Token.Id.Keyword_while => { |
| 871 | stack.append(State { | |
| 872 | .While = LoopCtx { | |
| 873 | .label = ctx.label, | |
| 874 | .inline_token = null, | |
| 875 | .loop_token = token_index, | |
| 876 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 877 | } | |
| 878 | }) catch unreachable; | |
| 797 | stack.append(State{ .While = LoopCtx{ | |
| 798 | .label = ctx.label, | |
| 799 | .inline_token = null, | |
| 800 | .loop_token = token_index, | |
| 801 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 802 | } }) catch unreachable; | |
| 879 | 803 | continue; |
| 880 | 804 | }, |
| 881 | 805 | Token.Id.Keyword_for => { |
| 882 | stack.append(State { | |
| 883 | .For = LoopCtx { | |
| 884 | .label = ctx.label, | |
| 885 | .inline_token = null, | |
| 886 | .loop_token = token_index, | |
| 887 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 888 | } | |
| 889 | }) catch unreachable; | |
| 806 | stack.append(State{ .For = LoopCtx{ | |
| 807 | .label = ctx.label, | |
| 808 | .inline_token = null, | |
| 809 | .loop_token = token_index, | |
| 810 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 811 | } }) catch unreachable; | |
| 890 | 812 | continue; |
| 891 | 813 | }, |
| 892 | 814 | Token.Id.Keyword_suspend => { |
| 893 | const node = try arena.construct(ast.Node.Suspend { | |
| 894 | .base = ast.Node { | |
| 895 | .id = ast.Node.Id.Suspend, | |
| 896 | }, | |
| 815 | const node = try arena.construct(ast.Node.Suspend{ | |
| 816 | .base = ast.Node{ .id = ast.Node.Id.Suspend }, | |
| 897 | 817 | .label = ctx.label, |
| 898 | 818 | .suspend_token = token_index, |
| 899 | 819 | .payload = null, |
| 900 | 820 | .body = null, |
| 901 | 821 | }); |
| 902 | 822 | ctx.opt_ctx.store(&node.base); |
| 903 | stack.append(State { .SuspendBody = node }) catch unreachable; | |
| 904 | try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); | |
| 823 | stack.append(State{ .SuspendBody = node }) catch unreachable; | |
| 824 | try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); | |
| 905 | 825 | continue; |
| 906 | 826 | }, |
| 907 | 827 | Token.Id.Keyword_inline => { |
| 908 | stack.append(State { | |
| 909 | .Inline = InlineCtx { | |
| 910 | .label = ctx.label, | |
| 911 | .inline_token = token_index, | |
| 912 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 913 | } | |
| 914 | }) catch unreachable; | |
| 828 | stack.append(State{ .Inline = InlineCtx{ | |
| 829 | .label = ctx.label, | |
| 830 | .inline_token = token_index, | |
| 831 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 832 | } }) catch unreachable; | |
| 915 | 833 | continue; |
| 916 | 834 | }, |
| 917 | 835 | else => { |
| 918 | 836 | if (ctx.opt_ctx != OptionalCtx.Optional) { |
| 919 | *(try tree.errors.addOne()) = Error { | |
| 920 | .ExpectedLabelable = Error.ExpectedLabelable { .token = token_index }, | |
| 921 | }; | |
| 837 | ((try tree.errors.addOne())).* = Error{ .ExpectedLabelable = Error.ExpectedLabelable{ .token = token_index } }; | |
| 922 | 838 | return tree; |
| 923 | 839 | } |
| 924 | 840 | |
| ... | ... | @@ -933,32 +849,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 933 | 849 | const token_ptr = token.ptr; |
| 934 | 850 | switch (token_ptr.id) { |
| 935 | 851 | Token.Id.Keyword_while => { |
| 936 | stack.append(State { | |
| 937 | .While = LoopCtx { | |
| 938 | .inline_token = ctx.inline_token, | |
| 939 | .label = ctx.label, | |
| 940 | .loop_token = token_index, | |
| 941 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 942 | } | |
| 943 | }) catch unreachable; | |
| 852 | stack.append(State{ .While = LoopCtx{ | |
| 853 | .inline_token = ctx.inline_token, | |
| 854 | .label = ctx.label, | |
| 855 | .loop_token = token_index, | |
| 856 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 857 | } }) catch unreachable; | |
| 944 | 858 | continue; |
| 945 | 859 | }, |
| 946 | 860 | Token.Id.Keyword_for => { |
| 947 | stack.append(State { | |
| 948 | .For = LoopCtx { | |
| 949 | .inline_token = ctx.inline_token, | |
| 950 | .label = ctx.label, | |
| 951 | .loop_token = token_index, | |
| 952 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 953 | } | |
| 954 | }) catch unreachable; | |
| 861 | stack.append(State{ .For = LoopCtx{ | |
| 862 | .inline_token = ctx.inline_token, | |
| 863 | .label = ctx.label, | |
| 864 | .loop_token = token_index, | |
| 865 | .opt_ctx = ctx.opt_ctx.toRequired(), | |
| 866 | } }) catch unreachable; | |
| 955 | 867 | continue; |
| 956 | 868 | }, |
| 957 | 869 | else => { |
| 958 | 870 | if (ctx.opt_ctx != OptionalCtx.Optional) { |
| 959 | *(try tree.errors.addOne()) = Error { | |
| 960 | .ExpectedInlinable = Error.ExpectedInlinable { .token = token_index }, | |
| 961 | }; | |
| 871 | ((try tree.errors.addOne())).* = Error{ .ExpectedInlinable = Error.ExpectedInlinable{ .token = token_index } }; | |
| 962 | 872 | return tree; |
| 963 | 873 | } |
| 964 | 874 | |
| ... | ... | @@ -968,8 +878,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 968 | 878 | } |
| 969 | 879 | }, |
| 970 | 880 | State.While => |ctx| { |
| 971 | const node = try arena.construct(ast.Node.While { | |
| 972 | .base = ast.Node {.id = ast.Node.Id.While }, | |
| 881 | const node = try arena.construct(ast.Node.While{ | |
| 882 | .base = ast.Node{ .id = ast.Node.Id.While }, | |
| 973 | 883 | .label = ctx.label, |
| 974 | 884 | .inline_token = ctx.inline_token, |
| 975 | 885 | .while_token = ctx.loop_token, |
| ... | ... | @@ -980,25 +890,25 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 980 | 890 | .@"else" = null, |
| 981 | 891 | }); |
| 982 | 892 | ctx.opt_ctx.store(&node.base); |
| 983 | stack.append(State { .Else = &node.@"else" }) catch unreachable; | |
| 984 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); | |
| 985 | try stack.append(State { .WhileContinueExpr = &node.continue_expr }); | |
| 986 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 987 | try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); | |
| 988 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 989 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } }); | |
| 990 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 893 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; | |
| 894 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); | |
| 895 | try stack.append(State{ .WhileContinueExpr = &node.continue_expr }); | |
| 896 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 897 | try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); | |
| 898 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 899 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.condition } }); | |
| 900 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 991 | 901 | continue; |
| 992 | 902 | }, |
| 993 | 903 | State.WhileContinueExpr => |dest| { |
| 994 | stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable; | |
| 995 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } }); | |
| 996 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 904 | stack.append(State{ .ExpectToken = Token.Id.RParen }) catch unreachable; | |
| 905 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = dest } }); | |
| 906 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 997 | 907 | continue; |
| 998 | 908 | }, |
| 999 | 909 | State.For => |ctx| { |
| 1000 | const node = try arena.construct(ast.Node.For { | |
| 1001 | .base = ast.Node {.id = ast.Node.Id.For }, | |
| 910 | const node = try arena.construct(ast.Node.For{ | |
| 911 | .base = ast.Node{ .id = ast.Node.Id.For }, | |
| 1002 | 912 | .label = ctx.label, |
| 1003 | 913 | .inline_token = ctx.inline_token, |
| 1004 | 914 | .for_token = ctx.loop_token, |
| ... | ... | @@ -1008,12 +918,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1008 | 918 | .@"else" = null, |
| 1009 | 919 | }); |
| 1010 | 920 | ctx.opt_ctx.store(&node.base); |
| 1011 | stack.append(State { .Else = &node.@"else" }) catch unreachable; | |
| 1012 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); | |
| 1013 | try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } }); | |
| 1014 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 1015 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } }); | |
| 1016 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 921 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; | |
| 922 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); | |
| 923 | try stack.append(State{ .PointerIndexPayload = OptionalCtx{ .Optional = &node.payload } }); | |
| 924 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 925 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.array_expr } }); | |
| 926 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 1017 | 927 | continue; |
| 1018 | 928 | }, |
| 1019 | 929 | State.Else => |dest| { |
| ... | ... | @@ -1023,16 +933,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1023 | 933 | need_index_restore = true; |
| 1024 | 934 | } |
| 1025 | 935 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| { |
| 1026 | const node = try arena.construct(ast.Node.Else { | |
| 1027 | .base = ast.Node {.id = ast.Node.Id.Else }, | |
| 936 | const node = try arena.construct(ast.Node.Else{ | |
| 937 | .base = ast.Node{ .id = ast.Node.Id.Else }, | |
| 1028 | 938 | .else_token = else_token, |
| 1029 | 939 | .payload = null, |
| 1030 | 940 | .body = undefined, |
| 1031 | 941 | }); |
| 1032 | *dest = node; | |
| 942 | dest.* = node; | |
| 1033 | 943 | |
| 1034 | stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable; | |
| 1035 | try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); | |
| 944 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable; | |
| 945 | try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); | |
| 1036 | 946 | continue; |
| 1037 | 947 | } else { |
| 1038 | 948 | if (need_index_restore) { |
| ... | ... | @@ -1042,7 +952,6 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1042 | 952 | } |
| 1043 | 953 | }, |
| 1044 | 954 | |
| 1045 | ||
| 1046 | 955 | State.Block => |block| { |
| 1047 | 956 | const token = nextToken(&tok_it, &tree); |
| 1048 | 957 | const token_index = token.index; |
| ... | ... | @@ -1054,7 +963,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1054 | 963 | }, |
| 1055 | 964 | else => { |
| 1056 | 965 | putBackToken(&tok_it, &tree); |
| 1057 | stack.append(State { .Block = block }) catch unreachable; | |
| 966 | stack.append(State{ .Block = block }) catch unreachable; | |
| 1058 | 967 | |
| 1059 | 968 | var any_comments = false; |
| 1060 | 969 | while (try eatLineComment(arena, &tok_it, &tree)) |line_comment| { |
| ... | ... | @@ -1063,7 +972,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1063 | 972 | } |
| 1064 | 973 | if (any_comments) continue; |
| 1065 | 974 | |
| 1066 | try stack.append(State { .Statement = block }); | |
| 975 | try stack.append(State{ .Statement = block }); | |
| 1067 | 976 | continue; |
| 1068 | 977 | }, |
| 1069 | 978 | } |
| ... | ... | @@ -1074,33 +983,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1074 | 983 | const token_ptr = token.ptr; |
| 1075 | 984 | switch (token_ptr.id) { |
| 1076 | 985 | Token.Id.Keyword_comptime => { |
| 1077 | stack.append(State { | |
| 1078 | .ComptimeStatement = ComptimeStatementCtx { | |
| 1079 | .comptime_token = token_index, | |
| 1080 | .block = block, | |
| 1081 | } | |
| 1082 | }) catch unreachable; | |
| 1083 | continue; | |
| 1084 | }, | |
| 1085 | Token.Id.Keyword_var, Token.Id.Keyword_const => { | |
| 1086 | stack.append(State { | |
| 1087 | .VarDecl = VarDeclCtx { | |
| 1088 | .comments = null, | |
| 1089 | .visib_token = null, | |
| 1090 | .comptime_token = null, | |
| 1091 | .extern_export_token = null, | |
| 1092 | .lib_name = null, | |
| 1093 | .mut_token = token_index, | |
| 1094 | .list = &block.statements, | |
| 1095 | } | |
| 1096 | }) catch unreachable; | |
| 986 | stack.append(State{ .ComptimeStatement = ComptimeStatementCtx{ | |
| 987 | .comptime_token = token_index, | |
| 988 | .block = block, | |
| 989 | } }) catch unreachable; | |
| 1097 | 990 | continue; |
| 1098 | 991 | }, |
| 1099 | Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => { | |
| 1100 | const node = try arena.construct(ast.Node.Defer { | |
| 1101 | .base = ast.Node { | |
| 1102 | .id = ast.Node.Id.Defer, | |
| 1103 | }, | |
| 992 | Token.Id.Keyword_var, | |
| 993 | Token.Id.Keyword_const => { | |
| 994 | stack.append(State{ .VarDecl = VarDeclCtx{ | |
| 995 | .comments = null, | |
| 996 | .visib_token = null, | |
| 997 | .comptime_token = null, | |
| 998 | .extern_export_token = null, | |
| 999 | .lib_name = null, | |
| 1000 | .mut_token = token_index, | |
| 1001 | .list = &block.statements, | |
| 1002 | } }) catch unreachable; | |
| 1003 | continue; | |
| 1004 | }, | |
| 1005 | Token.Id.Keyword_defer, | |
| 1006 | Token.Id.Keyword_errdefer => { | |
| 1007 | const node = try arena.construct(ast.Node.Defer{ | |
| 1008 | .base = ast.Node{ .id = ast.Node.Id.Defer }, | |
| 1104 | 1009 | .defer_token = token_index, |
| 1105 | 1010 | .kind = switch (token_ptr.id) { |
| 1106 | 1011 | Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional, |
| ... | ... | @@ -1110,15 +1015,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1110 | 1015 | .expr = undefined, |
| 1111 | 1016 | }); |
| 1112 | 1017 | const node_ptr = try block.statements.addOne(); |
| 1113 | *node_ptr = &node.base; | |
| 1018 | node_ptr.* = &node.base; | |
| 1114 | 1019 | |
| 1115 | stack.append(State { .Semicolon = node_ptr }) catch unreachable; | |
| 1116 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); | |
| 1020 | stack.append(State{ .Semicolon = node_ptr }) catch unreachable; | |
| 1021 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); | |
| 1117 | 1022 | continue; |
| 1118 | 1023 | }, |
| 1119 | 1024 | Token.Id.LBrace => { |
| 1120 | const inner_block = try arena.construct(ast.Node.Block { | |
| 1121 | .base = ast.Node { .id = ast.Node.Id.Block }, | |
| 1025 | const inner_block = try arena.construct(ast.Node.Block{ | |
| 1026 | .base = ast.Node{ .id = ast.Node.Id.Block }, | |
| 1122 | 1027 | .label = null, |
| 1123 | 1028 | .lbrace = token_index, |
| 1124 | 1029 | .statements = ast.Node.Block.StatementList.init(arena), |
| ... | ... | @@ -1126,16 +1031,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1126 | 1031 | }); |
| 1127 | 1032 | try block.statements.push(&inner_block.base); |
| 1128 | 1033 | |
| 1129 | stack.append(State { .Block = inner_block }) catch unreachable; | |
| 1034 | stack.append(State{ .Block = inner_block }) catch unreachable; | |
| 1130 | 1035 | continue; |
| 1131 | 1036 | }, |
| 1132 | 1037 | else => { |
| 1133 | 1038 | putBackToken(&tok_it, &tree); |
| 1134 | 1039 | const statement = try block.statements.addOne(); |
| 1135 | try stack.append(State { .Semicolon = statement }); | |
| 1136 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } }); | |
| 1040 | try stack.append(State{ .Semicolon = statement }); | |
| 1041 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = statement } }); | |
| 1137 | 1042 | continue; |
| 1138 | } | |
| 1043 | }, | |
| 1139 | 1044 | } |
| 1140 | 1045 | }, |
| 1141 | 1046 | State.ComptimeStatement => |ctx| { |
| ... | ... | @@ -1143,34 +1048,33 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1143 | 1048 | const token_index = token.index; |
| 1144 | 1049 | const token_ptr = token.ptr; |
| 1145 | 1050 | switch (token_ptr.id) { |
| 1146 | Token.Id.Keyword_var, Token.Id.Keyword_const => { | |
| 1147 | stack.append(State { | |
| 1148 | .VarDecl = VarDeclCtx { | |
| 1149 | .comments = null, | |
| 1150 | .visib_token = null, | |
| 1151 | .comptime_token = ctx.comptime_token, | |
| 1152 | .extern_export_token = null, | |
| 1153 | .lib_name = null, | |
| 1154 | .mut_token = token_index, | |
| 1155 | .list = &ctx.block.statements, | |
| 1156 | } | |
| 1157 | }) catch unreachable; | |
| 1051 | Token.Id.Keyword_var, | |
| 1052 | Token.Id.Keyword_const => { | |
| 1053 | stack.append(State{ .VarDecl = VarDeclCtx{ | |
| 1054 | .comments = null, | |
| 1055 | .visib_token = null, | |
| 1056 | .comptime_token = ctx.comptime_token, | |
| 1057 | .extern_export_token = null, | |
| 1058 | .lib_name = null, | |
| 1059 | .mut_token = token_index, | |
| 1060 | .list = &ctx.block.statements, | |
| 1061 | } }) catch unreachable; | |
| 1158 | 1062 | continue; |
| 1159 | 1063 | }, |
| 1160 | 1064 | else => { |
| 1161 | 1065 | putBackToken(&tok_it, &tree); |
| 1162 | 1066 | putBackToken(&tok_it, &tree); |
| 1163 | 1067 | const statement = try ctx.block.statements.addOne(); |
| 1164 | try stack.append(State { .Semicolon = statement }); | |
| 1165 | try stack.append(State { .Expression = OptionalCtx { .Required = statement } }); | |
| 1068 | try stack.append(State{ .Semicolon = statement }); | |
| 1069 | try stack.append(State{ .Expression = OptionalCtx{ .Required = statement } }); | |
| 1166 | 1070 | continue; |
| 1167 | } | |
| 1071 | }, | |
| 1168 | 1072 | } |
| 1169 | 1073 | }, |
| 1170 | 1074 | State.Semicolon => |node_ptr| { |
| 1171 | const node = *node_ptr; | |
| 1075 | const node = node_ptr.*; | |
| 1172 | 1076 | if (node.requireSemiColon()) { |
| 1173 | stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable; | |
| 1077 | stack.append(State{ .ExpectToken = Token.Id.Semicolon }) catch unreachable; | |
| 1174 | 1078 | continue; |
| 1175 | 1079 | } |
| 1176 | 1080 | continue; |
| ... | ... | @@ -1185,22 +1089,22 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1185 | 1089 | continue; |
| 1186 | 1090 | } |
| 1187 | 1091 | |
| 1188 | const node = try arena.construct(ast.Node.AsmOutput { | |
| 1189 | .base = ast.Node {.id = ast.Node.Id.AsmOutput }, | |
| 1092 | const node = try arena.construct(ast.Node.AsmOutput{ | |
| 1093 | .base = ast.Node{ .id = ast.Node.Id.AsmOutput }, | |
| 1190 | 1094 | .symbolic_name = undefined, |
| 1191 | 1095 | .constraint = undefined, |
| 1192 | 1096 | .kind = undefined, |
| 1193 | 1097 | }); |
| 1194 | 1098 | try items.push(node); |
| 1195 | 1099 | |
| 1196 | stack.append(State { .AsmOutputItems = items }) catch unreachable; | |
| 1197 | try stack.append(State { .IfToken = Token.Id.Comma }); | |
| 1198 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 1199 | try stack.append(State { .AsmOutputReturnOrType = node }); | |
| 1200 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 1201 | try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } }); | |
| 1202 | try stack.append(State { .ExpectToken = Token.Id.RBracket }); | |
| 1203 | try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } }); | |
| 1100 | stack.append(State{ .AsmOutputItems = items }) catch unreachable; | |
| 1101 | try stack.append(State{ .IfToken = Token.Id.Comma }); | |
| 1102 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 1103 | try stack.append(State{ .AsmOutputReturnOrType = node }); | |
| 1104 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 1105 | try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } }); | |
| 1106 | try stack.append(State{ .ExpectToken = Token.Id.RBracket }); | |
| 1107 | try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.symbolic_name } }); | |
| 1204 | 1108 | continue; |
| 1205 | 1109 | }, |
| 1206 | 1110 | State.AsmOutputReturnOrType => |node| { |
| ... | ... | @@ -1209,20 +1113,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1209 | 1113 | const token_ptr = token.ptr; |
| 1210 | 1114 | switch (token_ptr.id) { |
| 1211 | 1115 | Token.Id.Identifier => { |
| 1212 | node.kind = ast.Node.AsmOutput.Kind { .Variable = try createLiteral(arena, ast.Node.Identifier, token_index) }; | |
| 1116 | node.kind = ast.Node.AsmOutput.Kind{ .Variable = try createLiteral(arena, ast.Node.Identifier, token_index) }; | |
| 1213 | 1117 | continue; |
| 1214 | 1118 | }, |
| 1215 | 1119 | Token.Id.Arrow => { |
| 1216 | node.kind = ast.Node.AsmOutput.Kind { .Return = undefined }; | |
| 1217 | try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.kind.Return } }); | |
| 1120 | node.kind = ast.Node.AsmOutput.Kind{ .Return = undefined }; | |
| 1121 | try stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.kind.Return } }); | |
| 1218 | 1122 | continue; |
| 1219 | 1123 | }, |
| 1220 | 1124 | else => { |
| 1221 | *(try tree.errors.addOne()) = Error { | |
| 1222 | .ExpectedAsmOutputReturnOrType = Error.ExpectedAsmOutputReturnOrType { | |
| 1223 | .token = token_index, | |
| 1224 | }, | |
| 1225 | }; | |
| 1125 | ((try tree.errors.addOne())).* = Error{ .ExpectedAsmOutputReturnOrType = Error.ExpectedAsmOutputReturnOrType{ .token = token_index } }; | |
| 1226 | 1126 | return tree; |
| 1227 | 1127 | }, |
| 1228 | 1128 | } |
| ... | ... | @@ -1236,49 +1136,48 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1236 | 1136 | continue; |
| 1237 | 1137 | } |
| 1238 | 1138 | |
| 1239 | const node = try arena.construct(ast.Node.AsmInput { | |
| 1240 | .base = ast.Node {.id = ast.Node.Id.AsmInput }, | |
| 1139 | const node = try arena.construct(ast.Node.AsmInput{ | |
| 1140 | .base = ast.Node{ .id = ast.Node.Id.AsmInput }, | |
| 1241 | 1141 | .symbolic_name = undefined, |
| 1242 | 1142 | .constraint = undefined, |
| 1243 | 1143 | .expr = undefined, |
| 1244 | 1144 | }); |
| 1245 | 1145 | try items.push(node); |
| 1246 | 1146 | |
| 1247 | stack.append(State { .AsmInputItems = items }) catch unreachable; | |
| 1248 | try stack.append(State { .IfToken = Token.Id.Comma }); | |
| 1249 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 1250 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); | |
| 1251 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 1252 | try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } }); | |
| 1253 | try stack.append(State { .ExpectToken = Token.Id.RBracket }); | |
| 1254 | try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } }); | |
| 1147 | stack.append(State{ .AsmInputItems = items }) catch unreachable; | |
| 1148 | try stack.append(State{ .IfToken = Token.Id.Comma }); | |
| 1149 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 1150 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 1151 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 1152 | try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.constraint } }); | |
| 1153 | try stack.append(State{ .ExpectToken = Token.Id.RBracket }); | |
| 1154 | try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.symbolic_name } }); | |
| 1255 | 1155 | continue; |
| 1256 | 1156 | }, |
| 1257 | 1157 | State.AsmClobberItems => |items| { |
| 1258 | stack.append(State { .AsmClobberItems = items }) catch unreachable; | |
| 1259 | try stack.append(State { .IfToken = Token.Id.Comma }); | |
| 1260 | try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } }); | |
| 1158 | stack.append(State{ .AsmClobberItems = items }) catch unreachable; | |
| 1159 | try stack.append(State{ .IfToken = Token.Id.Comma }); | |
| 1160 | try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } }); | |
| 1261 | 1161 | continue; |
| 1262 | 1162 | }, |
| 1263 | 1163 | |
| 1264 | ||
| 1265 | 1164 | State.ExprListItemOrEnd => |list_state| { |
| 1266 | 1165 | if (eatToken(&tok_it, &tree, list_state.end)) |token_index| { |
| 1267 | *list_state.ptr = token_index; | |
| 1166 | (list_state.ptr).* = token_index; | |
| 1268 | 1167 | continue; |
| 1269 | 1168 | } |
| 1270 | 1169 | |
| 1271 | stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable; | |
| 1272 | try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } }); | |
| 1170 | stack.append(State{ .ExprListCommaOrEnd = list_state }) catch unreachable; | |
| 1171 | try stack.append(State{ .Expression = OptionalCtx{ .Required = try list_state.list.addOne() } }); | |
| 1273 | 1172 | continue; |
| 1274 | 1173 | }, |
| 1275 | 1174 | State.ExprListCommaOrEnd => |list_state| { |
| 1276 | 1175 | switch (expectCommaOrEnd(&tok_it, &tree, list_state.end)) { |
| 1277 | 1176 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1278 | *list_state.ptr = end; | |
| 1177 | (list_state.ptr).* = end; | |
| 1279 | 1178 | continue; |
| 1280 | 1179 | } else { |
| 1281 | stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable; | |
| 1180 | stack.append(State{ .ExprListItemOrEnd = list_state }) catch unreachable; | |
| 1282 | 1181 | continue; |
| 1283 | 1182 | }, |
| 1284 | 1183 | ExpectCommaOrEndResult.parse_error => |e| { |
| ... | ... | @@ -1293,44 +1192,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1293 | 1192 | } |
| 1294 | 1193 | |
| 1295 | 1194 | if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { |
| 1296 | *list_state.ptr = rbrace; | |
| 1195 | (list_state.ptr).* = rbrace; | |
| 1297 | 1196 | continue; |
| 1298 | 1197 | } |
| 1299 | 1198 | |
| 1300 | const node = try arena.construct(ast.Node.FieldInitializer { | |
| 1301 | .base = ast.Node { | |
| 1302 | .id = ast.Node.Id.FieldInitializer, | |
| 1303 | }, | |
| 1199 | const node = try arena.construct(ast.Node.FieldInitializer{ | |
| 1200 | .base = ast.Node{ .id = ast.Node.Id.FieldInitializer }, | |
| 1304 | 1201 | .period_token = undefined, |
| 1305 | 1202 | .name_token = undefined, |
| 1306 | 1203 | .expr = undefined, |
| 1307 | 1204 | }); |
| 1308 | 1205 | try list_state.list.push(&node.base); |
| 1309 | 1206 | |
| 1310 | stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable; | |
| 1311 | try stack.append(State { .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 1312 | try stack.append(State { .ExpectToken = Token.Id.Equal }); | |
| 1313 | try stack.append(State { | |
| 1314 | .ExpectTokenSave = ExpectTokenSave { | |
| 1315 | .id = Token.Id.Identifier, | |
| 1316 | .ptr = &node.name_token, | |
| 1317 | } | |
| 1318 | }); | |
| 1319 | try stack.append(State { | |
| 1320 | .ExpectTokenSave = ExpectTokenSave { | |
| 1321 | .id = Token.Id.Period, | |
| 1322 | .ptr = &node.period_token, | |
| 1323 | } | |
| 1324 | }); | |
| 1207 | stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable; | |
| 1208 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 1209 | try stack.append(State{ .ExpectToken = Token.Id.Equal }); | |
| 1210 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 1211 | .id = Token.Id.Identifier, | |
| 1212 | .ptr = &node.name_token, | |
| 1213 | } }); | |
| 1214 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 1215 | .id = Token.Id.Period, | |
| 1216 | .ptr = &node.period_token, | |
| 1217 | } }); | |
| 1325 | 1218 | continue; |
| 1326 | 1219 | }, |
| 1327 | 1220 | State.FieldInitListCommaOrEnd => |list_state| { |
| 1328 | 1221 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { |
| 1329 | 1222 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1330 | *list_state.ptr = end; | |
| 1223 | (list_state.ptr).* = end; | |
| 1331 | 1224 | continue; |
| 1332 | 1225 | } else { |
| 1333 | stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable; | |
| 1226 | stack.append(State{ .FieldInitListItemOrEnd = list_state }) catch unreachable; | |
| 1334 | 1227 | continue; |
| 1335 | 1228 | }, |
| 1336 | 1229 | ExpectCommaOrEndResult.parse_error => |e| { |
| ... | ... | @@ -1345,7 +1238,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1345 | 1238 | container_decl.rbrace_token = end; |
| 1346 | 1239 | continue; |
| 1347 | 1240 | } else { |
| 1348 | try stack.append(State { .ContainerDecl = container_decl }); | |
| 1241 | try stack.append(State{ .ContainerDecl = container_decl }); | |
| 1349 | 1242 | continue; |
| 1350 | 1243 | }, |
| 1351 | 1244 | ExpectCommaOrEndResult.parse_error => |e| { |
| ... | ... | @@ -1360,23 +1253,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1360 | 1253 | } |
| 1361 | 1254 | |
| 1362 | 1255 | if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { |
| 1363 | *list_state.ptr = rbrace; | |
| 1256 | (list_state.ptr).* = rbrace; | |
| 1364 | 1257 | continue; |
| 1365 | 1258 | } |
| 1366 | 1259 | |
| 1367 | 1260 | const node_ptr = try list_state.list.addOne(); |
| 1368 | 1261 | |
| 1369 | try stack.append(State { .ErrorTagListCommaOrEnd = list_state }); | |
| 1370 | try stack.append(State { .ErrorTag = node_ptr }); | |
| 1262 | try stack.append(State{ .ErrorTagListCommaOrEnd = list_state }); | |
| 1263 | try stack.append(State{ .ErrorTag = node_ptr }); | |
| 1371 | 1264 | continue; |
| 1372 | 1265 | }, |
| 1373 | 1266 | State.ErrorTagListCommaOrEnd => |list_state| { |
| 1374 | 1267 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { |
| 1375 | 1268 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1376 | *list_state.ptr = end; | |
| 1269 | (list_state.ptr).* = end; | |
| 1377 | 1270 | continue; |
| 1378 | 1271 | } else { |
| 1379 | stack.append(State { .ErrorTagListItemOrEnd = list_state }) catch unreachable; | |
| 1272 | stack.append(State{ .ErrorTagListItemOrEnd = list_state }) catch unreachable; | |
| 1380 | 1273 | continue; |
| 1381 | 1274 | }, |
| 1382 | 1275 | ExpectCommaOrEndResult.parse_error => |e| { |
| ... | ... | @@ -1391,24 +1284,22 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1391 | 1284 | } |
| 1392 | 1285 | |
| 1393 | 1286 | if (eatToken(&tok_it, &tree, Token.Id.RBrace)) |rbrace| { |
| 1394 | *list_state.ptr = rbrace; | |
| 1287 | (list_state.ptr).* = rbrace; | |
| 1395 | 1288 | continue; |
| 1396 | 1289 | } |
| 1397 | 1290 | |
| 1398 | 1291 | const comments = try eatDocComments(arena, &tok_it, &tree); |
| 1399 | const node = try arena.construct(ast.Node.SwitchCase { | |
| 1400 | .base = ast.Node { | |
| 1401 | .id = ast.Node.Id.SwitchCase, | |
| 1402 | }, | |
| 1292 | const node = try arena.construct(ast.Node.SwitchCase{ | |
| 1293 | .base = ast.Node{ .id = ast.Node.Id.SwitchCase }, | |
| 1403 | 1294 | .items = ast.Node.SwitchCase.ItemList.init(arena), |
| 1404 | 1295 | .payload = null, |
| 1405 | 1296 | .expr = undefined, |
| 1406 | 1297 | }); |
| 1407 | 1298 | try list_state.list.push(&node.base); |
| 1408 | try stack.append(State { .SwitchCaseCommaOrEnd = list_state }); | |
| 1409 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } }); | |
| 1410 | try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); | |
| 1411 | try stack.append(State { .SwitchCaseFirstItem = &node.items }); | |
| 1299 | try stack.append(State{ .SwitchCaseCommaOrEnd = list_state }); | |
| 1300 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } }); | |
| 1301 | try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); | |
| 1302 | try stack.append(State{ .SwitchCaseFirstItem = &node.items }); | |
| 1412 | 1303 | |
| 1413 | 1304 | continue; |
| 1414 | 1305 | }, |
| ... | ... | @@ -1416,10 +1307,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1416 | 1307 | State.SwitchCaseCommaOrEnd => |list_state| { |
| 1417 | 1308 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) { |
| 1418 | 1309 | ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| { |
| 1419 | *list_state.ptr = end; | |
| 1310 | (list_state.ptr).* = end; | |
| 1420 | 1311 | continue; |
| 1421 | 1312 | } else { |
| 1422 | try stack.append(State { .SwitchCaseOrEnd = list_state }); | |
| 1313 | try stack.append(State{ .SwitchCaseOrEnd = list_state }); | |
| 1423 | 1314 | continue; |
| 1424 | 1315 | }, |
| 1425 | 1316 | ExpectCommaOrEndResult.parse_error => |e| { |
| ... | ... | @@ -1434,29 +1325,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1434 | 1325 | const token_index = token.index; |
| 1435 | 1326 | const token_ptr = token.ptr; |
| 1436 | 1327 | if (token_ptr.id == Token.Id.Keyword_else) { |
| 1437 | const else_node = try arena.construct(ast.Node.SwitchElse { | |
| 1438 | .base = ast.Node{ .id = ast.Node.Id.SwitchElse}, | |
| 1328 | const else_node = try arena.construct(ast.Node.SwitchElse{ | |
| 1329 | .base = ast.Node{ .id = ast.Node.Id.SwitchElse }, | |
| 1439 | 1330 | .token = token_index, |
| 1440 | 1331 | }); |
| 1441 | 1332 | try case_items.push(&else_node.base); |
| 1442 | 1333 | |
| 1443 | try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight }); | |
| 1334 | try stack.append(State{ .ExpectToken = Token.Id.EqualAngleBracketRight }); | |
| 1444 | 1335 | continue; |
| 1445 | 1336 | } else { |
| 1446 | 1337 | putBackToken(&tok_it, &tree); |
| 1447 | try stack.append(State { .SwitchCaseItem = case_items }); | |
| 1338 | try stack.append(State{ .SwitchCaseItem = case_items }); | |
| 1448 | 1339 | continue; |
| 1449 | 1340 | } |
| 1450 | 1341 | }, |
| 1451 | 1342 | State.SwitchCaseItem => |case_items| { |
| 1452 | stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; | |
| 1453 | try stack.append(State { .RangeExpressionBegin = OptionalCtx { .Required = try case_items.addOne() } }); | |
| 1343 | stack.append(State{ .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable; | |
| 1344 | try stack.append(State{ .RangeExpressionBegin = OptionalCtx{ .Required = try case_items.addOne() } }); | |
| 1454 | 1345 | }, |
| 1455 | 1346 | State.SwitchCaseItemCommaOrEnd => |case_items| { |
| 1456 | 1347 | switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.EqualAngleBracketRight)) { |
| 1457 | 1348 | ExpectCommaOrEndResult.end_token => |t| { |
| 1458 | 1349 | if (t == null) { |
| 1459 | stack.append(State { .SwitchCaseItem = case_items }) catch unreachable; | |
| 1350 | stack.append(State{ .SwitchCaseItem = case_items }) catch unreachable; | |
| 1460 | 1351 | } |
| 1461 | 1352 | continue; |
| 1462 | 1353 | }, |
| ... | ... | @@ -1468,10 +1359,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1468 | 1359 | continue; |
| 1469 | 1360 | }, |
| 1470 | 1361 | |
| 1471 | ||
| 1472 | 1362 | State.SuspendBody => |suspend_node| { |
| 1473 | 1363 | if (suspend_node.payload != null) { |
| 1474 | try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = &suspend_node.body } }); | |
| 1364 | try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } }); | |
| 1475 | 1365 | } |
| 1476 | 1366 | continue; |
| 1477 | 1367 | }, |
| ... | ... | @@ -1481,13 +1371,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1481 | 1371 | } |
| 1482 | 1372 | |
| 1483 | 1373 | async_node.rangle_bracket = TokenIndex(0); |
| 1484 | try stack.append(State { | |
| 1485 | .ExpectTokenSave = ExpectTokenSave { | |
| 1486 | .id = Token.Id.AngleBracketRight, | |
| 1487 | .ptr = &??async_node.rangle_bracket, | |
| 1488 | } | |
| 1489 | }); | |
| 1490 | try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } }); | |
| 1374 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 1375 | .id = Token.Id.AngleBracketRight, | |
| 1376 | .ptr = &??async_node.rangle_bracket, | |
| 1377 | } }); | |
| 1378 | try stack.append(State{ .TypeExprBegin = OptionalCtx{ .RequiredNull = &async_node.allocator_type } }); | |
| 1491 | 1379 | continue; |
| 1492 | 1380 | }, |
| 1493 | 1381 | State.AsyncEnd => |ctx| { |
| ... | ... | @@ -1506,27 +1394,20 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1506 | 1394 | continue; |
| 1507 | 1395 | } |
| 1508 | 1396 | |
| 1509 | *(try tree.errors.addOne()) = Error { | |
| 1510 | .ExpectedCall = Error.ExpectedCall { .node = node }, | |
| 1511 | }; | |
| 1397 | ((try tree.errors.addOne())).* = Error{ .ExpectedCall = Error.ExpectedCall{ .node = node } }; | |
| 1512 | 1398 | return tree; |
| 1513 | 1399 | }, |
| 1514 | 1400 | else => { |
| 1515 | *(try tree.errors.addOne()) = Error { | |
| 1516 | .ExpectedCallOrFnProto = Error.ExpectedCallOrFnProto { .node = node }, | |
| 1517 | }; | |
| 1401 | ((try tree.errors.addOne())).* = Error{ .ExpectedCallOrFnProto = Error.ExpectedCallOrFnProto{ .node = node } }; | |
| 1518 | 1402 | return tree; |
| 1519 | } | |
| 1403 | }, | |
| 1520 | 1404 | } |
| 1521 | 1405 | }, |
| 1522 | 1406 | |
| 1523 | ||
| 1524 | 1407 | State.ExternType => |ctx| { |
| 1525 | 1408 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| { |
| 1526 | const fn_proto = try arena.construct(ast.Node.FnProto { | |
| 1527 | .base = ast.Node { | |
| 1528 | .id = ast.Node.Id.FnProto, | |
| 1529 | }, | |
| 1409 | const fn_proto = try arena.construct(ast.Node.FnProto{ | |
| 1410 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | |
| 1530 | 1411 | .doc_comments = ctx.comments, |
| 1531 | 1412 | .visib_token = null, |
| 1532 | 1413 | .name_token = null, |
| ... | ... | @@ -1542,17 +1423,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1542 | 1423 | .align_expr = null, |
| 1543 | 1424 | }); |
| 1544 | 1425 | ctx.opt_ctx.store(&fn_proto.base); |
| 1545 | stack.append(State { .FnProto = fn_proto }) catch unreachable; | |
| 1426 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; | |
| 1546 | 1427 | continue; |
| 1547 | 1428 | } |
| 1548 | 1429 | |
| 1549 | stack.append(State { | |
| 1550 | .ContainerKind = ContainerKindCtx { | |
| 1551 | .opt_ctx = ctx.opt_ctx, | |
| 1552 | .ltoken = ctx.extern_token, | |
| 1553 | .layout = ast.Node.ContainerDecl.Layout.Extern, | |
| 1554 | }, | |
| 1555 | }) catch unreachable; | |
| 1430 | stack.append(State{ .ContainerKind = ContainerKindCtx{ | |
| 1431 | .opt_ctx = ctx.opt_ctx, | |
| 1432 | .ltoken = ctx.extern_token, | |
| 1433 | .layout = ast.Node.ContainerDecl.Layout.Extern, | |
| 1434 | } }) catch unreachable; | |
| 1556 | 1435 | continue; |
| 1557 | 1436 | }, |
| 1558 | 1437 | State.SliceOrArrayAccess => |node| { |
| ... | ... | @@ -1562,20 +1441,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1562 | 1441 | switch (token_ptr.id) { |
| 1563 | 1442 | Token.Id.Ellipsis2 => { |
| 1564 | 1443 | const start = node.op.ArrayAccess; |
| 1565 | node.op = ast.Node.SuffixOp.Op { | |
| 1566 | .Slice = ast.Node.SuffixOp.Op.Slice { | |
| 1567 | .start = start, | |
| 1568 | .end = null, | |
| 1569 | } | |
| 1570 | }; | |
| 1444 | node.op = ast.Node.SuffixOp.Op{ .Slice = ast.Node.SuffixOp.Op.Slice{ | |
| 1445 | .start = start, | |
| 1446 | .end = null, | |
| 1447 | } }; | |
| 1571 | 1448 | |
| 1572 | stack.append(State { | |
| 1573 | .ExpectTokenSave = ExpectTokenSave { | |
| 1574 | .id = Token.Id.RBracket, | |
| 1575 | .ptr = &node.rtoken, | |
| 1576 | } | |
| 1577 | }) catch unreachable; | |
| 1578 | 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 } }); | |
| 1579 | 1454 | continue; |
| 1580 | 1455 | }, |
| 1581 | 1456 | Token.Id.RBracket => { |
| ... | ... | @@ -1583,33 +1458,29 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1583 | 1458 | continue; |
| 1584 | 1459 | }, |
| 1585 | 1460 | else => { |
| 1586 | *(try tree.errors.addOne()) = Error { | |
| 1587 | .ExpectedSliceOrRBracket = Error.ExpectedSliceOrRBracket { .token = token_index }, | |
| 1588 | }; | |
| 1461 | ((try tree.errors.addOne())).* = Error{ .ExpectedSliceOrRBracket = Error.ExpectedSliceOrRBracket{ .token = token_index } }; | |
| 1589 | 1462 | return tree; |
| 1590 | } | |
| 1463 | }, | |
| 1591 | 1464 | } |
| 1592 | 1465 | }, |
| 1593 | 1466 | State.SliceOrArrayType => |node| { |
| 1594 | 1467 | if (eatToken(&tok_it, &tree, Token.Id.RBracket)) |_| { |
| 1595 | node.op = ast.Node.PrefixOp.Op { | |
| 1596 | .SliceType = ast.Node.PrefixOp.AddrOfInfo { | |
| 1597 | .align_expr = null, | |
| 1598 | .bit_offset_start_token = null, | |
| 1599 | .bit_offset_end_token = null, | |
| 1600 | .const_token = null, | |
| 1601 | .volatile_token = null, | |
| 1602 | } | |
| 1603 | }; | |
| 1604 | stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; | |
| 1605 | try stack.append(State { .AddrOfModifiers = &node.op.SliceType }); | |
| 1468 | node.op = ast.Node.PrefixOp.Op{ .SliceType = ast.Node.PrefixOp.AddrOfInfo{ | |
| 1469 | .align_expr = null, | |
| 1470 | .bit_offset_start_token = null, | |
| 1471 | .bit_offset_end_token = null, | |
| 1472 | .const_token = null, | |
| 1473 | .volatile_token = null, | |
| 1474 | } }; | |
| 1475 | stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | |
| 1476 | try stack.append(State{ .AddrOfModifiers = &node.op.SliceType }); | |
| 1606 | 1477 | continue; |
| 1607 | 1478 | } |
| 1608 | 1479 | |
| 1609 | node.op = ast.Node.PrefixOp.Op { .ArrayType = undefined }; | |
| 1610 | stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; | |
| 1611 | try stack.append(State { .ExpectToken = Token.Id.RBracket }); | |
| 1612 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayType } }); | |
| 1480 | node.op = ast.Node.PrefixOp.Op{ .ArrayType = undefined }; | |
| 1481 | stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | |
| 1482 | try stack.append(State{ .ExpectToken = Token.Id.RBracket }); | |
| 1483 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayType } }); | |
| 1613 | 1484 | continue; |
| 1614 | 1485 | }, |
| 1615 | 1486 | State.AddrOfModifiers => |addr_of_info| { |
| ... | ... | @@ -1620,22 +1491,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1620 | 1491 | Token.Id.Keyword_align => { |
| 1621 | 1492 | stack.append(state) catch unreachable; |
| 1622 | 1493 | if (addr_of_info.align_expr != null) { |
| 1623 | *(try tree.errors.addOne()) = Error { | |
| 1624 | .ExtraAlignQualifier = Error.ExtraAlignQualifier { .token = token_index }, | |
| 1625 | }; | |
| 1494 | ((try tree.errors.addOne())).* = Error{ .ExtraAlignQualifier = Error.ExtraAlignQualifier{ .token = token_index } }; | |
| 1626 | 1495 | return tree; |
| 1627 | 1496 | } |
| 1628 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 1629 | try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &addr_of_info.align_expr} }); | |
| 1630 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 1497 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 1498 | try stack.append(State{ .Expression = OptionalCtx{ .RequiredNull = &addr_of_info.align_expr } }); | |
| 1499 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 1631 | 1500 | continue; |
| 1632 | 1501 | }, |
| 1633 | 1502 | Token.Id.Keyword_const => { |
| 1634 | 1503 | stack.append(state) catch unreachable; |
| 1635 | 1504 | if (addr_of_info.const_token != null) { |
| 1636 | *(try tree.errors.addOne()) = Error { | |
| 1637 | .ExtraConstQualifier = Error.ExtraConstQualifier { .token = token_index }, | |
| 1638 | }; | |
| 1505 | ((try tree.errors.addOne())).* = Error{ .ExtraConstQualifier = Error.ExtraConstQualifier{ .token = token_index } }; | |
| 1639 | 1506 | return tree; |
| 1640 | 1507 | } |
| 1641 | 1508 | addr_of_info.const_token = token_index; |
| ... | ... | @@ -1644,9 +1511,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1644 | 1511 | Token.Id.Keyword_volatile => { |
| 1645 | 1512 | stack.append(state) catch unreachable; |
| 1646 | 1513 | if (addr_of_info.volatile_token != null) { |
| 1647 | *(try tree.errors.addOne()) = Error { | |
| 1648 | .ExtraVolatileQualifier = Error.ExtraVolatileQualifier { .token = token_index }, | |
| 1649 | }; | |
| 1514 | ((try tree.errors.addOne())).* = Error{ .ExtraVolatileQualifier = Error.ExtraVolatileQualifier{ .token = token_index } }; | |
| 1650 | 1515 | return tree; |
| 1651 | 1516 | } |
| 1652 | 1517 | addr_of_info.volatile_token = token_index; |
| ... | ... | @@ -1659,19 +1524,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1659 | 1524 | } |
| 1660 | 1525 | }, |
| 1661 | 1526 | |
| 1662 | ||
| 1663 | 1527 | State.Payload => |opt_ctx| { |
| 1664 | 1528 | const token = nextToken(&tok_it, &tree); |
| 1665 | 1529 | const token_index = token.index; |
| 1666 | 1530 | const token_ptr = token.ptr; |
| 1667 | 1531 | if (token_ptr.id != Token.Id.Pipe) { |
| 1668 | 1532 | if (opt_ctx != OptionalCtx.Optional) { |
| 1669 | *(try tree.errors.addOne()) = Error { | |
| 1670 | .ExpectedToken = Error.ExpectedToken { | |
| 1671 | .token = token_index, | |
| 1672 | .expected_id = Token.Id.Pipe, | |
| 1673 | }, | |
| 1674 | }; | |
| 1533 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 1534 | .token = token_index, | |
| 1535 | .expected_id = Token.Id.Pipe, | |
| 1536 | } }; | |
| 1675 | 1537 | return tree; |
| 1676 | 1538 | } |
| 1677 | 1539 | |
| ... | ... | @@ -1679,21 +1541,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1679 | 1541 | continue; |
| 1680 | 1542 | } |
| 1681 | 1543 | |
| 1682 | const node = try arena.construct(ast.Node.Payload { | |
| 1683 | .base = ast.Node {.id = ast.Node.Id.Payload }, | |
| 1544 | const node = try arena.construct(ast.Node.Payload{ | |
| 1545 | .base = ast.Node{ .id = ast.Node.Id.Payload }, | |
| 1684 | 1546 | .lpipe = token_index, |
| 1685 | 1547 | .error_symbol = undefined, |
| 1686 | .rpipe = undefined | |
| 1548 | .rpipe = undefined, | |
| 1687 | 1549 | }); |
| 1688 | 1550 | opt_ctx.store(&node.base); |
| 1689 | 1551 | |
| 1690 | stack.append(State { | |
| 1691 | .ExpectTokenSave = ExpectTokenSave { | |
| 1692 | .id = Token.Id.Pipe, | |
| 1693 | .ptr = &node.rpipe, | |
| 1694 | } | |
| 1695 | }) catch unreachable; | |
| 1696 | try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } }); | |
| 1552 | stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 1553 | .id = Token.Id.Pipe, | |
| 1554 | .ptr = &node.rpipe, | |
| 1555 | } }) catch unreachable; | |
| 1556 | try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.error_symbol } }); | |
| 1697 | 1557 | continue; |
| 1698 | 1558 | }, |
| 1699 | 1559 | State.PointerPayload => |opt_ctx| { |
| ... | ... | @@ -1702,12 +1562,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1702 | 1562 | const token_ptr = token.ptr; |
| 1703 | 1563 | if (token_ptr.id != Token.Id.Pipe) { |
| 1704 | 1564 | if (opt_ctx != OptionalCtx.Optional) { |
| 1705 | *(try tree.errors.addOne()) = Error { | |
| 1706 | .ExpectedToken = Error.ExpectedToken { | |
| 1707 | .token = token_index, | |
| 1708 | .expected_id = Token.Id.Pipe, | |
| 1709 | }, | |
| 1710 | }; | |
| 1565 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 1566 | .token = token_index, | |
| 1567 | .expected_id = Token.Id.Pipe, | |
| 1568 | } }; | |
| 1711 | 1569 | return tree; |
| 1712 | 1570 | } |
| 1713 | 1571 | |
| ... | ... | @@ -1715,28 +1573,24 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1715 | 1573 | continue; |
| 1716 | 1574 | } |
| 1717 | 1575 | |
| 1718 | const node = try arena.construct(ast.Node.PointerPayload { | |
| 1719 | .base = ast.Node {.id = ast.Node.Id.PointerPayload }, | |
| 1576 | const node = try arena.construct(ast.Node.PointerPayload{ | |
| 1577 | .base = ast.Node{ .id = ast.Node.Id.PointerPayload }, | |
| 1720 | 1578 | .lpipe = token_index, |
| 1721 | 1579 | .ptr_token = null, |
| 1722 | 1580 | .value_symbol = undefined, |
| 1723 | .rpipe = undefined | |
| 1581 | .rpipe = undefined, | |
| 1724 | 1582 | }); |
| 1725 | 1583 | opt_ctx.store(&node.base); |
| 1726 | 1584 | |
| 1727 | try stack.append(State { | |
| 1728 | .ExpectTokenSave = ExpectTokenSave { | |
| 1729 | .id = Token.Id.Pipe, | |
| 1730 | .ptr = &node.rpipe, | |
| 1731 | } | |
| 1732 | }); | |
| 1733 | try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } }); | |
| 1734 | try stack.append(State { | |
| 1735 | .OptionalTokenSave = OptionalTokenSave { | |
| 1736 | .id = Token.Id.Asterisk, | |
| 1737 | .ptr = &node.ptr_token, | |
| 1738 | } | |
| 1739 | }); | |
| 1585 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 1586 | .id = Token.Id.Pipe, | |
| 1587 | .ptr = &node.rpipe, | |
| 1588 | } }); | |
| 1589 | try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.value_symbol } }); | |
| 1590 | try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{ | |
| 1591 | .id = Token.Id.Asterisk, | |
| 1592 | .ptr = &node.ptr_token, | |
| 1593 | } }); | |
| 1740 | 1594 | continue; |
| 1741 | 1595 | }, |
| 1742 | 1596 | State.PointerIndexPayload => |opt_ctx| { |
| ... | ... | @@ -1745,12 +1599,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1745 | 1599 | const token_ptr = token.ptr; |
| 1746 | 1600 | if (token_ptr.id != Token.Id.Pipe) { |
| 1747 | 1601 | if (opt_ctx != OptionalCtx.Optional) { |
| 1748 | *(try tree.errors.addOne()) = Error { | |
| 1749 | .ExpectedToken = Error.ExpectedToken { | |
| 1750 | .token = token_index, | |
| 1751 | .expected_id = Token.Id.Pipe, | |
| 1752 | }, | |
| 1753 | }; | |
| 1602 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 1603 | .token = token_index, | |
| 1604 | .expected_id = Token.Id.Pipe, | |
| 1605 | } }; | |
| 1754 | 1606 | return tree; |
| 1755 | 1607 | } |
| 1756 | 1608 | |
| ... | ... | @@ -1758,61 +1610,58 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1758 | 1610 | continue; |
| 1759 | 1611 | } |
| 1760 | 1612 | |
| 1761 | const node = try arena.construct(ast.Node.PointerIndexPayload { | |
| 1762 | .base = ast.Node {.id = ast.Node.Id.PointerIndexPayload }, | |
| 1613 | const node = try arena.construct(ast.Node.PointerIndexPayload{ | |
| 1614 | .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload }, | |
| 1763 | 1615 | .lpipe = token_index, |
| 1764 | 1616 | .ptr_token = null, |
| 1765 | 1617 | .value_symbol = undefined, |
| 1766 | 1618 | .index_symbol = null, |
| 1767 | .rpipe = undefined | |
| 1619 | .rpipe = undefined, | |
| 1768 | 1620 | }); |
| 1769 | 1621 | opt_ctx.store(&node.base); |
| 1770 | 1622 | |
| 1771 | stack.append(State { | |
| 1772 | .ExpectTokenSave = ExpectTokenSave { | |
| 1773 | .id = Token.Id.Pipe, | |
| 1774 | .ptr = &node.rpipe, | |
| 1775 | } | |
| 1776 | }) catch unreachable; | |
| 1777 | try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.index_symbol } }); | |
| 1778 | try stack.append(State { .IfToken = Token.Id.Comma }); | |
| 1779 | try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } }); | |
| 1780 | try stack.append(State { | |
| 1781 | .OptionalTokenSave = OptionalTokenSave { | |
| 1782 | .id = Token.Id.Asterisk, | |
| 1783 | .ptr = &node.ptr_token, | |
| 1784 | } | |
| 1785 | }); | |
| 1623 | stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 1624 | .id = Token.Id.Pipe, | |
| 1625 | .ptr = &node.rpipe, | |
| 1626 | } }) catch unreachable; | |
| 1627 | try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.index_symbol } }); | |
| 1628 | try stack.append(State{ .IfToken = Token.Id.Comma }); | |
| 1629 | try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.value_symbol } }); | |
| 1630 | try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{ | |
| 1631 | .id = Token.Id.Asterisk, | |
| 1632 | .ptr = &node.ptr_token, | |
| 1633 | } }); | |
| 1786 | 1634 | continue; |
| 1787 | 1635 | }, |
| 1788 | 1636 | |
| 1789 | ||
| 1790 | 1637 | State.Expression => |opt_ctx| { |
| 1791 | 1638 | const token = nextToken(&tok_it, &tree); |
| 1792 | 1639 | const token_index = token.index; |
| 1793 | 1640 | const token_ptr = token.ptr; |
| 1794 | 1641 | switch (token_ptr.id) { |
| 1795 | Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => { | |
| 1796 | const node = try arena.construct(ast.Node.ControlFlowExpression { | |
| 1797 | .base = ast.Node {.id = ast.Node.Id.ControlFlowExpression }, | |
| 1642 | Token.Id.Keyword_return, | |
| 1643 | Token.Id.Keyword_break, | |
| 1644 | Token.Id.Keyword_continue => { | |
| 1645 | const node = try arena.construct(ast.Node.ControlFlowExpression{ | |
| 1646 | .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression }, | |
| 1798 | 1647 | .ltoken = token_index, |
| 1799 | 1648 | .kind = undefined, |
| 1800 | 1649 | .rhs = null, |
| 1801 | 1650 | }); |
| 1802 | 1651 | opt_ctx.store(&node.base); |
| 1803 | 1652 | |
| 1804 | stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable; | |
| 1653 | stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable; | |
| 1805 | 1654 | |
| 1806 | 1655 | switch (token_ptr.id) { |
| 1807 | 1656 | Token.Id.Keyword_break => { |
| 1808 | node.kind = ast.Node.ControlFlowExpression.Kind { .Break = null }; | |
| 1809 | try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Break } }); | |
| 1810 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 1657 | node.kind = ast.Node.ControlFlowExpression.Kind{ .Break = null }; | |
| 1658 | try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.kind.Break } }); | |
| 1659 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 1811 | 1660 | }, |
| 1812 | 1661 | Token.Id.Keyword_continue => { |
| 1813 | node.kind = ast.Node.ControlFlowExpression.Kind { .Continue = null }; | |
| 1814 | try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } }); | |
| 1815 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 1662 | node.kind = ast.Node.ControlFlowExpression.Kind{ .Continue = null }; | |
| 1663 | try stack.append(State{ .Identifier = OptionalCtx{ .RequiredNull = &node.kind.Continue } }); | |
| 1664 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 1816 | 1665 | }, |
| 1817 | 1666 | Token.Id.Keyword_return => { |
| 1818 | 1667 | node.kind = ast.Node.ControlFlowExpression.Kind.Return; |
| ... | ... | @@ -1821,56 +1670,58 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1821 | 1670 | } |
| 1822 | 1671 | continue; |
| 1823 | 1672 | }, |
| 1824 | Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => { | |
| 1825 | const node = try arena.construct(ast.Node.PrefixOp { | |
| 1826 | .base = ast.Node {.id = ast.Node.Id.PrefixOp }, | |
| 1673 | Token.Id.Keyword_try, | |
| 1674 | Token.Id.Keyword_cancel, | |
| 1675 | Token.Id.Keyword_resume => { | |
| 1676 | const node = try arena.construct(ast.Node.PrefixOp{ | |
| 1677 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | |
| 1827 | 1678 | .op_token = token_index, |
| 1828 | 1679 | .op = switch (token_ptr.id) { |
| 1829 | Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} }, | |
| 1830 | Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} }, | |
| 1831 | Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} }, | |
| 1680 | Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} }, | |
| 1681 | Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op{ .Cancel = void{} }, | |
| 1682 | Token.Id.Keyword_resume => ast.Node.PrefixOp.Op{ .Resume = void{} }, | |
| 1832 | 1683 | else => unreachable, |
| 1833 | 1684 | }, |
| 1834 | 1685 | .rhs = undefined, |
| 1835 | 1686 | }); |
| 1836 | 1687 | opt_ctx.store(&node.base); |
| 1837 | 1688 | |
| 1838 | stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable; | |
| 1689 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | |
| 1839 | 1690 | continue; |
| 1840 | 1691 | }, |
| 1841 | 1692 | else => { |
| 1842 | 1693 | if (!try parseBlockExpr(&stack, arena, opt_ctx, token_ptr, token_index)) { |
| 1843 | 1694 | putBackToken(&tok_it, &tree); |
| 1844 | stack.append(State { .UnwrapExpressionBegin = opt_ctx }) catch unreachable; | |
| 1695 | stack.append(State{ .UnwrapExpressionBegin = opt_ctx }) catch unreachable; | |
| 1845 | 1696 | } |
| 1846 | 1697 | continue; |
| 1847 | } | |
| 1698 | }, | |
| 1848 | 1699 | } |
| 1849 | 1700 | }, |
| 1850 | 1701 | State.RangeExpressionBegin => |opt_ctx| { |
| 1851 | stack.append(State { .RangeExpressionEnd = opt_ctx }) catch unreachable; | |
| 1852 | try stack.append(State { .Expression = opt_ctx }); | |
| 1702 | stack.append(State{ .RangeExpressionEnd = opt_ctx }) catch unreachable; | |
| 1703 | try stack.append(State{ .Expression = opt_ctx }); | |
| 1853 | 1704 | continue; |
| 1854 | 1705 | }, |
| 1855 | 1706 | State.RangeExpressionEnd => |opt_ctx| { |
| 1856 | 1707 | const lhs = opt_ctx.get() ?? continue; |
| 1857 | 1708 | |
| 1858 | 1709 | if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| { |
| 1859 | const node = try arena.construct(ast.Node.InfixOp { | |
| 1860 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1710 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1711 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 1861 | 1712 | .lhs = lhs, |
| 1862 | 1713 | .op_token = ellipsis3, |
| 1863 | 1714 | .op = ast.Node.InfixOp.Op.Range, |
| 1864 | 1715 | .rhs = undefined, |
| 1865 | 1716 | }); |
| 1866 | 1717 | opt_ctx.store(&node.base); |
| 1867 | stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable; | |
| 1718 | stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | |
| 1868 | 1719 | continue; |
| 1869 | 1720 | } |
| 1870 | 1721 | }, |
| 1871 | 1722 | State.AssignmentExpressionBegin => |opt_ctx| { |
| 1872 | stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable; | |
| 1873 | try stack.append(State { .Expression = opt_ctx }); | |
| 1723 | stack.append(State{ .AssignmentExpressionEnd = opt_ctx }) catch unreachable; | |
| 1724 | try stack.append(State{ .Expression = opt_ctx }); | |
| 1874 | 1725 | continue; |
| 1875 | 1726 | }, |
| 1876 | 1727 | |
| ... | ... | @@ -1881,16 +1732,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1881 | 1732 | const token_index = token.index; |
| 1882 | 1733 | const token_ptr = token.ptr; |
| 1883 | 1734 | if (tokenIdToAssignment(token_ptr.id)) |ass_id| { |
| 1884 | const node = try arena.construct(ast.Node.InfixOp { | |
| 1885 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1735 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1736 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 1886 | 1737 | .lhs = lhs, |
| 1887 | 1738 | .op_token = token_index, |
| 1888 | 1739 | .op = ass_id, |
| 1889 | 1740 | .rhs = undefined, |
| 1890 | 1741 | }); |
| 1891 | 1742 | opt_ctx.store(&node.base); |
| 1892 | stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1893 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); | |
| 1743 | stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1744 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); | |
| 1894 | 1745 | continue; |
| 1895 | 1746 | } else { |
| 1896 | 1747 | putBackToken(&tok_it, &tree); |
| ... | ... | @@ -1899,8 +1750,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1899 | 1750 | }, |
| 1900 | 1751 | |
| 1901 | 1752 | State.UnwrapExpressionBegin => |opt_ctx| { |
| 1902 | stack.append(State { .UnwrapExpressionEnd = opt_ctx }) catch unreachable; | |
| 1903 | try stack.append(State { .BoolOrExpressionBegin = opt_ctx }); | |
| 1753 | stack.append(State{ .UnwrapExpressionEnd = opt_ctx }) catch unreachable; | |
| 1754 | try stack.append(State{ .BoolOrExpressionBegin = opt_ctx }); | |
| 1904 | 1755 | continue; |
| 1905 | 1756 | }, |
| 1906 | 1757 | |
| ... | ... | @@ -1911,8 +1762,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1911 | 1762 | const token_index = token.index; |
| 1912 | 1763 | const token_ptr = token.ptr; |
| 1913 | 1764 | if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| { |
| 1914 | const node = try arena.construct(ast.Node.InfixOp { | |
| 1915 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1765 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1766 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 1916 | 1767 | .lhs = lhs, |
| 1917 | 1768 | .op_token = token_index, |
| 1918 | 1769 | .op = unwrap_id, |
| ... | ... | @@ -1920,11 +1771,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1920 | 1771 | }); |
| 1921 | 1772 | opt_ctx.store(&node.base); |
| 1922 | 1773 | |
| 1923 | stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1924 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); | |
| 1774 | stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1775 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }); | |
| 1925 | 1776 | |
| 1926 | 1777 | if (node.op == ast.Node.InfixOp.Op.Catch) { |
| 1927 | try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } }); | |
| 1778 | try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.op.Catch } }); | |
| 1928 | 1779 | } |
| 1929 | 1780 | continue; |
| 1930 | 1781 | } else { |
| ... | ... | @@ -1934,8 +1785,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1934 | 1785 | }, |
| 1935 | 1786 | |
| 1936 | 1787 | State.BoolOrExpressionBegin => |opt_ctx| { |
| 1937 | stack.append(State { .BoolOrExpressionEnd = opt_ctx }) catch unreachable; | |
| 1938 | try stack.append(State { .BoolAndExpressionBegin = opt_ctx }); | |
| 1788 | stack.append(State{ .BoolOrExpressionEnd = opt_ctx }) catch unreachable; | |
| 1789 | try stack.append(State{ .BoolAndExpressionBegin = opt_ctx }); | |
| 1939 | 1790 | continue; |
| 1940 | 1791 | }, |
| 1941 | 1792 | |
| ... | ... | @@ -1943,23 +1794,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1943 | 1794 | const lhs = opt_ctx.get() ?? continue; |
| 1944 | 1795 | |
| 1945 | 1796 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| { |
| 1946 | const node = try arena.construct(ast.Node.InfixOp { | |
| 1947 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1797 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1798 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 1948 | 1799 | .lhs = lhs, |
| 1949 | 1800 | .op_token = or_token, |
| 1950 | 1801 | .op = ast.Node.InfixOp.Op.BoolOr, |
| 1951 | 1802 | .rhs = undefined, |
| 1952 | 1803 | }); |
| 1953 | 1804 | opt_ctx.store(&node.base); |
| 1954 | stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1955 | try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1805 | stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1806 | try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 1956 | 1807 | continue; |
| 1957 | 1808 | } |
| 1958 | 1809 | }, |
| 1959 | 1810 | |
| 1960 | 1811 | State.BoolAndExpressionBegin => |opt_ctx| { |
| 1961 | stack.append(State { .BoolAndExpressionEnd = opt_ctx }) catch unreachable; | |
| 1962 | try stack.append(State { .ComparisonExpressionBegin = opt_ctx }); | |
| 1812 | stack.append(State{ .BoolAndExpressionEnd = opt_ctx }) catch unreachable; | |
| 1813 | try stack.append(State{ .ComparisonExpressionBegin = opt_ctx }); | |
| 1963 | 1814 | continue; |
| 1964 | 1815 | }, |
| 1965 | 1816 | |
| ... | ... | @@ -1967,23 +1818,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1967 | 1818 | const lhs = opt_ctx.get() ?? continue; |
| 1968 | 1819 | |
| 1969 | 1820 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| { |
| 1970 | const node = try arena.construct(ast.Node.InfixOp { | |
| 1971 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1821 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1822 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 1972 | 1823 | .lhs = lhs, |
| 1973 | 1824 | .op_token = and_token, |
| 1974 | 1825 | .op = ast.Node.InfixOp.Op.BoolAnd, |
| 1975 | 1826 | .rhs = undefined, |
| 1976 | 1827 | }); |
| 1977 | 1828 | opt_ctx.store(&node.base); |
| 1978 | stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1979 | try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1829 | stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1830 | try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 1980 | 1831 | continue; |
| 1981 | 1832 | } |
| 1982 | 1833 | }, |
| 1983 | 1834 | |
| 1984 | 1835 | State.ComparisonExpressionBegin => |opt_ctx| { |
| 1985 | stack.append(State { .ComparisonExpressionEnd = opt_ctx }) catch unreachable; | |
| 1986 | try stack.append(State { .BinaryOrExpressionBegin = opt_ctx }); | |
| 1836 | stack.append(State{ .ComparisonExpressionEnd = opt_ctx }) catch unreachable; | |
| 1837 | try stack.append(State{ .BinaryOrExpressionBegin = opt_ctx }); | |
| 1987 | 1838 | continue; |
| 1988 | 1839 | }, |
| 1989 | 1840 | |
| ... | ... | @@ -1994,16 +1845,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 1994 | 1845 | const token_index = token.index; |
| 1995 | 1846 | const token_ptr = token.ptr; |
| 1996 | 1847 | if (tokenIdToComparison(token_ptr.id)) |comp_id| { |
| 1997 | const node = try arena.construct(ast.Node.InfixOp { | |
| 1998 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1848 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1849 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 1999 | 1850 | .lhs = lhs, |
| 2000 | 1851 | .op_token = token_index, |
| 2001 | 1852 | .op = comp_id, |
| 2002 | 1853 | .rhs = undefined, |
| 2003 | 1854 | }); |
| 2004 | 1855 | opt_ctx.store(&node.base); |
| 2005 | stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2006 | try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1856 | stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1857 | try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2007 | 1858 | continue; |
| 2008 | 1859 | } else { |
| 2009 | 1860 | putBackToken(&tok_it, &tree); |
| ... | ... | @@ -2012,8 +1863,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2012 | 1863 | }, |
| 2013 | 1864 | |
| 2014 | 1865 | State.BinaryOrExpressionBegin => |opt_ctx| { |
| 2015 | stack.append(State { .BinaryOrExpressionEnd = opt_ctx }) catch unreachable; | |
| 2016 | try stack.append(State { .BinaryXorExpressionBegin = opt_ctx }); | |
| 1866 | stack.append(State{ .BinaryOrExpressionEnd = opt_ctx }) catch unreachable; | |
| 1867 | try stack.append(State{ .BinaryXorExpressionBegin = opt_ctx }); | |
| 2017 | 1868 | continue; |
| 2018 | 1869 | }, |
| 2019 | 1870 | |
| ... | ... | @@ -2021,23 +1872,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2021 | 1872 | const lhs = opt_ctx.get() ?? continue; |
| 2022 | 1873 | |
| 2023 | 1874 | if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| { |
| 2024 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2025 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1875 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1876 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2026 | 1877 | .lhs = lhs, |
| 2027 | 1878 | .op_token = pipe, |
| 2028 | 1879 | .op = ast.Node.InfixOp.Op.BitOr, |
| 2029 | 1880 | .rhs = undefined, |
| 2030 | 1881 | }); |
| 2031 | 1882 | opt_ctx.store(&node.base); |
| 2032 | stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2033 | try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1883 | stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1884 | try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2034 | 1885 | continue; |
| 2035 | 1886 | } |
| 2036 | 1887 | }, |
| 2037 | 1888 | |
| 2038 | 1889 | State.BinaryXorExpressionBegin => |opt_ctx| { |
| 2039 | stack.append(State { .BinaryXorExpressionEnd = opt_ctx }) catch unreachable; | |
| 2040 | try stack.append(State { .BinaryAndExpressionBegin = opt_ctx }); | |
| 1890 | stack.append(State{ .BinaryXorExpressionEnd = opt_ctx }) catch unreachable; | |
| 1891 | try stack.append(State{ .BinaryAndExpressionBegin = opt_ctx }); | |
| 2041 | 1892 | continue; |
| 2042 | 1893 | }, |
| 2043 | 1894 | |
| ... | ... | @@ -2045,23 +1896,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2045 | 1896 | const lhs = opt_ctx.get() ?? continue; |
| 2046 | 1897 | |
| 2047 | 1898 | if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| { |
| 2048 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2049 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1899 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1900 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2050 | 1901 | .lhs = lhs, |
| 2051 | 1902 | .op_token = caret, |
| 2052 | 1903 | .op = ast.Node.InfixOp.Op.BitXor, |
| 2053 | 1904 | .rhs = undefined, |
| 2054 | 1905 | }); |
| 2055 | 1906 | opt_ctx.store(&node.base); |
| 2056 | stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2057 | try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1907 | stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1908 | try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2058 | 1909 | continue; |
| 2059 | 1910 | } |
| 2060 | 1911 | }, |
| 2061 | 1912 | |
| 2062 | 1913 | State.BinaryAndExpressionBegin => |opt_ctx| { |
| 2063 | stack.append(State { .BinaryAndExpressionEnd = opt_ctx }) catch unreachable; | |
| 2064 | try stack.append(State { .BitShiftExpressionBegin = opt_ctx }); | |
| 1914 | stack.append(State{ .BinaryAndExpressionEnd = opt_ctx }) catch unreachable; | |
| 1915 | try stack.append(State{ .BitShiftExpressionBegin = opt_ctx }); | |
| 2065 | 1916 | continue; |
| 2066 | 1917 | }, |
| 2067 | 1918 | |
| ... | ... | @@ -2069,23 +1920,23 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2069 | 1920 | const lhs = opt_ctx.get() ?? continue; |
| 2070 | 1921 | |
| 2071 | 1922 | if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| { |
| 2072 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2073 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1923 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1924 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2074 | 1925 | .lhs = lhs, |
| 2075 | 1926 | .op_token = ampersand, |
| 2076 | 1927 | .op = ast.Node.InfixOp.Op.BitAnd, |
| 2077 | 1928 | .rhs = undefined, |
| 2078 | 1929 | }); |
| 2079 | 1930 | opt_ctx.store(&node.base); |
| 2080 | stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2081 | try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1931 | stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1932 | try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2082 | 1933 | continue; |
| 2083 | 1934 | } |
| 2084 | 1935 | }, |
| 2085 | 1936 | |
| 2086 | 1937 | State.BitShiftExpressionBegin => |opt_ctx| { |
| 2087 | stack.append(State { .BitShiftExpressionEnd = opt_ctx }) catch unreachable; | |
| 2088 | try stack.append(State { .AdditionExpressionBegin = opt_ctx }); | |
| 1938 | stack.append(State{ .BitShiftExpressionEnd = opt_ctx }) catch unreachable; | |
| 1939 | try stack.append(State{ .AdditionExpressionBegin = opt_ctx }); | |
| 2089 | 1940 | continue; |
| 2090 | 1941 | }, |
| 2091 | 1942 | |
| ... | ... | @@ -2096,16 +1947,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2096 | 1947 | const token_index = token.index; |
| 2097 | 1948 | const token_ptr = token.ptr; |
| 2098 | 1949 | if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| { |
| 2099 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2100 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1950 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1951 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2101 | 1952 | .lhs = lhs, |
| 2102 | 1953 | .op_token = token_index, |
| 2103 | 1954 | .op = bitshift_id, |
| 2104 | 1955 | .rhs = undefined, |
| 2105 | 1956 | }); |
| 2106 | 1957 | opt_ctx.store(&node.base); |
| 2107 | stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2108 | try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1958 | stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1959 | try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2109 | 1960 | continue; |
| 2110 | 1961 | } else { |
| 2111 | 1962 | putBackToken(&tok_it, &tree); |
| ... | ... | @@ -2114,8 +1965,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2114 | 1965 | }, |
| 2115 | 1966 | |
| 2116 | 1967 | State.AdditionExpressionBegin => |opt_ctx| { |
| 2117 | stack.append(State { .AdditionExpressionEnd = opt_ctx }) catch unreachable; | |
| 2118 | try stack.append(State { .MultiplyExpressionBegin = opt_ctx }); | |
| 1968 | stack.append(State{ .AdditionExpressionEnd = opt_ctx }) catch unreachable; | |
| 1969 | try stack.append(State{ .MultiplyExpressionBegin = opt_ctx }); | |
| 2119 | 1970 | continue; |
| 2120 | 1971 | }, |
| 2121 | 1972 | |
| ... | ... | @@ -2126,16 +1977,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2126 | 1977 | const token_index = token.index; |
| 2127 | 1978 | const token_ptr = token.ptr; |
| 2128 | 1979 | if (tokenIdToAddition(token_ptr.id)) |add_id| { |
| 2129 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2130 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 1980 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 1981 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2131 | 1982 | .lhs = lhs, |
| 2132 | 1983 | .op_token = token_index, |
| 2133 | 1984 | .op = add_id, |
| 2134 | 1985 | .rhs = undefined, |
| 2135 | 1986 | }); |
| 2136 | 1987 | opt_ctx.store(&node.base); |
| 2137 | stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2138 | try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 1988 | stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 1989 | try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2139 | 1990 | continue; |
| 2140 | 1991 | } else { |
| 2141 | 1992 | putBackToken(&tok_it, &tree); |
| ... | ... | @@ -2144,8 +1995,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2144 | 1995 | }, |
| 2145 | 1996 | |
| 2146 | 1997 | State.MultiplyExpressionBegin => |opt_ctx| { |
| 2147 | stack.append(State { .MultiplyExpressionEnd = opt_ctx }) catch unreachable; | |
| 2148 | try stack.append(State { .CurlySuffixExpressionBegin = opt_ctx }); | |
| 1998 | stack.append(State{ .MultiplyExpressionEnd = opt_ctx }) catch unreachable; | |
| 1999 | try stack.append(State{ .CurlySuffixExpressionBegin = opt_ctx }); | |
| 2149 | 2000 | continue; |
| 2150 | 2001 | }, |
| 2151 | 2002 | |
| ... | ... | @@ -2156,16 +2007,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2156 | 2007 | const token_index = token.index; |
| 2157 | 2008 | const token_ptr = token.ptr; |
| 2158 | 2009 | if (tokenIdToMultiply(token_ptr.id)) |mult_id| { |
| 2159 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2160 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 2010 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 2011 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2161 | 2012 | .lhs = lhs, |
| 2162 | 2013 | .op_token = token_index, |
| 2163 | 2014 | .op = mult_id, |
| 2164 | 2015 | .rhs = undefined, |
| 2165 | 2016 | }); |
| 2166 | 2017 | opt_ctx.store(&node.base); |
| 2167 | stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2168 | try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } }); | |
| 2018 | stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2019 | try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } }); | |
| 2169 | 2020 | continue; |
| 2170 | 2021 | } else { |
| 2171 | 2022 | putBackToken(&tok_it, &tree); |
| ... | ... | @@ -2174,9 +2025,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2174 | 2025 | }, |
| 2175 | 2026 | |
| 2176 | 2027 | State.CurlySuffixExpressionBegin => |opt_ctx| { |
| 2177 | stack.append(State { .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable; | |
| 2178 | try stack.append(State { .IfToken = Token.Id.LBrace }); | |
| 2179 | try stack.append(State { .TypeExprBegin = opt_ctx }); | |
| 2028 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable; | |
| 2029 | try stack.append(State{ .IfToken = Token.Id.LBrace }); | |
| 2030 | try stack.append(State{ .TypeExprBegin = opt_ctx }); | |
| 2180 | 2031 | continue; |
| 2181 | 2032 | }, |
| 2182 | 2033 | |
| ... | ... | @@ -2184,51 +2035,43 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2184 | 2035 | const lhs = opt_ctx.get() ?? continue; |
| 2185 | 2036 | |
| 2186 | 2037 | if ((??tok_it.peek()).id == Token.Id.Period) { |
| 2187 | const node = try arena.construct(ast.Node.SuffixOp { | |
| 2188 | .base = ast.Node { .id = ast.Node.Id.SuffixOp }, | |
| 2038 | const node = try arena.construct(ast.Node.SuffixOp{ | |
| 2039 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | |
| 2189 | 2040 | .lhs = lhs, |
| 2190 | .op = ast.Node.SuffixOp.Op { | |
| 2191 | .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena), | |
| 2192 | }, | |
| 2041 | .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, | |
| 2193 | 2042 | .rtoken = undefined, |
| 2194 | 2043 | }); |
| 2195 | 2044 | opt_ctx.store(&node.base); |
| 2196 | 2045 | |
| 2197 | stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2198 | try stack.append(State { .IfToken = Token.Id.LBrace }); | |
| 2199 | try stack.append(State { | |
| 2200 | .FieldInitListItemOrEnd = ListSave(@typeOf(node.op.StructInitializer)) { | |
| 2201 | .list = &node.op.StructInitializer, | |
| 2202 | .ptr = &node.rtoken, | |
| 2203 | } | |
| 2204 | }); | |
| 2046 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2047 | try stack.append(State{ .IfToken = Token.Id.LBrace }); | |
| 2048 | try stack.append(State{ .FieldInitListItemOrEnd = ListSave(@typeOf(node.op.StructInitializer)){ | |
| 2049 | .list = &node.op.StructInitializer, | |
| 2050 | .ptr = &node.rtoken, | |
| 2051 | } }); | |
| 2205 | 2052 | continue; |
| 2206 | 2053 | } |
| 2207 | 2054 | |
| 2208 | const node = try arena.construct(ast.Node.SuffixOp { | |
| 2209 | .base = ast.Node {.id = ast.Node.Id.SuffixOp }, | |
| 2055 | const node = try arena.construct(ast.Node.SuffixOp{ | |
| 2056 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | |
| 2210 | 2057 | .lhs = lhs, |
| 2211 | .op = ast.Node.SuffixOp.Op { | |
| 2212 | .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena), | |
| 2213 | }, | |
| 2058 | .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) }, | |
| 2214 | 2059 | .rtoken = undefined, |
| 2215 | 2060 | }); |
| 2216 | 2061 | opt_ctx.store(&node.base); |
| 2217 | stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2218 | try stack.append(State { .IfToken = Token.Id.LBrace }); | |
| 2219 | try stack.append(State { | |
| 2220 | .ExprListItemOrEnd = ExprListCtx { | |
| 2221 | .list = &node.op.ArrayInitializer, | |
| 2222 | .end = Token.Id.RBrace, | |
| 2223 | .ptr = &node.rtoken, | |
| 2224 | } | |
| 2225 | }); | |
| 2062 | stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2063 | try stack.append(State{ .IfToken = Token.Id.LBrace }); | |
| 2064 | try stack.append(State{ .ExprListItemOrEnd = ExprListCtx{ | |
| 2065 | .list = &node.op.ArrayInitializer, | |
| 2066 | .end = Token.Id.RBrace, | |
| 2067 | .ptr = &node.rtoken, | |
| 2068 | } }); | |
| 2226 | 2069 | continue; |
| 2227 | 2070 | }, |
| 2228 | 2071 | |
| 2229 | 2072 | State.TypeExprBegin => |opt_ctx| { |
| 2230 | stack.append(State { .TypeExprEnd = opt_ctx }) catch unreachable; | |
| 2231 | try stack.append(State { .PrefixOpExpression = opt_ctx }); | |
| 2073 | stack.append(State{ .TypeExprEnd = opt_ctx }) catch unreachable; | |
| 2074 | try stack.append(State{ .PrefixOpExpression = opt_ctx }); | |
| 2232 | 2075 | continue; |
| 2233 | 2076 | }, |
| 2234 | 2077 | |
| ... | ... | @@ -2236,16 +2079,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2236 | 2079 | const lhs = opt_ctx.get() ?? continue; |
| 2237 | 2080 | |
| 2238 | 2081 | if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| { |
| 2239 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2240 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 2082 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 2083 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2241 | 2084 | .lhs = lhs, |
| 2242 | 2085 | .op_token = bang, |
| 2243 | 2086 | .op = ast.Node.InfixOp.Op.ErrorUnion, |
| 2244 | 2087 | .rhs = undefined, |
| 2245 | 2088 | }); |
| 2246 | 2089 | opt_ctx.store(&node.base); |
| 2247 | stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2248 | try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } }); | |
| 2090 | stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2091 | try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } }); | |
| 2249 | 2092 | continue; |
| 2250 | 2093 | } |
| 2251 | 2094 | }, |
| ... | ... | @@ -2255,8 +2098,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2255 | 2098 | const token_index = token.index; |
| 2256 | 2099 | const token_ptr = token.ptr; |
| 2257 | 2100 | if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| { |
| 2258 | var node = try arena.construct(ast.Node.PrefixOp { | |
| 2259 | .base = ast.Node {.id = ast.Node.Id.PrefixOp }, | |
| 2101 | var node = try arena.construct(ast.Node.PrefixOp{ | |
| 2102 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | |
| 2260 | 2103 | .op_token = token_index, |
| 2261 | 2104 | .op = prefix_id, |
| 2262 | 2105 | .rhs = undefined, |
| ... | ... | @@ -2265,8 +2108,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2265 | 2108 | |
| 2266 | 2109 | // Treat '**' token as two derefs |
| 2267 | 2110 | if (token_ptr.id == Token.Id.AsteriskAsterisk) { |
| 2268 | const child = try arena.construct(ast.Node.PrefixOp { | |
| 2269 | .base = ast.Node {.id = ast.Node.Id.PrefixOp}, | |
| 2111 | const child = try arena.construct(ast.Node.PrefixOp{ | |
| 2112 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | |
| 2270 | 2113 | .op_token = token_index, |
| 2271 | 2114 | .op = prefix_id, |
| 2272 | 2115 | .rhs = undefined, |
| ... | ... | @@ -2275,40 +2118,38 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2275 | 2118 | node = child; |
| 2276 | 2119 | } |
| 2277 | 2120 | |
| 2278 | stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; | |
| 2121 | stack.append(State{ .TypeExprBegin = OptionalCtx{ .Required = &node.rhs } }) catch unreachable; | |
| 2279 | 2122 | if (node.op == ast.Node.PrefixOp.Op.AddrOf) { |
| 2280 | try stack.append(State { .AddrOfModifiers = &node.op.AddrOf }); | |
| 2123 | try stack.append(State{ .AddrOfModifiers = &node.op.AddrOf }); | |
| 2281 | 2124 | } |
| 2282 | 2125 | continue; |
| 2283 | 2126 | } else { |
| 2284 | 2127 | putBackToken(&tok_it, &tree); |
| 2285 | stack.append(State { .SuffixOpExpressionBegin = opt_ctx }) catch unreachable; | |
| 2128 | stack.append(State{ .SuffixOpExpressionBegin = opt_ctx }) catch unreachable; | |
| 2286 | 2129 | continue; |
| 2287 | 2130 | } |
| 2288 | 2131 | }, |
| 2289 | 2132 | |
| 2290 | 2133 | State.SuffixOpExpressionBegin => |opt_ctx| { |
| 2291 | 2134 | if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| { |
| 2292 | const async_node = try arena.construct(ast.Node.AsyncAttribute { | |
| 2293 | .base = ast.Node {.id = ast.Node.Id.AsyncAttribute}, | |
| 2135 | const async_node = try arena.construct(ast.Node.AsyncAttribute{ | |
| 2136 | .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute }, | |
| 2294 | 2137 | .async_token = async_token, |
| 2295 | 2138 | .allocator_type = null, |
| 2296 | 2139 | .rangle_bracket = null, |
| 2297 | 2140 | }); |
| 2298 | stack.append(State { | |
| 2299 | .AsyncEnd = AsyncEndCtx { | |
| 2300 | .ctx = opt_ctx, | |
| 2301 | .attribute = async_node, | |
| 2302 | } | |
| 2303 | }) catch unreachable; | |
| 2304 | try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }); | |
| 2305 | try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() }); | |
| 2306 | try stack.append(State { .AsyncAllocator = async_node }); | |
| 2141 | stack.append(State{ .AsyncEnd = AsyncEndCtx{ | |
| 2142 | .ctx = opt_ctx, | |
| 2143 | .attribute = async_node, | |
| 2144 | } }) catch unreachable; | |
| 2145 | try stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }); | |
| 2146 | try stack.append(State{ .PrimaryExpression = opt_ctx.toRequired() }); | |
| 2147 | try stack.append(State{ .AsyncAllocator = async_node }); | |
| 2307 | 2148 | continue; |
| 2308 | 2149 | } |
| 2309 | 2150 | |
| 2310 | stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable; | |
| 2311 | try stack.append(State { .PrimaryExpression = opt_ctx }); | |
| 2151 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx }) catch unreachable; | |
| 2152 | try stack.append(State{ .PrimaryExpression = opt_ctx }); | |
| 2312 | 2153 | continue; |
| 2313 | 2154 | }, |
| 2314 | 2155 | |
| ... | ... | @@ -2320,48 +2161,42 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2320 | 2161 | const token_ptr = token.ptr; |
| 2321 | 2162 | switch (token_ptr.id) { |
| 2322 | 2163 | Token.Id.LParen => { |
| 2323 | const node = try arena.construct(ast.Node.SuffixOp { | |
| 2324 | .base = ast.Node {.id = ast.Node.Id.SuffixOp }, | |
| 2164 | const node = try arena.construct(ast.Node.SuffixOp{ | |
| 2165 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | |
| 2325 | 2166 | .lhs = lhs, |
| 2326 | .op = ast.Node.SuffixOp.Op { | |
| 2327 | .Call = ast.Node.SuffixOp.Op.Call { | |
| 2328 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena), | |
| 2329 | .async_attr = null, | |
| 2330 | } | |
| 2331 | }, | |
| 2167 | .op = ast.Node.SuffixOp.Op{ .Call = ast.Node.SuffixOp.Op.Call{ | |
| 2168 | .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena), | |
| 2169 | .async_attr = null, | |
| 2170 | } }, | |
| 2332 | 2171 | .rtoken = undefined, |
| 2333 | 2172 | }); |
| 2334 | 2173 | opt_ctx.store(&node.base); |
| 2335 | 2174 | |
| 2336 | stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2337 | try stack.append(State { | |
| 2338 | .ExprListItemOrEnd = ExprListCtx { | |
| 2339 | .list = &node.op.Call.params, | |
| 2340 | .end = Token.Id.RParen, | |
| 2341 | .ptr = &node.rtoken, | |
| 2342 | } | |
| 2343 | }); | |
| 2175 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2176 | try stack.append(State{ .ExprListItemOrEnd = ExprListCtx{ | |
| 2177 | .list = &node.op.Call.params, | |
| 2178 | .end = Token.Id.RParen, | |
| 2179 | .ptr = &node.rtoken, | |
| 2180 | } }); | |
| 2344 | 2181 | continue; |
| 2345 | 2182 | }, |
| 2346 | 2183 | Token.Id.LBracket => { |
| 2347 | const node = try arena.construct(ast.Node.SuffixOp { | |
| 2348 | .base = ast.Node {.id = ast.Node.Id.SuffixOp }, | |
| 2184 | const node = try arena.construct(ast.Node.SuffixOp{ | |
| 2185 | .base = ast.Node{ .id = ast.Node.Id.SuffixOp }, | |
| 2349 | 2186 | .lhs = lhs, |
| 2350 | .op = ast.Node.SuffixOp.Op { | |
| 2351 | .ArrayAccess = undefined, | |
| 2352 | }, | |
| 2353 | .rtoken = undefined | |
| 2187 | .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined }, | |
| 2188 | .rtoken = undefined, | |
| 2354 | 2189 | }); |
| 2355 | 2190 | opt_ctx.store(&node.base); |
| 2356 | 2191 | |
| 2357 | stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2358 | try stack.append(State { .SliceOrArrayAccess = node }); | |
| 2359 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }}); | |
| 2192 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2193 | try stack.append(State{ .SliceOrArrayAccess = node }); | |
| 2194 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.op.ArrayAccess } }); | |
| 2360 | 2195 | continue; |
| 2361 | 2196 | }, |
| 2362 | 2197 | Token.Id.Period => { |
| 2363 | const node = try arena.construct(ast.Node.InfixOp { | |
| 2364 | .base = ast.Node {.id = ast.Node.Id.InfixOp }, | |
| 2198 | const node = try arena.construct(ast.Node.InfixOp{ | |
| 2199 | .base = ast.Node{ .id = ast.Node.Id.InfixOp }, | |
| 2365 | 2200 | .lhs = lhs, |
| 2366 | 2201 | .op_token = token_index, |
| 2367 | 2202 | .op = ast.Node.InfixOp.Op.Period, |
| ... | ... | @@ -2369,8 +2204,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2369 | 2204 | }); |
| 2370 | 2205 | opt_ctx.store(&node.base); |
| 2371 | 2206 | |
| 2372 | stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2373 | try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } }); | |
| 2207 | stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable; | |
| 2208 | try stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }); | |
| 2374 | 2209 | continue; |
| 2375 | 2210 | }, |
| 2376 | 2211 | else => { |
| ... | ... | @@ -2399,7 +2234,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2399 | 2234 | _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.UndefinedLiteral, token.index); |
| 2400 | 2235 | continue; |
| 2401 | 2236 | }, |
| 2402 | Token.Id.Keyword_true, Token.Id.Keyword_false => { | |
| 2237 | Token.Id.Keyword_true, | |
| 2238 | Token.Id.Keyword_false => { | |
| 2403 | 2239 | _ = try createToCtxLiteral(arena, opt_ctx, ast.Node.BoolLiteral, token.index); |
| 2404 | 2240 | continue; |
| 2405 | 2241 | }, |
| ... | ... | @@ -2420,10 +2256,8 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2420 | 2256 | continue; |
| 2421 | 2257 | }, |
| 2422 | 2258 | Token.Id.Keyword_promise => { |
| 2423 | const node = try arena.construct(ast.Node.PromiseType { | |
| 2424 | .base = ast.Node { | |
| 2425 | .id = ast.Node.Id.PromiseType, | |
| 2426 | }, | |
| 2259 | const node = try arena.construct(ast.Node.PromiseType{ | |
| 2260 | .base = ast.Node{ .id = ast.Node.Id.PromiseType }, | |
| 2427 | 2261 | .promise_token = token.index, |
| 2428 | 2262 | .result = null, |
| 2429 | 2263 | }); |
| ... | ... | @@ -2435,121 +2269,108 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2435 | 2269 | putBackToken(&tok_it, &tree); |
| 2436 | 2270 | continue; |
| 2437 | 2271 | } |
| 2438 | node.result = ast.Node.PromiseType.Result { | |
| 2272 | node.result = ast.Node.PromiseType.Result{ | |
| 2439 | 2273 | .arrow_token = next_token_index, |
| 2440 | 2274 | .return_type = undefined, |
| 2441 | 2275 | }; |
| 2442 | 2276 | const return_type_ptr = &((??node.result).return_type); |
| 2443 | try stack.append(State { .Expression = OptionalCtx { .Required = return_type_ptr, } }); | |
| 2277 | try stack.append(State{ .Expression = OptionalCtx{ .Required = return_type_ptr } }); | |
| 2444 | 2278 | continue; |
| 2445 | 2279 | }, |
| 2446 | Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => { | |
| 2280 | Token.Id.StringLiteral, | |
| 2281 | Token.Id.MultilineStringLiteralLine => { | |
| 2447 | 2282 | opt_ctx.store((try parseStringLiteral(arena, &tok_it, token.ptr, token.index, &tree)) ?? unreachable); |
| 2448 | 2283 | continue; |
| 2449 | 2284 | }, |
| 2450 | 2285 | Token.Id.LParen => { |
| 2451 | const node = try arena.construct(ast.Node.GroupedExpression { | |
| 2452 | .base = ast.Node {.id = ast.Node.Id.GroupedExpression }, | |
| 2286 | const node = try arena.construct(ast.Node.GroupedExpression{ | |
| 2287 | .base = ast.Node{ .id = ast.Node.Id.GroupedExpression }, | |
| 2453 | 2288 | .lparen = token.index, |
| 2454 | 2289 | .expr = undefined, |
| 2455 | 2290 | .rparen = undefined, |
| 2456 | 2291 | }); |
| 2457 | 2292 | opt_ctx.store(&node.base); |
| 2458 | 2293 | |
| 2459 | stack.append(State { | |
| 2460 | .ExpectTokenSave = ExpectTokenSave { | |
| 2461 | .id = Token.Id.RParen, | |
| 2462 | .ptr = &node.rparen, | |
| 2463 | } | |
| 2464 | }) catch unreachable; | |
| 2465 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); | |
| 2294 | stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 2295 | .id = Token.Id.RParen, | |
| 2296 | .ptr = &node.rparen, | |
| 2297 | } }) catch unreachable; | |
| 2298 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 2466 | 2299 | continue; |
| 2467 | 2300 | }, |
| 2468 | 2301 | Token.Id.Builtin => { |
| 2469 | const node = try arena.construct(ast.Node.BuiltinCall { | |
| 2470 | .base = ast.Node {.id = ast.Node.Id.BuiltinCall }, | |
| 2302 | const node = try arena.construct(ast.Node.BuiltinCall{ | |
| 2303 | .base = ast.Node{ .id = ast.Node.Id.BuiltinCall }, | |
| 2471 | 2304 | .builtin_token = token.index, |
| 2472 | 2305 | .params = ast.Node.BuiltinCall.ParamList.init(arena), |
| 2473 | 2306 | .rparen_token = undefined, |
| 2474 | 2307 | }); |
| 2475 | 2308 | opt_ctx.store(&node.base); |
| 2476 | 2309 | |
| 2477 | stack.append(State { | |
| 2478 | .ExprListItemOrEnd = ExprListCtx { | |
| 2479 | .list = &node.params, | |
| 2480 | .end = Token.Id.RParen, | |
| 2481 | .ptr = &node.rparen_token, | |
| 2482 | } | |
| 2483 | }) catch unreachable; | |
| 2484 | try stack.append(State { .ExpectToken = Token.Id.LParen, }); | |
| 2310 | stack.append(State{ .ExprListItemOrEnd = ExprListCtx{ | |
| 2311 | .list = &node.params, | |
| 2312 | .end = Token.Id.RParen, | |
| 2313 | .ptr = &node.rparen_token, | |
| 2314 | } }) catch unreachable; | |
| 2315 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 2485 | 2316 | continue; |
| 2486 | 2317 | }, |
| 2487 | 2318 | Token.Id.LBracket => { |
| 2488 | const node = try arena.construct(ast.Node.PrefixOp { | |
| 2489 | .base = ast.Node {.id = ast.Node.Id.PrefixOp }, | |
| 2319 | const node = try arena.construct(ast.Node.PrefixOp{ | |
| 2320 | .base = ast.Node{ .id = ast.Node.Id.PrefixOp }, | |
| 2490 | 2321 | .op_token = token.index, |
| 2491 | 2322 | .op = undefined, |
| 2492 | 2323 | .rhs = undefined, |
| 2493 | 2324 | }); |
| 2494 | 2325 | opt_ctx.store(&node.base); |
| 2495 | 2326 | |
| 2496 | stack.append(State { .SliceOrArrayType = node }) catch unreachable; | |
| 2327 | stack.append(State{ .SliceOrArrayType = node }) catch unreachable; | |
| 2497 | 2328 | continue; |
| 2498 | 2329 | }, |
| 2499 | 2330 | Token.Id.Keyword_error => { |
| 2500 | stack.append(State { | |
| 2501 | .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx { | |
| 2502 | .error_token = token.index, | |
| 2503 | .opt_ctx = opt_ctx | |
| 2504 | } | |
| 2505 | }) catch unreachable; | |
| 2331 | stack.append(State{ .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx{ | |
| 2332 | .error_token = token.index, | |
| 2333 | .opt_ctx = opt_ctx, | |
| 2334 | } }) catch unreachable; | |
| 2506 | 2335 | continue; |
| 2507 | 2336 | }, |
| 2508 | 2337 | Token.Id.Keyword_packed => { |
| 2509 | stack.append(State { | |
| 2510 | .ContainerKind = ContainerKindCtx { | |
| 2511 | .opt_ctx = opt_ctx, | |
| 2512 | .ltoken = token.index, | |
| 2513 | .layout = ast.Node.ContainerDecl.Layout.Packed, | |
| 2514 | }, | |
| 2515 | }) catch unreachable; | |
| 2338 | stack.append(State{ .ContainerKind = ContainerKindCtx{ | |
| 2339 | .opt_ctx = opt_ctx, | |
| 2340 | .ltoken = token.index, | |
| 2341 | .layout = ast.Node.ContainerDecl.Layout.Packed, | |
| 2342 | } }) catch unreachable; | |
| 2516 | 2343 | continue; |
| 2517 | 2344 | }, |
| 2518 | 2345 | Token.Id.Keyword_extern => { |
| 2519 | stack.append(State { | |
| 2520 | .ExternType = ExternTypeCtx { | |
| 2521 | .opt_ctx = opt_ctx, | |
| 2522 | .extern_token = token.index, | |
| 2523 | .comments = null, | |
| 2524 | }, | |
| 2525 | }) catch unreachable; | |
| 2346 | stack.append(State{ .ExternType = ExternTypeCtx{ | |
| 2347 | .opt_ctx = opt_ctx, | |
| 2348 | .extern_token = token.index, | |
| 2349 | .comments = null, | |
| 2350 | } }) catch unreachable; | |
| 2526 | 2351 | continue; |
| 2527 | 2352 | }, |
| 2528 | Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => { | |
| 2353 | Token.Id.Keyword_struct, | |
| 2354 | Token.Id.Keyword_union, | |
| 2355 | Token.Id.Keyword_enum => { | |
| 2529 | 2356 | putBackToken(&tok_it, &tree); |
| 2530 | stack.append(State { | |
| 2531 | .ContainerKind = ContainerKindCtx { | |
| 2532 | .opt_ctx = opt_ctx, | |
| 2533 | .ltoken = token.index, | |
| 2534 | .layout = ast.Node.ContainerDecl.Layout.Auto, | |
| 2535 | }, | |
| 2536 | }) catch unreachable; | |
| 2357 | stack.append(State{ .ContainerKind = ContainerKindCtx{ | |
| 2358 | .opt_ctx = opt_ctx, | |
| 2359 | .ltoken = token.index, | |
| 2360 | .layout = ast.Node.ContainerDecl.Layout.Auto, | |
| 2361 | } }) catch unreachable; | |
| 2537 | 2362 | continue; |
| 2538 | 2363 | }, |
| 2539 | 2364 | Token.Id.Identifier => { |
| 2540 | stack.append(State { | |
| 2541 | .MaybeLabeledExpression = MaybeLabeledExpressionCtx { | |
| 2542 | .label = token.index, | |
| 2543 | .opt_ctx = opt_ctx | |
| 2544 | } | |
| 2545 | }) catch unreachable; | |
| 2365 | stack.append(State{ .MaybeLabeledExpression = MaybeLabeledExpressionCtx{ | |
| 2366 | .label = token.index, | |
| 2367 | .opt_ctx = opt_ctx, | |
| 2368 | } }) catch unreachable; | |
| 2546 | 2369 | continue; |
| 2547 | 2370 | }, |
| 2548 | 2371 | Token.Id.Keyword_fn => { |
| 2549 | const fn_proto = try arena.construct(ast.Node.FnProto { | |
| 2550 | .base = ast.Node { | |
| 2551 | .id = ast.Node.Id.FnProto, | |
| 2552 | }, | |
| 2372 | const fn_proto = try arena.construct(ast.Node.FnProto{ | |
| 2373 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | |
| 2553 | 2374 | .doc_comments = null, |
| 2554 | 2375 | .visib_token = null, |
| 2555 | 2376 | .name_token = null, |
| ... | ... | @@ -2565,14 +2386,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2565 | 2386 | .align_expr = null, |
| 2566 | 2387 | }); |
| 2567 | 2388 | opt_ctx.store(&fn_proto.base); |
| 2568 | stack.append(State { .FnProto = fn_proto }) catch unreachable; | |
| 2389 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; | |
| 2569 | 2390 | continue; |
| 2570 | 2391 | }, |
| 2571 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { | |
| 2572 | const fn_proto = try arena.construct(ast.Node.FnProto { | |
| 2573 | .base = ast.Node { | |
| 2574 | .id = ast.Node.Id.FnProto, | |
| 2575 | }, | |
| 2392 | Token.Id.Keyword_nakedcc, | |
| 2393 | Token.Id.Keyword_stdcallcc => { | |
| 2394 | const fn_proto = try arena.construct(ast.Node.FnProto{ | |
| 2395 | .base = ast.Node{ .id = ast.Node.Id.FnProto }, | |
| 2576 | 2396 | .doc_comments = null, |
| 2577 | 2397 | .visib_token = null, |
| 2578 | 2398 | .name_token = null, |
| ... | ... | @@ -2588,18 +2408,16 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2588 | 2408 | .align_expr = null, |
| 2589 | 2409 | }); |
| 2590 | 2410 | opt_ctx.store(&fn_proto.base); |
| 2591 | stack.append(State { .FnProto = fn_proto }) catch unreachable; | |
| 2592 | try stack.append(State { | |
| 2593 | .ExpectTokenSave = ExpectTokenSave { | |
| 2594 | .id = Token.Id.Keyword_fn, | |
| 2595 | .ptr = &fn_proto.fn_token | |
| 2596 | } | |
| 2597 | }); | |
| 2411 | stack.append(State{ .FnProto = fn_proto }) catch unreachable; | |
| 2412 | try stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 2413 | .id = Token.Id.Keyword_fn, | |
| 2414 | .ptr = &fn_proto.fn_token, | |
| 2415 | } }); | |
| 2598 | 2416 | continue; |
| 2599 | 2417 | }, |
| 2600 | 2418 | Token.Id.Keyword_asm => { |
| 2601 | const node = try arena.construct(ast.Node.Asm { | |
| 2602 | .base = ast.Node {.id = ast.Node.Id.Asm }, | |
| 2419 | const node = try arena.construct(ast.Node.Asm{ | |
| 2420 | .base = ast.Node{ .id = ast.Node.Id.Asm }, | |
| 2603 | 2421 | .asm_token = token.index, |
| 2604 | 2422 | .volatile_token = null, |
| 2605 | 2423 | .template = undefined, |
| ... | ... | @@ -2610,94 +2428,77 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2610 | 2428 | }); |
| 2611 | 2429 | opt_ctx.store(&node.base); |
| 2612 | 2430 | |
| 2613 | stack.append(State { | |
| 2614 | .ExpectTokenSave = ExpectTokenSave { | |
| 2615 | .id = Token.Id.RParen, | |
| 2616 | .ptr = &node.rparen, | |
| 2617 | } | |
| 2618 | }) catch unreachable; | |
| 2619 | try stack.append(State { .AsmClobberItems = &node.clobbers }); | |
| 2620 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 2621 | try stack.append(State { .AsmInputItems = &node.inputs }); | |
| 2622 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 2623 | try stack.append(State { .AsmOutputItems = &node.outputs }); | |
| 2624 | try stack.append(State { .IfToken = Token.Id.Colon }); | |
| 2625 | try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.template } }); | |
| 2626 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 2627 | try stack.append(State { | |
| 2628 | .OptionalTokenSave = OptionalTokenSave { | |
| 2629 | .id = Token.Id.Keyword_volatile, | |
| 2630 | .ptr = &node.volatile_token, | |
| 2631 | } | |
| 2632 | }); | |
| 2431 | stack.append(State{ .ExpectTokenSave = ExpectTokenSave{ | |
| 2432 | .id = Token.Id.RParen, | |
| 2433 | .ptr = &node.rparen, | |
| 2434 | } }) catch unreachable; | |
| 2435 | try stack.append(State{ .AsmClobberItems = &node.clobbers }); | |
| 2436 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 2437 | try stack.append(State{ .AsmInputItems = &node.inputs }); | |
| 2438 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 2439 | try stack.append(State{ .AsmOutputItems = &node.outputs }); | |
| 2440 | try stack.append(State{ .IfToken = Token.Id.Colon }); | |
| 2441 | try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = &node.template } }); | |
| 2442 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 2443 | try stack.append(State{ .OptionalTokenSave = OptionalTokenSave{ | |
| 2444 | .id = Token.Id.Keyword_volatile, | |
| 2445 | .ptr = &node.volatile_token, | |
| 2446 | } }); | |
| 2633 | 2447 | }, |
| 2634 | 2448 | Token.Id.Keyword_inline => { |
| 2635 | stack.append(State { | |
| 2636 | .Inline = InlineCtx { | |
| 2637 | .label = null, | |
| 2638 | .inline_token = token.index, | |
| 2639 | .opt_ctx = opt_ctx, | |
| 2640 | } | |
| 2641 | }) catch unreachable; | |
| 2449 | stack.append(State{ .Inline = InlineCtx{ | |
| 2450 | .label = null, | |
| 2451 | .inline_token = token.index, | |
| 2452 | .opt_ctx = opt_ctx, | |
| 2453 | } }) catch unreachable; | |
| 2642 | 2454 | continue; |
| 2643 | 2455 | }, |
| 2644 | 2456 | else => { |
| 2645 | 2457 | if (!try parseBlockExpr(&stack, arena, opt_ctx, token.ptr, token.index)) { |
| 2646 | 2458 | putBackToken(&tok_it, &tree); |
| 2647 | 2459 | if (opt_ctx != OptionalCtx.Optional) { |
| 2648 | *(try tree.errors.addOne()) = Error { | |
| 2649 | .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr { .token = token.index }, | |
| 2650 | }; | |
| 2460 | ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token.index } }; | |
| 2651 | 2461 | return tree; |
| 2652 | 2462 | } |
| 2653 | 2463 | } |
| 2654 | 2464 | continue; |
| 2655 | } | |
| 2465 | }, | |
| 2656 | 2466 | } |
| 2657 | 2467 | }, |
| 2658 | 2468 | |
| 2659 | ||
| 2660 | 2469 | State.ErrorTypeOrSetDecl => |ctx| { |
| 2661 | 2470 | if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) { |
| 2662 | 2471 | _ = try createToCtxLiteral(arena, ctx.opt_ctx, ast.Node.ErrorType, ctx.error_token); |
| 2663 | 2472 | continue; |
| 2664 | 2473 | } |
| 2665 | 2474 | |
| 2666 | const node = try arena.construct(ast.Node.ErrorSetDecl { | |
| 2667 | .base = ast.Node { | |
| 2668 | .id = ast.Node.Id.ErrorSetDecl, | |
| 2669 | }, | |
| 2475 | const node = try arena.construct(ast.Node.ErrorSetDecl{ | |
| 2476 | .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl }, | |
| 2670 | 2477 | .error_token = ctx.error_token, |
| 2671 | 2478 | .decls = ast.Node.ErrorSetDecl.DeclList.init(arena), |
| 2672 | 2479 | .rbrace_token = undefined, |
| 2673 | 2480 | }); |
| 2674 | 2481 | ctx.opt_ctx.store(&node.base); |
| 2675 | 2482 | |
| 2676 | stack.append(State { | |
| 2677 | .ErrorTagListItemOrEnd = ListSave(@typeOf(node.decls)) { | |
| 2678 | .list = &node.decls, | |
| 2679 | .ptr = &node.rbrace_token, | |
| 2680 | } | |
| 2681 | }) catch unreachable; | |
| 2483 | stack.append(State{ .ErrorTagListItemOrEnd = ListSave(@typeOf(node.decls)){ | |
| 2484 | .list = &node.decls, | |
| 2485 | .ptr = &node.rbrace_token, | |
| 2486 | } }) catch unreachable; | |
| 2682 | 2487 | continue; |
| 2683 | 2488 | }, |
| 2684 | 2489 | State.StringLiteral => |opt_ctx| { |
| 2685 | 2490 | const token = nextToken(&tok_it, &tree); |
| 2686 | 2491 | const token_index = token.index; |
| 2687 | 2492 | const token_ptr = token.ptr; |
| 2688 | opt_ctx.store( | |
| 2689 | (try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? { | |
| 2690 | putBackToken(&tok_it, &tree); | |
| 2691 | if (opt_ctx != OptionalCtx.Optional) { | |
| 2692 | *(try tree.errors.addOne()) = Error { | |
| 2693 | .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr { .token = token_index }, | |
| 2694 | }; | |
| 2695 | return tree; | |
| 2696 | } | |
| 2697 | ||
| 2698 | continue; | |
| 2493 | opt_ctx.store((try parseStringLiteral(arena, &tok_it, token_ptr, token_index, &tree)) ?? { | |
| 2494 | putBackToken(&tok_it, &tree); | |
| 2495 | if (opt_ctx != OptionalCtx.Optional) { | |
| 2496 | ((try tree.errors.addOne())).* = Error{ .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = token_index } }; | |
| 2497 | return tree; | |
| 2699 | 2498 | } |
| 2700 | ); | |
| 2499 | ||
| 2500 | continue; | |
| 2501 | }); | |
| 2701 | 2502 | }, |
| 2702 | 2503 | |
| 2703 | 2504 | State.Identifier => |opt_ctx| { |
| ... | ... | @@ -2710,12 +2511,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2710 | 2511 | const token = nextToken(&tok_it, &tree); |
| 2711 | 2512 | const token_index = token.index; |
| 2712 | 2513 | const token_ptr = token.ptr; |
| 2713 | *(try tree.errors.addOne()) = Error { | |
| 2714 | .ExpectedToken = Error.ExpectedToken { | |
| 2715 | .token = token_index, | |
| 2716 | .expected_id = Token.Id.Identifier, | |
| 2717 | }, | |
| 2718 | }; | |
| 2514 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 2515 | .token = token_index, | |
| 2516 | .expected_id = Token.Id.Identifier, | |
| 2517 | } }; | |
| 2719 | 2518 | return tree; |
| 2720 | 2519 | } |
| 2721 | 2520 | }, |
| ... | ... | @@ -2726,23 +2525,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2726 | 2525 | const ident_token_index = ident_token.index; |
| 2727 | 2526 | const ident_token_ptr = ident_token.ptr; |
| 2728 | 2527 | if (ident_token_ptr.id != Token.Id.Identifier) { |
| 2729 | *(try tree.errors.addOne()) = Error { | |
| 2730 | .ExpectedToken = Error.ExpectedToken { | |
| 2731 | .token = ident_token_index, | |
| 2732 | .expected_id = Token.Id.Identifier, | |
| 2733 | }, | |
| 2734 | }; | |
| 2528 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 2529 | .token = ident_token_index, | |
| 2530 | .expected_id = Token.Id.Identifier, | |
| 2531 | } }; | |
| 2735 | 2532 | return tree; |
| 2736 | 2533 | } |
| 2737 | 2534 | |
| 2738 | const node = try arena.construct(ast.Node.ErrorTag { | |
| 2739 | .base = ast.Node { | |
| 2740 | .id = ast.Node.Id.ErrorTag, | |
| 2741 | }, | |
| 2535 | const node = try arena.construct(ast.Node.ErrorTag{ | |
| 2536 | .base = ast.Node{ .id = ast.Node.Id.ErrorTag }, | |
| 2742 | 2537 | .doc_comments = comments, |
| 2743 | 2538 | .name_token = ident_token_index, |
| 2744 | 2539 | }); |
| 2745 | *node_ptr = &node.base; | |
| 2540 | node_ptr.* = &node.base; | |
| 2746 | 2541 | continue; |
| 2747 | 2542 | }, |
| 2748 | 2543 | |
| ... | ... | @@ -2751,12 +2546,10 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2751 | 2546 | const token_index = token.index; |
| 2752 | 2547 | const token_ptr = token.ptr; |
| 2753 | 2548 | if (token_ptr.id != token_id) { |
| 2754 | *(try tree.errors.addOne()) = Error { | |
| 2755 | .ExpectedToken = Error.ExpectedToken { | |
| 2756 | .token = token_index, | |
| 2757 | .expected_id = token_id, | |
| 2758 | }, | |
| 2759 | }; | |
| 2549 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 2550 | .token = token_index, | |
| 2551 | .expected_id = token_id, | |
| 2552 | } }; | |
| 2760 | 2553 | return tree; |
| 2761 | 2554 | } |
| 2762 | 2555 | continue; |
| ... | ... | @@ -2766,15 +2559,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2766 | 2559 | const token_index = token.index; |
| 2767 | 2560 | const token_ptr = token.ptr; |
| 2768 | 2561 | if (token_ptr.id != expect_token_save.id) { |
| 2769 | *(try tree.errors.addOne()) = Error { | |
| 2770 | .ExpectedToken = Error.ExpectedToken { | |
| 2771 | .token = token_index, | |
| 2772 | .expected_id = expect_token_save.id, | |
| 2773 | }, | |
| 2774 | }; | |
| 2562 | ((try tree.errors.addOne())).* = Error{ .ExpectedToken = Error.ExpectedToken{ | |
| 2563 | .token = token_index, | |
| 2564 | .expected_id = expect_token_save.id, | |
| 2565 | } }; | |
| 2775 | 2566 | return tree; |
| 2776 | 2567 | } |
| 2777 | *expect_token_save.ptr = token_index; | |
| 2568 | (expect_token_save.ptr).* = token_index; | |
| 2778 | 2569 | continue; |
| 2779 | 2570 | }, |
| 2780 | 2571 | State.IfToken => |token_id| { |
| ... | ... | @@ -2787,7 +2578,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2787 | 2578 | }, |
| 2788 | 2579 | State.IfTokenSave => |if_token_save| { |
| 2789 | 2580 | if (eatToken(&tok_it, &tree, if_token_save.id)) |token_index| { |
| 2790 | *if_token_save.ptr = token_index; | |
| 2581 | (if_token_save.ptr).* = token_index; | |
| 2791 | 2582 | continue; |
| 2792 | 2583 | } |
| 2793 | 2584 | |
| ... | ... | @@ -2796,7 +2587,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree { |
| 2796 | 2587 | }, |
| 2797 | 2588 | State.OptionalTokenSave => |optional_token_save| { |
| 2798 | 2589 | if (eatToken(&tok_it, &tree, optional_token_save.id)) |token_index| { |
| 2799 | *optional_token_save.ptr = token_index; | |
| 2590 | (optional_token_save.ptr).* = token_index; | |
| 2800 | 2591 | continue; |
| 2801 | 2592 | } |
| 2802 | 2593 | |
| ... | ... | @@ -2919,28 +2710,28 @@ const OptionalCtx = union(enum) { |
| 2919 | 2710 | Required: &&ast.Node, |
| 2920 | 2711 | |
| 2921 | 2712 | pub fn store(self: &const OptionalCtx, value: &ast.Node) void { |
| 2922 | switch (*self) { | |
| 2923 | OptionalCtx.Optional => |ptr| *ptr = value, | |
| 2924 | OptionalCtx.RequiredNull => |ptr| *ptr = value, | |
| 2925 | OptionalCtx.Required => |ptr| *ptr = value, | |
| 2713 | switch (self.*) { | |
| 2714 | OptionalCtx.Optional => |ptr| ptr.* = value, | |
| 2715 | OptionalCtx.RequiredNull => |ptr| ptr.* = value, | |
| 2716 | OptionalCtx.Required => |ptr| ptr.* = value, | |
| 2926 | 2717 | } |
| 2927 | 2718 | } |
| 2928 | 2719 | |
| 2929 | 2720 | pub fn get(self: &const OptionalCtx) ?&ast.Node { |
| 2930 | switch (*self) { | |
| 2931 | OptionalCtx.Optional => |ptr| return *ptr, | |
| 2932 | OptionalCtx.RequiredNull => |ptr| return ??*ptr, | |
| 2933 | OptionalCtx.Required => |ptr| return *ptr, | |
| 2721 | switch (self.*) { | |
| 2722 | OptionalCtx.Optional => |ptr| return ptr.*, | |
| 2723 | OptionalCtx.RequiredNull => |ptr| return ??ptr.*, | |
| 2724 | OptionalCtx.Required => |ptr| return ptr.*, | |
| 2934 | 2725 | } |
| 2935 | 2726 | } |
| 2936 | 2727 | |
| 2937 | 2728 | pub fn toRequired(self: &const OptionalCtx) OptionalCtx { |
| 2938 | switch (*self) { | |
| 2729 | switch (self.*) { | |
| 2939 | 2730 | OptionalCtx.Optional => |ptr| { |
| 2940 | return OptionalCtx { .RequiredNull = ptr }; | |
| 2731 | return OptionalCtx{ .RequiredNull = ptr }; | |
| 2941 | 2732 | }, |
| 2942 | OptionalCtx.RequiredNull => |ptr| return *self, | |
| 2943 | OptionalCtx.Required => |ptr| return *self, | |
| 2733 | OptionalCtx.RequiredNull => |ptr| return self.*, | |
| 2734 | OptionalCtx.Required => |ptr| return self.*, | |
| 2944 | 2735 | } |
| 2945 | 2736 | } |
| 2946 | 2737 | }; |
| ... | ... | @@ -3062,7 +2853,6 @@ const State = union(enum) { |
| 3062 | 2853 | Identifier: OptionalCtx, |
| 3063 | 2854 | ErrorTag: &&ast.Node, |
| 3064 | 2855 | |
| 3065 | ||
| 3066 | 2856 | IfToken: @TagType(Token.Id), |
| 3067 | 2857 | IfTokenSave: ExpectTokenSave, |
| 3068 | 2858 | ExpectToken: @TagType(Token.Id), |
| ... | ... | @@ -3072,16 +2862,14 @@ const State = union(enum) { |
| 3072 | 2862 | |
| 3073 | 2863 | fn pushDocComment(arena: &mem.Allocator, line_comment: TokenIndex, result: &?&ast.Node.DocComment) !void { |
| 3074 | 2864 | const node = blk: { |
| 3075 | if (*result) |comment_node| { | |
| 2865 | if (result.*) |comment_node| { | |
| 3076 | 2866 | break :blk comment_node; |
| 3077 | 2867 | } else { |
| 3078 | const comment_node = try arena.construct(ast.Node.DocComment { | |
| 3079 | .base = ast.Node { | |
| 3080 | .id = ast.Node.Id.DocComment, | |
| 3081 | }, | |
| 2868 | const comment_node = try arena.construct(ast.Node.DocComment{ | |
| 2869 | .base = ast.Node{ .id = ast.Node.Id.DocComment }, | |
| 3082 | 2870 | .lines = ast.Node.DocComment.LineList.init(arena), |
| 3083 | 2871 | }); |
| 3084 | *result = comment_node; | |
| 2872 | result.* = comment_node; | |
| 3085 | 2873 | break :blk comment_node; |
| 3086 | 2874 | } |
| 3087 | 2875 | }; |
| ... | ... | @@ -3102,24 +2890,20 @@ fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, t |
| 3102 | 2890 | |
| 3103 | 2891 | fn eatLineComment(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.LineComment { |
| 3104 | 2892 | const token = eatToken(tok_it, tree, Token.Id.LineComment) ?? return null; |
| 3105 | return try arena.construct(ast.Node.LineComment { | |
| 3106 | .base = ast.Node { | |
| 3107 | .id = ast.Node.Id.LineComment, | |
| 3108 | }, | |
| 2893 | return try arena.construct(ast.Node.LineComment{ | |
| 2894 | .base = ast.Node{ .id = ast.Node.Id.LineComment }, | |
| 3109 | 2895 | .token = token, |
| 3110 | 2896 | }); |
| 3111 | 2897 | } |
| 3112 | 2898 | |
| 3113 | fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, | |
| 3114 | token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node | |
| 3115 | { | |
| 2899 | fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, token_ptr: &const Token, token_index: TokenIndex, tree: &ast.Tree) !?&ast.Node { | |
| 3116 | 2900 | switch (token_ptr.id) { |
| 3117 | 2901 | Token.Id.StringLiteral => { |
| 3118 | 2902 | return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base; |
| 3119 | 2903 | }, |
| 3120 | 2904 | Token.Id.MultilineStringLiteralLine => { |
| 3121 | const node = try arena.construct(ast.Node.MultilineStringLiteral { | |
| 3122 | .base = ast.Node { .id = ast.Node.Id.MultilineStringLiteral }, | |
| 2905 | const node = try arena.construct(ast.Node.MultilineStringLiteral{ | |
| 2906 | .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral }, | |
| 3123 | 2907 | .lines = ast.Node.MultilineStringLiteral.LineList.init(arena), |
| 3124 | 2908 | }); |
| 3125 | 2909 | try node.lines.push(token_index); |
| ... | ... | @@ -3143,12 +2927,11 @@ fn parseStringLiteral(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterato |
| 3143 | 2927 | } |
| 3144 | 2928 | } |
| 3145 | 2929 | |
| 3146 | fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, | |
| 3147 | token_ptr: &const Token, token_index: TokenIndex) !bool { | |
| 2930 | fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, token_ptr: &const Token, token_index: TokenIndex) !bool { | |
| 3148 | 2931 | switch (token_ptr.id) { |
| 3149 | 2932 | Token.Id.Keyword_suspend => { |
| 3150 | const node = try arena.construct(ast.Node.Suspend { | |
| 3151 | .base = ast.Node {.id = ast.Node.Id.Suspend }, | |
| 2933 | const node = try arena.construct(ast.Node.Suspend{ | |
| 2934 | .base = ast.Node{ .id = ast.Node.Id.Suspend }, | |
| 3152 | 2935 | .label = null, |
| 3153 | 2936 | .suspend_token = token_index, |
| 3154 | 2937 | .payload = null, |
| ... | ... | @@ -3156,13 +2939,13 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con |
| 3156 | 2939 | }); |
| 3157 | 2940 | ctx.store(&node.base); |
| 3158 | 2941 | |
| 3159 | stack.append(State { .SuspendBody = node }) catch unreachable; | |
| 3160 | try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } }); | |
| 2942 | stack.append(State{ .SuspendBody = node }) catch unreachable; | |
| 2943 | try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); | |
| 3161 | 2944 | return true; |
| 3162 | 2945 | }, |
| 3163 | 2946 | Token.Id.Keyword_if => { |
| 3164 | const node = try arena.construct(ast.Node.If { | |
| 3165 | .base = ast.Node {.id = ast.Node.Id.If }, | |
| 2947 | const node = try arena.construct(ast.Node.If{ | |
| 2948 | .base = ast.Node{ .id = ast.Node.Id.If }, | |
| 3166 | 2949 | .if_token = token_index, |
| 3167 | 2950 | .condition = undefined, |
| 3168 | 2951 | .payload = null, |
| ... | ... | @@ -3171,41 +2954,35 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con |
| 3171 | 2954 | }); |
| 3172 | 2955 | ctx.store(&node.base); |
| 3173 | 2956 | |
| 3174 | stack.append(State { .Else = &node.@"else" }) catch unreachable; | |
| 3175 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }); | |
| 3176 | try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } }); | |
| 3177 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 3178 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } }); | |
| 3179 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 2957 | stack.append(State{ .Else = &node.@"else" }) catch unreachable; | |
| 2958 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }); | |
| 2959 | try stack.append(State{ .PointerPayload = OptionalCtx{ .Optional = &node.payload } }); | |
| 2960 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 2961 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.condition } }); | |
| 2962 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 3180 | 2963 | return true; |
| 3181 | 2964 | }, |
| 3182 | 2965 | Token.Id.Keyword_while => { |
| 3183 | stack.append(State { | |
| 3184 | .While = LoopCtx { | |
| 3185 | .label = null, | |
| 3186 | .inline_token = null, | |
| 3187 | .loop_token = token_index, | |
| 3188 | .opt_ctx = *ctx, | |
| 3189 | } | |
| 3190 | }) catch unreachable; | |
| 2966 | stack.append(State{ .While = LoopCtx{ | |
| 2967 | .label = null, | |
| 2968 | .inline_token = null, | |
| 2969 | .loop_token = token_index, | |
| 2970 | .opt_ctx = ctx.*, | |
| 2971 | } }) catch unreachable; | |
| 3191 | 2972 | return true; |
| 3192 | 2973 | }, |
| 3193 | 2974 | Token.Id.Keyword_for => { |
| 3194 | stack.append(State { | |
| 3195 | .For = LoopCtx { | |
| 3196 | .label = null, | |
| 3197 | .inline_token = null, | |
| 3198 | .loop_token = token_index, | |
| 3199 | .opt_ctx = *ctx, | |
| 3200 | } | |
| 3201 | }) catch unreachable; | |
| 2975 | stack.append(State{ .For = LoopCtx{ | |
| 2976 | .label = null, | |
| 2977 | .inline_token = null, | |
| 2978 | .loop_token = token_index, | |
| 2979 | .opt_ctx = ctx.*, | |
| 2980 | } }) catch unreachable; | |
| 3202 | 2981 | return true; |
| 3203 | 2982 | }, |
| 3204 | 2983 | Token.Id.Keyword_switch => { |
| 3205 | const node = try arena.construct(ast.Node.Switch { | |
| 3206 | .base = ast.Node { | |
| 3207 | .id = ast.Node.Id.Switch, | |
| 3208 | }, | |
| 2984 | const node = try arena.construct(ast.Node.Switch{ | |
| 2985 | .base = ast.Node{ .id = ast.Node.Id.Switch }, | |
| 3209 | 2986 | .switch_token = token_index, |
| 3210 | 2987 | .expr = undefined, |
| 3211 | 2988 | .cases = ast.Node.Switch.CaseList.init(arena), |
| ... | ... | @@ -3213,45 +2990,43 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con |
| 3213 | 2990 | }); |
| 3214 | 2991 | ctx.store(&node.base); |
| 3215 | 2992 | |
| 3216 | stack.append(State { | |
| 3217 | .SwitchCaseOrEnd = ListSave(@typeOf(node.cases)) { | |
| 3218 | .list = &node.cases, | |
| 3219 | .ptr = &node.rbrace, | |
| 3220 | }, | |
| 3221 | }) catch unreachable; | |
| 3222 | try stack.append(State { .ExpectToken = Token.Id.LBrace }); | |
| 3223 | try stack.append(State { .ExpectToken = Token.Id.RParen }); | |
| 3224 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); | |
| 3225 | try stack.append(State { .ExpectToken = Token.Id.LParen }); | |
| 2993 | stack.append(State{ .SwitchCaseOrEnd = ListSave(@typeOf(node.cases)){ | |
| 2994 | .list = &node.cases, | |
| 2995 | .ptr = &node.rbrace, | |
| 2996 | } }) catch unreachable; | |
| 2997 | try stack.append(State{ .ExpectToken = Token.Id.LBrace }); | |
| 2998 | try stack.append(State{ .ExpectToken = Token.Id.RParen }); | |
| 2999 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 3000 | try stack.append(State{ .ExpectToken = Token.Id.LParen }); | |
| 3226 | 3001 | return true; |
| 3227 | 3002 | }, |
| 3228 | 3003 | Token.Id.Keyword_comptime => { |
| 3229 | const node = try arena.construct(ast.Node.Comptime { | |
| 3230 | .base = ast.Node {.id = ast.Node.Id.Comptime }, | |
| 3004 | const node = try arena.construct(ast.Node.Comptime{ | |
| 3005 | .base = ast.Node{ .id = ast.Node.Id.Comptime }, | |
| 3231 | 3006 | .comptime_token = token_index, |
| 3232 | 3007 | .expr = undefined, |
| 3233 | 3008 | .doc_comments = null, |
| 3234 | 3009 | }); |
| 3235 | 3010 | ctx.store(&node.base); |
| 3236 | 3011 | |
| 3237 | try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } }); | |
| 3012 | try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } }); | |
| 3238 | 3013 | return true; |
| 3239 | 3014 | }, |
| 3240 | 3015 | Token.Id.LBrace => { |
| 3241 | const block = try arena.construct(ast.Node.Block { | |
| 3242 | .base = ast.Node {.id = ast.Node.Id.Block }, | |
| 3016 | const block = try arena.construct(ast.Node.Block{ | |
| 3017 | .base = ast.Node{ .id = ast.Node.Id.Block }, | |
| 3243 | 3018 | .label = null, |
| 3244 | 3019 | .lbrace = token_index, |
| 3245 | 3020 | .statements = ast.Node.Block.StatementList.init(arena), |
| 3246 | 3021 | .rbrace = undefined, |
| 3247 | 3022 | }); |
| 3248 | 3023 | ctx.store(&block.base); |
| 3249 | stack.append(State { .Block = block }) catch unreachable; | |
| 3024 | stack.append(State{ .Block = block }) catch unreachable; | |
| 3250 | 3025 | return true; |
| 3251 | 3026 | }, |
| 3252 | 3027 | else => { |
| 3253 | 3028 | return false; |
| 3254 | } | |
| 3029 | }, | |
| 3255 | 3030 | } |
| 3256 | 3031 | } |
| 3257 | 3032 | |
| ... | ... | @@ -3265,20 +3040,16 @@ fn expectCommaOrEnd(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, end: |
| 3265 | 3040 | const token_index = token.index; |
| 3266 | 3041 | const token_ptr = token.ptr; |
| 3267 | 3042 | switch (token_ptr.id) { |
| 3268 | Token.Id.Comma => return ExpectCommaOrEndResult { .end_token = null}, | |
| 3043 | Token.Id.Comma => return ExpectCommaOrEndResult{ .end_token = null }, | |
| 3269 | 3044 | else => { |
| 3270 | 3045 | if (end == token_ptr.id) { |
| 3271 | return ExpectCommaOrEndResult { .end_token = token_index }; | |
| 3046 | return ExpectCommaOrEndResult{ .end_token = token_index }; | |
| 3272 | 3047 | } |
| 3273 | 3048 | |
| 3274 | return ExpectCommaOrEndResult { | |
| 3275 | .parse_error = Error { | |
| 3276 | .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd { | |
| 3277 | .token = token_index, | |
| 3278 | .end_id = end, | |
| 3279 | }, | |
| 3280 | }, | |
| 3281 | }; | |
| 3049 | return ExpectCommaOrEndResult{ .parse_error = Error{ .ExpectedCommaOrEnd = Error.ExpectedCommaOrEnd{ | |
| 3050 | .token = token_index, | |
| 3051 | .end_id = end, | |
| 3052 | } } }; | |
| 3282 | 3053 | }, |
| 3283 | 3054 | } |
| 3284 | 3055 | } |
| ... | ... | @@ -3286,103 +3057,102 @@ fn expectCommaOrEnd(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, end: |
| 3286 | 3057 | fn tokenIdToAssignment(id: &const Token.Id) ?ast.Node.InfixOp.Op { |
| 3287 | 3058 | // TODO: We have to cast all cases because of this: |
| 3288 | 3059 | // error: expected type '?InfixOp', found '?@TagType(InfixOp)' |
| 3289 | return switch (*id) { | |
| 3290 | Token.Id.AmpersandEqual => ast.Node.InfixOp.Op { .AssignBitAnd = {} }, | |
| 3291 | Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op { .AssignBitShiftLeft = {} }, | |
| 3292 | Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op { .AssignBitShiftRight = {} }, | |
| 3293 | Token.Id.AsteriskEqual => ast.Node.InfixOp.Op { .AssignTimes = {} }, | |
| 3294 | Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op { .AssignTimesWarp = {} }, | |
| 3295 | Token.Id.CaretEqual => ast.Node.InfixOp.Op { .AssignBitXor = {} }, | |
| 3296 | Token.Id.Equal => ast.Node.InfixOp.Op { .Assign = {} }, | |
| 3297 | Token.Id.MinusEqual => ast.Node.InfixOp.Op { .AssignMinus = {} }, | |
| 3298 | Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op { .AssignMinusWrap = {} }, | |
| 3299 | Token.Id.PercentEqual => ast.Node.InfixOp.Op { .AssignMod = {} }, | |
| 3300 | Token.Id.PipeEqual => ast.Node.InfixOp.Op { .AssignBitOr = {} }, | |
| 3301 | Token.Id.PlusEqual => ast.Node.InfixOp.Op { .AssignPlus = {} }, | |
| 3302 | Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op { .AssignPlusWrap = {} }, | |
| 3303 | Token.Id.SlashEqual => ast.Node.InfixOp.Op { .AssignDiv = {} }, | |
| 3060 | return switch (id.*) { | |
| 3061 | Token.Id.AmpersandEqual => ast.Node.InfixOp.Op{ .AssignBitAnd = {} }, | |
| 3062 | Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op{ .AssignBitShiftLeft = {} }, | |
| 3063 | Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op{ .AssignBitShiftRight = {} }, | |
| 3064 | Token.Id.AsteriskEqual => ast.Node.InfixOp.Op{ .AssignTimes = {} }, | |
| 3065 | Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op{ .AssignTimesWarp = {} }, | |
| 3066 | Token.Id.CaretEqual => ast.Node.InfixOp.Op{ .AssignBitXor = {} }, | |
| 3067 | Token.Id.Equal => ast.Node.InfixOp.Op{ .Assign = {} }, | |
| 3068 | Token.Id.MinusEqual => ast.Node.InfixOp.Op{ .AssignMinus = {} }, | |
| 3069 | Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op{ .AssignMinusWrap = {} }, | |
| 3070 | Token.Id.PercentEqual => ast.Node.InfixOp.Op{ .AssignMod = {} }, | |
| 3071 | Token.Id.PipeEqual => ast.Node.InfixOp.Op{ .AssignBitOr = {} }, | |
| 3072 | Token.Id.PlusEqual => ast.Node.InfixOp.Op{ .AssignPlus = {} }, | |
| 3073 | Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op{ .AssignPlusWrap = {} }, | |
| 3074 | Token.Id.SlashEqual => ast.Node.InfixOp.Op{ .AssignDiv = {} }, | |
| 3304 | 3075 | else => null, |
| 3305 | 3076 | }; |
| 3306 | 3077 | } |
| 3307 | 3078 | |
| 3308 | 3079 | fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { |
| 3309 | 3080 | return switch (id) { |
| 3310 | Token.Id.Keyword_catch => ast.Node.InfixOp.Op { .Catch = null }, | |
| 3311 | Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op { .UnwrapMaybe = void{} }, | |
| 3081 | Token.Id.Keyword_catch => ast.Node.InfixOp.Op{ .Catch = null }, | |
| 3082 | Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op{ .UnwrapMaybe = void{} }, | |
| 3312 | 3083 | else => null, |
| 3313 | 3084 | }; |
| 3314 | 3085 | } |
| 3315 | 3086 | |
| 3316 | 3087 | fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { |
| 3317 | 3088 | return switch (id) { |
| 3318 | Token.Id.BangEqual => ast.Node.InfixOp.Op { .BangEqual = void{} }, | |
| 3319 | Token.Id.EqualEqual => ast.Node.InfixOp.Op { .EqualEqual = void{} }, | |
| 3320 | Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op { .LessThan = void{} }, | |
| 3321 | Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op { .LessOrEqual = void{} }, | |
| 3322 | Token.Id.AngleBracketRight => ast.Node.InfixOp.Op { .GreaterThan = void{} }, | |
| 3323 | Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op { .GreaterOrEqual = void{} }, | |
| 3089 | Token.Id.BangEqual => ast.Node.InfixOp.Op{ .BangEqual = void{} }, | |
| 3090 | Token.Id.EqualEqual => ast.Node.InfixOp.Op{ .EqualEqual = void{} }, | |
| 3091 | Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op{ .LessThan = void{} }, | |
| 3092 | Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op{ .LessOrEqual = void{} }, | |
| 3093 | Token.Id.AngleBracketRight => ast.Node.InfixOp.Op{ .GreaterThan = void{} }, | |
| 3094 | Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op{ .GreaterOrEqual = void{} }, | |
| 3324 | 3095 | else => null, |
| 3325 | 3096 | }; |
| 3326 | 3097 | } |
| 3327 | 3098 | |
| 3328 | 3099 | fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { |
| 3329 | 3100 | return switch (id) { |
| 3330 | Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op { .BitShiftLeft = void{} }, | |
| 3331 | Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op { .BitShiftRight = void{} }, | |
| 3101 | Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op{ .BitShiftLeft = void{} }, | |
| 3102 | Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op{ .BitShiftRight = void{} }, | |
| 3332 | 3103 | else => null, |
| 3333 | 3104 | }; |
| 3334 | 3105 | } |
| 3335 | 3106 | |
| 3336 | 3107 | fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { |
| 3337 | 3108 | return switch (id) { |
| 3338 | Token.Id.Minus => ast.Node.InfixOp.Op { .Sub = void{} }, | |
| 3339 | Token.Id.MinusPercent => ast.Node.InfixOp.Op { .SubWrap = void{} }, | |
| 3340 | Token.Id.Plus => ast.Node.InfixOp.Op { .Add = void{} }, | |
| 3341 | Token.Id.PlusPercent => ast.Node.InfixOp.Op { .AddWrap = void{} }, | |
| 3342 | Token.Id.PlusPlus => ast.Node.InfixOp.Op { .ArrayCat = void{} }, | |
| 3109 | Token.Id.Minus => ast.Node.InfixOp.Op{ .Sub = void{} }, | |
| 3110 | Token.Id.MinusPercent => ast.Node.InfixOp.Op{ .SubWrap = void{} }, | |
| 3111 | Token.Id.Plus => ast.Node.InfixOp.Op{ .Add = void{} }, | |
| 3112 | Token.Id.PlusPercent => ast.Node.InfixOp.Op{ .AddWrap = void{} }, | |
| 3113 | Token.Id.PlusPlus => ast.Node.InfixOp.Op{ .ArrayCat = void{} }, | |
| 3343 | 3114 | else => null, |
| 3344 | 3115 | }; |
| 3345 | 3116 | } |
| 3346 | 3117 | |
| 3347 | 3118 | fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { |
| 3348 | 3119 | return switch (id) { |
| 3349 | Token.Id.Slash => ast.Node.InfixOp.Op { .Div = void{} }, | |
| 3350 | Token.Id.Asterisk => ast.Node.InfixOp.Op { .Mult = void{} }, | |
| 3351 | Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op { .ArrayMult = void{} }, | |
| 3352 | Token.Id.AsteriskPercent => ast.Node.InfixOp.Op { .MultWrap = void{} }, | |
| 3353 | Token.Id.Percent => ast.Node.InfixOp.Op { .Mod = void{} }, | |
| 3354 | Token.Id.PipePipe => ast.Node.InfixOp.Op { .MergeErrorSets = void{} }, | |
| 3120 | Token.Id.Slash => ast.Node.InfixOp.Op{ .Div = void{} }, | |
| 3121 | Token.Id.Asterisk => ast.Node.InfixOp.Op{ .Mult = void{} }, | |
| 3122 | Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op{ .ArrayMult = void{} }, | |
| 3123 | Token.Id.AsteriskPercent => ast.Node.InfixOp.Op{ .MultWrap = void{} }, | |
| 3124 | Token.Id.Percent => ast.Node.InfixOp.Op{ .Mod = void{} }, | |
| 3125 | Token.Id.PipePipe => ast.Node.InfixOp.Op{ .MergeErrorSets = void{} }, | |
| 3355 | 3126 | else => null, |
| 3356 | 3127 | }; |
| 3357 | 3128 | } |
| 3358 | 3129 | |
| 3359 | 3130 | fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op { |
| 3360 | 3131 | return switch (id) { |
| 3361 | Token.Id.Bang => ast.Node.PrefixOp.Op { .BoolNot = void{} }, | |
| 3362 | Token.Id.Tilde => ast.Node.PrefixOp.Op { .BitNot = void{} }, | |
| 3363 | Token.Id.Minus => ast.Node.PrefixOp.Op { .Negation = void{} }, | |
| 3364 | Token.Id.MinusPercent => ast.Node.PrefixOp.Op { .NegationWrap = void{} }, | |
| 3365 | Token.Id.Asterisk, Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op { .Deref = void{} }, | |
| 3366 | Token.Id.Ampersand => ast.Node.PrefixOp.Op { | |
| 3367 | .AddrOf = ast.Node.PrefixOp.AddrOfInfo { | |
| 3368 | .align_expr = null, | |
| 3369 | .bit_offset_start_token = null, | |
| 3370 | .bit_offset_end_token = null, | |
| 3371 | .const_token = null, | |
| 3372 | .volatile_token = null, | |
| 3373 | }, | |
| 3374 | }, | |
| 3375 | Token.Id.QuestionMark => ast.Node.PrefixOp.Op { .MaybeType = void{} }, | |
| 3376 | Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op { .UnwrapMaybe = void{} }, | |
| 3377 | Token.Id.Keyword_await => ast.Node.PrefixOp.Op { .Await = void{} }, | |
| 3378 | Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{ } }, | |
| 3132 | Token.Id.Bang => ast.Node.PrefixOp.Op{ .BoolNot = void{} }, | |
| 3133 | Token.Id.Tilde => ast.Node.PrefixOp.Op{ .BitNot = void{} }, | |
| 3134 | Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} }, | |
| 3135 | Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} }, | |
| 3136 | Token.Id.Asterisk, | |
| 3137 | Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} }, | |
| 3138 | Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{ | |
| 3139 | .align_expr = null, | |
| 3140 | .bit_offset_start_token = null, | |
| 3141 | .bit_offset_end_token = null, | |
| 3142 | .const_token = null, | |
| 3143 | .volatile_token = null, | |
| 3144 | } }, | |
| 3145 | Token.Id.QuestionMark => ast.Node.PrefixOp.Op{ .MaybeType = void{} }, | |
| 3146 | Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op{ .UnwrapMaybe = void{} }, | |
| 3147 | Token.Id.Keyword_await => ast.Node.PrefixOp.Op{ .Await = void{} }, | |
| 3148 | Token.Id.Keyword_try => ast.Node.PrefixOp.Op{ .Try = void{} }, | |
| 3379 | 3149 | else => null, |
| 3380 | 3150 | }; |
| 3381 | 3151 | } |
| 3382 | 3152 | |
| 3383 | 3153 | fn createLiteral(arena: &mem.Allocator, comptime T: type, token_index: TokenIndex) !&T { |
| 3384 | return arena.construct(T { | |
| 3385 | .base = ast.Node {.id = ast.Node.typeToId(T)}, | |
| 3154 | return arena.construct(T{ | |
| 3155 | .base = ast.Node{ .id = ast.Node.typeToId(T) }, | |
| 3386 | 3156 | .token = token_index, |
| 3387 | 3157 | }); |
| 3388 | 3158 | } |
| ... | ... | @@ -3397,15 +3167,14 @@ fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, compti |
| 3397 | 3167 | fn eatToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree, id: @TagType(Token.Id)) ?TokenIndex { |
| 3398 | 3168 | const token = nextToken(tok_it, tree); |
| 3399 | 3169 | |
| 3400 | if (token.ptr.id == id) | |
| 3401 | return token.index; | |
| 3170 | if (token.ptr.id == id) return token.index; | |
| 3402 | 3171 | |
| 3403 | 3172 | putBackToken(tok_it, tree); |
| 3404 | 3173 | return null; |
| 3405 | 3174 | } |
| 3406 | 3175 | |
| 3407 | 3176 | fn nextToken(tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) AnnotatedToken { |
| 3408 | const result = AnnotatedToken { | |
| 3177 | const result = AnnotatedToken{ | |
| 3409 | 3178 | .index = tok_it.index, |
| 3410 | 3179 | .ptr = ??tok_it.next(), |
| 3411 | 3180 | }; |
std/zig/render.zig+49-44| ... | ... | @@ -7,7 +7,7 @@ const Token = std.zig.Token; |
| 7 | 7 | |
| 8 | 8 | const indent_delta = 4; |
| 9 | 9 | |
| 10 | pub const Error = error { | |
| 10 | pub const Error = error{ | |
| 11 | 11 | /// Ran out of memory allocating call stack frames to complete rendering. |
| 12 | 12 | OutOfMemory, |
| 13 | 13 | }; |
| ... | ... | @@ -17,9 +17,9 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf( |
| 17 | 17 | |
| 18 | 18 | var it = tree.root_node.decls.iterator(0); |
| 19 | 19 | while (it.next()) |decl| { |
| 20 | try renderTopLevelDecl(allocator, stream, tree, 0, *decl); | |
| 20 | try renderTopLevelDecl(allocator, stream, tree, 0, decl.*); | |
| 21 | 21 | if (it.peek()) |next_decl| { |
| 22 | const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); | |
| 22 | const n = if (nodeLineOffset(tree, decl.*, next_decl.*) >= 2) u8(2) else u8(1); | |
| 23 | 23 | try stream.writeByteNTimes('\n', n); |
| 24 | 24 | } |
| 25 | 25 | } |
| ... | ... | @@ -154,10 +154,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 154 | 154 | var it = block.statements.iterator(0); |
| 155 | 155 | while (it.next()) |statement| { |
| 156 | 156 | try stream.writeByteNTimes(' ', block_indent); |
| 157 | try renderStatement(allocator, stream, tree, block_indent, *statement); | |
| 157 | try renderStatement(allocator, stream, tree, block_indent, statement.*); | |
| 158 | 158 | |
| 159 | 159 | if (it.peek()) |next_statement| { |
| 160 | const n = if (nodeLineOffset(tree, *statement, *next_statement) >= 2) u8(2) else u8(1); | |
| 160 | const n = if (nodeLineOffset(tree, statement.*, next_statement.*) >= 2) u8(2) else u8(1); | |
| 161 | 161 | try stream.writeByteNTimes('\n', n); |
| 162 | 162 | } |
| 163 | 163 | } |
| ... | ... | @@ -203,7 +203,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 203 | 203 | try stream.write(" "); |
| 204 | 204 | try renderExpression(allocator, stream, tree, indent, body); |
| 205 | 205 | } |
| 206 | ||
| 207 | 206 | }, |
| 208 | 207 | |
| 209 | 208 | ast.Node.Id.InfixOp => { |
| ... | ... | @@ -307,12 +306,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 307 | 306 | }, |
| 308 | 307 | ast.Node.PrefixOp.Op.BitNot => try stream.write("~"), |
| 309 | 308 | ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"), |
| 310 | ast.Node.PrefixOp.Op.Deref => try stream.write("*"), | |
| 311 | 309 | ast.Node.PrefixOp.Op.Negation => try stream.write("-"), |
| 312 | 310 | ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"), |
| 313 | 311 | ast.Node.PrefixOp.Op.Try => try stream.write("try "), |
| 314 | 312 | ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"), |
| 315 | 313 | ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"), |
| 314 | ast.Node.PrefixOp.Op.PointerType => try stream.write("*"), | |
| 316 | 315 | ast.Node.PrefixOp.Op.Await => try stream.write("await "), |
| 317 | 316 | ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "), |
| 318 | 317 | ast.Node.PrefixOp.Op.Resume => try stream.write("resume "), |
| ... | ... | @@ -336,7 +335,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 336 | 335 | |
| 337 | 336 | var it = call_info.params.iterator(0); |
| 338 | 337 | while (it.next()) |param_node| { |
| 339 | try renderExpression(allocator, stream, tree, indent, *param_node); | |
| 338 | try renderExpression(allocator, stream, tree, indent, param_node.*); | |
| 340 | 339 | if (it.peek() != null) { |
| 341 | 340 | try stream.write(", "); |
| 342 | 341 | } |
| ... | ... | @@ -352,6 +351,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 352 | 351 | try stream.write("]"); |
| 353 | 352 | }, |
| 354 | 353 | |
| 354 | ast.Node.SuffixOp.Op.Deref => { | |
| 355 | try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); | |
| 356 | try stream.write(".*"); | |
| 357 | }, | |
| 358 | ||
| 355 | 359 | @TagType(ast.Node.SuffixOp.Op).Slice => |range| { |
| 356 | 360 | try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); |
| 357 | 361 | try stream.write("["); |
| ... | ... | @@ -371,7 +375,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 371 | 375 | } |
| 372 | 376 | |
| 373 | 377 | if (field_inits.len == 1) { |
| 374 | const field_init = *field_inits.at(0); | |
| 378 | const field_init = field_inits.at(0).*; | |
| 375 | 379 | |
| 376 | 380 | try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); |
| 377 | 381 | try stream.write("{ "); |
| ... | ... | @@ -388,12 +392,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 388 | 392 | var it = field_inits.iterator(0); |
| 389 | 393 | while (it.next()) |field_init| { |
| 390 | 394 | try stream.writeByteNTimes(' ', new_indent); |
| 391 | try renderExpression(allocator, stream, tree, new_indent, *field_init); | |
| 392 | if ((*field_init).id != ast.Node.Id.LineComment) { | |
| 395 | try renderExpression(allocator, stream, tree, new_indent, field_init.*); | |
| 396 | if ((field_init.*).id != ast.Node.Id.LineComment) { | |
| 393 | 397 | try stream.write(","); |
| 394 | 398 | } |
| 395 | 399 | if (it.peek()) |next_field_init| { |
| 396 | const n = if (nodeLineOffset(tree, *field_init, *next_field_init) >= 2) u8(2) else u8(1); | |
| 400 | const n = if (nodeLineOffset(tree, field_init.*, next_field_init.*) >= 2) u8(2) else u8(1); | |
| 397 | 401 | try stream.writeByteNTimes('\n', n); |
| 398 | 402 | } |
| 399 | 403 | } |
| ... | ... | @@ -404,14 +408,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 404 | 408 | }, |
| 405 | 409 | |
| 406 | 410 | ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { |
| 407 | ||
| 408 | 411 | if (exprs.len == 0) { |
| 409 | 412 | try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); |
| 410 | 413 | try stream.write("{}"); |
| 411 | 414 | return; |
| 412 | 415 | } |
| 413 | 416 | if (exprs.len == 1) { |
| 414 | const expr = *exprs.at(0); | |
| 417 | const expr = exprs.at(0).*; | |
| 415 | 418 | |
| 416 | 419 | try renderExpression(allocator, stream, tree, indent, suffix_op.lhs); |
| 417 | 420 | try stream.write("{"); |
| ... | ... | @@ -428,11 +431,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 428 | 431 | var it = exprs.iterator(0); |
| 429 | 432 | while (it.next()) |expr| { |
| 430 | 433 | try stream.writeByteNTimes(' ', new_indent); |
| 431 | try renderExpression(allocator, stream, tree, new_indent, *expr); | |
| 434 | try renderExpression(allocator, stream, tree, new_indent, expr.*); | |
| 432 | 435 | try stream.write(","); |
| 433 | 436 | |
| 434 | 437 | if (it.peek()) |next_expr| { |
| 435 | const n = if (nodeLineOffset(tree, *expr, *next_expr) >= 2) u8(2) else u8(1); | |
| 438 | const n = if (nodeLineOffset(tree, expr.*, next_expr.*) >= 2) u8(2) else u8(1); | |
| 436 | 439 | try stream.writeByteNTimes('\n', n); |
| 437 | 440 | } |
| 438 | 441 | } |
| ... | ... | @@ -465,7 +468,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 465 | 468 | ast.Node.ControlFlowExpression.Kind.Return => { |
| 466 | 469 | try stream.print("return"); |
| 467 | 470 | }, |
| 468 | ||
| 469 | 471 | } |
| 470 | 472 | |
| 471 | 473 | if (flow_expr.rhs) |rhs| { |
| ... | ... | @@ -571,7 +573,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 571 | 573 | switch (container_decl.layout) { |
| 572 | 574 | ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "), |
| 573 | 575 | ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "), |
| 574 | ast.Node.ContainerDecl.Layout.Auto => { }, | |
| 576 | ast.Node.ContainerDecl.Layout.Auto => {}, | |
| 575 | 577 | } |
| 576 | 578 | |
| 577 | 579 | switch (container_decl.kind) { |
| ... | ... | @@ -607,10 +609,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 607 | 609 | var it = container_decl.fields_and_decls.iterator(0); |
| 608 | 610 | while (it.next()) |decl| { |
| 609 | 611 | try stream.writeByteNTimes(' ', new_indent); |
| 610 | try renderTopLevelDecl(allocator, stream, tree, new_indent, *decl); | |
| 612 | try renderTopLevelDecl(allocator, stream, tree, new_indent, decl.*); | |
| 611 | 613 | |
| 612 | 614 | if (it.peek()) |next_decl| { |
| 613 | const n = if (nodeLineOffset(tree, *decl, *next_decl) >= 2) u8(2) else u8(1); | |
| 615 | const n = if (nodeLineOffset(tree, decl.*, next_decl.*) >= 2) u8(2) else u8(1); | |
| 614 | 616 | try stream.writeByteNTimes('\n', n); |
| 615 | 617 | } |
| 616 | 618 | } |
| ... | ... | @@ -630,7 +632,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 630 | 632 | } |
| 631 | 633 | |
| 632 | 634 | if (err_set_decl.decls.len == 1) blk: { |
| 633 | const node = *err_set_decl.decls.at(0); | |
| 635 | const node = err_set_decl.decls.at(0).*; | |
| 634 | 636 | |
| 635 | 637 | // if there are any doc comments or same line comments |
| 636 | 638 | // don't try to put it all on one line |
| ... | ... | @@ -640,7 +642,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 640 | 642 | break :blk; |
| 641 | 643 | } |
| 642 | 644 | |
| 643 | ||
| 644 | 645 | try stream.write("error{"); |
| 645 | 646 | try renderTopLevelDecl(allocator, stream, tree, indent, node); |
| 646 | 647 | try stream.write("}"); |
| ... | ... | @@ -653,12 +654,12 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 653 | 654 | var it = err_set_decl.decls.iterator(0); |
| 654 | 655 | while (it.next()) |node| { |
| 655 | 656 | try stream.writeByteNTimes(' ', new_indent); |
| 656 | try renderTopLevelDecl(allocator, stream, tree, new_indent, *node); | |
| 657 | if ((*node).id != ast.Node.Id.LineComment) { | |
| 657 | try renderTopLevelDecl(allocator, stream, tree, new_indent, node.*); | |
| 658 | if ((node.*).id != ast.Node.Id.LineComment) { | |
| 658 | 659 | try stream.write(","); |
| 659 | 660 | } |
| 660 | 661 | if (it.peek()) |next_node| { |
| 661 | const n = if (nodeLineOffset(tree, *node, *next_node) >= 2) u8(2) else u8(1); | |
| 662 | const n = if (nodeLineOffset(tree, node.*, next_node.*) >= 2) u8(2) else u8(1); | |
| 662 | 663 | try stream.writeByteNTimes('\n', n); |
| 663 | 664 | } |
| 664 | 665 | } |
| ... | ... | @@ -672,9 +673,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 672 | 673 | const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base); |
| 673 | 674 | try stream.print("\n"); |
| 674 | 675 | |
| 675 | var i : usize = 0; | |
| 676 | var i: usize = 0; | |
| 676 | 677 | while (i < multiline_str_literal.lines.len) : (i += 1) { |
| 677 | const t = *multiline_str_literal.lines.at(i); | |
| 678 | const t = multiline_str_literal.lines.at(i).*; | |
| 678 | 679 | try stream.writeByteNTimes(' ', indent + indent_delta); |
| 679 | 680 | try stream.print("{}", tree.tokenSlice(t)); |
| 680 | 681 | } |
| ... | ... | @@ -691,7 +692,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 691 | 692 | |
| 692 | 693 | var it = builtin_call.params.iterator(0); |
| 693 | 694 | while (it.next()) |param_node| { |
| 694 | try renderExpression(allocator, stream, tree, indent, *param_node); | |
| 695 | try renderExpression(allocator, stream, tree, indent, param_node.*); | |
| 695 | 696 | if (it.peek() != null) { |
| 696 | 697 | try stream.write(", "); |
| 697 | 698 | } |
| ... | ... | @@ -736,7 +737,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 736 | 737 | |
| 737 | 738 | var it = fn_proto.params.iterator(0); |
| 738 | 739 | while (it.next()) |param_decl_node| { |
| 739 | try renderParamDecl(allocator, stream, tree, indent, *param_decl_node); | |
| 740 | try renderParamDecl(allocator, stream, tree, indent, param_decl_node.*); | |
| 740 | 741 | |
| 741 | 742 | if (it.peek() != null) { |
| 742 | 743 | try stream.write(", "); |
| ... | ... | @@ -760,7 +761,6 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 760 | 761 | try renderExpression(allocator, stream, tree, indent, node); |
| 761 | 762 | }, |
| 762 | 763 | } |
| 763 | ||
| 764 | 764 | }, |
| 765 | 765 | |
| 766 | 766 | ast.Node.Id.PromiseType => { |
| ... | ... | @@ -797,10 +797,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 797 | 797 | var it = switch_node.cases.iterator(0); |
| 798 | 798 | while (it.next()) |node| { |
| 799 | 799 | try stream.writeByteNTimes(' ', new_indent); |
| 800 | try renderExpression(allocator, stream, tree, new_indent, *node); | |
| 800 | try renderExpression(allocator, stream, tree, new_indent, node.*); | |
| 801 | 801 | |
| 802 | 802 | if (it.peek()) |next_node| { |
| 803 | const n = if (nodeLineOffset(tree, *node, *next_node) >= 2) u8(2) else u8(1); | |
| 803 | const n = if (nodeLineOffset(tree, node.*, next_node.*) >= 2) u8(2) else u8(1); | |
| 804 | 804 | try stream.writeByteNTimes('\n', n); |
| 805 | 805 | } |
| 806 | 806 | } |
| ... | ... | @@ -815,7 +815,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 815 | 815 | |
| 816 | 816 | var it = switch_case.items.iterator(0); |
| 817 | 817 | while (it.next()) |node| { |
| 818 | try renderExpression(allocator, stream, tree, indent, *node); | |
| 818 | try renderExpression(allocator, stream, tree, indent, node.*); | |
| 819 | 819 | |
| 820 | 820 | if (it.peek() != null) { |
| 821 | 821 | try stream.write(",\n"); |
| ... | ... | @@ -864,8 +864,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 864 | 864 | try stream.print("{}", tree.tokenSlice(else_node.else_token)); |
| 865 | 865 | |
| 866 | 866 | const block_body = switch (else_node.body.id) { |
| 867 | ast.Node.Id.Block, ast.Node.Id.If, | |
| 868 | ast.Node.Id.For, ast.Node.Id.While, | |
| 867 | ast.Node.Id.Block, | |
| 868 | ast.Node.Id.If, | |
| 869 | ast.Node.Id.For, | |
| 870 | ast.Node.Id.While, | |
| 869 | 871 | ast.Node.Id.Switch => true, |
| 870 | 872 | else => false, |
| 871 | 873 | }; |
| ... | ... | @@ -990,7 +992,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 990 | 992 | try renderExpression(allocator, stream, tree, indent, if_node.body); |
| 991 | 993 | |
| 992 | 994 | switch (if_node.body.id) { |
| 993 | ast.Node.Id.Block, ast.Node.Id.If, ast.Node.Id.For, ast.Node.Id.While, ast.Node.Id.Switch => { | |
| 995 | ast.Node.Id.Block, | |
| 996 | ast.Node.Id.If, | |
| 997 | ast.Node.Id.For, | |
| 998 | ast.Node.Id.While, | |
| 999 | ast.Node.Id.Switch => { | |
| 994 | 1000 | if (if_node.@"else") |@"else"| { |
| 995 | 1001 | if (if_node.body.id == ast.Node.Id.Block) { |
| 996 | 1002 | try stream.write(" "); |
| ... | ... | @@ -1013,7 +1019,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1013 | 1019 | |
| 1014 | 1020 | try renderExpression(allocator, stream, tree, indent, @"else".body); |
| 1015 | 1021 | } |
| 1016 | } | |
| 1022 | }, | |
| 1017 | 1023 | } |
| 1018 | 1024 | }, |
| 1019 | 1025 | |
| ... | ... | @@ -1036,11 +1042,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1036 | 1042 | { |
| 1037 | 1043 | var it = asm_node.outputs.iterator(0); |
| 1038 | 1044 | while (it.next()) |asm_output| { |
| 1039 | const node = &(*asm_output).base; | |
| 1045 | const node = &(asm_output.*).base; | |
| 1040 | 1046 | try renderExpression(allocator, stream, tree, indent_extra, node); |
| 1041 | 1047 | |
| 1042 | 1048 | if (it.peek()) |next_asm_output| { |
| 1043 | const next_node = &(*next_asm_output).base; | |
| 1049 | const next_node = &(next_asm_output.*).base; | |
| 1044 | 1050 | const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); |
| 1045 | 1051 | try stream.writeByte(','); |
| 1046 | 1052 | try stream.writeByteNTimes('\n', n); |
| ... | ... | @@ -1056,11 +1062,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1056 | 1062 | { |
| 1057 | 1063 | var it = asm_node.inputs.iterator(0); |
| 1058 | 1064 | while (it.next()) |asm_input| { |
| 1059 | const node = &(*asm_input).base; | |
| 1065 | const node = &(asm_input.*).base; | |
| 1060 | 1066 | try renderExpression(allocator, stream, tree, indent_extra, node); |
| 1061 | 1067 | |
| 1062 | 1068 | if (it.peek()) |next_asm_input| { |
| 1063 | const next_node = &(*next_asm_input).base; | |
| 1069 | const next_node = &(next_asm_input.*).base; | |
| 1064 | 1070 | const n = if (nodeLineOffset(tree, node, next_node) >= 2) u8(2) else u8(1); |
| 1065 | 1071 | try stream.writeByte(','); |
| 1066 | 1072 | try stream.writeByteNTimes('\n', n); |
| ... | ... | @@ -1076,7 +1082,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind |
| 1076 | 1082 | { |
| 1077 | 1083 | var it = asm_node.clobbers.iterator(0); |
| 1078 | 1084 | while (it.next()) |node| { |
| 1079 | try renderExpression(allocator, stream, tree, indent_once, *node); | |
| 1085 | try renderExpression(allocator, stream, tree, indent_once, node.*); | |
| 1080 | 1086 | |
| 1081 | 1087 | if (it.peek() != null) { |
| 1082 | 1088 | try stream.write(", "); |
| ... | ... | @@ -1245,8 +1251,7 @@ fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) (@type |
| 1245 | 1251 | const comment = node.doc_comments ?? return; |
| 1246 | 1252 | var it = comment.lines.iterator(0); |
| 1247 | 1253 | while (it.next()) |line_token_index| { |
| 1248 | try stream.print("{}\n", tree.tokenSlice(*line_token_index)); | |
| 1254 | try stream.print("{}\n", tree.tokenSlice(line_token_index.*)); | |
| 1249 | 1255 | try stream.writeByteNTimes(' ', indent); |
| 1250 | 1256 | } |
| 1251 | 1257 | } |
| 1252 |
test/behavior.zig+1| ... | ... | @@ -35,6 +35,7 @@ comptime { |
| 35 | 35 | _ = @import("cases/namespace_depends_on_compile_var/index.zig"); |
| 36 | 36 | _ = @import("cases/new_stack_call.zig"); |
| 37 | 37 | _ = @import("cases/null.zig"); |
| 38 | _ = @import("cases/pointers.zig"); | |
| 38 | 39 | _ = @import("cases/pub_enum/index.zig"); |
| 39 | 40 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); |
| 40 | 41 | _ = @import("cases/reflection.zig"); |
test/cases/align.zig+60-26| ... | ... | @@ -10,7 +10,9 @@ test "global variable alignment" { |
| 10 | 10 | assert(@typeOf(slice) == []align(4) u8); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; } | |
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { | |
| 14 | return 1234; | |
| 15 | } | |
| 14 | 16 | fn noop1() align(1) void {} |
| 15 | 17 | fn noop4() align(4) void {} |
| 16 | 18 | |
| ... | ... | @@ -22,7 +24,6 @@ test "function alignment" { |
| 22 | 24 | noop4(); |
| 23 | 25 | } |
| 24 | 26 | |
| 25 | ||
| 26 | 27 | var baz: packed struct { |
| 27 | 28 | a: u32, |
| 28 | 29 | b: u32, |
| ... | ... | @@ -32,7 +33,6 @@ test "packed struct alignment" { |
| 32 | 33 | assert(@typeOf(&baz.b) == &align(1) u32); |
| 33 | 34 | } |
| 34 | 35 | |
| 35 | ||
| 36 | 36 | const blah: packed struct { |
| 37 | 37 | a: u3, |
| 38 | 38 | b: u3, |
| ... | ... | @@ -53,29 +53,43 @@ test "implicitly decreasing pointer alignment" { |
| 53 | 53 | assert(addUnaligned(&a, &b) == 7); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { return *a + *b; } | |
| 56 | fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { | |
| 57 | return a.* + b.*; | |
| 58 | } | |
| 57 | 59 | |
| 58 | 60 | test "implicitly decreasing slice alignment" { |
| 59 | 61 | const a: u32 align(4) = 3; |
| 60 | 62 | const b: u32 align(8) = 4; |
| 61 | 63 | assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); |
| 62 | 64 | } |
| 63 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; } | |
| 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { | |
| 66 | return a[0] + b[0]; | |
| 67 | } | |
| 64 | 68 | |
| 65 | 69 | test "specifying alignment allows pointer cast" { |
| 66 | 70 | testBytesAlign(0x33); |
| 67 | 71 | } |
| 68 | 72 | fn 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 | }; | |
| 70 | 79 | const ptr = @ptrCast(&u32, &bytes[0]); |
| 71 | assert(*ptr == 0x33333333); | |
| 80 | assert(ptr.* == 0x33333333); | |
| 72 | 81 | } |
| 73 | 82 | |
| 74 | 83 | test "specifying alignment allows slice cast" { |
| 75 | 84 | testBytesAlignSlice(0x33); |
| 76 | 85 | } |
| 77 | 86 | fn 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 | }; | |
| 79 | 93 | const slice = ([]u32)(bytes[0..]); |
| 80 | 94 | assert(slice[0] == 0x33333333); |
| 81 | 95 | } |
| ... | ... | @@ -89,11 +103,14 @@ fn expectsOnly1(x: &align(1) u32) void { |
| 89 | 103 | expects4(@alignCast(4, x)); |
| 90 | 104 | } |
| 91 | 105 | fn expects4(x: &align(4) u32) void { |
| 92 | *x += 1; | |
| 106 | x.* += 1; | |
| 93 | 107 | } |
| 94 | 108 | |
| 95 | 109 | test "@alignCast slices" { |
| 96 | var array align(4) = []u32{1, 1}; | |
| 110 | var array align(4) = []u32 { | |
| 111 | 1, | |
| 112 | 1, | |
| 113 | }; | |
| 97 | 114 | const slice = array[0..]; |
| 98 | 115 | sliceExpectsOnly1(slice); |
| 99 | 116 | assert(slice[0] == 2); |
| ... | ... | @@ -105,31 +122,34 @@ fn sliceExpects4(slice: []align(4) u32) void { |
| 105 | 122 | slice[0] += 1; |
| 106 | 123 | } |
| 107 | 124 | |
| 108 | ||
| 109 | 125 | test "implicitly decreasing fn alignment" { |
| 110 | 126 | testImplicitlyDecreaseFnAlign(alignedSmall, 1234); |
| 111 | 127 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); |
| 112 | 128 | } |
| 113 | 129 | |
| 114 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { | |
| 130 | fn testImplicitlyDecreaseFnAlign(ptr: fn() align(1) i32, answer: i32) void { | |
| 115 | 131 | assert(ptr() == answer); |
| 116 | 132 | } |
| 117 | 133 | |
| 118 | fn alignedSmall() align(8) i32 { return 1234; } | |
| 119 | fn alignedBig() align(16) i32 { return 5678; } | |
| 120 | ||
| 134 | fn alignedSmall() align(8) i32 { | |
| 135 | return 1234; | |
| 136 | } | |
| 137 | fn alignedBig() align(16) i32 { | |
| 138 | return 5678; | |
| 139 | } | |
| 121 | 140 | |
| 122 | 141 | test "@alignCast functions" { |
| 123 | 142 | assert(fnExpectsOnly1(simple4) == 0x19); |
| 124 | 143 | } |
| 125 | fn fnExpectsOnly1(ptr: fn()align(1) i32) i32 { | |
| 144 | fn fnExpectsOnly1(ptr: fn() align(1) i32) i32 { | |
| 126 | 145 | return fnExpects4(@alignCast(4, ptr)); |
| 127 | 146 | } |
| 128 | fn fnExpects4(ptr: fn()align(4) i32) i32 { | |
| 147 | fn fnExpects4(ptr: fn() align(4) i32) i32 { | |
| 129 | 148 | return ptr(); |
| 130 | 149 | } |
| 131 | fn simple4() align(4) i32 { return 0x19; } | |
| 132 | ||
| 150 | fn simple4() align(4) i32 { | |
| 151 | return 0x19; | |
| 152 | } | |
| 133 | 153 | |
| 134 | 154 | test "generic function with align param" { |
| 135 | 155 | assert(whyWouldYouEverDoThis(1) == 0x1); |
| ... | ... | @@ -137,8 +157,9 @@ test "generic function with align param" { |
| 137 | 157 | assert(whyWouldYouEverDoThis(8) == 0x1); |
| 138 | 158 | } |
| 139 | 159 | |
| 140 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { return 0x1; } | |
| 141 | ||
| 160 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { | |
| 161 | return 0x1; | |
| 162 | } | |
| 142 | 163 | |
| 143 | 164 | test "@ptrCast preserves alignment of bigger source" { |
| 144 | 165 | var x: u32 align(16) = 1234; |
| ... | ... | @@ -146,24 +167,38 @@ test "@ptrCast preserves alignment of bigger source" { |
| 146 | 167 | assert(@typeOf(ptr) == &align(16) u8); |
| 147 | 168 | } |
| 148 | 169 | |
| 149 | ||
| 150 | 170 | test "compile-time known array index has best alignment possible" { |
| 151 | 171 | // 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 | }; | |
| 153 | 178 | assert(@typeOf(&array[0]) == &align(4) u8); |
| 154 | 179 | assert(@typeOf(&array[1]) == &u8); |
| 155 | 180 | assert(@typeOf(&array[2]) == &align(2) u8); |
| 156 | 181 | assert(@typeOf(&array[3]) == &u8); |
| 157 | 182 | |
| 158 | 183 | // 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 | }; | |
| 160 | 190 | assert(@typeOf(&bigger[0]) == &align(2) u64); |
| 161 | 191 | assert(@typeOf(&bigger[1]) == &align(2) u64); |
| 162 | 192 | assert(@typeOf(&bigger[2]) == &align(2) u64); |
| 163 | 193 | assert(@typeOf(&bigger[3]) == &align(2) u64); |
| 164 | 194 | |
| 165 | 195 | // 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 | }; | |
| 167 | 202 | testIndex(&smaller[0], 0, &align(2) u32); |
| 168 | 203 | testIndex(&smaller[0], 1, &align(2) u32); |
| 169 | 204 | testIndex(&smaller[0], 2, &align(2) u32); |
| ... | ... | @@ -182,7 +217,6 @@ fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) void { |
| 182 | 217 | assert(@typeOf(&ptr[index]) == T); |
| 183 | 218 | } |
| 184 | 219 | |
| 185 | ||
| 186 | 220 | test "alignstack" { |
| 187 | 221 | assert(fnWithAlignedStack() == 1234); |
| 188 | 222 | } |
test/cases/alignof.zig+5-1| ... | ... | @@ -1,7 +1,11 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | const Foo = struct { x: u32, y: u32, z: u32, }; | |
| 4 | const Foo = struct { | |
| 5 | x: u32, | |
| 6 | y: u32, | |
| 7 | z: u32, | |
| 8 | }; | |
| 5 | 9 | |
| 6 | 10 | test "@alignOf(T) before referencing T" { |
| 7 | 11 | comptime assert(@alignOf(Foo) != @maxValue(usize)); |
test/cases/array.zig+31-10| ... | ... | @@ -2,9 +2,9 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | 3 | |
| 4 | 4 | test "arrays" { |
| 5 | var array : [5]u32 = undefined; | |
| 5 | var array: [5]u32 = undefined; | |
| 6 | 6 | |
| 7 | var i : u32 = 0; | |
| 7 | var i: u32 = 0; | |
| 8 | 8 | while (i < 5) { |
| 9 | 9 | array[i] = i + 1; |
| 10 | 10 | i = array[i]; |
| ... | ... | @@ -34,24 +34,41 @@ test "void arrays" { |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | test "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 | }; | |
| 38 | 43 | |
| 39 | 44 | assert(hex_mult.len == 4); |
| 40 | 45 | assert(hex_mult[1] == 256); |
| 41 | 46 | } |
| 42 | 47 | |
| 43 | 48 | test "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 | }); | |
| 45 | 52 | } |
| 46 | 53 | |
| 47 | 54 | const ArrayDotLenConstExpr = struct { |
| 48 | 55 | y: [some_array.len]u8, |
| 49 | 56 | }; |
| 50 | const some_array = []u8 {0, 1, 2, 3}; | |
| 51 | ||
| 57 | const some_array = []u8 { | |
| 58 | 0, | |
| 59 | 1, | |
| 60 | 2, | |
| 61 | 3, | |
| 62 | }; | |
| 52 | 63 | |
| 53 | 64 | test "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 | }; | |
| 55 | 72 | for (array_of_strings) |s, i| { |
| 56 | 73 | if (i == 0) assert(mem.eql(u8, s, "hello")); |
| 57 | 74 | if (i == 1) assert(mem.eql(u8, s, "this")); |
| ... | ... | @@ -61,7 +78,6 @@ test "nested arrays" { |
| 61 | 78 | } |
| 62 | 79 | } |
| 63 | 80 | |
| 64 | ||
| 65 | 81 | var s_array: [8]Sub = undefined; |
| 66 | 82 | const Sub = struct { |
| 67 | 83 | b: u8, |
| ... | ... | @@ -70,7 +86,9 @@ const Str = struct { |
| 70 | 86 | a: []Sub, |
| 71 | 87 | }; |
| 72 | 88 | test "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 | }; | |
| 74 | 92 | |
| 75 | 93 | s.a[0].b = 1; |
| 76 | 94 | s.a[1].b = 2; |
| ... | ... | @@ -82,7 +100,10 @@ test "set global var array via slice embedded in struct" { |
| 82 | 100 | } |
| 83 | 101 | |
| 84 | 102 | test "array literal with specified size" { |
| 85 | var array = [2]u8{1, 2}; | |
| 103 | var array = [2]u8 { | |
| 104 | 1, | |
| 105 | 2, | |
| 106 | }; | |
| 86 | 107 | assert(array[0] == 1); |
| 87 | 108 | assert(array[1] == 2); |
| 88 | 109 | } |
test/cases/bitcast.zig+6-2| ... | ... | @@ -10,5 +10,9 @@ fn testBitCast_i32_u32() void { |
| 10 | 10 | assert(conv2(@maxValue(u32)) == -1); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn conv(x: i32) u32 { return @bitCast(u32, x); } | |
| 14 | fn conv2(x: u32) i32 { return @bitCast(i32, x); } | |
| 13 | fn conv(x: i32) u32 { | |
| 14 | return @bitCast(u32, x); | |
| 15 | } | |
| 16 | fn conv2(x: u32) i32 { | |
| 17 | return @bitCast(i32, x); | |
| 18 | } |
test/cases/bugs/394.zig+14-3| ... | ... | @@ -1,9 +1,20 @@ |
| 1 | const E = union(enum) { A: [9]u8, B: u64, }; | |
| 2 | const S = struct { x: u8, y: E, }; | |
| 1 | const E = union(enum) { | |
| 2 | A: [9]u8, | |
| 3 | B: u64, | |
| 4 | }; | |
| 5 | const S = struct { | |
| 6 | x: u8, | |
| 7 | y: E, | |
| 8 | }; | |
| 3 | 9 | |
| 4 | 10 | const assert = @import("std").debug.assert; |
| 5 | 11 | |
| 6 | 12 | test "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 | }; | |
| 8 | 19 | assert(x.x == 3); |
| 9 | 20 | } |
test/cases/bugs/655.zig+1-1| ... | ... | @@ -8,5 +8,5 @@ test "function with &const parameter with type dereferenced by namespace" { |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | 10 | fn foo(x: &const other_file.Integer) void { |
| 11 | std.debug.assert(*x == 1234); | |
| 11 | std.debug.assert(x.* == 1234); | |
| 12 | 12 | } |
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 |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | fn 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 { | |
| 20 | 23 | switch (prefix_op) { |
| 21 | 24 | PrefixOp.AddrOf => |addr_of_info| { |
| 22 | if (b) { } | |
| 25 | if (b) {} | |
| 23 | 26 | if (addr_of_info.align_expr) |align_expr| { |
| 24 | 27 | assert(align_expr == 1234); |
| 25 | 28 | } |
test/cases/bugs/828.zig+5-5| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | 1 | const CountBy = struct { |
| 2 | 2 | a: usize, |
| 3 | ||
| 3 | ||
| 4 | 4 | const One = CountBy { |
| 5 | 5 | .a = 1, |
| 6 | 6 | }; |
| 7 | ||
| 7 | ||
| 8 | 8 | pub fn counter(self: &const CountBy) Counter { |
| 9 | 9 | return Counter { |
| 10 | 10 | .i = 0, |
| ... | ... | @@ -14,7 +14,7 @@ const CountBy = struct { |
| 14 | 14 | |
| 15 | 15 | const Counter = struct { |
| 16 | 16 | i: usize, |
| 17 | ||
| 17 | ||
| 18 | 18 | pub fn count(self: &Counter) bool { |
| 19 | 19 | self.i += 1; |
| 20 | 20 | return self.i <= 10; |
| ... | ... | @@ -24,8 +24,8 @@ const Counter = struct { |
| 24 | 24 | fn constCount(comptime cb: &const CountBy, comptime unused: u32) void { |
| 25 | 25 | comptime { |
| 26 | 26 | 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()) {} | |
| 29 | 29 | } |
| 30 | 30 | } |
| 31 | 31 |
test/cases/bugs/920.zig+12-7| ... | ... | @@ -12,8 +12,7 @@ const ZigTable = struct { |
| 12 | 12 | zero_case: fn(&Random, f64) f64, |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | fn 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 { | |
| 15 | fn 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 { | |
| 17 | 16 | var tables: ZigTable = undefined; |
| 18 | 17 | |
| 19 | 18 | tables.is_symmetric = is_symmetric; |
| ... | ... | @@ -26,12 +25,12 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co |
| 26 | 25 | |
| 27 | 26 | for (tables.x[2..256]) |*entry, i| { |
| 28 | 27 | const last = tables.x[2 + i - 1]; |
| 29 | *entry = f_inv(v / last + f(last)); | |
| 28 | entry.* = f_inv(v / last + f(last)); | |
| 30 | 29 | } |
| 31 | 30 | tables.x[256] = 0; |
| 32 | 31 | |
| 33 | 32 | for (tables.f[0..]) |*entry, i| { |
| 34 | *entry = f(tables.x[i]); | |
| 33 | entry.* = f(tables.x[i]); | |
| 35 | 34 | } |
| 36 | 35 | |
| 37 | 36 | return tables; |
| ... | ... | @@ -40,9 +39,15 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co |
| 40 | 39 | const norm_r = 3.6541528853610088; |
| 41 | 40 | const norm_v = 0.00492867323399; |
| 42 | 41 | |
| 43 | fn norm_f(x: f64) f64 { return math.exp(-x * x / 2.0); } | |
| 44 | fn norm_f_inv(y: f64) f64 { return math.sqrt(-2.0 * math.ln(y)); } | |
| 45 | fn norm_zero_case(random: &Random, u: f64) f64 { return 0.0; } | |
| 42 | fn norm_f(x: f64) f64 { | |
| 43 | return math.exp(-x * x / 2.0); | |
| 44 | } | |
| 45 | fn norm_f_inv(y: f64) f64 { | |
| 46 | return math.sqrt(-2.0 * math.ln(y)); | |
| 47 | } | |
| 48 | fn norm_zero_case(random: &Random, u: f64) f64 { | |
| 49 | return 0.0; | |
| 50 | } | |
| 46 | 51 | |
| 47 | 52 | const NormalDist = blk: { |
| 48 | 53 | @setEvalBranchQuota(30000); |
test/cases/cast.zig+42-28| ... | ... | @@ -17,7 +17,7 @@ test "pointer reinterpret const float to int" { |
| 17 | 17 | const float: f64 = 5.99999999999994648725e-01; |
| 18 | 18 | const float_ptr = &float; |
| 19 | 19 | const int_ptr = @ptrCast(&const i32, float_ptr); |
| 20 | const int_val = *int_ptr; | |
| 20 | const int_val = int_ptr.*; | |
| 21 | 21 | assert(int_val == 858993411); |
| 22 | 22 | } |
| 23 | 23 | |
| ... | ... | @@ -29,25 +29,31 @@ test "implicitly cast a pointer to a const pointer of it" { |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | 31 | fn funcWithConstPtrPtr(x: &const &i32) void { |
| 32 | **x += 1; | |
| 32 | x.*.* += 1; | |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | 35 | test "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 | }; | |
| 37 | 39 | assert(0 == @sizeOf(@typeOf(z))); |
| 38 | 40 | assert(void{} == Struct(void).pointer(z).x); |
| 39 | 41 | assert(void{} == Struct(void).pointer(&z).x); |
| 40 | 42 | assert(void{} == Struct(void).maybePointer(z).x); |
| 41 | 43 | assert(void{} == Struct(void).maybePointer(&z).x); |
| 42 | 44 | assert(void{} == Struct(void).maybePointer(null).x); |
| 43 | const s = Struct(u8) { .x = 42 }; | |
| 45 | const s = Struct(u8) { | |
| 46 | .x = 42, | |
| 47 | }; | |
| 44 | 48 | assert(0 != @sizeOf(@typeOf(s))); |
| 45 | 49 | assert(42 == Struct(u8).pointer(s).x); |
| 46 | 50 | assert(42 == Struct(u8).pointer(&s).x); |
| 47 | 51 | assert(42 == Struct(u8).maybePointer(s).x); |
| 48 | 52 | assert(42 == Struct(u8).maybePointer(&s).x); |
| 49 | 53 | assert(0 == Struct(u8).maybePointer(null).x); |
| 50 | const u = Union { .x = 42 }; | |
| 54 | const u = Union { | |
| 55 | .x = 42, | |
| 56 | }; | |
| 51 | 57 | assert(42 == Union.pointer(u).x); |
| 52 | 58 | assert(42 == Union.pointer(&u).x); |
| 53 | 59 | assert(42 == Union.maybePointer(u).x); |
| ... | ... | @@ -67,12 +73,14 @@ fn Struct(comptime T: type) type { |
| 67 | 73 | x: T, |
| 68 | 74 | |
| 69 | 75 | fn pointer(self: &const Self) Self { |
| 70 | return *self; | |
| 76 | return self.*; | |
| 71 | 77 | } |
| 72 | 78 | |
| 73 | 79 | 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).*; | |
| 76 | 84 | } |
| 77 | 85 | }; |
| 78 | 86 | } |
| ... | ... | @@ -81,12 +89,14 @@ const Union = union { |
| 81 | 89 | x: u8, |
| 82 | 90 | |
| 83 | 91 | fn pointer(self: &const Union) Union { |
| 84 | return *self; | |
| 92 | return self.*; | |
| 85 | 93 | } |
| 86 | 94 | |
| 87 | 95 | 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).*; | |
| 90 | 100 | } |
| 91 | 101 | }; |
| 92 | 102 | |
| ... | ... | @@ -95,11 +105,11 @@ const Enum = enum { |
| 95 | 105 | Some, |
| 96 | 106 | |
| 97 | 107 | fn pointer(self: &const Enum) Enum { |
| 98 | return *self; | |
| 108 | return self.*; | |
| 99 | 109 | } |
| 100 | 110 | |
| 101 | 111 | fn maybePointer(self: ?&const Enum) Enum { |
| 102 | return *(self ?? &Enum.None); | |
| 112 | return (self ?? &Enum.None).*; | |
| 103 | 113 | } |
| 104 | 114 | }; |
| 105 | 115 | |
| ... | ... | @@ -108,19 +118,21 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" { |
| 108 | 118 | const Self = this; |
| 109 | 119 | x: u8, |
| 110 | 120 | fn constConst(p: &const &const Self) u8 { |
| 111 | return (*p).x; | |
| 121 | return (p.*).x; | |
| 112 | 122 | } |
| 113 | 123 | fn maybeConstConst(p: ?&const &const Self) u8 { |
| 114 | return (*??p).x; | |
| 124 | return ((??p).*).x; | |
| 115 | 125 | } |
| 116 | 126 | fn constConstConst(p: &const &const &const Self) u8 { |
| 117 | return (**p).x; | |
| 127 | return (p.*.*).x; | |
| 118 | 128 | } |
| 119 | 129 | fn maybeConstConstConst(p: ?&const &const &const Self) u8 { |
| 120 | return (**??p).x; | |
| 130 | return ((??p).*.*).x; | |
| 121 | 131 | } |
| 122 | 132 | }; |
| 123 | const s = S { .x = 42 }; | |
| 133 | const s = S { | |
| 134 | .x = 42, | |
| 135 | }; | |
| 124 | 136 | const p = &s; |
| 125 | 137 | const q = &p; |
| 126 | 138 | const r = &q; |
| ... | ... | @@ -154,7 +166,6 @@ fn boolToStr(b: bool) []const u8 { |
| 154 | 166 | return if (b) "true" else "false"; |
| 155 | 167 | } |
| 156 | 168 | |
| 157 | ||
| 158 | 169 | test "peer resolve array and const slice" { |
| 159 | 170 | testPeerResolveArrayConstSlice(true); |
| 160 | 171 | comptime testPeerResolveArrayConstSlice(true); |
| ... | ... | @@ -168,12 +179,12 @@ fn testPeerResolveArrayConstSlice(b: bool) void { |
| 168 | 179 | |
| 169 | 180 | test "integer literal to &const int" { |
| 170 | 181 | const x: &const i32 = 3; |
| 171 | assert(*x == 3); | |
| 182 | assert(x.* == 3); | |
| 172 | 183 | } |
| 173 | 184 | |
| 174 | 185 | test "string literal to &const []const u8" { |
| 175 | 186 | const x: &const []const u8 = "hello"; |
| 176 | assert(mem.eql(u8, *x, "hello")); | |
| 187 | assert(mem.eql(u8, x.*, "hello")); | |
| 177 | 188 | } |
| 178 | 189 | |
| 179 | 190 | test "implicitly cast from T to error!?T" { |
| ... | ... | @@ -191,7 +202,9 @@ fn castToMaybeTypeError(z: i32) void { |
| 191 | 202 | const f = z; |
| 192 | 203 | const g: error!?i32 = f; |
| 193 | 204 | |
| 194 | const a = A{ .a = z }; | |
| 205 | const a = A { | |
| 206 | .a = z, | |
| 207 | }; | |
| 195 | 208 | const b: error!?A = a; |
| 196 | 209 | assert((??(b catch unreachable)).a == 1); |
| 197 | 210 | } |
| ... | ... | @@ -205,7 +218,6 @@ fn implicitIntLitToMaybe() void { |
| 205 | 218 | const g: error!?i32 = 1; |
| 206 | 219 | } |
| 207 | 220 | |
| 208 | ||
| 209 | 221 | test "return null from fn() error!?&T" { |
| 210 | 222 | const a = returnNullFromMaybeTypeErrorRef(); |
| 211 | 223 | const b = returnNullLitFromMaybeTypeErrorRef(); |
| ... | ... | @@ -235,7 +247,6 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize { |
| 235 | 247 | return usize(3); |
| 236 | 248 | } |
| 237 | 249 | |
| 238 | ||
| 239 | 250 | test "peer type resolution: [0]u8 and []const u8" { |
| 240 | 251 | assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); |
| 241 | 252 | assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); |
| ... | ... | @@ -246,7 +257,7 @@ test "peer type resolution: [0]u8 and []const u8" { |
| 246 | 257 | } |
| 247 | 258 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { |
| 248 | 259 | if (a) { |
| 249 | return []const u8 {}; | |
| 260 | return []const u8{}; | |
| 250 | 261 | } |
| 251 | 262 | |
| 252 | 263 | return slice[0..1]; |
| ... | ... | @@ -261,7 +272,6 @@ fn castToMaybeSlice() ?[]const u8 { |
| 261 | 272 | return "hi"; |
| 262 | 273 | } |
| 263 | 274 | |
| 264 | ||
| 265 | 275 | test "implicitly cast from [0]T to error![]T" { |
| 266 | 276 | testCastZeroArrayToErrSliceMut(); |
| 267 | 277 | comptime testCastZeroArrayToErrSliceMut(); |
| ... | ... | @@ -329,7 +339,6 @@ fn foo(args: ...) void { |
| 329 | 339 | assert(@typeOf(args[0]) == &const [5]u8); |
| 330 | 340 | } |
| 331 | 341 | |
| 332 | ||
| 333 | 342 | test "peer type resolution: error and [N]T" { |
| 334 | 343 | // TODO: implicit error!T to error!U where T can implicitly cast to U |
| 335 | 344 | //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); |
| ... | ... | @@ -378,7 +387,12 @@ fn cast128Float(x: u128) f128 { |
| 378 | 387 | } |
| 379 | 388 | |
| 380 | 389 | test "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 | }; | |
| 382 | 396 | |
| 383 | 397 | const u32_value = ([]const u32)(bytes[0..])[0]; |
| 384 | 398 | assert(u32_value == 0x12121212); |
test/cases/coroutines.zig+9-9| ... | ... | @@ -36,7 +36,7 @@ async fn testAsyncSeq() void { |
| 36 | 36 | suspend; |
| 37 | 37 | seq('d'); |
| 38 | 38 | } |
| 39 | var points = []u8{0} ** "abcdefg".len; | |
| 39 | var points = []u8 {0} ** "abcdefg".len; | |
| 40 | 40 | var index: usize = 0; |
| 41 | 41 | |
| 42 | 42 | fn seq(c: u8) void { |
| ... | ... | @@ -94,7 +94,7 @@ async fn await_another() i32 { |
| 94 | 94 | return 1234; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | var await_points = []u8{0} ** "abcdefghi".len; | |
| 97 | var await_points = []u8 {0} ** "abcdefghi".len; | |
| 98 | 98 | var await_seq_index: usize = 0; |
| 99 | 99 | |
| 100 | 100 | fn await_seq(c: u8) void { |
| ... | ... | @@ -102,7 +102,6 @@ fn await_seq(c: u8) void { |
| 102 | 102 | await_seq_index += 1; |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | ||
| 106 | 105 | var early_final_result: i32 = 0; |
| 107 | 106 | |
| 108 | 107 | test "coroutine await early return" { |
| ... | ... | @@ -126,7 +125,7 @@ async fn early_another() i32 { |
| 126 | 125 | return 1234; |
| 127 | 126 | } |
| 128 | 127 | |
| 129 | var early_points = []u8{0} ** "abcdef".len; | |
| 128 | var early_points = []u8 {0} ** "abcdef".len; | |
| 130 | 129 | var early_seq_index: usize = 0; |
| 131 | 130 | |
| 132 | 131 | fn early_seq(c: u8) void { |
| ... | ... | @@ -175,8 +174,8 @@ test "async fn pointer in a struct field" { |
| 175 | 174 | } |
| 176 | 175 | |
| 177 | 176 | async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void { |
| 178 | defer *y += 2; | |
| 179 | *y += 1; | |
| 177 | defer y.* += 2; | |
| 178 | y.* += 1; | |
| 180 | 179 | suspend; |
| 181 | 180 | } |
| 182 | 181 | |
| ... | ... | @@ -205,7 +204,8 @@ test "error return trace across suspend points - async return" { |
| 205 | 204 | cancel p2; |
| 206 | 205 | } |
| 207 | 206 | |
| 208 | fn nonFailing() promise->error!void { | |
| 207 | // TODO https://github.com/zig-lang/zig/issues/760 | |
| 208 | fn nonFailing() (promise->error!void) { | |
| 209 | 209 | return async<std.debug.global_allocator> suspendThenFail() catch unreachable; |
| 210 | 210 | } |
| 211 | 211 | |
| ... | ... | @@ -239,7 +239,7 @@ async fn testBreakFromSuspend(my_result: &i32) void { |
| 239 | 239 | s: suspend |p| { |
| 240 | 240 | break :s; |
| 241 | 241 | } |
| 242 | *my_result += 1; | |
| 242 | my_result.* += 1; | |
| 243 | 243 | suspend; |
| 244 | *my_result += 1; | |
| 244 | my_result.* += 1; | |
| 245 | 245 | } |
test/cases/defer.zig+12-3| ... | ... | @@ -5,9 +5,18 @@ var index: usize = undefined; |
| 5 | 5 | |
| 6 | 6 | fn runSomeErrorDefers(x: bool) !bool { |
| 7 | 7 | 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 | } | |
| 11 | 20 | return if (x) x else error.FalseNotAllowed; |
| 12 | 21 | } |
| 13 | 22 |
test/cases/enum.zig+548-58| ... | ... | @@ -2,8 +2,15 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | 3 | |
| 4 | 4 | test "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 | }; | |
| 7 | 14 | const bar = Bar.B; |
| 8 | 15 | |
| 9 | 16 | assert(bar == Bar.B); |
| ... | ... | @@ -41,26 +48,31 @@ const Bar = enum { |
| 41 | 48 | }; |
| 42 | 49 | |
| 43 | 50 | fn returnAnInt(x: i32) Foo { |
| 44 | return Foo { .One = x }; | |
| 51 | return Foo { | |
| 52 | .One = x, | |
| 53 | }; | |
| 45 | 54 | } |
| 46 | 55 | |
| 47 | ||
| 48 | 56 | test "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 | }; | |
| 51 | 63 | shouldBeEmpty(empty); |
| 52 | 64 | shouldBeNotEmpty(full); |
| 53 | 65 | } |
| 54 | 66 | |
| 55 | 67 | fn shouldBeEmpty(x: &const AnEnumWithPayload) void { |
| 56 | switch (*x) { | |
| 68 | switch (x.*) { | |
| 57 | 69 | AnEnumWithPayload.Empty => {}, |
| 58 | 70 | else => unreachable, |
| 59 | 71 | } |
| 60 | 72 | } |
| 61 | 73 | |
| 62 | 74 | fn shouldBeNotEmpty(x: &const AnEnumWithPayload) void { |
| 63 | switch (*x) { | |
| 75 | switch (x.*) { | |
| 64 | 76 | AnEnumWithPayload.Empty => unreachable, |
| 65 | 77 | else => {}, |
| 66 | 78 | } |
| ... | ... | @@ -71,8 +83,6 @@ const AnEnumWithPayload = union(enum) { |
| 71 | 83 | Full: i32, |
| 72 | 84 | }; |
| 73 | 85 | |
| 74 | ||
| 75 | ||
| 76 | 86 | const Number = enum { |
| 77 | 87 | Zero, |
| 78 | 88 | One, |
| ... | ... | @@ -93,7 +103,6 @@ fn shouldEqual(n: Number, expected: u3) void { |
| 93 | 103 | assert(u3(n) == expected); |
| 94 | 104 | } |
| 95 | 105 | |
| 96 | ||
| 97 | 106 | test "int to enum" { |
| 98 | 107 | testIntToEnumEval(3); |
| 99 | 108 | } |
| ... | ... | @@ -108,7 +117,6 @@ const IntToEnumNumber = enum { |
| 108 | 117 | Four, |
| 109 | 118 | }; |
| 110 | 119 | |
| 111 | ||
| 112 | 120 | test "@tagName" { |
| 113 | 121 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| 114 | 122 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| ... | ... | @@ -124,7 +132,6 @@ const BareNumber = enum { |
| 124 | 132 | Three, |
| 125 | 133 | }; |
| 126 | 134 | |
| 127 | ||
| 128 | 135 | test "enum alignment" { |
| 129 | 136 | comptime { |
| 130 | 137 | assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); |
| ... | ... | @@ -137,47 +144,529 @@ const AlignTestEnum = union(enum) { |
| 137 | 144 | B: u64, |
| 138 | 145 | }; |
| 139 | 146 | |
| 140 | const ValueCount1 = enum { I0 }; | |
| 141 | const ValueCount2 = enum { I0, I1 }; | |
| 147 | const ValueCount1 = enum { | |
| 148 | I0, | |
| 149 | }; | |
| 150 | const ValueCount2 = enum { | |
| 151 | I0, | |
| 152 | I1, | |
| 153 | }; | |
| 142 | 154 | const 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, | |
| 161 | 411 | }; |
| 162 | 412 | const 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, | |
| 181 | 670 | }; |
| 182 | 671 | |
| 183 | 672 | test "enum sizes" { |
| ... | ... | @@ -189,11 +678,11 @@ test "enum sizes" { |
| 189 | 678 | } |
| 190 | 679 | } |
| 191 | 680 | |
| 192 | const Small2 = enum (u2) { | |
| 681 | const Small2 = enum(u2) { | |
| 193 | 682 | One, |
| 194 | 683 | Two, |
| 195 | 684 | }; |
| 196 | const Small = enum (u2) { | |
| 685 | const Small = enum(u2) { | |
| 197 | 686 | One, |
| 198 | 687 | Two, |
| 199 | 688 | Three, |
| ... | ... | @@ -213,8 +702,7 @@ test "set enum tag type" { |
| 213 | 702 | } |
| 214 | 703 | } |
| 215 | 704 | |
| 216 | ||
| 217 | const A = enum (u3) { | |
| 705 | const A = enum(u3) { | |
| 218 | 706 | One, |
| 219 | 707 | Two, |
| 220 | 708 | Three, |
| ... | ... | @@ -225,7 +713,7 @@ const A = enum (u3) { |
| 225 | 713 | Four2, |
| 226 | 714 | }; |
| 227 | 715 | |
| 228 | const B = enum (u3) { | |
| 716 | const B = enum(u3) { | |
| 229 | 717 | One3, |
| 230 | 718 | Two3, |
| 231 | 719 | Three3, |
| ... | ... | @@ -236,7 +724,7 @@ const B = enum (u3) { |
| 236 | 724 | Four23, |
| 237 | 725 | }; |
| 238 | 726 | |
| 239 | const C = enum (u2) { | |
| 727 | const C = enum(u2) { | |
| 240 | 728 | One4, |
| 241 | 729 | Two4, |
| 242 | 730 | Three4, |
| ... | ... | @@ -389,7 +877,9 @@ test "enum with tag values don't require parens" { |
| 389 | 877 | } |
| 390 | 878 | |
| 391 | 879 | test "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 | }; | |
| 393 | 883 | comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8)); |
| 394 | 884 | } |
| 395 | 885 |
test/cases/enum_with_members.zig+7-3| ... | ... | @@ -7,7 +7,7 @@ const ET = union(enum) { |
| 7 | 7 | UINT: u32, |
| 8 | 8 | |
| 9 | 9 | pub fn print(a: &const ET, buf: []u8) error!usize { |
| 10 | return switch (*a) { | |
| 10 | return switch (a.*) { | |
| 11 | 11 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), |
| 12 | 12 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), |
| 13 | 13 | }; |
| ... | ... | @@ -15,8 +15,12 @@ const ET = union(enum) { |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | 17 | test "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 | }; | |
| 20 | 24 | var buf: [20]u8 = undefined; |
| 21 | 25 | |
| 22 | 26 | assert((a.print(buf[0..]) catch unreachable) == 3); |
test/cases/error.zig+30-26| ... | ... | @@ -30,14 +30,12 @@ test "@errorName" { |
| 30 | 30 | assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | ||
| 34 | 33 | test "error values" { |
| 35 | 34 | const a = i32(error.err1); |
| 36 | 35 | const b = i32(error.err2); |
| 37 | 36 | assert(a != b); |
| 38 | 37 | } |
| 39 | 38 | |
| 40 | ||
| 41 | 39 | test "redefinition of error values allowed" { |
| 42 | 40 | shouldBeNotEqual(error.AnError, error.SecondError); |
| 43 | 41 | } |
| ... | ... | @@ -45,7 +43,6 @@ fn shouldBeNotEqual(a: error, b: error) void { |
| 45 | 43 | if (a == b) unreachable; |
| 46 | 44 | } |
| 47 | 45 | |
| 48 | ||
| 49 | 46 | test "error binary operator" { |
| 50 | 47 | const a = errBinaryOperatorG(true) catch 3; |
| 51 | 48 | const b = errBinaryOperatorG(false) catch 3; |
| ... | ... | @@ -56,20 +53,20 @@ fn errBinaryOperatorG(x: bool) error!isize { |
| 56 | 53 | return if (x) error.ItBroke else isize(10); |
| 57 | 54 | } |
| 58 | 55 | |
| 59 | ||
| 60 | 56 | test "unwrap simple value from error" { |
| 61 | 57 | const i = unwrapSimpleValueFromErrorDo() catch unreachable; |
| 62 | 58 | assert(i == 13); |
| 63 | 59 | } |
| 64 | fn unwrapSimpleValueFromErrorDo() error!isize { return 13; } | |
| 65 | ||
| 60 | fn unwrapSimpleValueFromErrorDo() error!isize { | |
| 61 | return 13; | |
| 62 | } | |
| 66 | 63 | |
| 67 | 64 | test "error return in assignment" { |
| 68 | 65 | doErrReturnInAssignment() catch unreachable; |
| 69 | 66 | } |
| 70 | 67 | |
| 71 | 68 | fn doErrReturnInAssignment() error!void { |
| 72 | var x : i32 = undefined; | |
| 69 | var x: i32 = undefined; | |
| 73 | 70 | x = try makeANonErr(); |
| 74 | 71 | } |
| 75 | 72 | |
| ... | ... | @@ -95,7 +92,10 @@ test "error set type " { |
| 95 | 92 | comptime testErrorSetType(); |
| 96 | 93 | } |
| 97 | 94 | |
| 98 | const MyErrSet = error {OutOfMemory, FileNotFound}; | |
| 95 | const MyErrSet = error { | |
| 96 | OutOfMemory, | |
| 97 | FileNotFound, | |
| 98 | }; | |
| 99 | 99 | |
| 100 | 100 | fn testErrorSetType() void { |
| 101 | 101 | assert(@memberCount(MyErrSet) == 2); |
| ... | ... | @@ -109,14 +109,19 @@ fn testErrorSetType() void { |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | ||
| 113 | 112 | test "explicit error set cast" { |
| 114 | 113 | testExplicitErrorSetCast(Set1.A); |
| 115 | 114 | comptime testExplicitErrorSetCast(Set1.A); |
| 116 | 115 | } |
| 117 | 116 | |
| 118 | const Set1 = error{A, B}; | |
| 119 | const Set2 = error{A, C}; | |
| 117 | const Set1 = error { | |
| 118 | A, | |
| 119 | B, | |
| 120 | }; | |
| 121 | const Set2 = error { | |
| 122 | A, | |
| 123 | C, | |
| 124 | }; | |
| 120 | 125 | |
| 121 | 126 | fn testExplicitErrorSetCast(set1: Set1) void { |
| 122 | 127 | var x = Set2(set1); |
| ... | ... | @@ -129,7 +134,8 @@ test "comptime test error for empty error set" { |
| 129 | 134 | comptime testComptimeTestErrorEmptySet(1234); |
| 130 | 135 | } |
| 131 | 136 | |
| 132 | const EmptyErrorSet = error {}; | |
| 137 | const EmptyErrorSet = error { | |
| 138 | }; | |
| 133 | 139 | |
| 134 | 140 | fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { |
| 135 | 141 | 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" { |
| 145 | 151 | testErrToIntWithOnePossibleValue(error.A, u32(error.A)); |
| 146 | 152 | comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A)); |
| 147 | 153 | } |
| 148 | fn testErrToIntWithOnePossibleValue(x: error{A}, comptime value: u32) void { | |
| 154 | fn testErrToIntWithOnePossibleValue(x: error { | |
| 155 | A, | |
| 156 | }, comptime value: u32) void { | |
| 149 | 157 | if (u32(x) != value) { |
| 150 | 158 | @compileError("bad"); |
| 151 | 159 | } |
| ... | ... | @@ -176,7 +184,6 @@ fn quux_1() !i32 { |
| 176 | 184 | return error.C; |
| 177 | 185 | } |
| 178 | 186 | |
| 179 | ||
| 180 | 187 | test "error: fn returning empty error set can be passed as fn returning any error" { |
| 181 | 188 | entry(); |
| 182 | 189 | comptime entry(); |
| ... | ... | @@ -186,24 +193,24 @@ fn entry() void { |
| 186 | 193 | foo2(bar2); |
| 187 | 194 | } |
| 188 | 195 | |
| 189 | fn foo2(f: fn()error!void) void { | |
| 196 | fn foo2(f: fn() error!void) void { | |
| 190 | 197 | const x = f(); |
| 191 | 198 | } |
| 192 | 199 | |
| 193 | fn bar2() (error{}!void) { } | |
| 194 | ||
| 200 | fn bar2() (error { | |
| 201 | }!void) {} | |
| 195 | 202 | |
| 196 | 203 | test "error: Zero sized error set returned with value payload crash" { |
| 197 | 204 | _ = foo3(0); |
| 198 | 205 | _ = comptime foo3(0); |
| 199 | 206 | } |
| 200 | 207 | |
| 201 | const Error = error{}; | |
| 208 | const Error = error { | |
| 209 | }; | |
| 202 | 210 | fn foo3(b: usize) Error!usize { |
| 203 | 211 | return b; |
| 204 | 212 | } |
| 205 | 213 | |
| 206 | ||
| 207 | 214 | test "error: Infer error set from literals" { |
| 208 | 215 | _ = nullLiteral("n") catch |err| handleErrors(err); |
| 209 | 216 | _ = floatLiteral("n") catch |err| handleErrors(err); |
| ... | ... | @@ -215,29 +222,26 @@ test "error: Infer error set from literals" { |
| 215 | 222 | |
| 216 | 223 | fn handleErrors(err: var) noreturn { |
| 217 | 224 | switch (err) { |
| 218 | error.T => {} | |
| 225 | error.T => {}, | |
| 219 | 226 | } |
| 220 | 227 | |
| 221 | 228 | unreachable; |
| 222 | 229 | } |
| 223 | 230 | |
| 224 | 231 | fn nullLiteral(str: []const u8) !?i64 { |
| 225 | if (str[0] == 'n') | |
| 226 | return null; | |
| 232 | if (str[0] == 'n') return null; | |
| 227 | 233 | |
| 228 | 234 | return error.T; |
| 229 | 235 | } |
| 230 | 236 | |
| 231 | 237 | fn floatLiteral(str: []const u8) !?f64 { |
| 232 | if (str[0] == 'n') | |
| 233 | return 1.0; | |
| 238 | if (str[0] == 'n') return 1.0; | |
| 234 | 239 | |
| 235 | 240 | return error.T; |
| 236 | 241 | } |
| 237 | 242 | |
| 238 | 243 | fn intLiteral(str: []const u8) !?i64 { |
| 239 | if (str[0] == 'n') | |
| 240 | return 1; | |
| 244 | if (str[0] == 'n') return 1; | |
| 241 | 245 | |
| 242 | 246 | return error.T; |
| 243 | 247 | } |
test/cases/eval.zig+88-55| ... | ... | @@ -11,8 +11,6 @@ fn fibonacci(x: i32) i32 { |
| 11 | 11 | return fibonacci(x - 1) + fibonacci(x - 2); |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | ||
| 15 | ||
| 16 | 14 | fn unwrapAndAddOne(blah: ?i32) i32 { |
| 17 | 15 | return ??blah + 1; |
| 18 | 16 | } |
| ... | ... | @@ -40,13 +38,13 @@ test "inline variable gets result of const if" { |
| 40 | 38 | assert(gimme1or2(false) == 2); |
| 41 | 39 | } |
| 42 | 40 | |
| 43 | ||
| 44 | 41 | test "static function evaluation" { |
| 45 | 42 | assert(statically_added_number == 3); |
| 46 | 43 | } |
| 47 | 44 | const statically_added_number = staticAdd(1, 2); |
| 48 | fn staticAdd(a: i32, b: i32) i32 { return a + b; } | |
| 49 | ||
| 45 | fn staticAdd(a: i32, b: i32) i32 { | |
| 46 | return a + b; | |
| 47 | } | |
| 50 | 48 | |
| 51 | 49 | test "const expr eval on single expr blocks" { |
| 52 | 50 | assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); |
| ... | ... | @@ -64,9 +62,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { |
| 64 | 62 | return result; |
| 65 | 63 | } |
| 66 | 64 | |
| 67 | ||
| 68 | ||
| 69 | ||
| 70 | 65 | test "statically initialized list" { |
| 71 | 66 | assert(static_point_list[0].x == 1); |
| 72 | 67 | assert(static_point_list[0].y == 2); |
| ... | ... | @@ -77,7 +72,10 @@ const Point = struct { |
| 77 | 72 | x: i32, |
| 78 | 73 | y: i32, |
| 79 | 74 | }; |
| 80 | const static_point_list = []Point { makePoint(1, 2), makePoint(3, 4) }; | |
| 75 | const static_point_list = []Point { | |
| 76 | makePoint(1, 2), | |
| 77 | makePoint(3, 4), | |
| 78 | }; | |
| 81 | 79 | fn makePoint(x: i32, y: i32) Point { |
| 82 | 80 | return Point { |
| 83 | 81 | .x = x, |
| ... | ... | @@ -85,7 +83,6 @@ fn makePoint(x: i32, y: i32) Point { |
| 85 | 83 | }; |
| 86 | 84 | } |
| 87 | 85 | |
| 88 | ||
| 89 | 86 | test "static eval list init" { |
| 90 | 87 | assert(static_vec3.data[2] == 1.0); |
| 91 | 88 | assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); |
| ... | ... | @@ -96,17 +93,19 @@ pub const Vec3 = struct { |
| 96 | 93 | }; |
| 97 | 94 | pub fn vec3(x: f32, y: f32, z: f32) Vec3 { |
| 98 | 95 | return Vec3 { |
| 99 | .data = []f32 { x, y, z, }, | |
| 96 | .data = []f32 { | |
| 97 | x, | |
| 98 | y, | |
| 99 | z, | |
| 100 | }, | |
| 100 | 101 | }; |
| 101 | 102 | } |
| 102 | 103 | |
| 103 | ||
| 104 | 104 | test "constant expressions" { |
| 105 | var array : [array_size]u8 = undefined; | |
| 105 | var array: [array_size]u8 = undefined; | |
| 106 | 106 | assert(@sizeOf(@typeOf(array)) == 20); |
| 107 | 107 | } |
| 108 | const array_size : u8 = 20; | |
| 109 | ||
| 108 | const array_size: u8 = 20; | |
| 110 | 109 | |
| 111 | 110 | test "constant struct with negation" { |
| 112 | 111 | assert(vertices[0].x == -0.6); |
| ... | ... | @@ -119,12 +118,29 @@ const Vertex = struct { |
| 119 | 118 | b: f32, |
| 120 | 119 | }; |
| 121 | 120 | const 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 | }, | |
| 125 | 142 | }; |
| 126 | 143 | |
| 127 | ||
| 128 | 144 | test "statically initialized struct" { |
| 129 | 145 | st_init_str_foo.x += 1; |
| 130 | 146 | assert(st_init_str_foo.x == 14); |
| ... | ... | @@ -133,15 +149,21 @@ const StInitStrFoo = struct { |
| 133 | 149 | x: i32, |
| 134 | 150 | y: bool, |
| 135 | 151 | }; |
| 136 | var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, }; | |
| 137 | ||
| 152 | var st_init_str_foo = StInitStrFoo { | |
| 153 | .x = 13, | |
| 154 | .y = true, | |
| 155 | }; | |
| 138 | 156 | |
| 139 | 157 | test "statically initalized array literal" { |
| 140 | const y : [4]u8 = st_init_arr_lit_x; | |
| 158 | const y: [4]u8 = st_init_arr_lit_x; | |
| 141 | 159 | assert(y[3] == 4); |
| 142 | 160 | } |
| 143 | const st_init_arr_lit_x = []u8{1,2,3,4}; | |
| 144 | ||
| 161 | const st_init_arr_lit_x = []u8 { | |
| 162 | 1, | |
| 163 | 2, | |
| 164 | 3, | |
| 165 | 4, | |
| 166 | }; | |
| 145 | 167 | |
| 146 | 168 | test "const slice" { |
| 147 | 169 | comptime { |
| ... | ... | @@ -198,14 +220,29 @@ const CmdFn = struct { |
| 198 | 220 | func: fn(i32) i32, |
| 199 | 221 | }; |
| 200 | 222 | |
| 201 | const cmd_fns = []CmdFn{ | |
| 202 | CmdFn {.name = "one", .func = one}, | |
| 203 | CmdFn {.name = "two", .func = two}, | |
| 204 | CmdFn {.name = "three", .func = three}, | |
| 223 | const 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 | }, | |
| 205 | 236 | }; |
| 206 | fn one(value: i32) i32 { return value + 1; } | |
| 207 | fn two(value: i32) i32 { return value + 2; } | |
| 208 | fn three(value: i32) i32 { return value + 3; } | |
| 237 | fn one(value: i32) i32 { | |
| 238 | return value + 1; | |
| 239 | } | |
| 240 | fn two(value: i32) i32 { | |
| 241 | return value + 2; | |
| 242 | } | |
| 243 | fn three(value: i32) i32 { | |
| 244 | return value + 3; | |
| 245 | } | |
| 209 | 246 | |
| 210 | 247 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { |
| 211 | 248 | var result: i32 = start_value; |
| ... | ... | @@ -229,7 +266,7 @@ test "eval @setRuntimeSafety at compile-time" { |
| 229 | 266 | assert(result == 1234); |
| 230 | 267 | } |
| 231 | 268 | |
| 232 | fn fnWithSetRuntimeSafety() i32{ | |
| 269 | fn fnWithSetRuntimeSafety() i32 { | |
| 233 | 270 | @setRuntimeSafety(true); |
| 234 | 271 | return 1234; |
| 235 | 272 | } |
| ... | ... | @@ -244,7 +281,6 @@ fn fnWithFloatMode() f32 { |
| 244 | 281 | return 1234.0; |
| 245 | 282 | } |
| 246 | 283 | |
| 247 | ||
| 248 | 284 | const SimpleStruct = struct { |
| 249 | 285 | field: i32, |
| 250 | 286 | |
| ... | ... | @@ -253,7 +289,9 @@ const SimpleStruct = struct { |
| 253 | 289 | } |
| 254 | 290 | }; |
| 255 | 291 | |
| 256 | var simple_struct = SimpleStruct{ .field = 1234, }; | |
| 292 | var simple_struct = SimpleStruct { | |
| 293 | .field = 1234, | |
| 294 | }; | |
| 257 | 295 | |
| 258 | 296 | const bound_fn = simple_struct.method; |
| 259 | 297 | |
| ... | ... | @@ -261,8 +299,6 @@ test "call method on bound fn referring to var instance" { |
| 261 | 299 | assert(bound_fn() == 1237); |
| 262 | 300 | } |
| 263 | 301 | |
| 264 | ||
| 265 | ||
| 266 | 302 | test "ptr to local array argument at comptime" { |
| 267 | 303 | comptime { |
| 268 | 304 | var bytes: [10]u8 = undefined; |
| ... | ... | @@ -277,7 +313,6 @@ fn modifySomeBytes(bytes: []u8) void { |
| 277 | 313 | bytes[9] = 'b'; |
| 278 | 314 | } |
| 279 | 315 | |
| 280 | ||
| 281 | 316 | test "comparisons 0 <= uint and 0 > uint should be comptime" { |
| 282 | 317 | testCompTimeUIntComparisons(1234); |
| 283 | 318 | } |
| ... | ... | @@ -296,8 +331,6 @@ fn testCompTimeUIntComparisons(x: u32) void { |
| 296 | 331 | } |
| 297 | 332 | } |
| 298 | 333 | |
| 299 | ||
| 300 | ||
| 301 | 334 | test "const ptr to variable data changes at runtime" { |
| 302 | 335 | assert(foo_ref.name[0] == 'a'); |
| 303 | 336 | foo_ref.name = "b"; |
| ... | ... | @@ -308,11 +341,11 @@ const Foo = struct { |
| 308 | 341 | name: []const u8, |
| 309 | 342 | }; |
| 310 | 343 | |
| 311 | var foo_contents = Foo { .name = "a", }; | |
| 344 | var foo_contents = Foo { | |
| 345 | .name = "a", | |
| 346 | }; | |
| 312 | 347 | const foo_ref = &foo_contents; |
| 313 | 348 | |
| 314 | ||
| 315 | ||
| 316 | 349 | test "create global array with for loop" { |
| 317 | 350 | assert(global_array[5] == 5 * 5); |
| 318 | 351 | assert(global_array[9] == 9 * 9); |
| ... | ... | @@ -321,7 +354,7 @@ test "create global array with for loop" { |
| 321 | 354 | const global_array = x: { |
| 322 | 355 | var result: [10]usize = undefined; |
| 323 | 356 | for (result) |*item, index| { |
| 324 | *item = index * index; | |
| 357 | item.* = index * index; | |
| 325 | 358 | } |
| 326 | 359 | break :x result; |
| 327 | 360 | }; |
| ... | ... | @@ -379,7 +412,7 @@ test "f128 at compile time is lossy" { |
| 379 | 412 | |
| 380 | 413 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { |
| 381 | 414 | return struct { |
| 382 | pub const Node = struct { }; | |
| 415 | pub const Node = struct {}; | |
| 383 | 416 | }; |
| 384 | 417 | } |
| 385 | 418 | |
| ... | ... | @@ -401,10 +434,10 @@ fn copyWithPartialInline(s: []u32, b: []u8) void { |
| 401 | 434 | comptime var i: usize = 0; |
| 402 | 435 | inline while (i < 4) : (i += 1) { |
| 403 | 436 | 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; | |
| 408 | 441 | } |
| 409 | 442 | } |
| 410 | 443 | |
| ... | ... | @@ -413,7 +446,7 @@ test "binary math operator in partially inlined function" { |
| 413 | 446 | var b: [16]u8 = undefined; |
| 414 | 447 | |
| 415 | 448 | for (b) |*r, i| |
| 416 | *r = u8(i + 1); | |
| 449 | r.* = u8(i + 1); | |
| 417 | 450 | |
| 418 | 451 | copyWithPartialInline(s[0..], b[0..]); |
| 419 | 452 | assert(s[0] == 0x1020304); |
| ... | ... | @@ -422,7 +455,6 @@ test "binary math operator in partially inlined function" { |
| 422 | 455 | assert(s[3] == 0xd0e0f10); |
| 423 | 456 | } |
| 424 | 457 | |
| 425 | ||
| 426 | 458 | test "comptime function with the same args is memoized" { |
| 427 | 459 | comptime { |
| 428 | 460 | assert(MakeType(i32) == MakeType(i32)); |
| ... | ... | @@ -447,12 +479,12 @@ test "comptime function with mutable pointer is not memoized" { |
| 447 | 479 | } |
| 448 | 480 | |
| 449 | 481 | fn increment(value: &i32) void { |
| 450 | *value += 1; | |
| 482 | value.* += 1; | |
| 451 | 483 | } |
| 452 | 484 | |
| 453 | 485 | fn 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; | |
| 456 | 488 | while (i < 1010) : (i += 1) { |
| 457 | 489 | res[i] = T(i); |
| 458 | 490 | } |
| ... | ... | @@ -496,9 +528,10 @@ const SingleFieldStruct = struct { |
| 496 | 528 | } |
| 497 | 529 | }; |
| 498 | 530 | test "const ptr to comptime mutable data is not memoized" { |
| 499 | ||
| 500 | 531 | comptime { |
| 501 | var foo = SingleFieldStruct {.x = 1}; | |
| 532 | var foo = SingleFieldStruct { | |
| 533 | .x = 1, | |
| 534 | }; | |
| 502 | 535 | assert(foo.read_x() == 1); |
| 503 | 536 | foo.x = 2; |
| 504 | 537 | assert(foo.read_x() == 2); |
test/cases/fn.zig+26-18| ... | ... | @@ -7,7 +7,6 @@ fn testParamsAdd(a: i32, b: i32) i32 { |
| 7 | 7 | return a + b; |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | ||
| 11 | 10 | test "local variables" { |
| 12 | 11 | testLocVars(2); |
| 13 | 12 | } |
| ... | ... | @@ -16,7 +15,6 @@ fn testLocVars(b: i32) void { |
| 16 | 15 | if (a + b != 3) unreachable; |
| 17 | 16 | } |
| 18 | 17 | |
| 19 | ||
| 20 | 18 | test "void parameters" { |
| 21 | 19 | voidFun(1, void{}, 2, {}); |
| 22 | 20 | } |
| ... | ... | @@ -27,9 +25,8 @@ fn voidFun(a: i32, b: void, c: i32, d: void) void { |
| 27 | 25 | return vv; |
| 28 | 26 | } |
| 29 | 27 | |
| 30 | ||
| 31 | 28 | test "mutable local variables" { |
| 32 | var zero : i32 = 0; | |
| 29 | var zero: i32 = 0; | |
| 33 | 30 | assert(zero == 0); |
| 34 | 31 | |
| 35 | 32 | var i = i32(0); |
| ... | ... | @@ -41,7 +38,7 @@ test "mutable local variables" { |
| 41 | 38 | |
| 42 | 39 | test "separate block scopes" { |
| 43 | 40 | { |
| 44 | const no_conflict : i32 = 5; | |
| 41 | const no_conflict: i32 = 5; | |
| 45 | 42 | assert(no_conflict == 5); |
| 46 | 43 | } |
| 47 | 44 | |
| ... | ... | @@ -56,8 +53,7 @@ test "call function with empty string" { |
| 56 | 53 | acceptsString(""); |
| 57 | 54 | } |
| 58 | 55 | |
| 59 | fn acceptsString(foo: []u8) void { } | |
| 60 | ||
| 56 | fn acceptsString(foo: []u8) void {} | |
| 61 | 57 | |
| 62 | 58 | fn @"weird function name"() i32 { |
| 63 | 59 | return 1234; |
| ... | ... | @@ -70,31 +66,43 @@ test "implicit cast function unreachable return" { |
| 70 | 66 | wantsFnWithVoid(fnWithUnreachable); |
| 71 | 67 | } |
| 72 | 68 | |
| 73 | fn wantsFnWithVoid(f: fn() void) void { } | |
| 69 | fn wantsFnWithVoid(f: fn() void) void {} | |
| 74 | 70 | |
| 75 | 71 | fn fnWithUnreachable() noreturn { |
| 76 | 72 | unreachable; |
| 77 | 73 | } |
| 78 | 74 | |
| 79 | ||
| 80 | 75 | test "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 | }; | |
| 82 | 82 | for (fns) |f, i| { |
| 83 | 83 | assert(f() == u32(i) + 5); |
| 84 | 84 | } |
| 85 | 85 | } |
| 86 | fn fn1() u32 {return 5;} | |
| 87 | fn fn2() u32 {return 6;} | |
| 88 | fn fn3() u32 {return 7;} | |
| 89 | fn fn4() u32 {return 8;} | |
| 90 | ||
| 86 | fn fn1() u32 { | |
| 87 | return 5; | |
| 88 | } | |
| 89 | fn fn2() u32 { | |
| 90 | return 6; | |
| 91 | } | |
| 92 | fn fn3() u32 { | |
| 93 | return 7; | |
| 94 | } | |
| 95 | fn fn4() u32 { | |
| 96 | return 8; | |
| 97 | } | |
| 91 | 98 | |
| 92 | 99 | test "inline function call" { |
| 93 | 100 | assert(@inlineCall(add, 3, 9) == 12); |
| 94 | 101 | } |
| 95 | 102 | |
| 96 | fn add(a: i32, b: i32) i32 { return a + b; } | |
| 97 | ||
| 103 | fn add(a: i32, b: i32) i32 { | |
| 104 | return a + b; | |
| 105 | } | |
| 98 | 106 | |
| 99 | 107 | test "number literal as an argument" { |
| 100 | 108 | numberLiteralArg(3); |
| ... | ... | @@ -110,4 +118,4 @@ test "assign inline fn to const variable" { |
| 110 | 118 | a(); |
| 111 | 119 | } |
| 112 | 120 | |
| 113 | inline fn inlineFn() void { } | |
| 121 | inline fn inlineFn() void {} |
test/cases/for.zig+37-7| ... | ... | @@ -3,8 +3,14 @@ const assert = std.debug.assert; |
| 3 | 3 | const mem = std.mem; |
| 4 | 4 | |
| 5 | 5 | test "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; | |
| 8 | 14 | for (array) |x| { |
| 9 | 15 | sum += x; |
| 10 | 16 | if (x < 3) { |
| ... | ... | @@ -24,17 +30,39 @@ test "for loop with pointer elem var" { |
| 24 | 30 | } |
| 25 | 31 | fn mangleString(s: []u8) void { |
| 26 | 32 | for (s) |*c| { |
| 27 | *c += 1; | |
| 33 | c.* += 1; | |
| 28 | 34 | } |
| 29 | 35 | } |
| 30 | 36 | |
| 31 | 37 | test "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 | }; | |
| 33 | 56 | |
| 34 | 57 | var buffer: [expected_result.len]u8 = undefined; |
| 35 | 58 | var buf_index: usize = 0; |
| 36 | 59 | |
| 37 | const array = []u8 {9, 8, 7, 6}; | |
| 60 | const array = []u8 { | |
| 61 | 9, | |
| 62 | 8, | |
| 63 | 7, | |
| 64 | 6, | |
| 65 | }; | |
| 38 | 66 | for (array) |item| { |
| 39 | 67 | buffer[buf_index] = item; |
| 40 | 68 | buf_index += 1; |
| ... | ... | @@ -65,7 +93,8 @@ fn testBreakOuter() void { |
| 65 | 93 | var array = "aoeu"; |
| 66 | 94 | var count: usize = 0; |
| 67 | 95 | 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| { | |
| 69 | 98 | count += 1; |
| 70 | 99 | break :outer; |
| 71 | 100 | } |
| ... | ... | @@ -82,7 +111,8 @@ fn testContinueOuter() void { |
| 82 | 111 | var array = "aoeu"; |
| 83 | 112 | var counter: usize = 0; |
| 84 | 113 | 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| { | |
| 86 | 116 | counter += 1; |
| 87 | 117 | continue :outer; |
| 88 | 118 | } |
test/cases/generics.zig+28-14| ... | ... | @@ -37,7 +37,6 @@ test "fn with comptime args" { |
| 37 | 37 | assert(sameButWithFloats(0.43, 0.49) == 0.49); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | ||
| 41 | 40 | test "var params" { |
| 42 | 41 | assert(max_i32(12, 34) == 34); |
| 43 | 42 | assert(max_f64(1.2, 3.4) == 3.4); |
| ... | ... | @@ -60,7 +59,6 @@ fn max_f64(a: f64, b: f64) f64 { |
| 60 | 59 | return max_var(a, b); |
| 61 | 60 | } |
| 62 | 61 | |
| 63 | ||
| 64 | 62 | pub fn List(comptime T: type) type { |
| 65 | 63 | return SmallList(T, 8); |
| 66 | 64 | } |
| ... | ... | @@ -82,10 +80,15 @@ test "function with return type type" { |
| 82 | 80 | assert(list2.prealloc_items.len == 8); |
| 83 | 81 | } |
| 84 | 82 | |
| 85 | ||
| 86 | 83 | test "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 | }; | |
| 89 | 92 | assert(a1.value == 13); |
| 90 | 93 | assert(a1.value == a1.getVal()); |
| 91 | 94 | assert(b1.getVal()); |
| ... | ... | @@ -94,7 +97,9 @@ fn GenNode(comptime T: type) type { |
| 94 | 97 | return struct { |
| 95 | 98 | value: T, |
| 96 | 99 | 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 | } | |
| 98 | 103 | }; |
| 99 | 104 | } |
| 100 | 105 | |
| ... | ... | @@ -107,7 +112,6 @@ fn GenericDataThing(comptime count: isize) type { |
| 107 | 112 | }; |
| 108 | 113 | } |
| 109 | 114 | |
| 110 | ||
| 111 | 115 | test "use generic param in generic param" { |
| 112 | 116 | assert(aGenericFn(i32, 3, 4) == 7); |
| 113 | 117 | } |
| ... | ... | @@ -115,21 +119,31 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T { |
| 115 | 119 | return a + b; |
| 116 | 120 | } |
| 117 | 121 | |
| 118 | ||
| 119 | 122 | test "generic fn with implicit cast" { |
| 120 | 123 | 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 | } | |
| 129 | fn getByte(ptr: ?&const u8) u8 { | |
| 130 | return (??ptr).*; | |
| 122 | 131 | } |
| 123 | fn getByte(ptr: ?&const u8) u8 {return *??ptr;} | |
| 124 | 132 | fn getFirstByte(comptime T: type, mem: []const T) u8 { |
| 125 | 133 | return getByte(@ptrCast(&const u8, &mem[0])); |
| 126 | 134 | } |
| 127 | 135 | |
| 136 | const foos = []fn(var) bool { | |
| 137 | foo1, | |
| 138 | foo2, | |
| 139 | }; | |
| 128 | 140 | |
| 129 | const foos = []fn(var) bool { foo1, foo2 }; | |
| 130 | ||
| 131 | fn foo1(arg: var) bool { return arg; } | |
| 132 | fn foo2(arg: var) bool { return !arg; } | |
| 141 | fn foo1(arg: var) bool { | |
| 142 | return arg; | |
| 143 | } | |
| 144 | fn foo2(arg: var) bool { | |
| 145 | return !arg; | |
| 146 | } | |
| 133 | 147 | |
| 134 | 148 | test "array of generic fns" { |
| 135 | 149 | assert(foos[0](true)); |
test/cases/if.zig-1| ... | ... | @@ -23,7 +23,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void { |
| 23 | 23 | } |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | ||
| 27 | 26 | test "else if expression" { |
| 28 | 27 | assert(elseIfExpressionF(1) == 1); |
| 29 | 28 | } |
test/cases/import/a_namespace.zig+3-1| ... | ... | @@ -1 +1,3 @@ |
| 1 | pub fn foo() i32 { return 1234; } | |
| 1 | pub fn foo() i32 { | |
| 2 | return 1234; | |
| 3 | } |
test/cases/ir_block_deps.zig+3-1| ... | ... | @@ -11,7 +11,9 @@ fn foo(id: u64) !i32 { |
| 11 | 11 | }; |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | fn getErrInt() error!i32 { return 0; } | |
| 14 | fn getErrInt() error!i32 { | |
| 15 | return 0; | |
| 16 | } | |
| 15 | 17 | |
| 16 | 18 | test "ir block deps" { |
| 17 | 19 | assert((foo(1) catch unreachable) == 0); |
test/cases/math.zig+40-52| ... | ... | @@ -28,25 +28,12 @@ fn testDivision() void { |
| 28 | 28 | assert(divTrunc(f32, -5.0, 3.0) == -1.0); |
| 29 | 29 | |
| 30 | 30 | 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); | |
| 50 | 37 | assert(4126227191251978491697987544882340798050766755606969681711 % 10 == 1); |
| 51 | 38 | } |
| 52 | 39 | } |
| ... | ... | @@ -114,18 +101,28 @@ fn ctz(x: var) usize { |
| 114 | 101 | |
| 115 | 102 | test "assignment operators" { |
| 116 | 103 | 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); | |
| 124 | 118 | 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); | |
| 127 | 123 | i = 6; |
| 128 | i |= 3; assert(i == 7); | |
| 124 | i |= 3; | |
| 125 | assert(i == 7); | |
| 129 | 126 | } |
| 130 | 127 | |
| 131 | 128 | test "three expr in a row" { |
| ... | ... | @@ -138,7 +135,7 @@ fn testThreeExprInARow(f: bool, t: bool) void { |
| 138 | 135 | assertFalse(1 | 2 | 4 != 7); |
| 139 | 136 | assertFalse(3 ^ 6 ^ 8 != 13); |
| 140 | 137 | assertFalse(7 & 14 & 28 != 4); |
| 141 | assertFalse(9 << 1 << 2 != 9 << 3); | |
| 138 | assertFalse(9 << 1 << 2 != 9 << 3); | |
| 142 | 139 | assertFalse(90 >> 1 >> 2 != 90 >> 3); |
| 143 | 140 | assertFalse(100 - 1 + 1000 != 1099); |
| 144 | 141 | assertFalse(5 * 4 / 2 % 3 != 1); |
| ... | ... | @@ -150,7 +147,6 @@ fn assertFalse(b: bool) void { |
| 150 | 147 | assert(!b); |
| 151 | 148 | } |
| 152 | 149 | |
| 153 | ||
| 154 | 150 | test "const number literal" { |
| 155 | 151 | const one = 1; |
| 156 | 152 | const eleven = ten + one; |
| ... | ... | @@ -159,8 +155,6 @@ test "const number literal" { |
| 159 | 155 | } |
| 160 | 156 | const ten = 10; |
| 161 | 157 | |
| 162 | ||
| 163 | ||
| 164 | 158 | test "unsigned wrapping" { |
| 165 | 159 | testUnsignedWrappingEval(@maxValue(u32)); |
| 166 | 160 | comptime testUnsignedWrappingEval(@maxValue(u32)); |
| ... | ... | @@ -214,8 +208,12 @@ const DivResult = struct { |
| 214 | 208 | }; |
| 215 | 209 | |
| 216 | 210 | test "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 | }); | |
| 219 | 217 | testBinaryNot(0b1010101010101010); |
| 220 | 218 | } |
| 221 | 219 | |
| ... | ... | @@ -319,27 +317,15 @@ fn testShrExact(x: u8) void { |
| 319 | 317 | |
| 320 | 318 | test "big number addition" { |
| 321 | 319 | 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); | |
| 330 | 322 | } |
| 331 | 323 | } |
| 332 | 324 | |
| 333 | 325 | test "big number multiplication" { |
| 334 | 326 | 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); | |
| 343 | 329 | } |
| 344 | 330 | } |
| 345 | 331 | |
| ... | ... | @@ -405,7 +391,9 @@ test "f128" { |
| 405 | 391 | comptime test_f128(); |
| 406 | 392 | } |
| 407 | 393 | |
| 408 | fn make_f128(x: f128) f128 { return x; } | |
| 394 | fn make_f128(x: f128) f128 { | |
| 395 | return x; | |
| 396 | } | |
| 409 | 397 | |
| 410 | 398 | fn test_f128() void { |
| 411 | 399 | assert(@sizeOf(f128) == 16); |
test/cases/misc.zig+138-87| ... | ... | @@ -4,6 +4,7 @@ const cstr = @import("std").cstr; |
| 4 | 4 | const builtin = @import("builtin"); |
| 5 | 5 | |
| 6 | 6 | // normal comment |
| 7 | ||
| 7 | 8 | /// this is a documentation comment |
| 8 | 9 | /// doc comment line 2 |
| 9 | 10 | fn emptyFunctionWithComments() void {} |
| ... | ... | @@ -16,8 +17,7 @@ comptime { |
| 16 | 17 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); |
| 17 | 18 | } |
| 18 | 19 | |
| 19 | extern fn disabledExternFn() void { | |
| 20 | } | |
| 20 | extern fn disabledExternFn() void {} | |
| 21 | 21 | |
| 22 | 22 | test "call disabled extern fn" { |
| 23 | 23 | disabledExternFn(); |
| ... | ... | @@ -110,17 +110,29 @@ fn testShortCircuit(f: bool, t: bool) void { |
| 110 | 110 | var hit_3 = f; |
| 111 | 111 | var hit_4 = f; |
| 112 | 112 | |
| 113 | if (t or x: {assert(f); break :x f;}) { | |
| 113 | if (t or x: { | |
| 114 | assert(f); | |
| 115 | break :x f; | |
| 116 | }) { | |
| 114 | 117 | hit_1 = t; |
| 115 | 118 | } |
| 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 | }) { | |
| 117 | 123 | assert(f); |
| 118 | 124 | } |
| 119 | 125 | |
| 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 | }) { | |
| 121 | 130 | assert(f); |
| 122 | 131 | } |
| 123 | if (f and x: {assert(f); break :x f;}) { | |
| 132 | if (f and x: { | |
| 133 | assert(f); | |
| 134 | break :x f; | |
| 135 | }) { | |
| 124 | 136 | assert(f); |
| 125 | 137 | } else { |
| 126 | 138 | hit_4 = t; |
| ... | ... | @@ -146,8 +158,8 @@ test "return string from function" { |
| 146 | 158 | assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); |
| 147 | 159 | } |
| 148 | 160 | |
| 149 | const g1 : i32 = 1233 + 1; | |
| 150 | var g2 : i32 = 0; | |
| 161 | const g1: i32 = 1233 + 1; | |
| 162 | var g2: i32 = 0; | |
| 151 | 163 | |
| 152 | 164 | test "global variables" { |
| 153 | 165 | assert(g2 == 0); |
| ... | ... | @@ -155,10 +167,9 @@ test "global variables" { |
| 155 | 167 | assert(g2 == 1234); |
| 156 | 168 | } |
| 157 | 169 | |
| 158 | ||
| 159 | 170 | test "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; | |
| 162 | 173 | |
| 163 | 174 | @memset(&foo[0], 'A', foo.len); |
| 164 | 175 | @memcpy(&bar[0], &foo[0], bar.len); |
| ... | ... | @@ -167,12 +178,14 @@ test "memcpy and memset intrinsics" { |
| 167 | 178 | } |
| 168 | 179 | |
| 169 | 180 | test "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 | }; | |
| 171 | 184 | assert(x == comptime 6); |
| 172 | 185 | } |
| 173 | 186 | |
| 174 | 187 | test "slicing" { |
| 175 | var array : [20]i32 = undefined; | |
| 188 | var array: [20]i32 = undefined; | |
| 176 | 189 | |
| 177 | 190 | array[5] = 1234; |
| 178 | 191 | |
| ... | ... | @@ -187,15 +200,15 @@ test "slicing" { |
| 187 | 200 | if (slice_rest.len != 10) unreachable; |
| 188 | 201 | } |
| 189 | 202 | |
| 190 | ||
| 191 | 203 | test "constant equal function pointers" { |
| 192 | 204 | const alias = emptyFn; |
| 193 | assert(comptime x: {break :x emptyFn == alias;}); | |
| 205 | assert(comptime x: { | |
| 206 | break :x emptyFn == alias; | |
| 207 | }); | |
| 194 | 208 | } |
| 195 | 209 | |
| 196 | 210 | fn emptyFn() void {} |
| 197 | 211 | |
| 198 | ||
| 199 | 212 | test "hex escape" { |
| 200 | 213 | assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); |
| 201 | 214 | } |
| ... | ... | @@ -219,7 +232,7 @@ test "string escapes" { |
| 219 | 232 | } |
| 220 | 233 | |
| 221 | 234 | test "multiline string" { |
| 222 | const s1 = | |
| 235 | const s1 = | |
| 223 | 236 | \\one |
| 224 | 237 | \\two) |
| 225 | 238 | \\three |
| ... | ... | @@ -229,7 +242,7 @@ test "multiline string" { |
| 229 | 242 | } |
| 230 | 243 | |
| 231 | 244 | test "multiline C string" { |
| 232 | const s1 = | |
| 245 | const s1 = | |
| 233 | 246 | c\\one |
| 234 | 247 | c\\two) |
| 235 | 248 | c\\three |
| ... | ... | @@ -238,18 +251,16 @@ test "multiline C string" { |
| 238 | 251 | assert(cstr.cmp(s1, s2) == 0); |
| 239 | 252 | } |
| 240 | 253 | |
| 241 | ||
| 242 | 254 | test "type equality" { |
| 243 | 255 | assert(&const u8 != &u8); |
| 244 | 256 | } |
| 245 | 257 | |
| 246 | ||
| 247 | 258 | const global_a: i32 = 1234; |
| 248 | 259 | const global_b: &const i32 = &global_a; |
| 249 | 260 | const global_c: &const f32 = @ptrCast(&const f32, global_b); |
| 250 | 261 | test "compile time global reinterpret" { |
| 251 | 262 | const d = @ptrCast(&const i32, global_c); |
| 252 | assert(*d == 1234); | |
| 263 | assert(d.* == 1234); | |
| 253 | 264 | } |
| 254 | 265 | |
| 255 | 266 | test "explicit cast maybe pointers" { |
| ... | ... | @@ -261,12 +272,11 @@ test "generic malloc free" { |
| 261 | 272 | const a = memAlloc(u8, 10) catch unreachable; |
| 262 | 273 | memFree(u8, a); |
| 263 | 274 | } |
| 264 | var some_mem : [100]u8 = undefined; | |
| 275 | var some_mem: [100]u8 = undefined; | |
| 265 | 276 | fn memAlloc(comptime T: type, n: usize) error![]T { |
| 266 | 277 | return @ptrCast(&T, &some_mem[0])[0..n]; |
| 267 | 278 | } |
| 268 | fn memFree(comptime T: type, memory: []T) void { } | |
| 269 | ||
| 279 | fn memFree(comptime T: type, memory: []T) void {} | |
| 270 | 280 | |
| 271 | 281 | test "cast undefined" { |
| 272 | 282 | const array: [100]u8 = undefined; |
| ... | ... | @@ -275,32 +285,35 @@ test "cast undefined" { |
| 275 | 285 | } |
| 276 | 286 | fn testCastUndefined(x: []const u8) void {} |
| 277 | 287 | |
| 278 | ||
| 279 | 288 | test "cast small unsigned to larger signed" { |
| 280 | 289 | assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); |
| 281 | 290 | assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); |
| 282 | 291 | } |
| 283 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; } | |
| 284 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { return x; } | |
| 285 | ||
| 292 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | |
| 293 | return x; | |
| 294 | } | |
| 295 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | |
| 296 | return x; | |
| 297 | } | |
| 286 | 298 | |
| 287 | 299 | test "implicit cast after unreachable" { |
| 288 | 300 | assert(outer() == 1234); |
| 289 | 301 | } |
| 290 | fn inner() i32 { return 1234; } | |
| 302 | fn inner() i32 { | |
| 303 | return 1234; | |
| 304 | } | |
| 291 | 305 | fn outer() i64 { |
| 292 | 306 | return inner(); |
| 293 | 307 | } |
| 294 | 308 | |
| 295 | ||
| 296 | 309 | test "pointer dereferencing" { |
| 297 | 310 | var x = i32(3); |
| 298 | 311 | const y = &x; |
| 299 | 312 | |
| 300 | *y += 1; | |
| 313 | y.* += 1; | |
| 301 | 314 | |
| 302 | 315 | assert(x == 4); |
| 303 | assert(*y == 4); | |
| 316 | assert(y.* == 4); | |
| 304 | 317 | } |
| 305 | 318 | |
| 306 | 319 | test "call result of if else expression" { |
| ... | ... | @@ -310,9 +323,12 @@ test "call result of if else expression" { |
| 310 | 323 | fn f2(x: bool) []const u8 { |
| 311 | 324 | return (if (x) fA else fB)(); |
| 312 | 325 | } |
| 313 | fn fA() []const u8 { return "a"; } | |
| 314 | fn fB() []const u8 { return "b"; } | |
| 315 | ||
| 326 | fn fA() []const u8 { | |
| 327 | return "a"; | |
| 328 | } | |
| 329 | fn fB() []const u8 { | |
| 330 | return "b"; | |
| 331 | } | |
| 316 | 332 | |
| 317 | 333 | test "const expression eval handling of variables" { |
| 318 | 334 | var x = true; |
| ... | ... | @@ -321,8 +337,6 @@ test "const expression eval handling of variables" { |
| 321 | 337 | } |
| 322 | 338 | } |
| 323 | 339 | |
| 324 | ||
| 325 | ||
| 326 | 340 | test "constant enum initialization with differing sizes" { |
| 327 | 341 | test3_1(test3_foo); |
| 328 | 342 | test3_2(test3_bar); |
| ... | ... | @@ -336,10 +350,17 @@ const Test3Point = struct { |
| 336 | 350 | x: i32, |
| 337 | 351 | y: i32, |
| 338 | 352 | }; |
| 339 | const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}}; | |
| 340 | const test3_bar = Test3Foo { .Two = 13}; | |
| 353 | const test3_foo = Test3Foo { | |
| 354 | .Three = Test3Point { | |
| 355 | .x = 3, | |
| 356 | .y = 4, | |
| 357 | }, | |
| 358 | }; | |
| 359 | const test3_bar = Test3Foo { | |
| 360 | .Two = 13, | |
| 361 | }; | |
| 341 | 362 | fn test3_1(f: &const Test3Foo) void { |
| 342 | switch (*f) { | |
| 363 | switch (f.*) { | |
| 343 | 364 | Test3Foo.Three => |pt| { |
| 344 | 365 | assert(pt.x == 3); |
| 345 | 366 | assert(pt.y == 4); |
| ... | ... | @@ -348,7 +369,7 @@ fn test3_1(f: &const Test3Foo) void { |
| 348 | 369 | } |
| 349 | 370 | } |
| 350 | 371 | fn test3_2(f: &const Test3Foo) void { |
| 351 | switch (*f) { | |
| 372 | switch (f.*) { | |
| 352 | 373 | Test3Foo.Two => |x| { |
| 353 | 374 | assert(x == 13); |
| 354 | 375 | }, |
| ... | ... | @@ -356,23 +377,19 @@ fn test3_2(f: &const Test3Foo) void { |
| 356 | 377 | } |
| 357 | 378 | } |
| 358 | 379 | |
| 359 | ||
| 360 | 380 | test "character literals" { |
| 361 | 381 | assert('\'' == single_quote); |
| 362 | 382 | } |
| 363 | 383 | const single_quote = '\''; |
| 364 | 384 | |
| 365 | ||
| 366 | ||
| 367 | 385 | test "take address of parameter" { |
| 368 | 386 | testTakeAddressOfParameter(12.34); |
| 369 | 387 | } |
| 370 | 388 | fn testTakeAddressOfParameter(f: f32) void { |
| 371 | 389 | const f_ptr = &f; |
| 372 | assert(*f_ptr == 12.34); | |
| 390 | assert(f_ptr.* == 12.34); | |
| 373 | 391 | } |
| 374 | 392 | |
| 375 | ||
| 376 | 393 | test "pointer comparison" { |
| 377 | 394 | const a = ([]const u8)("a"); |
| 378 | 395 | const b = &a; |
| ... | ... | @@ -382,23 +399,30 @@ fn ptrEql(a: &const []const u8, b: &const []const u8) bool { |
| 382 | 399 | return a == b; |
| 383 | 400 | } |
| 384 | 401 | |
| 385 | ||
| 386 | 402 | test "C string concatenation" { |
| 387 | 403 | const a = c"OK" ++ c" IT " ++ c"WORKED"; |
| 388 | 404 | const b = c"OK IT WORKED"; |
| 389 | 405 | |
| 390 | 406 | const len = cstr.len(b); |
| 391 | 407 | 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 | } | |
| 395 | 414 | assert(a[len] == 0); |
| 396 | 415 | assert(b[len] == 0); |
| 397 | 416 | } |
| 398 | 417 | |
| 399 | 418 | test "cast slice to u8 slice" { |
| 400 | 419 | 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 | }; | |
| 402 | 426 | const big_thing_slice: []i32 = big_thing_array[0..]; |
| 403 | 427 | const bytes = ([]u8)(big_thing_slice); |
| 404 | 428 | assert(bytes.len == 4 * 4); |
| ... | ... | @@ -421,25 +445,22 @@ test "pointer to void return type" { |
| 421 | 445 | } |
| 422 | 446 | fn testPointerToVoidReturnType() error!void { |
| 423 | 447 | const a = testPointerToVoidReturnType2(); |
| 424 | return *a; | |
| 448 | return a.*; | |
| 425 | 449 | } |
| 426 | 450 | const test_pointer_to_void_return_type_x = void{}; |
| 427 | 451 | fn testPointerToVoidReturnType2() &const void { |
| 428 | 452 | return &test_pointer_to_void_return_type_x; |
| 429 | 453 | } |
| 430 | 454 | |
| 431 | ||
| 432 | 455 | test "non const ptr to aliased type" { |
| 433 | 456 | const int = i32; |
| 434 | 457 | assert(?&int == ?&i32); |
| 435 | 458 | } |
| 436 | 459 | |
| 437 | ||
| 438 | ||
| 439 | 460 | test "array 2D const double ptr" { |
| 440 | 461 | const rect_2d_vertexes = [][1]f32 { |
| 441 | []f32{1.0}, | |
| 442 | []f32{2.0}, | |
| 462 | []f32 {1.0}, | |
| 463 | []f32 {2.0}, | |
| 443 | 464 | }; |
| 444 | 465 | testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); |
| 445 | 466 | } |
| ... | ... | @@ -450,10 +471,21 @@ fn testArray2DConstDoublePtr(ptr: &const f32) void { |
| 450 | 471 | } |
| 451 | 472 | |
| 452 | 473 | const Tid = builtin.TypeId; |
| 453 | const AStruct = struct { x: i32, }; | |
| 454 | const AnEnum = enum { One, Two, }; | |
| 455 | const AUnionEnum = union(enum) { One: i32, Two: void, }; | |
| 456 | const AUnion = union { One: void, Two: void }; | |
| 474 | const AStruct = struct { | |
| 475 | x: i32, | |
| 476 | }; | |
| 477 | const AnEnum = enum { | |
| 478 | One, | |
| 479 | Two, | |
| 480 | }; | |
| 481 | const AUnionEnum = union(enum) { | |
| 482 | One: i32, | |
| 483 | Two: void, | |
| 484 | }; | |
| 485 | const AUnion = union { | |
| 486 | One: void, | |
| 487 | Two: void, | |
| 488 | }; | |
| 457 | 489 | |
| 458 | 490 | test "@typeId" { |
| 459 | 491 | comptime { |
| ... | ... | @@ -481,9 +513,11 @@ test "@typeId" { |
| 481 | 513 | assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); |
| 482 | 514 | assert(@typeId(AUnionEnum) == Tid.Union); |
| 483 | 515 | assert(@typeId(AUnion) == Tid.Union); |
| 484 | assert(@typeId(fn()void) == Tid.Fn); | |
| 516 | assert(@typeId(fn() void) == Tid.Fn); | |
| 485 | 517 | 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); | |
| 487 | 521 | // TODO bound fn |
| 488 | 522 | // TODO arg tuple |
| 489 | 523 | // TODO opaque |
| ... | ... | @@ -499,8 +533,7 @@ test "@canImplicitCast" { |
| 499 | 533 | } |
| 500 | 534 | |
| 501 | 535 | test "@typeName" { |
| 502 | const Struct = struct { | |
| 503 | }; | |
| 536 | const Struct = struct {}; | |
| 504 | 537 | const Union = union { |
| 505 | 538 | unused: u8, |
| 506 | 539 | }; |
| ... | ... | @@ -525,14 +558,19 @@ fn TypeFromFn(comptime T: type) type { |
| 525 | 558 | test "volatile load and store" { |
| 526 | 559 | var number: i32 = 1234; |
| 527 | 560 | const ptr = (&volatile i32)(&number); |
| 528 | *ptr += 1; | |
| 529 | assert(*ptr == 1235); | |
| 561 | ptr.* += 1; | |
| 562 | assert(ptr.* == 1235); | |
| 530 | 563 | } |
| 531 | 564 | |
| 532 | 565 | test "slice string literal has type []const u8" { |
| 533 | 566 | comptime { |
| 534 | 567 | 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 | }; | |
| 536 | 574 | assert(@typeOf(array[0..]) == []const i32); |
| 537 | 575 | } |
| 538 | 576 | } |
| ... | ... | @@ -544,12 +582,15 @@ const GDTEntry = struct { |
| 544 | 582 | field: i32, |
| 545 | 583 | }; |
| 546 | 584 | var gdt = []GDTEntry { |
| 547 | GDTEntry {.field = 1}, | |
| 548 | GDTEntry {.field = 2}, | |
| 585 | GDTEntry { | |
| 586 | .field = 1, | |
| 587 | }, | |
| 588 | GDTEntry { | |
| 589 | .field = 2, | |
| 590 | }, | |
| 549 | 591 | }; |
| 550 | 592 | var global_ptr = &gdt[0]; |
| 551 | 593 | |
| 552 | ||
| 553 | 594 | // can't really run this test but we can make sure it has no compile error |
| 554 | 595 | // and generates code |
| 555 | 596 | const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000]; |
| ... | ... | @@ -584,7 +625,7 @@ test "comptime if inside runtime while which unconditionally breaks" { |
| 584 | 625 | } |
| 585 | 626 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { |
| 586 | 627 | while (cond) { |
| 587 | if (false) { } | |
| 628 | if (false) {} | |
| 588 | 629 | break; |
| 589 | 630 | } |
| 590 | 631 | } |
| ... | ... | @@ -607,7 +648,9 @@ fn testStructInFn() void { |
| 607 | 648 | kind: BlockKind, |
| 608 | 649 | }; |
| 609 | 650 | |
| 610 | var block = Block { .kind = 1234 }; | |
| 651 | var block = Block { | |
| 652 | .kind = 1234, | |
| 653 | }; | |
| 611 | 654 | |
| 612 | 655 | block.kind += 1; |
| 613 | 656 | |
| ... | ... | @@ -617,7 +660,9 @@ fn testStructInFn() void { |
| 617 | 660 | fn fnThatClosesOverLocalConst() type { |
| 618 | 661 | const c = 1; |
| 619 | 662 | return struct { |
| 620 | fn g() i32 { return c; } | |
| 663 | fn g() i32 { | |
| 664 | return c; | |
| 665 | } | |
| 621 | 666 | }; |
| 622 | 667 | } |
| 623 | 668 | |
| ... | ... | @@ -635,22 +680,29 @@ fn thisIsAColdFn() void { |
| 635 | 680 | @setCold(true); |
| 636 | 681 | } |
| 637 | 682 | |
| 638 | ||
| 639 | const PackedStruct = packed struct { a: u8, b: u8, }; | |
| 640 | const PackedUnion = packed union { a: u8, b: u32, }; | |
| 641 | const PackedEnum = packed enum { A, B, }; | |
| 683 | const PackedStruct = packed struct { | |
| 684 | a: u8, | |
| 685 | b: u8, | |
| 686 | }; | |
| 687 | const PackedUnion = packed union { | |
| 688 | a: u8, | |
| 689 | b: u32, | |
| 690 | }; | |
| 691 | const PackedEnum = packed enum { | |
| 692 | A, | |
| 693 | B, | |
| 694 | }; | |
| 642 | 695 | |
| 643 | 696 | test "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 | ||
| 651 | export 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); | |
| 652 | 703 | } |
| 653 | 704 | |
| 705 | export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {} | |
| 654 | 706 | |
| 655 | 707 | test "slicing zero length array" { |
| 656 | 708 | const s1 = ""[0..]; |
| ... | ... | @@ -661,7 +713,6 @@ test "slicing zero length array" { |
| 661 | 713 | assert(mem.eql(u32, s2, []u32{})); |
| 662 | 714 | } |
| 663 | 715 | |
| 664 | ||
| 665 | 716 | const addr1 = @ptrCast(&const u8, emptyFn); |
| 666 | 717 | test "comptime cast fn to ptr" { |
| 667 | 718 | 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" { |
| 8 | 8 | assert(!some_namespace.a_bool); |
| 9 | 9 | } |
| 10 | 10 | } |
| 11 | const some_namespace = switch(builtin.os) { | |
| 11 | const some_namespace = switch (builtin.os) { | |
| 12 | 12 | builtin.Os.linux => @import("a.zig"), |
| 13 | 13 | else => @import("b.zig"), |
| 14 | 14 | }; |
test/cases/new_stack_call.zig+1-1| ... | ... | @@ -19,7 +19,7 @@ fn targetFunction(x: i32) usize { |
| 19 | 19 | |
| 20 | 20 | var local_variable: i32 = 42; |
| 21 | 21 | const ptr = &local_variable; |
| 22 | *ptr += 1; | |
| 22 | ptr.* += 1; | |
| 23 | 23 | |
| 24 | 24 | assert(local_variable == 43); |
| 25 | 25 | return @ptrToInt(ptr); |
test/cases/null.zig+12-15| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | 3 | test "nullable type" { |
| 4 | const x : ?bool = true; | |
| 4 | const x: ?bool = true; | |
| 5 | 5 | |
| 6 | 6 | if (x) |y| { |
| 7 | 7 | if (y) { |
| ... | ... | @@ -13,13 +13,13 @@ test "nullable type" { |
| 13 | 13 | unreachable; |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | const next_x : ?i32 = null; | |
| 16 | const next_x: ?i32 = null; | |
| 17 | 17 | |
| 18 | 18 | const z = next_x ?? 1234; |
| 19 | 19 | |
| 20 | 20 | assert(z == 1234); |
| 21 | 21 | |
| 22 | const final_x : ?i32 = 13; | |
| 22 | const final_x: ?i32 = 13; | |
| 23 | 23 | |
| 24 | 24 | const num = final_x ?? unreachable; |
| 25 | 25 | |
| ... | ... | @@ -30,19 +30,17 @@ test "test maybe object and get a pointer to the inner value" { |
| 30 | 30 | var maybe_bool: ?bool = true; |
| 31 | 31 | |
| 32 | 32 | if (maybe_bool) |*b| { |
| 33 | *b = false; | |
| 33 | b.* = false; | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | assert(??maybe_bool == false); |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | ||
| 40 | 39 | test "rhs maybe unwrap return" { |
| 41 | 40 | const x: ?bool = true; |
| 42 | 41 | const y = x ?? return; |
| 43 | 42 | } |
| 44 | 43 | |
| 45 | ||
| 46 | 44 | test "maybe return" { |
| 47 | 45 | maybeReturnImpl(); |
| 48 | 46 | comptime maybeReturnImpl(); |
| ... | ... | @@ -50,8 +48,7 @@ test "maybe return" { |
| 50 | 48 | |
| 51 | 49 | fn maybeReturnImpl() void { |
| 52 | 50 | assert(??foo(1235)); |
| 53 | if (foo(null) != null) | |
| 54 | unreachable; | |
| 51 | if (foo(null) != null) unreachable; | |
| 55 | 52 | assert(!??foo(1234)); |
| 56 | 53 | } |
| 57 | 54 | |
| ... | ... | @@ -60,12 +57,16 @@ fn foo(x: ?i32) ?bool { |
| 60 | 57 | return value > 1234; |
| 61 | 58 | } |
| 62 | 59 | |
| 63 | ||
| 64 | 60 | test "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); | |
| 66 | 67 | } |
| 67 | 68 | fn shouldBeAPlus1(p: &const Particle) u64 { |
| 68 | var maybe_particle: ?Particle = *p; | |
| 69 | var maybe_particle: ?Particle = p.*; | |
| 69 | 70 | if (maybe_particle) |*particle| { |
| 70 | 71 | particle.a += 1; |
| 71 | 72 | } |
| ... | ... | @@ -81,7 +82,6 @@ const Particle = struct { |
| 81 | 82 | d: u64, |
| 82 | 83 | }; |
| 83 | 84 | |
| 84 | ||
| 85 | 85 | test "null literal outside function" { |
| 86 | 86 | const is_null = here_is_a_null_literal.context == null; |
| 87 | 87 | assert(is_null); |
| ... | ... | @@ -96,7 +96,6 @@ const here_is_a_null_literal = SillyStruct { |
| 96 | 96 | .context = null, |
| 97 | 97 | }; |
| 98 | 98 | |
| 99 | ||
| 100 | 99 | test "test null runtime" { |
| 101 | 100 | testTestNullRuntime(null); |
| 102 | 101 | } |
| ... | ... | @@ -123,8 +122,6 @@ fn bar(x: ?void) ?void { |
| 123 | 122 | } |
| 124 | 123 | } |
| 125 | 124 | |
| 126 | ||
| 127 | ||
| 128 | 125 | const StructWithNullable = struct { |
| 129 | 126 | field: ?i32, |
| 130 | 127 | }; |
test/cases/pointers.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | test "dereference pointer" { | |
| 5 | comptime testDerefPtr(); | |
| 6 | testDerefPtr(); | |
| 7 | } | |
| 8 | ||
| 9 | fn 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 { |
| 23 | 23 | if (c) { |
| 24 | 24 | const output_path = b; |
| 25 | 25 | |
| 26 | if (c2) { } | |
| 26 | if (c2) {} | |
| 27 | 27 | |
| 28 | 28 | a(output_path); |
| 29 | 29 | } |
test/cases/reflection.zig+3-2| ... | ... | @@ -23,7 +23,9 @@ test "reflection: function return type, var args, and param types" { |
| 23 | 23 | } |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; } | |
| 26 | fn dummy(a: bool, b: i32, c: f32) i32 { | |
| 27 | return 1234; | |
| 28 | } | |
| 27 | 29 | fn dummy_varargs(args: ...) void {} |
| 28 | 30 | |
| 29 | 31 | test "reflection: struct member types and names" { |
| ... | ... | @@ -54,7 +56,6 @@ test "reflection: enum member types and names" { |
| 54 | 56 | assert(mem.eql(u8, @memberName(Bar, 2), "Three")); |
| 55 | 57 | assert(mem.eql(u8, @memberName(Bar, 3), "Four")); |
| 56 | 58 | } |
| 57 | ||
| 58 | 59 | } |
| 59 | 60 | |
| 60 | 61 | test "reflection: @field" { |
test/cases/slice.zig+6-2| ... | ... | @@ -18,7 +18,11 @@ test "slice child property" { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | test "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 | }; | |
| 22 | 26 | assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); |
| 23 | 27 | } |
| 24 | 28 | |
| ... | ... | @@ -27,7 +31,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { |
| 27 | 31 | } |
| 28 | 32 | |
| 29 | 33 | test "implicitly cast array of size 0 to slice" { |
| 30 | var msg = []u8 {}; | |
| 34 | var msg = []u8{}; | |
| 31 | 35 | assertLenIsZero(msg); |
| 32 | 36 | } |
| 33 | 37 |
test/cases/struct.zig+48-35| ... | ... | @@ -2,9 +2,11 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | const 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 | } | |
| 6 | 8 | }; |
| 7 | const empty_global_instance = StructWithNoFields {}; | |
| 9 | const empty_global_instance = StructWithNoFields{}; | |
| 8 | 10 | |
| 9 | 11 | test "call struct static method" { |
| 10 | 12 | const result = StructWithNoFields.add(3, 4); |
| ... | ... | @@ -34,12 +36,11 @@ test "void struct fields" { |
| 34 | 36 | assert(@sizeOf(VoidStructFieldsFoo) == 4); |
| 35 | 37 | } |
| 36 | 38 | const VoidStructFieldsFoo = struct { |
| 37 | a : void, | |
| 38 | b : i32, | |
| 39 | c : void, | |
| 39 | a: void, | |
| 40 | b: i32, | |
| 41 | c: void, | |
| 40 | 42 | }; |
| 41 | 43 | |
| 42 | ||
| 43 | 44 | test "structs" { |
| 44 | 45 | var foo: StructFoo = undefined; |
| 45 | 46 | @memset(@ptrCast(&u8, &foo), 0, @sizeOf(StructFoo)); |
| ... | ... | @@ -50,9 +51,9 @@ test "structs" { |
| 50 | 51 | assert(foo.c == 100); |
| 51 | 52 | } |
| 52 | 53 | const StructFoo = struct { |
| 53 | a : i32, | |
| 54 | b : bool, | |
| 55 | c : f32, | |
| 54 | a: i32, | |
| 55 | b: bool, | |
| 56 | c: f32, | |
| 56 | 57 | }; |
| 57 | 58 | fn testFoo(foo: &const StructFoo) void { |
| 58 | 59 | assert(foo.b); |
| ... | ... | @@ -61,7 +62,6 @@ fn testMutation(foo: &StructFoo) void { |
| 61 | 62 | foo.c = 100; |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | ||
| 65 | 65 | const Node = struct { |
| 66 | 66 | val: Val, |
| 67 | 67 | next: &Node, |
| ... | ... | @@ -72,10 +72,10 @@ const Val = struct { |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | 74 | test "struct point to self" { |
| 75 | var root : Node = undefined; | |
| 75 | var root: Node = undefined; | |
| 76 | 76 | root.val.x = 1; |
| 77 | 77 | |
| 78 | var node : Node = undefined; | |
| 78 | var node: Node = undefined; | |
| 79 | 79 | node.next = &root; |
| 80 | 80 | node.val.x = 2; |
| 81 | 81 | |
| ... | ... | @@ -85,8 +85,8 @@ test "struct point to self" { |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | 87 | test "struct byval assign" { |
| 88 | var foo1 : StructFoo = undefined; | |
| 89 | var foo2 : StructFoo = undefined; | |
| 88 | var foo1: StructFoo = undefined; | |
| 89 | var foo2: StructFoo = undefined; | |
| 90 | 90 | |
| 91 | 91 | foo1.a = 1234; |
| 92 | 92 | foo2.a = 0; |
| ... | ... | @@ -96,46 +96,57 @@ test "struct byval assign" { |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | 98 | fn structInitializer() void { |
| 99 | const val = Val { .x = 42 }; | |
| 99 | const val = Val { | |
| 100 | .x = 42, | |
| 101 | }; | |
| 100 | 102 | assert(val.x == 42); |
| 101 | 103 | } |
| 102 | 104 | |
| 103 | ||
| 104 | 105 | test "fn call of struct field" { |
| 105 | assert(callStructField(Foo {.ptr = aFunc,}) == 13); | |
| 106 | assert(callStructField(Foo { | |
| 107 | .ptr = aFunc, | |
| 108 | }) == 13); | |
| 106 | 109 | } |
| 107 | 110 | |
| 108 | 111 | const Foo = struct { |
| 109 | 112 | ptr: fn() i32, |
| 110 | 113 | }; |
| 111 | 114 | |
| 112 | fn aFunc() i32 { return 13; } | |
| 115 | fn aFunc() i32 { | |
| 116 | return 13; | |
| 117 | } | |
| 113 | 118 | |
| 114 | 119 | fn callStructField(foo: &const Foo) i32 { |
| 115 | 120 | return foo.ptr(); |
| 116 | 121 | } |
| 117 | 122 | |
| 118 | ||
| 119 | 123 | test "store member function in variable" { |
| 120 | const instance = MemberFnTestFoo { .x = 1234, }; | |
| 124 | const instance = MemberFnTestFoo { | |
| 125 | .x = 1234, | |
| 126 | }; | |
| 121 | 127 | const memberFn = MemberFnTestFoo.member; |
| 122 | 128 | const result = memberFn(instance); |
| 123 | 129 | assert(result == 1234); |
| 124 | 130 | } |
| 125 | 131 | const MemberFnTestFoo = struct { |
| 126 | 132 | x: i32, |
| 127 | fn member(foo: &const MemberFnTestFoo) i32 { return foo.x; } | |
| 133 | fn member(foo: &const MemberFnTestFoo) i32 { | |
| 134 | return foo.x; | |
| 135 | } | |
| 128 | 136 | }; |
| 129 | 137 | |
| 130 | ||
| 131 | 138 | test "call member function directly" { |
| 132 | const instance = MemberFnTestFoo { .x = 1234, }; | |
| 139 | const instance = MemberFnTestFoo { | |
| 140 | .x = 1234, | |
| 141 | }; | |
| 133 | 142 | const result = MemberFnTestFoo.member(instance); |
| 134 | 143 | assert(result == 1234); |
| 135 | 144 | } |
| 136 | 145 | |
| 137 | 146 | test "member functions" { |
| 138 | const r = MemberFnRand {.seed = 1234}; | |
| 147 | const r = MemberFnRand { | |
| 148 | .seed = 1234, | |
| 149 | }; | |
| 139 | 150 | assert(r.getSeed() == 1234); |
| 140 | 151 | } |
| 141 | 152 | const MemberFnRand = struct { |
| ... | ... | @@ -170,17 +181,16 @@ const EmptyStruct = struct { |
| 170 | 181 | } |
| 171 | 182 | }; |
| 172 | 183 | |
| 173 | ||
| 174 | 184 | test "return empty struct from fn" { |
| 175 | 185 | _ = testReturnEmptyStructFromFn(); |
| 176 | 186 | } |
| 177 | 187 | const EmptyStruct2 = struct {}; |
| 178 | 188 | fn testReturnEmptyStructFromFn() EmptyStruct2 { |
| 179 | return EmptyStruct2 {}; | |
| 189 | return EmptyStruct2{}; | |
| 180 | 190 | } |
| 181 | 191 | |
| 182 | 192 | test "pass slice of empty struct to fn" { |
| 183 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); | |
| 193 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2 {EmptyStruct2{}}) == 1); | |
| 184 | 194 | } |
| 185 | 195 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { |
| 186 | 196 | return slice.len; |
| ... | ... | @@ -201,7 +211,6 @@ test "packed struct" { |
| 201 | 211 | assert(four == 4); |
| 202 | 212 | } |
| 203 | 213 | |
| 204 | ||
| 205 | 214 | const BitField1 = packed struct { |
| 206 | 215 | a: u3, |
| 207 | 216 | b: u3, |
| ... | ... | @@ -301,7 +310,7 @@ test "packed array 24bits" { |
| 301 | 310 | assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); |
| 302 | 311 | } |
| 303 | 312 | |
| 304 | var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); | |
| 313 | var bytes = []u8 {0} ** (@sizeOf(FooArray24Bits) + 1); | |
| 305 | 314 | bytes[bytes.len - 1] = 0xaa; |
| 306 | 315 | const ptr = &([]FooArray24Bits)(bytes[0..bytes.len - 1])[0]; |
| 307 | 316 | assert(ptr.a == 0); |
| ... | ... | @@ -351,7 +360,7 @@ test "aligned array of packed struct" { |
| 351 | 360 | assert(@sizeOf(FooArrayOfAligned) == 2 * 2); |
| 352 | 361 | } |
| 353 | 362 | |
| 354 | var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); | |
| 363 | var bytes = []u8 {0xbb} ** @sizeOf(FooArrayOfAligned); | |
| 355 | 364 | const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0]; |
| 356 | 365 | |
| 357 | 366 | assert(ptr.a[0].a == 0xbb); |
| ... | ... | @@ -360,11 +369,15 @@ test "aligned array of packed struct" { |
| 360 | 369 | assert(ptr.a[1].b == 0xbb); |
| 361 | 370 | } |
| 362 | 371 | |
| 363 | ||
| 364 | ||
| 365 | 372 | test "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 | }; | |
| 368 | 381 | |
| 369 | 382 | assert(s1.x == x1); |
| 370 | 383 | assert(s1.y == x1); |
| ... | ... | @@ -394,7 +407,7 @@ test "native bit field understands endianness" { |
| 394 | 407 | var all: u64 = 0x7765443322221111; |
| 395 | 408 | var bytes: [8]u8 = undefined; |
| 396 | 409 | @memcpy(&bytes[0], @ptrCast(&u8, &all), 8); |
| 397 | var bitfields = *@ptrCast(&Bitfields, &bytes[0]); | |
| 410 | var bitfields = @ptrCast(&Bitfields, &bytes[0]).*; | |
| 398 | 411 | |
| 399 | 412 | assert(bitfields.f1 == 0x1111); |
| 400 | 413 | assert(bitfields.f2 == 0x2222); |
test/cases/struct_contains_null_ptr_itself.zig-1| ... | ... | @@ -19,4 +19,3 @@ pub const Node = struct { |
| 19 | 19 | pub const NodeLineComment = struct { |
| 20 | 20 | base: Node, |
| 21 | 21 | }; |
| 22 |
test/cases/struct_contains_slice_of_itself.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const Node = struct { |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | 8 | test "struct contains slice of itself" { |
| 9 | var other_nodes = []Node{ | |
| 9 | var other_nodes = []Node { | |
| 10 | 10 | Node { |
| 11 | 11 | .payload = 31, |
| 12 | 12 | .children = []Node{}, |
test/cases/switch.zig+33-16| ... | ... | @@ -6,7 +6,10 @@ test "switch with numbers" { |
| 6 | 6 | |
| 7 | 7 | fn testSwitchWithNumbers(x: u32) void { |
| 8 | 8 | const result = switch (x) { |
| 9 | 1, 2, 3, 4 ... 8 => false, | |
| 9 | 1, | |
| 10 | 2, | |
| 11 | 3, | |
| 12 | 4 ... 8 => false, | |
| 10 | 13 | 13 => true, |
| 11 | 14 | else => false, |
| 12 | 15 | }; |
| ... | ... | @@ -34,8 +37,10 @@ test "implicit comptime switch" { |
| 34 | 37 | const result = switch (x) { |
| 35 | 38 | 3 => 10, |
| 36 | 39 | 4 => 11, |
| 37 | 5, 6 => 12, | |
| 38 | 7, 8 => 13, | |
| 40 | 5, | |
| 41 | 6 => 12, | |
| 42 | 7, | |
| 43 | 8 => 13, | |
| 39 | 44 | else => 14, |
| 40 | 45 | }; |
| 41 | 46 | |
| ... | ... | @@ -61,7 +66,6 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void { |
| 61 | 66 | } |
| 62 | 67 | } |
| 63 | 68 | |
| 64 | ||
| 65 | 69 | test "switch statement" { |
| 66 | 70 | nonConstSwitch(SwitchStatmentFoo.C); |
| 67 | 71 | } |
| ... | ... | @@ -81,11 +85,16 @@ const SwitchStatmentFoo = enum { |
| 81 | 85 | D, |
| 82 | 86 | }; |
| 83 | 87 | |
| 84 | ||
| 85 | 88 | test "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 | }); | |
| 89 | 98 | } |
| 90 | 99 | const SwitchProngWithVarEnum = union(enum) { |
| 91 | 100 | One: i32, |
| ... | ... | @@ -93,7 +102,7 @@ const SwitchProngWithVarEnum = union(enum) { |
| 93 | 102 | Meh: void, |
| 94 | 103 | }; |
| 95 | 104 | fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) void { |
| 96 | switch(*a) { | |
| 105 | switch (a.*) { | |
| 97 | 106 | SwitchProngWithVarEnum.One => |x| { |
| 98 | 107 | assert(x == 13); |
| 99 | 108 | }, |
| ... | ... | @@ -112,9 +121,11 @@ test "switch on enum using pointer capture" { |
| 112 | 121 | } |
| 113 | 122 | |
| 114 | 123 | fn testSwitchEnumPtrCapture() void { |
| 115 | var value = SwitchProngWithVarEnum { .One = 1234 }; | |
| 124 | var value = SwitchProngWithVarEnum { | |
| 125 | .One = 1234, | |
| 126 | }; | |
| 116 | 127 | switch (value) { |
| 117 | SwitchProngWithVarEnum.One => |*x| *x += 1, | |
| 128 | SwitchProngWithVarEnum.One => |*x| x.* += 1, | |
| 118 | 129 | else => unreachable, |
| 119 | 130 | } |
| 120 | 131 | switch (value) { |
| ... | ... | @@ -125,8 +136,12 @@ fn testSwitchEnumPtrCapture() void { |
| 125 | 136 | |
| 126 | 137 | test "switch with multiple expressions" { |
| 127 | 138 | 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, | |
| 130 | 145 | else => i32(3), |
| 131 | 146 | }; |
| 132 | 147 | assert(x == 2); |
| ... | ... | @@ -135,14 +150,15 @@ fn returnsFive() i32 { |
| 135 | 150 | return 5; |
| 136 | 151 | } |
| 137 | 152 | |
| 138 | ||
| 139 | 153 | const Number = union(enum) { |
| 140 | 154 | One: u64, |
| 141 | 155 | Two: u8, |
| 142 | 156 | Three: f32, |
| 143 | 157 | }; |
| 144 | 158 | |
| 145 | const number = Number { .Three = 1.23 }; | |
| 159 | const number = Number { | |
| 160 | .Three = 1.23, | |
| 161 | }; | |
| 146 | 162 | |
| 147 | 163 | fn returnsFalse() bool { |
| 148 | 164 | switch (number) { |
| ... | ... | @@ -198,7 +214,8 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 { |
| 198 | 214 | return switch (x) { |
| 199 | 215 | 0 ... 100 => u8(0), |
| 200 | 216 | 101 ... 200 => 1, |
| 201 | 201, 203 => 2, | |
| 217 | 201, | |
| 218 | 203 => 2, | |
| 202 | 219 | 202 => 4, |
| 203 | 220 | 204 ... 255 => 3, |
| 204 | 221 | }; |
test/cases/switch_prong_err_enum.zig+6-2| ... | ... | @@ -14,14 +14,18 @@ const FormValue = union(enum) { |
| 14 | 14 | |
| 15 | 15 | fn doThing(form_id: u64) error!FormValue { |
| 16 | 16 | return switch (form_id) { |
| 17 | 17 => FormValue { .Address = try readOnce() }, | |
| 17 | 17 => FormValue { | |
| 18 | .Address = try readOnce(), | |
| 19 | }, | |
| 18 | 20 | else => error.InvalidDebugInfo, |
| 19 | 21 | }; |
| 20 | 22 | } |
| 21 | 23 | |
| 22 | 24 | test "switch prong returns error enum" { |
| 23 | 25 | switch (doThing(17) catch unreachable) { |
| 24 | FormValue.Address => |payload| { assert(payload == 1); }, | |
| 26 | FormValue.Address => |payload| { | |
| 27 | assert(payload == 1); | |
| 28 | }, | |
| 25 | 29 | else => unreachable, |
| 26 | 30 | } |
| 27 | 31 | assert(read_count == 1); |
test/cases/switch_prong_implicit_cast.zig+6-2| ... | ... | @@ -7,8 +7,12 @@ const FormValue = union(enum) { |
| 7 | 7 | |
| 8 | 8 | fn foo(id: u64) !FormValue { |
| 9 | 9 | 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 | }, | |
| 12 | 16 | else => return error.Whatever, |
| 13 | 17 | }; |
| 14 | 18 | } |
test/cases/try.zig+3-5| ... | ... | @@ -3,14 +3,12 @@ const assert = @import("std").debug.assert; |
| 3 | 3 | test "try on error union" { |
| 4 | 4 | tryOnErrorUnionImpl(); |
| 5 | 5 | comptime tryOnErrorUnionImpl(); |
| 6 | ||
| 7 | 6 | } |
| 8 | 7 | |
| 9 | 8 | fn 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, | |
| 14 | 12 | error.CrappedOut => i32(2), |
| 15 | 13 | else => unreachable, |
| 16 | 14 | }; |
test/cases/undefined.zig+2-2| ... | ... | @@ -63,6 +63,6 @@ test "assign undefined to struct with method" { |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | 65 | test "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)")); | |
| 68 | 68 | } |
test/cases/union.zig+50-36| ... | ... | @@ -10,38 +10,41 @@ const Agg = struct { |
| 10 | 10 | val2: Value, |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | const v1 = Value { .Int = 1234 }; | |
| 14 | const v2 = Value { .Array = []u8{3} ** 9 }; | |
| 13 | const v1 = Value{ .Int = 1234 }; | |
| 14 | const v2 = Value{ .Array = []u8{3} ** 9 }; | |
| 15 | 15 | |
| 16 | const err = (error!Agg)(Agg { | |
| 16 | const err = (error!Agg)(Agg{ | |
| 17 | 17 | .val1 = v1, |
| 18 | 18 | .val2 = v2, |
| 19 | 19 | }); |
| 20 | 20 | |
| 21 | const array = []Value { v1, v2, v1, v2}; | |
| 22 | ||
| 21 | const array = []Value{ | |
| 22 | v1, | |
| 23 | v2, | |
| 24 | v1, | |
| 25 | v2, | |
| 26 | }; | |
| 23 | 27 | |
| 24 | 28 | test "unions embedded in aggregate types" { |
| 25 | 29 | switch (array[1]) { |
| 26 | 30 | Value.Array => |arr| assert(arr[4] == 3), |
| 27 | 31 | else => unreachable, |
| 28 | 32 | } |
| 29 | switch((err catch unreachable).val1) { | |
| 33 | switch ((err catch unreachable).val1) { | |
| 30 | 34 | Value.Int => |x| assert(x == 1234), |
| 31 | 35 | else => unreachable, |
| 32 | 36 | } |
| 33 | 37 | } |
| 34 | 38 | |
| 35 | ||
| 36 | 39 | const Foo = union { |
| 37 | 40 | float: f64, |
| 38 | 41 | int: i32, |
| 39 | 42 | }; |
| 40 | 43 | |
| 41 | 44 | test "basic unions" { |
| 42 | var foo = Foo { .int = 1 }; | |
| 45 | var foo = Foo{ .int = 1 }; | |
| 43 | 46 | assert(foo.int == 1); |
| 44 | foo = Foo {.float = 12.34}; | |
| 47 | foo = Foo{ .float = 12.34 }; | |
| 45 | 48 | assert(foo.float == 12.34); |
| 46 | 49 | } |
| 47 | 50 | |
| ... | ... | @@ -66,11 +69,11 @@ test "init union with runtime value" { |
| 66 | 69 | } |
| 67 | 70 | |
| 68 | 71 | fn setFloat(foo: &Foo, x: f64) void { |
| 69 | *foo = Foo { .float = x }; | |
| 72 | foo.* = Foo{ .float = x }; | |
| 70 | 73 | } |
| 71 | 74 | |
| 72 | 75 | fn setInt(foo: &Foo, x: i32) void { |
| 73 | *foo = Foo { .int = x }; | |
| 76 | foo.* = Foo{ .int = x }; | |
| 74 | 77 | } |
| 75 | 78 | |
| 76 | 79 | const FooExtern = extern union { |
| ... | ... | @@ -79,13 +82,12 @@ const FooExtern = extern union { |
| 79 | 82 | }; |
| 80 | 83 | |
| 81 | 84 | test "basic extern unions" { |
| 82 | var foo = FooExtern { .int = 1 }; | |
| 85 | var foo = FooExtern{ .int = 1 }; | |
| 83 | 86 | assert(foo.int == 1); |
| 84 | 87 | foo.float = 12.34; |
| 85 | 88 | assert(foo.float == 12.34); |
| 86 | 89 | } |
| 87 | 90 | |
| 88 | ||
| 89 | 91 | const Letter = enum { |
| 90 | 92 | A, |
| 91 | 93 | B, |
| ... | ... | @@ -103,12 +105,12 @@ test "union with specified enum tag" { |
| 103 | 105 | } |
| 104 | 106 | |
| 105 | 107 | fn doTest() void { |
| 106 | assert(bar(Payload {.A = 1234}) == -10); | |
| 108 | assert(bar(Payload{ .A = 1234 }) == -10); | |
| 107 | 109 | } |
| 108 | 110 | |
| 109 | 111 | fn 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.*) { | |
| 112 | 114 | Payload.A => |x| return x - 1244, |
| 113 | 115 | Payload.B => |x| if (x == 12.34) i32(20) else 21, |
| 114 | 116 | Payload.C => |x| if (x) i32(30) else 31, |
| ... | ... | @@ -141,13 +143,13 @@ const MultipleChoice2 = union(enum(u32)) { |
| 141 | 143 | |
| 142 | 144 | test "union(enum(u32)) with specified and unspecified tag values" { |
| 143 | 145 | 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 }); | |
| 146 | 148 | } |
| 147 | 149 | |
| 148 | 150 | fn 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.*) { | |
| 151 | 153 | MultipleChoice2.A => 1, |
| 152 | 154 | MultipleChoice2.B => 2, |
| 153 | 155 | MultipleChoice2.C => |v| i32(1000) + v, |
| ... | ... | @@ -160,10 +162,9 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void |
| 160 | 162 | }); |
| 161 | 163 | } |
| 162 | 164 | |
| 163 | ||
| 164 | 165 | const ExternPtrOrInt = extern union { |
| 165 | 166 | ptr: &u8, |
| 166 | int: u64 | |
| 167 | int: u64, | |
| 167 | 168 | }; |
| 168 | 169 | test "extern union size" { |
| 169 | 170 | comptime assert(@sizeOf(ExternPtrOrInt) == 8); |
| ... | ... | @@ -171,7 +172,7 @@ test "extern union size" { |
| 171 | 172 | |
| 172 | 173 | const PackedPtrOrInt = packed union { |
| 173 | 174 | ptr: &u8, |
| 174 | int: u64 | |
| 175 | int: u64, | |
| 175 | 176 | }; |
| 176 | 177 | test "extern union size" { |
| 177 | 178 | comptime assert(@sizeOf(PackedPtrOrInt) == 8); |
| ... | ... | @@ -184,8 +185,16 @@ test "union with only 1 field which is void should be zero bits" { |
| 184 | 185 | comptime assert(@sizeOf(ZeroBits) == 0); |
| 185 | 186 | } |
| 186 | 187 | |
| 187 | const TheTag = enum {A, B, C}; | |
| 188 | const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 }; | |
| 188 | const TheTag = enum { | |
| 189 | A, | |
| 190 | B, | |
| 191 | C, | |
| 192 | }; | |
| 193 | const TheUnion = union(TheTag) { | |
| 194 | A: i32, | |
| 195 | B: i32, | |
| 196 | C: i32, | |
| 197 | }; | |
| 189 | 198 | test "union field access gives the enum values" { |
| 190 | 199 | assert(TheUnion.A == TheTag.A); |
| 191 | 200 | assert(TheUnion.B == TheTag.B); |
| ... | ... | @@ -193,20 +202,28 @@ test "union field access gives the enum values" { |
| 193 | 202 | } |
| 194 | 203 | |
| 195 | 204 | test "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 }); | |
| 198 | 207 | } |
| 199 | 208 | |
| 200 | 209 | fn testCastUnionToTagType(x: &const TheUnion) void { |
| 201 | assert(TheTag(*x) == TheTag.B); | |
| 210 | assert(TheTag(x.*) == TheTag.B); | |
| 202 | 211 | } |
| 203 | 212 | |
| 204 | 213 | test "cast tag type of union to union" { |
| 205 | 214 | var x: Value2 = Letter2.B; |
| 206 | 215 | assert(Letter2(x) == Letter2.B); |
| 207 | 216 | } |
| 208 | const Letter2 = enum { A, B, C }; | |
| 209 | const Value2 = union(Letter2) { A: i32, B, C, }; | |
| 217 | const Letter2 = enum { | |
| 218 | A, | |
| 219 | B, | |
| 220 | C, | |
| 221 | }; | |
| 222 | const Value2 = union(Letter2) { | |
| 223 | A: i32, | |
| 224 | B, | |
| 225 | C, | |
| 226 | }; | |
| 210 | 227 | |
| 211 | 228 | test "implicit cast union to its tag type" { |
| 212 | 229 | var x: Value2 = Letter2.B; |
| ... | ... | @@ -227,19 +244,16 @@ const TheUnion2 = union(enum) { |
| 227 | 244 | }; |
| 228 | 245 | |
| 229 | 246 | fn assertIsTheUnion2Item1(value: &const TheUnion2) void { |
| 230 | assert(*value == TheUnion2.Item1); | |
| 247 | assert(value.* == TheUnion2.Item1); | |
| 231 | 248 | } |
| 232 | 249 | |
| 233 | ||
| 234 | 250 | pub const PackThis = union(enum) { |
| 235 | 251 | Invalid: bool, |
| 236 | 252 | StringLiteral: u2, |
| 237 | 253 | }; |
| 238 | 254 | |
| 239 | 255 | test "constant packed union" { |
| 240 | testConstPackedUnion([]PackThis { | |
| 241 | PackThis { .StringLiteral = 1 }, | |
| 242 | }); | |
| 256 | testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); | |
| 243 | 257 | } |
| 244 | 258 | |
| 245 | 259 | fn testConstPackedUnion(expected_tokens: []const PackThis) void { |
| ... | ... | @@ -252,7 +266,7 @@ test "switch on union with only 1 field" { |
| 252 | 266 | switch (r) { |
| 253 | 267 | PartialInst.Compiled => { |
| 254 | 268 | var z: PartialInstWithPayload = undefined; |
| 255 | z = PartialInstWithPayload { .Compiled = 1234 }; | |
| 269 | z = PartialInstWithPayload{ .Compiled = 1234 }; | |
| 256 | 270 | switch (z) { |
| 257 | 271 | PartialInstWithPayload.Compiled => |x| { |
| 258 | 272 | assert(x == 1234); |
test/cases/var_args.zig+16-9| ... | ... | @@ -2,9 +2,12 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | 3 | fn add(args: ...) i32 { |
| 4 | 4 | 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 | } | |
| 8 | 11 | return sum; |
| 9 | 12 | } |
| 10 | 13 | |
| ... | ... | @@ -55,18 +58,23 @@ fn extraFn(extra: u32, args: ...) usize { |
| 55 | 58 | return args.len; |
| 56 | 59 | } |
| 57 | 60 | |
| 61 | const foos = []fn(...) bool { | |
| 62 | foo1, | |
| 63 | foo2, | |
| 64 | }; | |
| 58 | 65 | |
| 59 | const foos = []fn(...) bool { foo1, foo2 }; | |
| 60 | ||
| 61 | fn foo1(args: ...) bool { return true; } | |
| 62 | fn foo2(args: ...) bool { return false; } | |
| 66 | fn foo1(args: ...) bool { | |
| 67 | return true; | |
| 68 | } | |
| 69 | fn foo2(args: ...) bool { | |
| 70 | return false; | |
| 71 | } | |
| 63 | 72 | |
| 64 | 73 | test "array of var args functions" { |
| 65 | 74 | assert(foos[0]()); |
| 66 | 75 | assert(!foos[1]()); |
| 67 | 76 | } |
| 68 | 77 | |
| 69 | ||
| 70 | 78 | test "pass array and slice of same array to var args should have same pointers" { |
| 71 | 79 | const array = "hi"; |
| 72 | 80 | const slice: []const u8 = array; |
| ... | ... | @@ -79,7 +87,6 @@ fn assertSlicePtrsEql(args: ...) void { |
| 79 | 87 | assert(s1.ptr == s2.ptr); |
| 80 | 88 | } |
| 81 | 89 | |
| 82 | ||
| 83 | 90 | test "pass zero length array to var args param" { |
| 84 | 91 | doNothingWithFirstArg(""); |
| 85 | 92 | } |
test/cases/while.zig+41-24| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | 3 | test "while loop" { |
| 4 | var i : i32 = 0; | |
| 4 | var i: i32 = 0; | |
| 5 | 5 | while (i < 4) { |
| 6 | 6 | i += 1; |
| 7 | 7 | } |
| ... | ... | @@ -35,7 +35,7 @@ test "continue and break" { |
| 35 | 35 | } |
| 36 | 36 | var continue_and_break_counter: i32 = 0; |
| 37 | 37 | fn runContinueAndBreakTest() void { |
| 38 | var i : i32 = 0; | |
| 38 | var i: i32 = 0; | |
| 39 | 39 | while (true) { |
| 40 | 40 | continue_and_break_counter += 2; |
| 41 | 41 | i += 1; |
| ... | ... | @@ -58,10 +58,13 @@ fn returnWithImplicitCastFromWhileLoopTest() error!void { |
| 58 | 58 | |
| 59 | 59 | test "while with continue expression" { |
| 60 | 60 | 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 | } | |
| 65 | 68 | assert(sum == 40); |
| 66 | 69 | } |
| 67 | 70 | |
| ... | ... | @@ -117,17 +120,13 @@ test "while with error union condition" { |
| 117 | 120 | |
| 118 | 121 | var numbers_left: i32 = undefined; |
| 119 | 122 | fn 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: { | |
| 123 | 124 | numbers_left -= 1; |
| 124 | 125 | break :x numbers_left; |
| 125 | 126 | }; |
| 126 | 127 | } |
| 127 | 128 | fn getNumberOrNull() ?i32 { |
| 128 | return if (numbers_left == 0) | |
| 129 | null | |
| 130 | else x: { | |
| 129 | return if (numbers_left == 0) null else x: { | |
| 131 | 130 | numbers_left -= 1; |
| 132 | 131 | break :x numbers_left; |
| 133 | 132 | }; |
| ... | ... | @@ -136,42 +135,48 @@ fn getNumberOrNull() ?i32 { |
| 136 | 135 | test "while on nullable with else result follow else prong" { |
| 137 | 136 | const result = while (returnNull()) |value| { |
| 138 | 137 | break value; |
| 139 | } else i32(2); | |
| 138 | } else | |
| 139 | i32(2); | |
| 140 | 140 | assert(result == 2); |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | test "while on nullable with else result follow break prong" { |
| 144 | 144 | const result = while (returnMaybe(10)) |value| { |
| 145 | 145 | break value; |
| 146 | } else i32(2); | |
| 146 | } else | |
| 147 | i32(2); | |
| 147 | 148 | assert(result == 10); |
| 148 | 149 | } |
| 149 | 150 | |
| 150 | 151 | test "while on error union with else result follow else prong" { |
| 151 | 152 | const result = while (returnError()) |value| { |
| 152 | 153 | break value; |
| 153 | } else |err| i32(2); | |
| 154 | } else|err| | |
| 155 | i32(2); | |
| 154 | 156 | assert(result == 2); |
| 155 | 157 | } |
| 156 | 158 | |
| 157 | 159 | test "while on error union with else result follow break prong" { |
| 158 | 160 | const result = while (returnSuccess(10)) |value| { |
| 159 | 161 | break value; |
| 160 | } else |err| i32(2); | |
| 162 | } else|err| | |
| 163 | i32(2); | |
| 161 | 164 | assert(result == 10); |
| 162 | 165 | } |
| 163 | 166 | |
| 164 | 167 | test "while on bool with else result follow else prong" { |
| 165 | 168 | const result = while (returnFalse()) { |
| 166 | 169 | break i32(10); |
| 167 | } else i32(2); | |
| 170 | } else | |
| 171 | i32(2); | |
| 168 | 172 | assert(result == 2); |
| 169 | 173 | } |
| 170 | 174 | |
| 171 | 175 | test "while on bool with else result follow break prong" { |
| 172 | 176 | const result = while (returnTrue()) { |
| 173 | 177 | break i32(10); |
| 174 | } else i32(2); | |
| 178 | } else | |
| 179 | i32(2); | |
| 175 | 180 | assert(result == 10); |
| 176 | 181 | } |
| 177 | 182 | |
| ... | ... | @@ -202,9 +207,21 @@ fn testContinueOuter() void { |
| 202 | 207 | } |
| 203 | 208 | } |
| 204 | 209 | |
| 205 | fn returnNull() ?i32 { return null; } | |
| 206 | fn returnMaybe(x: i32) ?i32 { return x; } | |
| 207 | fn returnError() error!i32 { return error.YouWantedAnError; } | |
| 208 | fn returnSuccess(x: i32) error!i32 { return x; } | |
| 209 | fn returnFalse() bool { return false; } | |
| 210 | fn returnTrue() bool { return true; } | |
| 210 | fn returnNull() ?i32 { | |
| 211 | return null; | |
| 212 | } | |
| 213 | fn returnMaybe(x: i32) ?i32 { | |
| 214 | return x; | |
| 215 | } | |
| 216 | fn returnError() error!i32 { | |
| 217 | return error.YouWantedAnError; | |
| 218 | } | |
| 219 | fn returnSuccess(x: i32) error!i32 { | |
| 220 | return x; | |
| 221 | } | |
| 222 | fn returnFalse() bool { | |
| 223 | return false; | |
| 224 | } | |
| 225 | fn returnTrue() bool { | |
| 226 | return true; | |
| 227 | } |
test/compare_output.zig+2-2| ... | ... | @@ -287,9 +287,9 @@ pub fn addCases(cases: &tests.CompareOutputContext) void { |
| 287 | 287 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int { |
| 288 | 288 | \\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable); |
| 289 | 289 | \\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable); |
| 290 | \\ if (*a_int < *b_int) { | |
| 290 | \\ if (a_int.* < b_int.*) { | |
| 291 | 291 | \\ return -1; |
| 292 | \\ } else if (*a_int > *b_int) { | |
| 292 | \\ } else if (a_int.* > b_int.*) { | |
| 293 | 293 | \\ return 1; |
| 294 | 294 | \\ } else { |
| 295 | 295 | \\ return 0; |
test/compile_errors.zig+15-15| ... | ... | @@ -4,7 +4,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 4 | 4 | cases.add("invalid deref on switch target", |
| 5 | 5 | \\comptime { |
| 6 | 6 | \\ var tile = Tile.Empty; |
| 7 | \\ switch (*tile) { | |
| 7 | \\ switch (tile.*) { | |
| 8 | 8 | \\ Tile.Empty => {}, |
| 9 | 9 | \\ Tile.Filled => {}, |
| 10 | 10 | \\ } |
| ... | ... | @@ -14,7 +14,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 14 | 14 | \\ Filled, |
| 15 | 15 | \\}; |
| 16 | 16 | , |
| 17 | ".tmp_source.zig:3:13: error: invalid deref on switch target"); | |
| 17 | ".tmp_source.zig:3:17: error: invalid deref on switch target"); | |
| 18 | 18 | |
| 19 | 19 | cases.add("invalid field access in comptime", |
| 20 | 20 | \\comptime { var x = doesnt_exist.whatever; } |
| ... | ... | @@ -1408,14 +1408,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 1408 | 1408 | \\ Two: i32, |
| 1409 | 1409 | \\}; |
| 1410 | 1410 | \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool { |
| 1411 | \\ return *a == *b; | |
| 1411 | \\ return a.* == b.*; | |
| 1412 | 1412 | \\} |
| 1413 | 1413 | \\ |
| 1414 | 1414 | \\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); } |
| 1415 | 1415 | \\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); } |
| 1416 | 1416 | , |
| 1417 | 1417 | ".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'"); | |
| 1419 | 1419 | |
| 1420 | 1420 | cases.add("non-const switch number literal", |
| 1421 | 1421 | \\export fn foo() void { |
| ... | ... | @@ -1513,7 +1513,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 1513 | 1513 | \\var bytes: [ext()]u8 = undefined; |
| 1514 | 1514 | \\export fn f() void { |
| 1515 | 1515 | \\ for (bytes) |*b, i| { |
| 1516 | \\ *b = u8(i); | |
| 1516 | \\ b.* = u8(i); | |
| 1517 | 1517 | \\ } |
| 1518 | 1518 | \\} |
| 1519 | 1519 | , ".tmp_source.zig:2:13: error: unable to evaluate constant expression"); |
| ... | ... | @@ -1819,7 +1819,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 1819 | 1819 | \\} |
| 1820 | 1820 | \\ |
| 1821 | 1821 | \\fn bar(x: &const u3) u3 { |
| 1822 | \\ return *x; | |
| 1822 | \\ return x.*; | |
| 1823 | 1823 | \\} |
| 1824 | 1824 | \\ |
| 1825 | 1825 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } |
| ... | ... | @@ -1903,12 +1903,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 1903 | 1903 | \\var s_buffer: [10]u8 = undefined; |
| 1904 | 1904 | \\pub fn pass(in: []u8) []u8 { |
| 1905 | 1905 | \\ var out = &s_buffer; |
| 1906 | \\ *out[0] = in[0]; | |
| 1907 | \\ return (*out)[0..1]; | |
| 1906 | \\ out[0].* = in[0]; | |
| 1907 | \\ return out.*[0..1]; | |
| 1908 | 1908 | \\} |
| 1909 | 1909 | \\ |
| 1910 | 1910 | \\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'"); | |
| 1912 | 1912 | |
| 1913 | 1913 | cases.add("pass const ptr to mutable ptr fn", |
| 1914 | 1914 | \\fn foo() bool { |
| ... | ... | @@ -2434,7 +2434,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 2434 | 2434 | \\} |
| 2435 | 2435 | \\ |
| 2436 | 2436 | \\fn bar(x: &u32) void { |
| 2437 | \\ *x += 1; | |
| 2437 | \\ x.* += 1; | |
| 2438 | 2438 | \\} |
| 2439 | 2439 | , |
| 2440 | 2440 | ".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'"); |
| ... | ... | @@ -2461,7 +2461,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 2461 | 2461 | \\export fn entry() u32 { |
| 2462 | 2462 | \\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04}; |
| 2463 | 2463 | \\ const ptr = @ptrCast(&u32, &bytes[0]); |
| 2464 | \\ return *ptr; | |
| 2464 | \\ return ptr.*; | |
| 2465 | 2465 | \\} |
| 2466 | 2466 | , |
| 2467 | 2467 | ".tmp_source.zig:3:17: error: cast increases pointer alignment", |
| ... | ... | @@ -2540,14 +2540,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 2540 | 2540 | \\ |
| 2541 | 2541 | \\export fn entry(opaque: &Opaque) void { |
| 2542 | 2542 | \\ var m2 = &2; |
| 2543 | \\ const y: u32 = *m2; | |
| 2543 | \\ const y: u32 = m2.*; | |
| 2544 | 2544 | \\ |
| 2545 | 2545 | \\ var a = undefined; |
| 2546 | 2546 | \\ var b = 1; |
| 2547 | 2547 | \\ var c = 1.0; |
| 2548 | 2548 | \\ var d = this; |
| 2549 | 2549 | \\ var e = null; |
| 2550 | \\ var f = *opaque; | |
| 2550 | \\ var f = opaque.*; | |
| 2551 | 2551 | \\ var g = i32; |
| 2552 | 2552 | \\ var h = @import("std"); |
| 2553 | 2553 | \\ var i = (Foo {}).bar; |
| ... | ... | @@ -3136,13 +3136,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void { |
| 3136 | 3136 | \\ foo(a); |
| 3137 | 3137 | \\} |
| 3138 | 3138 | \\fn foo(a: &const Payload) void { |
| 3139 | \\ switch (*a) { | |
| 3139 | \\ switch (a.*) { | |
| 3140 | 3140 | \\ Payload.A => {}, |
| 3141 | 3141 | \\ else => unreachable, |
| 3142 | 3142 | \\ } |
| 3143 | 3143 | \\} |
| 3144 | 3144 | , |
| 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", | |
| 3146 | 3146 | ".tmp_source.zig:1:17: note: consider 'union(enum)' here"); |
| 3147 | 3147 | |
| 3148 | 3148 | 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) { |
| 16 | 16 | |
| 17 | 17 | var global_allocator: &mem.Allocator = undefined; |
| 18 | 18 | |
| 19 | fn tokenize(input:[] const u8) !ArrayList(Token) { | |
| 19 | fn tokenize(input: []const u8) !ArrayList(Token) { | |
| 20 | 20 | const State = enum { |
| 21 | 21 | Start, |
| 22 | 22 | Word, |
| ... | ... | @@ -29,7 +29,8 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { |
| 29 | 29 | for (input) |b, i| { |
| 30 | 30 | switch (state) { |
| 31 | 31 | State.Start => switch (b) { |
| 32 | 'a'...'z', 'A'...'Z' => { | |
| 32 | 'a' ... 'z', | |
| 33 | 'A' ... 'Z' => { | |
| 33 | 34 | state = State.Word; |
| 34 | 35 | tok_begin = i; |
| 35 | 36 | }, |
| ... | ... | @@ -39,9 +40,12 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { |
| 39 | 40 | else => return error.InvalidInput, |
| 40 | 41 | }, |
| 41 | 42 | 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] }); | |
| 45 | 49 | switch (b) { |
| 46 | 50 | '{' => try token_list.append(Token.OpenBrace), |
| 47 | 51 | '}' => try token_list.append(Token.CloseBrace), |
| ... | ... | @@ -56,7 +60,7 @@ fn tokenize(input:[] const u8) !ArrayList(Token) { |
| 56 | 60 | } |
| 57 | 61 | switch (state) { |
| 58 | 62 | 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..] }), | |
| 60 | 64 | } |
| 61 | 65 | try token_list.append(Token.Eof); |
| 62 | 66 | return token_list; |
| ... | ... | @@ -68,24 +72,24 @@ const Node = union(enum) { |
| 68 | 72 | Combine: []Node, |
| 69 | 73 | }; |
| 70 | 74 | |
| 71 | const ParseError = error { | |
| 75 | const ParseError = error{ | |
| 72 | 76 | InvalidInput, |
| 73 | 77 | OutOfMemory, |
| 74 | 78 | }; |
| 75 | 79 | |
| 76 | 80 | fn 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; | |
| 79 | 83 | |
| 80 | 84 | const result_node = switch (first_token) { |
| 81 | Token.Word => |word| Node { .Scalar = word }, | |
| 85 | Token.Word => |word| Node{ .Scalar = word }, | |
| 82 | 86 | Token.OpenBrace => blk: { |
| 83 | 87 | var list = ArrayList(Node).init(global_allocator); |
| 84 | 88 | while (true) { |
| 85 | 89 | try list.append(try parse(tokens, token_index)); |
| 86 | 90 | |
| 87 | const token = tokens.items[*token_index]; | |
| 88 | *token_index += 1; | |
| 91 | const token = tokens.items[token_index.*]; | |
| 92 | token_index.* += 1; | |
| 89 | 93 | |
| 90 | 94 | switch (token) { |
| 91 | 95 | Token.CloseBrace => break, |
| ... | ... | @@ -93,17 +97,18 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node { |
| 93 | 97 | else => return error.InvalidInput, |
| 94 | 98 | } |
| 95 | 99 | } |
| 96 | break :blk Node { .List = list }; | |
| 100 | break :blk Node{ .List = list }; | |
| 97 | 101 | }, |
| 98 | 102 | else => return error.InvalidInput, |
| 99 | 103 | }; |
| 100 | 104 | |
| 101 | switch (tokens.items[*token_index]) { | |
| 102 | Token.Word, Token.OpenBrace => { | |
| 105 | switch (tokens.items[token_index.*]) { | |
| 106 | Token.Word, | |
| 107 | Token.OpenBrace => { | |
| 103 | 108 | const pair = try global_allocator.alloc(Node, 2); |
| 104 | 109 | pair[0] = result_node; |
| 105 | 110 | pair[1] = try parse(tokens, token_index); |
| 106 | return Node { .Combine = pair }; | |
| 111 | return Node{ .Combine = pair }; | |
| 107 | 112 | }, |
| 108 | 113 | else => return result_node, |
| 109 | 114 | } |
| ... | ... | @@ -137,13 +142,11 @@ fn expandString(input: []const u8, output: &Buffer) !void { |
| 137 | 142 | } |
| 138 | 143 | } |
| 139 | 144 | |
| 140 | const ExpandNodeError = error { | |
| 141 | OutOfMemory, | |
| 142 | }; | |
| 145 | const ExpandNodeError = error{OutOfMemory}; | |
| 143 | 146 | |
| 144 | 147 | fn expandNode(node: &const Node, output: &ArrayList(Buffer)) ExpandNodeError!void { |
| 145 | 148 | assert(output.len == 0); |
| 146 | switch (*node) { | |
| 149 | switch (node.*) { | |
| 147 | 150 | Node.Scalar => |scalar| { |
| 148 | 151 | try output.append(try Buffer.init(global_allocator, scalar)); |
| 149 | 152 | }, |
test/tests.zig+90-100| ... | ... | @@ -27,18 +27,18 @@ const TestTarget = struct { |
| 27 | 27 | environ: builtin.Environ, |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | const test_targets = []TestTarget { | |
| 31 | TestTarget { | |
| 30 | const test_targets = []TestTarget{ | |
| 31 | TestTarget{ | |
| 32 | 32 | .os = builtin.Os.linux, |
| 33 | 33 | .arch = builtin.Arch.x86_64, |
| 34 | 34 | .environ = builtin.Environ.gnu, |
| 35 | 35 | }, |
| 36 | TestTarget { | |
| 36 | TestTarget{ | |
| 37 | 37 | .os = builtin.Os.macosx, |
| 38 | 38 | .arch = builtin.Arch.x86_64, |
| 39 | 39 | .environ = builtin.Environ.unknown, |
| 40 | 40 | }, |
| 41 | TestTarget { | |
| 41 | TestTarget{ | |
| 42 | 42 | .os = builtin.Os.windows, |
| 43 | 43 | .arch = builtin.Arch.x86_64, |
| 44 | 44 | .environ = builtin.Environ.msvc, |
| ... | ... | @@ -49,7 +49,7 @@ const max_stdout_size = 1 * 1024 * 1024; // 1 MB |
| 49 | 49 | |
| 50 | 50 | pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 51 | 51 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 52 | *cases = CompareOutputContext { | |
| 52 | cases.* = CompareOutputContext{ | |
| 53 | 53 | .b = b, |
| 54 | 54 | .step = b.step("test-compare-output", "Run the compare output tests"), |
| 55 | 55 | .test_index = 0, |
| ... | ... | @@ -63,7 +63,7 @@ pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build |
| 63 | 63 | |
| 64 | 64 | pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 65 | 65 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 66 | *cases = CompareOutputContext { | |
| 66 | cases.* = CompareOutputContext{ | |
| 67 | 67 | .b = b, |
| 68 | 68 | .step = b.step("test-runtime-safety", "Run the runtime safety tests"), |
| 69 | 69 | .test_index = 0, |
| ... | ... | @@ -77,7 +77,7 @@ pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build |
| 77 | 77 | |
| 78 | 78 | pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 79 | 79 | const cases = b.allocator.create(CompileErrorContext) catch unreachable; |
| 80 | *cases = CompileErrorContext { | |
| 80 | cases.* = CompileErrorContext{ | |
| 81 | 81 | .b = b, |
| 82 | 82 | .step = b.step("test-compile-errors", "Run the compile error tests"), |
| 83 | 83 | .test_index = 0, |
| ... | ... | @@ -91,7 +91,7 @@ pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build. |
| 91 | 91 | |
| 92 | 92 | pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 93 | 93 | const cases = b.allocator.create(BuildExamplesContext) catch unreachable; |
| 94 | *cases = BuildExamplesContext { | |
| 94 | cases.* = BuildExamplesContext{ | |
| 95 | 95 | .b = b, |
| 96 | 96 | .step = b.step("test-build-examples", "Build the examples"), |
| 97 | 97 | .test_index = 0, |
| ... | ... | @@ -105,7 +105,7 @@ pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build. |
| 105 | 105 | |
| 106 | 106 | pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 107 | 107 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 108 | *cases = CompareOutputContext { | |
| 108 | cases.* = CompareOutputContext{ | |
| 109 | 109 | .b = b, |
| 110 | 110 | .step = b.step("test-asm-link", "Run the assemble and link tests"), |
| 111 | 111 | .test_index = 0, |
| ... | ... | @@ -119,7 +119,7 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &bui |
| 119 | 119 | |
| 120 | 120 | pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 121 | 121 | const cases = b.allocator.create(TranslateCContext) catch unreachable; |
| 122 | *cases = TranslateCContext { | |
| 122 | cases.* = TranslateCContext{ | |
| 123 | 123 | .b = b, |
| 124 | 124 | .step = b.step("test-translate-c", "Run the C transation tests"), |
| 125 | 125 | .test_index = 0, |
| ... | ... | @@ -133,7 +133,7 @@ pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.St |
| 133 | 133 | |
| 134 | 134 | pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 135 | 135 | const cases = b.allocator.create(GenHContext) catch unreachable; |
| 136 | *cases = GenHContext { | |
| 136 | cases.* = GenHContext{ | |
| 137 | 137 | .b = b, |
| 138 | 138 | .step = b.step("test-gen-h", "Run the C header file generation tests"), |
| 139 | 139 | .test_index = 0, |
| ... | ... | @@ -145,22 +145,26 @@ pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { |
| 145 | 145 | return cases.step; |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | ||
| 149 | pub 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 | { | |
| 148 | pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8, name: []const u8, desc: []const u8, with_lldb: bool) &build.Step { | |
| 152 | 149 | const step = b.step(b.fmt("test-{}", name), desc); |
| 153 | 150 | for (test_targets) |test_target| { |
| 154 | 151 | 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| { | |
| 157 | 162 | if (link_libc and !is_native) { |
| 158 | 163 | // don't assume we have a cross-compiling libc set up |
| 159 | 164 | continue; |
| 160 | 165 | } |
| 161 | 166 | 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")); | |
| 164 | 168 | these_tests.setFilter(test_filter); |
| 165 | 169 | these_tests.setBuildMode(mode); |
| 166 | 170 | if (!is_native) { |
| ... | ... | @@ -171,7 +175,15 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons |
| 171 | 175 | } |
| 172 | 176 | if (with_lldb) { |
| 173 | 177 | 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 | }); | |
| 175 | 187 | } |
| 176 | 188 | step.dependOn(&these_tests.step); |
| 177 | 189 | } |
| ... | ... | @@ -206,7 +218,7 @@ pub const CompareOutputContext = struct { |
| 206 | 218 | }; |
| 207 | 219 | |
| 208 | 220 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { |
| 209 | self.sources.append(SourceFile { | |
| 221 | self.sources.append(SourceFile{ | |
| 210 | 222 | .filename = filename, |
| 211 | 223 | .source = source, |
| 212 | 224 | }) catch unreachable; |
| ... | ... | @@ -226,13 +238,10 @@ pub const CompareOutputContext = struct { |
| 226 | 238 | test_index: usize, |
| 227 | 239 | cli_args: []const []const u8, |
| 228 | 240 | |
| 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 { | |
| 233 | 242 | const allocator = context.b.allocator; |
| 234 | 243 | const ptr = allocator.create(RunCompareOutputStep) catch unreachable; |
| 235 | *ptr = RunCompareOutputStep { | |
| 244 | ptr.* = RunCompareOutputStep{ | |
| 236 | 245 | .context = context, |
| 237 | 246 | .exe_path = exe_path, |
| 238 | 247 | .name = name, |
| ... | ... | @@ -258,7 +267,7 @@ pub const CompareOutputContext = struct { |
| 258 | 267 | args.append(arg) catch unreachable; |
| 259 | 268 | } |
| 260 | 269 | |
| 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); | |
| 262 | 271 | |
| 263 | 272 | const child = os.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable; |
| 264 | 273 | defer child.deinit(); |
| ... | ... | @@ -295,7 +304,6 @@ pub const CompareOutputContext = struct { |
| 295 | 304 | }, |
| 296 | 305 | } |
| 297 | 306 | |
| 298 | ||
| 299 | 307 | if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) { |
| 300 | 308 | warn( |
| 301 | 309 | \\ |
| ... | ... | @@ -318,12 +326,10 @@ pub const CompareOutputContext = struct { |
| 318 | 326 | name: []const u8, |
| 319 | 327 | test_index: usize, |
| 320 | 328 | |
| 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 { | |
| 324 | 330 | const allocator = context.b.allocator; |
| 325 | 331 | const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable; |
| 326 | *ptr = RuntimeSafetyRunStep { | |
| 332 | ptr.* = RuntimeSafetyRunStep{ | |
| 327 | 333 | .context = context, |
| 328 | 334 | .exe_path = exe_path, |
| 329 | 335 | .name = name, |
| ... | ... | @@ -340,7 +346,7 @@ pub const CompareOutputContext = struct { |
| 340 | 346 | |
| 341 | 347 | const full_exe_path = b.pathFromRoot(self.exe_path); |
| 342 | 348 | |
| 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); | |
| 344 | 350 | |
| 345 | 351 | const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable; |
| 346 | 352 | defer child.deinit(); |
| ... | ... | @@ -358,19 +364,16 @@ pub const CompareOutputContext = struct { |
| 358 | 364 | switch (term) { |
| 359 | 365 | Term.Exited => |code| { |
| 360 | 366 | 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); | |
| 363 | 368 | return error.TestFailed; |
| 364 | 369 | } |
| 365 | 370 | }, |
| 366 | 371 | 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); | |
| 369 | 373 | return error.TestFailed; |
| 370 | 374 | }, |
| 371 | 375 | 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); | |
| 374 | 377 | return error.TestFailed; |
| 375 | 378 | }, |
| 376 | 379 | } |
| ... | ... | @@ -379,10 +382,8 @@ pub const CompareOutputContext = struct { |
| 379 | 382 | } |
| 380 | 383 | }; |
| 381 | 384 | |
| 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{ | |
| 386 | 387 | .name = name, |
| 387 | 388 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 388 | 389 | .expected_output = expected_output, |
| ... | ... | @@ -395,9 +396,7 @@ pub const CompareOutputContext = struct { |
| 395 | 396 | return tc; |
| 396 | 397 | } |
| 397 | 398 | |
| 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 { | |
| 401 | 400 | return createExtra(self, name, source, expected_output, Special.None); |
| 402 | 401 | } |
| 403 | 402 | |
| ... | ... | @@ -431,8 +430,7 @@ pub const CompareOutputContext = struct { |
| 431 | 430 | Special.Asm => { |
| 432 | 431 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable; |
| 433 | 432 | 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; | |
| 436 | 434 | } |
| 437 | 435 | |
| 438 | 436 | const exe = b.addExecutable("test", null); |
| ... | ... | @@ -444,19 +442,21 @@ pub const CompareOutputContext = struct { |
| 444 | 442 | exe.step.dependOn(&write_src.step); |
| 445 | 443 | } |
| 446 | 444 | |
| 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); | |
| 449 | 446 | run_and_cmp_output.step.dependOn(&exe.step); |
| 450 | 447 | |
| 451 | 448 | self.step.dependOn(&run_and_cmp_output.step); |
| 452 | 449 | }, |
| 453 | 450 | 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; | |
| 457 | 458 | 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; | |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | 462 | const exe = b.addExecutable("test", root_src); |
| ... | ... | @@ -471,8 +471,7 @@ pub const CompareOutputContext = struct { |
| 471 | 471 | exe.step.dependOn(&write_src.step); |
| 472 | 472 | } |
| 473 | 473 | |
| 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); | |
| 476 | 475 | run_and_cmp_output.step.dependOn(&exe.step); |
| 477 | 476 | |
| 478 | 477 | self.step.dependOn(&run_and_cmp_output.step); |
| ... | ... | @@ -481,8 +480,7 @@ pub const CompareOutputContext = struct { |
| 481 | 480 | Special.RuntimeSafety => { |
| 482 | 481 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable; |
| 483 | 482 | 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; | |
| 486 | 484 | } |
| 487 | 485 | |
| 488 | 486 | const exe = b.addExecutable("test", root_src); |
| ... | ... | @@ -524,7 +522,7 @@ pub const CompileErrorContext = struct { |
| 524 | 522 | }; |
| 525 | 523 | |
| 526 | 524 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { |
| 527 | self.sources.append(SourceFile { | |
| 525 | self.sources.append(SourceFile{ | |
| 528 | 526 | .filename = filename, |
| 529 | 527 | .source = source, |
| 530 | 528 | }) catch unreachable; |
| ... | ... | @@ -543,12 +541,10 @@ pub const CompileErrorContext = struct { |
| 543 | 541 | case: &const TestCase, |
| 544 | 542 | build_mode: Mode, |
| 545 | 543 | |
| 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 { | |
| 549 | 545 | const allocator = context.b.allocator; |
| 550 | 546 | const ptr = allocator.create(CompileCmpOutputStep) catch unreachable; |
| 551 | *ptr = CompileCmpOutputStep { | |
| 547 | ptr.* = CompileCmpOutputStep{ | |
| 552 | 548 | .step = build.Step.init("CompileCmpOutput", allocator, make), |
| 553 | 549 | .context = context, |
| 554 | 550 | .name = name, |
| ... | ... | @@ -586,7 +582,7 @@ pub const CompileErrorContext = struct { |
| 586 | 582 | Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable, |
| 587 | 583 | } |
| 588 | 584 | |
| 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); | |
| 590 | 586 | |
| 591 | 587 | if (b.verbose) { |
| 592 | 588 | printInvocation(zig_args.toSliceConst()); |
| ... | ... | @@ -626,7 +622,6 @@ pub const CompileErrorContext = struct { |
| 626 | 622 | }, |
| 627 | 623 | } |
| 628 | 624 | |
| 629 | ||
| 630 | 625 | const stdout = stdout_buf.toSliceConst(); |
| 631 | 626 | const stderr = stderr_buf.toSliceConst(); |
| 632 | 627 | |
| ... | ... | @@ -666,11 +661,9 @@ pub const CompileErrorContext = struct { |
| 666 | 661 | warn("\n"); |
| 667 | 662 | } |
| 668 | 663 | |
| 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 { | |
| 672 | 665 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 673 | *tc = TestCase { | |
| 666 | tc.* = TestCase{ | |
| 674 | 667 | .name = name, |
| 675 | 668 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 676 | 669 | .expected_errors = ArrayList([]const u8).init(self.b.allocator), |
| ... | ... | @@ -705,12 +698,13 @@ pub const CompileErrorContext = struct { |
| 705 | 698 | pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void { |
| 706 | 699 | const b = self.b; |
| 707 | 700 | |
| 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; | |
| 711 | 706 | 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; | |
| 714 | 708 | } |
| 715 | 709 | |
| 716 | 710 | const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode); |
| ... | ... | @@ -744,8 +738,7 @@ pub const BuildExamplesContext = struct { |
| 744 | 738 | |
| 745 | 739 | const annotated_case_name = b.fmt("build {} (Debug)", build_file); |
| 746 | 740 | 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; | |
| 749 | 742 | } |
| 750 | 743 | |
| 751 | 744 | var zig_args = ArrayList([]const u8).init(b.allocator); |
| ... | ... | @@ -773,12 +766,15 @@ pub const BuildExamplesContext = struct { |
| 773 | 766 | pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void { |
| 774 | 767 | const b = self.b; |
| 775 | 768 | |
| 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; | |
| 779 | 776 | 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; | |
| 782 | 778 | } |
| 783 | 779 | |
| 784 | 780 | const exe = b.addExecutable("test", root_src); |
| ... | ... | @@ -813,7 +809,7 @@ pub const TranslateCContext = struct { |
| 813 | 809 | }; |
| 814 | 810 | |
| 815 | 811 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { |
| 816 | self.sources.append(SourceFile { | |
| 812 | self.sources.append(SourceFile{ | |
| 817 | 813 | .filename = filename, |
| 818 | 814 | .source = source, |
| 819 | 815 | }) catch unreachable; |
| ... | ... | @@ -834,7 +830,7 @@ pub const TranslateCContext = struct { |
| 834 | 830 | pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep { |
| 835 | 831 | const allocator = context.b.allocator; |
| 836 | 832 | const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable; |
| 837 | *ptr = TranslateCCmpOutputStep { | |
| 833 | ptr.* = TranslateCCmpOutputStep{ | |
| 838 | 834 | .step = build.Step.init("ParseCCmpOutput", allocator, make), |
| 839 | 835 | .context = context, |
| 840 | 836 | .name = name, |
| ... | ... | @@ -857,7 +853,7 @@ pub const TranslateCContext = struct { |
| 857 | 853 | zig_args.append("translate-c") catch unreachable; |
| 858 | 854 | zig_args.append(b.pathFromRoot(root_src)) catch unreachable; |
| 859 | 855 | |
| 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); | |
| 861 | 857 | |
| 862 | 858 | if (b.verbose) { |
| 863 | 859 | printInvocation(zig_args.toSliceConst()); |
| ... | ... | @@ -939,11 +935,9 @@ pub const TranslateCContext = struct { |
| 939 | 935 | warn("\n"); |
| 940 | 936 | } |
| 941 | 937 | |
| 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 { | |
| 945 | 939 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 946 | *tc = TestCase { | |
| 940 | tc.* = TestCase{ | |
| 947 | 941 | .name = name, |
| 948 | 942 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 949 | 943 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), |
| ... | ... | @@ -977,8 +971,7 @@ pub const TranslateCContext = struct { |
| 977 | 971 | |
| 978 | 972 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable; |
| 979 | 973 | 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; | |
| 982 | 975 | } |
| 983 | 976 | |
| 984 | 977 | const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case); |
| ... | ... | @@ -1009,7 +1002,7 @@ pub const GenHContext = struct { |
| 1009 | 1002 | }; |
| 1010 | 1003 | |
| 1011 | 1004 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { |
| 1012 | self.sources.append(SourceFile { | |
| 1005 | self.sources.append(SourceFile{ | |
| 1013 | 1006 | .filename = filename, |
| 1014 | 1007 | .source = source, |
| 1015 | 1008 | }) catch unreachable; |
| ... | ... | @@ -1031,7 +1024,7 @@ pub const GenHContext = struct { |
| 1031 | 1024 | pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep { |
| 1032 | 1025 | const allocator = context.b.allocator; |
| 1033 | 1026 | const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; |
| 1034 | *ptr = GenHCmpOutputStep { | |
| 1027 | ptr.* = GenHCmpOutputStep{ | |
| 1035 | 1028 | .step = build.Step.init("ParseCCmpOutput", allocator, make), |
| 1036 | 1029 | .context = context, |
| 1037 | 1030 | .h_path = h_path, |
| ... | ... | @@ -1047,7 +1040,7 @@ pub const GenHContext = struct { |
| 1047 | 1040 | const self = @fieldParentPtr(GenHCmpOutputStep, "step", step); |
| 1048 | 1041 | const b = self.context.b; |
| 1049 | 1042 | |
| 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); | |
| 1051 | 1044 | |
| 1052 | 1045 | const full_h_path = b.pathFromRoot(self.h_path); |
| 1053 | 1046 | const actual_h = try io.readFileAlloc(b.allocator, full_h_path); |
| ... | ... | @@ -1076,11 +1069,9 @@ pub const GenHContext = struct { |
| 1076 | 1069 | warn("\n"); |
| 1077 | 1070 | } |
| 1078 | 1071 | |
| 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 { | |
| 1082 | 1073 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 1083 | *tc = TestCase { | |
| 1074 | tc.* = TestCase{ | |
| 1084 | 1075 | .name = name, |
| 1085 | 1076 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), |
| 1086 | 1077 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), |
| ... | ... | @@ -1105,8 +1096,7 @@ pub const GenHContext = struct { |
| 1105 | 1096 | const mode = builtin.Mode.Debug; |
| 1106 | 1097 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; |
| 1107 | 1098 | 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; | |
| 1110 | 1100 | } |
| 1111 | 1101 | |
| 1112 | 1102 | const obj = b.addObject("test", root_src); |
test/translate_c.zig+50-50| ... | ... | @@ -720,43 +720,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 720 | 720 | \\ var a: c_int = 0; |
| 721 | 721 | \\ a += x: { |
| 722 | 722 | \\ const _ref = &a; |
| 723 | \\ (*_ref) = ((*_ref) + 1); | |
| 724 | \\ break :x *_ref; | |
| 723 | \\ _ref.* = (_ref.* + 1); | |
| 724 | \\ break :x _ref.*; | |
| 725 | 725 | \\ }; |
| 726 | 726 | \\ a -= x: { |
| 727 | 727 | \\ const _ref = &a; |
| 728 | \\ (*_ref) = ((*_ref) - 1); | |
| 729 | \\ break :x *_ref; | |
| 728 | \\ _ref.* = (_ref.* - 1); | |
| 729 | \\ break :x _ref.*; | |
| 730 | 730 | \\ }; |
| 731 | 731 | \\ a *= x: { |
| 732 | 732 | \\ const _ref = &a; |
| 733 | \\ (*_ref) = ((*_ref) * 1); | |
| 734 | \\ break :x *_ref; | |
| 733 | \\ _ref.* = (_ref.* * 1); | |
| 734 | \\ break :x _ref.*; | |
| 735 | 735 | \\ }; |
| 736 | 736 | \\ a &= x: { |
| 737 | 737 | \\ const _ref = &a; |
| 738 | \\ (*_ref) = ((*_ref) & 1); | |
| 739 | \\ break :x *_ref; | |
| 738 | \\ _ref.* = (_ref.* & 1); | |
| 739 | \\ break :x _ref.*; | |
| 740 | 740 | \\ }; |
| 741 | 741 | \\ a |= x: { |
| 742 | 742 | \\ const _ref = &a; |
| 743 | \\ (*_ref) = ((*_ref) | 1); | |
| 744 | \\ break :x *_ref; | |
| 743 | \\ _ref.* = (_ref.* | 1); | |
| 744 | \\ break :x _ref.*; | |
| 745 | 745 | \\ }; |
| 746 | 746 | \\ a ^= x: { |
| 747 | 747 | \\ const _ref = &a; |
| 748 | \\ (*_ref) = ((*_ref) ^ 1); | |
| 749 | \\ break :x *_ref; | |
| 748 | \\ _ref.* = (_ref.* ^ 1); | |
| 749 | \\ break :x _ref.*; | |
| 750 | 750 | \\ }; |
| 751 | 751 | \\ a >>= @import("std").math.Log2Int(c_int)(x: { |
| 752 | 752 | \\ 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.*; | |
| 755 | 755 | \\ }); |
| 756 | 756 | \\ a <<= @import("std").math.Log2Int(c_int)(x: { |
| 757 | 757 | \\ 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.*; | |
| 760 | 760 | \\ }); |
| 761 | 761 | \\} |
| 762 | 762 | ); |
| ... | ... | @@ -778,43 +778,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 778 | 778 | \\ var a: c_uint = c_uint(0); |
| 779 | 779 | \\ a +%= x: { |
| 780 | 780 | \\ const _ref = &a; |
| 781 | \\ (*_ref) = ((*_ref) +% c_uint(1)); | |
| 782 | \\ break :x *_ref; | |
| 781 | \\ _ref.* = (_ref.* +% c_uint(1)); | |
| 782 | \\ break :x _ref.*; | |
| 783 | 783 | \\ }; |
| 784 | 784 | \\ a -%= x: { |
| 785 | 785 | \\ const _ref = &a; |
| 786 | \\ (*_ref) = ((*_ref) -% c_uint(1)); | |
| 787 | \\ break :x *_ref; | |
| 786 | \\ _ref.* = (_ref.* -% c_uint(1)); | |
| 787 | \\ break :x _ref.*; | |
| 788 | 788 | \\ }; |
| 789 | 789 | \\ a *%= x: { |
| 790 | 790 | \\ const _ref = &a; |
| 791 | \\ (*_ref) = ((*_ref) *% c_uint(1)); | |
| 792 | \\ break :x *_ref; | |
| 791 | \\ _ref.* = (_ref.* *% c_uint(1)); | |
| 792 | \\ break :x _ref.*; | |
| 793 | 793 | \\ }; |
| 794 | 794 | \\ a &= x: { |
| 795 | 795 | \\ const _ref = &a; |
| 796 | \\ (*_ref) = ((*_ref) & c_uint(1)); | |
| 797 | \\ break :x *_ref; | |
| 796 | \\ _ref.* = (_ref.* & c_uint(1)); | |
| 797 | \\ break :x _ref.*; | |
| 798 | 798 | \\ }; |
| 799 | 799 | \\ a |= x: { |
| 800 | 800 | \\ const _ref = &a; |
| 801 | \\ (*_ref) = ((*_ref) | c_uint(1)); | |
| 802 | \\ break :x *_ref; | |
| 801 | \\ _ref.* = (_ref.* | c_uint(1)); | |
| 802 | \\ break :x _ref.*; | |
| 803 | 803 | \\ }; |
| 804 | 804 | \\ a ^= x: { |
| 805 | 805 | \\ const _ref = &a; |
| 806 | \\ (*_ref) = ((*_ref) ^ c_uint(1)); | |
| 807 | \\ break :x *_ref; | |
| 806 | \\ _ref.* = (_ref.* ^ c_uint(1)); | |
| 807 | \\ break :x _ref.*; | |
| 808 | 808 | \\ }; |
| 809 | 809 | \\ a >>= @import("std").math.Log2Int(c_uint)(x: { |
| 810 | 810 | \\ 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.*; | |
| 813 | 813 | \\ }); |
| 814 | 814 | \\ a <<= @import("std").math.Log2Int(c_uint)(x: { |
| 815 | 815 | \\ 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.*; | |
| 818 | 818 | \\ }); |
| 819 | 819 | \\} |
| 820 | 820 | ); |
| ... | ... | @@ -853,26 +853,26 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 853 | 853 | \\ u -%= 1; |
| 854 | 854 | \\ i = x: { |
| 855 | 855 | \\ const _ref = &i; |
| 856 | \\ const _tmp = *_ref; | |
| 857 | \\ (*_ref) += 1; | |
| 856 | \\ const _tmp = _ref.*; | |
| 857 | \\ _ref.* += 1; | |
| 858 | 858 | \\ break :x _tmp; |
| 859 | 859 | \\ }; |
| 860 | 860 | \\ i = x: { |
| 861 | 861 | \\ const _ref = &i; |
| 862 | \\ const _tmp = *_ref; | |
| 863 | \\ (*_ref) -= 1; | |
| 862 | \\ const _tmp = _ref.*; | |
| 863 | \\ _ref.* -= 1; | |
| 864 | 864 | \\ break :x _tmp; |
| 865 | 865 | \\ }; |
| 866 | 866 | \\ u = x: { |
| 867 | 867 | \\ const _ref = &u; |
| 868 | \\ const _tmp = *_ref; | |
| 869 | \\ (*_ref) +%= 1; | |
| 868 | \\ const _tmp = _ref.*; | |
| 869 | \\ _ref.* +%= 1; | |
| 870 | 870 | \\ break :x _tmp; |
| 871 | 871 | \\ }; |
| 872 | 872 | \\ u = x: { |
| 873 | 873 | \\ const _ref = &u; |
| 874 | \\ const _tmp = *_ref; | |
| 875 | \\ (*_ref) -%= 1; | |
| 874 | \\ const _tmp = _ref.*; | |
| 875 | \\ _ref.* -%= 1; | |
| 876 | 876 | \\ break :x _tmp; |
| 877 | 877 | \\ }; |
| 878 | 878 | \\} |
| ... | ... | @@ -901,23 +901,23 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 901 | 901 | \\ u -%= 1; |
| 902 | 902 | \\ i = x: { |
| 903 | 903 | \\ const _ref = &i; |
| 904 | \\ (*_ref) += 1; | |
| 905 | \\ break :x *_ref; | |
| 904 | \\ _ref.* += 1; | |
| 905 | \\ break :x _ref.*; | |
| 906 | 906 | \\ }; |
| 907 | 907 | \\ i = x: { |
| 908 | 908 | \\ const _ref = &i; |
| 909 | \\ (*_ref) -= 1; | |
| 910 | \\ break :x *_ref; | |
| 909 | \\ _ref.* -= 1; | |
| 910 | \\ break :x _ref.*; | |
| 911 | 911 | \\ }; |
| 912 | 912 | \\ u = x: { |
| 913 | 913 | \\ const _ref = &u; |
| 914 | \\ (*_ref) +%= 1; | |
| 915 | \\ break :x *_ref; | |
| 914 | \\ _ref.* +%= 1; | |
| 915 | \\ break :x _ref.*; | |
| 916 | 916 | \\ }; |
| 917 | 917 | \\ u = x: { |
| 918 | 918 | \\ const _ref = &u; |
| 919 | \\ (*_ref) -%= 1; | |
| 920 | \\ break :x *_ref; | |
| 919 | \\ _ref.* -%= 1; | |
| 920 | \\ break :x _ref.*; | |
| 921 | 921 | \\ }; |
| 922 | 922 | \\} |
| 923 | 923 | ); |
| ... | ... | @@ -985,7 +985,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 985 | 985 | \\} |
| 986 | 986 | , |
| 987 | 987 | \\pub export fn foo(x: ?&c_int) void { |
| 988 | \\ (*??x) = 1; | |
| 988 | \\ (??x).* = 1; | |
| 989 | 989 | \\} |
| 990 | 990 | ); |
| 991 | 991 | |
| ... | ... | @@ -1013,7 +1013,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void { |
| 1013 | 1013 | \\pub fn foo() c_int { |
| 1014 | 1014 | \\ var x: c_int = 1234; |
| 1015 | 1015 | \\ var ptr: ?&c_int = &x; |
| 1016 | \\ return *??ptr; | |
| 1016 | \\ return (??ptr).*; | |
| 1017 | 1017 | \\} |
| 1018 | 1018 | ); |
| 1019 | 1019 |