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")]
|
[LinkName("#CallerExpression")]
|
||||||
public static extern String[0x00FFFFFF] CallerExpression;
|
public static extern String[0x00FFFFFF] CallerExpression;
|
||||||
|
|
||||||
|
[LinkName("#OrigCalleeType")]
|
||||||
|
public static extern Type OrigCalleeType;
|
||||||
|
|
||||||
[LinkName("#ProjectName")]
|
[LinkName("#ProjectName")]
|
||||||
public static extern String ProjectName;
|
public static extern String ProjectName;
|
||||||
|
|
||||||
|
@ -287,6 +290,7 @@ namespace System
|
||||||
Runtime.FatalError("Assert failed");
|
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_MethodBuilder_EmitStr(void* native, StringView str);
|
||||||
static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
|
static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
|
||||||
static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
|
static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
|
||||||
|
@ -309,6 +313,12 @@ namespace System
|
||||||
Comptime_EmitTypeBody((.)owner.TypeId, text);
|
Comptime_EmitTypeBody((.)owner.TypeId, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Comptime(OnlyFromComptime=true)]
|
||||||
|
public static void SetReturnType(Type type)
|
||||||
|
{
|
||||||
|
Comptime_SetReturnType((.)type.TypeId);
|
||||||
|
}
|
||||||
|
|
||||||
[Comptime(OnlyFromComptime=true)]
|
[Comptime(OnlyFromComptime=true)]
|
||||||
public static void EmitAddInterface(Type owner, Type iface)
|
public static void EmitAddInterface(Type owner, Type iface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,67 @@ namespace System
|
||||||
{
|
{
|
||||||
struct Enum
|
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)
|
public static void EnumToString(Type type, String strBuffer, int64 iVal)
|
||||||
{
|
{
|
||||||
for (var field in type.GetFields())
|
for (var field in type.GetFields())
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace System.Reflection
|
||||||
public int32 MemberOffset => (int32)mFieldData.mData;
|
public int32 MemberOffset => (int32)mFieldData.mData;
|
||||||
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
||||||
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
|
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
|
||||||
|
public bool IsEnumCase => mFieldData.mFlags.HasFlag(.EnumCase);
|
||||||
public bool IsReadOnly => mFieldData.mFlags.HasFlag(.ReadOnly);
|
public bool IsReadOnly => mFieldData.mFlags.HasFlag(.ReadOnly);
|
||||||
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
|
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
|
||||||
public bool IsPublic => (mFieldData.mFlags & .FieldAccessMask) == .Public;
|
public bool IsPublic => (mFieldData.mFlags & .FieldAccessMask) == .Public;
|
||||||
|
|
|
@ -4691,7 +4691,13 @@ void BfCompiler::ProcessAutocompleteTempType()
|
||||||
auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDecl);
|
auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDecl);
|
||||||
if (propDeclaration != NULL)
|
if (propDeclaration != NULL)
|
||||||
autoComplete->CheckProperty(propDeclaration);
|
autoComplete->CheckProperty(propDeclaration);
|
||||||
module->ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
|
|
||||||
|
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))
|
if (auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propDef->mFieldDeclaration))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
#include "BfDeferEvalChecker.h"
|
#include "BfDeferEvalChecker.h"
|
||||||
|
#include "BfUtil.h"
|
||||||
|
|
||||||
USING_NS_BF;
|
USING_NS_BF;
|
||||||
|
|
||||||
BfDeferEvalChecker::BfDeferEvalChecker()
|
BfDeferEvalChecker::BfDeferEvalChecker()
|
||||||
{
|
{
|
||||||
|
mRootNode = NULL;
|
||||||
mNeedsDeferEval = false;
|
mNeedsDeferEval = false;
|
||||||
mDeferLiterals = true;
|
mDeferLiterals = true;
|
||||||
mDeferDelegateBind = true;
|
mDeferDelegateBind = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfDeferEvalChecker::Check(BfAstNode* node)
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<BfAstNode*> rootNode(mRootNode, node);
|
||||||
|
node->Accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
|
void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
|
||||||
|
@ -174,3 +182,9 @@ void BfDeferEvalChecker::Visit(BfDefaultExpression* defaultExpr)
|
||||||
mNeedsDeferEval = true;
|
mNeedsDeferEval = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfDeferEvalChecker::Visit(BfVariableDeclaration* varDecl)
|
||||||
|
{
|
||||||
|
if (varDecl != mRootNode)
|
||||||
|
mNeedsDeferEval = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ NS_BF_BEGIN
|
||||||
class BfDeferEvalChecker : public BfStructuralVisitor
|
class BfDeferEvalChecker : public BfStructuralVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
BfAstNode* mRootNode;
|
||||||
bool mNeedsDeferEval;
|
bool mNeedsDeferEval;
|
||||||
bool mDeferDelegateBind;
|
bool mDeferDelegateBind;
|
||||||
bool mDeferLiterals;
|
bool mDeferLiterals;
|
||||||
|
@ -15,6 +16,8 @@ public:
|
||||||
public:
|
public:
|
||||||
BfDeferEvalChecker();
|
BfDeferEvalChecker();
|
||||||
|
|
||||||
|
void Check(BfAstNode* node);
|
||||||
|
|
||||||
virtual void Visit(BfAstNode* node) override;
|
virtual void Visit(BfAstNode* node) override;
|
||||||
|
|
||||||
virtual void Visit(BfInitializerExpression* collectionInitExpr);
|
virtual void Visit(BfInitializerExpression* collectionInitExpr);
|
||||||
|
@ -29,8 +32,9 @@ public:
|
||||||
virtual void Visit(BfConditionalExpression* condExpr) override;
|
virtual void Visit(BfConditionalExpression* condExpr) override;
|
||||||
virtual void Visit(BfUnaryOperatorExpression* unaryOpExpr) override;
|
virtual void Visit(BfUnaryOperatorExpression* unaryOpExpr) override;
|
||||||
virtual void Visit(BfObjectCreateExpression* objCreateExpr) override;
|
virtual void Visit(BfObjectCreateExpression* objCreateExpr) override;
|
||||||
virtual void Visit(BfBinaryOperatorExpression* binOpExpr) override;
|
virtual void Visit(BfBinaryOperatorExpression* binOpExpr) override;
|
||||||
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
||||||
|
virtual void Visit(BfVariableDeclaration* varDecl) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4630,7 +4630,7 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
|
||||||
bool isBaseLookup = (target.mType) && (typeInstance != target.mType);
|
bool isBaseLookup = (target.mType) && (typeInstance != target.mType);
|
||||||
if ((isBaseLookup) && (target.mType->IsWrappableType()))
|
if ((isBaseLookup) && (target.mType->IsWrappableType()))
|
||||||
isBaseLookup = false;
|
isBaseLookup = false;
|
||||||
|
|
||||||
if (prop->mIsStatic)
|
if (prop->mIsStatic)
|
||||||
mPropTarget = BfTypedValue(typeInstance);
|
mPropTarget = BfTypedValue(typeInstance);
|
||||||
else if (isBaseLookup)
|
else if (isBaseLookup)
|
||||||
|
@ -4655,6 +4655,8 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
|
||||||
}
|
}
|
||||||
|
|
||||||
mOrigPropTarget = mPropTarget;
|
mOrigPropTarget = mPropTarget;
|
||||||
|
if (prop->mIsStatic)
|
||||||
|
mOrigPropTarget = target;
|
||||||
|
|
||||||
if ((flags & BfLookupFieldFlag_IsAnonymous) == 0)
|
if ((flags & BfLookupFieldFlag_IsAnonymous) == 0)
|
||||||
{
|
{
|
||||||
|
@ -4742,7 +4744,7 @@ BfTypedValue BfExprEvaluator::LoadProperty(BfAstNode* targetSrc, BfTypedValue ta
|
||||||
|
|
||||||
mPropDef = NULL;
|
mPropDef = NULL;
|
||||||
mPropSrc = NULL;
|
mPropSrc = NULL;
|
||||||
mOrigPropTarget = NULL;
|
mOrigPropTarget = BfTypedValue();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5780,7 +5782,7 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
||||||
{
|
{
|
||||||
BfDeferEvalChecker deferEvalChecker;
|
BfDeferEvalChecker deferEvalChecker;
|
||||||
deferEvalChecker.mDeferDelegateBind = false;
|
deferEvalChecker.mDeferDelegateBind = false;
|
||||||
argExpr->Accept(&deferEvalChecker);
|
deferEvalChecker.Check(argExpr);
|
||||||
deferParamEval = deferEvalChecker.mNeedsDeferEval;
|
deferParamEval = deferEvalChecker.mNeedsDeferEval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5938,7 +5940,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN
|
||||||
mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);
|
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;
|
// static int sCallIdx = 0;
|
||||||
// if (!mModule->mCompiler->mIsResolveOnly)
|
// if (!mModule->mCompiler->mIsResolveOnly)
|
||||||
|
@ -6218,8 +6220,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (constRet)
|
||||||
{
|
{
|
||||||
auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
|
auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
|
||||||
|
@ -7131,6 +7135,31 @@ void BfExprEvaluator::AddCallDependencies(BfMethodInstance* methodInstance)
|
||||||
//TODO: delete argumentsZ
|
//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)
|
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 bypassVirtual = (callFlags & BfCreateCallFlags_BypassVirtual) != 0;
|
||||||
bool skipThis = (callFlags & BfCreateCallFlags_SkipThis) != 0;;
|
bool skipThis = (callFlags & BfCreateCallFlags_SkipThis) != 0;;
|
||||||
|
|
||||||
|
@ -8194,7 +8223,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
physCallFlags = (BfCreateCallFlags)(physCallFlags | BfCreateCallFlags_GenericParamThis);
|
physCallFlags = (BfCreateCallFlags)(physCallFlags | BfCreateCallFlags_GenericParamThis);
|
||||||
|
|
||||||
auto func = moduleMethodInstance.mFunc;
|
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) &&
|
if ((methodInstance->mMethodDef->mIsNoReturn) && ((mBfEvalExprFlags & BfEvalExprFlags_IsExpressionBody) != 0) &&
|
||||||
(mExpectingType != NULL) && (callResult.mType != mExpectingType))
|
(mExpectingType != NULL) && (callResult.mType != mExpectingType))
|
||||||
|
@ -10129,41 +10158,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
|
|
||||||
BfTypedValue result;
|
BfTypedValue result;
|
||||||
BfTypedValue argCascade;
|
BfTypedValue argCascade;
|
||||||
|
|
||||||
//
|
|
||||||
{
|
|
||||||
SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags);
|
|
||||||
|
|
||||||
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
|
BfCreateCallFlags subCallFlags = BfCreateCallFlags_None;
|
||||||
{
|
if (bypassVirtual)
|
||||||
mModule->mAttributeState->mUsed = true;
|
subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_BypassVirtual);
|
||||||
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
|
if (skipThis)
|
||||||
}
|
subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_SkipThis);
|
||||||
else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0)
|
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);
|
||||||
{
|
|
||||||
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)
|
if (overrideReturnType != NULL)
|
||||||
{
|
{
|
||||||
|
@ -18409,10 +18410,13 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
|
||||||
((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface())))
|
((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface())))
|
||||||
{
|
{
|
||||||
auto checkType = mOrigPropTarget.mType;
|
auto checkType = mOrigPropTarget.mType;
|
||||||
|
|
||||||
|
if ((checkType->IsNullable()) && (!mPropTarget.mType->IsNullable()))
|
||||||
|
checkType = checkType->GetUnderlyingType();
|
||||||
if (checkType->IsPointer())
|
if (checkType->IsPointer())
|
||||||
checkType = ((BfPointerType*)checkType)->mElementType;
|
checkType = ((BfPointerType*)checkType)->mElementType;
|
||||||
if (checkType->IsWrappableType())
|
if (checkType->IsWrappableType())
|
||||||
checkType = mModule->GetWrappedStructType(checkType);
|
checkType = mModule->GetWrappedStructType(checkType);
|
||||||
if ((checkType != NULL) && (checkType->IsTypeInstance()))
|
if ((checkType != NULL) && (checkType->IsTypeInstance()))
|
||||||
{
|
{
|
||||||
auto activeTypeDef = mModule->GetActiveTypeDef();
|
auto activeTypeDef = mModule->GetActiveTypeDef();
|
||||||
|
@ -23707,6 +23711,24 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
}
|
}
|
||||||
|
|
||||||
auto underlyingType = resultType->GetUnderlyingType();
|
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;
|
BfIRValue convResultValue;
|
||||||
if (resultTypedValue->mType == resultType)
|
if (resultTypedValue->mType == resultType)
|
||||||
|
@ -23728,7 +23750,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
else
|
else
|
||||||
PerformBinaryOperation(underlyingType, convOtherValue, convResultValue, binaryOp, opToken);
|
PerformBinaryOperation(underlyingType, convOtherValue, convResultValue, binaryOp, opToken);
|
||||||
if (mResult.mType == underlyingType)
|
if (mResult.mType == underlyingType)
|
||||||
mResult.mType = resultType;
|
mResult.mType = resultType;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,7 @@ public:
|
||||||
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
|
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
|
||||||
void AddCallDependencies(BfMethodInstance* methodInstance);
|
void AddCallDependencies(BfMethodInstance* methodInstance);
|
||||||
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
|
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(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);
|
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
|
||||||
void MakeBaseConcrete(BfTypedValue& typedValue);
|
void MakeBaseConcrete(BfTypedValue& typedValue);
|
||||||
|
|
|
@ -11348,7 +11348,7 @@ BfIRType BfModule::CurrentAddToConstHolder(BfIRType irType)
|
||||||
if (irType.mKind == BfIRTypeData::TypeKind_SizedArray)
|
if (irType.mKind == BfIRTypeData::TypeKind_SizedArray)
|
||||||
{
|
{
|
||||||
auto sizedArrayType = (BfConstantSizedArrayType*)mBfIRBuilder->GetConstantById(irType.mId);
|
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;
|
return irType;
|
||||||
|
@ -12591,7 +12591,9 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return GetDefaultTypedValue(typedValue.mType);
|
|
||||||
|
if (!mIsComptimeModule)
|
||||||
|
return GetDefaultTypedValue(typedValue.mType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14654,6 +14656,25 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str)
|
||||||
filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
|
filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
|
||||||
return BfTypedValue(GetStringObjectValue(GetFileDir(filePath)), ResolveTypeDef(mCompiler->mStringTypeDef));
|
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")
|
else if (str == "#CallerMemberName")
|
||||||
{
|
{
|
||||||
String memberName = "";
|
String memberName = "";
|
||||||
|
@ -14668,7 +14689,7 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str)
|
||||||
if (project != NULL)
|
if (project != NULL)
|
||||||
return BfTypedValue(GetStringObjectValue(mProject->mName), ResolveTypeDef(mCompiler->mStringTypeDef));
|
return BfTypedValue(GetStringObjectValue(mProject->mName), ResolveTypeDef(mCompiler->mStringTypeDef));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str == "#TimeLocal")
|
if (str == "#TimeLocal")
|
||||||
{
|
{
|
||||||
|
@ -15099,6 +15120,9 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo
|
||||||
|
|
||||||
void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
|
void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
|
||||||
{
|
{
|
||||||
|
if ((localVar->mName == "maxValue") && (mIsComptimeModule))
|
||||||
|
BF_ASSERT(!localVar->mAddr.IsFake());
|
||||||
|
|
||||||
while (localVar->mName.StartsWith('@'))
|
while (localVar->mName.StartsWith('@'))
|
||||||
{
|
{
|
||||||
localVar->mNamePrefixCount++;
|
localVar->mNamePrefixCount++;
|
||||||
|
|
|
@ -109,7 +109,8 @@ enum BfCastFlags
|
||||||
BfCastFlags_WarnOnBox = 0x800,
|
BfCastFlags_WarnOnBox = 0x800,
|
||||||
BfCastFlags_IsCastCheck = 0x1000,
|
BfCastFlags_IsCastCheck = 0x1000,
|
||||||
BfCastFlags_IsConstraintCheck = 0x2000,
|
BfCastFlags_IsConstraintCheck = 0x2000,
|
||||||
BfCastFlags_WantsConst = 0x4000
|
BfCastFlags_WantsConst = 0x4000,
|
||||||
|
BfCastFlags_FromComptimeReturn = 0x8000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfCastResultFlags : int8
|
enum BfCastResultFlags : int8
|
||||||
|
|
|
@ -4328,6 +4328,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
|
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->IsBoxed())
|
||||||
{
|
{
|
||||||
if ((typeInstance->mCustomAttributes == NULL) && (typeDef->mTypeDeclaration != NULL) && (typeDef->HasCustomAttributes()))
|
if ((typeInstance->mCustomAttributes == NULL) && (typeDef->mTypeDeclaration != NULL) && (typeDef->HasCustomAttributes()))
|
||||||
|
@ -4696,7 +4700,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
{
|
{
|
||||||
// Already handled
|
// 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))
|
if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
|
||||||
{
|
{
|
||||||
|
@ -4941,7 +4945,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
if (propDef->IsExpressionBodied())
|
if (propDef->IsExpressionBodied())
|
||||||
target = (BfAttributeTargets)(target | BfAttributeTargets_Method);
|
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);
|
auto customAttrs = GetCustomAttributes(propDef->GetFieldDeclaration()->mAttributes, target);
|
||||||
delete customAttrs;
|
delete customAttrs;
|
||||||
|
@ -5523,7 +5527,13 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
typeState.mCurTypeDef = propDef->mDeclaringType;
|
typeState.mCurTypeDef = propDef->mDeclaringType;
|
||||||
typeState.mType = typeInstance;
|
typeState.mType = typeInstance;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowRef);
|
|
||||||
|
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 cast '%s' to '%s'" :
|
||||||
"Unable to implicitly cast '%s' to '%s'";
|
"Unable to implicitly cast '%s' to '%s'";
|
||||||
|
|
||||||
String errStr = StrFormat(errStrF, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str());
|
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);
|
auto error = Fail(errStr, srcNode);
|
||||||
if ((error != NULL) && (srcNode != NULL))
|
if ((error != NULL) && (srcNode != NULL))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1024,6 +1024,19 @@ int CeBuilder::GetCallTableIdx(BeFunction* beFunction, CeOperand* outOperand)
|
||||||
callEntry.mFunctionInfo = ceFunctionInfo;
|
callEntry.mFunctionInfo = ceFunctionInfo;
|
||||||
*callIdxPtr = (int)mCeFunction->mCallTable.size();
|
*callIdxPtr = (int)mCeFunction->mCallTable.size();
|
||||||
mCeFunction->mCallTable.Add(callEntry);
|
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;
|
return *callIdxPtr;
|
||||||
}
|
}
|
||||||
|
@ -5148,7 +5161,8 @@ BfTypedValue CeContext::Call(CeCallSource callSource, BfModule* module, BfMethod
|
||||||
mCeMachine->mAppendAllocInfo = NULL;
|
mCeMachine->mAppendAllocInfo = NULL;
|
||||||
|
|
||||||
BfType* returnType = 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];
|
memStart = &mMemory[0];
|
||||||
|
|
||||||
addr_ce retInstAddr = retAddr;
|
addr_ce retInstAddr = retAddr;
|
||||||
|
@ -5228,6 +5242,13 @@ BfTypedValue CeContext::Call(CeCallSource callSource, BfModule* module, BfMethod
|
||||||
mCallStack = prevCallStack;
|
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;
|
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;
|
auto ceModule = mCeMachine->mCeModule;
|
||||||
CeFunction* ceFunction = startFunction;
|
CeFunction* ceFunction = startFunction;
|
||||||
|
@ -6057,6 +6078,14 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
_FixVariables();
|
_FixVariables();
|
||||||
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
|
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)
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody)
|
||||||
{
|
{
|
||||||
int32 typeId = *(int32*)((uint8*)stackPtr);
|
int32 typeId = *(int32*)((uint8*)stackPtr);
|
||||||
|
@ -7621,7 +7650,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
auto& ceStaticFieldEntry = ceFunction->mStaticFieldTable[tableIdx];
|
auto& ceStaticFieldEntry = ceFunction->mStaticFieldTable[tableIdx];
|
||||||
if (ceStaticFieldEntry.mBindExecuteId != mExecuteId)
|
if (ceStaticFieldEntry.mBindExecuteId != mExecuteId)
|
||||||
{
|
{
|
||||||
if (mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL))
|
if ((mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL)) && (!ceStaticFieldEntry.mName.StartsWith("#")))
|
||||||
{
|
{
|
||||||
auto bfType = GetBfType(ceStaticFieldEntry.mTypeId);
|
auto bfType = GetBfType(ceStaticFieldEntry.mTypeId);
|
||||||
BfTypeInstance* bfTypeInstance = NULL;
|
BfTypeInstance* bfTypeInstance = NULL;
|
||||||
|
@ -7667,6 +7696,74 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
if (ceStaticFieldEntry.mSize > 0)
|
if (ceStaticFieldEntry.mSize > 0)
|
||||||
memset(ptr, 0, ceStaticFieldEntry.mSize);
|
memset(ptr, 0, ceStaticFieldEntry.mSize);
|
||||||
staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
|
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;
|
ceStaticFieldEntry.mAddr = staticFieldInfo->mAddr;
|
||||||
|
@ -9199,11 +9296,15 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
|
||||||
}
|
}
|
||||||
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
|
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;
|
ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
|
||||||
}
|
}
|
||||||
if (methodDef->mName == "Comptime_EmitAddInterface")
|
else if (methodDef->mName == "Comptime_EmitAddInterface")
|
||||||
{
|
{
|
||||||
ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface;
|
ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface;
|
||||||
}
|
}
|
||||||
|
@ -9493,7 +9594,7 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
|
||||||
CeFunctionInfo* ceFunctionInfo = NULL;
|
CeFunctionInfo* ceFunctionInfo = NULL;
|
||||||
CeFunction* ceFunction = NULL;
|
CeFunction* ceFunction = NULL;
|
||||||
if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr))
|
if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr))
|
||||||
{
|
{
|
||||||
ceFunctionInfo = *functionInfoPtr;
|
ceFunctionInfo = *functionInfoPtr;
|
||||||
BF_ASSERT(ceFunctionInfo->mCeFunction != NULL);
|
BF_ASSERT(ceFunctionInfo->mCeFunction != NULL);
|
||||||
return ceFunctionInfo->mCeFunction;
|
return ceFunctionInfo->mCeFunction;
|
||||||
|
@ -9524,6 +9625,11 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ceFunctionInfo = *namedFunctionInfoPtr;
|
ceFunctionInfo = *namedFunctionInfoPtr;
|
||||||
|
if ((ceFunctionInfo->mMethodInstance != NULL) && (ceFunctionInfo->mMethodInstance != methodInstance))
|
||||||
|
{
|
||||||
|
// This ceFunctionInfo is already taken - probably from a name mangling conflict
|
||||||
|
ceFunctionInfo = new CeFunctionInfo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -329,8 +329,15 @@ public:
|
||||||
mCeFunction = NULL;
|
mCeFunction = NULL;
|
||||||
mRefCount = 0;
|
mRefCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~CeFunctionInfo();
|
~CeFunctionInfo();
|
||||||
|
|
||||||
|
BfTypeInstance* GetOwner()
|
||||||
|
{
|
||||||
|
if (mMethodInstance != NULL)
|
||||||
|
return mMethodInstance->GetOwner();
|
||||||
|
return mMethodRef.mTypeInstance;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CeCallEntry
|
class CeCallEntry
|
||||||
|
@ -440,6 +447,7 @@ enum CeFunctionKind
|
||||||
CeFunctionKind_Method_GetParamInfo,
|
CeFunctionKind_Method_GetParamInfo,
|
||||||
CeFunctionKind_Method_GetGenericArg,
|
CeFunctionKind_Method_GetGenericArg,
|
||||||
|
|
||||||
|
CeFunctionKind_SetReturnType,
|
||||||
CeFunctionKind_EmitTypeBody,
|
CeFunctionKind_EmitTypeBody,
|
||||||
CeFunctionKind_EmitAddInterface,
|
CeFunctionKind_EmitAddInterface,
|
||||||
CeFunctionKind_EmitMethodEntry,
|
CeFunctionKind_EmitMethodEntry,
|
||||||
|
@ -1050,6 +1058,7 @@ public:
|
||||||
Kind mKind;
|
Kind mKind;
|
||||||
BfAstNode* mRefNode;
|
BfAstNode* mRefNode;
|
||||||
BfFieldInstance* mFieldInstance;
|
BfFieldInstance* mFieldInstance;
|
||||||
|
BfType* mOrigCalleeType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CeCallSource(BfAstNode* refNode)
|
CeCallSource(BfAstNode* refNode)
|
||||||
|
@ -1057,6 +1066,7 @@ public:
|
||||||
mKind = Kind_Unknown;
|
mKind = Kind_Unknown;
|
||||||
mRefNode = refNode;
|
mRefNode = refNode;
|
||||||
mFieldInstance = NULL;
|
mFieldInstance = NULL;
|
||||||
|
mOrigCalleeType = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CeCallSource()
|
CeCallSource()
|
||||||
|
@ -1064,6 +1074,7 @@ public:
|
||||||
mKind = Kind_Unknown;
|
mKind = Kind_Unknown;
|
||||||
mRefNode = NULL;
|
mRefNode = NULL;
|
||||||
mFieldInstance = NULL;
|
mFieldInstance = NULL;
|
||||||
|
mOrigCalleeType = NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1135,7 +1146,7 @@ public:
|
||||||
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
|
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);
|
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);
|
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;
|
EnumG eg = .A;
|
||||||
eg.Set(66);
|
eg.Set(66);
|
||||||
Test.Assert(eg == .B);
|
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