diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 0aa0ffe3..02743d19 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -17351,7 +17351,20 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m if (isCascade) mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_InCascade); 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 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); if (mModule->mAttributeState == &attributeState) diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 6cc82fd8..e502e1a6 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -971,6 +971,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type) case BfTypeCode_Int32: case BfTypeCode_UInt32: case BfTypeCode_Char32: + case BfTypeCode_StringId: *(int32*)ptr = constant->mInt32; return true; case BfTypeCode_Int64: @@ -1003,7 +1004,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type) return false; } - return false; + return true; } else { @@ -1055,6 +1056,24 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* 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; } @@ -1077,6 +1096,7 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type) case BfTypeCode_Int32: case BfTypeCode_UInt32: case BfTypeCode_Char32: + case BfTypeCode_StringId: return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr); case BfTypeCode_Int64: case BfTypeCode_UInt64: @@ -1097,7 +1117,7 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type) return BfIRValue(); } } - + if (type->IsTypedPrimitive()) { return ReadConstant(ptr, type->GetUnderlyingType()); @@ -1164,6 +1184,11 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type) irType.mId = type->mTypeId; return CreateConstAgg(irType, irValues); } + + if (type->IsInstanceOf(mModule->mCompiler->mStringTypeDef)) + { + return CreateConst(BfTypeCode_StringId, *(int32*)ptr); + } return BfIRValue(); } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index da37561e..d5355276 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -3029,7 +3029,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers } if (!mReportErrors) - { + { mCompiler->mPassInstance->SilentFail(); return NULL; } @@ -23842,6 +23842,8 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo continue; int checkMethodIdx = lookupMethodInstance->mVirtualTableIdx; + if (checkMethodIdx >= baseVirtualMethodTable.mSize) + FatalError("SlotVirtualMethod OOB in baseVirtualMethodTable[checkMethodIdx]"); auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx]; if (baseMethodRef.mDeclaringMethod.mMethodNum == -1) { diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 78c69a09..e8c63fac 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -3618,12 +3618,50 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta return false; } + BfType* innerType = NULL; + BfType* payloadType = NULL; + if (typeInst->IsUnion()) + innerType = typeInst->GetUnionInnerType(); + 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()) { - auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[1]); + BfIRValue dataVal = aggConstant->mValues[1]; + if ((payloadType != NULL) && (innerType != NULL)) + { + Array 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) return false; 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) - continue; + for (auto& fieldInstance : typeInst->mFieldInstances) + { + if (fieldInstance.mDataOffset < 0) + continue; - auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[fieldInstance.mDataIdx]); - if (fieldConstant == NULL) - return false; - if (!WriteConstant(module, addr + fieldInstance.mDataOffset, fieldConstant, fieldInstance.mResolvedType)) - return false; + auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[fieldInstance.mDataIdx]); + if (fieldConstant == NULL) + return false; + if (!WriteConstant(module, addr + fieldInstance.mDataOffset, fieldConstant, fieldInstance.mResolvedType)) + return false; + } } } return true; diff --git a/IDEHelper/Tests/src/ConstEval.bf b/IDEHelper/Tests/src/ConstEval.bf index 9f74e7d5..a5321279 100644 --- a/IDEHelper/Tests/src/ConstEval.bf +++ b/IDEHelper/Tests/src/ConstEval.bf @@ -6,6 +6,18 @@ namespace Tests { 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 { public int32 mA; @@ -145,6 +157,11 @@ namespace Tests return test!(); } + static String EnumAToStr(EnumA ea) + { + return ea.ToString(.. new .()); + } + [Test] public static void TestBasics() { @@ -183,6 +200,15 @@ namespace Tests Test.Assert(MethodC() == 1753); 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\")"); } } }