1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-17 15:46:05 +02:00
Beef/IDEHelper/Tests/src/ConstEval.bf

161 lines
3.3 KiB
Beef
Raw Normal View History

2020-12-23 08:53:38 -08:00
using System;
using System.Collections;
using System.Diagnostics;
namespace Tests
{
class ConstEval
{
struct StructA
{
public int32 mA;
public int32 mB;
public static int32 sVal = 1000;
public this(int32 a, int32 b)
{
mA = a + sVal;
mB = b;
}
}
const String cStrA = "Abc";
const String cStrB = GetStringA(cStrA, 12, 23);
2020-12-23 08:59:22 -08:00
// ConstEval attribute means this method will always be const-evaluated
2020-12-23 08:53:38 -08:00
[ConstEval]
static String GetStringA(String str, int a, int b)
{
// Const-eval functions can return scope-allocated data
return scope $"{str}:{a}:{b}";
}
static int32 Factorial(int32 n)
{
return n <= 1 ? 1 : (n * Factorial(n - 1));
}
static int32 Fibonacci(int32 n)
{
return n <= 1 ? n : Fibonacci(n - 1) + Fibonacci(n - 2);
}
public static String GetTypeDesc<T>()
{
String str = scope .();
T val = default;
val.GetType().GetFullName(str);
str.Append(" ");
for (var fieldInfo in typeof(T).GetFields())
{
if (!fieldInfo.IsInstanceField)
continue;
if (@fieldInfo.Index > 0)
str.Append(", ");
fieldInfo.FieldType.GetFullName(str);
str.Append(" ");
str.Append(fieldInfo.Name);
}
return str;
}
public static Span<int32> GetSorted(String numList)
{
List<int32> list = scope .();
for (var sv in numList.Split(','))
{
sv.Trim();
if (int32.Parse(sv) case .Ok(let val))
list.Add(val);
}
list.Sort();
return list;
}
public static int32 MethodA()
{
mixin Add10(var a)
{
a += 10
}
int32 a = 1;
void Inc()
{
a++;
}
for (int i < 2)
{
defer { a *= 2; }
Inc();
Add10!(a);
}
return a;
}
// This method can only be const evaluated
[ConstEval]
public static int32 ConstSum(params int32[] vals)
{
int32 sum = 0;
for (let val in vals)
sum += val;
return sum;
}
public static int32 MethodB()
{
// Returns different results depending on whether we are const-evaluating
return Compiler.IsConstEval ? 1 : 0;
}
public static int32 MethodC(StructA sa = .(1, 2), (int32, int32) tup = (20, 30), int32[2] arr = .(300, 400))
{
return sa.mA + sa.mB + tup.0 + tup.1 + arr[0] + arr[1];
}
[Test]
public static void TestBasics()
{
const int fac = Factorial(8);
Test.Assert(fac == 40320);
const int fib = Fibonacci(27);
Test.Assert(fib == 196418);
// Generated string has reference equality to equivalent literal
Test.Assert(cStrB === "Abc:12:23");
const String strC = GetTypeDesc<StructA>();
Test.Assert(strC === "Tests.ConstEval.StructA int32 mA, int32 mB");
// Const Span<T> results can be used to initialize statically-sized arrays
const int32[?] iArr = GetSorted("8, 1, 3, 7");
Compiler.Assert(iArr == .(1, 3, 7, 8));
Test.Assert(iArr == .(1, 3, 7, 8));
let val0 = [ConstEval]MethodA();
Compiler.Assert(val0 == 70);
let val1 = MethodA();
// 'val1' is a read-only variable, but not const, so the following line would fail
//Compiler.Assert(val1 == 24);
Test.Assert(val1 == 70);
// This method is marked as ConstEval so it always evaluates as const
let val2 = ConstSum(3, 20, 100);
Compiler.Assert(val2 == 123);
Test.Assert(MethodB() == 0);
Test.Assert([ConstEval]MethodB() == 1);
Test.Assert(MethodC() == 1753);
}
}
}