mirror of
https://github.com/ziglang/zig.git
synced 2024-12-04 02:48:50 +00:00
f1e5be9686
add error when `%return` shows up in a function with incorrect return type
1659 lines
32 KiB
Zig
1659 lines
32 KiB
Zig
const std = @import("std");
|
|
const assert = std.assert;
|
|
const str = std.str;
|
|
const cstr = std.cstr;
|
|
const other = @import("other.zig");
|
|
|
|
#attribute("test")
|
|
fn empty_function() {}
|
|
|
|
|
|
|
|
/**
|
|
* multi line doc comment
|
|
*/
|
|
/// this is a documentation comment
|
|
/// doc comment line 2
|
|
#attribute("test")
|
|
fn comments() {
|
|
comments_f1(/* mid-line comment /* nested */ */ "OK\n");
|
|
}
|
|
|
|
fn comments_f1(s: []u8) {}
|
|
|
|
|
|
#attribute("test")
|
|
fn if_statements() {
|
|
should_be_equal(1, 1);
|
|
first_eql_third(2, 1, 2);
|
|
}
|
|
fn should_be_equal(a: i32, b: i32) {
|
|
if (a != b) {
|
|
unreachable{};
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
fn first_eql_third(a: i32, b: i32, c: i32) {
|
|
if (a == b) {
|
|
unreachable{};
|
|
} else if (b == c) {
|
|
unreachable{};
|
|
} else if (a == c) {
|
|
return;
|
|
} else {
|
|
unreachable{};
|
|
}
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn params() {
|
|
assert(test_params_add(22, 11) == 33);
|
|
}
|
|
fn test_params_add(a: i32, b: i32) -> i32 {
|
|
a + b
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn local_variables() {
|
|
test_loc_vars(2);
|
|
}
|
|
fn test_loc_vars(b: i32) {
|
|
const a: i32 = 1;
|
|
if (a + b != 3) unreachable{};
|
|
}
|
|
|
|
#attribute("test")
|
|
fn bool_literals() {
|
|
assert(true);
|
|
assert(!false);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn void_parameters() {
|
|
void_fun(1, void{}, 2, {});
|
|
}
|
|
fn void_fun(a : i32, b : void, c : i32, d : void) {
|
|
const v = b;
|
|
const vv : void = if (a == 1) {v} else {};
|
|
assert(a + c == 3);
|
|
return vv;
|
|
}
|
|
|
|
#attribute("test")
|
|
fn mutable_local_variables() {
|
|
var zero : i32 = 0;
|
|
assert(zero == 0);
|
|
|
|
var i = i32(0);
|
|
while (i != 3) {
|
|
i += 1;
|
|
}
|
|
assert(i == 3);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn arrays() {
|
|
var array : [5]i32 = undefined;
|
|
|
|
var i : i32 = 0;
|
|
while (i < 5) {
|
|
array[i] = i + 1;
|
|
i = array[i];
|
|
}
|
|
|
|
i = 0;
|
|
var accumulator = i32(0);
|
|
while (i < 5) {
|
|
accumulator += array[i];
|
|
|
|
i += 1;
|
|
}
|
|
|
|
assert(accumulator == 15);
|
|
assert(get_array_len(array) == 5);
|
|
}
|
|
fn get_array_len(a: []i32) -> isize {
|
|
a.len
|
|
}
|
|
|
|
#attribute("test")
|
|
fn short_circuit() {
|
|
var hit_1 = false;
|
|
var hit_2 = false;
|
|
var hit_3 = false;
|
|
var hit_4 = false;
|
|
|
|
if (true || {assert_runtime(false); false}) {
|
|
hit_1 = true;
|
|
}
|
|
if (false || { hit_2 = true; false }) {
|
|
assert_runtime(false);
|
|
}
|
|
|
|
if (true && { hit_3 = true; false }) {
|
|
assert_runtime(false);
|
|
}
|
|
if (false && {assert_runtime(false); false}) {
|
|
assert_runtime(false);
|
|
} else {
|
|
hit_4 = true;
|
|
}
|
|
assert(hit_1);
|
|
assert(hit_2);
|
|
assert(hit_3);
|
|
assert(hit_4);
|
|
}
|
|
|
|
#static_eval_enable(false)
|
|
fn assert_runtime(b: bool) {
|
|
if (!b) unreachable{}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn modify_operators() {
|
|
var i : i32 = 0;
|
|
i += 5; assert(i == 5);
|
|
i -= 2; assert(i == 3);
|
|
i *= 20; assert(i == 60);
|
|
i /= 3; assert(i == 20);
|
|
i %= 11; assert(i == 9);
|
|
i <<= 1; assert(i == 18);
|
|
i >>= 2; assert(i == 4);
|
|
i = 6;
|
|
i &= 5; assert(i == 4);
|
|
i ^= 6; assert(i == 2);
|
|
i = 6;
|
|
i |= 3; assert(i == 7);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn separate_block_scopes() {
|
|
{
|
|
const no_conflict : i32 = 5;
|
|
assert(no_conflict == 5);
|
|
}
|
|
|
|
const c = {
|
|
const no_conflict = i32(10);
|
|
no_conflict
|
|
};
|
|
assert(c == 10);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn void_struct_fields() {
|
|
const foo = VoidStructFieldsFoo {
|
|
.a = void{},
|
|
.b = 1,
|
|
.c = void{},
|
|
};
|
|
assert(foo.b == 1);
|
|
assert(@sizeof(VoidStructFieldsFoo) == 4);
|
|
}
|
|
struct VoidStructFieldsFoo {
|
|
a : void,
|
|
b : i32,
|
|
c : void,
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
pub fn structs() {
|
|
var foo : StructFoo = undefined;
|
|
@memset(&foo, 0, @sizeof(StructFoo));
|
|
foo.a += 1;
|
|
foo.b = foo.a == 1;
|
|
test_foo(foo);
|
|
test_mutation(&foo);
|
|
assert(foo.c == 100);
|
|
}
|
|
struct StructFoo {
|
|
a : i32,
|
|
b : bool,
|
|
c : f32,
|
|
}
|
|
fn test_foo(foo : StructFoo) {
|
|
assert(foo.b);
|
|
}
|
|
fn test_mutation(foo : &StructFoo) {
|
|
foo.c = 100;
|
|
}
|
|
struct Node {
|
|
val: Val,
|
|
next: &Node,
|
|
}
|
|
|
|
struct Val {
|
|
x: i32,
|
|
}
|
|
|
|
#attribute("test")
|
|
fn struct_point_to_self() {
|
|
var root : Node = undefined;
|
|
root.val.x = 1;
|
|
|
|
var node : Node = undefined;
|
|
node.next = &root;
|
|
node.val.x = 2;
|
|
|
|
root.next = &node;
|
|
|
|
assert(node.next.next.next.val.x == 1);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn struct_byval_assign() {
|
|
var foo1 : StructFoo = undefined;
|
|
var foo2 : StructFoo = undefined;
|
|
|
|
foo1.a = 1234;
|
|
foo2.a = 0;
|
|
assert(foo2.a == 0);
|
|
foo2 = foo1;
|
|
assert(foo2.a == 1234);
|
|
}
|
|
|
|
fn struct_initializer() {
|
|
const val = Val { .x = 42 };
|
|
assert(val.x == 42);
|
|
}
|
|
|
|
|
|
const g1 : i32 = 1233 + 1;
|
|
var g2 : i32 = 0;
|
|
|
|
#attribute("test")
|
|
fn global_variables() {
|
|
assert(g2 == 0);
|
|
g2 = g1;
|
|
assert(g2 == 1234);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn while_loop() {
|
|
var i : i32 = 0;
|
|
while (i < 4) {
|
|
i += 1;
|
|
}
|
|
assert(i == 4);
|
|
assert(while_loop_1() == 1);
|
|
}
|
|
fn while_loop_1() -> i32 {
|
|
return while_loop_2();
|
|
}
|
|
fn while_loop_2() -> i32 {
|
|
while (true) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn void_arrays() {
|
|
var array: [4]void = undefined;
|
|
array[0] = void{};
|
|
array[1] = array[2];
|
|
assert(@sizeof(@typeof(array)) == 0);
|
|
assert(array.len == 4);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn three_expr_in_a_row() {
|
|
assert_false(false || false || false);
|
|
assert_false(true && true && false);
|
|
assert_false(1 | 2 | 4 != 7);
|
|
assert_false(3 ^ 6 ^ 8 != 13);
|
|
assert_false(7 & 14 & 28 != 4);
|
|
assert_false(9 << 1 << 2 != 9 << 3);
|
|
assert_false(90 >> 1 >> 2 != 90 >> 3);
|
|
assert_false(100 - 1 + 1000 != 1099);
|
|
assert_false(5 * 4 / 2 % 3 != 1);
|
|
assert_false(i32(i32(5)) != 5);
|
|
assert_false(!!false);
|
|
assert_false(i32(7) != --(i32(7)));
|
|
}
|
|
fn assert_false(b: bool) {
|
|
assert(!b);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn maybe_type() {
|
|
const x : ?bool = true;
|
|
|
|
if (const y ?= x) {
|
|
if (y) {
|
|
// OK
|
|
} else {
|
|
unreachable{};
|
|
}
|
|
} else {
|
|
unreachable{};
|
|
}
|
|
|
|
const next_x : ?i32 = null;
|
|
|
|
const z = next_x ?? 1234;
|
|
|
|
assert(z == 1234);
|
|
|
|
const final_x : ?i32 = 13;
|
|
|
|
const num = final_x ?? unreachable{};
|
|
|
|
assert(num == 13);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn enum_type() {
|
|
const foo1 = EnumTypeFoo.One {13};
|
|
const foo2 = EnumTypeFoo.Two {EnumType { .x = 1234, .y = 5678, }};
|
|
const bar = EnumTypeBar.B;
|
|
|
|
assert(bar == EnumTypeBar.B);
|
|
assert(@member_count(EnumTypeFoo) == 3);
|
|
assert(@member_count(EnumTypeBar) == 4);
|
|
const expected_foo_size = switch (@compile_var("arch")) {
|
|
i386 => 20,
|
|
x86_64 => 24,
|
|
else => unreachable{},
|
|
};
|
|
assert(@sizeof(EnumTypeFoo) == expected_foo_size);
|
|
assert(@sizeof(EnumTypeBar) == 1);
|
|
}
|
|
struct EnumType {
|
|
x: u64,
|
|
y: u64,
|
|
}
|
|
enum EnumTypeFoo {
|
|
One: i32,
|
|
Two: EnumType,
|
|
Three: void,
|
|
}
|
|
enum EnumTypeBar {
|
|
A,
|
|
B,
|
|
C,
|
|
D,
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn array_literal() {
|
|
const HEX_MULT = []u16{4096, 256, 16, 1};
|
|
|
|
assert(HEX_MULT.len == 4);
|
|
assert(HEX_MULT[1] == 256);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn const_number_literal() {
|
|
const one = 1;
|
|
const eleven = ten + one;
|
|
|
|
assert(eleven == 11);
|
|
}
|
|
const ten = 10;
|
|
|
|
|
|
#attribute("test")
|
|
fn error_values() {
|
|
const a = i32(error.err1);
|
|
const b = i32(error.err2);
|
|
assert(a != b);
|
|
}
|
|
error err1;
|
|
error err2;
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn fn_call_of_struct_field() {
|
|
assert(call_struct_field(Foo {.ptr = a_func,}) == 13);
|
|
}
|
|
|
|
struct Foo {
|
|
ptr: fn() -> i32,
|
|
}
|
|
|
|
fn a_func() -> i32 { 13 }
|
|
|
|
fn call_struct_field(foo: Foo) -> i32 {
|
|
return foo.ptr();
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn redefinition_of_error_values_allowed() {
|
|
should_be_not_equal(error.AnError, error.SecondError);
|
|
}
|
|
error AnError;
|
|
error AnError;
|
|
error SecondError;
|
|
fn should_be_not_equal(a: error, b: error) {
|
|
if (a == b) unreachable{}
|
|
}
|
|
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn constant_enum_with_payload() {
|
|
var empty = AnEnumWithPayload.Empty;
|
|
var full = AnEnumWithPayload.Full {13};
|
|
should_be_empty(empty);
|
|
should_be_not_empty(full);
|
|
}
|
|
|
|
fn should_be_empty(x: AnEnumWithPayload) {
|
|
switch (x) {
|
|
Empty => {},
|
|
else => unreachable{},
|
|
}
|
|
}
|
|
|
|
fn should_be_not_empty(x: AnEnumWithPayload) {
|
|
switch (x) {
|
|
Empty => unreachable{},
|
|
else => {},
|
|
}
|
|
}
|
|
|
|
enum AnEnumWithPayload {
|
|
Empty,
|
|
Full: i32,
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn continue_in_for_loop() {
|
|
const array = []i32 {1, 2, 3, 4, 5};
|
|
var sum : i32 = 0;
|
|
for (array) |x| {
|
|
sum += x;
|
|
if (x < 3) {
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if (sum != 6) unreachable{}
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn cast_bool_to_int() {
|
|
const t = true;
|
|
const f = false;
|
|
assert(i32(t) == i32(1));
|
|
assert(i32(f) == i32(0));
|
|
non_const_cast_bool_to_int(t, f);
|
|
}
|
|
|
|
fn non_const_cast_bool_to_int(t: bool, f: bool) {
|
|
assert(i32(t) == i32(1));
|
|
assert(i32(f) == i32(0));
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn switch_on_enum() {
|
|
const fruit = Fruit.Orange;
|
|
non_const_switch_on_enum(fruit);
|
|
}
|
|
enum Fruit {
|
|
Apple,
|
|
Orange,
|
|
Banana,
|
|
}
|
|
#static_eval_enable(false)
|
|
fn non_const_switch_on_enum(fruit: Fruit) {
|
|
switch (fruit) {
|
|
Apple => unreachable{},
|
|
Orange => {},
|
|
Banana => unreachable{},
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn switch_statement() {
|
|
non_const_switch(SwitchStatmentFoo.C);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn non_const_switch(foo: SwitchStatmentFoo) {
|
|
const val: i32 = switch (foo) {
|
|
A => 1,
|
|
B => 2,
|
|
C => 3,
|
|
D => 4,
|
|
};
|
|
if (val != 3) unreachable{};
|
|
}
|
|
enum SwitchStatmentFoo {
|
|
A,
|
|
B,
|
|
C,
|
|
D,
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn switch_prong_with_var() {
|
|
switch_prong_with_var_fn(SwitchProngWithVarEnum.One {13});
|
|
switch_prong_with_var_fn(SwitchProngWithVarEnum.Two {13.0});
|
|
switch_prong_with_var_fn(SwitchProngWithVarEnum.Meh);
|
|
}
|
|
enum SwitchProngWithVarEnum {
|
|
One: i32,
|
|
Two: f32,
|
|
Meh,
|
|
}
|
|
#static_eval_enable(false)
|
|
fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {
|
|
switch(a) {
|
|
One => |x| {
|
|
if (x != 13) unreachable{};
|
|
},
|
|
Two => |x| {
|
|
if (x != 13.0) unreachable{};
|
|
},
|
|
Meh => |x| {
|
|
const v: void = x;
|
|
},
|
|
}
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn err_return_in_assignment() {
|
|
%%do_err_return_in_assignment();
|
|
}
|
|
|
|
#static_eval_enable(false)
|
|
fn do_err_return_in_assignment() -> %void {
|
|
var x : i32 = undefined;
|
|
x = %return make_a_non_err();
|
|
}
|
|
|
|
fn make_a_non_err() -> %i32 {
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn rhs_maybe_unwrap_return() {
|
|
const x = ?true;
|
|
const y = x ?? return;
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn implicit_cast_fn_unreachable_return() {
|
|
wants_fn_with_void(fn_with_unreachable);
|
|
}
|
|
|
|
fn wants_fn_with_void(f: fn()) { }
|
|
|
|
fn fn_with_unreachable() -> unreachable {
|
|
unreachable {}
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn explicit_cast_maybe_pointers() {
|
|
const a: ?&i32 = undefined;
|
|
const b: ?&f32 = (?&f32)(a);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn const_expr_eval_on_single_expr_blocks() {
|
|
assert(const_expr_eval_on_single_expr_blocks_fn(1, true) == 3);
|
|
}
|
|
|
|
fn const_expr_eval_on_single_expr_blocks_fn(x: i32, b: bool) -> i32 {
|
|
const literal = 3;
|
|
|
|
const result = if (b) {
|
|
literal
|
|
} else {
|
|
x
|
|
};
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn builtin_const_eval() {
|
|
const x : i32 = @const_eval(1 + 2 + 3);
|
|
assert(x == @const_eval(6));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn slicing() {
|
|
var array : [20]i32 = undefined;
|
|
|
|
array[5] = 1234;
|
|
|
|
var slice = array[5...10];
|
|
|
|
if (slice.len != 5) unreachable{};
|
|
|
|
const ptr = &slice[0];
|
|
if (ptr[0] != 1234) unreachable{};
|
|
|
|
var slice_rest = array[10...];
|
|
if (slice_rest.len != 10) unreachable{};
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn memcpy_and_memset_intrinsics() {
|
|
var foo : [20]u8 = undefined;
|
|
var bar : [20]u8 = undefined;
|
|
|
|
@memset(&foo[0], 'A', foo.len);
|
|
@memcpy(&bar[0], &foo[0], bar.len);
|
|
|
|
if (bar[11] != 'A') unreachable{};
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn array_dot_len_const_expr() { }
|
|
struct ArrayDotLenConstExpr {
|
|
y: [@const_eval(some_array.len)]u8,
|
|
}
|
|
const some_array = []u8 {0, 1, 2, 3};
|
|
|
|
|
|
#attribute("test")
|
|
fn count_leading_zeroes() {
|
|
assert(@clz(u8, 0b00001010) == 4);
|
|
assert(@clz(u8, 0b10001010) == 0);
|
|
assert(@clz(u8, 0b00000000) == 8);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn count_trailing_zeroes() {
|
|
assert(@ctz(u8, 0b10100000) == 5);
|
|
assert(@ctz(u8, 0b10001010) == 1);
|
|
assert(@ctz(u8, 0b00000000) == 8);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn multiline_string() {
|
|
const s1 = r"AOEU(
|
|
one
|
|
two)
|
|
three)AOEU";
|
|
const s2 = "\none\ntwo)\nthree";
|
|
const s3 = r"(
|
|
one
|
|
two)
|
|
three)";
|
|
assert(str.eql(s1, s2));
|
|
assert(str.eql(s3, s2));
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn simple_generic_fn() {
|
|
assert(max(i32)(3, -1) == 3);
|
|
assert(max(f32)(0.123, 0.456) == 0.456);
|
|
assert(add(2)(3) == 5);
|
|
}
|
|
|
|
fn max(T: type)(a: T, b: T) -> T {
|
|
return if (a > b) a else b;
|
|
}
|
|
|
|
fn add(a: i32)(b: i32) -> i32 {
|
|
return a + b;
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn constant_equal_function_pointers() {
|
|
const alias = empty_fn;
|
|
assert(@const_eval(empty_fn == alias));
|
|
}
|
|
|
|
fn empty_fn() {}
|
|
|
|
#attribute("test")
|
|
fn generic_function_equality() {
|
|
assert(max(i32) == max(i32));
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn generic_malloc_free() {
|
|
const a = %%mem_alloc(u8)(10);
|
|
mem_free(u8)(a);
|
|
}
|
|
const some_mem : [100]u8 = undefined;
|
|
#static_eval_enable(false)
|
|
fn mem_alloc(T: type)(n: isize) -> %[]T {
|
|
return (&T)(&some_mem[0])[0...n];
|
|
}
|
|
fn mem_free(T: type)(mem: []T) { }
|
|
|
|
|
|
#attribute("test")
|
|
fn call_fn_with_empty_string() {
|
|
accepts_string("");
|
|
}
|
|
|
|
fn accepts_string(foo: []u8) { }
|
|
|
|
|
|
#attribute("test")
|
|
fn hex_escape() {
|
|
assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello"));
|
|
}
|
|
|
|
|
|
error AnError;
|
|
error ALongerErrorName;
|
|
#attribute("test")
|
|
fn error_name_string() {
|
|
assert(str.eql(@err_name(error.AnError), "AnError"));
|
|
assert(str.eql(@err_name(error.ALongerErrorName), "ALongerErrorName"));
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn goto_and_labels() {
|
|
goto_loop();
|
|
assert(goto_counter == 10);
|
|
}
|
|
fn goto_loop() {
|
|
var i: i32 = 0;
|
|
goto cond;
|
|
loop:
|
|
i += 1;
|
|
cond:
|
|
if (!(i < 10)) goto end;
|
|
goto_counter += 1;
|
|
goto loop;
|
|
end:
|
|
}
|
|
var goto_counter: i32 = 0;
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn goto_leave_defer_scope() {
|
|
test_goto_leave_defer_scope(true);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_goto_leave_defer_scope(b: bool) {
|
|
var it_worked = false;
|
|
|
|
goto entry;
|
|
exit:
|
|
if (it_worked) {
|
|
return;
|
|
}
|
|
unreachable{};
|
|
entry:
|
|
defer it_worked = true;
|
|
if (b) goto exit;
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn cast_undefined() {
|
|
const array: [100]u8 = undefined;
|
|
const slice = ([]u8)(array);
|
|
test_cast_undefined(slice);
|
|
}
|
|
fn test_cast_undefined(x: []u8) {}
|
|
|
|
|
|
#attribute("test")
|
|
fn cast_small_unsigned_to_larger_signed() {
|
|
assert(cast_small_unsigned_to_larger_signed_1(200) == i16(200));
|
|
assert(cast_small_unsigned_to_larger_signed_2(9999) == isize(9999));
|
|
}
|
|
fn cast_small_unsigned_to_larger_signed_1(x: u8) -> i16 { x }
|
|
fn cast_small_unsigned_to_larger_signed_2(x: u16) -> isize { x }
|
|
|
|
|
|
#attribute("test")
|
|
fn implicit_cast_after_unreachable() {
|
|
assert(outer() == 1234);
|
|
}
|
|
fn inner() -> i32 { 1234 }
|
|
fn outer() -> isize {
|
|
return inner();
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn else_if_expression() {
|
|
assert(else_if_expression_f(1) == 1);
|
|
}
|
|
fn else_if_expression_f(c: u8) -> u8 {
|
|
if (c == 0) {
|
|
0
|
|
} else if (c == 1) {
|
|
1
|
|
} else {
|
|
2
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn err_binary_operator() {
|
|
const a = err_binary_operator_g(true) %% 3;
|
|
const b = err_binary_operator_g(false) %% 3;
|
|
assert(a == 3);
|
|
assert(b == 10);
|
|
}
|
|
error ItBroke;
|
|
fn err_binary_operator_g(x: bool) -> %isize {
|
|
if (x) {
|
|
error.ItBroke
|
|
} else {
|
|
10
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn unwrap_simple_value_from_error() {
|
|
const i = %%unwrap_simple_value_from_error_do();
|
|
assert(i == 13);
|
|
}
|
|
fn unwrap_simple_value_from_error_do() -> %isize { 13 }
|
|
|
|
|
|
#attribute("test")
|
|
fn store_member_function_in_variable() {
|
|
const instance = MemberFnTestFoo { .x = 1234, };
|
|
const member_fn = MemberFnTestFoo.member;
|
|
const result = member_fn(instance);
|
|
assert(result == 1234);
|
|
}
|
|
struct MemberFnTestFoo {
|
|
x: i32,
|
|
fn member(foo: MemberFnTestFoo) -> i32 { foo.x }
|
|
}
|
|
|
|
#attribute("test")
|
|
fn call_member_function_directly() {
|
|
const instance = MemberFnTestFoo { .x = 1234, };
|
|
const result = MemberFnTestFoo.member(instance);
|
|
assert(result == 1234);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn member_functions() {
|
|
const r = MemberFnRand {.seed = 1234};
|
|
assert(r.get_seed() == 1234);
|
|
}
|
|
struct MemberFnRand {
|
|
seed: u32,
|
|
pub fn get_seed(r: MemberFnRand) -> u32 {
|
|
r.seed
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn static_function_evaluation() {
|
|
assert(statically_added_number == 3);
|
|
}
|
|
const statically_added_number = static_add(1, 2);
|
|
fn static_add(a: i32, b: i32) -> i32 { a + b }
|
|
|
|
|
|
#attribute("test")
|
|
fn statically_initalized_list() {
|
|
assert(static_point_list[0].x == 1);
|
|
assert(static_point_list[0].y == 2);
|
|
assert(static_point_list[1].x == 3);
|
|
assert(static_point_list[1].y == 4);
|
|
}
|
|
struct Point {
|
|
x: i32,
|
|
y: i32,
|
|
}
|
|
const static_point_list = []Point { make_point(1, 2), make_point(3, 4) };
|
|
fn make_point(x: i32, y: i32) -> Point {
|
|
return Point {
|
|
.x = x,
|
|
.y = y,
|
|
};
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn static_eval_recursive() {
|
|
assert(seventh_fib_number == 21);
|
|
}
|
|
const seventh_fib_number = fibbonaci(7);
|
|
fn fibbonaci(x: i32) -> i32 {
|
|
if (x <= 1) return 1;
|
|
return fibbonaci(x - 1) + fibbonaci(x - 2);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn static_eval_while() {
|
|
assert(static_eval_while_number == 1);
|
|
}
|
|
const static_eval_while_number = static_while_loop_1();
|
|
fn static_while_loop_1() -> i32 {
|
|
return while_loop_2();
|
|
}
|
|
fn static_while_loop_2() -> i32 {
|
|
while (true) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn static_eval_list_init() {
|
|
assert(static_vec3.data[2] == 1.0);
|
|
}
|
|
const static_vec3 = vec3(0.0, 0.0, 1.0);
|
|
pub struct Vec3 {
|
|
data: [3]f32,
|
|
}
|
|
pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
|
|
Vec3 {
|
|
.data = []f32 { x, y, z, },
|
|
}
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn generic_fn_with_implicit_cast() {
|
|
assert(get_first_byte(u8)([]u8 {13}) == 13);
|
|
assert(get_first_byte(u16)([]u16 {0, 13}) == 0);
|
|
}
|
|
fn get_byte(ptr: ?&u8) -> u8 {*??ptr}
|
|
fn get_first_byte(T: type)(mem: []T) -> u8 {
|
|
get_byte((&u8)(&mem[0]))
|
|
}
|
|
|
|
#attribute("test")
|
|
fn continue_and_break() {
|
|
run_continue_and_break_test();
|
|
assert(continue_and_break_counter == 8);
|
|
}
|
|
var continue_and_break_counter: i32 = 0;
|
|
fn run_continue_and_break_test() {
|
|
var i : i32 = 0;
|
|
while (true) {
|
|
continue_and_break_counter += 2;
|
|
i += 1;
|
|
if (i < 4) {
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
assert(i == 4);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn sizeof_and_typeof() {
|
|
const y: @typeof(sizeof_and_typeof_x) = 120;
|
|
assert(@sizeof(@typeof(y)) == 2);
|
|
}
|
|
const sizeof_and_typeof_x: u16 = 13;
|
|
const sizeof_and_typeof_z: @typeof(sizeof_and_typeof_x) = 19;
|
|
|
|
|
|
#attribute("test")
|
|
fn pointer_dereferencing() {
|
|
var x = i32(3);
|
|
const y = &x;
|
|
|
|
*y += 1;
|
|
|
|
assert(x == 4);
|
|
assert(*y == 4);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn constant_expressions() {
|
|
var array : [ARRAY_SIZE]u8 = undefined;
|
|
assert(@sizeof(@typeof(array)) == 20);
|
|
}
|
|
const ARRAY_SIZE : i8 = 20;
|
|
|
|
|
|
#attribute("test")
|
|
fn min_value_and_max_value() {
|
|
assert(@max_value(u8) == 255);
|
|
assert(@max_value(u16) == 65535);
|
|
assert(@max_value(u32) == 4294967295);
|
|
assert(@max_value(u64) == 18446744073709551615);
|
|
|
|
assert(@max_value(i8) == 127);
|
|
assert(@max_value(i16) == 32767);
|
|
assert(@max_value(i32) == 2147483647);
|
|
assert(@max_value(i64) == 9223372036854775807);
|
|
|
|
assert(@min_value(u8) == 0);
|
|
assert(@min_value(u16) == 0);
|
|
assert(@min_value(u32) == 0);
|
|
assert(@min_value(u64) == 0);
|
|
|
|
assert(@min_value(i8) == -128);
|
|
assert(@min_value(i16) == -32768);
|
|
assert(@min_value(i32) == -2147483648);
|
|
assert(@min_value(i64) == -9223372036854775808);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn overflow_intrinsics() {
|
|
var result: u8 = undefined;
|
|
assert(@add_with_overflow(u8, 250, 100, &result));
|
|
assert(!@add_with_overflow(u8, 100, 150, &result));
|
|
assert(result == 250);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn nested_arrays() {
|
|
const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
|
|
for (array_of_strings) |s, i| {
|
|
if (i == 0) assert(str.eql(s, "hello"));
|
|
if (i == 1) assert(str.eql(s, "this"));
|
|
if (i == 2) assert(str.eql(s, "is"));
|
|
if (i == 3) assert(str.eql(s, "my"));
|
|
if (i == 4) assert(str.eql(s, "thing"));
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn int_to_ptr_cast() {
|
|
const x = isize(13);
|
|
const y = (&u8)(x);
|
|
const z = usize(y);
|
|
assert(z == 13);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn string_concatenation() {
|
|
assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn constant_struct_with_negation() {
|
|
assert(vertices[0].x == -0.6);
|
|
}
|
|
struct Vertex {
|
|
x: f32,
|
|
y: f32,
|
|
r: f32,
|
|
g: f32,
|
|
b: f32,
|
|
}
|
|
const vertices = []Vertex {
|
|
Vertex { .x = -0.6, .y = -0.4, .r = 1.0, .g = 0.0, .b = 0.0 },
|
|
Vertex { .x = 0.6, .y = -0.4, .r = 0.0, .g = 1.0, .b = 0.0 },
|
|
Vertex { .x = 0.0, .y = 0.6, .r = 0.0, .g = 0.0, .b = 1.0 },
|
|
};
|
|
|
|
|
|
#attribute("test")
|
|
fn return_with_implicit_cast_from_while_loop() {
|
|
%%return_with_implicit_cast_from_while_loop_test();
|
|
}
|
|
fn return_with_implicit_cast_from_while_loop_test() -> %void {
|
|
while (true) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn return_struct_byval_from_function() {
|
|
const bar = make_bar(1234, 5678);
|
|
assert(bar.y == 5678);
|
|
}
|
|
struct Bar {
|
|
x: i32,
|
|
y: i32,
|
|
}
|
|
fn make_bar(x: i32, y: i32) -> Bar {
|
|
Bar {
|
|
.x = x,
|
|
.y = y,
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn function_pointers() {
|
|
const fns = []@typeof(fn1) { fn1, fn2, fn3, fn4, };
|
|
for (fns) |f, i| {
|
|
assert(f() == u32(i) + 5);
|
|
}
|
|
}
|
|
fn fn1() -> u32 {5}
|
|
fn fn2() -> u32 {6}
|
|
fn fn3() -> u32 {7}
|
|
fn fn4() -> u32 {8}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn statically_initalized_struct() {
|
|
st_init_str_foo.x += 1;
|
|
assert(st_init_str_foo.x == 14);
|
|
}
|
|
struct StInitStrFoo {
|
|
x: i32,
|
|
y: bool,
|
|
}
|
|
var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, };
|
|
|
|
#attribute("test")
|
|
fn statically_initialized_array_literal() {
|
|
const y : [4]u8 = st_init_arr_lit_x;
|
|
assert(y[3] == 4);
|
|
}
|
|
const st_init_arr_lit_x = []u8{1,2,3,4};
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn pointer_to_void_return_type() {
|
|
%%test_pointer_to_void_return_type();
|
|
}
|
|
fn test_pointer_to_void_return_type() -> %void {
|
|
const a = test_pointer_to_void_return_type_2();
|
|
return *a;
|
|
}
|
|
const test_pointer_to_void_return_type_x = void{};
|
|
fn test_pointer_to_void_return_type_2() -> &void {
|
|
return &test_pointer_to_void_return_type_x;
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn call_result_of_if_else_expression() {
|
|
assert(str.eql(f2(true), "a"));
|
|
assert(str.eql(f2(false), "b"));
|
|
}
|
|
fn f2(x: bool) -> []u8 {
|
|
return (if (x) f_a else f_b)();
|
|
}
|
|
fn f_a() -> []u8 { "a" }
|
|
fn f_b() -> []u8 { "b" }
|
|
|
|
|
|
#attribute("test")
|
|
fn const_expression_eval_handling_of_variables() {
|
|
var x = true;
|
|
while (x) {
|
|
x = false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn constant_enum_initialization_with_differing_sizes() {
|
|
test3_1(test3_foo);
|
|
test3_2(test3_bar);
|
|
}
|
|
enum Test3Foo {
|
|
One,
|
|
Two: f32,
|
|
Three: Test3Point,
|
|
}
|
|
struct Test3Point {
|
|
x: i32,
|
|
y: i32,
|
|
}
|
|
const test3_foo = Test3Foo.Three{Test3Point {.x = 3, .y = 4}};
|
|
const test3_bar = Test3Foo.Two{13};
|
|
#static_eval_enable(false)
|
|
fn test3_1(f: Test3Foo) {
|
|
switch (f) {
|
|
Three => |pt| {
|
|
assert(pt.x == 3);
|
|
assert(pt.y == 4);
|
|
},
|
|
else => unreachable{},
|
|
}
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test3_2(f: Test3Foo) {
|
|
switch (f) {
|
|
Two => |x| {
|
|
assert(x == 13);
|
|
},
|
|
else => unreachable{},
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
fn pub_enum() {
|
|
pub_enum_test(other.APubEnum.Two);
|
|
}
|
|
fn pub_enum_test(foo: other.APubEnum) {
|
|
assert(foo == other.APubEnum.Two);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn cast_with_imported_symbol() {
|
|
assert(other.size_t(42) == 42);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn while_with_continue_expr() {
|
|
var sum: i32 = 0;
|
|
{var i: i32 = 0; while (i < 10; i += 1) {
|
|
if (i == 5) continue;
|
|
sum += i;
|
|
}}
|
|
assert(sum == 40);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn for_loop_with_pointer_elem_var() {
|
|
const source = "abcdefg";
|
|
var target: [source.len]u8 = undefined;
|
|
@memcpy(&target[0], &source[0], source.len);
|
|
mangle_string(target);
|
|
assert(str.eql(target, "bcdefgh"));
|
|
}
|
|
#static_eval_enable(false)
|
|
fn mangle_string(s: []u8) {
|
|
for (s) |*c| {
|
|
*c += 1;
|
|
}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn empty_struct_method_call() {
|
|
const es = EmptyStruct{};
|
|
assert(es.method() == 1234);
|
|
}
|
|
struct EmptyStruct {
|
|
#static_eval_enable(false)
|
|
fn method(es: EmptyStruct) -> i32 { 1234 }
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn @"weird function name"() { }
|
|
|
|
|
|
#attribute("test")
|
|
fn return_empty_struct_from_fn() {
|
|
test_return_empty_struct_from_fn();
|
|
test_return_empty_struct_from_fn_noeval();
|
|
}
|
|
struct EmptyStruct2 {}
|
|
fn test_return_empty_struct_from_fn() -> EmptyStruct2 {
|
|
EmptyStruct2 {}
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_return_empty_struct_from_fn_noeval() -> EmptyStruct2 {
|
|
EmptyStruct2 {}
|
|
}
|
|
|
|
#attribute("test")
|
|
fn pass_slice_of_empty_struct_to_fn() {
|
|
assert(test_pass_slice_of_empty_struct_to_fn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
|
|
}
|
|
fn test_pass_slice_of_empty_struct_to_fn(slice: []EmptyStruct2) -> isize {
|
|
slice.len
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn pointer_comparison() {
|
|
const a = ([]u8)("a");
|
|
const b = &a;
|
|
assert(ptr_eql(b, b));
|
|
}
|
|
fn ptr_eql(a: &[]u8, b: &[]u8) -> bool {
|
|
a == b
|
|
}
|
|
|
|
#attribute("test")
|
|
fn character_literals() {
|
|
assert('\'' == single_quote);
|
|
}
|
|
const single_quote = '\'';
|
|
|
|
|
|
#attribute("test")
|
|
fn switch_with_multiple_expressions() {
|
|
const x: i32 = switch (returns_five()) {
|
|
1, 2, 3 => 1,
|
|
4, 5, 6 => 2,
|
|
else => 3,
|
|
};
|
|
assert(x == 2);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn returns_five() -> i32 { 5 }
|
|
|
|
|
|
#attribute("test")
|
|
fn switch_on_error_union() {
|
|
const x = switch (returns_ten()) {
|
|
Ok => |val| val + 1,
|
|
ItBroke, NoMem => 1,
|
|
CrappedOut => 2,
|
|
};
|
|
assert(x == 11);
|
|
}
|
|
error ItBroke;
|
|
error NoMem;
|
|
error CrappedOut;
|
|
#static_eval_enable(false)
|
|
fn returns_ten() -> %i32 { 10 }
|
|
|
|
|
|
#attribute("test")
|
|
fn bool_cmp() {
|
|
assert(test_bool_cmp(true, false) == false);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_bool_cmp(a: bool, b: bool) -> bool { a == b }
|
|
|
|
|
|
#attribute("test")
|
|
fn take_address_of_parameter() {
|
|
test_take_address_of_parameter(12.34);
|
|
test_take_address_of_parameter_noeval(12.34);
|
|
}
|
|
fn test_take_address_of_parameter(f: f32) {
|
|
const f_ptr = &f;
|
|
assert(*f_ptr == 12.34);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_take_address_of_parameter_noeval(f: f32) {
|
|
const f_ptr = &f;
|
|
assert(*f_ptr == 12.34);
|
|
}
|
|
|
|
|
|
#attribute("test")
|
|
fn array_mult_operator() {
|
|
assert(str.eql("ab" ** 5, "ababababab"));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn string_escapes() {
|
|
assert(str.eql("\"", "\x22"));
|
|
assert(str.eql("\'", "\x27"));
|
|
assert(str.eql("\n", "\x0a"));
|
|
assert(str.eql("\r", "\x0d"));
|
|
assert(str.eql("\t", "\x09"));
|
|
assert(str.eql("\\", "\x5c"));
|
|
assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn if_var_maybe_pointer() {
|
|
assert(should_be_a_plus_1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn should_be_a_plus_1(p: Particle) -> u64 {
|
|
var maybe_particle: ?Particle = p;
|
|
if (const *particle ?= maybe_particle) {
|
|
particle.a += 1;
|
|
}
|
|
if (const particle ?= maybe_particle) {
|
|
return particle.a;
|
|
}
|
|
return 0;
|
|
}
|
|
struct Particle {
|
|
a: u64,
|
|
b: u64,
|
|
c: u64,
|
|
d: u64,
|
|
}
|
|
|
|
#attribute("test")
|
|
fn assign_to_if_var_ptr() {
|
|
var maybe_bool: ?bool = true;
|
|
|
|
if (const *b ?= maybe_bool) {
|
|
*b = false;
|
|
}
|
|
|
|
assert(??maybe_bool == false);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn cmpxchg() {
|
|
var x: i32 = 1234;
|
|
while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {}
|
|
assert(x == 5678);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn fence() {
|
|
var x: i32 = 1234;
|
|
@fence(AtomicOrder.SeqCst);
|
|
x = 5678;
|
|
}
|
|
|
|
#attribute("test")
|
|
fn unsigned_wrapping() {
|
|
test_unsigned_wrapping_eval(@max_value(u32));
|
|
test_unsigned_wrapping_noeval(@max_value(u32));
|
|
}
|
|
fn test_unsigned_wrapping_eval(x: u32w) {
|
|
const zero = x + 1;
|
|
assert(zero == 0);
|
|
const orig = zero - 1;
|
|
assert(orig == @max_value(u32));
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_unsigned_wrapping_noeval(x: u32w) {
|
|
const zero = x + 1;
|
|
assert(zero == 0);
|
|
const orig = zero - 1;
|
|
assert(orig == @max_value(u32));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn signed_wrapping() {
|
|
test_signed_wrapping_eval(@max_value(i32));
|
|
test_signed_wrapping_noeval(@max_value(i32));
|
|
}
|
|
fn test_signed_wrapping_eval(x: i32w) {
|
|
const min_val = x + 1;
|
|
assert(min_val == @min_value(i32));
|
|
const max_val = min_val - 1;
|
|
assert(max_val == @max_value(i32));
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_signed_wrapping_noeval(x: i32w) {
|
|
const min_val = x + 1;
|
|
assert(min_val == @min_value(i32));
|
|
const max_val = min_val - 1;
|
|
assert(max_val == @max_value(i32));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn negation_wrapping() {
|
|
test_negation_wrapping_eval(@min_value(i16));
|
|
test_negation_wrapping_noeval(@min_value(i16));
|
|
}
|
|
fn test_negation_wrapping_eval(x: i16w) {
|
|
assert(x == -32768);
|
|
const neg = -x;
|
|
assert(neg == -32768);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_negation_wrapping_noeval(x: i16w) {
|
|
assert(x == -32768);
|
|
const neg = -x;
|
|
assert(neg == -32768);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn shl_wrapping() {
|
|
test_shl_wrapping_eval(@max_value(u16));
|
|
test_shl_wrapping_noeval(@max_value(u16));
|
|
}
|
|
fn test_shl_wrapping_eval(x: u16w) {
|
|
const shifted = x << 1;
|
|
assert(shifted == 65534);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_shl_wrapping_noeval(x: u16w) {
|
|
const shifted = x << 1;
|
|
assert(shifted == 65534);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn shl_with_overflow() {
|
|
var result: u16 = undefined;
|
|
assert(@shl_with_overflow(u16, 0b0010111111111111, 3, &result));
|
|
assert(!@shl_with_overflow(u16, 0b0010111111111111, 2, &result));
|
|
assert(result == 0b1011111111111100);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn combine_non_wrap_with_wrap() {
|
|
const x: i32 = 123;
|
|
const y: i32w = 456;
|
|
const z = x + y;
|
|
const z2 = y + x;
|
|
assert(@typeof(z) == i32w);
|
|
assert(@typeof(z2) == i32w);
|
|
|
|
const a: i8 = 123;
|
|
const b: i32w = 456;
|
|
const c = b + a;
|
|
const d = a + b;
|
|
assert(@typeof(c) == i32w);
|
|
assert(@typeof(d) == i32w);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn c_string_concatenation() {
|
|
const a = c"OK" ++ c" IT " ++ c"WORKED";
|
|
const b = c"OK IT WORKED";
|
|
|
|
const len = cstr.len(b);
|
|
const len_with_null = len + 1;
|
|
{var i: i32 = 0; while (i < len_with_null; i += 1) {
|
|
assert(a[i] == b[i]);
|
|
}}
|
|
assert(a[len] == 0);
|
|
assert(b[len] == 0);
|
|
}
|
|
|
|
#attribute("test")
|
|
fn generic_struct() {
|
|
var a1 = GenNode(i32) {.value = 13, .next = null,};
|
|
var b1 = GenNode(bool) {.value = true, .next = null,};
|
|
assert(a1.value == 13);
|
|
assert(a1.value == a1.get_val());
|
|
assert(b1.get_val());
|
|
}
|
|
struct GenNode(T: type) {
|
|
value: T,
|
|
next: ?&GenNode(T),
|
|
fn get_val(n: &const GenNode(T)) -> T { n.value }
|
|
}
|
|
|
|
#attribute("test")
|
|
fn cast_slice_to_u8_slice() {
|
|
assert(@sizeof(i32) == 4);
|
|
var big_thing_array = []i32{1, 2, 3, 4};
|
|
const big_thing_slice: []i32 = big_thing_array;
|
|
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);
|
|
const big_thing_again = ([]i32)(bytes);
|
|
assert(big_thing_again[2] == 3);
|
|
big_thing_again[2] = -1;
|
|
assert(bytes[8] == @max_value(u8));
|
|
assert(bytes[9] == @max_value(u8));
|
|
assert(bytes[10] == @max_value(u8));
|
|
assert(bytes[11] == @max_value(u8));
|
|
}
|
|
|
|
#attribute("test")
|
|
fn float_division() {
|
|
assert(fdiv32(12.0, 3.0) == 4.0);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn fdiv32(a: f32, b: f32) -> f32 {
|
|
a / b
|
|
}
|
|
|
|
#attribute("test")
|
|
fn exact_division() {
|
|
assert(div_exact(55, 11) == 5);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn div_exact(a: u32, b: u32) -> u32 {
|
|
@div_exact(a, b)
|
|
}
|
|
|
|
#attribute("test")
|
|
fn null_literal_outside_function() {
|
|
const is_null = if (const _ ?= here_is_a_null_literal.context) false else true;
|
|
assert(is_null);
|
|
}
|
|
struct SillyStruct {
|
|
context: ?i32,
|
|
}
|
|
const here_is_a_null_literal = SillyStruct {
|
|
.context = null,
|
|
};
|
|
|
|
#attribute("test")
|
|
fn truncate() {
|
|
assert(test_truncate(0x10fd) == 0xfd);
|
|
}
|
|
#static_eval_enable(false)
|
|
fn test_truncate(x: u32) -> u8 {
|
|
@truncate(u8, x)
|
|
}
|
|
|
|
#attribute("test")
|
|
fn const_decls_in_struct() {
|
|
assert(GenericDataThing(3).count_plus_one == 4);
|
|
}
|
|
struct GenericDataThing(count: isize) {
|
|
const count_plus_one = count + 1;
|
|
}
|
|
|
|
#attribute("test")
|
|
fn use_generic_param_in_generic_param() {
|
|
assert(a_generic_fn(i32, 3)(4) == 7);
|
|
}
|
|
fn a_generic_fn(T: type, a: T)(b: T) -> T {
|
|
return a + b;
|
|
}
|