2019-11-17 09:28:39 -08:00
|
|
|
#pragma warning disable 168
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
using System;
|
|
|
|
|
|
|
|
namespace Tests
|
|
|
|
{
|
|
|
|
class Operators
|
|
|
|
{
|
2020-12-23 15:56:43 -08:00
|
|
|
struct FlagsRegister
|
|
|
|
{
|
|
|
|
public bool zero;
|
|
|
|
public bool subtract;
|
|
|
|
public bool half_carry;
|
|
|
|
public bool carry;
|
|
|
|
|
|
|
|
const uint8 ZERO_FLAG_BYTE_POSITION = 7;
|
|
|
|
const uint8 SUBTRACT_FLAG_BYTE_POSITION = 6;
|
|
|
|
const uint8 HALF_CARRY_FLAG_BYTE_POSITION = 5;
|
|
|
|
const uint8 CARRY_FLAG_BYTE_POSITION = 4;
|
|
|
|
|
|
|
|
public this(bool z, bool s, bool hc, bool c)
|
|
|
|
{
|
|
|
|
zero = z;
|
|
|
|
subtract = s;
|
|
|
|
half_carry = hc;
|
|
|
|
carry = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Convert flag register to a uint8
|
|
|
|
public static implicit operator uint8 (FlagsRegister flag)
|
|
|
|
{
|
|
|
|
return (flag.zero ? 1 : 0) << ZERO_FLAG_BYTE_POSITION |
|
|
|
|
(flag.subtract ? 1 : 0) << SUBTRACT_FLAG_BYTE_POSITION |
|
|
|
|
(flag.half_carry ? 1 : 0) << HALF_CARRY_FLAG_BYTE_POSITION |
|
|
|
|
(flag.carry ? 1 : 0) << CARRY_FLAG_BYTE_POSITION;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
struct StructA
|
|
|
|
{
|
|
|
|
public int mA;
|
|
|
|
|
|
|
|
public static StructA operator+(StructA lhs, StructA rhs)
|
|
|
|
{
|
|
|
|
StructA res;
|
|
|
|
res.mA = lhs.mA + rhs.mA;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static StructA operator-(StructA lhs, StructA rhs)
|
|
|
|
{
|
|
|
|
StructA res;
|
|
|
|
res.mA = lhs.mA - rhs.mA;
|
|
|
|
return res;
|
|
|
|
}
|
2020-11-05 08:51:20 -08:00
|
|
|
|
|
|
|
public static StructA operator++(StructA val)
|
|
|
|
{
|
|
|
|
StructA newVal;
|
|
|
|
newVal.mA = val.mA + 1;
|
|
|
|
return newVal;
|
|
|
|
}
|
2020-12-03 07:50:36 -08:00
|
|
|
|
|
|
|
[Commutable]
|
|
|
|
public static bool operator<(StructA lhs, StructB rhs)
|
|
|
|
{
|
|
|
|
return lhs.mA < rhs.mB;
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
|
2019-11-17 09:28:39 -08:00
|
|
|
struct StructB
|
|
|
|
{
|
|
|
|
public int mB;
|
|
|
|
|
|
|
|
public static StructA operator+(StructA sa, StructB sb)
|
|
|
|
{
|
|
|
|
StructA result;
|
|
|
|
result.mA = sa.mA + sb.mB + 1000;
|
|
|
|
return result;
|
|
|
|
}
|
2020-11-05 08:51:20 -08:00
|
|
|
|
|
|
|
public void operator++() mut
|
|
|
|
{
|
|
|
|
mB++;
|
|
|
|
}
|
2019-11-17 09:28:39 -08:00
|
|
|
}
|
|
|
|
|
2020-06-18 06:33:33 -07:00
|
|
|
struct StructC
|
|
|
|
{
|
|
|
|
public int mA;
|
|
|
|
public int mB;
|
|
|
|
|
|
|
|
public this(int a, int b)
|
|
|
|
{
|
|
|
|
mA = a;
|
|
|
|
mB = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool operator==(StructC lhs, StructC rhs)
|
|
|
|
{
|
|
|
|
return lhs.mA == rhs.mA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-17 09:28:39 -08:00
|
|
|
struct StructOp<T, T2> where T : operator T + T2
|
|
|
|
{
|
|
|
|
public T DoIt(T val, T2 val2)
|
|
|
|
{
|
|
|
|
return val + val2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct StructOp2<T>
|
|
|
|
{
|
|
|
|
public T mVal;
|
|
|
|
|
|
|
|
public static T operator+<T2>(StructOp2<T> lhs, T2 rhs) where T : operator T + T2
|
|
|
|
{
|
|
|
|
return lhs.mVal + rhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T operator|<T2>(StructOp2<T> lhs, T2 rhs) where T : operator implicit T2
|
|
|
|
{
|
|
|
|
T temp = rhs;
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
public T GetNeg<T2>(T2 val) where T : operator -T2
|
|
|
|
{
|
|
|
|
return -val;
|
|
|
|
}
|
|
|
|
|
2020-07-24 05:20:50 -07:00
|
|
|
public T GetInt() where T : Int32
|
2019-11-17 09:28:39 -08:00
|
|
|
{
|
|
|
|
return mVal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*struct OuterOp<T>
|
|
|
|
{
|
|
|
|
public struct InnerOp<T2>
|
|
|
|
where T : operator T + T2
|
|
|
|
where T : operator -T
|
|
|
|
where T : operator implicit T2
|
|
|
|
{
|
|
|
|
public static T Op(T val, T2 val2)
|
|
|
|
{
|
|
|
|
return val + val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Neg(T val)
|
|
|
|
{
|
|
|
|
return -val;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Cast(T2 val)
|
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct InnerOp2
|
|
|
|
{
|
|
|
|
public static T Op(T val, T2 val2)
|
|
|
|
{
|
|
|
|
return val + val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Neg(T val)
|
|
|
|
{
|
|
|
|
return -val;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Cast(T2 val)
|
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct InnerOp3<T3>
|
|
|
|
{
|
|
|
|
public static T Op(T val, T2 val2)
|
|
|
|
{
|
|
|
|
return val + val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Neg(T val)
|
|
|
|
{
|
|
|
|
return -val;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Cast(T2 val)
|
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct OuterOp2<T>
|
|
|
|
{
|
|
|
|
public struct InnerOp<T2>
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extension InnerOp<T2>
|
|
|
|
where T : operator T + T2
|
|
|
|
where T : operator -T
|
|
|
|
{
|
|
|
|
public static T Op(T val, T2 val2)
|
|
|
|
{
|
|
|
|
return val + val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T Neg(T val)
|
|
|
|
{
|
|
|
|
return -val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
public static T Op<T, T2>(T val, T2 val2) where T : operator T + T2
|
|
|
|
{
|
|
|
|
return val + val2;
|
|
|
|
}
|
|
|
|
|
2020-08-05 05:34:32 -07:00
|
|
|
public static T Complex<T, T2, T3>(T val, T2 val2, T3 val3)
|
2019-11-17 09:28:39 -08:00
|
|
|
where T : operator -T
|
|
|
|
where T : operator implicit T2
|
2020-08-05 05:34:32 -07:00
|
|
|
where T : operator T + T2
|
|
|
|
where int32 : operator T + T3
|
2019-11-17 09:28:39 -08:00
|
|
|
{
|
|
|
|
T conv = val2;
|
|
|
|
T result = val + val2;
|
|
|
|
result = -result;
|
2020-08-05 05:34:32 -07:00
|
|
|
int32 iRes = val + val3;
|
2019-11-17 09:28:39 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-08-05 05:34:32 -07:00
|
|
|
struct StructOp3<T, T2> where float : operator T + T2
|
|
|
|
{
|
|
|
|
public float Use(T lhs, T2 rhs)
|
|
|
|
{
|
|
|
|
float f = lhs + rhs;
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
[Test]
|
|
|
|
public static void TestBasics()
|
|
|
|
{
|
|
|
|
StructA sa0 = default;
|
|
|
|
sa0.mA = 1;
|
|
|
|
StructA sa1 = default;
|
|
|
|
sa1.mA = 2;
|
|
|
|
|
|
|
|
StructA sa2 = sa0 + sa1;
|
|
|
|
Test.Assert(sa2.mA == 3);
|
2019-11-17 09:28:39 -08:00
|
|
|
|
|
|
|
StructB sb0;
|
|
|
|
sb0.mB = 11;
|
|
|
|
StructB sb1;
|
|
|
|
sb1.mB = 12;
|
|
|
|
|
2020-12-03 07:50:36 -08:00
|
|
|
Test.Assert(sa1 < sb0);
|
|
|
|
Test.Assert(!(sa1 >= sb0));
|
|
|
|
|
|
|
|
Test.Assert(sb0 > sa1);
|
|
|
|
Test.Assert(!(sb0 <= sa1));
|
|
|
|
|
2019-11-17 09:28:39 -08:00
|
|
|
StructA sa3 = sa0 + sb0;
|
|
|
|
Test.Assert(sa3.mA == 1012);
|
|
|
|
|
|
|
|
StructA sa4 = Op(sa0, sb0);
|
|
|
|
Test.Assert(sa4.mA == 1012);
|
|
|
|
|
2020-11-05 08:51:20 -08:00
|
|
|
StructA sa6 = sa0++;
|
|
|
|
Test.Assert(sa0.mA == 2);
|
|
|
|
Test.Assert(sa6.mA == 1);
|
|
|
|
sa6 = ++sa0;
|
|
|
|
Test.Assert(sa0.mA == 3);
|
|
|
|
Test.Assert(sa6.mA == 3);
|
|
|
|
|
|
|
|
StructB sb6 = sb0++;
|
|
|
|
Test.Assert(sb0.mB == 12);
|
|
|
|
Test.Assert(sb6.mB == 11);
|
|
|
|
sb6 = ++sb0;
|
|
|
|
Test.Assert(sb0.mB == 13);
|
|
|
|
Test.Assert(sb6.mB == 13);
|
|
|
|
|
2019-11-17 09:28:39 -08:00
|
|
|
float val = Op((int32)100, (int16)23);
|
|
|
|
Test.Assert(val == 123);
|
|
|
|
|
2020-08-05 05:34:32 -07:00
|
|
|
int32 i32res = Complex((int32)100, (int16)23, (int8)4);
|
2019-11-17 09:28:39 -08:00
|
|
|
Test.Assert(i32res == -123);
|
|
|
|
|
|
|
|
StructOp<StructA, StructB> sOp;
|
|
|
|
let sa5 = sOp.DoIt(sa1, sb1);
|
|
|
|
Test.Assert(sa5.mA == 1014);
|
|
|
|
|
|
|
|
StructOp2<int32> sOp2;
|
|
|
|
sOp2.mVal = 100;
|
|
|
|
int32 res6 = sOp2 + (int16)40;
|
|
|
|
Test.Assert(res6 == 140);
|
|
|
|
int32 res7 = sOp2.GetInt();
|
|
|
|
Test.Assert(res7 == 100);
|
|
|
|
|
2020-06-18 06:33:33 -07:00
|
|
|
Result<StructC> rsc = .Ok(.(123, 234));
|
|
|
|
Result<StructC> rsc2 = .Ok(.(123, 345));
|
|
|
|
Test.Assert(rsc == rsc2);
|
|
|
|
Test.Assert(rsc !== rsc2);
|
|
|
|
|
2020-08-05 05:34:32 -07:00
|
|
|
StructOp3<int16, int32> so3 = .();
|
|
|
|
float f = so3.Use(1, 2);
|
|
|
|
Test.Assert(f == 3);
|
|
|
|
|
2020-12-23 15:56:43 -08:00
|
|
|
FlagsRegister fr = .(true, false, true, true);
|
|
|
|
Test.Assert(fr == (uint8)0b10110000);
|
|
|
|
|
2019-11-17 09:28:39 -08:00
|
|
|
/*let oai = OuterOp<float>.InnerOp<int>.Op(1.0f, 100);
|
|
|
|
Test.Assert(oai == 101.0f);
|
|
|
|
|
|
|
|
let oai2 = OuterOp2<float>.InnerOp<int>.Op(2.0f, 200);
|
|
|
|
Test.Assert(oai2 == 202.0f);*/
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
2020-01-31 16:09:35 -08:00
|
|
|
|
|
|
|
struct IntStruct
|
|
|
|
{
|
|
|
|
public int mA = 123;
|
|
|
|
|
|
|
|
public typealias ZaffInt = int;
|
|
|
|
|
|
|
|
public ZaffInt GetIt()
|
|
|
|
{
|
|
|
|
return 123;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static implicit operator int(Self val)
|
|
|
|
{
|
|
|
|
return val.mA;
|
|
|
|
}
|
2020-03-11 07:57:20 -07:00
|
|
|
|
|
|
|
public static implicit operator Self(int val)
|
|
|
|
{
|
|
|
|
IntStruct sVal;
|
|
|
|
sVal.mA = val;
|
|
|
|
return sVal;
|
|
|
|
}
|
2020-09-01 06:37:02 -07:00
|
|
|
|
|
|
|
public void operator++() mut
|
|
|
|
{
|
|
|
|
mA++;
|
|
|
|
}
|
2020-01-31 16:09:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public static void TestCompareWithCastOperator()
|
|
|
|
{
|
|
|
|
IntStruct iVal = .();
|
|
|
|
Test.Assert(iVal == 123);
|
|
|
|
Test.Assert(iVal == 123.0f);
|
2020-09-01 06:37:02 -07:00
|
|
|
|
|
|
|
var iVal2 = iVal++;
|
|
|
|
var iVal3 = ++iVal;
|
|
|
|
++iVal;
|
|
|
|
|
|
|
|
Test.Assert(iVal == 126);
|
|
|
|
Test.Assert(iVal2 == 123);
|
|
|
|
Test.Assert(iVal3 == 125);
|
2020-01-31 16:09:35 -08:00
|
|
|
}
|
2020-02-28 09:20:43 -08:00
|
|
|
|
|
|
|
const String cStrD = "D";
|
|
|
|
const char8* cStrPD = "D";
|
|
|
|
|
2020-03-11 07:57:20 -07:00
|
|
|
public static void TestDefaults(StringView sv = "ABC", IntStruct intStruct = 123)
|
|
|
|
{
|
|
|
|
Test.Assert(sv == "ABC");
|
|
|
|
Test.Assert(intStruct.mA == 123);
|
|
|
|
}
|
|
|
|
|
2020-02-28 09:20:43 -08:00
|
|
|
[Test]
|
|
|
|
public static void TestStringOp()
|
|
|
|
{
|
|
|
|
const String cStr1 = "A" + "B";
|
|
|
|
const String cStr2 = cStr1 + "C" + cStrD;
|
|
|
|
Test.Assert(cStr2 == "ABCD");
|
2020-06-18 06:12:14 -07:00
|
|
|
Test.Assert(cStr2 === "ABCD");
|
2020-02-28 09:20:43 -08:00
|
|
|
|
|
|
|
const char8* cStr3 = "A" + "B";
|
|
|
|
const char8* cStr4 = cStr1 + "C" + cStrPD;
|
|
|
|
Test.Assert(StringView(cStr4) == "ABCD");
|
2020-03-11 07:57:20 -07:00
|
|
|
|
|
|
|
TestDefaults();
|
2020-06-18 06:12:14 -07:00
|
|
|
|
|
|
|
String strA = scope String("ABCD");
|
|
|
|
Test.Assert(strA == cStr2);
|
|
|
|
Test.Assert(strA !== cStr1);
|
|
|
|
|
|
|
|
let strTup = (strA, strA);
|
|
|
|
Test.Assert(strTup == (cStr2, cStr2));
|
|
|
|
Test.Assert(strTup !== (cStr2, cStr2));
|
2020-02-28 09:20:43 -08:00
|
|
|
}
|
2020-05-27 09:46:09 -07:00
|
|
|
|
|
|
|
public static TTo Convert<TFrom, TTo>(TFrom val) where TTo : operator explicit TFrom
|
|
|
|
{
|
|
|
|
return (TTo)val;
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public static void TestConversion()
|
|
|
|
{
|
|
|
|
int a = 123;
|
|
|
|
float f = Convert<int, float>(a);
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
}
|