use super::*; #[test] fn test_assignment_operators() { fn construct_source(value_type: &str, value_initial: &str, value_op: &str) -> String { return format!( "func foo() -> {} {{ {} value = {}; value {}; return value; }}", value_type, value_type, value_initial, value_op ); } fn perform_test(name: &str, source: String, expected_value: Value) { Tester::new_single_source_expect_ok(name, source) .for_function("foo", move |f| { f.call_ok(Some(expected_value)); }); } perform_test( "set", construct_source("u32", "1", "= 5"), Value::UInt32(5) ); perform_test( "multiplied", construct_source("u32", "2", "*= 4"), Value::UInt32(8) ); perform_test( "divided", construct_source("u32", "8", "/= 4"), Value::UInt32(2) ); perform_test( "remained", construct_source("u32", "8", "%= 3"), Value::UInt32(2) ); perform_test( "added", construct_source("u32", "2", "+= 4"), Value::UInt32(6) ); perform_test( "subtracted", construct_source("u32", "6", "-= 4"), Value::UInt32(2) ); perform_test( "shifted left", construct_source("u32", "2", "<<= 2"), Value::UInt32(8) ); perform_test( "shifted right", construct_source("u32", "8", ">>= 2"), Value::UInt32(2) ); perform_test( "bitwise and", construct_source("u32", "15", "&= 35"), Value::UInt32(3) ); perform_test( "bitwise xor", construct_source("u32", "3", "^= 7"), Value::UInt32(4) ); perform_test( "bitwise or", construct_source("u32", "12", "|= 3"), Value::UInt32(15) ); } #[test] fn test_binary_integer_operators() { fn construct_source(value_type: &str, code: &str) -> String { format!(" func foo() -> {} {{ {} }} ", value_type, code) } fn perform_test(test_name: &str, value_type: &str, code: &str, expected_value: Value) { Tester::new_single_source_expect_ok(test_name, construct_source(value_type, code)) .for_function("foo", move |f| { f.call_ok(Some(expected_value)); }); } perform_test( "bitwise_or", "u16", "auto a = 3; return a | 4;", Value::UInt16(7) ); perform_test( "bitwise_xor", "u16", "auto a = 3; return a ^ 7;", Value::UInt16(4) ); perform_test( "bitwise and", "u16", "auto a = 0b110011; return a & 0b011110;", Value::UInt16(0b010010) ); perform_test( "shift left", "u16", "auto a = 0x0F; return a << 4;", Value::UInt16(0xF0) ); perform_test( "shift right", "u64", "auto a = 0xF0; return a >> 4;", Value::UInt64(0x0F) ); perform_test( "add", "u32", "auto a = 5; return a + 5;", Value::UInt32(10) ); perform_test( "subtract", "u32", "auto a = 3; return a - 3;", Value::UInt32(0) ); perform_test( "multiply", "u8", "auto a = 2 * 2; return a * 2 * 2;", Value::UInt8(16) ); perform_test( "divide", "u8", "auto a = 32 / 2; return a / 2 / 2;", Value::UInt8(4) ); perform_test( "remainder", "u16", "auto a = 29; return a % 3;", Value::UInt16(2) ); } #[test] fn test_tuple_comparison_operators() { Tester::new_single_source_expect_ok("tuple equality", " func test_func() -> bool { auto a1 = (8, 16, 32); (u8, u16, u32) a2 = (8, 16, 32); auto b1 = (); () b2 = (); return a1 == a2 && a2 == (8, 16, 32) && b1 == b2 && b2 == (); } ").for_function("test_func", |f| { f .call_ok(Some(Value::Bool(true))); }); Tester::new_single_source_expect_ok("tuple inequality", " func test_func() -> bool { auto a = (8, 16, 32); (u8, u16, u32) a_same = (8, 16, 32); auto a_diff = (0b111, 0b1111, 0b11111); auto b = (); return !(a != a_same) && a != a_diff && a != (8, 16, 320) && !(b != ()); } ").for_function("test_func", |f| { f .call_ok(Some(Value::Bool(true))); }); } #[test] fn test_tuple_select_operator() { Tester::new_single_source_expect_ok("tuple member assignment", " func test() -> bool { auto tuple = (0, 1, 0, 1); tuple.0 = cast(1); tuple.1 = cast(2); tuple.2 = cast(3); tuple.3 = cast(4); return cast(tuple.0) + cast(tuple.1) + tuple.2 + cast(tuple.3) == 10; } ").for_function("test", |f| { f .for_variable("tuple", |v| { v.assert_concrete_type("(u8,u16,u32,u64)"); }) .call_ok(Some(Value::Bool(true))); }); Tester::new_single_source_expect_ok("tuple polymorph member access", " func sum_variant_a((A,B,C,D) v) -> C { return cast(v.0) + cast(v.1) + v.2 + cast(v.3); } func sum_variant_b((A,B,C,D) i) -> B { (A,B,C,D) c = (0,0,0,0); c.0 = i.0; c.1 = i.1; c.2 = i.2; c.3 = i.3; return cast(c.0) + c.1 + cast(c.2) + cast(c.3); } func test() -> bool { (u8,u16,u32,u64) tuple = (1, 2, 3, 4); return sum_variant_a(tuple) == 10 && sum_variant_b(tuple) == 10; } ").for_function("test", |f| { f .call_ok(Some(Value::Bool(true))); }); } #[test] fn test_string_operators() { Tester::new_single_source_expect_ok("string concatenation", " func create_concatenated(string left, string right) -> string { return left @ \", but also \" @ right; } func perform_concatenate(string left, string right) -> string { left @= \", but also \"; left @= right; return left; } func foo() -> bool { auto left = \"Darth Vader\"; auto right = \"Anakin Skywalker\"; auto res1 = create_concatenated(left, right); auto res2 = perform_concatenate(left, right); auto expected = \"Darth Vader, but also Anakin Skywalker\"; print(res1); print(expected); return res1 == expected; // && res2 == \"Darth Vader, but also Anakin Skywalker\" && res1 != \"This kind of thing\" && res2 != \"Another likewise kind of thing\"; } ").for_function("foo", |f| { f .call_ok(Some(Value::Bool(true))); }); }