mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Support System.Compiler values in comptime, SetReturnType, Enum helpers
This commit is contained in:
parent
0e86b5c49d
commit
2a55b5c7bb
14 changed files with 341 additions and 63 deletions
|
@ -259,6 +259,9 @@ namespace System
|
|||
[LinkName("#CallerExpression")]
|
||||
public static extern String[0x00FFFFFF] CallerExpression;
|
||||
|
||||
[LinkName("#OrigCalleeType")]
|
||||
public static extern Type OrigCalleeType;
|
||||
|
||||
[LinkName("#ProjectName")]
|
||||
public static extern String ProjectName;
|
||||
|
||||
|
@ -287,6 +290,7 @@ namespace System
|
|||
Runtime.FatalError("Assert failed");
|
||||
}
|
||||
|
||||
static extern void Comptime_SetReturnType(int32 typeId);
|
||||
static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str);
|
||||
static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
|
||||
static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
|
||||
|
@ -309,6 +313,12 @@ namespace System
|
|||
Comptime_EmitTypeBody((.)owner.TypeId, text);
|
||||
}
|
||||
|
||||
[Comptime(OnlyFromComptime=true)]
|
||||
public static void SetReturnType(Type type)
|
||||
{
|
||||
Comptime_SetReturnType((.)type.TypeId);
|
||||
}
|
||||
|
||||
[Comptime(OnlyFromComptime=true)]
|
||||
public static void EmitAddInterface(Type owner, Type iface)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,67 @@ namespace System
|
|||
{
|
||||
struct Enum
|
||||
{
|
||||
public static int Count
|
||||
{
|
||||
[Comptime(ConstEval=true)]
|
||||
get
|
||||
{
|
||||
int count = 0;
|
||||
for (var field in Compiler.OrigCalleeType.GetFields())
|
||||
{
|
||||
if (field.IsEnumCase)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public static var MinValue
|
||||
{
|
||||
[Comptime(ConstEval=true)]
|
||||
get
|
||||
{
|
||||
Compiler.SetReturnType(Compiler.OrigCalleeType);
|
||||
|
||||
int? minValue = null;
|
||||
for (var field in Compiler.OrigCalleeType.GetFields())
|
||||
{
|
||||
if (field.IsEnumCase)
|
||||
{
|
||||
if (minValue == null)
|
||||
minValue = field.[Friend]mFieldData.mData;
|
||||
else
|
||||
minValue = Math.Min(minValue.Value, field.[Friend]mFieldData.mData);
|
||||
}
|
||||
}
|
||||
return minValue.ValueOrDefault;
|
||||
}
|
||||
}
|
||||
|
||||
public static var MaxValue
|
||||
{
|
||||
[Comptime(ConstEval=true)]
|
||||
get
|
||||
{
|
||||
Compiler.SetReturnType(Compiler.OrigCalleeType);
|
||||
|
||||
int? maxValue = null;
|
||||
for (var field in Compiler.OrigCalleeType.GetFields())
|
||||
{
|
||||
if (field.IsEnumCase)
|
||||
{
|
||||
if (maxValue == null)
|
||||
maxValue = field.[Friend]mFieldData.mData;
|
||||
else
|
||||
maxValue = Math.Max(maxValue.Value, field.[Friend]mFieldData.mData);
|
||||
}
|
||||
}
|
||||
if (maxValue == null)
|
||||
return -1;
|
||||
return maxValue.ValueOrDefault;
|
||||
}
|
||||
}
|
||||
|
||||
public static void EnumToString(Type type, String strBuffer, int64 iVal)
|
||||
{
|
||||
for (var field in type.GetFields())
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace System.Reflection
|
|||
public int32 MemberOffset => (int32)mFieldData.mData;
|
||||
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
||||
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
|
||||
public bool IsEnumCase => mFieldData.mFlags.HasFlag(.EnumCase);
|
||||
public bool IsReadOnly => mFieldData.mFlags.HasFlag(.ReadOnly);
|
||||
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
|
||||
public bool IsPublic => (mFieldData.mFlags & .FieldAccessMask) == .Public;
|
||||
|
|
|
@ -4691,6 +4691,12 @@ void BfCompiler::ProcessAutocompleteTempType()
|
|||
auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDecl);
|
||||
if (propDeclaration != NULL)
|
||||
autoComplete->CheckProperty(propDeclaration);
|
||||
|
||||
if (BfNodeIsA<BfVarTypeReference>(propDef->mTypeRef))
|
||||
{
|
||||
// This is only valid for ConstEval properties
|
||||
}
|
||||
else
|
||||
module->ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
|
||||
|
||||
if (auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propDef->mFieldDeclaration))
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
#include "BfDeferEvalChecker.h"
|
||||
#include "BfUtil.h"
|
||||
|
||||
USING_NS_BF;
|
||||
|
||||
BfDeferEvalChecker::BfDeferEvalChecker()
|
||||
{
|
||||
mRootNode = NULL;
|
||||
mNeedsDeferEval = false;
|
||||
mDeferLiterals = true;
|
||||
mDeferDelegateBind = true;
|
||||
}
|
||||
|
||||
void BfDeferEvalChecker::Check(BfAstNode* node)
|
||||
{
|
||||
SetAndRestoreValue<BfAstNode*> rootNode(mRootNode, node);
|
||||
node->Accept(this);
|
||||
}
|
||||
|
||||
void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
|
||||
{
|
||||
mNeedsDeferEval = false;
|
||||
|
@ -174,3 +182,9 @@ void BfDeferEvalChecker::Visit(BfDefaultExpression* defaultExpr)
|
|||
mNeedsDeferEval = true;
|
||||
}
|
||||
|
||||
void BfDeferEvalChecker::Visit(BfVariableDeclaration* varDecl)
|
||||
{
|
||||
if (varDecl != mRootNode)
|
||||
mNeedsDeferEval = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ NS_BF_BEGIN
|
|||
class BfDeferEvalChecker : public BfStructuralVisitor
|
||||
{
|
||||
public:
|
||||
BfAstNode* mRootNode;
|
||||
bool mNeedsDeferEval;
|
||||
bool mDeferDelegateBind;
|
||||
bool mDeferLiterals;
|
||||
|
@ -15,6 +16,8 @@ public:
|
|||
public:
|
||||
BfDeferEvalChecker();
|
||||
|
||||
void Check(BfAstNode* node);
|
||||
|
||||
virtual void Visit(BfAstNode* node) override;
|
||||
|
||||
virtual void Visit(BfInitializerExpression* collectionInitExpr);
|
||||
|
@ -31,6 +34,7 @@ public:
|
|||
virtual void Visit(BfObjectCreateExpression* objCreateExpr) override;
|
||||
virtual void Visit(BfBinaryOperatorExpression* binOpExpr) override;
|
||||
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
||||
virtual void Visit(BfVariableDeclaration* varDecl) override;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4655,6 +4655,8 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
|
|||
}
|
||||
|
||||
mOrigPropTarget = mPropTarget;
|
||||
if (prop->mIsStatic)
|
||||
mOrigPropTarget = target;
|
||||
|
||||
if ((flags & BfLookupFieldFlag_IsAnonymous) == 0)
|
||||
{
|
||||
|
@ -4742,7 +4744,7 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
|
|||
|
||||
mPropDef = NULL;
|
||||
mPropSrc = NULL;
|
||||
mOrigPropTarget = NULL;
|
||||
mOrigPropTarget = BfTypedValue();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -5780,7 +5782,7 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
|||
{
|
||||
BfDeferEvalChecker deferEvalChecker;
|
||||
deferEvalChecker.mDeferDelegateBind = false;
|
||||
argExpr->Accept(&deferEvalChecker);
|
||||
deferEvalChecker.Check(argExpr);
|
||||
deferParamEval = deferEvalChecker.mNeedsDeferEval;
|
||||
}
|
||||
}
|
||||
|
@ -5938,7 +5940,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN
|
|||
mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);
|
||||
}
|
||||
|
||||
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, BfCreateCallFlags callFlags)
|
||||
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, BfCreateCallFlags callFlags, BfType* origTargetType)
|
||||
{
|
||||
// static int sCallIdx = 0;
|
||||
// if (!mModule->mCompiler->mIsResolveOnly)
|
||||
|
@ -6219,7 +6221,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
|||
}
|
||||
else
|
||||
{
|
||||
auto constRet = mModule->mCompiler->mCeMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
|
||||
CeCallSource ceCallSource(targetSrc);
|
||||
ceCallSource.mOrigCalleeType = origTargetType;
|
||||
auto constRet = mModule->mCompiler->mCeMachine->Call(ceCallSource, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
|
||||
if (constRet)
|
||||
{
|
||||
auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
|
||||
|
@ -7131,6 +7135,31 @@ void BfExprEvaluator::AddCallDependencies(BfMethodInstance* methodInstance)
|
|||
//TODO: delete argumentsZ
|
||||
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0)
|
||||
{
|
||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
|
||||
}
|
||||
else if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_Comptime) != 0) && (!mModule->mIsComptimeModule))
|
||||
{
|
||||
if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None))
|
||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
|
||||
}
|
||||
|
||||
if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) &&
|
||||
((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) &&
|
||||
((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None)) &&
|
||||
(!mModule->mIsComptimeModule))
|
||||
{
|
||||
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||
}
|
||||
|
||||
bool bypassVirtual = (callFlags & BfCreateCallFlags_BypassVirtual) != 0;
|
||||
bool skipThis = (callFlags & BfCreateCallFlags_SkipThis) != 0;;
|
||||
|
||||
|
@ -8194,7 +8223,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
physCallFlags = (BfCreateCallFlags)(physCallFlags | BfCreateCallFlags_GenericParamThis);
|
||||
|
||||
auto func = moduleMethodInstance.mFunc;
|
||||
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs, NULL, physCallFlags);
|
||||
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs, NULL, physCallFlags, origTarget.mType);
|
||||
|
||||
if ((methodInstance->mMethodDef->mIsNoReturn) && ((mBfEvalExprFlags & BfEvalExprFlags_IsExpressionBody) != 0) &&
|
||||
(mExpectingType != NULL) && (callResult.mType != mExpectingType))
|
||||
|
@ -10130,40 +10159,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
BfTypedValue result;
|
||||
BfTypedValue argCascade;
|
||||
|
||||
//
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0)
|
||||
{
|
||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
|
||||
}
|
||||
else if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_Comptime) != 0) && (!mModule->mIsComptimeModule))
|
||||
{
|
||||
if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None))
|
||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
|
||||
}
|
||||
|
||||
if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) &&
|
||||
((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) &&
|
||||
((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None)) &&
|
||||
(!mModule->mIsComptimeModule))
|
||||
{
|
||||
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||
}
|
||||
|
||||
BfCreateCallFlags subCallFlags = BfCreateCallFlags_None;
|
||||
if (bypassVirtual)
|
||||
subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_BypassVirtual);
|
||||
if (skipThis)
|
||||
subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_SkipThis);
|
||||
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);
|
||||
}
|
||||
|
||||
if (overrideReturnType != NULL)
|
||||
{
|
||||
|
@ -18409,6 +18410,9 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
|
|||
((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface())))
|
||||
{
|
||||
auto checkType = mOrigPropTarget.mType;
|
||||
|
||||
if ((checkType->IsNullable()) && (!mPropTarget.mType->IsNullable()))
|
||||
checkType = checkType->GetUnderlyingType();
|
||||
if (checkType->IsPointer())
|
||||
checkType = ((BfPointerType*)checkType)->mElementType;
|
||||
if (checkType->IsWrappableType())
|
||||
|
@ -23708,6 +23712,24 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
|||
|
||||
auto underlyingType = resultType->GetUnderlyingType();
|
||||
|
||||
if (binaryOp == BfBinaryOp_Subtract)
|
||||
{
|
||||
intptr maxDist = 0;
|
||||
auto resultTypeInstance = resultType->ToTypeInstance();
|
||||
if ((resultTypeInstance != NULL) && (resultTypeInstance->mTypeInfoEx != NULL))
|
||||
maxDist = resultTypeInstance->mTypeInfoEx->mMaxValue - resultTypeInstance->mTypeInfoEx->mMinValue;
|
||||
|
||||
if (maxDist >= 0x80000000UL)
|
||||
resultType = mModule->GetPrimitiveType(BfTypeCode_Int64);
|
||||
else if (maxDist >= 0x8000)
|
||||
resultType = mModule->GetPrimitiveType(BfTypeCode_Int32);
|
||||
else if (maxDist >= 0x80)
|
||||
resultType = mModule->GetPrimitiveType(BfTypeCode_Int16);
|
||||
else
|
||||
resultType = mModule->GetPrimitiveType(BfTypeCode_Int8);
|
||||
underlyingType = resultType;
|
||||
}
|
||||
|
||||
BfIRValue convResultValue;
|
||||
if (resultTypedValue->mType == resultType)
|
||||
convResultValue = mModule->LoadValue(*resultTypedValue).mValue;
|
||||
|
|
|
@ -476,7 +476,7 @@ public:
|
|||
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
|
||||
void AddCallDependencies(BfMethodInstance* methodInstance);
|
||||
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
|
||||
BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, BfCreateCallFlags callFlags = BfCreateCallFlags_None);
|
||||
BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, BfCreateCallFlags callFlags = BfCreateCallFlags_None, BfType* origTargetType = NULL);
|
||||
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL);
|
||||
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
|
||||
void MakeBaseConcrete(BfTypedValue& typedValue);
|
||||
|
|
|
@ -11348,7 +11348,7 @@ BfIRType BfModule::CurrentAddToConstHolder(BfIRType irType)
|
|||
if (irType.mKind == BfIRTypeData::TypeKind_SizedArray)
|
||||
{
|
||||
auto sizedArrayType = (BfConstantSizedArrayType*)mBfIRBuilder->GetConstantById(irType.mId);
|
||||
return mCurTypeInstance->GetOrCreateConstHolder()->GetSizedArrayType(CurrentAddToConstHolder(sizedArrayType->mType), sizedArrayType->mLength);
|
||||
return mCurTypeInstance->GetOrCreateConstHolder()->GetSizedArrayType(CurrentAddToConstHolder(sizedArrayType->mType), (int)sizedArrayType->mLength);
|
||||
}
|
||||
|
||||
return irType;
|
||||
|
@ -12591,6 +12591,8 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!mIsComptimeModule)
|
||||
return GetDefaultTypedValue(typedValue.mType);
|
||||
}
|
||||
}
|
||||
|
@ -14654,6 +14656,25 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str)
|
|||
filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
|
||||
return BfTypedValue(GetStringObjectValue(GetFileDir(filePath)), ResolveTypeDef(mCompiler->mStringTypeDef));
|
||||
}
|
||||
else if (str == "#CallerTypeName")
|
||||
{
|
||||
String typeName = "";
|
||||
if (mCurMethodState->mMixinState->mMixinMethodInstance)
|
||||
typeName = TypeToString(mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner());
|
||||
return BfTypedValue(GetStringObjectValue(typeName), ResolveTypeDef(mCompiler->mStringTypeDef));
|
||||
}
|
||||
else if (str == "#CallerType")
|
||||
{
|
||||
auto typeType = ResolveTypeDef(mCompiler->mTypeTypeDef);
|
||||
BfType* type = NULL;
|
||||
if (mCurMethodState->mMixinState->mMixinMethodInstance)
|
||||
type = mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner();
|
||||
if (type != NULL)
|
||||
{
|
||||
AddDependency(type, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
||||
return BfTypedValue(CreateTypeDataRef(type), typeType);
|
||||
}
|
||||
}
|
||||
else if (str == "#CallerMemberName")
|
||||
{
|
||||
String memberName = "";
|
||||
|
@ -15099,6 +15120,9 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo
|
|||
|
||||
void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
|
||||
{
|
||||
if ((localVar->mName == "maxValue") && (mIsComptimeModule))
|
||||
BF_ASSERT(!localVar->mAddr.IsFake());
|
||||
|
||||
while (localVar->mName.StartsWith('@'))
|
||||
{
|
||||
localVar->mNamePrefixCount++;
|
||||
|
|
|
@ -109,7 +109,8 @@ enum BfCastFlags
|
|||
BfCastFlags_WarnOnBox = 0x800,
|
||||
BfCastFlags_IsCastCheck = 0x1000,
|
||||
BfCastFlags_IsConstraintCheck = 0x2000,
|
||||
BfCastFlags_WantsConst = 0x4000
|
||||
BfCastFlags_WantsConst = 0x4000,
|
||||
BfCastFlags_FromComptimeReturn = 0x8000
|
||||
};
|
||||
|
||||
enum BfCastResultFlags : int8
|
||||
|
|
|
@ -4328,6 +4328,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
|
||||
}
|
||||
|
||||
bool isRootSystemType = typeInstance->IsInstanceOf(mCompiler->mValueTypeTypeDef) ||
|
||||
typeInstance->IsInstanceOf(mCompiler->mAttributeTypeDef) ||
|
||||
typeInstance->IsInstanceOf(mCompiler->mEnumTypeDef);
|
||||
|
||||
if (!typeInstance->IsBoxed())
|
||||
{
|
||||
if ((typeInstance->mCustomAttributes == NULL) && (typeDef->mTypeDeclaration != NULL) && (typeDef->HasCustomAttributes()))
|
||||
|
@ -4696,7 +4700,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
{
|
||||
// Already handled
|
||||
}
|
||||
else if ((fieldDef != NULL) && (fieldDef->GetFieldDeclaration() != NULL) && (fieldDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed))
|
||||
else if ((fieldDef != NULL) && (fieldDef->GetFieldDeclaration() != NULL) && (fieldDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed) && (!isRootSystemType))
|
||||
{
|
||||
if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
|
||||
{
|
||||
|
@ -4941,7 +4945,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
if (propDef->IsExpressionBodied())
|
||||
target = (BfAttributeTargets)(target | BfAttributeTargets_Method);
|
||||
|
||||
if ((propDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed))
|
||||
if ((propDef->GetFieldDeclaration()->mAttributes != NULL) && (!typeInstance->mTypeFailed) && (!isRootSystemType))
|
||||
{
|
||||
auto customAttrs = GetCustomAttributes(propDef->GetFieldDeclaration()->mAttributes, target);
|
||||
delete customAttrs;
|
||||
|
@ -5523,6 +5527,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
typeState.mCurTypeDef = propDef->mDeclaringType;
|
||||
typeState.mType = typeInstance;
|
||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||
|
||||
if (BfNodeIsA<BfVarTypeReference>(propDef->mTypeRef))
|
||||
{
|
||||
// This is only valid for ConstEval properties
|
||||
}
|
||||
else
|
||||
ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
|
||||
}
|
||||
}
|
||||
|
@ -14044,7 +14054,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
"Unable to cast '%s' to '%s'" :
|
||||
"Unable to implicitly cast '%s' to '%s'";
|
||||
|
||||
if ((castFlags & BfCastFlags_FromComptimeReturn) != 0)
|
||||
errStrF = "Comptime return unable to cast '%s' to '%s'";
|
||||
|
||||
String errStr = StrFormat(errStrF, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str());
|
||||
|
||||
auto error = Fail(errStr, srcNode);
|
||||
if ((error != NULL) && (srcNode != NULL))
|
||||
{
|
||||
|
|
|
@ -1024,6 +1024,19 @@ int CeBuilder::GetCallTableIdx(BeFunction* beFunction, CeOperand* outOperand)
|
|||
callEntry.mFunctionInfo = ceFunctionInfo;
|
||||
*callIdxPtr = (int)mCeFunction->mCallTable.size();
|
||||
mCeFunction->mCallTable.Add(callEntry);
|
||||
|
||||
if (ceFunctionInfo != NULL)
|
||||
{
|
||||
auto callerType = mCeFunction->mCeFunctionInfo->GetOwner();
|
||||
auto calleeType = ceFunctionInfo->GetOwner();
|
||||
|
||||
if ((callerType != NULL) && (calleeType != NULL))
|
||||
{
|
||||
// This will generally already be set, but there are some error cases (such as duplicate type names)
|
||||
// where this will not be set yet
|
||||
callerType->mModule->AddDependency(calleeType, callerType, BfDependencyMap::DependencyFlag_Calls);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *callIdxPtr;
|
||||
}
|
||||
|
@ -5148,7 +5161,8 @@ BfTypedValue CeContext::Call(CeCallSource callSource, BfModule* module, BfMethod
|
|||
mCeMachine->mAppendAllocInfo = NULL;
|
||||
|
||||
BfType* returnType = NULL;
|
||||
bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr, returnType);
|
||||
BfType* castReturnType = NULL;
|
||||
bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr, returnType, castReturnType);
|
||||
memStart = &mMemory[0];
|
||||
|
||||
addr_ce retInstAddr = retAddr;
|
||||
|
@ -5228,6 +5242,13 @@ BfTypedValue CeContext::Call(CeCallSource callSource, BfModule* module, BfMethod
|
|||
mCallStack = prevCallStack;
|
||||
}
|
||||
|
||||
if ((castReturnType != NULL) && (returnValue))
|
||||
{
|
||||
auto castedReturnValue = module->Cast(callSource.mRefNode, returnValue, castReturnType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_FromComptimeReturn));
|
||||
if (castedReturnValue)
|
||||
return castedReturnValue;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
@ -5486,7 +5507,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType)
|
||||
bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType, BfType*& castReturnType)
|
||||
{
|
||||
auto ceModule = mCeMachine->mCeModule;
|
||||
CeFunction* ceFunction = startFunction;
|
||||
|
@ -6057,6 +6078,14 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
_FixVariables();
|
||||
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_SetReturnType)
|
||||
{
|
||||
int32 typeId = *(int32*)((uint8*)stackPtr);
|
||||
if (returnType->IsVar())
|
||||
castReturnType = GetBfType(typeId);
|
||||
else
|
||||
_Fail("Comptime return types can only be set on methods declared with a 'var' return type");
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody)
|
||||
{
|
||||
int32 typeId = *(int32*)((uint8*)stackPtr);
|
||||
|
@ -7621,7 +7650,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
auto& ceStaticFieldEntry = ceFunction->mStaticFieldTable[tableIdx];
|
||||
if (ceStaticFieldEntry.mBindExecuteId != mExecuteId)
|
||||
{
|
||||
if (mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL))
|
||||
if ((mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL)) && (!ceStaticFieldEntry.mName.StartsWith("#")))
|
||||
{
|
||||
auto bfType = GetBfType(ceStaticFieldEntry.mTypeId);
|
||||
BfTypeInstance* bfTypeInstance = NULL;
|
||||
|
@ -7667,6 +7696,74 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
if (ceStaticFieldEntry.mSize > 0)
|
||||
memset(ptr, 0, ceStaticFieldEntry.mSize);
|
||||
staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
|
||||
|
||||
if (ceStaticFieldEntry.mName.StartsWith("#"))
|
||||
{
|
||||
addr_ce resultAddr = 0;
|
||||
|
||||
if (ceStaticFieldEntry.mName == "#CallerLineNum")
|
||||
{
|
||||
*(int*)ptr = mCurModule->mCurFilePosition.mCurLine;
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerFilePath")
|
||||
{
|
||||
String filePath;
|
||||
if (mCurModule->mCurFilePosition.mFileInstance != NULL)
|
||||
filePath = mCurModule->mCurFilePosition.mFileInstance->mParser->mFileName;
|
||||
resultAddr = GetString(filePath);
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerFileName")
|
||||
{
|
||||
String filePath;
|
||||
if (mCurModule->mCurFilePosition.mFileInstance != NULL)
|
||||
filePath = mCurModule->mCurFilePosition.mFileInstance->mParser->mFileName;
|
||||
resultAddr = GetString(GetFileName(filePath));
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerFileDir")
|
||||
{
|
||||
String filePath;
|
||||
if (mCurModule->mCurFilePosition.mFileInstance != NULL)
|
||||
filePath = mCurModule->mCurFilePosition.mFileInstance->mParser->mFileName;
|
||||
resultAddr = GetString(GetFileDir(filePath));
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerTypeName")
|
||||
{
|
||||
String typeName = "";
|
||||
typeName = mCeMachine->mCeModule->TypeToString(mCallerTypeInstance);
|
||||
resultAddr = GetString(typeName);
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerType")
|
||||
{
|
||||
addr_ce typeAddr = GetReflectType(mCallerTypeInstance->mTypeId);
|
||||
resultAddr = typeAddr;
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerMemberName")
|
||||
{
|
||||
String memberName = mCeMachine->mCeModule->MethodToString(mCallerMethodInstance);
|
||||
resultAddr = GetString(memberName);
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#CallerProject")
|
||||
{
|
||||
BfProject* project = NULL;
|
||||
project = mCallerTypeInstance->mTypeDef->mProject;
|
||||
if (project != NULL)
|
||||
resultAddr = GetString(project->mName);
|
||||
}
|
||||
else if (ceStaticFieldEntry.mName == "#OrigCalleeType")
|
||||
{
|
||||
if (mCurCallSource->mOrigCalleeType != NULL)
|
||||
{
|
||||
addr_ce typeAddr = GetReflectType(mCurCallSource->mOrigCalleeType->mTypeId);
|
||||
resultAddr = typeAddr;
|
||||
}
|
||||
}
|
||||
|
||||
if (resultAddr != 0)
|
||||
{
|
||||
_FixVariables();
|
||||
CeSetAddrVal(memStart + staticFieldInfo->mAddr, resultAddr, ptrSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ceStaticFieldEntry.mAddr = staticFieldInfo->mAddr;
|
||||
|
@ -9199,11 +9296,15 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
|
|||
}
|
||||
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
|
||||
{
|
||||
if (methodDef->mName == "Comptime_EmitTypeBody")
|
||||
if (methodDef->mName == "Comptime_SetReturnType")
|
||||
{
|
||||
ceFunction->mFunctionKind = CeFunctionKind_SetReturnType;
|
||||
}
|
||||
else if (methodDef->mName == "Comptime_EmitTypeBody")
|
||||
{
|
||||
ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
|
||||
}
|
||||
if (methodDef->mName == "Comptime_EmitAddInterface")
|
||||
else if (methodDef->mName == "Comptime_EmitAddInterface")
|
||||
{
|
||||
ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface;
|
||||
}
|
||||
|
@ -9524,6 +9625,11 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
|
|||
else
|
||||
{
|
||||
ceFunctionInfo = *namedFunctionInfoPtr;
|
||||
if ((ceFunctionInfo->mMethodInstance != NULL) && (ceFunctionInfo->mMethodInstance != methodInstance))
|
||||
{
|
||||
// This ceFunctionInfo is already taken - probably from a name mangling conflict
|
||||
ceFunctionInfo = new CeFunctionInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -331,6 +331,13 @@ public:
|
|||
}
|
||||
|
||||
~CeFunctionInfo();
|
||||
|
||||
BfTypeInstance* GetOwner()
|
||||
{
|
||||
if (mMethodInstance != NULL)
|
||||
return mMethodInstance->GetOwner();
|
||||
return mMethodRef.mTypeInstance;
|
||||
}
|
||||
};
|
||||
|
||||
class CeCallEntry
|
||||
|
@ -440,6 +447,7 @@ enum CeFunctionKind
|
|||
CeFunctionKind_Method_GetParamInfo,
|
||||
CeFunctionKind_Method_GetGenericArg,
|
||||
|
||||
CeFunctionKind_SetReturnType,
|
||||
CeFunctionKind_EmitTypeBody,
|
||||
CeFunctionKind_EmitAddInterface,
|
||||
CeFunctionKind_EmitMethodEntry,
|
||||
|
@ -1050,6 +1058,7 @@ public:
|
|||
Kind mKind;
|
||||
BfAstNode* mRefNode;
|
||||
BfFieldInstance* mFieldInstance;
|
||||
BfType* mOrigCalleeType;
|
||||
|
||||
public:
|
||||
CeCallSource(BfAstNode* refNode)
|
||||
|
@ -1057,6 +1066,7 @@ public:
|
|||
mKind = Kind_Unknown;
|
||||
mRefNode = refNode;
|
||||
mFieldInstance = NULL;
|
||||
mOrigCalleeType = NULL;
|
||||
}
|
||||
|
||||
CeCallSource()
|
||||
|
@ -1064,6 +1074,7 @@ public:
|
|||
mKind = Kind_Unknown;
|
||||
mRefNode = NULL;
|
||||
mFieldInstance = NULL;
|
||||
mOrigCalleeType = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1135,7 +1146,7 @@ public:
|
|||
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
|
||||
BfIRValue CreateAttribute(BfAstNode* targetSrc, BfModule* module, BfIRConstHolder* constHolder, BfCustomAttribute* customAttribute, addr_ce ceAttrAddr = 0);
|
||||
|
||||
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType);
|
||||
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType, BfType*& castReturnType);
|
||||
BfTypedValue Call(CeCallSource callSource, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
|
||||
};
|
||||
|
||||
|
|
|
@ -137,6 +137,10 @@ namespace Tests
|
|||
EnumG eg = .A;
|
||||
eg.Set(66);
|
||||
Test.Assert(eg == .B);
|
||||
|
||||
var ea = EnumA.MaxValue;
|
||||
Test.Assert(ea == .B);
|
||||
Test.Assert(EnumA.Count == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue