mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Early code generation support
This commit is contained in:
parent
0b48a60592
commit
71d4dd0e90
26 changed files with 2422 additions and 1576 deletions
|
@ -274,6 +274,21 @@ namespace System
|
|||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method)]
|
||||
struct OnCompileAttribute : Attribute
|
||||
{
|
||||
public enum Kind
|
||||
{
|
||||
None,
|
||||
TypeInit,
|
||||
TypeDone
|
||||
}
|
||||
|
||||
public this(Kind kind)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method)]
|
||||
public struct ComptimeAttribute : Attribute
|
||||
{
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
using System.Reflection;
|
||||
namespace System
|
||||
{
|
||||
[AttributeUsage(.Method)]
|
||||
struct OnCompileAttribute : Attribute
|
||||
{
|
||||
public enum Kind
|
||||
{
|
||||
None,
|
||||
TypeInit,
|
||||
TypeDone
|
||||
}
|
||||
|
||||
public this(Kind kind)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static class Compiler
|
||||
{
|
||||
public struct MethodBuilder
|
||||
|
|
|
@ -7,9 +7,33 @@ namespace System.Reflection
|
|||
*((*(T2**)&data)++)
|
||||
}
|
||||
|
||||
public static bool HasCustomAttribute(void* inAttrData, Type attributeType)
|
||||
{
|
||||
TypeId findTypeId = attributeType.[Friend]mTypeId;
|
||||
|
||||
void* data = inAttrData;
|
||||
data++;
|
||||
|
||||
uint8 count = Decode!<uint8>(data);
|
||||
for (int32 attrIdx = 0; attrIdx < count; attrIdx++)
|
||||
AttrBlock:
|
||||
{
|
||||
void* startPtr = data;
|
||||
var len = Decode!<uint16>(data);
|
||||
void* endPtr = (uint8*)startPtr + len;
|
||||
|
||||
var typeId = Decode!<TypeId>(data);
|
||||
if (typeId == findTypeId)
|
||||
return true;
|
||||
|
||||
data = endPtr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Result<void> GetCustomAttribute(void* inAttrData, Type attributeType, Object targetAttr)
|
||||
{
|
||||
|
||||
TypeId findTypeId = attributeType.[Friend]mTypeId;
|
||||
|
||||
void* data = inAttrData;
|
||||
|
|
|
@ -472,6 +472,9 @@ namespace System
|
|||
}
|
||||
|
||||
static extern Type Comptime_GetTypeById(int32 typeId);
|
||||
static extern Type Comptime_GetTypeByName(StringView name);
|
||||
static extern Type Comptime_GetSpecializedType(Type unspecializedType, Span<Type> typeArgs);
|
||||
static extern bool Comptime_Type_GetCustomAttribute(int32 typeId, int32 attributeId, void* dataPtr);
|
||||
|
||||
protected static Type GetType(TypeId typeId)
|
||||
{
|
||||
|
@ -487,6 +490,19 @@ namespace System
|
|||
return sTypes[typeId];
|
||||
}
|
||||
|
||||
public static Result<Type> GetTypeByName(StringView typeName)
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
{
|
||||
var type = Comptime_GetTypeByName(typeName);
|
||||
if (type == null)
|
||||
return .Err;
|
||||
return type;
|
||||
}
|
||||
|
||||
return .Err;
|
||||
}
|
||||
|
||||
void GetBasicName(String strBuffer)
|
||||
{
|
||||
switch (mTypeCode)
|
||||
|
@ -557,8 +573,28 @@ namespace System
|
|||
return FieldInfo.Enumerator(null, bindingFlags);
|
||||
}
|
||||
|
||||
public bool HasCustomAttribute<T>() where T : Attribute
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
{
|
||||
return Comptime_Type_GetCustomAttribute((int32)TypeId, typeof(T).TypeId, null);
|
||||
}
|
||||
|
||||
if (var typeInstance = this as TypeInstance)
|
||||
return typeInstance.[Friend]HasCustomAttribute<T>(typeInstance.[Friend]mCustomAttributesIdx);
|
||||
return false;
|
||||
}
|
||||
|
||||
public Result<T> GetCustomAttribute<T>() where T : Attribute
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
{
|
||||
T val = ?;
|
||||
if (Comptime_Type_GetCustomAttribute((int32)TypeId, typeof(T).TypeId, &val))
|
||||
return val;
|
||||
return .Err;
|
||||
}
|
||||
|
||||
if (var typeInstance = this as TypeInstance)
|
||||
return typeInstance.[Friend]GetCustomAttribute<T>(typeInstance.[Friend]mCustomAttributesIdx);
|
||||
return .Err;
|
||||
|
@ -577,6 +613,9 @@ namespace System
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
Runtime.FatalError("Comptime type enumeration not supported");
|
||||
|
||||
if (mCurId >= sTypeCount)
|
||||
return .Err;
|
||||
let type = sTypes[mCurId++];
|
||||
|
@ -929,6 +968,15 @@ namespace System.Reflection
|
|||
return FieldInfo.Enumerator(this, bindingFlags);
|
||||
}
|
||||
|
||||
bool HasCustomAttribute<T>(int customAttributeIdx) where T : Attribute
|
||||
{
|
||||
if (customAttributeIdx == -1)
|
||||
return false;
|
||||
|
||||
void* data = mCustomAttrDataPtr[customAttributeIdx];
|
||||
return AttributeInfo.HasCustomAttribute(data, typeof(T));
|
||||
}
|
||||
|
||||
Result<T> GetCustomAttribute<T>(int customAttributeIdx) where T : Attribute
|
||||
{
|
||||
if (customAttributeIdx == -1)
|
||||
|
@ -1043,6 +1091,17 @@ namespace System.Reflection
|
|||
}
|
||||
|
||||
uint8 mGenericParamCount;
|
||||
|
||||
public Result<Type> GetSpecializedType(params Span<Type> typeArgs)
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
{
|
||||
var specializedType = Type.[Friend]Comptime_GetSpecializedType(this, typeArgs);
|
||||
if (specializedType != null)
|
||||
return specializedType;
|
||||
}
|
||||
return .Err;
|
||||
}
|
||||
}
|
||||
|
||||
// Only for resolved types
|
||||
|
|
|
@ -813,6 +813,25 @@ bool BfAstNode::LocationEndEquals(BfAstNode* otherNode)
|
|||
(GetSrcEnd() == otherNode->GetSrcEnd());
|
||||
}
|
||||
|
||||
String BfAstNode::LocationToString()
|
||||
{
|
||||
auto parserData = GetParserData();
|
||||
if (parserData == NULL)
|
||||
return String();
|
||||
|
||||
String loc;
|
||||
|
||||
int line = -1;
|
||||
int lineChar = -1;
|
||||
parserData->GetLineCharAtIdx(mSrcStart, line, lineChar);
|
||||
if (line != -1)
|
||||
loc += StrFormat("at line %d:%d", line + 1, lineChar + 1);
|
||||
loc += " in ";
|
||||
loc += parserData->mFileName;
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
void BfAstNode::Add(BfAstNode* bfAstNode)
|
||||
{
|
||||
#ifdef BF_AST_HAS_PARENT_MEMBER
|
||||
|
|
|
@ -1101,6 +1101,7 @@ public:
|
|||
static void ClassAccept(BfAstNode* node, BfStructuralVisitor* bfVisitor) { bfVisitor->Visit(node); }
|
||||
bool LocationEquals(BfAstNode* otherNode);
|
||||
bool LocationEndEquals(BfAstNode* otherNode);
|
||||
String LocationToString();
|
||||
void Add(BfAstNode* bfAstNode);
|
||||
bool IsMissingSemicolon();
|
||||
bool IsExpression();
|
||||
|
|
|
@ -8574,8 +8574,6 @@ int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
|
|||
return -1;
|
||||
|
||||
String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);
|
||||
|
||||
int revisionId = (int)atoi(typeIdStr.c_str());
|
||||
int typeId = (int)atoi(typeIdStr.c_str());
|
||||
if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize))
|
||||
return -1;
|
||||
|
@ -8786,7 +8784,9 @@ BF_EXPORT int BF_CALLTYPE BfCompiler_GetCurConstEvalExecuteId(BfCompiler* bfComp
|
|||
{
|
||||
if (bfCompiler->mCEMachine == NULL)
|
||||
return -1;
|
||||
if (bfCompiler->mCEMachine->mCurMethodInstance == NULL)
|
||||
if (bfCompiler->mCEMachine->mCurContext == NULL)
|
||||
return -1;
|
||||
if (bfCompiler->mCEMachine->mCurContext->mCurMethodInstance == NULL)
|
||||
return -1;
|
||||
return bfCompiler->mCEMachine->mExecuteId;
|
||||
}
|
||||
|
|
|
@ -366,6 +366,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
|
|||
}
|
||||
}
|
||||
|
||||
if (mModule->PreFail())
|
||||
mModule->Fail(StrFormat("Not enough parameters specified. Expected %d fewer.", methodInstance->GetParamCount() - (int)arguments.size()), refNode);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ public:
|
|||
ResolveKind_ResolvingVarType,
|
||||
ResolveKind_UnionInnerType,
|
||||
ResolveKind_LocalVariable,
|
||||
ResolveKind_Attributes
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
@ -61,6 +61,7 @@ BfDefBuilder::BfDefBuilder(BfSystem* bfSystem)
|
|||
mCurTypeDef = NULL;
|
||||
mCurActualTypeDef = NULL;
|
||||
mFullRefresh = false;
|
||||
mIsComptime = false;
|
||||
mResolvePassData = NULL;
|
||||
mCurSource = NULL;
|
||||
|
||||
|
@ -1184,7 +1185,7 @@ BfFieldDef* BfDefBuilder::AddField(BfTypeDef* typeDef, BfTypeReference* fieldTyp
|
|||
return fieldDef;
|
||||
}
|
||||
|
||||
BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType, BfProtection protection, bool isStatic, const StringImpl& name)
|
||||
BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType, BfProtection protection, bool isStatic, const StringImpl& name, bool addedAfterEmit)
|
||||
{
|
||||
BF_ASSERT(typeDef->mTypeCode != BfTypeCode_TypeAlias);
|
||||
|
||||
|
@ -1193,6 +1194,7 @@ BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType
|
|||
typeDef->mMethods.push_back(methodDef);
|
||||
methodDef->mDeclaringType = typeDef;
|
||||
methodDef->mMethodType = methodType;
|
||||
methodDef->mAddedAfterEmit = addedAfterEmit;
|
||||
if (name.empty())
|
||||
{
|
||||
if (methodType == BfMethodType_Ctor)
|
||||
|
@ -1364,6 +1366,12 @@ BfTypeDef* BfDefBuilder::ComparePrevTypeDef(BfTypeDef* prevTypeDef, BfTypeDef* c
|
|||
|
||||
void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
||||
{
|
||||
if (typeDeclaration->IsEmitted())
|
||||
{
|
||||
Fail("Type declarations are not allowed in emitted code", typeDeclaration);
|
||||
return;
|
||||
}
|
||||
|
||||
BF_ASSERT(typeDeclaration->GetSourceData() == mCurSource->mSourceData);
|
||||
|
||||
if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mNameNode == NULL))
|
||||
|
@ -1999,6 +2007,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mReturnTypeRef = mSystem->mDirectIntTypeRef;
|
||||
methodDef->mIsStatic = true;
|
||||
methodDef->mBody = method->mBody;
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
|
||||
for (auto param : method->mParams)
|
||||
{
|
||||
|
@ -2158,24 +2167,24 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
|
||||
if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic) && (ctorClear == NULL))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "");
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, "", mIsComptime);
|
||||
methodDef->mIsMutating = true;
|
||||
}
|
||||
|
||||
if ((needsDtor) && (dtor == NULL))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, false, "");
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, false, "", mIsComptime);
|
||||
BF_ASSERT(mCurTypeDef->mDtorDef == methodDef);
|
||||
}
|
||||
|
||||
if ((needsStaticDtor) && (staticDtor == NULL))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, true, "");
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, true, "", mIsComptime);
|
||||
}
|
||||
|
||||
if ((needsStaticInit) && (staticCtor == NULL))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "");
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, "", mIsComptime);
|
||||
}
|
||||
|
||||
bool makeCtorPrivate = hasCtor;
|
||||
|
@ -2193,7 +2202,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
|
||||
// Create default constructor. If it's the only constructor then make it public,
|
||||
// otherwise make it private so we can still internally use it but the user can't
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, prot, false, "");
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, prot, false, "", mIsComptime);
|
||||
methodDef->mIsMutating = true;
|
||||
}
|
||||
|
||||
|
@ -2229,19 +2238,19 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
{
|
||||
if ((hasStaticField) && (staticMarkMethod == NULL))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC);
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC, mIsComptime);
|
||||
methodDef->mIsNoReflect = true;
|
||||
}
|
||||
|
||||
if (hasThreadStatics)
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_FIND_TLS_MEMBERS);
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_FIND_TLS_MEMBERS, mIsComptime);
|
||||
methodDef->mIsNoReflect = true;
|
||||
}
|
||||
|
||||
if ((hasNonStaticField) && (markMethod == NULL))
|
||||
{
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS);
|
||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS, mIsComptime);
|
||||
methodDef->mIsVirtual = true;
|
||||
methodDef->mIsOverride = true;
|
||||
methodDef->mIsNoReflect = true;
|
||||
|
@ -2262,6 +2271,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
|
||||
methodDef->mProtection = BfProtection_Public;
|
||||
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "checkEnum");
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
|
||||
// Underlying
|
||||
{
|
||||
|
@ -2272,6 +2282,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mReturnTypeRef = mSystem->mDirectSelfBaseTypeRef;
|
||||
methodDef->mMethodType = BfMethodType_PropertyGetter;
|
||||
methodDef->mProtection = BfProtection_Public;
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
|
||||
auto propDef = new BfPropertyDef();
|
||||
mCurTypeDef->mProperties.Add(propDef);
|
||||
|
@ -2292,6 +2303,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mReturnTypeRef = mSystem->mDirectRefSelfBaseTypeRef;
|
||||
methodDef->mMethodType = BfMethodType_PropertyGetter;
|
||||
methodDef->mProtection = BfProtection_Public;
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
|
||||
auto propDef = new BfPropertyDef();
|
||||
mCurTypeDef->mProperties.Add(propDef);
|
||||
|
@ -2315,6 +2327,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mIsVirtual = true;
|
||||
AddParam(methodDef, mSystem->mDirectStringTypeRef, "outStr");
|
||||
mCurTypeDef->mHasOverrideMethods = true;
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
}
|
||||
|
||||
if ((needsEqualsMethod) && (equalsMethod == NULL))
|
||||
|
@ -2328,6 +2341,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mIsStatic = true;
|
||||
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
|
||||
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
}
|
||||
|
||||
if (needsEqualsMethod)
|
||||
|
@ -2341,6 +2355,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
|||
methodDef->mIsStatic = true;
|
||||
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
|
||||
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
|
||||
methodDef->mAddedAfterEmit = mIsComptime;
|
||||
}
|
||||
|
||||
HashContext inlineHashCtx;
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
BfTypeDef* mCurTypeDef;
|
||||
BfTypeDef* mCurActualTypeDef;
|
||||
bool mFullRefresh;
|
||||
bool mIsComptime;
|
||||
BfResolvePassData* mResolvePassData;
|
||||
BfAtomComposite mNamespace;
|
||||
Array<BfAtomComposite> mNamespaceSearch;
|
||||
|
@ -33,7 +34,7 @@ public:
|
|||
//static BfNamedTypeReference* AllocTypeReference(BfSource* bfSource, const StringImpl& typeName);
|
||||
//static BfResolvedTypeReference* AllocTypeReference(BfSource* bfSource, BfType* type);
|
||||
static BfFieldDef* AddField(BfTypeDef* typeDef, BfTypeReference* typeRef, const StringImpl& name);
|
||||
static BfMethodDef* AddMethod(BfTypeDef* typeDef, BfMethodType methodType, BfProtection protection, bool isStatic, const StringImpl& name);
|
||||
static BfMethodDef* AddMethod(BfTypeDef* typeDef, BfMethodType methodType, BfProtection protection, bool isStatic, const StringImpl& name, bool addedAfterEmit = false);
|
||||
static BfMethodDef* AddDtor(BfTypeDef* typeDef);
|
||||
static void AddDynamicCastMethods(BfTypeDef* typeDef);
|
||||
void AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName);
|
||||
|
|
|
@ -2092,6 +2092,8 @@ Done:
|
|||
void BfMethodMatcher::FlushAmbiguityError()
|
||||
{
|
||||
if (!mAmbiguousEntries.empty())
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
BfError* error;
|
||||
if (!mMethodName.empty())
|
||||
|
@ -2124,6 +2126,7 @@ void BfMethodMatcher::FlushAmbiguityError()
|
|||
ambiguousEntry.mMethodInstance->mMethodDef->GetRefNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mAmbiguousEntries.Clear();
|
||||
}
|
||||
|
@ -3759,6 +3762,12 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
|
|||
|
||||
if (!thisValue.HasType())
|
||||
{
|
||||
if ((mModule->mContext->mCurTypeState != NULL) && (mModule->mContext->mCurTypeState->mTypeInstance == mModule->mCurTypeInstance) &&
|
||||
(mModule->mContext->mCurTypeState->mResolveKind == BfTypeState::ResolveKind_Attributes))
|
||||
{
|
||||
// Can't do static lookups yet
|
||||
}
|
||||
else
|
||||
thisValue = BfTypedValue(mModule->mCurTypeInstance);
|
||||
}
|
||||
|
||||
|
@ -4314,6 +4323,8 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
return retVal;
|
||||
}
|
||||
else if (!target)
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
if ((flags & BfLookupFieldFlag_CheckingOuter) != 0)
|
||||
mModule->Fail(StrFormat("An instance reference is required to reference non-static outer field '%s.%s'", mModule->TypeToString(curCheckType).c_str(), field->mName.c_str()),
|
||||
|
@ -4322,6 +4333,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
mModule->Fail(StrFormat("Cannot reference field '%s' before append allocations", field->mName.c_str()), targetSrc);
|
||||
else
|
||||
mModule->Fail(StrFormat("Cannot reference non-static field '%s' from a static method", field->mName.c_str()), targetSrc);
|
||||
}
|
||||
return mModule->GetDefaultTypedValue(resolvedFieldType, false, BfDefaultValueKind_Addr);
|
||||
}
|
||||
|
||||
|
@ -4500,6 +4512,8 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
continue;
|
||||
|
||||
if (matchedProp != NULL)
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
auto error = mModule->Fail(StrFormat("Ambiguous reference to property '%s.%s'", mModule->TypeToString(curCheckType).c_str(), fieldName.c_str()), targetSrc);
|
||||
if (error != NULL)
|
||||
|
@ -4509,6 +4523,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchedProp = prop;
|
||||
}
|
||||
|
@ -6201,6 +6216,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
}
|
||||
|
||||
if (argExprIdx < (int)argValues.size())
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
BfAstNode* errorRef = argValues[argExprIdx].mExpression;
|
||||
if (errorRef == NULL)
|
||||
|
@ -6227,6 +6244,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
error = mModule->Fail(StrFormat("Too many arguments, expected %d fewer.", (int)argValues.size() - argExprIdx), errorRef);
|
||||
if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL))
|
||||
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
|
||||
}
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
@ -6487,9 +6505,12 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
|
||||
|
||||
if (showCtorError)
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
error = mModule->Fail(StrFormat("No parameterless constructor is available for base class. Consider calling base constructor '%s'.",
|
||||
mModule->MethodToString(methodInstance).c_str()), refNode);
|
||||
}
|
||||
|
||||
auto srcNode = mModule->mCurMethodInstance->mMethodDef->GetRefNode();
|
||||
if ((autoComplete != NULL) && (autoComplete->CheckFixit(srcNode)))
|
||||
|
@ -6497,10 +6518,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
}
|
||||
}
|
||||
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
if (error == NULL)
|
||||
error = mModule->Fail(StrFormat("Not enough parameters specified, expected %d more.", methodInstance->GetParamCount() - paramIdx), refNode);
|
||||
if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL))
|
||||
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
|
||||
}
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -758,6 +758,20 @@ BfIRValue BfIRConstHolder::CreateConstAgg(BfIRType type, const BfSizedArray<BfIR
|
|||
return irValue;
|
||||
}
|
||||
|
||||
BfIRValue BfIRConstHolder::CreateConstAggCE(BfIRType type, addr_ce addr)
|
||||
{
|
||||
BfConstantAggCE* constant = mTempAlloc.Alloc<BfConstantAggCE>();
|
||||
constant->mConstType = BfConstType_AggCE;
|
||||
constant->mType = type = type;
|
||||
constant->mCEAddr = addr;
|
||||
auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(constant));
|
||||
|
||||
#ifdef CHECK_CONSTHOLDER
|
||||
irValue.mHolder = this;
|
||||
#endif
|
||||
return irValue;
|
||||
}
|
||||
|
||||
BfIRValue BfIRConstHolder::CreateConstArrayZero(BfIRType type, int count)
|
||||
{
|
||||
BfConstantArrayZero* constant = mTempAlloc.Alloc<BfConstantArrayZero>();
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
NS_BF_BEGIN
|
||||
|
||||
typedef int addr_ce;
|
||||
|
||||
class BfModule;
|
||||
class BfType;
|
||||
class BfTypeInstance;
|
||||
|
@ -123,6 +125,7 @@ enum BfConstType
|
|||
BfConstType_TypeOf_WithData,
|
||||
BfConstType_AggZero,
|
||||
BfConstType_Agg,
|
||||
BfConstType_AggCE,
|
||||
BfConstType_ArrayZero,
|
||||
BfConstType_ArrayZero8,
|
||||
BfConstType_Undef,
|
||||
|
@ -874,6 +877,13 @@ struct BfConstantAgg
|
|||
BfSizedArray<BfIRValue> mValues;
|
||||
};
|
||||
|
||||
struct BfConstantAggCE
|
||||
{
|
||||
BfConstType mConstType;
|
||||
BfIRType mType;
|
||||
addr_ce mCEAddr;
|
||||
};
|
||||
|
||||
struct BfConstantArrayZero
|
||||
{
|
||||
BfConstType mConstType;
|
||||
|
@ -904,6 +914,7 @@ public:
|
|||
bool TryGetBool(BfIRValue id, bool& boolVal);
|
||||
int IsZero(BfIRValue val);
|
||||
int CheckConstEquality(BfIRValue lhs, BfIRValue rhs); // -1 = fail, 0 = false, 1 = true
|
||||
//void WriteConstant(void* data, BeConstant* constVal);
|
||||
|
||||
BfIRValue CreateConst(BfTypeCode typeCode, uint64 val);
|
||||
BfIRValue CreateConst(BfTypeCode typeCode, int val);
|
||||
|
@ -913,6 +924,7 @@ public:
|
|||
BfIRValue CreateConstNull(BfIRType nullType);
|
||||
BfIRValue CreateConstStructZero(BfIRType aggType);
|
||||
BfIRValue CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values);
|
||||
BfIRValue CreateConstAggCE(BfIRType type, addr_ce ptr);
|
||||
BfIRValue CreateConstArrayZero(BfIRType type, int count);
|
||||
BfIRValue CreateConstArrayZero(int count);
|
||||
BfIRValue CreateTypeOf(BfType* type);
|
||||
|
|
|
@ -2714,6 +2714,14 @@ void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementTyp
|
|||
}
|
||||
}
|
||||
|
||||
bool BfModule::PreFail()
|
||||
{
|
||||
if (!mIgnoreErrors)
|
||||
return true;
|
||||
SetFail();
|
||||
return false;
|
||||
}
|
||||
|
||||
void BfModule::SetFail()
|
||||
{
|
||||
if (mIgnoreErrors)
|
||||
|
@ -2758,7 +2766,7 @@ bool BfModule::IsSkippingExtraResolveChecks()
|
|||
return mCompiler->IsSkippingExtraResolveChecks();
|
||||
}
|
||||
|
||||
BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent)
|
||||
BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent, bool deferError)
|
||||
{
|
||||
BP_ZONE("BfModule::Fail");
|
||||
|
||||
|
@ -2825,7 +2833,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
{
|
||||
auto _CheckMethodInstance = [&](BfMethodInstance* methodInstance)
|
||||
{
|
||||
// Propogatea the fail all the way to the main method (assuming we're in a local method or lambda)
|
||||
// Propogate the fail all the way to the main method (assuming we're in a local method or lambda)
|
||||
methodInstance->mHasFailed = true;
|
||||
|
||||
bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0));
|
||||
|
@ -2887,19 +2895,19 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
if (!_CheckMethodInstance(mCurMethodInstance))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep in mind that all method specializations with generic type instances as its method generic params
|
||||
// need to be deferred because the specified generic type instance might get deleted at the end of the
|
||||
// compilation due to no longer having indirect references removed, and we have to ignore errors from
|
||||
// those method specializations if that occurs
|
||||
if (isWhileSpecializing)
|
||||
if ((isWhileSpecializing) || (deferError))
|
||||
{
|
||||
BfError* bfError = mCompiler->mPassInstance->DeferFail(errorString, refNode);
|
||||
if (bfError != NULL)
|
||||
bfError->mIsWhileSpecializing = isWhileSpecializing;
|
||||
return bfError;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())))
|
||||
{
|
||||
|
@ -10618,7 +10626,7 @@ BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConst
|
|||
return BfTypedValue(irValue, wantType, false);
|
||||
}
|
||||
|
||||
BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType)
|
||||
BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowStringId)
|
||||
{
|
||||
if (constant->mTypeCode == BfTypeCode_NullPtr)
|
||||
{
|
||||
|
@ -10632,6 +10640,8 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
|
|||
}
|
||||
|
||||
if (constant->mTypeCode == BfTypeCode_StringId)
|
||||
{
|
||||
if (!allowStringId)
|
||||
{
|
||||
if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) ||
|
||||
((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
|
||||
|
@ -10643,6 +10653,7 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
|
|||
return stringObjConst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (constant->mConstType == BfConstType_Agg)
|
||||
{
|
||||
|
@ -10686,7 +10697,7 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
|
|||
}
|
||||
}
|
||||
|
||||
return mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(wantType), newVals);
|
||||
return mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(wantType, BfIRPopulateType_Identity), newVals);
|
||||
}
|
||||
|
||||
return mBfIRBuilder->CreateConst(constant, constHolder);
|
||||
|
@ -10838,6 +10849,23 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
|
|||
|
||||
customAttribute.mType = attrTypeInst;
|
||||
|
||||
bool allocatedMethodState = NULL;
|
||||
defer(
|
||||
{
|
||||
if (allocatedMethodState)
|
||||
{
|
||||
delete mCurMethodState;
|
||||
mCurMethodState = NULL;
|
||||
}
|
||||
});
|
||||
|
||||
if (mCurMethodState == NULL)
|
||||
{
|
||||
allocatedMethodState = true;
|
||||
mCurMethodState = new BfMethodState();
|
||||
mCurMethodState->mTempKind = BfMethodState::TempKind_Static;
|
||||
}
|
||||
|
||||
BfConstResolver constResolver(this);
|
||||
if (allowNonConstArgs)
|
||||
constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst);
|
||||
|
@ -19747,6 +19775,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
|
||||
}
|
||||
|
||||
// Avoid linking any internal funcs that were just supposed to be comptime-accessible
|
||||
if (((methodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) && (!mIsComptimeModule))
|
||||
wantsRemoveBody = true;
|
||||
|
||||
if ((hasExternSpecifier) && (!skipBody))
|
||||
{
|
||||
// If we hot swap, we want to make sure at least one method refers to this extern method so it gets pulled in
|
||||
|
|
|
@ -1481,10 +1481,11 @@ public:
|
|||
void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
|
||||
bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType);
|
||||
void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
|
||||
bool PreFail();
|
||||
void SetFail();
|
||||
void VerifyOnDemandMethods();
|
||||
bool IsSkippingExtraResolveChecks();
|
||||
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
|
||||
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false);
|
||||
BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
|
||||
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
|
||||
BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);
|
||||
|
@ -1526,7 +1527,7 @@ public:
|
|||
void CurrentAddToConstHolder(BfIRValue& irVal);
|
||||
void ClearConstData();
|
||||
BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
|
||||
BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
|
||||
BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowStringId = false);
|
||||
void ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget);
|
||||
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
|
||||
BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
|
||||
|
@ -1698,7 +1699,8 @@ public:
|
|||
BfModuleOptions GetModuleOptions();
|
||||
BfCheckedKind GetDefaultCheckedKind();
|
||||
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode);
|
||||
void ExecuteCEOnCompile(BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, CeEmitContext* ceEmitContext);
|
||||
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes);
|
||||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind);
|
||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
|
||||
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
||||
static BfModule* GetModuleFor(BfType* type);
|
||||
|
|
|
@ -1952,9 +1952,11 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
|||
src += ceEmitContext->mEmitData;
|
||||
ceEmitContext->mEmitData.Clear();
|
||||
|
||||
bool createdParser = false;
|
||||
int startSrcIdx = 0;
|
||||
if (activeTypeDef->mEmitParser == NULL)
|
||||
{
|
||||
createdParser = true;
|
||||
BfParser* parser = new BfParser(mSystem, typeInstance->mTypeDef->mProject);
|
||||
parser->mIsEmitted = true;
|
||||
parser->mFileName = typeInstance->mTypeDef->mName->ToString();
|
||||
|
@ -1999,11 +2001,14 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
|||
bfReducer.HandleTypeDeclaration(typeDeclaration, NULL);
|
||||
|
||||
BfDefBuilder defBuilder(mSystem);
|
||||
defBuilder.mCurSource = activeTypeDef->mEmitParser;
|
||||
defBuilder.mCurTypeDef = typeInstance->mTypeDef;
|
||||
defBuilder.mPassInstance = mCompiler->mPassInstance;
|
||||
defBuilder.mIsComptime = true;
|
||||
defBuilder.DoVisitChild(typeDeclaration->mDefineNode);
|
||||
defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum);
|
||||
|
||||
//
|
||||
if (createdParser)
|
||||
{
|
||||
AutoCrit crit(mSystem->mDataLock);
|
||||
mSystem->mParsers.Add(activeTypeDef->mEmitParser);
|
||||
|
@ -2020,10 +2025,77 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
|||
}
|
||||
}
|
||||
|
||||
void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, CeEmitContext* ceEmitContext)
|
||||
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes)
|
||||
{
|
||||
if (!typeInstance->mTypeDef->mHasCEOnCompile)
|
||||
return;
|
||||
BfTypeInstance* iComptimeTypeApply = NULL;
|
||||
for (auto& customAttribute : customAttributes->mAttributes)
|
||||
{
|
||||
auto attrType = customAttribute.mType;
|
||||
PopulateType(attrType, BfPopulateType_DataAndMethods);
|
||||
if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
|
||||
continue;
|
||||
|
||||
for (auto& ifaceEntry : attrType->mInterfaces)
|
||||
{
|
||||
if (iComptimeTypeApply == NULL)
|
||||
iComptimeTypeApply = ResolveTypeDef(mCompiler->mIComptimeTypeApply)->ToTypeInstance();
|
||||
if (ifaceEntry.mInterfaceType != iComptimeTypeApply)
|
||||
continue;
|
||||
|
||||
if (!foundAttributes.Add(attrType))
|
||||
continue;
|
||||
|
||||
BfMethodInstance* methodInstance = attrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
|
||||
if (methodInstance == NULL)
|
||||
continue;
|
||||
|
||||
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, ceEmitContext);
|
||||
auto ceContext = mCompiler->mCEMachine->AllocContext();
|
||||
|
||||
BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
|
||||
|
||||
SizedArray<BfIRValue, 1> args;
|
||||
if (!attrType->IsValuelessType())
|
||||
args.Add(attrVal);
|
||||
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
|
||||
|
||||
//TESTING
|
||||
// mCompiler->mCEMachine->ReleaseContext(ceContext);
|
||||
// ceContext = mCompiler->mCEMachine->AllocContext();
|
||||
// ceContext->mMemory.mSize = ceContext->mMemory.mAllocSize;
|
||||
|
||||
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
|
||||
|
||||
if (!ceEmitContext->mEmitData.IsEmpty())
|
||||
{
|
||||
String ctxStr = "comptime ApplyToType of ";
|
||||
ctxStr += TypeToString(attrType);
|
||||
ctxStr += " to ";
|
||||
ctxStr += TypeToString(typeInstance);
|
||||
ctxStr += " ";
|
||||
ctxStr += customAttribute.mRef->LocationToString();
|
||||
UpdateCEEmit(ceEmitContext, typeInstance, typeInstance->mTypeDef, ctxStr, customAttribute.mRef);
|
||||
}
|
||||
|
||||
mCompiler->mCEMachine->ReleaseContext(ceContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind)
|
||||
{
|
||||
HashSet<BfTypeInstance*> foundAttributes;
|
||||
if (ceEmitContext != NULL)
|
||||
{
|
||||
if (typeInstance->mCustomAttributes != NULL)
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes);
|
||||
|
||||
for (auto& fieldInstance : typeInstance->mFieldInstances)
|
||||
{
|
||||
if (fieldInstance.mCustomAttributes != NULL)
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
int methodCount = (int)typeInstance->mTypeDef->mMethods.size();
|
||||
for (int methodIdx = 0; methodIdx < methodCount; methodIdx++)
|
||||
|
@ -2034,6 +2106,28 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
|
|||
continue;
|
||||
if (methodDeclaration->mAttributes == NULL)
|
||||
continue;
|
||||
|
||||
bool wantsAttributes = false;
|
||||
BfAttributeDirective* checkAttributes = methodDeclaration->mAttributes;
|
||||
while (checkAttributes != NULL)
|
||||
{
|
||||
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
|
||||
BfType* attrType = ResolveTypeRef(checkAttributes->mAttributeTypeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_Attribute | BfResolveTypeRefFlag_NoReify));
|
||||
if (attrType != NULL)
|
||||
{
|
||||
if (attrType->IsInstanceOf(mCompiler->mOnCompileAttributeTypeDef))
|
||||
wantsAttributes = true;
|
||||
auto attrTypeInstance = attrType->ToTypeInstance();
|
||||
if ((attrTypeInstance != NULL) && (!attrTypeInstance->mInterfaces.IsEmpty()))
|
||||
wantsAttributes = true;
|
||||
}
|
||||
|
||||
checkAttributes = checkAttributes->mNextAttribute;
|
||||
}
|
||||
|
||||
if (!wantsAttributes)
|
||||
return;
|
||||
|
||||
auto customAttributes = GetCustomAttributes(methodDeclaration->mAttributes, BfAttributeTargets_Method);
|
||||
defer({ delete customAttributes; });
|
||||
|
||||
|
@ -2041,6 +2135,8 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
|
|||
if (onCompileAttribute == NULL)
|
||||
continue;
|
||||
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes);
|
||||
|
||||
if (onCompileAttribute->mCtorArgs.size() < 1)
|
||||
continue;
|
||||
auto constant = typeInstance->mConstHolder->GetConstant(onCompileAttribute->mCtorArgs[0]);
|
||||
|
@ -2062,7 +2158,6 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
|
|||
}
|
||||
|
||||
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext);
|
||||
|
||||
if (onCompileKind == BfCEOnCompileKind_TypeInit)
|
||||
{
|
||||
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
|
||||
|
@ -2075,6 +2170,8 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
|
|||
{
|
||||
String ctxStr = "OnCompile execution of ";
|
||||
ctxStr += MethodToString(methodInstance);
|
||||
ctxStr += " ";
|
||||
ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString();
|
||||
UpdateCEEmit(ceEmitContext, typeInstance, methodInstance->mMethodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode());
|
||||
}
|
||||
|
||||
|
@ -2091,13 +2188,15 @@ void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers)
|
|||
|
||||
int startMethodCount = typeInstance->mTypeDef->mMethods.mSize;
|
||||
int startFieldCount = typeInstance->mTypeDef->mFields.mSize;
|
||||
int startPropCount = typeInstance->mTypeDef->mProperties.mSize;
|
||||
|
||||
CeEmitContext emitContext;
|
||||
emitContext.mType = typeInstance;
|
||||
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit, &emitContext);
|
||||
ExecuteCEOnCompile(&emitContext, typeInstance, BfCEOnCompileKind_TypeInit);
|
||||
|
||||
if ((startMethodCount != typeInstance->mTypeDef->mMethods.mSize) ||
|
||||
(startFieldCount != typeInstance->mTypeDef->mFields.mSize))
|
||||
(startFieldCount != typeInstance->mTypeDef->mFields.mSize) ||
|
||||
(startPropCount != typeInstance->mTypeDef->mProperties.mSize))
|
||||
{
|
||||
typeInstance->mTypeDef->ClearMemberSets();
|
||||
hadNewMembers = true;
|
||||
|
@ -3004,6 +3103,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
attrTarget = BfAttributeTargets_Class;
|
||||
if (!typeInstance->mTypeFailed)
|
||||
{
|
||||
BfTypeState typeState;
|
||||
typeState.mPrevState = mContext->mCurTypeState;
|
||||
typeState.mResolveKind = BfTypeState::ResolveKind_Attributes;
|
||||
typeState.mTypeInstance = typeInstance;
|
||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||
|
||||
// This allows us to avoid reentrancy when checking for inner types
|
||||
SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
|
||||
if (typeDef->mIsCombinedPartial)
|
||||
|
@ -3012,22 +3117,20 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
{
|
||||
if (partialTypeDef->mTypeDeclaration->mAttributes == NULL)
|
||||
continue;
|
||||
BfTypeState typeState;
|
||||
typeState.mPrevState = mContext->mCurTypeState;
|
||||
typeState.mCurTypeDef = partialTypeDef;
|
||||
typeState.mTypeInstance = typeInstance;
|
||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||
|
||||
typeState.mCurTypeDef = partialTypeDef;
|
||||
if (typeInstance->mCustomAttributes == NULL)
|
||||
typeInstance->mCustomAttributes = new BfCustomAttributes();
|
||||
GetCustomAttributes(typeInstance->mCustomAttributes, partialTypeDef->mTypeDeclaration->mAttributes, attrTarget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
typeInstance->mCustomAttributes = GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, attrTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeInstance->mTypeOptionsIdx == -2)
|
||||
SetTypeOptions(typeInstance);
|
||||
|
@ -3364,10 +3467,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
|
||||
auto refNode = typeDef->GetRefNode();
|
||||
Fail(error, refNode);
|
||||
if (mCompiler->mCEMachine->mCurFrame != NULL)
|
||||
mCompiler->mCEMachine->Fail(*mCompiler->mCEMachine->mCurFrame, error);
|
||||
else
|
||||
mCompiler->mCEMachine->Fail(error);
|
||||
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurFrame != NULL))
|
||||
mCompiler->mCEMachine->mCurContext->Fail(*mCompiler->mCEMachine->mCurContext->mCurFrame, error);
|
||||
else if (mCompiler->mCEMachine->mCurContext != NULL)
|
||||
mCompiler->mCEMachine->mCurContext->Fail(error);
|
||||
}
|
||||
else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
|
||||
{
|
||||
|
@ -3906,7 +4009,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
{
|
||||
typeInstance->mDefineState = BfTypeDefineState_Defined;
|
||||
if (!typeInstance->IsBoxed())
|
||||
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeDone, NULL);
|
||||
ExecuteCEOnCompile(NULL, typeInstance, BfCEOnCompileKind_TypeDone);
|
||||
}
|
||||
|
||||
if (typeInstance->mTypeFailed)
|
||||
|
|
|
@ -493,6 +493,8 @@ void BfParser::NewLine()
|
|||
mLineStart = mSrcIdx;
|
||||
mLineNum++;
|
||||
|
||||
if (mJumpTable == NULL)
|
||||
return;
|
||||
int idx = (mSrcIdx / PARSER_JUMPTABLE_DIVIDE);
|
||||
if (idx == 0)
|
||||
return;
|
||||
|
@ -575,6 +577,7 @@ void BfParser::SetSource(const char* data, int length)
|
|||
mOrigSrcLength = length;
|
||||
mSrcAllocSize = mSrcLength /*+ EXTRA_BUFFER_SIZE*/;
|
||||
char* ownedSrc = new char[mSrcAllocSize + 1];
|
||||
if (data != NULL)
|
||||
memcpy(ownedSrc, data, length);
|
||||
ownedSrc[length] = 0;
|
||||
mSrc = ownedSrc;
|
||||
|
@ -3482,9 +3485,12 @@ void BfParser::Parse(BfPassInstance* passInstance)
|
|||
mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first);
|
||||
}
|
||||
|
||||
if (mJumpTable != NULL)
|
||||
{
|
||||
for (int i = (startIdx / PARSER_JUMPTABLE_DIVIDE) + 1; i < mJumpTableSize; i++)
|
||||
if (mJumpTable[i].mCharIdx == 0)
|
||||
mJumpTable[i] = mJumpTable[i - 1];
|
||||
}
|
||||
|
||||
if (mPassInstance->HasFailed())
|
||||
mParsingFailed = true;
|
||||
|
|
|
@ -2671,6 +2671,14 @@ BfCustomAttribute* BfCustomAttributes::Get(BfTypeDef * typeDef)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BfCustomAttribute* BfCustomAttributes::Get(BfType* type)
|
||||
{
|
||||
for (auto& customAttr : mAttributes)
|
||||
if (customAttr.mType == type)
|
||||
return &customAttr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BfResolvedTypeSet::~BfResolvedTypeSet()
|
||||
|
|
|
@ -2410,6 +2410,7 @@ public:
|
|||
Array<BfCustomAttribute> mAttributes;
|
||||
bool Contains(BfTypeDef* typeDef);
|
||||
BfCustomAttribute* Get(BfTypeDef* typeDef);
|
||||
BfCustomAttribute* Get(BfType* type);
|
||||
|
||||
void ReportMemory(MemReporter* memReporter);
|
||||
};
|
||||
|
|
|
@ -696,7 +696,8 @@ void BfTypeDef::ClearEmitted()
|
|||
for (int methodIdx = (int)mMethods.size() - 1; methodIdx >= 0; methodIdx--)
|
||||
{
|
||||
auto methodDef = mMethods[methodIdx];
|
||||
if ((methodDef->mMethodDeclaration != NULL) && (methodDef->mMethodDeclaration->IsEmitted()))
|
||||
if ((methodDef->mAddedAfterEmit) ||
|
||||
((methodDef->mMethodDeclaration != NULL) && (methodDef->mMethodDeclaration->IsEmitted())))
|
||||
{
|
||||
delete methodDef;
|
||||
mMethods.RemoveAt(methodIdx);
|
||||
|
@ -712,6 +713,16 @@ void BfTypeDef::ClearEmitted()
|
|||
mFields.RemoveAt(fieldIdx);
|
||||
}
|
||||
}
|
||||
|
||||
for (int propIdx = (int)mProperties.size() - 1; propIdx >= 0; propIdx--)
|
||||
{
|
||||
auto propDef = mProperties[propIdx];
|
||||
if ((propDef->mFieldDeclaration != NULL) && (propDef->mFieldDeclaration->IsEmitted()))
|
||||
{
|
||||
delete propDef;
|
||||
mProperties.RemoveAt(propIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -830,6 +841,16 @@ BfMethodDef* BfTypeDef::GetMethodByName(const StringImpl& name, int paramCount)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BfFieldDef* BfTypeDef::GetFieldByName(const StringImpl& name)
|
||||
{
|
||||
PopulateMemberSets();
|
||||
BfFieldDef* nextField = NULL;
|
||||
BfMemberSetEntry* entry;
|
||||
if (mFieldSet.TryGetWith(name, &entry))
|
||||
return (BfFieldDef*)entry->mMemberDef;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
String BfTypeDef::ToString()
|
||||
{
|
||||
String typeName(mName->ToString());
|
||||
|
|
|
@ -41,6 +41,7 @@ class BfSystem;
|
|||
class BfTypeReference;
|
||||
class BfCompiler;
|
||||
class BfProject;
|
||||
class BfTypeDef;
|
||||
|
||||
struct BfTypeDefMapFuncs;
|
||||
typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap;
|
||||
|
@ -794,6 +795,7 @@ public:
|
|||
bool mIsExtern;
|
||||
bool mIsNoDiscard;
|
||||
bool mHasExplicitThis;
|
||||
bool mAddedAfterEmit;
|
||||
BfCommutableKind mCommutableKind;
|
||||
BfCheckedKind mCheckedKind;
|
||||
BfImportKind mImportKind;
|
||||
|
@ -823,6 +825,7 @@ public:
|
|||
mIsExtern = false;
|
||||
mIsNoDiscard = false;
|
||||
mHasExplicitThis = false;
|
||||
mAddedAfterEmit = false;
|
||||
mBody = NULL;
|
||||
mExplicitInterface = NULL;
|
||||
mReturnTypeRef = NULL;
|
||||
|
@ -1054,6 +1057,7 @@ public:
|
|||
int GetSelfGenericParamCount();
|
||||
String ToString();
|
||||
BfMethodDef* GetMethodByName(const StringImpl& name, int paramCount = -1);
|
||||
BfFieldDef* GetFieldByName(const StringImpl& name);
|
||||
bool HasAutoProperty(BfPropertyDeclaration* propertyDeclaration);
|
||||
String GetAutoPropertyName(BfPropertyDeclaration* propertyDeclaration);
|
||||
BfAstNode* GetRefNode();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,8 @@
|
|||
|
||||
NS_BF_BEGIN
|
||||
|
||||
class BfParser;
|
||||
class BfReducer;
|
||||
class BfMethodInstance;
|
||||
class BeModule;
|
||||
class BeContext;
|
||||
|
@ -23,8 +25,6 @@ class BeGlobalVariable;
|
|||
class CeMachine;
|
||||
class CeFunction;
|
||||
|
||||
typedef int addr_ce;
|
||||
|
||||
#define CEOP_SIZED(OPNAME) \
|
||||
CeOp_##OPNAME##_8, \
|
||||
CeOp_##OPNAME##_16, \
|
||||
|
@ -251,6 +251,9 @@ enum CeFunctionKind
|
|||
CeFunctionKind_DebugWrite_Int,
|
||||
CeFunctionKind_GetReflectType,
|
||||
CeFunctionKind_GetReflectTypeById,
|
||||
CeFunctionKind_GetReflectTypeByName,
|
||||
CeFunctionKind_GetReflectSpecializedType,
|
||||
CeFunctionKind_Type_GetCustomAttribute,
|
||||
CeFunctionKind_EmitDefinition,
|
||||
CeFunctionKind_Sleep,
|
||||
CeFunctionKind_Char32_ToLower,
|
||||
|
@ -368,6 +371,7 @@ public:
|
|||
}
|
||||
|
||||
~CeFunction();
|
||||
void Print();
|
||||
};
|
||||
|
||||
enum CeEvalFlags
|
||||
|
@ -424,8 +428,9 @@ public:
|
|||
};
|
||||
|
||||
#define BF_CE_STACK_SIZE 4*1024*1024
|
||||
#define BF_CE_INITIAL_MEMORY BF_CE_STACK_SIZE + 128*1024
|
||||
#define BF_CE_MAX_MEMORY 128*1024*1024
|
||||
#define BF_CE_MAX_CARRYOVER_MEMORY BF_CE_STACK_SIZE + 1024*1024
|
||||
#define BF_CE_MAX_CARRYOVER_MEMORY BF_CE_STACK_SIZE * 2
|
||||
#define BF_CE_MAX_CARRYOVER_HEAP 1024*1024
|
||||
|
||||
enum CeOperandInfoKind
|
||||
|
@ -518,6 +523,7 @@ public:
|
|||
Dictionary<BeConstant*, int> mConstDataMap;
|
||||
Dictionary<BeFunction*, int> mInnerFunctionMap;
|
||||
Dictionary<BeGlobalVariable*, int> mStaticFieldMap;
|
||||
Dictionary<String, BfFieldInstance*> mStaticFieldInstanceMap;
|
||||
|
||||
public:
|
||||
CeBuilder()
|
||||
|
@ -586,13 +592,11 @@ public:
|
|||
class CeStaticFieldInfo
|
||||
{
|
||||
public:
|
||||
BfFieldInstance* mFieldInstance;
|
||||
addr_ce mAddr;
|
||||
|
||||
public:
|
||||
CeStaticFieldInfo()
|
||||
{
|
||||
mFieldInstance = NULL;
|
||||
mAddr = 0;
|
||||
}
|
||||
};
|
||||
|
@ -617,6 +621,62 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class CeContext
|
||||
{
|
||||
public:
|
||||
CeMachine* mCeMachine;
|
||||
int mReflectTypeIdOffset;
|
||||
int mExecuteId;
|
||||
CeEvalFlags mCurEvalFlags;
|
||||
|
||||
// These are only valid for the current execution
|
||||
ContiguousHeap* mHeap;
|
||||
Array<CeFrame> mCallStack;
|
||||
Array<uint8> mMemory;
|
||||
Dictionary<int, addr_ce> mStringMap;
|
||||
Dictionary<int, addr_ce> mReflectMap;
|
||||
Dictionary<Val128, addr_ce> mConstDataMap;
|
||||
HashSet<int> mStaticCtorExecSet;
|
||||
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
|
||||
Dictionary<void*, addr_ce> mMemToCtxMap;
|
||||
|
||||
BfMethodInstance* mCurMethodInstance;
|
||||
BfType* mCurExpectingType;
|
||||
BfAstNode* mCurTargetSrc;
|
||||
BfModule* mCurModule;
|
||||
CeFrame* mCurFrame;
|
||||
CeEmitContext* mCurEmitContext;
|
||||
|
||||
public:
|
||||
CeContext();
|
||||
~CeContext();
|
||||
|
||||
BfError* Fail(const StringImpl& error);
|
||||
BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
|
||||
|
||||
uint8* CeMalloc(int size);
|
||||
bool CeFree(addr_ce addr);
|
||||
addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
|
||||
addr_ce GetReflectType(int typeId);
|
||||
addr_ce GetReflectType(const String& typeName);
|
||||
int GetTypeIdFromType(addr_ce typeAddr);
|
||||
addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
|
||||
addr_ce GetString(int stringId);
|
||||
addr_ce GetConstantData(BeConstant* constant);
|
||||
BfType* GetBfType(int typeId);
|
||||
void PrepareConstStructEntry(CeConstStructData& constStructData);
|
||||
bool CheckMemory(addr_ce addr, int32 size);
|
||||
bool GetStringFromStringView(addr_ce addr, StringImpl& str);
|
||||
bool GetCustomAttribute(BfCustomAttributes* customAttributes, int attributeTypeId, addr_ce resultAddr);
|
||||
|
||||
bool WriteConstant(BfModule* module, addr_ce addr, BfConstant* constant, BfType* type, bool isParams = false);
|
||||
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
|
||||
BfIRValue CreateAttribute(BfAstNode* targetSrc, BfModule* module, BfIRConstHolder* constHolder, BfCustomAttribute* customAttribute);
|
||||
|
||||
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType);
|
||||
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
|
||||
};
|
||||
|
||||
class CeMachine
|
||||
{
|
||||
public:
|
||||
|
@ -624,63 +684,37 @@ public:
|
|||
Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
|
||||
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit
|
||||
|
||||
Array<CeContext*> mContextList;
|
||||
|
||||
BfCompiler* mCompiler;
|
||||
BfModule* mCeModule;
|
||||
int mRevision;
|
||||
int mRevisionExecuteTime;
|
||||
int mExecuteId;
|
||||
int mCurFunctionId;
|
||||
|
||||
// These are only valid for the current execution
|
||||
ContiguousHeap* mHeap;
|
||||
Array<CeFrame> mCallStack;
|
||||
Array<uint8> mMemory;
|
||||
Dictionary<int, addr_ce> mStringMap;
|
||||
int mStringCharsOffset;
|
||||
Dictionary<int, addr_ce> mReflectMap;
|
||||
Dictionary<Val128, addr_ce> mConstDataMap;
|
||||
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
|
||||
HashSet<int> mStaticCtorExecSet;
|
||||
int mExecuteId;
|
||||
CeAppendAllocInfo* mAppendAllocInfo;
|
||||
|
||||
CeContext* mCurContext;
|
||||
CeEmitContext* mCurEmitContext;
|
||||
CeEvalFlags mCurEvalFlags;
|
||||
CeBuilder* mCurBuilder;
|
||||
CeFunction* mPreparingFunction;
|
||||
CeFrame* mCurFrame;
|
||||
BfAstNode* mCurTargetSrc;
|
||||
BfMethodInstance* mCurMethodInstance;
|
||||
BfModule* mCurModule;
|
||||
BfType* mCurExpectingType;
|
||||
|
||||
BfParser* mTempParser;
|
||||
BfReducer* mTempReducer;
|
||||
BfPassInstance* mTempPassInstance;
|
||||
|
||||
public:
|
||||
CeMachine(BfCompiler* compiler);
|
||||
~CeMachine();
|
||||
|
||||
BfError* Fail(const StringImpl& error);
|
||||
BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
|
||||
|
||||
void Init();
|
||||
uint8* CeMalloc(int size);
|
||||
bool CeFree(addr_ce addr);
|
||||
addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
|
||||
addr_ce GetReflectType(int typeId);
|
||||
addr_ce GetString(int stringId);
|
||||
addr_ce GetConstantData(BeConstant* constant);
|
||||
BfType* GetBfType(int typeId);
|
||||
void PrepareConstStructEntry(CeConstStructData& constStructData);
|
||||
bool CheckMemory(addr_ce addr, int32 size);
|
||||
bool GetStringFromStringView(addr_ce addr, StringImpl& str);
|
||||
|
||||
BeContext* GetBeContext();
|
||||
BeModule* GetBeModule();
|
||||
|
||||
void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
|
||||
void RemoveMethod(BfMethodInstance* methodInstance);
|
||||
bool WriteConstant(BfModule* module, addr_ce addr, BfConstant* constant, BfType* type, bool isParams = false);
|
||||
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal);
|
||||
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
|
||||
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
|
||||
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType);
|
||||
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext);
|
||||
|
||||
void PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder);
|
||||
void MapFunctionId(CeFunction* ceFunction);
|
||||
|
@ -699,6 +733,8 @@ public:
|
|||
void SetAppendAllocInfo(BfModule* module, BfIRValue allocValue, BfIRValue appendSizeValue);
|
||||
void ClearAppendAllocInfo();
|
||||
|
||||
CeContext* AllocContext();
|
||||
void ReleaseContext(CeContext* context);
|
||||
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
|
||||
};
|
||||
|
||||
|
|
64
IDEHelper/Tests/src/Comptime.bf
Normal file
64
IDEHelper/Tests/src/Comptime.bf
Normal file
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
class Comptime
|
||||
{
|
||||
[AttributeUsage(.All)]
|
||||
struct IFaceAAttribute : Attribute, IComptimeTypeApply
|
||||
{
|
||||
String mMemberName;
|
||||
int32 mInitVal;
|
||||
|
||||
public int32 InitVal
|
||||
{
|
||||
set mut
|
||||
{
|
||||
mInitVal = value;
|
||||
}
|
||||
}
|
||||
|
||||
public this(String memberName)
|
||||
{
|
||||
mMemberName = memberName;
|
||||
mInitVal = 0;
|
||||
}
|
||||
|
||||
[Comptime]
|
||||
public void ApplyToType(Type type)
|
||||
{
|
||||
Compiler.EmitDefinition(type, scope $"""
|
||||
public int32 m{mMemberName} = {mInitVal};
|
||||
public int32 GetVal{mMemberName}() => mC;
|
||||
""");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[IFaceA("C", InitVal=345)]
|
||||
class ClassA
|
||||
{
|
||||
public int mA = 123;
|
||||
|
||||
[OnCompile(.TypeInit), Comptime]
|
||||
public static void Generate()
|
||||
{
|
||||
Compiler.EmitDefinition(typeof(Self), """
|
||||
public int32 mB = 234;
|
||||
public int32 GetValB() => mB;
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
ClassA ca = scope .();
|
||||
Test.Assert(ca.mA == 123);
|
||||
Test.Assert(ca.mB == 234);
|
||||
Test.Assert(ca.GetValB() == 234);
|
||||
Test.Assert(ca.mC == 345);
|
||||
Test.Assert(ca.GetValC() == 345);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -211,9 +211,26 @@ namespace Tests
|
|||
MethodA(list);
|
||||
}
|
||||
|
||||
public static void MethodC()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void MethodD(delegate void() dlg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void MethodD<T1>(delegate void(T1) dlg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
MethodD(scope => MethodC);
|
||||
|
||||
List<Entry> list = scope .();
|
||||
list.Sort();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue