mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Improved handling of strings in const enum payloads
This commit is contained in:
parent
63ef0fed7a
commit
c9f1e37da7
5 changed files with 121 additions and 14 deletions
|
@ -17351,7 +17351,20 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
||||||
if (isCascade)
|
if (isCascade)
|
||||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_InCascade);
|
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_InCascade);
|
||||||
ResolveArgValues(argValues, resolveArgsFlags);
|
ResolveArgValues(argValues, resolveArgsFlags);
|
||||||
mResult = MatchMethod(methodNodeSrc, methodBoundExpr, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, argValues, methodGenericArgs, checkedKind);
|
|
||||||
|
//
|
||||||
|
{
|
||||||
|
// We also apply this right before the actual call, but we need to set the comptime flag earlier
|
||||||
|
SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags);
|
||||||
|
|
||||||
|
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
|
||||||
|
{
|
||||||
|
mModule->mAttributeState->mUsed = true;
|
||||||
|
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
|
||||||
|
}
|
||||||
|
mResult = MatchMethod(methodNodeSrc, methodBoundExpr, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, argValues, methodGenericArgs, checkedKind);
|
||||||
|
}
|
||||||
|
|
||||||
argValues.HandleFixits(mModule);
|
argValues.HandleFixits(mModule);
|
||||||
|
|
||||||
if (mModule->mAttributeState == &attributeState)
|
if (mModule->mAttributeState == &attributeState)
|
||||||
|
|
|
@ -971,6 +971,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
|
||||||
case BfTypeCode_Int32:
|
case BfTypeCode_Int32:
|
||||||
case BfTypeCode_UInt32:
|
case BfTypeCode_UInt32:
|
||||||
case BfTypeCode_Char32:
|
case BfTypeCode_Char32:
|
||||||
|
case BfTypeCode_StringId:
|
||||||
*(int32*)ptr = constant->mInt32;
|
*(int32*)ptr = constant->mInt32;
|
||||||
return true;
|
return true;
|
||||||
case BfTypeCode_Int64:
|
case BfTypeCode_Int64:
|
||||||
|
@ -1003,7 +1004,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1055,6 +1056,24 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
|
||||||
return WriteConstant(BfIRValue(BfIRValueFlags_Const, constBitCast->mTarget), ptr, type);
|
return WriteConstant(BfIRValue(BfIRValueFlags_Const, constBitCast->mTarget), ptr, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (constant->mConstType == BfConstType_GlobalVar)
|
||||||
|
{
|
||||||
|
auto constGV = (BfGlobalVar*)constant;
|
||||||
|
const char* strDataPrefix = "__bfStrData";
|
||||||
|
if (strncmp(constGV->mName, strDataPrefix, strlen(strDataPrefix)) == 0)
|
||||||
|
{
|
||||||
|
*(int32*)ptr = atoi(constGV->mName + strlen(strDataPrefix));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* strObjPrefix = "__bfStrObj";
|
||||||
|
if (strncmp(constGV->mName, strObjPrefix, strlen(strObjPrefix)) == 0)
|
||||||
|
{
|
||||||
|
*(int32*)ptr = atoi(constGV->mName + strlen(strObjPrefix));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,6 +1096,7 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
|
||||||
case BfTypeCode_Int32:
|
case BfTypeCode_Int32:
|
||||||
case BfTypeCode_UInt32:
|
case BfTypeCode_UInt32:
|
||||||
case BfTypeCode_Char32:
|
case BfTypeCode_Char32:
|
||||||
|
case BfTypeCode_StringId:
|
||||||
return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr);
|
return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr);
|
||||||
case BfTypeCode_Int64:
|
case BfTypeCode_Int64:
|
||||||
case BfTypeCode_UInt64:
|
case BfTypeCode_UInt64:
|
||||||
|
@ -1097,7 +1117,7 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
|
||||||
return BfIRValue();
|
return BfIRValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->IsTypedPrimitive())
|
if (type->IsTypedPrimitive())
|
||||||
{
|
{
|
||||||
return ReadConstant(ptr, type->GetUnderlyingType());
|
return ReadConstant(ptr, type->GetUnderlyingType());
|
||||||
|
@ -1164,6 +1184,11 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
|
||||||
irType.mId = type->mTypeId;
|
irType.mId = type->mTypeId;
|
||||||
return CreateConstAgg(irType, irValues);
|
return CreateConstAgg(irType, irValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type->IsInstanceOf(mModule->mCompiler->mStringTypeDef))
|
||||||
|
{
|
||||||
|
return CreateConst(BfTypeCode_StringId, *(int32*)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
return BfIRValue();
|
return BfIRValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3029,7 +3029,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mReportErrors)
|
if (!mReportErrors)
|
||||||
{
|
{
|
||||||
mCompiler->mPassInstance->SilentFail();
|
mCompiler->mPassInstance->SilentFail();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -23842,6 +23842,8 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int checkMethodIdx = lookupMethodInstance->mVirtualTableIdx;
|
int checkMethodIdx = lookupMethodInstance->mVirtualTableIdx;
|
||||||
|
if (checkMethodIdx >= baseVirtualMethodTable.mSize)
|
||||||
|
FatalError("SlotVirtualMethod OOB in baseVirtualMethodTable[checkMethodIdx]");
|
||||||
auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx];
|
auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx];
|
||||||
if (baseMethodRef.mDeclaringMethod.mMethodNum == -1)
|
if (baseMethodRef.mDeclaringMethod.mMethodNum == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3618,12 +3618,50 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfType* innerType = NULL;
|
||||||
|
BfType* payloadType = NULL;
|
||||||
|
if (typeInst->IsUnion())
|
||||||
|
innerType = typeInst->GetUnionInnerType();
|
||||||
|
|
||||||
if (typeInst->IsPayloadEnum())
|
if (typeInst->IsPayloadEnum())
|
||||||
{
|
{
|
||||||
auto innerType = typeInst->GetUnionInnerType();
|
auto& dscrFieldInstance = typeInst->mFieldInstances.back();
|
||||||
|
|
||||||
|
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[dscrFieldInstance.mDataIdx]);
|
||||||
|
if (fieldConstant == NULL)
|
||||||
|
return false;
|
||||||
|
if (!WriteConstant(module, addr + dscrFieldInstance.mDataOffset, fieldConstant, dscrFieldInstance.mResolvedType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto& fieldInstance : typeInst->mFieldInstances)
|
||||||
|
{
|
||||||
|
auto fieldDef = fieldInstance.GetFieldDef();
|
||||||
|
if (!fieldInstance.mIsEnumPayloadCase)
|
||||||
|
continue;
|
||||||
|
int tagIdx = -fieldInstance.mDataIdx - 1;
|
||||||
|
if (fieldConstant->mInt32 == tagIdx)
|
||||||
|
payloadType = fieldInstance.mResolvedType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeInst->IsUnion())
|
||||||
|
{
|
||||||
if (!innerType->IsValuelessType())
|
if (!innerType->IsValuelessType())
|
||||||
{
|
{
|
||||||
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[1]);
|
BfIRValue dataVal = aggConstant->mValues[1];
|
||||||
|
if ((payloadType != NULL) && (innerType != NULL))
|
||||||
|
{
|
||||||
|
Array<uint8> memArr;
|
||||||
|
memArr.Resize(innerType->mSize);
|
||||||
|
if (!module->mBfIRBuilder->WriteConstant(dataVal, memArr.mVals, innerType))
|
||||||
|
return false;
|
||||||
|
dataVal = module->mBfIRBuilder->ReadConstant(memArr.mVals, payloadType);
|
||||||
|
if (!dataVal)
|
||||||
|
return false;
|
||||||
|
innerType = payloadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fieldConstant = module->mBfIRBuilder->GetConstant(dataVal);
|
||||||
if (fieldConstant == NULL)
|
if (fieldConstant == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (!WriteConstant(module, addr, fieldConstant, innerType))
|
if (!WriteConstant(module, addr, fieldConstant, innerType))
|
||||||
|
@ -3631,16 +3669,19 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& fieldInstance : typeInst->mFieldInstances)
|
if (!typeInst->IsUnion())
|
||||||
{
|
{
|
||||||
if (fieldInstance.mDataOffset < 0)
|
for (auto& fieldInstance : typeInst->mFieldInstances)
|
||||||
continue;
|
{
|
||||||
|
if (fieldInstance.mDataOffset < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[fieldInstance.mDataIdx]);
|
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[fieldInstance.mDataIdx]);
|
||||||
if (fieldConstant == NULL)
|
if (fieldConstant == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (!WriteConstant(module, addr + fieldInstance.mDataOffset, fieldConstant, fieldInstance.mResolvedType))
|
if (!WriteConstant(module, addr + fieldInstance.mDataOffset, fieldConstant, fieldInstance.mResolvedType))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -6,6 +6,18 @@ namespace Tests
|
||||||
{
|
{
|
||||||
class ConstEval
|
class ConstEval
|
||||||
{
|
{
|
||||||
|
public enum EnumA
|
||||||
|
{
|
||||||
|
case A;
|
||||||
|
case B(float a, float b);
|
||||||
|
case C(String str);
|
||||||
|
|
||||||
|
public struct Inner
|
||||||
|
{
|
||||||
|
public const EnumA cVal = EnumA.C("InnerTest");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct StructA
|
struct StructA
|
||||||
{
|
{
|
||||||
public int32 mA;
|
public int32 mA;
|
||||||
|
@ -145,6 +157,11 @@ namespace Tests
|
||||||
return test!();
|
return test!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String EnumAToStr(EnumA ea)
|
||||||
|
{
|
||||||
|
return ea.ToString(.. new .());
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -183,6 +200,15 @@ namespace Tests
|
||||||
|
|
||||||
Test.Assert(MethodC() == 1753);
|
Test.Assert(MethodC() == 1753);
|
||||||
Test.Assert(StrLenMixin("ABCD") == 4);
|
Test.Assert(StrLenMixin("ABCD") == 4);
|
||||||
|
|
||||||
|
String s1 = [ConstEval]EnumAToStr(.C("Test1"));
|
||||||
|
Test.Assert(s1 === "C(\"Test1\")");
|
||||||
|
const String s2 = EnumAToStr(.C("Test2"));
|
||||||
|
Test.Assert(s2 === "C(\"Test2\")");
|
||||||
|
const String s3 = EnumAToStr(.B(1, 2));
|
||||||
|
Test.Assert(s3 === "B(1, 2)");
|
||||||
|
const let s4 = EnumAToStr(EnumA.Inner.cVal);
|
||||||
|
Test.Assert(s4 === "C(\"InnerTest\")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue