2018-10-27 02:59:58 +08:00
|
|
|
const std = @import("std");
|
2019-02-09 07:18:47 +08:00
|
|
|
const expect = std.testing.expect;
|
2019-03-01 04:40:57 +08:00
|
|
|
const expectEqualSlices = std.testing.expectEqualSlices;
|
stage1: rework tokenizer to match stage2
* Extracts AstGen logic from ir.cpp into astgen.cpp. Reduces the
largest file of stage1 from 33,551 lines to 25,510.
* tokenizer: rework it completely to match the stage2 tokenizer logic.
They can now be maintained together; when one is changed, the other
can be changed in the same way.
- Each token now takes up 13 bytes instead of 64 bytes. The tokenizer
does not parse char literals, string literals, integer literals,
etc into meaningful data. Instead, that happens during parsing or
astgen.
- no longer store line offsets. Error messages scan source
files to find the line/column as needed (same as stage2).
- main loop: instead of checking the loop, handle a null byte
explicitly in the switch statements. This is a nice improvement
that we may want to backport to stage2.
- delete some dead tokens, artifacts of past syntax that no longer
exists.
* Parser: fix a TODO by parsing builtin functions as tokens rather than
`@` as a separate token. This is how stage2 does it.
* Remove some debugging infrastructure. These will need to be redone,
if at all, as the code migrates to match stage2.
- remove the ast_render code.
- remove the IR debugging stuff
- remove teh token printing code
2021-05-28 07:32:35 +08:00
|
|
|
const expectEqualStrings = std.testing.expectEqualStrings;
|
2018-10-27 02:59:58 +08:00
|
|
|
const mem = std.mem;
|
2017-05-02 01:12:38 +08:00
|
|
|
const builtin = @import("builtin");
|
2017-01-05 16:57:48 +08:00
|
|
|
|
2016-12-19 13:53:18 +08:00
|
|
|
// normal comment
|
2018-05-01 08:35:54 +08:00
|
|
|
|
2016-12-19 13:53:18 +08:00
|
|
|
/// this is a documentation comment
|
|
|
|
/// doc comment line 2
|
2018-01-25 17:10:11 +08:00
|
|
|
fn emptyFunctionWithComments() void {}
|
2017-03-17 04:02:35 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "empty function with comments" {
|
2017-03-17 04:02:35 +08:00
|
|
|
emptyFunctionWithComments();
|
2016-12-19 13:53:18 +08:00
|
|
|
}
|
|
|
|
|
2017-12-18 22:59:57 +08:00
|
|
|
comptime {
|
2020-01-09 17:36:51 +08:00
|
|
|
@export(disabledExternFn, .{ .name = "disabledExternFn", .linkage = .Internal });
|
2017-12-18 22:59:57 +08:00
|
|
|
}
|
2017-12-19 15:39:43 +08:00
|
|
|
|
2020-01-07 04:34:50 +08:00
|
|
|
fn disabledExternFn() callconv(.C) void {}
|
2016-12-19 13:53:18 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "call disabled extern fn" {
|
2016-12-19 13:53:18 +08:00
|
|
|
disabledExternFn();
|
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "short circuit" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try testShortCircuit(false, true);
|
|
|
|
comptime try testShortCircuit(false, true);
|
2017-01-09 11:25:38 +08:00
|
|
|
}
|
2016-12-19 13:41:37 +08:00
|
|
|
|
2021-05-05 02:23:22 +08:00
|
|
|
fn testShortCircuit(f: bool, t: bool) !void {
|
2017-01-09 11:25:38 +08:00
|
|
|
var hit_1 = f;
|
|
|
|
var hit_2 = f;
|
|
|
|
var hit_3 = f;
|
|
|
|
var hit_4 = f;
|
2016-12-19 13:41:37 +08:00
|
|
|
|
2018-05-01 08:35:54 +08:00
|
|
|
if (t or x: {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(f);
|
2018-05-01 08:35:54 +08:00
|
|
|
break :x f;
|
|
|
|
}) {
|
2017-01-09 11:25:38 +08:00
|
|
|
hit_1 = t;
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
if (f or x: {
|
|
|
|
hit_2 = t;
|
|
|
|
break :x f;
|
|
|
|
}) {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(f);
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
|
|
|
|
2018-05-01 08:35:54 +08:00
|
|
|
if (t and x: {
|
|
|
|
hit_3 = t;
|
|
|
|
break :x f;
|
|
|
|
}) {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(f);
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
if (f and x: {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(f);
|
2018-05-01 08:35:54 +08:00
|
|
|
break :x f;
|
|
|
|
}) {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(f);
|
2016-12-19 13:41:37 +08:00
|
|
|
} else {
|
2017-01-09 11:25:38 +08:00
|
|
|
hit_4 = t;
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(hit_1);
|
|
|
|
try expect(hit_2);
|
|
|
|
try expect(hit_3);
|
|
|
|
try expect(hit_4);
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
|
|
|
|
2017-03-17 04:02:35 +08:00
|
|
|
test "truncate" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(testTruncate(0x10fd) == 0xfd);
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
2018-01-25 17:10:11 +08:00
|
|
|
fn testTruncate(x: u32) u8 {
|
2017-12-22 13:50:30 +08:00
|
|
|
return @truncate(u8, x);
|
2016-12-19 13:41:37 +08:00
|
|
|
}
|
|
|
|
|
2018-01-25 17:10:11 +08:00
|
|
|
fn first4KeysOfHomeRow() []const u8 {
|
2017-12-22 13:50:30 +08:00
|
|
|
return "aoeu";
|
2016-12-22 13:12:27 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "return string from function" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
|
2016-12-22 13:12:27 +08:00
|
|
|
}
|
|
|
|
|
2018-05-01 08:35:54 +08:00
|
|
|
const g1: i32 = 1233 + 1;
|
|
|
|
var g2: i32 = 0;
|
2016-12-22 14:20:08 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "global variables" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(g2 == 0);
|
2016-12-22 14:20:08 +08:00
|
|
|
g2 = g1;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(g2 == 1234);
|
2016-12-22 13:20:14 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "memcpy and memset intrinsics" {
|
2018-05-01 08:35:54 +08:00
|
|
|
var foo: [20]u8 = undefined;
|
|
|
|
var bar: [20]u8 = undefined;
|
2016-12-22 14:42:30 +08:00
|
|
|
|
2020-03-17 09:41:46 +08:00
|
|
|
@memset(&foo, 'A', foo.len);
|
|
|
|
@memcpy(&bar, &foo, bar.len);
|
2016-12-22 14:42:30 +08:00
|
|
|
|
2017-03-26 16:58:48 +08:00
|
|
|
if (bar[11] != 'A') unreachable;
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "builtin static eval" {
|
2018-05-01 08:35:54 +08:00
|
|
|
const x: i32 = comptime x: {
|
|
|
|
break :x 1 + 2 + 3;
|
|
|
|
};
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(x == comptime 6);
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2017-03-17 04:02:35 +08:00
|
|
|
test "slicing" {
|
2018-05-01 08:35:54 +08:00
|
|
|
var array: [20]i32 = undefined;
|
2016-12-22 14:42:30 +08:00
|
|
|
|
|
|
|
array[5] = 1234;
|
|
|
|
|
2017-05-19 22:39:59 +08:00
|
|
|
var slice = array[5..10];
|
2016-12-22 14:42:30 +08:00
|
|
|
|
2017-03-26 16:58:48 +08:00
|
|
|
if (slice.len != 5) unreachable;
|
2016-12-22 14:42:30 +08:00
|
|
|
|
|
|
|
const ptr = &slice[0];
|
2018-06-04 13:09:15 +08:00
|
|
|
if (ptr.* != 1234) unreachable;
|
2016-12-22 14:42:30 +08:00
|
|
|
|
2017-05-19 22:39:59 +08:00
|
|
|
var slice_rest = array[10..];
|
2017-03-26 16:58:48 +08:00
|
|
|
if (slice_rest.len != 10) unreachable;
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "constant equal function pointers" {
|
2016-12-22 14:42:30 +08:00
|
|
|
const alias = emptyFn;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(comptime x: {
|
2018-05-01 08:35:54 +08:00
|
|
|
break :x emptyFn == alias;
|
|
|
|
});
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2018-01-25 17:10:11 +08:00
|
|
|
fn emptyFn() void {}
|
2016-12-22 14:42:30 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "hex escape" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "string concatenation" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "array mult operator" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, "ab" ** 5, "ababababab"));
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "string escapes" {
|
stage1: rework tokenizer to match stage2
* Extracts AstGen logic from ir.cpp into astgen.cpp. Reduces the
largest file of stage1 from 33,551 lines to 25,510.
* tokenizer: rework it completely to match the stage2 tokenizer logic.
They can now be maintained together; when one is changed, the other
can be changed in the same way.
- Each token now takes up 13 bytes instead of 64 bytes. The tokenizer
does not parse char literals, string literals, integer literals,
etc into meaningful data. Instead, that happens during parsing or
astgen.
- no longer store line offsets. Error messages scan source
files to find the line/column as needed (same as stage2).
- main loop: instead of checking the loop, handle a null byte
explicitly in the switch statements. This is a nice improvement
that we may want to backport to stage2.
- delete some dead tokens, artifacts of past syntax that no longer
exists.
* Parser: fix a TODO by parsing builtin functions as tokens rather than
`@` as a separate token. This is how stage2 does it.
* Remove some debugging infrastructure. These will need to be redone,
if at all, as the code migrates to match stage2.
- remove the ast_render code.
- remove the IR debugging stuff
- remove teh token printing code
2021-05-28 07:32:35 +08:00
|
|
|
try expectEqualStrings("\"", "\x22");
|
|
|
|
try expectEqualStrings("\'", "\x27");
|
|
|
|
try expectEqualStrings("\n", "\x0a");
|
|
|
|
try expectEqualStrings("\r", "\x0d");
|
|
|
|
try expectEqualStrings("\t", "\x09");
|
|
|
|
try expectEqualStrings("\\", "\x5c");
|
|
|
|
try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01");
|
2016-12-22 14:42:30 +08:00
|
|
|
}
|
2016-12-22 14:20:08 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "multiline string" {
|
2018-05-29 08:23:55 +08:00
|
|
|
const s1 =
|
2016-12-22 23:09:53 +08:00
|
|
|
\\one
|
|
|
|
\\two)
|
|
|
|
\\three
|
|
|
|
;
|
|
|
|
const s2 = "one\ntwo)\nthree";
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, s1, s2));
|
2016-12-22 23:09:53 +08:00
|
|
|
}
|
|
|
|
|
2020-10-30 23:20:16 +08:00
|
|
|
test "multiline string comments at start" {
|
|
|
|
const s1 =
|
|
|
|
//\\one
|
|
|
|
\\two)
|
|
|
|
\\three
|
|
|
|
;
|
|
|
|
const s2 = "two)\nthree";
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, s1, s2));
|
2020-10-30 23:20:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
test "multiline string comments at end" {
|
|
|
|
const s1 =
|
|
|
|
\\one
|
|
|
|
\\two)
|
|
|
|
//\\three
|
|
|
|
;
|
|
|
|
const s2 = "one\ntwo)";
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, s1, s2));
|
2020-10-30 23:20:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
test "multiline string comments in middle" {
|
|
|
|
const s1 =
|
|
|
|
\\one
|
|
|
|
//\\two)
|
|
|
|
\\three
|
|
|
|
;
|
|
|
|
const s2 = "one\nthree";
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, s1, s2));
|
2020-10-30 23:20:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
test "multiline string comments at multiple places" {
|
|
|
|
const s1 =
|
|
|
|
\\one
|
|
|
|
//\\two
|
|
|
|
\\three
|
|
|
|
//\\four
|
|
|
|
\\five
|
|
|
|
;
|
|
|
|
const s2 = "one\nthree\nfive";
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, s1, s2));
|
2020-10-30 23:20:16 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "multiline C string" {
|
2018-05-29 08:23:55 +08:00
|
|
|
const s1 =
|
2019-11-20 09:29:08 +08:00
|
|
|
\\one
|
|
|
|
\\two)
|
|
|
|
\\three
|
2016-12-22 23:39:10 +08:00
|
|
|
;
|
2019-11-20 09:29:08 +08:00
|
|
|
const s2 = "one\ntwo)\nthree";
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(std.cstr.cmp(s1, s2) == 0);
|
2016-12-22 23:39:10 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "type equality" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(*const u8 != *u8);
|
2016-12-22 23:39:10 +08:00
|
|
|
}
|
2016-12-22 14:20:08 +08:00
|
|
|
|
2016-12-25 17:15:23 +08:00
|
|
|
const global_a: i32 = 1234;
|
2018-05-31 22:56:59 +08:00
|
|
|
const global_b: *const i32 = &global_a;
|
|
|
|
const global_c: *const f32 = @ptrCast(*const f32, global_b);
|
2017-05-08 06:09:45 +08:00
|
|
|
test "compile time global reinterpret" {
|
2018-05-31 22:56:59 +08:00
|
|
|
const d = @ptrCast(*const i32, global_c);
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(d.* == 1234);
|
2016-12-25 17:15:23 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "explicit cast maybe pointers" {
|
2018-05-31 22:56:59 +08:00
|
|
|
const a: ?*i32 = undefined;
|
|
|
|
const b: ?*f32 = @ptrCast(?*f32, a);
|
2021-06-10 09:35:42 +08:00
|
|
|
_ = b;
|
2016-12-26 15:53:42 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "generic malloc free" {
|
2018-01-09 13:07:01 +08:00
|
|
|
const a = memAlloc(u8, 10) catch unreachable;
|
2016-12-26 16:02:20 +08:00
|
|
|
memFree(u8, a);
|
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
var some_mem: [100]u8 = undefined;
|
2018-11-13 21:08:37 +08:00
|
|
|
fn memAlloc(comptime T: type, n: usize) anyerror![]T {
|
2018-06-05 10:11:14 +08:00
|
|
|
return @ptrCast([*]T, &some_mem[0])[0..n];
|
2016-12-26 16:02:20 +08:00
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
fn memFree(comptime T: type, memory: []T) void {}
|
2016-12-26 16:02:20 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "cast undefined" {
|
2016-12-26 16:05:33 +08:00
|
|
|
const array: [100]u8 = undefined;
|
2019-11-27 16:30:39 +08:00
|
|
|
const slice = @as([]const u8, &array);
|
2016-12-26 16:05:33 +08:00
|
|
|
testCastUndefined(slice);
|
|
|
|
}
|
2018-01-25 17:10:11 +08:00
|
|
|
fn testCastUndefined(x: []const u8) void {}
|
2016-12-26 16:05:33 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "cast small unsigned to larger signed" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200));
|
|
|
|
try expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999));
|
2016-12-26 16:05:33 +08:00
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
|
|
|
|
return x;
|
|
|
|
}
|
2016-12-26 16:05:33 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "implicit cast after unreachable" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(outer() == 1234);
|
2016-12-26 16:05:33 +08:00
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
fn inner() i32 {
|
|
|
|
return 1234;
|
|
|
|
}
|
2018-01-25 17:10:11 +08:00
|
|
|
fn outer() i64 {
|
2016-12-26 16:05:33 +08:00
|
|
|
return inner();
|
|
|
|
}
|
2016-12-26 16:02:20 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "pointer dereferencing" {
|
2019-11-07 12:25:57 +08:00
|
|
|
var x = @as(i32, 3);
|
2016-12-26 16:44:59 +08:00
|
|
|
const y = &x;
|
|
|
|
|
2018-05-01 08:35:54 +08:00
|
|
|
y.* += 1;
|
2016-12-26 16:44:59 +08:00
|
|
|
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(x == 4);
|
|
|
|
try expect(y.* == 4);
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "call result of if else expression" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, f2(true), "a"));
|
|
|
|
try expect(mem.eql(u8, f2(false), "b"));
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
2018-01-25 17:10:11 +08:00
|
|
|
fn f2(x: bool) []const u8 {
|
2016-12-26 16:44:59 +08:00
|
|
|
return (if (x) fA else fB)();
|
|
|
|
}
|
2018-05-01 08:35:54 +08:00
|
|
|
fn fA() []const u8 {
|
|
|
|
return "a";
|
|
|
|
}
|
|
|
|
fn fB() []const u8 {
|
|
|
|
return "b";
|
|
|
|
}
|
2016-12-26 16:44:59 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "const expression eval handling of variables" {
|
2016-12-26 16:44:59 +08:00
|
|
|
var x = true;
|
|
|
|
while (x) {
|
|
|
|
x = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "constant enum initialization with differing sizes" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try test3_1(test3_foo);
|
|
|
|
try test3_2(test3_bar);
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
2018-11-13 21:08:37 +08:00
|
|
|
const Test3Foo = union(enum) {
|
2017-12-04 09:43:56 +08:00
|
|
|
One: void,
|
2016-12-26 16:44:59 +08:00
|
|
|
Two: f32,
|
|
|
|
Three: Test3Point,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const Test3Point = struct {
|
2016-12-26 16:44:59 +08:00
|
|
|
x: i32,
|
|
|
|
y: i32,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const test3_foo = Test3Foo{
|
|
|
|
.Three = Test3Point{
|
2018-05-01 08:35:54 +08:00
|
|
|
.x = 3,
|
|
|
|
.y = 4,
|
|
|
|
},
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const test3_bar = Test3Foo{ .Two = 13 };
|
2021-05-05 02:23:22 +08:00
|
|
|
fn test3_1(f: Test3Foo) !void {
|
2018-10-16 06:23:47 +08:00
|
|
|
switch (f) {
|
2016-12-26 16:44:59 +08:00
|
|
|
Test3Foo.Three => |pt| {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(pt.x == 3);
|
|
|
|
try expect(pt.y == 4);
|
2016-12-26 16:44:59 +08:00
|
|
|
},
|
2017-03-26 16:58:48 +08:00
|
|
|
else => unreachable,
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
|
|
|
}
|
2021-05-05 02:23:22 +08:00
|
|
|
fn test3_2(f: Test3Foo) !void {
|
2018-10-16 06:23:47 +08:00
|
|
|
switch (f) {
|
2016-12-26 16:44:59 +08:00
|
|
|
Test3Foo.Two => |x| {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(x == 13);
|
2016-12-26 16:44:59 +08:00
|
|
|
},
|
2017-03-26 16:58:48 +08:00
|
|
|
else => unreachable,
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "character literals" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect('\'' == single_quote);
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
|
|
|
const single_quote = '\'';
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "take address of parameter" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try testTakeAddressOfParameter(12.34);
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
2021-05-05 02:23:22 +08:00
|
|
|
fn testTakeAddressOfParameter(f: f32) !void {
|
2016-12-26 16:44:59 +08:00
|
|
|
const f_ptr = &f;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(f_ptr.* == 12.34);
|
2016-12-26 16:44:59 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "pointer comparison" {
|
2019-11-08 03:46:48 +08:00
|
|
|
const a = @as([]const u8, "a");
|
2016-12-27 04:49:03 +08:00
|
|
|
const b = &a;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(ptrEql(b, b));
|
2016-12-27 04:49:03 +08:00
|
|
|
}
|
2018-05-31 22:56:59 +08:00
|
|
|
fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
|
2017-12-22 13:50:30 +08:00
|
|
|
return a == b;
|
2016-12-27 04:49:03 +08:00
|
|
|
}
|
2016-12-26 16:44:59 +08:00
|
|
|
|
2019-11-20 09:29:08 +08:00
|
|
|
test "string concatenation" {
|
|
|
|
const a = "OK" ++ " IT " ++ "WORKED";
|
|
|
|
const b = "OK IT WORKED";
|
|
|
|
|
2021-05-05 02:23:22 +08:00
|
|
|
comptime try expect(@TypeOf(a) == *const [12:0]u8);
|
|
|
|
comptime try expect(@TypeOf(b) == *const [12:0]u8);
|
2016-12-27 05:04:14 +08:00
|
|
|
|
2020-03-02 02:21:29 +08:00
|
|
|
const len = mem.len(b);
|
2016-12-27 05:04:14 +08:00
|
|
|
const len_with_null = len + 1;
|
2018-05-01 08:35:54 +08:00
|
|
|
{
|
|
|
|
var i: u32 = 0;
|
|
|
|
while (i < len_with_null) : (i += 1) {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(a[i] == b[i]);
|
2018-05-01 08:35:54 +08:00
|
|
|
}
|
|
|
|
}
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(a[len] == 0);
|
|
|
|
try expect(b[len] == 0);
|
2016-12-27 05:04:14 +08:00
|
|
|
}
|
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "pointer to void return type" {
|
2018-01-09 13:07:01 +08:00
|
|
|
testPointerToVoidReturnType() catch unreachable;
|
2016-12-28 14:31:46 +08:00
|
|
|
}
|
2018-11-13 21:08:37 +08:00
|
|
|
fn testPointerToVoidReturnType() anyerror!void {
|
2016-12-28 14:31:46 +08:00
|
|
|
const a = testPointerToVoidReturnType2();
|
2018-05-01 08:35:54 +08:00
|
|
|
return a.*;
|
2016-12-28 14:31:46 +08:00
|
|
|
}
|
2018-11-13 21:08:37 +08:00
|
|
|
const test_pointer_to_void_return_type_x = void{};
|
2018-05-31 22:56:59 +08:00
|
|
|
fn testPointerToVoidReturnType2() *const void {
|
2016-12-28 14:31:46 +08:00
|
|
|
return &test_pointer_to_void_return_type_x;
|
|
|
|
}
|
2017-01-06 07:50:36 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "non const ptr to aliased type" {
|
2017-01-06 07:50:36 +08:00
|
|
|
const int = i32;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(?*int == ?*i32);
|
2017-01-06 07:50:36 +08:00
|
|
|
}
|
2017-01-17 01:42:46 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "array 2D const double ptr" {
|
2019-06-10 07:24:24 +08:00
|
|
|
const rect_2d_vertexes = [_][1]f32{
|
|
|
|
[_]f32{1.0},
|
|
|
|
[_]f32{2.0},
|
2017-01-17 01:42:46 +08:00
|
|
|
};
|
2021-05-05 02:23:22 +08:00
|
|
|
try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
|
2017-01-17 01:42:46 +08:00
|
|
|
}
|
|
|
|
|
2021-05-05 02:23:22 +08:00
|
|
|
fn testArray2DConstDoublePtr(ptr: *const f32) !void {
|
2018-06-04 13:09:15 +08:00
|
|
|
const ptr2 = @ptrCast([*]const f32, ptr);
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(ptr2[0] == 1.0);
|
|
|
|
try expect(ptr2[1] == 2.0);
|
2017-01-17 01:42:46 +08:00
|
|
|
}
|
2017-01-24 14:58:20 +08:00
|
|
|
|
2018-11-13 21:08:37 +08:00
|
|
|
const AStruct = struct {
|
2018-05-01 08:35:54 +08:00
|
|
|
x: i32,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const AnEnum = enum {
|
2018-05-01 08:35:54 +08:00
|
|
|
One,
|
|
|
|
Two,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const AUnionEnum = union(enum) {
|
2018-05-01 08:35:54 +08:00
|
|
|
One: i32,
|
|
|
|
Two: void,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const AUnion = union {
|
2018-05-01 08:35:54 +08:00
|
|
|
One: void,
|
|
|
|
Two: void,
|
|
|
|
};
|
2017-01-24 14:58:20 +08:00
|
|
|
|
2017-05-08 06:09:45 +08:00
|
|
|
test "@typeName" {
|
2018-11-13 21:08:37 +08:00
|
|
|
const Struct = struct {};
|
|
|
|
const Union = union {
|
2018-02-23 00:53:58 +08:00
|
|
|
unused: u8,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const Enum = enum {
|
2018-02-23 00:53:58 +08:00
|
|
|
Unused,
|
|
|
|
};
|
2017-01-24 14:58:20 +08:00
|
|
|
comptime {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, @typeName(i64), "i64"));
|
|
|
|
try expect(mem.eql(u8, @typeName(*usize), "*usize"));
|
2018-05-25 09:27:44 +08:00
|
|
|
// https://github.com/ziglang/zig/issues/675
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(mem.eql(u8, "behavior.misc.TypeFromFn(u8)", @typeName(TypeFromFn(u8))));
|
|
|
|
try expect(mem.eql(u8, @typeName(Struct), "Struct"));
|
|
|
|
try expect(mem.eql(u8, @typeName(Union), "Union"));
|
|
|
|
try expect(mem.eql(u8, @typeName(Enum), "Enum"));
|
2017-01-24 14:58:20 +08:00
|
|
|
}
|
|
|
|
}
|
2017-02-05 10:49:27 +08:00
|
|
|
|
2018-02-23 00:53:58 +08:00
|
|
|
fn TypeFromFn(comptime T: type) type {
|
2018-11-13 21:08:37 +08:00
|
|
|
return struct {};
|
2018-02-23 00:53:58 +08:00
|
|
|
}
|
|
|
|
|
2019-01-30 10:47:26 +08:00
|
|
|
test "double implicit cast in same expression" {
|
2019-11-07 12:25:57 +08:00
|
|
|
var x = @as(i32, @as(u16, nine()));
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(x == 9);
|
2017-02-05 10:49:27 +08:00
|
|
|
}
|
2019-01-30 10:47:26 +08:00
|
|
|
fn nine() u8 {
|
|
|
|
return 9;
|
2017-05-01 00:21:24 +08:00
|
|
|
}
|
2017-05-08 06:09:45 +08:00
|
|
|
|
|
|
|
test "global variable initialized to global variable array element" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(global_ptr == &gdt[0]);
|
2017-05-08 06:09:45 +08:00
|
|
|
}
|
2018-11-13 21:08:37 +08:00
|
|
|
const GDTEntry = struct {
|
2017-05-08 06:09:45 +08:00
|
|
|
field: i32,
|
|
|
|
};
|
2019-06-10 07:24:24 +08:00
|
|
|
var gdt = [_]GDTEntry{
|
2018-11-13 21:08:37 +08:00
|
|
|
GDTEntry{ .field = 1 },
|
|
|
|
GDTEntry{ .field = 2 },
|
2017-05-08 06:09:45 +08:00
|
|
|
};
|
|
|
|
var global_ptr = &gdt[0];
|
2017-05-30 02:25:00 +08:00
|
|
|
|
|
|
|
// can't really run this test but we can make sure it has no compile error
|
|
|
|
// and generates code
|
2018-06-05 10:11:14 +08:00
|
|
|
const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
|
2018-01-25 17:10:11 +08:00
|
|
|
export fn writeToVRam() void {
|
2017-05-30 02:25:00 +08:00
|
|
|
vram[0] = 'X';
|
|
|
|
}
|
2017-08-30 12:17:11 +08:00
|
|
|
|
2020-09-26 04:29:03 +08:00
|
|
|
const OpaqueA = opaque {};
|
|
|
|
const OpaqueB = opaque {};
|
2020-04-28 13:14:40 +08:00
|
|
|
test "opaque types" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(*OpaqueA != *OpaqueB);
|
|
|
|
try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
|
|
|
|
try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
|
2017-09-06 06:51:07 +08:00
|
|
|
}
|
2017-09-10 12:34:44 +08:00
|
|
|
|
|
|
|
test "variable is allowed to be a pointer to an opaque type" {
|
|
|
|
var x: i32 = 1234;
|
2018-05-31 22:56:59 +08:00
|
|
|
_ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
|
2017-09-10 12:34:44 +08:00
|
|
|
}
|
2018-05-31 22:56:59 +08:00
|
|
|
fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
|
2017-09-10 12:34:44 +08:00
|
|
|
var a = ptr;
|
|
|
|
return a;
|
|
|
|
}
|
2018-01-03 09:52:24 +08:00
|
|
|
|
|
|
|
test "comptime if inside runtime while which unconditionally breaks" {
|
|
|
|
testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
|
|
|
|
comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
|
|
|
|
}
|
2018-01-25 17:10:11 +08:00
|
|
|
fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
|
2018-01-03 09:52:24 +08:00
|
|
|
while (cond) {
|
2018-05-01 08:35:54 +08:00
|
|
|
if (false) {}
|
2018-01-03 09:52:24 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-01-03 16:15:06 +08:00
|
|
|
|
|
|
|
test "implicit comptime while" {
|
|
|
|
while (false) {
|
|
|
|
@compileError("bad");
|
|
|
|
}
|
|
|
|
}
|
2018-01-07 13:20:26 +08:00
|
|
|
|
2018-01-25 17:10:11 +08:00
|
|
|
fn fnThatClosesOverLocalConst() type {
|
2018-01-07 13:50:43 +08:00
|
|
|
const c = 1;
|
2018-11-13 21:08:37 +08:00
|
|
|
return struct {
|
2018-05-01 08:35:54 +08:00
|
|
|
fn g() i32 {
|
|
|
|
return c;
|
|
|
|
}
|
2018-01-07 13:50:43 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
test "function closes over local const" {
|
|
|
|
const x = fnThatClosesOverLocalConst().g();
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(x == 1);
|
2018-01-07 13:50:43 +08:00
|
|
|
}
|
2018-01-23 11:24:07 +08:00
|
|
|
|
|
|
|
test "cold function" {
|
|
|
|
thisIsAColdFn();
|
|
|
|
comptime thisIsAColdFn();
|
|
|
|
}
|
|
|
|
|
2018-01-25 17:10:11 +08:00
|
|
|
fn thisIsAColdFn() void {
|
2018-01-23 11:24:07 +08:00
|
|
|
@setCold(true);
|
|
|
|
}
|
2018-01-29 23:57:09 +08:00
|
|
|
|
2018-11-13 21:08:37 +08:00
|
|
|
const PackedStruct = packed struct {
|
2018-05-01 08:35:54 +08:00
|
|
|
a: u8,
|
|
|
|
b: u8,
|
|
|
|
};
|
2018-11-13 21:08:37 +08:00
|
|
|
const PackedUnion = packed union {
|
2018-05-01 08:35:54 +08:00
|
|
|
a: u8,
|
|
|
|
b: u32,
|
|
|
|
};
|
2018-01-29 23:57:09 +08:00
|
|
|
|
|
|
|
test "packed struct, enum, union parameters in extern function" {
|
2018-11-13 21:08:37 +08:00
|
|
|
testPackedStuff(&(PackedStruct{
|
2018-05-01 08:35:54 +08:00
|
|
|
.a = 1,
|
|
|
|
.b = 2,
|
2021-06-14 03:27:27 +08:00
|
|
|
}), &(PackedUnion{ .a = 1 }));
|
2018-01-29 23:57:09 +08:00
|
|
|
}
|
2018-03-07 06:19:45 +08:00
|
|
|
|
2021-06-14 03:27:27 +08:00
|
|
|
export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {}
|
2018-03-07 06:19:45 +08:00
|
|
|
|
|
|
|
test "slicing zero length array" {
|
|
|
|
const s1 = ""[0..];
|
2019-06-10 07:24:24 +08:00
|
|
|
const s2 = ([_]u32{})[0..];
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(s1.len == 0);
|
|
|
|
try expect(s2.len == 0);
|
|
|
|
try expect(mem.eql(u8, s1, ""));
|
|
|
|
try expect(mem.eql(u32, s2, &[_]u32{}));
|
2018-03-07 06:19:45 +08:00
|
|
|
}
|
2018-03-14 07:13:10 +08:00
|
|
|
|
2018-05-31 22:56:59 +08:00
|
|
|
const addr1 = @ptrCast(*const u8, emptyFn);
|
2018-03-14 07:13:10 +08:00
|
|
|
test "comptime cast fn to ptr" {
|
2018-05-31 22:56:59 +08:00
|
|
|
const addr2 = @ptrCast(*const u8, emptyFn);
|
2021-05-05 02:23:22 +08:00
|
|
|
comptime try expect(addr1 == addr2);
|
2018-03-14 07:13:10 +08:00
|
|
|
}
|
2018-06-20 18:45:45 +08:00
|
|
|
|
|
|
|
test "equality compare fn ptrs" {
|
|
|
|
var a = emptyFn;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(a == a);
|
2018-06-20 18:45:45 +08:00
|
|
|
}
|
2018-09-25 22:45:11 +08:00
|
|
|
|
|
|
|
test "self reference through fn ptr field" {
|
2018-11-13 21:08:37 +08:00
|
|
|
const S = struct {
|
|
|
|
const A = struct {
|
2018-09-25 22:45:11 +08:00
|
|
|
f: fn (A) u8,
|
|
|
|
};
|
|
|
|
|
|
|
|
fn foo(a: A) u8 {
|
|
|
|
return 12;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
var a: S.A = undefined;
|
|
|
|
a.f = S.foo;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(a.f(a) == 12);
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
test "volatile load and store" {
|
|
|
|
var number: i32 = 1234;
|
2019-11-08 03:46:48 +08:00
|
|
|
const ptr = @as(*volatile i32, &number);
|
2019-01-30 10:47:26 +08:00
|
|
|
ptr.* += 1;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(ptr.* == 1235);
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
|
|
|
|
2020-03-17 09:41:46 +08:00
|
|
|
test "slice string literal has correct type" {
|
2019-01-30 10:47:26 +08:00
|
|
|
comptime {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
|
2019-06-10 07:24:24 +08:00
|
|
|
const array = [_]i32{ 1, 2, 3, 4 };
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(@TypeOf(array[0..]) == *const [4]i32);
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
2020-03-17 09:41:46 +08:00
|
|
|
var runtime_zero: usize = 0;
|
2021-05-05 02:23:22 +08:00
|
|
|
comptime try expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
|
2020-03-17 09:41:46 +08:00
|
|
|
const array = [_]i32{ 1, 2, 3, 4 };
|
2021-05-05 02:23:22 +08:00
|
|
|
comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
test "struct inside function" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try testStructInFn();
|
|
|
|
comptime try testStructInFn();
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
|
|
|
|
2021-05-05 02:23:22 +08:00
|
|
|
fn testStructInFn() !void {
|
2019-01-30 10:47:26 +08:00
|
|
|
const BlockKind = u32;
|
|
|
|
|
|
|
|
const Block = struct {
|
|
|
|
kind: BlockKind,
|
|
|
|
};
|
|
|
|
|
|
|
|
var block = Block{ .kind = 1234 };
|
|
|
|
|
|
|
|
block.kind += 1;
|
|
|
|
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(block.kind == 1235);
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
test "fn call returning scalar optional in equality expression" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(getNull() == null);
|
2019-01-30 10:47:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn getNull() ?*i32 {
|
|
|
|
return null;
|
2018-09-25 22:45:11 +08:00
|
|
|
}
|
2019-02-07 02:48:04 +08:00
|
|
|
|
2019-06-20 11:39:49 +08:00
|
|
|
test "thread local variable" {
|
|
|
|
const S = struct {
|
|
|
|
threadlocal var t: i32 = 1234;
|
|
|
|
};
|
|
|
|
S.t += 1;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(S.t == 1235);
|
2019-06-20 11:39:49 +08:00
|
|
|
}
|
2019-03-24 05:35:21 +08:00
|
|
|
|
|
|
|
test "unicode escape in character literal" {
|
2019-07-05 13:40:19 +08:00
|
|
|
var a: u24 = '\u{01f4a9}';
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(a == 128169);
|
2019-03-24 05:35:21 +08:00
|
|
|
}
|
2019-06-21 12:58:18 +08:00
|
|
|
|
2019-10-07 01:52:35 +08:00
|
|
|
test "unicode character in character literal" {
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect('💩' == 128169);
|
2019-10-07 01:52:35 +08:00
|
|
|
}
|
|
|
|
|
2019-06-21 12:58:18 +08:00
|
|
|
test "result location zero sized array inside struct field implicit cast to slice" {
|
|
|
|
const E = struct {
|
|
|
|
entries: []u32,
|
|
|
|
};
|
2019-11-27 16:30:39 +08:00
|
|
|
var foo = E{ .entries = &[_]u32{} };
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(foo.entries.len == 0);
|
2019-06-21 12:58:18 +08:00
|
|
|
}
|
2019-08-27 03:24:24 +08:00
|
|
|
|
|
|
|
var global_foo: *i32 = undefined;
|
|
|
|
|
|
|
|
test "global variable assignment with optional unwrapping with var initialized to undefined" {
|
|
|
|
const S = struct {
|
|
|
|
var data: i32 = 1234;
|
|
|
|
fn foo() ?*i32 {
|
|
|
|
return &data;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
global_foo = S.foo() orelse {
|
|
|
|
@panic("bad");
|
|
|
|
};
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(global_foo.* == 1234);
|
2019-08-27 03:24:24 +08:00
|
|
|
}
|
2019-09-18 10:30:49 +08:00
|
|
|
|
|
|
|
test "peer result location with typed parent, runtime condition, comptime prongs" {
|
|
|
|
const S = struct {
|
|
|
|
fn doTheTest(arg: i32) i32 {
|
|
|
|
const st = Structy{
|
|
|
|
.bleh = if (arg == 1) 1 else 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (st.bleh == 1)
|
|
|
|
return 1234;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Structy = struct {
|
|
|
|
bleh: i32,
|
|
|
|
};
|
|
|
|
};
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(S.doTheTest(0) == 1234);
|
|
|
|
try expect(S.doTheTest(1) == 1234);
|
2019-09-18 10:30:49 +08:00
|
|
|
}
|
2019-09-13 05:02:15 +08:00
|
|
|
|
|
|
|
test "nested optional field in struct" {
|
|
|
|
const S2 = struct {
|
|
|
|
y: u8,
|
|
|
|
};
|
|
|
|
const S1 = struct {
|
|
|
|
x: ?S2,
|
|
|
|
};
|
|
|
|
var s = S1{
|
|
|
|
.x = S2{ .y = 127 },
|
|
|
|
};
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(s.x.?.y == 127);
|
2019-09-13 05:02:15 +08:00
|
|
|
}
|
2019-09-13 15:29:35 +08:00
|
|
|
|
|
|
|
fn maybe(x: bool) anyerror!?u32 {
|
|
|
|
return switch (x) {
|
2019-11-07 12:25:57 +08:00
|
|
|
true => @as(u32, 42),
|
2019-09-13 15:29:35 +08:00
|
|
|
else => null,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
test "result location is optional inside error union" {
|
|
|
|
const x = maybe(true) catch unreachable;
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(x.? == 42);
|
2019-09-13 15:29:35 +08:00
|
|
|
}
|
2019-12-16 02:25:41 +08:00
|
|
|
|
|
|
|
threadlocal var buffer: [11]u8 = undefined;
|
|
|
|
|
|
|
|
test "pointer to thread local array" {
|
|
|
|
const s = "Hello world";
|
|
|
|
std.mem.copy(u8, buffer[0..], s);
|
2021-05-05 02:23:22 +08:00
|
|
|
try std.testing.expectEqualSlices(u8, buffer[0..], s);
|
2019-12-16 02:25:41 +08:00
|
|
|
}
|
2020-01-28 08:42:32 +08:00
|
|
|
|
|
|
|
test "auto created variables have correct alignment" {
|
|
|
|
const S = struct {
|
|
|
|
fn foo(str: [*]const u8) u32 {
|
|
|
|
for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| {
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
|
|
|
comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a);
|
2020-01-28 08:42:32 +08:00
|
|
|
}
|
2020-07-18 01:16:23 +08:00
|
|
|
|
2020-09-26 04:29:03 +08:00
|
|
|
extern var opaque_extern_var: opaque {};
|
2020-07-18 01:16:23 +08:00
|
|
|
var var_to_export: u32 = 42;
|
|
|
|
test "extern variable with non-pointer opaque type" {
|
|
|
|
@export(var_to_export, .{ .name = "opaque_extern_var" });
|
2021-05-05 02:23:22 +08:00
|
|
|
try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42);
|
2020-07-18 01:16:23 +08:00
|
|
|
}
|
2020-12-15 00:39:35 +08:00
|
|
|
|
|
|
|
test "lazy typeInfo value as generic parameter" {
|
|
|
|
const S = struct {
|
|
|
|
fn foo(args: anytype) void {}
|
|
|
|
};
|
|
|
|
S.foo(@typeInfo(@TypeOf(.{})));
|
|
|
|
}
|