1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00
Beef/IDEHelper/Tests/src/Operators.bf

811 lines
14 KiB
Beef

#pragma warning disable 168
using System;
namespace System
{
public extension Event<T>
{
public implicit void operator+=(T action) mut
{
Add(action);
}
public implicit void operator-=(T action) mut
{
Remove(action, true);
}
}
}
namespace Tests
{
class Operators
{
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;
};
}
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;
}
public static StructA operator++(StructA val)
{
StructA newVal;
newVal.mA = val.mA + 1;
return newVal;
}
[Commutable]
public static bool operator<(StructA lhs, StructB rhs)
{
return lhs.mA < rhs.mB;
}
}
struct StructB
{
public int mB;
public static StructA operator+(StructA sa, StructB sb)
{
StructA result;
result.mA = sa.mA + sb.mB + 1000;
return result;
}
public void operator++() mut
{
mB++;
}
}
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;
}
}
struct StructD
{
int mVal;
public this(int val)
{
mVal = val;
}
public static implicit operator int(StructD x)
{
return x.mVal;
}
public static implicit operator StructD(int x)
{
return default(StructD);
}
}
struct StructE
{
float mVal;
public this(float val)
{
mVal = val;
}
public static implicit operator float(StructE x)
{
return x.mVal;
}
public static implicit operator StructE(float x)
{
return .(x);
}
public static StructE operator+(StructE lhs, StructE rhs)
{
return .(1);
}
public static int operator+(StructE lhs, int rhs)
{
return 2;
}
public static int operator+(int lhs, StructE rhs)
{
return 3;
}
}
struct StructF
{
public static int operator+(StructF lhs, int rhs)
{
return 1;
}
public static int operator+(int lhs, StructF rhs)
{
return 2;
}
[Commutable]
public static int operator+(StructF lhs, float rhs)
{
return 3;
}
}
struct StructG : this(int a)
{
public static StructG operator+(ref StructG lhs, ref StructG rhs)
{
lhs.a += 1000;
rhs.a += 1000;
return .(lhs.a + rhs.a);
}
public static StructG operator-(ref StructG val)
{
val.a += 1000;
return val;
}
public static implicit operator int(ref StructG val)
{
return val.a;
}
}
struct StructH
{
public static int operator+(StructH lhs, int rhs)
{
return 1;
}
public static int operator+(int lhs, StructH rhs)
{
return 2;
}
[Commutable]
public static int operator+(StructH lhs, float rhs)
{
return 3;
}
public static int operator&+(StructH lhs, int rhs)
{
return 4;
}
public static int operator&+(int lhs, StructH rhs)
{
return 5;
}
[Commutable]
public static int operator&+(StructH lhs, float rhs)
{
return 6;
}
}
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;
}
public T GetInt() where T : Int32
{
return mVal;
}
}
enum MyEnum
{
Case0,
Case1,
Case2,
Case3
}
enum MyOtherEnum
{
case Zero;
case One;
case Two;
case Three;
public static explicit operator MyEnum(Self self)
{
return .Case1;
}
}
struct StructI : int32
{
public static int8 operator implicit(Self self)
{
return 12;
}
public static int16 operator implicit(Self self)
{
return 23;
}
}
struct StructJ
{
public int mVal;
public static int8 operator implicit(Self self)
{
return 12;
}
public static int16 operator implicit(Self self)
{
return 23;
}
public static int32 operator explicit(Self self)
{
return 34;
}
public static Self operator explicit(int8 val)
{
return .(){mVal = 45};
}
public static Self operator implicit(int16 val)
{
return .(){mVal = 56};
}
public static Self operator implicit(int32 val)
{
return .(){mVal = 67};
}
}
struct StructK : uint64
{
public static T operator implicit<T>(Self self)
where T : operator explicit uint64
{
return (.)(uint64)self;
}
}
/*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;
}
public static T Complex<T, T2, T3>(T val, T2 val2, T3 val3)
where T : operator -T
where T : operator implicit T2
where T : operator T + T2
where int32 : operator T + T3
{
T conv = val2;
T result = val + val2;
result = -result;
int32 iRes = val + val3;
return result;
}
struct StructOp3<T, T2> where float : operator T + T2
{
public float Use(T lhs, T2 rhs)
{
float f = lhs + rhs;
return f;
}
}
public struct Vector2 : this(float x, float y);
public static Event<Action> sEvent ~ _.Dispose(); // Workaround for the lack of auto-destructor in properties
public static ref Event<Action> EventProp { get => ref sEvent; set => sEvent = value; };
static int sA = 123;
public static ref int RefVal => ref sA;
public static int Val
{
get
{
return sA;
}
set
{
sA = value;
}
}
[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);
StructB sb0;
sb0.mB = 11;
StructB sb1;
sb1.mB = 12;
Test.Assert(sa1 < sb0);
Test.Assert(!(sa1 >= sb0));
Test.Assert(sb0 > sa1);
Test.Assert(!(sb0 <= sa1));
StructA sa3 = sa0 + sb0;
Test.Assert(sa3.mA == 1012);
StructA sa4 = Op(sa0, sb0);
Test.Assert(sa4.mA == 1012);
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);
float val = Op((int32)100, (int16)23);
Test.Assert(val == 123);
int32 i32res = Complex((int32)100, (int16)23, (int8)4);
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);
Result<StructC> rsc = .Ok(.(123, 234));
Result<StructC> rsc2 = .Ok(.(123, 345));
Test.Assert(rsc == rsc2);
Test.Assert(rsc !== rsc2);
StructOp3<int16, int32> so3 = .();
float f = so3.Use(1, 2);
Test.Assert(f == 3);
FlagsRegister fr = .(true, false, true, true);
Test.Assert(fr == (uint8)0b10110000);
StructD sd = .(9);
Test.Assert(sd + 10 == 19);
Test.Assert(10 + sd == 19);
StructE se = .(9);
Test.Assert(se + 10 == 2);
Test.Assert(10 + se == 3);
Test.Assert(se + 1.2f == 1);
Test.Assert(1.2f + se == 1);
StructF sf = default;
Test.Assert(sf + 10 == 1);
Test.Assert(10 + sf == 2);
Test.Assert(sf + 1.0f == 3);
Test.Assert(2.0f + sf == 3);
Test.Assert(sf &+ 10 == 1);
Test.Assert(10 &+ sf == 2);
Test.Assert(sf &+ 1.0f == 3);
Test.Assert(2.0f &+ sf == 3);
StructH sh = default;
Test.Assert(sh + 10 == 1);
Test.Assert(10 + sh == 2);
Test.Assert(sh + 1.0f == 3);
Test.Assert(2.0f + sh == 3);
Test.Assert(sh &+ 10 == 4);
Test.Assert(10 &+ sh == 5);
Test.Assert(sh &+ 1.0f == 6);
Test.Assert(2.0f &+ sh == 6);
StructG sg = .(100);
StructG sg2 = .(200);
var sg3 = sg + sg2;
var sg4 = -sg3;
Test.Assert(sg.a == 1100);
Test.Assert(sg2.a == 1200);
Test.Assert(sg3.a == 3300);
Test.Assert(sg4.a == 3300);
/*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);*/
const int c0 = 1;
const int32 c1 = 1;
int i0 = 0;
var tVal = Vector2((i0 % c0) * (c1 + c1), 1);
int8 a = 123;
int32 b = a + 100;
Test.Assert(b == 223);
MyOtherEnum moe = .Zero;
MyEnum me = (MyEnum)moe;
Test.Assert(me == .Case1);
Test.Assert(moe == 0);
moe = .Two;
int32 i = (int32)moe;
Test.Assert(i == 2);
uint32 u = (uint32)moe;
Test.Assert(u == 2);
//
{
StructI si = (.)123;
int32 i32i = si;
int32 i32e = (int32)si;
int16 i16i = si;
int16 i16e = (int16)si;
int8 i8i = si;
int8 i8e = (int8)si;
float fi = si;
float fe = (float)si;
Test.Assert(i32i == 23);
Test.Assert(i32e == 123);
Test.Assert(i16i == 23);
Test.Assert(i16e == 23);
Test.Assert(i8i == 12);
Test.Assert(i8e == 12);
Test.Assert(fi == 23);
Test.Assert(fe == 123);
}
///
{
StructJ sj = default;
int32 i32i = sj;
int32 i32e = (int32)sj;
int16 i16i = sj;
int16 i16e = (int16)sj;
int8 i8i = sj;
int8 i8e = (int8)sj;
float fi = sj;
float fe = (float)sj;
StructJ sji32i = i32i;
StructJ sji32e = (.)i32e;
StructJ sji16i = i16i;
StructJ sji16e = (.)i16e;
StructJ sji8i = i8i;
StructJ sji8e = (.)i8e;
Test.Assert(i32i == 23);
Test.Assert(i32e == 34);
Test.Assert(i16i == 23);
Test.Assert(i16e == 23);
Test.Assert(i8i == 12);
Test.Assert(i8e == 12);
Test.Assert(fi == 23);
Test.Assert(fe == 34);
Test.Assert(sji32i.mVal == 67);
Test.Assert(sji32e.mVal == 67);
Test.Assert(sji16i.mVal == 56);
Test.Assert(sji16e.mVal == 56);
Test.Assert(sji8i.mVal == 56);
Test.Assert(sji8e.mVal == 45);
}
StructK sk = (.)123;
uint64 sku32 = sk;
Test.Assert(sku32 == 123);
int val2 = 10;
void Set()
{
val2 += 200;
}
EventProp += new => Set;
EventProp();
Test.Assert(val2 == 210);
RefVal += 99;
Test.Assert(sA == 222);
Val += 1000;
Test.Assert(sA == 1222);
RefCounted<String> rcStr = .Create("Abc");
Test.Assert(rcStr->Length == 3);
rcStr->Clear();
rcStr.Release();
//RefCounted<StructB> rcB = .Create();
}
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;
}
public static implicit operator Self(int val)
{
IntStruct sVal;
sVal.mA = val;
return sVal;
}
public void operator++() mut
{
mA++;
}
}
[Test]
public static void TestCompareWithCastOperator()
{
IntStruct iVal = .();
Test.Assert(iVal == 123);
Test.Assert(iVal == 123.0f);
var iVal2 = iVal++;
var iVal3 = ++iVal;
++iVal;
Test.Assert(iVal == 126);
Test.Assert(iVal2 == 123);
Test.Assert(iVal3 == 125);
}
const String cStrD = "D";
const char8* cStrPD = "D";
public static void TestDefaults(StringView sv = "ABC", IntStruct intStruct = 123)
{
Test.Assert(sv == "ABC");
Test.Assert(intStruct.mA == 123);
}
[Test]
public static void TestStringOp()
{
const String cStr1 = "A" + "B";
const String cStr2 = cStr1 + "C" + cStrD;
Test.Assert(cStr2 == "ABCD");
Test.Assert(cStr2 === "ABCD");
const char8* cStr3 = "A" + "B";
const char8* cStr4 = cStr1 + "C" + cStrPD;
Test.Assert(StringView(cStr4) == "ABCD");
TestDefaults();
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));
}
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);
}
}
}