2017-01-05 00:57:48 -08:00
|
|
|
const assert = @import("std").debug.assert;
|
2017-02-07 14:19:51 -08:00
|
|
|
const mem = @import("std").mem;
|
2017-01-05 00:57:48 -08:00
|
|
|
const cstr = @import("std").cstr;
|
2017-05-01 10:12:38 -07:00
|
|
|
const builtin = @import("builtin");
|
2017-01-05 00:57:48 -08:00
|
|
|
|
2016-12-18 21:53:18 -08:00
|
|
|
// normal comment
|
2018-04-30 17:35:54 -07:00
|
|
|
|
2016-12-18 21:53:18 -08:00
|
|
|
/// this is a documentation comment
|
|
|
|
/// doc comment line 2
|
2018-01-25 01:10:11 -08:00
|
|
|
fn emptyFunctionWithComments() void {}
|
2017-03-16 13:02:35 -07:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "empty function with comments" {
|
2017-03-16 13:02:35 -07:00
|
|
|
emptyFunctionWithComments();
|
2016-12-18 21:53:18 -08:00
|
|
|
}
|
|
|
|
|
2017-12-18 06:59:57 -08:00
|
|
|
comptime {
|
2017-12-18 23:39:43 -08:00
|
|
|
@export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
|
2017-12-18 06:59:57 -08:00
|
|
|
}
|
2017-12-18 23:39:43 -08:00
|
|
|
|
2018-04-30 17:35:54 -07:00
|
|
|
extern fn disabledExternFn() void {}
|
2016-12-18 21:53:18 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "call disabled extern fn" {
|
2016-12-18 21:53:18 -08:00
|
|
|
disabledExternFn();
|
|
|
|
}
|
|
|
|
|
2017-04-17 21:05:09 -07:00
|
|
|
test "@IntType builtin" {
|
|
|
|
assert(@IntType(true, 8) == i8);
|
|
|
|
assert(@IntType(true, 16) == i16);
|
|
|
|
assert(@IntType(true, 32) == i32);
|
|
|
|
assert(@IntType(true, 64) == i64);
|
2016-12-18 21:41:37 -08:00
|
|
|
|
2017-04-17 21:05:09 -07:00
|
|
|
assert(@IntType(false, 8) == u8);
|
|
|
|
assert(@IntType(false, 16) == u16);
|
|
|
|
assert(@IntType(false, 32) == u32);
|
|
|
|
assert(@IntType(false, 64) == u64);
|
2016-12-18 21:41:37 -08:00
|
|
|
|
|
|
|
assert(i8.bit_count == 8);
|
|
|
|
assert(i16.bit_count == 16);
|
|
|
|
assert(i32.bit_count == 32);
|
|
|
|
assert(i64.bit_count == 64);
|
|
|
|
|
|
|
|
assert(i8.is_signed);
|
|
|
|
assert(i16.is_signed);
|
|
|
|
assert(i32.is_signed);
|
|
|
|
assert(i64.is_signed);
|
|
|
|
assert(isize.is_signed);
|
|
|
|
|
|
|
|
assert(!u8.is_signed);
|
|
|
|
assert(!u16.is_signed);
|
|
|
|
assert(!u32.is_signed);
|
|
|
|
assert(!u64.is_signed);
|
|
|
|
assert(!usize.is_signed);
|
|
|
|
}
|
|
|
|
|
2017-05-06 20:13:12 -07:00
|
|
|
test "floating point primitive bit counts" {
|
|
|
|
assert(f32.bit_count == 32);
|
|
|
|
assert(f64.bit_count == 64);
|
|
|
|
}
|
|
|
|
|
2017-04-17 21:05:09 -07:00
|
|
|
const u1 = @IntType(false, 1);
|
|
|
|
const u63 = @IntType(false, 63);
|
|
|
|
const i1 = @IntType(true, 1);
|
|
|
|
const i63 = @IntType(true, 63);
|
2017-02-21 21:49:10 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "@minValue and @maxValue" {
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@maxValue(u1) == 1);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@maxValue(u8) == 255);
|
|
|
|
assert(@maxValue(u16) == 65535);
|
|
|
|
assert(@maxValue(u32) == 4294967295);
|
|
|
|
assert(@maxValue(u64) == 18446744073709551615);
|
|
|
|
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@maxValue(i1) == 0);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@maxValue(i8) == 127);
|
|
|
|
assert(@maxValue(i16) == 32767);
|
|
|
|
assert(@maxValue(i32) == 2147483647);
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@maxValue(i63) == 4611686018427387903);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@maxValue(i64) == 9223372036854775807);
|
|
|
|
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@minValue(u1) == 0);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@minValue(u8) == 0);
|
|
|
|
assert(@minValue(u16) == 0);
|
|
|
|
assert(@minValue(u32) == 0);
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@minValue(u63) == 0);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@minValue(u64) == 0);
|
|
|
|
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@minValue(i1) == -1);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@minValue(i8) == -128);
|
|
|
|
assert(@minValue(i16) == -32768);
|
|
|
|
assert(@minValue(i32) == -2147483648);
|
2017-02-21 21:49:10 -08:00
|
|
|
assert(@minValue(i63) == -4611686018427387904);
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(@minValue(i64) == -9223372036854775808);
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "max value type" {
|
2016-12-21 22:20:08 -08:00
|
|
|
// If the type of @maxValue(i32) was i32 then this implicit cast to
|
|
|
|
// u32 would not work. But since the value is a number literal,
|
|
|
|
// it works fine.
|
|
|
|
const x: u32 = @maxValue(i32);
|
|
|
|
assert(x == 2147483647);
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "short circuit" {
|
2017-01-08 19:25:38 -08:00
|
|
|
testShortCircuit(false, true);
|
2017-05-07 15:09:45 -07:00
|
|
|
comptime testShortCircuit(false, true);
|
2017-01-08 19:25:38 -08:00
|
|
|
}
|
2016-12-18 21:41:37 -08:00
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
fn testShortCircuit(f: bool, t: bool) void {
|
2017-01-08 19:25:38 -08:00
|
|
|
var hit_1 = f;
|
|
|
|
var hit_2 = f;
|
|
|
|
var hit_3 = f;
|
|
|
|
var hit_4 = f;
|
2016-12-18 21:41:37 -08:00
|
|
|
|
2018-04-30 17:35:54 -07:00
|
|
|
if (t or x: {
|
|
|
|
assert(f);
|
|
|
|
break :x f;
|
|
|
|
}) {
|
2017-01-08 19:25:38 -08:00
|
|
|
hit_1 = t;
|
2016-12-18 21:41:37 -08:00
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
if (f or x: {
|
|
|
|
hit_2 = t;
|
|
|
|
break :x f;
|
|
|
|
}) {
|
2017-01-08 19:25:38 -08:00
|
|
|
assert(f);
|
2016-12-18 21:41:37 -08:00
|
|
|
}
|
|
|
|
|
2018-04-30 17:35:54 -07:00
|
|
|
if (t and x: {
|
|
|
|
hit_3 = t;
|
|
|
|
break :x f;
|
|
|
|
}) {
|
2017-01-08 19:25:38 -08:00
|
|
|
assert(f);
|
2016-12-18 21:41:37 -08:00
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
if (f and x: {
|
|
|
|
assert(f);
|
|
|
|
break :x f;
|
|
|
|
}) {
|
2017-01-08 19:25:38 -08:00
|
|
|
assert(f);
|
2016-12-18 21:41:37 -08:00
|
|
|
} else {
|
2017-01-08 19:25:38 -08:00
|
|
|
hit_4 = t;
|
2016-12-18 21:41:37 -08:00
|
|
|
}
|
|
|
|
assert(hit_1);
|
|
|
|
assert(hit_2);
|
|
|
|
assert(hit_3);
|
|
|
|
assert(hit_4);
|
|
|
|
}
|
|
|
|
|
2017-03-16 13:02:35 -07:00
|
|
|
test "truncate" {
|
2016-12-18 21:41:37 -08:00
|
|
|
assert(testTruncate(0x10fd) == 0xfd);
|
|
|
|
}
|
2018-01-25 01:10:11 -08:00
|
|
|
fn testTruncate(x: u32) u8 {
|
2017-12-21 21:50:30 -08:00
|
|
|
return @truncate(u8, x);
|
2016-12-18 21:41:37 -08:00
|
|
|
}
|
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
fn first4KeysOfHomeRow() []const u8 {
|
2017-12-21 21:50:30 -08:00
|
|
|
return "aoeu";
|
2016-12-21 21:12:27 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "return string from function" {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
|
2016-12-21 21:12:27 -08:00
|
|
|
}
|
|
|
|
|
2018-04-30 17:35:54 -07:00
|
|
|
const g1: i32 = 1233 + 1;
|
|
|
|
var g2: i32 = 0;
|
2016-12-21 22:20:08 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "global variables" {
|
2016-12-21 22:20:08 -08:00
|
|
|
assert(g2 == 0);
|
|
|
|
g2 = g1;
|
|
|
|
assert(g2 == 1234);
|
2016-12-21 21:20:14 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "memcpy and memset intrinsics" {
|
2018-04-30 17:35:54 -07:00
|
|
|
var foo: [20]u8 = undefined;
|
|
|
|
var bar: [20]u8 = undefined;
|
2016-12-21 22:42:30 -08:00
|
|
|
|
2018-06-03 22:09:15 -07:00
|
|
|
@memset(foo[0..].ptr, 'A', foo.len);
|
|
|
|
@memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
|
2016-12-21 22:42:30 -08:00
|
|
|
|
2017-03-26 01:58:48 -07:00
|
|
|
if (bar[11] != 'A') unreachable;
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "builtin static eval" {
|
2018-04-30 17:35:54 -07:00
|
|
|
const x: i32 = comptime x: {
|
|
|
|
break :x 1 + 2 + 3;
|
|
|
|
};
|
2017-01-22 20:20:53 -08:00
|
|
|
assert(x == comptime 6);
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2017-03-16 13:02:35 -07:00
|
|
|
test "slicing" {
|
2018-04-30 17:35:54 -07:00
|
|
|
var array: [20]i32 = undefined;
|
2016-12-21 22:42:30 -08:00
|
|
|
|
|
|
|
array[5] = 1234;
|
|
|
|
|
2017-05-19 07:39:59 -07:00
|
|
|
var slice = array[5..10];
|
2016-12-21 22:42:30 -08:00
|
|
|
|
2017-03-26 01:58:48 -07:00
|
|
|
if (slice.len != 5) unreachable;
|
2016-12-21 22:42:30 -08:00
|
|
|
|
|
|
|
const ptr = &slice[0];
|
2018-06-03 22:09:15 -07:00
|
|
|
if (ptr.* != 1234) unreachable;
|
2016-12-21 22:42:30 -08:00
|
|
|
|
2017-05-19 07:39:59 -07:00
|
|
|
var slice_rest = array[10..];
|
2017-03-26 01:58:48 -07:00
|
|
|
if (slice_rest.len != 10) unreachable;
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "constant equal function pointers" {
|
2016-12-21 22:42:30 -08:00
|
|
|
const alias = emptyFn;
|
2018-04-30 17:35:54 -07:00
|
|
|
assert(comptime x: {
|
|
|
|
break :x emptyFn == alias;
|
|
|
|
});
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
fn emptyFn() void {}
|
2016-12-21 22:42:30 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "hex escape" {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "string concatenation" {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "array mult operator" {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, "ab" ** 5, "ababababab"));
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "string escapes" {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, "\"", "\x22"));
|
|
|
|
assert(mem.eql(u8, "\'", "\x27"));
|
|
|
|
assert(mem.eql(u8, "\n", "\x0a"));
|
|
|
|
assert(mem.eql(u8, "\r", "\x0d"));
|
|
|
|
assert(mem.eql(u8, "\t", "\x09"));
|
|
|
|
assert(mem.eql(u8, "\\", "\x5c"));
|
|
|
|
assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
|
2016-12-21 22:42:30 -08:00
|
|
|
}
|
2016-12-21 22:20:08 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "multiline string" {
|
2018-05-28 17:23:55 -07:00
|
|
|
const s1 =
|
2016-12-22 07:09:53 -08:00
|
|
|
\\one
|
|
|
|
\\two)
|
|
|
|
\\three
|
|
|
|
;
|
|
|
|
const s2 = "one\ntwo)\nthree";
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, s1, s2));
|
2016-12-22 07:09:53 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "multiline C string" {
|
2018-05-28 17:23:55 -07:00
|
|
|
const s1 =
|
2016-12-22 07:39:10 -08:00
|
|
|
c\\one
|
|
|
|
c\\two)
|
|
|
|
c\\three
|
|
|
|
;
|
|
|
|
const s2 = c"one\ntwo)\nthree";
|
2017-01-05 00:57:48 -08:00
|
|
|
assert(cstr.cmp(s1, s2) == 0);
|
2016-12-22 07:39:10 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "type equality" {
|
2018-05-31 07:56:59 -07:00
|
|
|
assert(*const u8 != *u8);
|
2016-12-22 07:39:10 -08:00
|
|
|
}
|
2016-12-21 22:20:08 -08:00
|
|
|
|
2016-12-25 01:15:23 -08:00
|
|
|
const global_a: i32 = 1234;
|
2018-05-31 07:56:59 -07:00
|
|
|
const global_b: *const i32 = &global_a;
|
|
|
|
const global_c: *const f32 = @ptrCast(*const f32, global_b);
|
2017-05-07 15:09:45 -07:00
|
|
|
test "compile time global reinterpret" {
|
2018-05-31 07:56:59 -07:00
|
|
|
const d = @ptrCast(*const i32, global_c);
|
2018-04-30 17:35:54 -07:00
|
|
|
assert(d.* == 1234);
|
2016-12-25 01:15:23 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "explicit cast maybe pointers" {
|
2018-05-31 07:56:59 -07:00
|
|
|
const a: ?*i32 = undefined;
|
|
|
|
const b: ?*f32 = @ptrCast(?*f32, a);
|
2016-12-25 23:53:42 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "generic malloc free" {
|
2018-01-08 21:07:01 -08:00
|
|
|
const a = memAlloc(u8, 10) catch unreachable;
|
2016-12-26 00:02:20 -08:00
|
|
|
memFree(u8, a);
|
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
var some_mem: [100]u8 = undefined;
|
2018-02-02 11:26:14 -08:00
|
|
|
fn memAlloc(comptime T: type, n: usize) error![]T {
|
2018-06-04 19:11:14 -07:00
|
|
|
return @ptrCast([*]T, &some_mem[0])[0..n];
|
2016-12-26 00:02:20 -08:00
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
fn memFree(comptime T: type, memory: []T) void {}
|
2016-12-26 00:02:20 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "cast undefined" {
|
2016-12-26 00:05:33 -08:00
|
|
|
const array: [100]u8 = undefined;
|
2017-02-12 14:22:35 -08:00
|
|
|
const slice = ([]const u8)(array);
|
2016-12-26 00:05:33 -08:00
|
|
|
testCastUndefined(slice);
|
|
|
|
}
|
2018-01-25 01:10:11 -08:00
|
|
|
fn testCastUndefined(x: []const u8) void {}
|
2016-12-26 00:05:33 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "cast small unsigned to larger signed" {
|
2016-12-26 00:05:33 -08:00
|
|
|
assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
|
|
|
|
assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
|
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
|
|
|
|
return x;
|
|
|
|
}
|
2016-12-26 00:05:33 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "implicit cast after unreachable" {
|
2016-12-26 00:05:33 -08:00
|
|
|
assert(outer() == 1234);
|
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
fn inner() i32 {
|
|
|
|
return 1234;
|
|
|
|
}
|
2018-01-25 01:10:11 -08:00
|
|
|
fn outer() i64 {
|
2016-12-26 00:05:33 -08:00
|
|
|
return inner();
|
|
|
|
}
|
2016-12-26 00:02:20 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "pointer dereferencing" {
|
2016-12-26 00:44:59 -08:00
|
|
|
var x = i32(3);
|
|
|
|
const y = &x;
|
|
|
|
|
2018-04-30 17:35:54 -07:00
|
|
|
y.* += 1;
|
2016-12-26 00:44:59 -08:00
|
|
|
|
|
|
|
assert(x == 4);
|
2018-04-30 17:35:54 -07:00
|
|
|
assert(y.* == 4);
|
2016-12-26 00:44:59 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "call result of if else expression" {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, f2(true), "a"));
|
|
|
|
assert(mem.eql(u8, f2(false), "b"));
|
2016-12-26 00:44:59 -08:00
|
|
|
}
|
2018-01-25 01:10:11 -08:00
|
|
|
fn f2(x: bool) []const u8 {
|
2016-12-26 00:44:59 -08:00
|
|
|
return (if (x) fA else fB)();
|
|
|
|
}
|
2018-04-30 17:35:54 -07:00
|
|
|
fn fA() []const u8 {
|
|
|
|
return "a";
|
|
|
|
}
|
|
|
|
fn fB() []const u8 {
|
|
|
|
return "b";
|
|
|
|
}
|
2016-12-26 00:44:59 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "const expression eval handling of variables" {
|
2016-12-26 00:44:59 -08:00
|
|
|
var x = true;
|
|
|
|
while (x) {
|
|
|
|
x = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "constant enum initialization with differing sizes" {
|
2016-12-26 00:44:59 -08:00
|
|
|
test3_1(test3_foo);
|
|
|
|
test3_2(test3_bar);
|
|
|
|
}
|
2017-12-03 17:43:56 -08:00
|
|
|
const Test3Foo = union(enum) {
|
|
|
|
One: void,
|
2016-12-26 00:44:59 -08:00
|
|
|
Two: f32,
|
|
|
|
Three: Test3Point,
|
|
|
|
};
|
|
|
|
const Test3Point = struct {
|
|
|
|
x: i32,
|
|
|
|
y: i32,
|
|
|
|
};
|
2018-05-28 17:23:55 -07:00
|
|
|
const test3_foo = Test3Foo{
|
|
|
|
.Three = Test3Point{
|
2018-04-30 17:35:54 -07:00
|
|
|
.x = 3,
|
|
|
|
.y = 4,
|
|
|
|
},
|
|
|
|
};
|
2018-05-28 17:23:55 -07:00
|
|
|
const test3_bar = Test3Foo{ .Two = 13 };
|
2018-05-31 07:56:59 -07:00
|
|
|
fn test3_1(f: *const Test3Foo) void {
|
2018-04-30 17:35:54 -07:00
|
|
|
switch (f.*) {
|
2016-12-26 00:44:59 -08:00
|
|
|
Test3Foo.Three => |pt| {
|
|
|
|
assert(pt.x == 3);
|
|
|
|
assert(pt.y == 4);
|
|
|
|
},
|
2017-03-26 01:58:48 -07:00
|
|
|
else => unreachable,
|
2016-12-26 00:44:59 -08:00
|
|
|
}
|
|
|
|
}
|
2018-05-31 07:56:59 -07:00
|
|
|
fn test3_2(f: *const Test3Foo) void {
|
2018-04-30 17:35:54 -07:00
|
|
|
switch (f.*) {
|
2016-12-26 00:44:59 -08:00
|
|
|
Test3Foo.Two => |x| {
|
|
|
|
assert(x == 13);
|
|
|
|
},
|
2017-03-26 01:58:48 -07:00
|
|
|
else => unreachable,
|
2016-12-26 00:44:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "character literals" {
|
2016-12-26 00:44:59 -08:00
|
|
|
assert('\'' == single_quote);
|
|
|
|
}
|
|
|
|
const single_quote = '\'';
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "take address of parameter" {
|
2016-12-26 00:44:59 -08:00
|
|
|
testTakeAddressOfParameter(12.34);
|
|
|
|
}
|
2018-01-25 01:10:11 -08:00
|
|
|
fn testTakeAddressOfParameter(f: f32) void {
|
2016-12-26 00:44:59 -08:00
|
|
|
const f_ptr = &f;
|
2018-04-30 17:35:54 -07:00
|
|
|
assert(f_ptr.* == 12.34);
|
2016-12-26 00:44:59 -08:00
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "pointer comparison" {
|
2017-02-12 14:22:35 -08:00
|
|
|
const a = ([]const u8)("a");
|
2016-12-26 12:49:03 -08:00
|
|
|
const b = &a;
|
|
|
|
assert(ptrEql(b, b));
|
|
|
|
}
|
2018-05-31 07:56:59 -07:00
|
|
|
fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
|
2017-12-21 21:50:30 -08:00
|
|
|
return a == b;
|
2016-12-26 12:49:03 -08:00
|
|
|
}
|
2016-12-26 00:44:59 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "C string concatenation" {
|
2016-12-26 13:04:14 -08:00
|
|
|
const a = c"OK" ++ c" IT " ++ c"WORKED";
|
|
|
|
const b = c"OK IT WORKED";
|
|
|
|
|
2017-01-05 00:57:48 -08:00
|
|
|
const len = cstr.len(b);
|
2016-12-26 13:04:14 -08:00
|
|
|
const len_with_null = len + 1;
|
2018-04-30 17:35:54 -07:00
|
|
|
{
|
|
|
|
var i: u32 = 0;
|
|
|
|
while (i < len_with_null) : (i += 1) {
|
|
|
|
assert(a[i] == b[i]);
|
|
|
|
}
|
|
|
|
}
|
2016-12-26 13:04:14 -08:00
|
|
|
assert(a[len] == 0);
|
|
|
|
assert(b[len] == 0);
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "cast slice to u8 slice" {
|
2016-12-26 14:11:36 -08:00
|
|
|
assert(@sizeOf(i32) == 4);
|
2018-05-28 17:23:55 -07:00
|
|
|
var big_thing_array = []i32{
|
2018-04-30 17:35:54 -07:00
|
|
|
1,
|
|
|
|
2,
|
|
|
|
3,
|
|
|
|
4,
|
|
|
|
};
|
2017-05-19 07:39:59 -07:00
|
|
|
const big_thing_slice: []i32 = big_thing_array[0..];
|
2016-12-26 14:11:36 -08:00
|
|
|
const bytes = ([]u8)(big_thing_slice);
|
|
|
|
assert(bytes.len == 4 * 4);
|
|
|
|
bytes[4] = 0;
|
|
|
|
bytes[5] = 0;
|
|
|
|
bytes[6] = 0;
|
|
|
|
bytes[7] = 0;
|
|
|
|
assert(big_thing_slice[1] == 0);
|
2017-08-30 01:54:33 -07:00
|
|
|
const big_thing_again = ([]align(1) i32)(bytes);
|
2016-12-26 14:11:36 -08:00
|
|
|
assert(big_thing_again[2] == 3);
|
|
|
|
big_thing_again[2] = -1;
|
|
|
|
assert(bytes[8] == @maxValue(u8));
|
|
|
|
assert(bytes[9] == @maxValue(u8));
|
|
|
|
assert(bytes[10] == @maxValue(u8));
|
|
|
|
assert(bytes[11] == @maxValue(u8));
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "pointer to void return type" {
|
2018-01-08 21:07:01 -08:00
|
|
|
testPointerToVoidReturnType() catch unreachable;
|
2016-12-27 22:31:46 -08:00
|
|
|
}
|
2018-02-02 11:26:14 -08:00
|
|
|
fn testPointerToVoidReturnType() error!void {
|
2016-12-27 22:31:46 -08:00
|
|
|
const a = testPointerToVoidReturnType2();
|
2018-04-30 17:35:54 -07:00
|
|
|
return a.*;
|
2016-12-27 22:31:46 -08:00
|
|
|
}
|
|
|
|
const test_pointer_to_void_return_type_x = void{};
|
2018-05-31 07:56:59 -07:00
|
|
|
fn testPointerToVoidReturnType2() *const void {
|
2016-12-27 22:31:46 -08:00
|
|
|
return &test_pointer_to_void_return_type_x;
|
|
|
|
}
|
2017-01-05 15:50:36 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "non const ptr to aliased type" {
|
2017-01-05 15:50:36 -08:00
|
|
|
const int = i32;
|
2018-05-31 07:56:59 -07:00
|
|
|
assert(?*int == ?*i32);
|
2017-01-05 15:50:36 -08:00
|
|
|
}
|
2017-01-16 09:42:46 -08:00
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "array 2D const double ptr" {
|
2018-05-28 17:23:55 -07:00
|
|
|
const rect_2d_vertexes = [][1]f32{
|
|
|
|
[]f32{1.0},
|
|
|
|
[]f32{2.0},
|
2017-01-16 09:42:46 -08:00
|
|
|
};
|
|
|
|
testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
|
|
|
|
}
|
|
|
|
|
2018-05-31 07:56:59 -07:00
|
|
|
fn testArray2DConstDoublePtr(ptr: *const f32) void {
|
2018-06-03 22:09:15 -07:00
|
|
|
const ptr2 = @ptrCast([*]const f32, ptr);
|
|
|
|
assert(ptr2[0] == 1.0);
|
|
|
|
assert(ptr2[1] == 2.0);
|
2017-01-16 09:42:46 -08:00
|
|
|
}
|
2017-01-23 22:58:20 -08:00
|
|
|
|
2017-05-17 09:26:35 -07:00
|
|
|
const Tid = builtin.TypeId;
|
2018-04-30 17:35:54 -07:00
|
|
|
const AStruct = struct {
|
|
|
|
x: i32,
|
|
|
|
};
|
|
|
|
const AnEnum = enum {
|
|
|
|
One,
|
|
|
|
Two,
|
|
|
|
};
|
|
|
|
const AUnionEnum = union(enum) {
|
|
|
|
One: i32,
|
|
|
|
Two: void,
|
|
|
|
};
|
|
|
|
const AUnion = union {
|
|
|
|
One: void,
|
|
|
|
Two: void,
|
|
|
|
};
|
2017-01-23 22:58:20 -08:00
|
|
|
|
2017-05-17 09:26:35 -07:00
|
|
|
test "@typeId" {
|
2017-01-23 22:58:20 -08:00
|
|
|
comptime {
|
2017-05-17 09:26:35 -07:00
|
|
|
assert(@typeId(type) == Tid.Type);
|
|
|
|
assert(@typeId(void) == Tid.Void);
|
|
|
|
assert(@typeId(bool) == Tid.Bool);
|
|
|
|
assert(@typeId(noreturn) == Tid.NoReturn);
|
|
|
|
assert(@typeId(i8) == Tid.Int);
|
|
|
|
assert(@typeId(u8) == Tid.Int);
|
|
|
|
assert(@typeId(i64) == Tid.Int);
|
|
|
|
assert(@typeId(u64) == Tid.Int);
|
|
|
|
assert(@typeId(f32) == Tid.Float);
|
|
|
|
assert(@typeId(f64) == Tid.Float);
|
2018-05-31 07:56:59 -07:00
|
|
|
assert(@typeId(*f32) == Tid.Pointer);
|
2017-05-17 09:26:35 -07:00
|
|
|
assert(@typeId([2]u8) == Tid.Array);
|
|
|
|
assert(@typeId(AStruct) == Tid.Struct);
|
2018-06-05 02:14:43 -07:00
|
|
|
assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
|
|
|
|
assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
|
2018-06-05 02:54:11 -07:00
|
|
|
assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
|
2018-06-05 02:30:01 -07:00
|
|
|
assert(@typeId(@typeOf(null)) == Tid.Null);
|
2017-05-17 09:26:35 -07:00
|
|
|
assert(@typeId(?i32) == Tid.Nullable);
|
2018-02-02 11:26:14 -08:00
|
|
|
assert(@typeId(error!i32) == Tid.ErrorUnion);
|
|
|
|
assert(@typeId(error) == Tid.ErrorSet);
|
2017-05-17 09:26:35 -07:00
|
|
|
assert(@typeId(AnEnum) == Tid.Enum);
|
2017-12-03 17:43:56 -08:00
|
|
|
assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
|
|
|
|
assert(@typeId(AUnionEnum) == Tid.Union);
|
|
|
|
assert(@typeId(AUnion) == Tid.Union);
|
2018-05-30 13:09:11 -07:00
|
|
|
assert(@typeId(fn () void) == Tid.Fn);
|
2017-05-17 09:26:35 -07:00
|
|
|
assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
|
2018-04-30 17:35:54 -07:00
|
|
|
assert(@typeId(@typeOf(x: {
|
|
|
|
break :x this;
|
|
|
|
})) == Tid.Block);
|
2017-05-17 09:26:35 -07:00
|
|
|
// TODO bound fn
|
|
|
|
// TODO arg tuple
|
|
|
|
// TODO opaque
|
2017-01-23 22:58:20 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "@canImplicitCast" {
|
2017-01-23 22:58:20 -08:00
|
|
|
comptime {
|
|
|
|
assert(@canImplicitCast(i64, i32(3)));
|
|
|
|
assert(!@canImplicitCast(i32, f32(1.234)));
|
|
|
|
assert(@canImplicitCast([]const u8, "aoeu"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "@typeName" {
|
2018-04-30 17:35:54 -07:00
|
|
|
const Struct = struct {};
|
2018-02-22 08:53:58 -08:00
|
|
|
const Union = union {
|
|
|
|
unused: u8,
|
|
|
|
};
|
|
|
|
const Enum = enum {
|
|
|
|
Unused,
|
|
|
|
};
|
2017-01-23 22:58:20 -08:00
|
|
|
comptime {
|
2017-02-12 14:22:35 -08:00
|
|
|
assert(mem.eql(u8, @typeName(i64), "i64"));
|
2018-05-31 07:56:59 -07:00
|
|
|
assert(mem.eql(u8, @typeName(*usize), "*usize"));
|
2018-05-24 18:27:44 -07:00
|
|
|
// https://github.com/ziglang/zig/issues/675
|
2018-02-22 08:53:58 -08:00
|
|
|
assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
|
|
|
|
assert(mem.eql(u8, @typeName(Struct), "Struct"));
|
|
|
|
assert(mem.eql(u8, @typeName(Union), "Union"));
|
|
|
|
assert(mem.eql(u8, @typeName(Enum), "Enum"));
|
2017-01-23 22:58:20 -08:00
|
|
|
}
|
|
|
|
}
|
2017-02-04 18:49:27 -08:00
|
|
|
|
2018-02-22 08:53:58 -08:00
|
|
|
fn TypeFromFn(comptime T: type) type {
|
|
|
|
return struct {};
|
|
|
|
}
|
|
|
|
|
2017-05-07 15:09:45 -07:00
|
|
|
test "volatile load and store" {
|
2017-02-04 18:49:27 -08:00
|
|
|
var number: i32 = 1234;
|
2018-05-31 07:56:59 -07:00
|
|
|
const ptr = (*volatile i32)(&number);
|
2018-04-30 17:35:54 -07:00
|
|
|
ptr.* += 1;
|
|
|
|
assert(ptr.* == 1235);
|
2017-02-04 18:49:27 -08:00
|
|
|
}
|
2017-04-30 09:21:24 -07:00
|
|
|
|
|
|
|
test "slice string literal has type []const u8" {
|
|
|
|
comptime {
|
2017-05-19 07:39:59 -07:00
|
|
|
assert(@typeOf("aoeu"[0..]) == []const u8);
|
2018-05-28 17:23:55 -07:00
|
|
|
const array = []i32{
|
2018-04-30 17:35:54 -07:00
|
|
|
1,
|
|
|
|
2,
|
|
|
|
3,
|
|
|
|
4,
|
|
|
|
};
|
2017-05-19 07:39:59 -07:00
|
|
|
assert(@typeOf(array[0..]) == []const i32);
|
2017-04-30 09:21:24 -07:00
|
|
|
}
|
|
|
|
}
|
2017-05-07 15:09:45 -07:00
|
|
|
|
|
|
|
test "global variable initialized to global variable array element" {
|
|
|
|
assert(global_ptr == &gdt[0]);
|
|
|
|
}
|
|
|
|
const GDTEntry = struct {
|
|
|
|
field: i32,
|
|
|
|
};
|
2018-05-28 17:23:55 -07:00
|
|
|
var gdt = []GDTEntry{
|
|
|
|
GDTEntry{ .field = 1 },
|
|
|
|
GDTEntry{ .field = 2 },
|
2017-05-07 15:09:45 -07:00
|
|
|
};
|
|
|
|
var global_ptr = &gdt[0];
|
2017-05-29 11:25:00 -07:00
|
|
|
|
|
|
|
// can't really run this test but we can make sure it has no compile error
|
|
|
|
// and generates code
|
2018-06-04 19:11:14 -07:00
|
|
|
const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
|
2018-01-25 01:10:11 -08:00
|
|
|
export fn writeToVRam() void {
|
2017-05-29 11:25:00 -07:00
|
|
|
vram[0] = 'X';
|
|
|
|
}
|
2017-08-29 21:17:11 -07:00
|
|
|
|
|
|
|
test "pointer child field" {
|
2018-05-31 07:56:59 -07:00
|
|
|
assert((*u32).Child == u32);
|
2017-08-29 21:17:11 -07:00
|
|
|
}
|
2017-09-05 15:51:07 -07:00
|
|
|
|
|
|
|
const OpaqueA = @OpaqueType();
|
|
|
|
const OpaqueB = @OpaqueType();
|
|
|
|
test "@OpaqueType" {
|
2018-05-31 07:56:59 -07:00
|
|
|
assert(*OpaqueA != *OpaqueB);
|
2017-09-05 15:51:07 -07:00
|
|
|
assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
|
|
|
|
assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
|
|
|
|
}
|
2017-09-09 21:34:44 -07:00
|
|
|
|
|
|
|
test "variable is allowed to be a pointer to an opaque type" {
|
|
|
|
var x: i32 = 1234;
|
2018-05-31 07:56:59 -07:00
|
|
|
_ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
|
2017-09-09 21:34:44 -07:00
|
|
|
}
|
2018-05-31 07:56:59 -07:00
|
|
|
fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
|
2017-09-09 21:34:44 -07:00
|
|
|
var a = ptr;
|
|
|
|
return a;
|
|
|
|
}
|
2018-01-02 17:52:24 -08:00
|
|
|
|
|
|
|
test "comptime if inside runtime while which unconditionally breaks" {
|
|
|
|
testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
|
|
|
|
comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
|
|
|
|
}
|
2018-01-25 01:10:11 -08:00
|
|
|
fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
|
2018-01-02 17:52:24 -08:00
|
|
|
while (cond) {
|
2018-04-30 17:35:54 -07:00
|
|
|
if (false) {}
|
2018-01-02 17:52:24 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-01-03 00:15:06 -08:00
|
|
|
|
|
|
|
test "implicit comptime while" {
|
|
|
|
while (false) {
|
|
|
|
@compileError("bad");
|
|
|
|
}
|
|
|
|
}
|
2018-01-06 21:20:26 -08:00
|
|
|
|
|
|
|
test "struct inside function" {
|
|
|
|
testStructInFn();
|
|
|
|
comptime testStructInFn();
|
|
|
|
}
|
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
fn testStructInFn() void {
|
2018-01-06 21:20:26 -08:00
|
|
|
const BlockKind = u32;
|
|
|
|
|
|
|
|
const Block = struct {
|
|
|
|
kind: BlockKind,
|
|
|
|
};
|
|
|
|
|
2018-05-28 17:23:55 -07:00
|
|
|
var block = Block{ .kind = 1234 };
|
2018-01-06 21:20:26 -08:00
|
|
|
|
|
|
|
block.kind += 1;
|
|
|
|
|
|
|
|
assert(block.kind == 1235);
|
|
|
|
}
|
2018-01-06 21:50:43 -08:00
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
fn fnThatClosesOverLocalConst() type {
|
2018-01-06 21:50:43 -08:00
|
|
|
const c = 1;
|
|
|
|
return struct {
|
2018-04-30 17:35:54 -07:00
|
|
|
fn g() i32 {
|
|
|
|
return c;
|
|
|
|
}
|
2018-01-06 21:50:43 -08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
test "function closes over local const" {
|
|
|
|
const x = fnThatClosesOverLocalConst().g();
|
|
|
|
assert(x == 1);
|
|
|
|
}
|
2018-01-22 19:24:07 -08:00
|
|
|
|
|
|
|
test "cold function" {
|
|
|
|
thisIsAColdFn();
|
|
|
|
comptime thisIsAColdFn();
|
|
|
|
}
|
|
|
|
|
2018-01-25 01:10:11 -08:00
|
|
|
fn thisIsAColdFn() void {
|
2018-01-22 19:24:07 -08:00
|
|
|
@setCold(true);
|
|
|
|
}
|
2018-01-29 07:57:09 -08:00
|
|
|
|
2018-04-30 17:35:54 -07:00
|
|
|
const PackedStruct = packed struct {
|
|
|
|
a: u8,
|
|
|
|
b: u8,
|
|
|
|
};
|
|
|
|
const PackedUnion = packed union {
|
|
|
|
a: u8,
|
|
|
|
b: u32,
|
|
|
|
};
|
|
|
|
const PackedEnum = packed enum {
|
|
|
|
A,
|
|
|
|
B,
|
|
|
|
};
|
2018-01-29 07:57:09 -08:00
|
|
|
|
|
|
|
test "packed struct, enum, union parameters in extern function" {
|
2018-05-28 17:23:55 -07:00
|
|
|
testPackedStuff(PackedStruct{
|
2018-04-30 17:35:54 -07:00
|
|
|
.a = 1,
|
|
|
|
.b = 2,
|
2018-05-28 17:23:55 -07:00
|
|
|
}, PackedUnion{ .a = 1 }, PackedEnum.A);
|
2018-01-29 07:57:09 -08:00
|
|
|
}
|
2018-03-06 14:19:45 -08:00
|
|
|
|
2018-05-31 07:56:59 -07:00
|
|
|
export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
|
2018-03-06 14:19:45 -08:00
|
|
|
|
|
|
|
test "slicing zero length array" {
|
|
|
|
const s1 = ""[0..];
|
|
|
|
const s2 = ([]u32{})[0..];
|
|
|
|
assert(s1.len == 0);
|
|
|
|
assert(s2.len == 0);
|
|
|
|
assert(mem.eql(u8, s1, ""));
|
|
|
|
assert(mem.eql(u32, s2, []u32{}));
|
|
|
|
}
|
2018-03-13 16:13:10 -07:00
|
|
|
|
2018-05-31 07:56:59 -07:00
|
|
|
const addr1 = @ptrCast(*const u8, emptyFn);
|
2018-03-13 16:13:10 -07:00
|
|
|
test "comptime cast fn to ptr" {
|
2018-05-31 07:56:59 -07:00
|
|
|
const addr2 = @ptrCast(*const u8, emptyFn);
|
2018-03-13 16:13:10 -07:00
|
|
|
comptime assert(addr1 == addr2);
|
|
|
|
}
|