1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-21 01:18:02 +02:00
Beef/IDEHelper/Tests/src/Comptime.bf

280 lines
5.9 KiB
Beef
Raw Normal View History

2021-01-11 09:41:43 -08:00
using System;
using System.Diagnostics;
using System.Reflection;
2021-01-15 14:28:21 -08:00
using System.Collections;
2021-01-11 09:41:43 -08:00
namespace Tests
{
class Comptime
{
[AttributeUsage(.All)]
struct IFaceAAttribute : Attribute, IComptimeTypeApply
{
String mMemberName;
int32 mInitVal;
public int32 InitVal
{
set mut
{
mInitVal = value;
}
}
public this(String memberName)
{
mMemberName = memberName;
mInitVal = 0;
}
[Comptime]
public void ApplyToType(Type type)
{
Compiler.EmitTypeBody(type, scope $"""
2021-01-11 09:41:43 -08:00
public int32 m{mMemberName} = {mInitVal};
public int32 GetVal{mMemberName}() => mC;
""");
}
}
[AttributeUsage(.Method)]
struct LogAttribute : Attribute, IComptimeMethodApply
{
public static String gLog = new .() ~ delete _;
2021-01-11 09:41:43 -08:00
[Comptime]
public void ApplyToMethod(ComptimeMethodInfo method)
{
String emit = scope $"LogAttribute.gLog.AppendF($\"Called {method}";
for (var fieldIdx < method.ParamCount)
emit.AppendF($" {{ {method.GetParamName(fieldIdx)} }}");
2021-01-16 12:35:51 -08:00
emit.Append("\\n\");");
Compiler.EmitMethodEntry(method, emit);
2021-01-16 12:35:51 -08:00
if (var genericType = method.ReturnType as SpecializedGenericType)
{
if ((genericType.UnspecializedType == typeof(Result<>)) || (genericType.UnspecializedType == typeof(Result<,>)))
{
Compiler.EmitMethodExit(method, """
if (@return case .Err)
LogAttribute.gLog.AppendF($"Error: {@return}");
""");
}
}
2021-01-11 09:41:43 -08:00
}
}
[IFaceA("C", InitVal=345)]
class ClassA
{
public int mA = 123;
[OnCompile(.TypeInit), Comptime]
public static void Generate()
{
Compiler.EmitTypeBody(typeof(Self), """
2021-01-11 09:41:43 -08:00
public int32 mB = 234;
public int32 GetValB() => mB;
""");
}
}
2021-02-25 10:14:22 -08:00
[IFaceA("C", InitVal=345)]
struct StructA
{
public int mA = 123;
public static StructA sSA;
public const StructA cSA = .();
2021-02-25 10:14:22 -08:00
[OnCompile(.TypeInit), Comptime]
public static void Generate()
{
Compiler.EmitTypeBody(typeof(Self), """
public int32 mB = 234;
public int32 GetValB() => mB;
""");
}
}
2021-01-16 12:35:51 -08:00
enum MethodAErr
{
2021-01-16 12:35:51 -08:00
ErrorA,
ErrorB
}
2021-01-16 12:35:51 -08:00
[Log]
static Result<int, MethodAErr> MethodA(int a, int b)
{
return .Err(.ErrorB);
}
2021-01-16 06:26:55 -08:00
static Type GetBiggerType(Type t)
2021-01-15 14:28:21 -08:00
{
2021-01-16 06:26:55 -08:00
switch (t)
2021-01-15 14:28:21 -08:00
{
2021-01-16 06:26:55 -08:00
case typeof(int8): return typeof(int16);
case typeof(int16): return typeof(int32);
case typeof(int32): return typeof(int64);
case typeof(float): return typeof(double);
2021-01-15 14:28:21 -08:00
}
2021-01-16 06:26:55 -08:00
return null;
2021-01-15 14:28:21 -08:00
}
2021-01-16 06:26:55 -08:00
static TTo GetBigger<TFrom, TTo>(TFrom val) where TTo : comptype(GetBiggerType(typeof(TFrom))), operator explicit TFrom
2021-01-15 14:28:21 -08:00
{
2021-01-16 06:26:55 -08:00
return (.)val;
2021-01-15 14:28:21 -08:00
}
public struct TypePrinter<T>
{
const int cFieldCount = GetFieldCount();
const (int32, StringView)[cFieldCount] cMembers = Make();
static int GetFieldCount()
{
int fieldCount = 0;
for (let field in typeof(T).GetFields())
if (!field.IsStatic)
fieldCount++;
return fieldCount;
}
static decltype(cMembers) Make()
{
if (cFieldCount == 0)
return default(decltype(cMembers));
decltype(cMembers) fields = ?;
int i = 0;
for (let field in typeof(T).GetFields())
{
if (!field.IsStatic)
fields[i++] = (field.MemberOffset, field.Name);
}
return fields;
}
public override void ToString(String strBuffer)
{
for (var t in cMembers)
{
if (@t != 0)
strBuffer.Append("\n");
strBuffer.AppendF($"{t.0} {t.1}");
}
}
}
struct TestType
{
public float mX;
public float mY;
public float mZ;
}
class SerializationContext
{
public String mStr = new String() ~ delete _;
public void Serialize<T>(String name, T val) where T : struct
{
mStr.AppendF($"{name} {val}\n");
}
}
interface ISerializable
{
void Serialize(SerializationContext ctx);
}
[AttributeUsage(.Enum | .Struct | .Class, .NotInherited | .ReflectAttribute | .DisallowAllowMultiple)]
struct SerializableAttribute : Attribute, IComptimeTypeApply
{
[Comptime]
public void ApplyToType(Type type)
{
const String SERIALIZE_NAME = "void ISerializable.Serialize(SerializationContext ctx)\n";
String serializeBuffer = new .();
Compiler.Assert(!type.IsUnion);
for (let field in type.GetFields())
{
if (!field.IsInstanceField || field.DeclaringType != type)
continue;
serializeBuffer.AppendF($"\n\tctx.Serialize(\"{field.Name}\", {field.Name});");
}
Compiler.EmitTypeBody(type, scope $"{SERIALIZE_NAME}{{{serializeBuffer}\n}}\n");
2021-12-16 09:38:19 -05:00
Compiler.EmitAddInterface(type, typeof(ISerializable));
}
}
[Serializable]
2021-12-16 09:38:19 -05:00
struct Foo : this(float x, float y)
{
}
public class ComponentHandler<T>
where T : struct
{
uint8* data;
protected override void GCMarkMembers()
{
T* ptr = (T*)data;
GC.Mark!((*ptr));
}
}
const String cTest0 = Compiler.ReadText("Test0.txt");
2021-01-11 09:41:43 -08:00
[Test]
public static void TestBasics()
{
ClassA ca = scope .();
Test.Assert(ca.mA == 123);
Test.Assert(ca.mB == 234);
Test.Assert(ca.GetValB() == 234);
Test.Assert(ca.mC == 345);
Test.Assert(ca.GetValC() == 345);
2021-02-25 10:14:22 -08:00
StructA sa = .();
Test.Assert(sa.mA == 123);
Test.Assert(sa.mB == 234);
Test.Assert(sa.GetValB() == 234);
Test.Assert(sa.mC == 345);
Test.Assert(sa.GetValC() == 345);
Compiler.Mixin("int val = 99;");
Test.Assert(val == 99);
2021-01-16 12:35:51 -08:00
MethodA(34, 45).IgnoreError();
Debug.Assert(LogAttribute.gLog == "Called Tests.Comptime.MethodA(int a, int b) 34 45\nError: Err(ErrorB)");
2021-01-15 14:28:21 -08:00
2021-01-16 06:26:55 -08:00
var v0 = GetBigger((int8)123);
Test.Assert(v0.GetType() == typeof(int16));
String str = scope .();
TypePrinter<TestType> tp = .();
tp.ToString(str);
Debug.Assert(str == """
0 mX
4 mY
8 mZ
""");
Foo bar = .(10, 2);
ISerializable iSer = bar;
SerializationContext serCtx = scope .();
iSer.Serialize(serCtx);
Test.Assert(serCtx.mStr == "x 10\ny 2\n");
Test.Assert(cTest0 == "Test\n0");
2021-01-11 09:41:43 -08:00
}
}
}