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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|