all tests passing with postfix deref syntax
This commit is contained in:
parent
99fc2bd4dd
commit
c38b165db4
59
build.zig
59
build.zig
@ -16,7 +16,7 @@ pub fn build(b: &Builder) !void {
|
|||||||
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
||||||
|
|
||||||
const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
|
const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
|
||||||
var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8 {
|
var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
|
||||||
docgen_exe.getOutputPath(),
|
docgen_exe.getOutputPath(),
|
||||||
rel_zig_exe,
|
rel_zig_exe,
|
||||||
"doc/langref.html.in",
|
"doc/langref.html.in",
|
||||||
@ -30,7 +30,10 @@ pub fn build(b: &Builder) !void {
|
|||||||
const test_step = b.step("test", "Run all the tests");
|
const test_step = b.step("test", "Run all the tests");
|
||||||
|
|
||||||
// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
|
// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
|
||||||
const build_info = try b.exec([][]const u8{b.zig_exe, "BUILD_INFO"});
|
const build_info = try b.exec([][]const u8{
|
||||||
|
b.zig_exe,
|
||||||
|
"BUILD_INFO",
|
||||||
|
});
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
const cmake_binary_dir = nextValue(&index, build_info);
|
const cmake_binary_dir = nextValue(&index, build_info);
|
||||||
const cxx_compiler = nextValue(&index, build_info);
|
const cxx_compiler = nextValue(&index, build_info);
|
||||||
@ -67,7 +70,10 @@ pub fn build(b: &Builder) !void {
|
|||||||
dependOnLib(exe, llvm);
|
dependOnLib(exe, llvm);
|
||||||
|
|
||||||
if (exe.target.getOs() == builtin.Os.linux) {
|
if (exe.target.getOs() == builtin.Os.linux) {
|
||||||
const libstdcxx_path_padded = try b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"});
|
const libstdcxx_path_padded = try b.exec([][]const u8{
|
||||||
|
cxx_compiler,
|
||||||
|
"-print-file-name=libstdc++.a",
|
||||||
|
});
|
||||||
const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next();
|
const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next();
|
||||||
if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
|
if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
|
||||||
warn(
|
warn(
|
||||||
@ -111,17 +117,11 @@ pub fn build(b: &Builder) !void {
|
|||||||
|
|
||||||
test_step.dependOn(docs_step);
|
test_step.dependOn(docs_step);
|
||||||
|
|
||||||
test_step.dependOn(tests.addPkgTests(b, test_filter,
|
test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", with_lldb));
|
||||||
"test/behavior.zig", "behavior", "Run the behavior tests",
|
|
||||||
with_lldb));
|
|
||||||
|
|
||||||
test_step.dependOn(tests.addPkgTests(b, test_filter,
|
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", with_lldb));
|
||||||
"std/index.zig", "std", "Run the standard library tests",
|
|
||||||
with_lldb));
|
|
||||||
|
|
||||||
test_step.dependOn(tests.addPkgTests(b, test_filter,
|
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/special/compiler_rt/index.zig", "compiler-rt", "Run the compiler_rt tests", with_lldb));
|
||||||
"std/special/compiler_rt/index.zig", "compiler-rt", "Run the compiler_rt tests",
|
|
||||||
with_lldb));
|
|
||||||
|
|
||||||
test_step.dependOn(tests.addCompareOutputTests(b, test_filter));
|
test_step.dependOn(tests.addCompareOutputTests(b, test_filter));
|
||||||
test_step.dependOn(tests.addBuildExampleTests(b, test_filter));
|
test_step.dependOn(tests.addBuildExampleTests(b, test_filter));
|
||||||
@ -149,8 +149,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) vo
|
|||||||
|
|
||||||
fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void {
|
fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void {
|
||||||
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
|
const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
|
||||||
lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp",
|
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);
|
||||||
b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LibraryDep = struct {
|
const LibraryDep = struct {
|
||||||
@ -161,11 +160,21 @@ const LibraryDep = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn findLLVM(b: &Builder, llvm_config_exe: []const u8) !LibraryDep {
|
fn findLLVM(b: &Builder, llvm_config_exe: []const u8) !LibraryDep {
|
||||||
const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"});
|
const libs_output = try b.exec([][]const u8{
|
||||||
const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"});
|
llvm_config_exe,
|
||||||
const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"});
|
"--libs",
|
||||||
|
"--system-libs",
|
||||||
|
});
|
||||||
|
const includes_output = try b.exec([][]const u8{
|
||||||
|
llvm_config_exe,
|
||||||
|
"--includedir",
|
||||||
|
});
|
||||||
|
const libdir_output = try b.exec([][]const u8{
|
||||||
|
llvm_config_exe,
|
||||||
|
"--libdir",
|
||||||
|
});
|
||||||
|
|
||||||
var result = LibraryDep {
|
var result = LibraryDep{
|
||||||
.libs = ArrayList([]const u8).init(b.allocator),
|
.libs = ArrayList([]const u8).init(b.allocator),
|
||||||
.system_libs = ArrayList([]const u8).init(b.allocator),
|
.system_libs = ArrayList([]const u8).init(b.allocator),
|
||||||
.includes = ArrayList([]const u8).init(b.allocator),
|
.includes = ArrayList([]const u8).init(b.allocator),
|
||||||
@ -227,17 +236,17 @@ pub fn installCHeaders(b: &Builder, c_header_files: []const u8) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn nextValue(index: &usize, build_info: []const u8) []const u8 {
|
fn nextValue(index: &usize, build_info: []const u8) []const u8 {
|
||||||
const start = *index;
|
const start = index.*;
|
||||||
while (true) : (*index += 1) {
|
while (true) : (index.* += 1) {
|
||||||
switch (build_info[*index]) {
|
switch (build_info[index.*]) {
|
||||||
'\n' => {
|
'\n' => {
|
||||||
const result = build_info[start..*index];
|
const result = build_info[start..index.*];
|
||||||
*index += 1;
|
index.* += 1;
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
'\r' => {
|
'\r' => {
|
||||||
const result = build_info[start..*index];
|
const result = build_info[start..index.*];
|
||||||
*index += 2;
|
index.* += 2;
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
else => continue,
|
else => continue,
|
||||||
|
@ -1232,7 +1232,7 @@ mem.eql(u8, pattern, "ababab")</code></pre>
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><pre><code class="zig">*a<code></pre></td>
|
<td><pre><code class="zig">a.*<code></pre></td>
|
||||||
<td>
|
<td>
|
||||||
<ul>
|
<ul>
|
||||||
<li>{#link|Pointers#}</li>
|
<li>{#link|Pointers#}</li>
|
||||||
@ -1244,7 +1244,7 @@ mem.eql(u8, pattern, "ababab")</code></pre>
|
|||||||
<td>
|
<td>
|
||||||
<pre><code class="zig">const x: u32 = 1234;
|
<pre><code class="zig">const x: u32 = 1234;
|
||||||
const ptr = &x;
|
const ptr = &x;
|
||||||
*x == 1234</code></pre>
|
x.* == 1234</code></pre>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -1258,7 +1258,7 @@ const ptr = &x;
|
|||||||
<td>
|
<td>
|
||||||
<pre><code class="zig">const x: u32 = 1234;
|
<pre><code class="zig">const x: u32 = 1234;
|
||||||
const ptr = &x;
|
const ptr = &x;
|
||||||
*x == 1234</code></pre>
|
x.* == 1234</code></pre>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -1267,8 +1267,8 @@ const ptr = &x;
|
|||||||
{#header_open|Precedence#}
|
{#header_open|Precedence#}
|
||||||
<pre><code>x() x[] x.y
|
<pre><code>x() x[] x.y
|
||||||
a!b
|
a!b
|
||||||
!x -x -%x ~x *x &x ?x ??x
|
!x -x -%x ~x &x ?x ??x
|
||||||
x{}
|
x{} x.*
|
||||||
! * / % ** *%
|
! * / % ** *%
|
||||||
+ - ++ +% -%
|
+ - ++ +% -%
|
||||||
<< >>
|
<< >>
|
||||||
@ -1316,7 +1316,7 @@ var some_integers: [100]i32 = undefined;
|
|||||||
|
|
||||||
test "modify an array" {
|
test "modify an array" {
|
||||||
for (some_integers) |*item, i| {
|
for (some_integers) |*item, i| {
|
||||||
*item = i32(i);
|
item.* = i32(i);
|
||||||
}
|
}
|
||||||
assert(some_integers[10] == 10);
|
assert(some_integers[10] == 10);
|
||||||
assert(some_integers[99] == 99);
|
assert(some_integers[99] == 99);
|
||||||
@ -1357,7 +1357,7 @@ comptime {
|
|||||||
var fancy_array = init: {
|
var fancy_array = init: {
|
||||||
var initial_value: [10]Point = undefined;
|
var initial_value: [10]Point = undefined;
|
||||||
for (initial_value) |*pt, i| {
|
for (initial_value) |*pt, i| {
|
||||||
*pt = Point {
|
pt.* = Point {
|
||||||
.x = i32(i),
|
.x = i32(i),
|
||||||
.y = i32(i) * 2,
|
.y = i32(i) * 2,
|
||||||
};
|
};
|
||||||
@ -1400,7 +1400,7 @@ test "address of syntax" {
|
|||||||
const x_ptr = &x;
|
const x_ptr = &x;
|
||||||
|
|
||||||
// Deference a pointer:
|
// Deference a pointer:
|
||||||
assert(*x_ptr == 1234);
|
assert(x_ptr.* == 1234);
|
||||||
|
|
||||||
// When you get the address of a const variable, you get a const pointer.
|
// When you get the address of a const variable, you get a const pointer.
|
||||||
assert(@typeOf(x_ptr) == &const i32);
|
assert(@typeOf(x_ptr) == &const i32);
|
||||||
@ -1409,8 +1409,8 @@ test "address of syntax" {
|
|||||||
var y: i32 = 5678;
|
var y: i32 = 5678;
|
||||||
const y_ptr = &y;
|
const y_ptr = &y;
|
||||||
assert(@typeOf(y_ptr) == &i32);
|
assert(@typeOf(y_ptr) == &i32);
|
||||||
*y_ptr += 1;
|
y_ptr.* += 1;
|
||||||
assert(*y_ptr == 5679);
|
assert(y_ptr.* == 5679);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "pointer array access" {
|
test "pointer array access" {
|
||||||
@ -1448,9 +1448,9 @@ comptime {
|
|||||||
// @ptrCast.
|
// @ptrCast.
|
||||||
var x: i32 = 1;
|
var x: i32 = 1;
|
||||||
const ptr = &x;
|
const ptr = &x;
|
||||||
*ptr += 1;
|
ptr.* += 1;
|
||||||
x += 1;
|
x += 1;
|
||||||
assert(*ptr == 3);
|
assert(ptr.* == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "@ptrToInt and @intToPtr" {
|
test "@ptrToInt and @intToPtr" {
|
||||||
@ -1492,7 +1492,7 @@ test "nullable pointers" {
|
|||||||
var x: i32 = 1;
|
var x: i32 = 1;
|
||||||
ptr = &x;
|
ptr = &x;
|
||||||
|
|
||||||
assert(*??ptr == 1);
|
assert((??ptr).* == 1);
|
||||||
|
|
||||||
// Nullable pointers are the same size as normal pointers, because pointer
|
// Nullable pointers are the same size as normal pointers, because pointer
|
||||||
// value 0 is used as the null value.
|
// value 0 is used as the null value.
|
||||||
@ -1505,7 +1505,7 @@ test "pointer casting" {
|
|||||||
// conversions are not possible.
|
// conversions are not possible.
|
||||||
const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12};
|
const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12};
|
||||||
const u32_ptr = @ptrCast(&const u32, &bytes[0]);
|
const u32_ptr = @ptrCast(&const u32, &bytes[0]);
|
||||||
assert(*u32_ptr == 0x12121212);
|
assert(u32_ptr.* == 0x12121212);
|
||||||
|
|
||||||
// Even this example is contrived - there are better ways to do the above than
|
// Even this example is contrived - there are better ways to do the above than
|
||||||
// pointer casting. For example, using a slice narrowing cast:
|
// pointer casting. For example, using a slice narrowing cast:
|
||||||
@ -1610,7 +1610,7 @@ fn foo(bytes: []u8) u32 {
|
|||||||
<code>u8</code> can alias any memory.
|
<code>u8</code> can alias any memory.
|
||||||
</p>
|
</p>
|
||||||
<p>As an example, this code produces undefined behavior:</p>
|
<p>As an example, this code produces undefined behavior:</p>
|
||||||
<pre><code class="zig">*@ptrCast(&u32, f32(12.34))</code></pre>
|
<pre><code class="zig">@ptrCast(&u32, f32(12.34)).*</code></pre>
|
||||||
<p>Instead, use {#link|@bitCast#}:
|
<p>Instead, use {#link|@bitCast#}:
|
||||||
<pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
|
<pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre>
|
||||||
<p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>
|
<p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p>
|
||||||
@ -2040,7 +2040,7 @@ const Variant = union(enum) {
|
|||||||
Bool: bool,
|
Bool: bool,
|
||||||
|
|
||||||
fn truthy(self: &const Variant) bool {
|
fn truthy(self: &const Variant) bool {
|
||||||
return switch (*self) {
|
return switch (self.*) {
|
||||||
Variant.Int => |x_int| x_int != 0,
|
Variant.Int => |x_int| x_int != 0,
|
||||||
Variant.Bool => |x_bool| x_bool,
|
Variant.Bool => |x_bool| x_bool,
|
||||||
};
|
};
|
||||||
@ -2151,7 +2151,7 @@ test "switch enum" {
|
|||||||
|
|
||||||
// A reference to the matched value can be obtained using `*` syntax.
|
// A reference to the matched value can be obtained using `*` syntax.
|
||||||
Item.C => |*item| blk: {
|
Item.C => |*item| blk: {
|
||||||
(*item).x += 1;
|
item.*.x += 1;
|
||||||
break :blk 6;
|
break :blk 6;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2374,7 +2374,7 @@ test "for reference" {
|
|||||||
// Iterate over the slice by reference by
|
// Iterate over the slice by reference by
|
||||||
// specifying that the capture value is a pointer.
|
// specifying that the capture value is a pointer.
|
||||||
for (items) |*value| {
|
for (items) |*value| {
|
||||||
*value += 1;
|
value.* += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(items[0] == 4);
|
assert(items[0] == 4);
|
||||||
@ -2483,7 +2483,7 @@ test "if nullable" {
|
|||||||
// Access the value by reference using a pointer capture.
|
// Access the value by reference using a pointer capture.
|
||||||
var c: ?u32 = 3;
|
var c: ?u32 = 3;
|
||||||
if (c) |*value| {
|
if (c) |*value| {
|
||||||
*value = 2;
|
value.* = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c) |value| {
|
if (c) |value| {
|
||||||
@ -2524,7 +2524,7 @@ test "if error union" {
|
|||||||
// Access the value by reference using a pointer capture.
|
// Access the value by reference using a pointer capture.
|
||||||
var c: error!u32 = 3;
|
var c: error!u32 = 3;
|
||||||
if (c) |*value| {
|
if (c) |*value| {
|
||||||
*value = 9;
|
value.* = 9;
|
||||||
} else |err| {
|
} else |err| {
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
@ -3872,7 +3872,7 @@ pub fn main() void {
|
|||||||
{#header_open|@addWithOverflow#}
|
{#header_open|@addWithOverflow#}
|
||||||
<pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool</code></pre>
|
<pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool</code></pre>
|
||||||
<p>
|
<p>
|
||||||
Performs <code>*result = a + b</code>. If overflow or underflow occurs,
|
Performs <code>result.* = a + b</code>. If overflow or underflow occurs,
|
||||||
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
||||||
If no overflow or underflow occurs, returns <code>false</code>.
|
If no overflow or underflow occurs, returns <code>false</code>.
|
||||||
</p>
|
</p>
|
||||||
@ -4073,9 +4073,9 @@ comptime {
|
|||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T {
|
fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T {
|
||||||
const old_value = *ptr;
|
const old_value = ptr.*;
|
||||||
if (old_value == expected_value) {
|
if (old_value == expected_value) {
|
||||||
*ptr = new_value;
|
ptr.* = new_value;
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return old_value;
|
return old_value;
|
||||||
@ -4100,9 +4100,9 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_v
|
|||||||
</p>
|
</p>
|
||||||
{#code_begin|syntax#}
|
{#code_begin|syntax#}
|
||||||
fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T {
|
fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: &T, expected_value: T, new_value: T) ?T {
|
||||||
const old_value = *ptr;
|
const old_value = ptr.*;
|
||||||
if (old_value == expected_value and usuallyTrueButSometimesFalse()) {
|
if (old_value == expected_value and usuallyTrueButSometimesFalse()) {
|
||||||
*ptr = new_value;
|
ptr.* = new_value;
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return old_value;
|
return old_value;
|
||||||
@ -4447,7 +4447,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre>
|
|||||||
This function is a low level intrinsic with no safety mechanisms. Most
|
This function is a low level intrinsic with no safety mechanisms. Most
|
||||||
code should not use this function, instead using something like this:
|
code should not use this function, instead using something like this:
|
||||||
</p>
|
</p>
|
||||||
<pre><code class="zig">for (dest[0...byte_count]) |*b| *b = c;</code></pre>
|
<pre><code class="zig">for (dest[0...byte_count]) |*b| b.* = c;</code></pre>
|
||||||
<p>
|
<p>
|
||||||
The optimizer is intelligent enough to turn the above snippet into a memset.
|
The optimizer is intelligent enough to turn the above snippet into a memset.
|
||||||
</p>
|
</p>
|
||||||
@ -4480,7 +4480,7 @@ mem.set(u8, dest, c);</code></pre>
|
|||||||
{#header_open|@mulWithOverflow#}
|
{#header_open|@mulWithOverflow#}
|
||||||
<pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool</code></pre>
|
<pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool</code></pre>
|
||||||
<p>
|
<p>
|
||||||
Performs <code>*result = a * b</code>. If overflow or underflow occurs,
|
Performs <code>result.* = a * b</code>. If overflow or underflow occurs,
|
||||||
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
||||||
If no overflow or underflow occurs, returns <code>false</code>.
|
If no overflow or underflow occurs, returns <code>false</code>.
|
||||||
</p>
|
</p>
|
||||||
@ -4514,7 +4514,7 @@ fn targetFunction(x: i32) usize {
|
|||||||
|
|
||||||
var local_variable: i32 = 42;
|
var local_variable: i32 = 42;
|
||||||
const ptr = &local_variable;
|
const ptr = &local_variable;
|
||||||
*ptr += 1;
|
ptr.* += 1;
|
||||||
|
|
||||||
assert(local_variable == 43);
|
assert(local_variable == 43);
|
||||||
return @ptrToInt(ptr);
|
return @ptrToInt(ptr);
|
||||||
@ -4746,7 +4746,7 @@ pub const FloatMode = enum {
|
|||||||
{#header_open|@shlWithOverflow#}
|
{#header_open|@shlWithOverflow#}
|
||||||
<pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -> bool</code></pre>
|
<pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -> bool</code></pre>
|
||||||
<p>
|
<p>
|
||||||
Performs <code>*result = a << b</code>. If overflow or underflow occurs,
|
Performs <code>result.* = a << b</code>. If overflow or underflow occurs,
|
||||||
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
||||||
If no overflow or underflow occurs, returns <code>false</code>.
|
If no overflow or underflow occurs, returns <code>false</code>.
|
||||||
</p>
|
</p>
|
||||||
@ -4790,7 +4790,7 @@ pub const FloatMode = enum {
|
|||||||
{#header_open|@subWithOverflow#}
|
{#header_open|@subWithOverflow#}
|
||||||
<pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool</code></pre>
|
<pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &T) -> bool</code></pre>
|
||||||
<p>
|
<p>
|
||||||
Performs <code>*result = a - b</code>. If overflow or underflow occurs,
|
Performs <code>result.* = a - b</code>. If overflow or underflow occurs,
|
||||||
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
stores the overflowed bits in <code>result</code> and returns <code>true</code>.
|
||||||
If no overflow or underflow occurs, returns <code>false</code>.
|
If no overflow or underflow occurs, returns <code>false</code>.
|
||||||
</p>
|
</p>
|
||||||
|
@ -30,24 +30,22 @@ fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Modifies the current argument index during iteration
|
// Modifies the current argument index during iteration
|
||||||
fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize,
|
fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: &usize) !FlagArg {
|
||||||
allowed_set: ?[]const []const u8, index: &usize) !FlagArg {
|
|
||||||
|
|
||||||
switch (required) {
|
switch (required) {
|
||||||
0 => return FlagArg { .None = undefined }, // TODO: Required to force non-tag but value?
|
0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value?
|
||||||
1 => {
|
1 => {
|
||||||
if (*index + 1 >= args.len) {
|
if (index.* + 1 >= args.len) {
|
||||||
return error.MissingFlagArguments;
|
return error.MissingFlagArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
*index += 1;
|
index.* += 1;
|
||||||
const arg = args[*index];
|
const arg = args[index.*];
|
||||||
|
|
||||||
if (!argInAllowedSet(allowed_set, arg)) {
|
if (!argInAllowedSet(allowed_set, arg)) {
|
||||||
return error.ArgumentNotInAllowedSet;
|
return error.ArgumentNotInAllowedSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FlagArg { .Single = arg };
|
return FlagArg{ .Single = arg };
|
||||||
},
|
},
|
||||||
else => |needed| {
|
else => |needed| {
|
||||||
var extra = ArrayList([]const u8).init(allocator);
|
var extra = ArrayList([]const u8).init(allocator);
|
||||||
@ -55,12 +53,12 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required:
|
|||||||
|
|
||||||
var j: usize = 0;
|
var j: usize = 0;
|
||||||
while (j < needed) : (j += 1) {
|
while (j < needed) : (j += 1) {
|
||||||
if (*index + 1 >= args.len) {
|
if (index.* + 1 >= args.len) {
|
||||||
return error.MissingFlagArguments;
|
return error.MissingFlagArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
*index += 1;
|
index.* += 1;
|
||||||
const arg = args[*index];
|
const arg = args[index.*];
|
||||||
|
|
||||||
if (!argInAllowedSet(allowed_set, arg)) {
|
if (!argInAllowedSet(allowed_set, arg)) {
|
||||||
return error.ArgumentNotInAllowedSet;
|
return error.ArgumentNotInAllowedSet;
|
||||||
@ -69,7 +67,7 @@ fn readFlagArguments(allocator: &Allocator, args: []const []const u8, required:
|
|||||||
try extra.append(arg);
|
try extra.append(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FlagArg { .Many = extra };
|
return FlagArg{ .Many = extra };
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +80,7 @@ pub const Args = struct {
|
|||||||
positionals: ArrayList([]const u8),
|
positionals: ArrayList([]const u8),
|
||||||
|
|
||||||
pub fn parse(allocator: &Allocator, comptime spec: []const Flag, args: []const []const u8) !Args {
|
pub fn parse(allocator: &Allocator, comptime spec: []const Flag, args: []const []const u8) !Args {
|
||||||
var parsed = Args {
|
var parsed = Args{
|
||||||
.flags = HashMapFlags.init(allocator),
|
.flags = HashMapFlags.init(allocator),
|
||||||
.positionals = ArrayList([]const u8).init(allocator),
|
.positionals = ArrayList([]const u8).init(allocator),
|
||||||
};
|
};
|
||||||
@ -116,11 +114,7 @@ pub const Args = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (flag.mergable) {
|
if (flag.mergable) {
|
||||||
var prev =
|
var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator);
|
||||||
if (parsed.flags.get(flag_name_trimmed)) |entry|
|
|
||||||
entry.value.Many
|
|
||||||
else
|
|
||||||
ArrayList([]const u8).init(allocator);
|
|
||||||
|
|
||||||
// MergeN creation disallows 0 length flag entry (doesn't make sense)
|
// MergeN creation disallows 0 length flag entry (doesn't make sense)
|
||||||
switch (flag_args) {
|
switch (flag_args) {
|
||||||
@ -129,7 +123,7 @@ pub const Args = struct {
|
|||||||
FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()),
|
FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()),
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = try parsed.flags.put(flag_name_trimmed, FlagArg { .Many = prev });
|
_ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
|
||||||
} else {
|
} else {
|
||||||
_ = try parsed.flags.put(flag_name_trimmed, flag_args);
|
_ = try parsed.flags.put(flag_name_trimmed, flag_args);
|
||||||
}
|
}
|
||||||
@ -163,7 +157,9 @@ pub const Args = struct {
|
|||||||
pub fn single(self: &Args, name: []const u8) ?[]const u8 {
|
pub fn single(self: &Args, name: []const u8) ?[]const u8 {
|
||||||
if (self.flags.get(name)) |entry| {
|
if (self.flags.get(name)) |entry| {
|
||||||
switch (entry.value) {
|
switch (entry.value) {
|
||||||
FlagArg.Single => |inner| { return inner; },
|
FlagArg.Single => |inner| {
|
||||||
|
return inner;
|
||||||
|
},
|
||||||
else => @panic("attempted to retrieve flag with wrong type"),
|
else => @panic("attempted to retrieve flag with wrong type"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -175,7 +171,9 @@ pub const Args = struct {
|
|||||||
pub fn many(self: &Args, name: []const u8) ?[]const []const u8 {
|
pub fn many(self: &Args, name: []const u8) ?[]const []const u8 {
|
||||||
if (self.flags.get(name)) |entry| {
|
if (self.flags.get(name)) |entry| {
|
||||||
switch (entry.value) {
|
switch (entry.value) {
|
||||||
FlagArg.Many => |inner| { return inner.toSliceConst(); },
|
FlagArg.Many => |inner| {
|
||||||
|
return inner.toSliceConst();
|
||||||
|
},
|
||||||
else => @panic("attempted to retrieve flag with wrong type"),
|
else => @panic("attempted to retrieve flag with wrong type"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -207,7 +205,7 @@ pub const Flag = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag {
|
pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag {
|
||||||
return Flag {
|
return Flag{
|
||||||
.name = name,
|
.name = name,
|
||||||
.required = n,
|
.required = n,
|
||||||
.mergable = false,
|
.mergable = false,
|
||||||
@ -220,7 +218,7 @@ pub const Flag = struct {
|
|||||||
@compileError("n must be greater than 0");
|
@compileError("n must be greater than 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Flag {
|
return Flag{
|
||||||
.name = name,
|
.name = name,
|
||||||
.required = n,
|
.required = n,
|
||||||
.mergable = true,
|
.mergable = true,
|
||||||
@ -229,7 +227,7 @@ pub const Flag = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag {
|
pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag {
|
||||||
return Flag {
|
return Flag{
|
||||||
.name = name,
|
.name = name,
|
||||||
.required = 1,
|
.required = 1,
|
||||||
.mergable = false,
|
.mergable = false,
|
||||||
@ -239,26 +237,36 @@ pub const Flag = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
test "parse arguments" {
|
test "parse arguments" {
|
||||||
const spec1 = comptime []const Flag {
|
const spec1 = comptime []const Flag{
|
||||||
Flag.Bool("--help"),
|
Flag.Bool("--help"),
|
||||||
Flag.Bool("--init"),
|
Flag.Bool("--init"),
|
||||||
Flag.Arg1("--build-file"),
|
Flag.Arg1("--build-file"),
|
||||||
Flag.Option("--color", []const []const u8 { "on", "off", "auto" }),
|
Flag.Option("--color", []const []const u8{
|
||||||
|
"on",
|
||||||
|
"off",
|
||||||
|
"auto",
|
||||||
|
}),
|
||||||
Flag.ArgN("--pkg-begin", 2),
|
Flag.ArgN("--pkg-begin", 2),
|
||||||
Flag.ArgMergeN("--object", 1),
|
Flag.ArgMergeN("--object", 1),
|
||||||
Flag.ArgN("--library", 1),
|
Flag.ArgN("--library", 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
const cliargs = []const []const u8 {
|
const cliargs = []const []const u8{
|
||||||
"build",
|
"build",
|
||||||
"--help",
|
"--help",
|
||||||
"pos1",
|
"pos1",
|
||||||
"--build-file", "build.zig",
|
"--build-file",
|
||||||
"--object", "obj1",
|
"build.zig",
|
||||||
"--object", "obj2",
|
"--object",
|
||||||
"--library", "lib1",
|
"obj1",
|
||||||
"--library", "lib2",
|
"--object",
|
||||||
"--color", "on",
|
"obj2",
|
||||||
|
"--library",
|
||||||
|
"lib1",
|
||||||
|
"--library",
|
||||||
|
"lib2",
|
||||||
|
"--color",
|
||||||
|
"on",
|
||||||
"pos2",
|
"pos2",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ pub const Module = struct {
|
|||||||
pub const LinkLib = struct {
|
pub const LinkLib = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
path: ?[]const u8,
|
path: ?[]const u8,
|
||||||
|
|
||||||
/// the list of symbols we depend on from this lib
|
/// the list of symbols we depend on from this lib
|
||||||
symbols: ArrayList([]u8),
|
symbols: ArrayList([]u8),
|
||||||
provided_explicitly: bool,
|
provided_explicitly: bool,
|
||||||
@ -130,9 +131,7 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target,
|
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 {
|
||||||
kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) !&Module
|
|
||||||
{
|
|
||||||
var name_buffer = try Buffer.init(allocator, name);
|
var name_buffer = try Buffer.init(allocator, name);
|
||||||
errdefer name_buffer.deinit();
|
errdefer name_buffer.deinit();
|
||||||
|
|
||||||
@ -148,14 +147,14 @@ pub const Module = struct {
|
|||||||
const module_ptr = try allocator.create(Module);
|
const module_ptr = try allocator.create(Module);
|
||||||
errdefer allocator.destroy(module_ptr);
|
errdefer allocator.destroy(module_ptr);
|
||||||
|
|
||||||
*module_ptr = Module {
|
module_ptr.* = Module{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.name = name_buffer,
|
.name = name_buffer,
|
||||||
.root_src_path = root_src_path,
|
.root_src_path = root_src_path,
|
||||||
.module = module,
|
.module = module,
|
||||||
.context = context,
|
.context = context,
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.target = *target,
|
.target = target.*,
|
||||||
.kind = kind,
|
.kind = kind,
|
||||||
.build_mode = build_mode,
|
.build_mode = build_mode,
|
||||||
.zig_lib_dir = zig_lib_dir,
|
.zig_lib_dir = zig_lib_dir,
|
||||||
@ -221,8 +220,10 @@ pub const Module = struct {
|
|||||||
|
|
||||||
pub fn build(self: &Module) !void {
|
pub fn build(self: &Module) !void {
|
||||||
if (self.llvm_argv.len != 0) {
|
if (self.llvm_argv.len != 0) {
|
||||||
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator,
|
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator, [][]const []const u8{
|
||||||
[][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, });
|
[][]const u8{"zig (LLVM option parsing)"},
|
||||||
|
self.llvm_argv,
|
||||||
|
});
|
||||||
defer c_compatible_args.deinit();
|
defer c_compatible_args.deinit();
|
||||||
c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
|
c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
|
||||||
}
|
}
|
||||||
@ -261,7 +262,6 @@ pub const Module = struct {
|
|||||||
|
|
||||||
warn("====llvm ir:====\n");
|
warn("====llvm ir:====\n");
|
||||||
self.dump();
|
self.dump();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link(self: &Module, out_file: ?[]const u8) !void {
|
pub fn link(self: &Module, out_file: ?[]const u8) !void {
|
||||||
@ -285,7 +285,7 @@ pub const Module = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const link_lib = try self.allocator.create(LinkLib);
|
const link_lib = try self.allocator.create(LinkLib);
|
||||||
*link_lib = LinkLib {
|
link_lib.* = LinkLib{
|
||||||
.name = name,
|
.name = name,
|
||||||
.path = null,
|
.path = null,
|
||||||
.provided_explicitly = provided_explicitly,
|
.provided_explicitly = provided_explicitly,
|
||||||
|
@ -12,7 +12,7 @@ pub const Target = union(enum) {
|
|||||||
Cross: CrossTarget,
|
Cross: CrossTarget,
|
||||||
|
|
||||||
pub fn oFileExt(self: &const Target) []const u8 {
|
pub fn oFileExt(self: &const Target) []const u8 {
|
||||||
const environ = switch (*self) {
|
const environ = switch (self.*) {
|
||||||
Target.Native => builtin.environ,
|
Target.Native => builtin.environ,
|
||||||
Target.Cross => |t| t.environ,
|
Target.Cross => |t| t.environ,
|
||||||
};
|
};
|
||||||
@ -30,7 +30,7 @@ pub const Target = union(enum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getOs(self: &const Target) builtin.Os {
|
pub fn getOs(self: &const Target) builtin.Os {
|
||||||
return switch (*self) {
|
return switch (self.*) {
|
||||||
Target.Native => builtin.os,
|
Target.Native => builtin.os,
|
||||||
Target.Cross => |t| t.os,
|
Target.Cross => |t| t.os,
|
||||||
};
|
};
|
||||||
@ -38,7 +38,8 @@ pub const Target = union(enum) {
|
|||||||
|
|
||||||
pub fn isDarwin(self: &const Target) bool {
|
pub fn isDarwin(self: &const Target) bool {
|
||||||
return switch (self.getOs()) {
|
return switch (self.getOs()) {
|
||||||
builtin.Os.ios, builtin.Os.macosx => true,
|
builtin.Os.ios,
|
||||||
|
builtin.Os.macosx => true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1485,6 +1485,7 @@ pub const Node = struct {
|
|||||||
BitNot,
|
BitNot,
|
||||||
BoolNot,
|
BoolNot,
|
||||||
Cancel,
|
Cancel,
|
||||||
|
PointerType,
|
||||||
MaybeType,
|
MaybeType,
|
||||||
Negation,
|
Negation,
|
||||||
NegationWrap,
|
NegationWrap,
|
||||||
|
@ -3134,7 +3134,7 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
|
|||||||
Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
|
Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
|
||||||
Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
|
Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
|
||||||
Token.Id.Asterisk,
|
Token.Id.Asterisk,
|
||||||
Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .Deref = void{} },
|
Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op{ .PointerType = void{} },
|
||||||
Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{
|
Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddrOf = ast.Node.PrefixOp.AddrOfInfo{
|
||||||
.align_expr = null,
|
.align_expr = null,
|
||||||
.bit_offset_start_token = null,
|
.bit_offset_start_token = null,
|
||||||
|
@ -311,6 +311,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
|
|||||||
ast.Node.PrefixOp.Op.Try => try stream.write("try "),
|
ast.Node.PrefixOp.Op.Try => try stream.write("try "),
|
||||||
ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"),
|
ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"),
|
||||||
ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"),
|
ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"),
|
||||||
|
ast.Node.PrefixOp.Op.PointerType => try stream.write("*"),
|
||||||
ast.Node.PrefixOp.Op.Await => try stream.write("await "),
|
ast.Node.PrefixOp.Op.Await => try stream.write("await "),
|
||||||
ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "),
|
ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "),
|
||||||
ast.Node.PrefixOp.Op.Resume => try stream.write("resume "),
|
ast.Node.PrefixOp.Op.Resume => try stream.write("resume "),
|
||||||
@ -350,7 +351,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
|
|||||||
try stream.write("]");
|
try stream.write("]");
|
||||||
},
|
},
|
||||||
|
|
||||||
ast.Node.SuffixOp.Op.SuffixOp => {
|
ast.Node.SuffixOp.Op.Deref => {
|
||||||
try renderExpression(allocator, stream, tree, indent, suffix_op.lhs);
|
try renderExpression(allocator, stream, tree, indent, suffix_op.lhs);
|
||||||
try stream.write(".*");
|
try stream.write(".*");
|
||||||
},
|
},
|
||||||
|
@ -287,9 +287,9 @@ pub fn addCases(cases: &tests.CompareOutputContext) void {
|
|||||||
\\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int {
|
\\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int {
|
||||||
\\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable);
|
\\ const a_int = @ptrCast(&align(1) const i32, a ?? unreachable);
|
||||||
\\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable);
|
\\ const b_int = @ptrCast(&align(1) const i32, b ?? unreachable);
|
||||||
\\ if (*a_int < *b_int) {
|
\\ if (a_int.* < b_int.*) {
|
||||||
\\ return -1;
|
\\ return -1;
|
||||||
\\ } else if (*a_int > *b_int) {
|
\\ } else if (a_int.* > b_int.*) {
|
||||||
\\ return 1;
|
\\ return 1;
|
||||||
\\ } else {
|
\\ } else {
|
||||||
\\ return 0;
|
\\ return 0;
|
||||||
|
@ -4,7 +4,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
cases.add("invalid deref on switch target",
|
cases.add("invalid deref on switch target",
|
||||||
\\comptime {
|
\\comptime {
|
||||||
\\ var tile = Tile.Empty;
|
\\ var tile = Tile.Empty;
|
||||||
\\ switch (*tile) {
|
\\ switch (tile.*) {
|
||||||
\\ Tile.Empty => {},
|
\\ Tile.Empty => {},
|
||||||
\\ Tile.Filled => {},
|
\\ Tile.Filled => {},
|
||||||
\\ }
|
\\ }
|
||||||
@ -14,7 +14,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\ Filled,
|
\\ Filled,
|
||||||
\\};
|
\\};
|
||||||
,
|
,
|
||||||
".tmp_source.zig:3:13: error: invalid deref on switch target");
|
".tmp_source.zig:3:17: error: invalid deref on switch target");
|
||||||
|
|
||||||
cases.add("invalid field access in comptime",
|
cases.add("invalid field access in comptime",
|
||||||
\\comptime { var x = doesnt_exist.whatever; }
|
\\comptime { var x = doesnt_exist.whatever; }
|
||||||
@ -1408,14 +1408,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\ Two: i32,
|
\\ Two: i32,
|
||||||
\\};
|
\\};
|
||||||
\\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool {
|
\\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool {
|
||||||
\\ return *a == *b;
|
\\ return a.* == b.*;
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
\\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); }
|
\\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); }
|
||||||
\\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); }
|
\\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); }
|
||||||
,
|
,
|
||||||
".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'",
|
".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'",
|
||||||
".tmp_source.zig:9:15: error: operator not allowed for type 'EnumWithData'");
|
".tmp_source.zig:9:16: error: operator not allowed for type 'EnumWithData'");
|
||||||
|
|
||||||
cases.add("non-const switch number literal",
|
cases.add("non-const switch number literal",
|
||||||
\\export fn foo() void {
|
\\export fn foo() void {
|
||||||
@ -1513,7 +1513,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\var bytes: [ext()]u8 = undefined;
|
\\var bytes: [ext()]u8 = undefined;
|
||||||
\\export fn f() void {
|
\\export fn f() void {
|
||||||
\\ for (bytes) |*b, i| {
|
\\ for (bytes) |*b, i| {
|
||||||
\\ *b = u8(i);
|
\\ b.* = u8(i);
|
||||||
\\ }
|
\\ }
|
||||||
\\}
|
\\}
|
||||||
, ".tmp_source.zig:2:13: error: unable to evaluate constant expression");
|
, ".tmp_source.zig:2:13: error: unable to evaluate constant expression");
|
||||||
@ -1819,7 +1819,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
\\fn bar(x: &const u3) u3 {
|
\\fn bar(x: &const u3) u3 {
|
||||||
\\ return *x;
|
\\ return x.*;
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
|
\\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
|
||||||
@ -1903,12 +1903,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\var s_buffer: [10]u8 = undefined;
|
\\var s_buffer: [10]u8 = undefined;
|
||||||
\\pub fn pass(in: []u8) []u8 {
|
\\pub fn pass(in: []u8) []u8 {
|
||||||
\\ var out = &s_buffer;
|
\\ var out = &s_buffer;
|
||||||
\\ *out[0] = in[0];
|
\\ out[0].* = in[0];
|
||||||
\\ return (*out)[0..1];
|
\\ return out.*[0..1];
|
||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
\\export fn entry() usize { return @sizeOf(@typeOf(pass)); }
|
\\export fn entry() usize { return @sizeOf(@typeOf(pass)); }
|
||||||
, ".tmp_source.zig:4:5: error: attempt to dereference non pointer type '[10]u8'");
|
, ".tmp_source.zig:4:11: error: attempt to dereference non pointer type '[10]u8'");
|
||||||
|
|
||||||
cases.add("pass const ptr to mutable ptr fn",
|
cases.add("pass const ptr to mutable ptr fn",
|
||||||
\\fn foo() bool {
|
\\fn foo() bool {
|
||||||
@ -2434,7 +2434,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\}
|
\\}
|
||||||
\\
|
\\
|
||||||
\\fn bar(x: &u32) void {
|
\\fn bar(x: &u32) void {
|
||||||
\\ *x += 1;
|
\\ x.* += 1;
|
||||||
\\}
|
\\}
|
||||||
,
|
,
|
||||||
".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'");
|
".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'");
|
||||||
@ -2461,7 +2461,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\export fn entry() u32 {
|
\\export fn entry() u32 {
|
||||||
\\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04};
|
\\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04};
|
||||||
\\ const ptr = @ptrCast(&u32, &bytes[0]);
|
\\ const ptr = @ptrCast(&u32, &bytes[0]);
|
||||||
\\ return *ptr;
|
\\ return ptr.*;
|
||||||
\\}
|
\\}
|
||||||
,
|
,
|
||||||
".tmp_source.zig:3:17: error: cast increases pointer alignment",
|
".tmp_source.zig:3:17: error: cast increases pointer alignment",
|
||||||
@ -2540,14 +2540,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\
|
\\
|
||||||
\\export fn entry(opaque: &Opaque) void {
|
\\export fn entry(opaque: &Opaque) void {
|
||||||
\\ var m2 = &2;
|
\\ var m2 = &2;
|
||||||
\\ const y: u32 = *m2;
|
\\ const y: u32 = m2.*;
|
||||||
\\
|
\\
|
||||||
\\ var a = undefined;
|
\\ var a = undefined;
|
||||||
\\ var b = 1;
|
\\ var b = 1;
|
||||||
\\ var c = 1.0;
|
\\ var c = 1.0;
|
||||||
\\ var d = this;
|
\\ var d = this;
|
||||||
\\ var e = null;
|
\\ var e = null;
|
||||||
\\ var f = *opaque;
|
\\ var f = opaque.*;
|
||||||
\\ var g = i32;
|
\\ var g = i32;
|
||||||
\\ var h = @import("std");
|
\\ var h = @import("std");
|
||||||
\\ var i = (Foo {}).bar;
|
\\ var i = (Foo {}).bar;
|
||||||
@ -3136,13 +3136,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
|
|||||||
\\ foo(a);
|
\\ foo(a);
|
||||||
\\}
|
\\}
|
||||||
\\fn foo(a: &const Payload) void {
|
\\fn foo(a: &const Payload) void {
|
||||||
\\ switch (*a) {
|
\\ switch (a.*) {
|
||||||
\\ Payload.A => {},
|
\\ Payload.A => {},
|
||||||
\\ else => unreachable,
|
\\ else => unreachable,
|
||||||
\\ }
|
\\ }
|
||||||
\\}
|
\\}
|
||||||
,
|
,
|
||||||
".tmp_source.zig:11:13: error: switch on union which has no attached enum",
|
".tmp_source.zig:11:14: error: switch on union which has no attached enum",
|
||||||
".tmp_source.zig:1:17: note: consider 'union(enum)' here");
|
".tmp_source.zig:1:17: note: consider 'union(enum)' here");
|
||||||
|
|
||||||
cases.add("enum in field count range but not matching tag",
|
cases.add("enum in field count range but not matching tag",
|
||||||
|
@ -16,7 +16,7 @@ const Token = union(enum) {
|
|||||||
|
|
||||||
var global_allocator: &mem.Allocator = undefined;
|
var global_allocator: &mem.Allocator = undefined;
|
||||||
|
|
||||||
fn tokenize(input:[] const u8) !ArrayList(Token) {
|
fn tokenize(input: []const u8) !ArrayList(Token) {
|
||||||
const State = enum {
|
const State = enum {
|
||||||
Start,
|
Start,
|
||||||
Word,
|
Word,
|
||||||
@ -29,7 +29,8 @@ fn tokenize(input:[] const u8) !ArrayList(Token) {
|
|||||||
for (input) |b, i| {
|
for (input) |b, i| {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
State.Start => switch (b) {
|
State.Start => switch (b) {
|
||||||
'a'...'z', 'A'...'Z' => {
|
'a' ... 'z',
|
||||||
|
'A' ... 'Z' => {
|
||||||
state = State.Word;
|
state = State.Word;
|
||||||
tok_begin = i;
|
tok_begin = i;
|
||||||
},
|
},
|
||||||
@ -39,9 +40,12 @@ fn tokenize(input:[] const u8) !ArrayList(Token) {
|
|||||||
else => return error.InvalidInput,
|
else => return error.InvalidInput,
|
||||||
},
|
},
|
||||||
State.Word => switch (b) {
|
State.Word => switch (b) {
|
||||||
'a'...'z', 'A'...'Z' => {},
|
'a' ... 'z',
|
||||||
'{', '}', ',' => {
|
'A' ... 'Z' => {},
|
||||||
try token_list.append(Token { .Word = input[tok_begin..i] });
|
'{',
|
||||||
|
'}',
|
||||||
|
',' => {
|
||||||
|
try token_list.append(Token{ .Word = input[tok_begin..i] });
|
||||||
switch (b) {
|
switch (b) {
|
||||||
'{' => try token_list.append(Token.OpenBrace),
|
'{' => try token_list.append(Token.OpenBrace),
|
||||||
'}' => try token_list.append(Token.CloseBrace),
|
'}' => try token_list.append(Token.CloseBrace),
|
||||||
@ -56,7 +60,7 @@ fn tokenize(input:[] const u8) !ArrayList(Token) {
|
|||||||
}
|
}
|
||||||
switch (state) {
|
switch (state) {
|
||||||
State.Start => {},
|
State.Start => {},
|
||||||
State.Word => try token_list.append(Token {.Word = input[tok_begin..] }),
|
State.Word => try token_list.append(Token{ .Word = input[tok_begin..] }),
|
||||||
}
|
}
|
||||||
try token_list.append(Token.Eof);
|
try token_list.append(Token.Eof);
|
||||||
return token_list;
|
return token_list;
|
||||||
@ -68,24 +72,24 @@ const Node = union(enum) {
|
|||||||
Combine: []Node,
|
Combine: []Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ParseError = error {
|
const ParseError = error{
|
||||||
InvalidInput,
|
InvalidInput,
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node {
|
fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node {
|
||||||
const first_token = tokens.items[*token_index];
|
const first_token = tokens.items[token_index.*];
|
||||||
*token_index += 1;
|
token_index.* += 1;
|
||||||
|
|
||||||
const result_node = switch (first_token) {
|
const result_node = switch (first_token) {
|
||||||
Token.Word => |word| Node { .Scalar = word },
|
Token.Word => |word| Node{ .Scalar = word },
|
||||||
Token.OpenBrace => blk: {
|
Token.OpenBrace => blk: {
|
||||||
var list = ArrayList(Node).init(global_allocator);
|
var list = ArrayList(Node).init(global_allocator);
|
||||||
while (true) {
|
while (true) {
|
||||||
try list.append(try parse(tokens, token_index));
|
try list.append(try parse(tokens, token_index));
|
||||||
|
|
||||||
const token = tokens.items[*token_index];
|
const token = tokens.items[token_index.*];
|
||||||
*token_index += 1;
|
token_index.* += 1;
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
Token.CloseBrace => break,
|
Token.CloseBrace => break,
|
||||||
@ -93,17 +97,18 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) ParseError!Node {
|
|||||||
else => return error.InvalidInput,
|
else => return error.InvalidInput,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break :blk Node { .List = list };
|
break :blk Node{ .List = list };
|
||||||
},
|
},
|
||||||
else => return error.InvalidInput,
|
else => return error.InvalidInput,
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (tokens.items[*token_index]) {
|
switch (tokens.items[token_index.*]) {
|
||||||
Token.Word, Token.OpenBrace => {
|
Token.Word,
|
||||||
|
Token.OpenBrace => {
|
||||||
const pair = try global_allocator.alloc(Node, 2);
|
const pair = try global_allocator.alloc(Node, 2);
|
||||||
pair[0] = result_node;
|
pair[0] = result_node;
|
||||||
pair[1] = try parse(tokens, token_index);
|
pair[1] = try parse(tokens, token_index);
|
||||||
return Node { .Combine = pair };
|
return Node{ .Combine = pair };
|
||||||
},
|
},
|
||||||
else => return result_node,
|
else => return result_node,
|
||||||
}
|
}
|
||||||
@ -137,13 +142,11 @@ fn expandString(input: []const u8, output: &Buffer) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExpandNodeError = error {
|
const ExpandNodeError = error{OutOfMemory};
|
||||||
OutOfMemory,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn expandNode(node: &const Node, output: &ArrayList(Buffer)) ExpandNodeError!void {
|
fn expandNode(node: &const Node, output: &ArrayList(Buffer)) ExpandNodeError!void {
|
||||||
assert(output.len == 0);
|
assert(output.len == 0);
|
||||||
switch (*node) {
|
switch (node.*) {
|
||||||
Node.Scalar => |scalar| {
|
Node.Scalar => |scalar| {
|
||||||
try output.append(try Buffer.init(global_allocator, scalar));
|
try output.append(try Buffer.init(global_allocator, scalar));
|
||||||
},
|
},
|
||||||
|
190
test/tests.zig
190
test/tests.zig
@ -27,18 +27,18 @@ const TestTarget = struct {
|
|||||||
environ: builtin.Environ,
|
environ: builtin.Environ,
|
||||||
};
|
};
|
||||||
|
|
||||||
const test_targets = []TestTarget {
|
const test_targets = []TestTarget{
|
||||||
TestTarget {
|
TestTarget{
|
||||||
.os = builtin.Os.linux,
|
.os = builtin.Os.linux,
|
||||||
.arch = builtin.Arch.x86_64,
|
.arch = builtin.Arch.x86_64,
|
||||||
.environ = builtin.Environ.gnu,
|
.environ = builtin.Environ.gnu,
|
||||||
},
|
},
|
||||||
TestTarget {
|
TestTarget{
|
||||||
.os = builtin.Os.macosx,
|
.os = builtin.Os.macosx,
|
||||||
.arch = builtin.Arch.x86_64,
|
.arch = builtin.Arch.x86_64,
|
||||||
.environ = builtin.Environ.unknown,
|
.environ = builtin.Environ.unknown,
|
||||||
},
|
},
|
||||||
TestTarget {
|
TestTarget{
|
||||||
.os = builtin.Os.windows,
|
.os = builtin.Os.windows,
|
||||||
.arch = builtin.Arch.x86_64,
|
.arch = builtin.Arch.x86_64,
|
||||||
.environ = builtin.Environ.msvc,
|
.environ = builtin.Environ.msvc,
|
||||||
@ -49,7 +49,7 @@ const max_stdout_size = 1 * 1024 * 1024; // 1 MB
|
|||||||
|
|
||||||
pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
|
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
|
||||||
*cases = CompareOutputContext {
|
cases.* = CompareOutputContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-compare-output", "Run the compare output tests"),
|
.step = b.step("test-compare-output", "Run the compare output tests"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -63,7 +63,7 @@ pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build
|
|||||||
|
|
||||||
pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
|
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
|
||||||
*cases = CompareOutputContext {
|
cases.* = CompareOutputContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-runtime-safety", "Run the runtime safety tests"),
|
.step = b.step("test-runtime-safety", "Run the runtime safety tests"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -77,7 +77,7 @@ pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build
|
|||||||
|
|
||||||
pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(CompileErrorContext) catch unreachable;
|
const cases = b.allocator.create(CompileErrorContext) catch unreachable;
|
||||||
*cases = CompileErrorContext {
|
cases.* = CompileErrorContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-compile-errors", "Run the compile error tests"),
|
.step = b.step("test-compile-errors", "Run the compile error tests"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -91,7 +91,7 @@ pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.
|
|||||||
|
|
||||||
pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
|
const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
|
||||||
*cases = BuildExamplesContext {
|
cases.* = BuildExamplesContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-build-examples", "Build the examples"),
|
.step = b.step("test-build-examples", "Build the examples"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -105,7 +105,7 @@ pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.
|
|||||||
|
|
||||||
pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
|
const cases = b.allocator.create(CompareOutputContext) catch unreachable;
|
||||||
*cases = CompareOutputContext {
|
cases.* = CompareOutputContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-asm-link", "Run the assemble and link tests"),
|
.step = b.step("test-asm-link", "Run the assemble and link tests"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -119,7 +119,7 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &bui
|
|||||||
|
|
||||||
pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(TranslateCContext) catch unreachable;
|
const cases = b.allocator.create(TranslateCContext) catch unreachable;
|
||||||
*cases = TranslateCContext {
|
cases.* = TranslateCContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-translate-c", "Run the C transation tests"),
|
.step = b.step("test-translate-c", "Run the C transation tests"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -133,7 +133,7 @@ pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.St
|
|||||||
|
|
||||||
pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
||||||
const cases = b.allocator.create(GenHContext) catch unreachable;
|
const cases = b.allocator.create(GenHContext) catch unreachable;
|
||||||
*cases = GenHContext {
|
cases.* = GenHContext{
|
||||||
.b = b,
|
.b = b,
|
||||||
.step = b.step("test-gen-h", "Run the C header file generation tests"),
|
.step = b.step("test-gen-h", "Run the C header file generation tests"),
|
||||||
.test_index = 0,
|
.test_index = 0,
|
||||||
@ -145,22 +145,26 @@ pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step {
|
|||||||
return cases.step;
|
return cases.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
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
|
|
||||||
{
|
|
||||||
const step = b.step(b.fmt("test-{}", name), desc);
|
const step = b.step(b.fmt("test-{}", name), desc);
|
||||||
for (test_targets) |test_target| {
|
for (test_targets) |test_target| {
|
||||||
const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
|
const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
|
||||||
for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
|
for ([]Mode{
|
||||||
for ([]bool{false, true}) |link_libc| {
|
Mode.Debug,
|
||||||
|
Mode.ReleaseSafe,
|
||||||
|
Mode.ReleaseFast,
|
||||||
|
Mode.ReleaseSmall,
|
||||||
|
}) |mode| {
|
||||||
|
for ([]bool{
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
}) |link_libc| {
|
||||||
if (link_libc and !is_native) {
|
if (link_libc and !is_native) {
|
||||||
// don't assume we have a cross-compiling libc set up
|
// don't assume we have a cross-compiling libc set up
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const these_tests = b.addTest(root_src);
|
const these_tests = b.addTest(root_src);
|
||||||
these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os),
|
these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
|
||||||
@tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
|
|
||||||
these_tests.setFilter(test_filter);
|
these_tests.setFilter(test_filter);
|
||||||
these_tests.setBuildMode(mode);
|
these_tests.setBuildMode(mode);
|
||||||
if (!is_native) {
|
if (!is_native) {
|
||||||
@ -171,7 +175,15 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
|
|||||||
}
|
}
|
||||||
if (with_lldb) {
|
if (with_lldb) {
|
||||||
these_tests.setExecCmd([]?[]const u8{
|
these_tests.setExecCmd([]?[]const u8{
|
||||||
"lldb", null, "-o", "run", "-o", "bt", "-o", "exit"});
|
"lldb",
|
||||||
|
null,
|
||||||
|
"-o",
|
||||||
|
"run",
|
||||||
|
"-o",
|
||||||
|
"bt",
|
||||||
|
"-o",
|
||||||
|
"exit",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
step.dependOn(&these_tests.step);
|
step.dependOn(&these_tests.step);
|
||||||
}
|
}
|
||||||
@ -206,7 +218,7 @@ pub const CompareOutputContext = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
||||||
self.sources.append(SourceFile {
|
self.sources.append(SourceFile{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
.source = source,
|
.source = source,
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
@ -226,13 +238,10 @@ pub const CompareOutputContext = struct {
|
|||||||
test_index: usize,
|
test_index: usize,
|
||||||
cli_args: []const []const u8,
|
cli_args: []const []const u8,
|
||||||
|
|
||||||
pub fn create(context: &CompareOutputContext, exe_path: []const u8,
|
pub fn create(context: &CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) &RunCompareOutputStep {
|
||||||
name: []const u8, expected_output: []const u8,
|
|
||||||
cli_args: []const []const u8) &RunCompareOutputStep
|
|
||||||
{
|
|
||||||
const allocator = context.b.allocator;
|
const allocator = context.b.allocator;
|
||||||
const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
|
const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
|
||||||
*ptr = RunCompareOutputStep {
|
ptr.* = RunCompareOutputStep{
|
||||||
.context = context,
|
.context = context,
|
||||||
.exe_path = exe_path,
|
.exe_path = exe_path,
|
||||||
.name = name,
|
.name = name,
|
||||||
@ -258,7 +267,7 @@ pub const CompareOutputContext = struct {
|
|||||||
args.append(arg) catch unreachable;
|
args.append(arg) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
|
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
|
||||||
|
|
||||||
const child = os.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable;
|
const child = os.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable;
|
||||||
defer child.deinit();
|
defer child.deinit();
|
||||||
@ -295,7 +304,6 @@ pub const CompareOutputContext = struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) {
|
if (!mem.eql(u8, self.expected_output, stdout.toSliceConst())) {
|
||||||
warn(
|
warn(
|
||||||
\\
|
\\
|
||||||
@ -318,12 +326,10 @@ pub const CompareOutputContext = struct {
|
|||||||
name: []const u8,
|
name: []const u8,
|
||||||
test_index: usize,
|
test_index: usize,
|
||||||
|
|
||||||
pub fn create(context: &CompareOutputContext, exe_path: []const u8,
|
pub fn create(context: &CompareOutputContext, exe_path: []const u8, name: []const u8) &RuntimeSafetyRunStep {
|
||||||
name: []const u8) &RuntimeSafetyRunStep
|
|
||||||
{
|
|
||||||
const allocator = context.b.allocator;
|
const allocator = context.b.allocator;
|
||||||
const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
|
const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
|
||||||
*ptr = RuntimeSafetyRunStep {
|
ptr.* = RuntimeSafetyRunStep{
|
||||||
.context = context,
|
.context = context,
|
||||||
.exe_path = exe_path,
|
.exe_path = exe_path,
|
||||||
.name = name,
|
.name = name,
|
||||||
@ -340,7 +346,7 @@ pub const CompareOutputContext = struct {
|
|||||||
|
|
||||||
const full_exe_path = b.pathFromRoot(self.exe_path);
|
const full_exe_path = b.pathFromRoot(self.exe_path);
|
||||||
|
|
||||||
warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
|
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
|
||||||
|
|
||||||
const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable;
|
const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable;
|
||||||
defer child.deinit();
|
defer child.deinit();
|
||||||
@ -358,19 +364,16 @@ pub const CompareOutputContext = struct {
|
|||||||
switch (term) {
|
switch (term) {
|
||||||
Term.Exited => |code| {
|
Term.Exited => |code| {
|
||||||
if (code != expected_exit_code) {
|
if (code != expected_exit_code) {
|
||||||
warn("\nProgram expected to exit with code {} " ++
|
warn("\nProgram expected to exit with code {} " ++ "but exited with code {}\n", expected_exit_code, code);
|
||||||
"but exited with code {}\n", expected_exit_code, code);
|
|
||||||
return error.TestFailed;
|
return error.TestFailed;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Term.Signal => |sig| {
|
Term.Signal => |sig| {
|
||||||
warn("\nProgram expected to exit with code {} " ++
|
warn("\nProgram expected to exit with code {} " ++ "but instead signaled {}\n", expected_exit_code, sig);
|
||||||
"but instead signaled {}\n", expected_exit_code, sig);
|
|
||||||
return error.TestFailed;
|
return error.TestFailed;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
warn("\nProgram expected to exit with code {}" ++
|
warn("\nProgram expected to exit with code {}" ++ " but exited in an unexpected way\n", expected_exit_code);
|
||||||
" but exited in an unexpected way\n", expected_exit_code);
|
|
||||||
return error.TestFailed;
|
return error.TestFailed;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -379,10 +382,8 @@ pub const CompareOutputContext = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8,
|
pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8, special: Special) TestCase {
|
||||||
expected_output: []const u8, special: Special) TestCase
|
var tc = TestCase{
|
||||||
{
|
|
||||||
var tc = TestCase {
|
|
||||||
.name = name,
|
.name = name,
|
||||||
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
||||||
.expected_output = expected_output,
|
.expected_output = expected_output,
|
||||||
@ -395,9 +396,7 @@ pub const CompareOutputContext = struct {
|
|||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8,
|
pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) TestCase {
|
||||||
expected_output: []const u8) TestCase
|
|
||||||
{
|
|
||||||
return createExtra(self, name, source, expected_output, Special.None);
|
return createExtra(self, name, source, expected_output, Special.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,8 +430,7 @@ pub const CompareOutputContext = struct {
|
|||||||
Special.Asm => {
|
Special.Asm => {
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable;
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "assemble-and-link {}", case.name) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const exe = b.addExecutable("test", null);
|
const exe = b.addExecutable("test", null);
|
||||||
@ -444,19 +442,21 @@ pub const CompareOutputContext = struct {
|
|||||||
exe.step.dependOn(&write_src.step);
|
exe.step.dependOn(&write_src.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name,
|
const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args);
|
||||||
case.expected_output, case.cli_args);
|
|
||||||
run_and_cmp_output.step.dependOn(&exe.step);
|
run_and_cmp_output.step.dependOn(&exe.step);
|
||||||
|
|
||||||
self.step.dependOn(&run_and_cmp_output.step);
|
self.step.dependOn(&run_and_cmp_output.step);
|
||||||
},
|
},
|
||||||
Special.None => {
|
Special.None => {
|
||||||
for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
|
for ([]Mode{
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})",
|
Mode.Debug,
|
||||||
"compare-output", case.name, @tagName(mode)) catch unreachable;
|
Mode.ReleaseSafe,
|
||||||
|
Mode.ReleaseFast,
|
||||||
|
Mode.ReleaseSmall,
|
||||||
|
}) |mode| {
|
||||||
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "compare-output", case.name, @tagName(mode)) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const exe = b.addExecutable("test", root_src);
|
const exe = b.addExecutable("test", root_src);
|
||||||
@ -471,8 +471,7 @@ pub const CompareOutputContext = struct {
|
|||||||
exe.step.dependOn(&write_src.step);
|
exe.step.dependOn(&write_src.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(),
|
const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args);
|
||||||
annotated_case_name, case.expected_output, case.cli_args);
|
|
||||||
run_and_cmp_output.step.dependOn(&exe.step);
|
run_and_cmp_output.step.dependOn(&exe.step);
|
||||||
|
|
||||||
self.step.dependOn(&run_and_cmp_output.step);
|
self.step.dependOn(&run_and_cmp_output.step);
|
||||||
@ -481,8 +480,7 @@ pub const CompareOutputContext = struct {
|
|||||||
Special.RuntimeSafety => {
|
Special.RuntimeSafety => {
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable;
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const exe = b.addExecutable("test", root_src);
|
const exe = b.addExecutable("test", root_src);
|
||||||
@ -524,7 +522,7 @@ pub const CompileErrorContext = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
||||||
self.sources.append(SourceFile {
|
self.sources.append(SourceFile{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
.source = source,
|
.source = source,
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
@ -543,12 +541,10 @@ pub const CompileErrorContext = struct {
|
|||||||
case: &const TestCase,
|
case: &const TestCase,
|
||||||
build_mode: Mode,
|
build_mode: Mode,
|
||||||
|
|
||||||
pub fn create(context: &CompileErrorContext, name: []const u8,
|
pub fn create(context: &CompileErrorContext, name: []const u8, case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep {
|
||||||
case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep
|
|
||||||
{
|
|
||||||
const allocator = context.b.allocator;
|
const allocator = context.b.allocator;
|
||||||
const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
|
const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
|
||||||
*ptr = CompileCmpOutputStep {
|
ptr.* = CompileCmpOutputStep{
|
||||||
.step = build.Step.init("CompileCmpOutput", allocator, make),
|
.step = build.Step.init("CompileCmpOutput", allocator, make),
|
||||||
.context = context,
|
.context = context,
|
||||||
.name = name,
|
.name = name,
|
||||||
@ -586,7 +582,7 @@ pub const CompileErrorContext = struct {
|
|||||||
Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
|
Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
|
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
|
||||||
|
|
||||||
if (b.verbose) {
|
if (b.verbose) {
|
||||||
printInvocation(zig_args.toSliceConst());
|
printInvocation(zig_args.toSliceConst());
|
||||||
@ -626,7 +622,6 @@ pub const CompileErrorContext = struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const stdout = stdout_buf.toSliceConst();
|
const stdout = stdout_buf.toSliceConst();
|
||||||
const stderr = stderr_buf.toSliceConst();
|
const stderr = stderr_buf.toSliceConst();
|
||||||
|
|
||||||
@ -666,11 +661,9 @@ pub const CompileErrorContext = struct {
|
|||||||
warn("\n");
|
warn("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8,
|
pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) &TestCase {
|
||||||
expected_lines: ...) &TestCase
|
|
||||||
{
|
|
||||||
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
||||||
*tc = TestCase {
|
tc.* = TestCase{
|
||||||
.name = name,
|
.name = name,
|
||||||
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
||||||
.expected_errors = ArrayList([]const u8).init(self.b.allocator),
|
.expected_errors = ArrayList([]const u8).init(self.b.allocator),
|
||||||
@ -705,12 +698,13 @@ pub const CompileErrorContext = struct {
|
|||||||
pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void {
|
pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void {
|
||||||
const b = self.b;
|
const b = self.b;
|
||||||
|
|
||||||
for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
|
for ([]Mode{
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
|
Mode.Debug,
|
||||||
case.name, @tagName(mode)) catch unreachable;
|
Mode.ReleaseFast,
|
||||||
|
}) |mode| {
|
||||||
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "compile-error {} ({})", case.name, @tagName(mode)) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode);
|
const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode);
|
||||||
@ -744,8 +738,7 @@ pub const BuildExamplesContext = struct {
|
|||||||
|
|
||||||
const annotated_case_name = b.fmt("build {} (Debug)", build_file);
|
const annotated_case_name = b.fmt("build {} (Debug)", build_file);
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var zig_args = ArrayList([]const u8).init(b.allocator);
|
var zig_args = ArrayList([]const u8).init(b.allocator);
|
||||||
@ -773,12 +766,15 @@ pub const BuildExamplesContext = struct {
|
|||||||
pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void {
|
pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void {
|
||||||
const b = self.b;
|
const b = self.b;
|
||||||
|
|
||||||
for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast, Mode.ReleaseSmall}) |mode| {
|
for ([]Mode{
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})",
|
Mode.Debug,
|
||||||
root_src, @tagName(mode)) catch unreachable;
|
Mode.ReleaseSafe,
|
||||||
|
Mode.ReleaseFast,
|
||||||
|
Mode.ReleaseSmall,
|
||||||
|
}) |mode| {
|
||||||
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "build {} ({})", root_src, @tagName(mode)) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const exe = b.addExecutable("test", root_src);
|
const exe = b.addExecutable("test", root_src);
|
||||||
@ -813,7 +809,7 @@ pub const TranslateCContext = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
||||||
self.sources.append(SourceFile {
|
self.sources.append(SourceFile{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
.source = source,
|
.source = source,
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
@ -834,7 +830,7 @@ pub const TranslateCContext = struct {
|
|||||||
pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep {
|
pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep {
|
||||||
const allocator = context.b.allocator;
|
const allocator = context.b.allocator;
|
||||||
const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
|
const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
|
||||||
*ptr = TranslateCCmpOutputStep {
|
ptr.* = TranslateCCmpOutputStep{
|
||||||
.step = build.Step.init("ParseCCmpOutput", allocator, make),
|
.step = build.Step.init("ParseCCmpOutput", allocator, make),
|
||||||
.context = context,
|
.context = context,
|
||||||
.name = name,
|
.name = name,
|
||||||
@ -857,7 +853,7 @@ pub const TranslateCContext = struct {
|
|||||||
zig_args.append("translate-c") catch unreachable;
|
zig_args.append("translate-c") catch unreachable;
|
||||||
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
|
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
|
||||||
|
|
||||||
warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
|
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
|
||||||
|
|
||||||
if (b.verbose) {
|
if (b.verbose) {
|
||||||
printInvocation(zig_args.toSliceConst());
|
printInvocation(zig_args.toSliceConst());
|
||||||
@ -939,11 +935,9 @@ pub const TranslateCContext = struct {
|
|||||||
warn("\n");
|
warn("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8,
|
pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) &TestCase {
|
||||||
source: []const u8, expected_lines: ...) &TestCase
|
|
||||||
{
|
|
||||||
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
||||||
*tc = TestCase {
|
tc.* = TestCase{
|
||||||
.name = name,
|
.name = name,
|
||||||
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
||||||
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
|
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
|
||||||
@ -977,8 +971,7 @@ pub const TranslateCContext = struct {
|
|||||||
|
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case);
|
const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case);
|
||||||
@ -1009,7 +1002,7 @@ pub const GenHContext = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void {
|
||||||
self.sources.append(SourceFile {
|
self.sources.append(SourceFile{
|
||||||
.filename = filename,
|
.filename = filename,
|
||||||
.source = source,
|
.source = source,
|
||||||
}) catch unreachable;
|
}) catch unreachable;
|
||||||
@ -1031,7 +1024,7 @@ pub const GenHContext = struct {
|
|||||||
pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep {
|
pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep {
|
||||||
const allocator = context.b.allocator;
|
const allocator = context.b.allocator;
|
||||||
const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
|
const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
|
||||||
*ptr = GenHCmpOutputStep {
|
ptr.* = GenHCmpOutputStep{
|
||||||
.step = build.Step.init("ParseCCmpOutput", allocator, make),
|
.step = build.Step.init("ParseCCmpOutput", allocator, make),
|
||||||
.context = context,
|
.context = context,
|
||||||
.h_path = h_path,
|
.h_path = h_path,
|
||||||
@ -1047,7 +1040,7 @@ pub const GenHContext = struct {
|
|||||||
const self = @fieldParentPtr(GenHCmpOutputStep, "step", step);
|
const self = @fieldParentPtr(GenHCmpOutputStep, "step", step);
|
||||||
const b = self.context.b;
|
const b = self.context.b;
|
||||||
|
|
||||||
warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
|
warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
|
||||||
|
|
||||||
const full_h_path = b.pathFromRoot(self.h_path);
|
const full_h_path = b.pathFromRoot(self.h_path);
|
||||||
const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
|
const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
|
||||||
@ -1076,11 +1069,9 @@ pub const GenHContext = struct {
|
|||||||
warn("\n");
|
warn("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(self: &GenHContext, filename: []const u8, name: []const u8,
|
pub fn create(self: &GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) &TestCase {
|
||||||
source: []const u8, expected_lines: ...) &TestCase
|
|
||||||
{
|
|
||||||
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
const tc = self.b.allocator.create(TestCase) catch unreachable;
|
||||||
*tc = TestCase {
|
tc.* = TestCase{
|
||||||
.name = name,
|
.name = name,
|
||||||
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
|
||||||
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
|
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
|
||||||
@ -1105,8 +1096,7 @@ pub const GenHContext = struct {
|
|||||||
const mode = builtin.Mode.Debug;
|
const mode = builtin.Mode.Debug;
|
||||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
|
const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
|
||||||
if (self.test_filter) |filter| {
|
if (self.test_filter) |filter| {
|
||||||
if (mem.indexOf(u8, annotated_case_name, filter) == null)
|
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const obj = b.addObject("test", root_src);
|
const obj = b.addObject("test", root_src);
|
||||||
|
@ -720,43 +720,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
|
|||||||
\\ var a: c_int = 0;
|
\\ var a: c_int = 0;
|
||||||
\\ a += x: {
|
\\ a += x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) + 1);
|
\\ _ref.* = (_ref.* + 1);
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a -= x: {
|
\\ a -= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) - 1);
|
\\ _ref.* = (_ref.* - 1);
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a *= x: {
|
\\ a *= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) * 1);
|
\\ _ref.* = (_ref.* * 1);
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a &= x: {
|
\\ a &= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) & 1);
|
\\ _ref.* = (_ref.* & 1);
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a |= x: {
|
\\ a |= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) | 1);
|
\\ _ref.* = (_ref.* | 1);
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a ^= x: {
|
\\ a ^= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) ^ 1);
|
\\ _ref.* = (_ref.* ^ 1);
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a >>= @import("std").math.Log2Int(c_int)(x: {
|
\\ a >>= @import("std").math.Log2Int(c_int)(x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_int)(1));
|
\\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_int)(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ });
|
\\ });
|
||||||
\\ a <<= @import("std").math.Log2Int(c_int)(x: {
|
\\ a <<= @import("std").math.Log2Int(c_int)(x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_int)(1));
|
\\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_int)(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ });
|
\\ });
|
||||||
\\}
|
\\}
|
||||||
);
|
);
|
||||||
@ -778,43 +778,43 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
|
|||||||
\\ var a: c_uint = c_uint(0);
|
\\ var a: c_uint = c_uint(0);
|
||||||
\\ a +%= x: {
|
\\ a +%= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) +% c_uint(1));
|
\\ _ref.* = (_ref.* +% c_uint(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a -%= x: {
|
\\ a -%= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) -% c_uint(1));
|
\\ _ref.* = (_ref.* -% c_uint(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a *%= x: {
|
\\ a *%= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) *% c_uint(1));
|
\\ _ref.* = (_ref.* *% c_uint(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a &= x: {
|
\\ a &= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) & c_uint(1));
|
\\ _ref.* = (_ref.* & c_uint(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a |= x: {
|
\\ a |= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) | c_uint(1));
|
\\ _ref.* = (_ref.* | c_uint(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a ^= x: {
|
\\ a ^= x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) ^ c_uint(1));
|
\\ _ref.* = (_ref.* ^ c_uint(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ a >>= @import("std").math.Log2Int(c_uint)(x: {
|
\\ a >>= @import("std").math.Log2Int(c_uint)(x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) >> @import("std").math.Log2Int(c_uint)(1));
|
\\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_uint)(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ });
|
\\ });
|
||||||
\\ a <<= @import("std").math.Log2Int(c_uint)(x: {
|
\\ a <<= @import("std").math.Log2Int(c_uint)(x: {
|
||||||
\\ const _ref = &a;
|
\\ const _ref = &a;
|
||||||
\\ (*_ref) = ((*_ref) << @import("std").math.Log2Int(c_uint)(1));
|
\\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_uint)(1));
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ });
|
\\ });
|
||||||
\\}
|
\\}
|
||||||
);
|
);
|
||||||
@ -853,26 +853,26 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
|
|||||||
\\ u -%= 1;
|
\\ u -%= 1;
|
||||||
\\ i = x: {
|
\\ i = x: {
|
||||||
\\ const _ref = &i;
|
\\ const _ref = &i;
|
||||||
\\ const _tmp = *_ref;
|
\\ const _tmp = _ref.*;
|
||||||
\\ (*_ref) += 1;
|
\\ _ref.* += 1;
|
||||||
\\ break :x _tmp;
|
\\ break :x _tmp;
|
||||||
\\ };
|
\\ };
|
||||||
\\ i = x: {
|
\\ i = x: {
|
||||||
\\ const _ref = &i;
|
\\ const _ref = &i;
|
||||||
\\ const _tmp = *_ref;
|
\\ const _tmp = _ref.*;
|
||||||
\\ (*_ref) -= 1;
|
\\ _ref.* -= 1;
|
||||||
\\ break :x _tmp;
|
\\ break :x _tmp;
|
||||||
\\ };
|
\\ };
|
||||||
\\ u = x: {
|
\\ u = x: {
|
||||||
\\ const _ref = &u;
|
\\ const _ref = &u;
|
||||||
\\ const _tmp = *_ref;
|
\\ const _tmp = _ref.*;
|
||||||
\\ (*_ref) +%= 1;
|
\\ _ref.* +%= 1;
|
||||||
\\ break :x _tmp;
|
\\ break :x _tmp;
|
||||||
\\ };
|
\\ };
|
||||||
\\ u = x: {
|
\\ u = x: {
|
||||||
\\ const _ref = &u;
|
\\ const _ref = &u;
|
||||||
\\ const _tmp = *_ref;
|
\\ const _tmp = _ref.*;
|
||||||
\\ (*_ref) -%= 1;
|
\\ _ref.* -%= 1;
|
||||||
\\ break :x _tmp;
|
\\ break :x _tmp;
|
||||||
\\ };
|
\\ };
|
||||||
\\}
|
\\}
|
||||||
@ -901,23 +901,23 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
|
|||||||
\\ u -%= 1;
|
\\ u -%= 1;
|
||||||
\\ i = x: {
|
\\ i = x: {
|
||||||
\\ const _ref = &i;
|
\\ const _ref = &i;
|
||||||
\\ (*_ref) += 1;
|
\\ _ref.* += 1;
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ i = x: {
|
\\ i = x: {
|
||||||
\\ const _ref = &i;
|
\\ const _ref = &i;
|
||||||
\\ (*_ref) -= 1;
|
\\ _ref.* -= 1;
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ u = x: {
|
\\ u = x: {
|
||||||
\\ const _ref = &u;
|
\\ const _ref = &u;
|
||||||
\\ (*_ref) +%= 1;
|
\\ _ref.* +%= 1;
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\ u = x: {
|
\\ u = x: {
|
||||||
\\ const _ref = &u;
|
\\ const _ref = &u;
|
||||||
\\ (*_ref) -%= 1;
|
\\ _ref.* -%= 1;
|
||||||
\\ break :x *_ref;
|
\\ break :x _ref.*;
|
||||||
\\ };
|
\\ };
|
||||||
\\}
|
\\}
|
||||||
);
|
);
|
||||||
@ -985,7 +985,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
|
|||||||
\\}
|
\\}
|
||||||
,
|
,
|
||||||
\\pub export fn foo(x: ?&c_int) void {
|
\\pub export fn foo(x: ?&c_int) void {
|
||||||
\\ (*??x) = 1;
|
\\ (??x).* = 1;
|
||||||
\\}
|
\\}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1013,7 +1013,7 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
|
|||||||
\\pub fn foo() c_int {
|
\\pub fn foo() c_int {
|
||||||
\\ var x: c_int = 1234;
|
\\ var x: c_int = 1234;
|
||||||
\\ var ptr: ?&c_int = &x;
|
\\ var ptr: ?&c_int = &x;
|
||||||
\\ return *??ptr;
|
\\ return (??ptr).*;
|
||||||
\\}
|
\\}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user