1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Early code generation support

This commit is contained in:
Brian Fiete 2021-01-11 09:41:43 -08:00
parent 0b48a60592
commit 71d4dd0e90
26 changed files with 2422 additions and 1576 deletions

View file

@ -274,6 +274,21 @@ namespace System
} }
[AttributeUsage(.Method)]
struct OnCompileAttribute : Attribute
{
public enum Kind
{
None,
TypeInit,
TypeDone
}
public this(Kind kind)
{
}
}
[AttributeUsage(.Method)] [AttributeUsage(.Method)]
public struct ComptimeAttribute : Attribute public struct ComptimeAttribute : Attribute
{ {

View file

@ -1,21 +1,6 @@
using System.Reflection; using System.Reflection;
namespace System namespace System
{ {
[AttributeUsage(.Method)]
struct OnCompileAttribute : Attribute
{
public enum Kind
{
None,
TypeInit,
TypeDone
}
public this(Kind kind)
{
}
}
static class Compiler static class Compiler
{ {
public struct MethodBuilder public struct MethodBuilder

View file

@ -7,9 +7,33 @@ namespace System.Reflection
*((*(T2**)&data)++) *((*(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) public static Result<void> GetCustomAttribute(void* inAttrData, Type attributeType, Object targetAttr)
{ {
TypeId findTypeId = attributeType.[Friend]mTypeId; TypeId findTypeId = attributeType.[Friend]mTypeId;
void* data = inAttrData; void* data = inAttrData;

View file

@ -472,6 +472,9 @@ namespace System
} }
static extern Type Comptime_GetTypeById(int32 typeId); 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) protected static Type GetType(TypeId typeId)
{ {
@ -487,6 +490,19 @@ namespace System
return sTypes[typeId]; 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) void GetBasicName(String strBuffer)
{ {
switch (mTypeCode) switch (mTypeCode)
@ -557,8 +573,28 @@ namespace System
return FieldInfo.Enumerator(null, bindingFlags); 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 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) if (var typeInstance = this as TypeInstance)
return typeInstance.[Friend]GetCustomAttribute<T>(typeInstance.[Friend]mCustomAttributesIdx); return typeInstance.[Friend]GetCustomAttribute<T>(typeInstance.[Friend]mCustomAttributesIdx);
return .Err; return .Err;
@ -577,6 +613,9 @@ namespace System
{ {
while (true) while (true)
{ {
if (Compiler.IsComptime)
Runtime.FatalError("Comptime type enumeration not supported");
if (mCurId >= sTypeCount) if (mCurId >= sTypeCount)
return .Err; return .Err;
let type = sTypes[mCurId++]; let type = sTypes[mCurId++];
@ -929,6 +968,15 @@ namespace System.Reflection
return FieldInfo.Enumerator(this, bindingFlags); 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 Result<T> GetCustomAttribute<T>(int customAttributeIdx) where T : Attribute
{ {
if (customAttributeIdx == -1) if (customAttributeIdx == -1)
@ -1043,6 +1091,17 @@ namespace System.Reflection
} }
uint8 mGenericParamCount; 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 // Only for resolved types

View file

@ -813,6 +813,25 @@ bool BfAstNode::LocationEndEquals(BfAstNode* otherNode)
(GetSrcEnd() == otherNode->GetSrcEnd()); (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) void BfAstNode::Add(BfAstNode* bfAstNode)
{ {
#ifdef BF_AST_HAS_PARENT_MEMBER #ifdef BF_AST_HAS_PARENT_MEMBER

View file

@ -1101,6 +1101,7 @@ public:
static void ClassAccept(BfAstNode* node, BfStructuralVisitor* bfVisitor) { bfVisitor->Visit(node); } static void ClassAccept(BfAstNode* node, BfStructuralVisitor* bfVisitor) { bfVisitor->Visit(node); }
bool LocationEquals(BfAstNode* otherNode); bool LocationEquals(BfAstNode* otherNode);
bool LocationEndEquals(BfAstNode* otherNode); bool LocationEndEquals(BfAstNode* otherNode);
String LocationToString();
void Add(BfAstNode* bfAstNode); void Add(BfAstNode* bfAstNode);
bool IsMissingSemicolon(); bool IsMissingSemicolon();
bool IsExpression(); bool IsExpression();

View file

@ -8574,8 +8574,6 @@ int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
return -1; return -1;
String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1); String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);
int revisionId = (int)atoi(typeIdStr.c_str());
int typeId = (int)atoi(typeIdStr.c_str()); int typeId = (int)atoi(typeIdStr.c_str());
if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize)) if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize))
return -1; return -1;
@ -8786,7 +8784,9 @@ BF_EXPORT int BF_CALLTYPE BfCompiler_GetCurConstEvalExecuteId(BfCompiler* bfComp
{ {
if (bfCompiler->mCEMachine == NULL) if (bfCompiler->mCEMachine == NULL)
return -1; return -1;
if (bfCompiler->mCEMachine->mCurMethodInstance == NULL) if (bfCompiler->mCEMachine->mCurContext == NULL)
return -1;
if (bfCompiler->mCEMachine->mCurContext->mCurMethodInstance == NULL)
return -1; return -1;
return bfCompiler->mCEMachine->mExecuteId; return bfCompiler->mCEMachine->mExecuteId;
} }

View file

@ -366,7 +366,8 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
} }
} }
mModule->Fail(StrFormat("Not enough parameters specified. Expected %d fewer.", methodInstance->GetParamCount() - (int)arguments.size()), refNode); if (mModule->PreFail())
mModule->Fail(StrFormat("Not enough parameters specified. Expected %d fewer.", methodInstance->GetParamCount() - (int)arguments.size()), refNode);
return false; return false;
} }

View file

@ -119,6 +119,7 @@ public:
ResolveKind_ResolvingVarType, ResolveKind_ResolvingVarType,
ResolveKind_UnionInnerType, ResolveKind_UnionInnerType,
ResolveKind_LocalVariable, ResolveKind_LocalVariable,
ResolveKind_Attributes
}; };
public: public:

View file

@ -61,6 +61,7 @@ BfDefBuilder::BfDefBuilder(BfSystem* bfSystem)
mCurTypeDef = NULL; mCurTypeDef = NULL;
mCurActualTypeDef = NULL; mCurActualTypeDef = NULL;
mFullRefresh = false; mFullRefresh = false;
mIsComptime = false;
mResolvePassData = NULL; mResolvePassData = NULL;
mCurSource = NULL; mCurSource = NULL;
@ -1184,7 +1185,7 @@ BfFieldDef* BfDefBuilder::AddField(BfTypeDef* typeDef, BfTypeReference* fieldTyp
return fieldDef; 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); BF_ASSERT(typeDef->mTypeCode != BfTypeCode_TypeAlias);
@ -1193,6 +1194,7 @@ BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType
typeDef->mMethods.push_back(methodDef); typeDef->mMethods.push_back(methodDef);
methodDef->mDeclaringType = typeDef; methodDef->mDeclaringType = typeDef;
methodDef->mMethodType = methodType; methodDef->mMethodType = methodType;
methodDef->mAddedAfterEmit = addedAfterEmit;
if (name.empty()) if (name.empty())
{ {
if (methodType == BfMethodType_Ctor) if (methodType == BfMethodType_Ctor)
@ -1364,6 +1366,12 @@ BfTypeDef* BfDefBuilder::ComparePrevTypeDef(BfTypeDef* prevTypeDef, BfTypeDef* c
void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) 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); BF_ASSERT(typeDeclaration->GetSourceData() == mCurSource->mSourceData);
if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mNameNode == NULL)) if ((typeDeclaration->mTypeNode != NULL) && (typeDeclaration->mNameNode == NULL))
@ -1999,6 +2007,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mReturnTypeRef = mSystem->mDirectIntTypeRef; methodDef->mReturnTypeRef = mSystem->mDirectIntTypeRef;
methodDef->mIsStatic = true; methodDef->mIsStatic = true;
methodDef->mBody = method->mBody; methodDef->mBody = method->mBody;
methodDef->mAddedAfterEmit = mIsComptime;
for (auto param : method->mParams) for (auto param : method->mParams)
{ {
@ -2158,24 +2167,24 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic) && (ctorClear == NULL)) 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; methodDef->mIsMutating = true;
} }
if ((needsDtor) && (dtor == NULL)) 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); BF_ASSERT(mCurTypeDef->mDtorDef == methodDef);
} }
if ((needsStaticDtor) && (staticDtor == NULL)) 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)) 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; 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, // 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 // 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; methodDef->mIsMutating = true;
} }
@ -2229,19 +2238,19 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
{ {
if ((hasStaticField) && (staticMarkMethod == NULL)) 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; methodDef->mIsNoReflect = true;
} }
if (hasThreadStatics) 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; methodDef->mIsNoReflect = true;
} }
if ((hasNonStaticField) && (markMethod == NULL)) 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->mIsVirtual = true;
methodDef->mIsOverride = true; methodDef->mIsOverride = true;
methodDef->mIsNoReflect = true; methodDef->mIsNoReflect = true;
@ -2262,6 +2271,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef; methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
methodDef->mProtection = BfProtection_Public; methodDef->mProtection = BfProtection_Public;
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "checkEnum"); AddParam(methodDef, mSystem->mDirectSelfTypeRef, "checkEnum");
methodDef->mAddedAfterEmit = mIsComptime;
// Underlying // Underlying
{ {
@ -2272,6 +2282,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mReturnTypeRef = mSystem->mDirectSelfBaseTypeRef; methodDef->mReturnTypeRef = mSystem->mDirectSelfBaseTypeRef;
methodDef->mMethodType = BfMethodType_PropertyGetter; methodDef->mMethodType = BfMethodType_PropertyGetter;
methodDef->mProtection = BfProtection_Public; methodDef->mProtection = BfProtection_Public;
methodDef->mAddedAfterEmit = mIsComptime;
auto propDef = new BfPropertyDef(); auto propDef = new BfPropertyDef();
mCurTypeDef->mProperties.Add(propDef); mCurTypeDef->mProperties.Add(propDef);
@ -2292,6 +2303,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mReturnTypeRef = mSystem->mDirectRefSelfBaseTypeRef; methodDef->mReturnTypeRef = mSystem->mDirectRefSelfBaseTypeRef;
methodDef->mMethodType = BfMethodType_PropertyGetter; methodDef->mMethodType = BfMethodType_PropertyGetter;
methodDef->mProtection = BfProtection_Public; methodDef->mProtection = BfProtection_Public;
methodDef->mAddedAfterEmit = mIsComptime;
auto propDef = new BfPropertyDef(); auto propDef = new BfPropertyDef();
mCurTypeDef->mProperties.Add(propDef); mCurTypeDef->mProperties.Add(propDef);
@ -2315,6 +2327,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mIsVirtual = true; methodDef->mIsVirtual = true;
AddParam(methodDef, mSystem->mDirectStringTypeRef, "outStr"); AddParam(methodDef, mSystem->mDirectStringTypeRef, "outStr");
mCurTypeDef->mHasOverrideMethods = true; mCurTypeDef->mHasOverrideMethods = true;
methodDef->mAddedAfterEmit = mIsComptime;
} }
if ((needsEqualsMethod) && (equalsMethod == NULL)) if ((needsEqualsMethod) && (equalsMethod == NULL))
@ -2328,6 +2341,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mIsStatic = true; methodDef->mIsStatic = true;
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs"); AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs"); AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
methodDef->mAddedAfterEmit = mIsComptime;
} }
if (needsEqualsMethod) if (needsEqualsMethod)
@ -2341,6 +2355,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mIsStatic = true; methodDef->mIsStatic = true;
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs"); AddParam(methodDef, mSystem->mDirectSelfTypeRef, "lhs");
AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs"); AddParam(methodDef, mSystem->mDirectSelfTypeRef, "rhs");
methodDef->mAddedAfterEmit = mIsComptime;
} }
HashContext inlineHashCtx; HashContext inlineHashCtx;

View file

@ -18,6 +18,7 @@ public:
BfTypeDef* mCurTypeDef; BfTypeDef* mCurTypeDef;
BfTypeDef* mCurActualTypeDef; BfTypeDef* mCurActualTypeDef;
bool mFullRefresh; bool mFullRefresh;
bool mIsComptime;
BfResolvePassData* mResolvePassData; BfResolvePassData* mResolvePassData;
BfAtomComposite mNamespace; BfAtomComposite mNamespace;
Array<BfAtomComposite> mNamespaceSearch; Array<BfAtomComposite> mNamespaceSearch;
@ -33,7 +34,7 @@ public:
//static BfNamedTypeReference* AllocTypeReference(BfSource* bfSource, const StringImpl& typeName); //static BfNamedTypeReference* AllocTypeReference(BfSource* bfSource, const StringImpl& typeName);
//static BfResolvedTypeReference* AllocTypeReference(BfSource* bfSource, BfType* type); //static BfResolvedTypeReference* AllocTypeReference(BfSource* bfSource, BfType* type);
static BfFieldDef* AddField(BfTypeDef* typeDef, BfTypeReference* typeRef, const StringImpl& name); 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 BfMethodDef* AddDtor(BfTypeDef* typeDef);
static void AddDynamicCastMethods(BfTypeDef* typeDef); static void AddDynamicCastMethods(BfTypeDef* typeDef);
void AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName); void AddParam(BfMethodDef* methodDef, BfTypeReference* typeRef, const StringImpl& paramName);

View file

@ -2093,35 +2093,38 @@ void BfMethodMatcher::FlushAmbiguityError()
{ {
if (!mAmbiguousEntries.empty()) if (!mAmbiguousEntries.empty())
{ {
BfError* error; if (mModule->PreFail())
if (!mMethodName.empty())
error = mModule->Fail(StrFormat("Ambiguous method call for '%s'", mMethodName.c_str()), mTargetSrc);
else
error = mModule->Fail("Ambiguous method call", mTargetSrc);
if (error != NULL)
{ {
auto unspecializedType = mModule->GetUnspecializedTypeInstance(mBestMethodTypeInstance); BfError* error;
BfMethodInstance* bestMethodInstance = mModule->GetRawMethodInstance(unspecializedType, mBestMethodDef); if (!mMethodName.empty())
BfTypeVector* typeGenericArguments = NULL; error = mModule->Fail(StrFormat("Ambiguous method call for '%s'", mMethodName.c_str()), mTargetSrc);
if (mBestMethodTypeInstance->mGenericTypeInfo != NULL) else
typeGenericArguments = &mBestMethodTypeInstance->mGenericTypeInfo->mTypeGenericArguments; error = mModule->Fail("Ambiguous method call", mTargetSrc);
if (error != NULL)
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", mModule->MethodToString(bestMethodInstance, BfMethodNameFlag_ResolveGenericParamNames,
typeGenericArguments, mBestMethodGenericArguments.empty() ? NULL : &mBestMethodGenericArguments).c_str()),
bestMethodInstance->mMethodDef->GetRefNode());
for (auto& ambiguousEntry : mAmbiguousEntries)
{ {
auto typeInstance = ambiguousEntry.mMethodInstance->GetOwner(); auto unspecializedType = mModule->GetUnspecializedTypeInstance(mBestMethodTypeInstance);
auto unspecTypeMethodInstance = mModule->GetUnspecializedMethodInstance(ambiguousEntry.mMethodInstance, true); BfMethodInstance* bestMethodInstance = mModule->GetRawMethodInstance(unspecializedType, mBestMethodDef);
BfTypeVector* typeGenericArguments = NULL; BfTypeVector* typeGenericArguments = NULL;
if (typeInstance->mGenericTypeInfo != NULL) if (mBestMethodTypeInstance->mGenericTypeInfo != NULL)
typeGenericArguments = &typeInstance->mGenericTypeInfo->mTypeGenericArguments; typeGenericArguments = &mBestMethodTypeInstance->mGenericTypeInfo->mTypeGenericArguments;
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", mModule->MethodToString(unspecTypeMethodInstance, BfMethodNameFlag_ResolveGenericParamNames, mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", mModule->MethodToString(bestMethodInstance, BfMethodNameFlag_ResolveGenericParamNames,
typeGenericArguments, ambiguousEntry.mBestMethodGenericArguments.empty() ? NULL : &ambiguousEntry.mBestMethodGenericArguments).c_str()), typeGenericArguments, mBestMethodGenericArguments.empty() ? NULL : &mBestMethodGenericArguments).c_str()),
ambiguousEntry.mMethodInstance->mMethodDef->GetRefNode()); bestMethodInstance->mMethodDef->GetRefNode());
for (auto& ambiguousEntry : mAmbiguousEntries)
{
auto typeInstance = ambiguousEntry.mMethodInstance->GetOwner();
auto unspecTypeMethodInstance = mModule->GetUnspecializedMethodInstance(ambiguousEntry.mMethodInstance, true);
BfTypeVector* typeGenericArguments = NULL;
if (typeInstance->mGenericTypeInfo != NULL)
typeGenericArguments = &typeInstance->mGenericTypeInfo->mTypeGenericArguments;
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", mModule->MethodToString(unspecTypeMethodInstance, BfMethodNameFlag_ResolveGenericParamNames,
typeGenericArguments, ambiguousEntry.mBestMethodGenericArguments.empty() ? NULL : &ambiguousEntry.mBestMethodGenericArguments).c_str()),
ambiguousEntry.mMethodInstance->mMethodDef->GetRefNode());
}
} }
} }
@ -3759,7 +3762,13 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
if (!thisValue.HasType()) if (!thisValue.HasType())
{ {
thisValue = BfTypedValue(mModule->mCurTypeInstance); 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);
} }
BfTypedValue result; BfTypedValue result;
@ -4315,13 +4324,16 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
} }
else if (!target) else if (!target)
{ {
if ((flags & BfLookupFieldFlag_CheckingOuter) != 0) if (mModule->PreFail())
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()), {
targetSrc); if ((flags & BfLookupFieldFlag_CheckingOuter) != 0)
else if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend)) 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()),
mModule->Fail(StrFormat("Cannot reference field '%s' before append allocations", field->mName.c_str()), targetSrc); targetSrc);
else else if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend))
mModule->Fail(StrFormat("Cannot reference non-static field '%s' from a static method", field->mName.c_str()), targetSrc); 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); return mModule->GetDefaultTypedValue(resolvedFieldType, false, BfDefaultValueKind_Addr);
} }
@ -4501,12 +4513,15 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
if (matchedProp != NULL) if (matchedProp != NULL)
{ {
auto error = mModule->Fail(StrFormat("Ambiguous reference to property '%s.%s'", mModule->TypeToString(curCheckType).c_str(), fieldName.c_str()), targetSrc); if (mModule->PreFail())
if (error != NULL)
{ {
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See property declaration in project '%s'", matchedProp->mDeclaringType->mProject->mName.c_str()), matchedProp->mFieldDeclaration); auto error = mModule->Fail(StrFormat("Ambiguous reference to property '%s.%s'", mModule->TypeToString(curCheckType).c_str(), fieldName.c_str()), targetSrc);
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See property declaration in project '%s'", prop->mDeclaringType->mProject->mName.c_str()), prop->mFieldDeclaration); if (error != NULL)
break; {
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See property declaration in project '%s'", matchedProp->mDeclaringType->mProject->mName.c_str()), matchedProp->mFieldDeclaration);
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See property declaration in project '%s'", prop->mDeclaringType->mProject->mName.c_str()), prop->mFieldDeclaration);
break;
}
} }
} }
@ -6202,31 +6217,34 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (argExprIdx < (int)argValues.size()) if (argExprIdx < (int)argValues.size())
{ {
BfAstNode* errorRef = argValues[argExprIdx].mExpression; if (mModule->PreFail())
if (errorRef == NULL)
errorRef = targetSrc;
BfError* error;
if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
{ {
int checkIdx = argExprIdx - 1; BfAstNode* errorRef = argValues[argExprIdx].mExpression;
while (checkIdx >= 0) if (errorRef == NULL)
errorRef = targetSrc;
BfError* error;
if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
{ {
if ((argValues[checkIdx].mArgFlags & BfArgFlag_StringInterpolateFormat) != 0) int checkIdx = argExprIdx - 1;
while (checkIdx >= 0)
{ {
errorRef = argValues[checkIdx].mExpression; if ((argValues[checkIdx].mArgFlags & BfArgFlag_StringInterpolateFormat) != 0)
break; {
errorRef = argValues[checkIdx].mExpression;
break;
}
checkIdx--;
} }
checkIdx--; error = mModule->Fail("Expanded string interpolation generates too many arguments. If string allocation was intended then consider adding a specifier such as 'scope'.", errorRef);
} }
error = mModule->Fail("Expanded string interpolation generates too many arguments. If string allocation was intended then consider adding a specifier such as 'scope'.", errorRef); else if ((prevBindResult.mPrevVal != NULL) && (prevBindResult.mPrevVal->mBindType != NULL))
error = mModule->Fail(StrFormat("Method '%s' has too few parameters to bind to '%s'.", mModule->MethodToString(methodInstance).c_str(), mModule->TypeToString(prevBindResult.mPrevVal->mBindType).c_str()), errorRef);
else
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());
} }
else if ((prevBindResult.mPrevVal != NULL) && (prevBindResult.mPrevVal->mBindType != NULL))
error = mModule->Fail(StrFormat("Method '%s' has too few parameters to bind to '%s'.", mModule->MethodToString(methodInstance).c_str(), mModule->TypeToString(prevBindResult.mPrevVal->mBindType).c_str()), errorRef);
else
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; failed = true;
break; break;
} }
@ -6488,8 +6506,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (showCtorError) if (showCtorError)
{ {
error = mModule->Fail(StrFormat("No parameterless constructor is available for base class. Consider calling base constructor '%s'.", if (mModule->PreFail())
mModule->MethodToString(methodInstance).c_str()), refNode); {
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(); auto srcNode = mModule->mCurMethodInstance->mMethodDef->GetRefNode();
if ((autoComplete != NULL) && (autoComplete->CheckFixit(srcNode))) if ((autoComplete != NULL) && (autoComplete->CheckFixit(srcNode)))
@ -6497,10 +6518,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
} }
} }
if (error == NULL) if (mModule->PreFail())
error = mModule->Fail(StrFormat("Not enough parameters specified, expected %d more.", methodInstance->GetParamCount() - paramIdx), refNode); {
if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL)) if (error == NULL)
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode()); 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; failed = true;
break; break;
} }

View file

@ -758,6 +758,20 @@ BfIRValue BfIRConstHolder::CreateConstAgg(BfIRType type, const BfSizedArray<BfIR
return irValue; 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) BfIRValue BfIRConstHolder::CreateConstArrayZero(BfIRType type, int count)
{ {
BfConstantArrayZero* constant = mTempAlloc.Alloc<BfConstantArrayZero>(); BfConstantArrayZero* constant = mTempAlloc.Alloc<BfConstantArrayZero>();

View file

@ -28,6 +28,8 @@
NS_BF_BEGIN NS_BF_BEGIN
typedef int addr_ce;
class BfModule; class BfModule;
class BfType; class BfType;
class BfTypeInstance; class BfTypeInstance;
@ -123,6 +125,7 @@ enum BfConstType
BfConstType_TypeOf_WithData, BfConstType_TypeOf_WithData,
BfConstType_AggZero, BfConstType_AggZero,
BfConstType_Agg, BfConstType_Agg,
BfConstType_AggCE,
BfConstType_ArrayZero, BfConstType_ArrayZero,
BfConstType_ArrayZero8, BfConstType_ArrayZero8,
BfConstType_Undef, BfConstType_Undef,
@ -874,6 +877,13 @@ struct BfConstantAgg
BfSizedArray<BfIRValue> mValues; BfSizedArray<BfIRValue> mValues;
}; };
struct BfConstantAggCE
{
BfConstType mConstType;
BfIRType mType;
addr_ce mCEAddr;
};
struct BfConstantArrayZero struct BfConstantArrayZero
{ {
BfConstType mConstType; BfConstType mConstType;
@ -904,6 +914,7 @@ public:
bool TryGetBool(BfIRValue id, bool& boolVal); bool TryGetBool(BfIRValue id, bool& boolVal);
int IsZero(BfIRValue val); int IsZero(BfIRValue val);
int CheckConstEquality(BfIRValue lhs, BfIRValue rhs); // -1 = fail, 0 = false, 1 = true 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, uint64 val);
BfIRValue CreateConst(BfTypeCode typeCode, int val); BfIRValue CreateConst(BfTypeCode typeCode, int val);
@ -913,6 +924,7 @@ public:
BfIRValue CreateConstNull(BfIRType nullType); BfIRValue CreateConstNull(BfIRType nullType);
BfIRValue CreateConstStructZero(BfIRType aggType); BfIRValue CreateConstStructZero(BfIRType aggType);
BfIRValue CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values); BfIRValue CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values);
BfIRValue CreateConstAggCE(BfIRType type, addr_ce ptr);
BfIRValue CreateConstArrayZero(BfIRType type, int count); BfIRValue CreateConstArrayZero(BfIRType type, int count);
BfIRValue CreateConstArrayZero(int count); BfIRValue CreateConstArrayZero(int count);
BfIRValue CreateTypeOf(BfType* type); BfIRValue CreateTypeOf(BfType* type);

View file

@ -2714,6 +2714,14 @@ void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementTyp
} }
} }
bool BfModule::PreFail()
{
if (!mIgnoreErrors)
return true;
SetFail();
return false;
}
void BfModule::SetFail() void BfModule::SetFail()
{ {
if (mIgnoreErrors) if (mIgnoreErrors)
@ -2758,7 +2766,7 @@ bool BfModule::IsSkippingExtraResolveChecks()
return mCompiler->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"); BP_ZONE("BfModule::Fail");
@ -2825,7 +2833,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
{ {
auto _CheckMethodInstance = [&](BfMethodInstance* methodInstance) 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; methodInstance->mHasFailed = true;
bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0)); bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0));
@ -2887,18 +2895,18 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
if (!_CheckMethodInstance(mCurMethodInstance)) if (!_CheckMethodInstance(mCurMethodInstance))
return NULL; return NULL;
} }
}
// Keep in mind that all method specializations with generic type instances as its method generic params // 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 // 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 // compilation due to no longer having indirect references removed, and we have to ignore errors from
// those method specializations if that occurs // those method specializations if that occurs
if (isWhileSpecializing) if ((isWhileSpecializing) || (deferError))
{ {
BfError* bfError = mCompiler->mPassInstance->DeferFail(errorString, refNode); BfError* bfError = mCompiler->mPassInstance->DeferFail(errorString, refNode);
if (bfError != NULL) if (bfError != NULL)
bfError->mIsWhileSpecializing = isWhileSpecializing; bfError->mIsWhileSpecializing = isWhileSpecializing;
return bfError; return bfError;
}
} }
if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))) if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())))
@ -10618,7 +10626,7 @@ BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConst
return BfTypedValue(irValue, wantType, false); 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) if (constant->mTypeCode == BfTypeCode_NullPtr)
{ {
@ -10633,14 +10641,17 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
if (constant->mTypeCode == BfTypeCode_StringId) if (constant->mTypeCode == BfTypeCode_StringId)
{ {
if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) || if (!allowStringId)
((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
{ {
const StringImpl& str = mContext->mStringObjectIdMap[constant->mInt32].mString; if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) ||
BfIRValue stringObjConst = GetStringObjectValue(str); ((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
if (wantType->IsPointer()) {
return GetStringCharPtr(stringObjConst); const StringImpl& str = mContext->mStringObjectIdMap[constant->mInt32].mString;
return stringObjConst; BfIRValue stringObjConst = GetStringObjectValue(str);
if (wantType->IsPointer())
return GetStringCharPtr(stringObjConst);
return stringObjConst;
}
} }
} }
@ -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); return mBfIRBuilder->CreateConst(constant, constHolder);
@ -10838,6 +10849,23 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
customAttribute.mType = attrTypeInst; 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); BfConstResolver constResolver(this);
if (allowNonConstArgs) if (allowNonConstArgs)
constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst); constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst);
@ -19747,6 +19775,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction); 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 ((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 // If we hot swap, we want to make sure at least one method refers to this extern method so it gets pulled in

View file

@ -1481,10 +1481,11 @@ public:
void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate); void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate);
bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType); bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType);
void SetElementType(BfAstNode* astNode, BfSourceElementType elementType); void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);
bool PreFail();
void SetFail(); void SetFail();
void VerifyOnDemandMethods(); void VerifyOnDemandMethods();
bool IsSkippingExtraResolveChecks(); 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* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode); BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false); BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);
@ -1526,7 +1527,7 @@ public:
void CurrentAddToConstHolder(BfIRValue& irVal); void CurrentAddToConstHolder(BfIRValue& irVal);
void ClearConstData(); void ClearConstData();
BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType); 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 ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget);
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL); 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); BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
@ -1698,7 +1699,8 @@ public:
BfModuleOptions GetModuleOptions(); BfModuleOptions GetModuleOptions();
BfCheckedKind GetDefaultCheckedKind(); BfCheckedKind GetDefaultCheckedKind();
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode); 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 DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data); void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
static BfModule* GetModuleFor(BfType* type); static BfModule* GetModuleFor(BfType* type);

View file

@ -1952,9 +1952,11 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
src += ceEmitContext->mEmitData; src += ceEmitContext->mEmitData;
ceEmitContext->mEmitData.Clear(); ceEmitContext->mEmitData.Clear();
bool createdParser = false;
int startSrcIdx = 0; int startSrcIdx = 0;
if (activeTypeDef->mEmitParser == NULL) if (activeTypeDef->mEmitParser == NULL)
{ {
createdParser = true;
BfParser* parser = new BfParser(mSystem, typeInstance->mTypeDef->mProject); BfParser* parser = new BfParser(mSystem, typeInstance->mTypeDef->mProject);
parser->mIsEmitted = true; parser->mIsEmitted = true;
parser->mFileName = typeInstance->mTypeDef->mName->ToString(); parser->mFileName = typeInstance->mTypeDef->mName->ToString();
@ -1999,11 +2001,14 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
bfReducer.HandleTypeDeclaration(typeDeclaration, NULL); bfReducer.HandleTypeDeclaration(typeDeclaration, NULL);
BfDefBuilder defBuilder(mSystem); BfDefBuilder defBuilder(mSystem);
defBuilder.mCurSource = activeTypeDef->mEmitParser;
defBuilder.mCurTypeDef = typeInstance->mTypeDef; defBuilder.mCurTypeDef = typeInstance->mTypeDef;
defBuilder.mPassInstance = mCompiler->mPassInstance;
defBuilder.mIsComptime = true;
defBuilder.DoVisitChild(typeDeclaration->mDefineNode); defBuilder.DoVisitChild(typeDeclaration->mDefineNode);
defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum); defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum);
// if (createdParser)
{ {
AutoCrit crit(mSystem->mDataLock); AutoCrit crit(mSystem->mDataLock);
mSystem->mParsers.Add(activeTypeDef->mEmitParser); 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) BfTypeInstance* iComptimeTypeApply = NULL;
return; 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(); int methodCount = (int)typeInstance->mTypeDef->mMethods.size();
for (int methodIdx = 0; methodIdx < methodCount; methodIdx++) for (int methodIdx = 0; methodIdx < methodCount; methodIdx++)
@ -2034,6 +2106,28 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
continue; continue;
if (methodDeclaration->mAttributes == NULL) if (methodDeclaration->mAttributes == NULL)
continue; 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); auto customAttributes = GetCustomAttributes(methodDeclaration->mAttributes, BfAttributeTargets_Method);
defer({ delete customAttributes; }); defer({ delete customAttributes; });
@ -2041,6 +2135,8 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
if (onCompileAttribute == NULL) if (onCompileAttribute == NULL)
continue; continue;
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes);
if (onCompileAttribute->mCtorArgs.size() < 1) if (onCompileAttribute->mCtorArgs.size() < 1)
continue; continue;
auto constant = typeInstance->mConstHolder->GetConstant(onCompileAttribute->mCtorArgs[0]); auto constant = typeInstance->mConstHolder->GetConstant(onCompileAttribute->mCtorArgs[0]);
@ -2062,7 +2158,6 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
} }
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext); SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext);
if (onCompileKind == BfCEOnCompileKind_TypeInit) if (onCompileKind == BfCEOnCompileKind_TypeInit)
{ {
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext; mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
@ -2075,6 +2170,8 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
{ {
String ctxStr = "OnCompile execution of "; String ctxStr = "OnCompile execution of ";
ctxStr += MethodToString(methodInstance); ctxStr += MethodToString(methodInstance);
ctxStr += " ";
ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString();
UpdateCEEmit(ceEmitContext, typeInstance, methodInstance->mMethodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode()); 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 startMethodCount = typeInstance->mTypeDef->mMethods.mSize;
int startFieldCount = typeInstance->mTypeDef->mFields.mSize; int startFieldCount = typeInstance->mTypeDef->mFields.mSize;
int startPropCount = typeInstance->mTypeDef->mProperties.mSize;
CeEmitContext emitContext; CeEmitContext emitContext;
emitContext.mType = typeInstance; emitContext.mType = typeInstance;
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit, &emitContext); ExecuteCEOnCompile(&emitContext, typeInstance, BfCEOnCompileKind_TypeInit);
if ((startMethodCount != typeInstance->mTypeDef->mMethods.mSize) || if ((startMethodCount != typeInstance->mTypeDef->mMethods.mSize) ||
(startFieldCount != typeInstance->mTypeDef->mFields.mSize)) (startFieldCount != typeInstance->mTypeDef->mFields.mSize) ||
(startPropCount != typeInstance->mTypeDef->mProperties.mSize))
{ {
typeInstance->mTypeDef->ClearMemberSets(); typeInstance->mTypeDef->ClearMemberSets();
hadNewMembers = true; hadNewMembers = true;
@ -3004,6 +3103,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
attrTarget = BfAttributeTargets_Class; attrTarget = BfAttributeTargets_Class;
if (!typeInstance->mTypeFailed) 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 // This allows us to avoid reentrancy when checking for inner types
SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true); SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
if (typeDef->mIsCombinedPartial) if (typeDef->mIsCombinedPartial)
@ -3012,19 +3117,17 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
if (partialTypeDef->mTypeDeclaration->mAttributes == NULL) if (partialTypeDef->mTypeDeclaration->mAttributes == NULL)
continue; 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) if (typeInstance->mCustomAttributes == NULL)
typeInstance->mCustomAttributes = new BfCustomAttributes(); typeInstance->mCustomAttributes = new BfCustomAttributes();
GetCustomAttributes(typeInstance->mCustomAttributes, partialTypeDef->mTypeDeclaration->mAttributes, attrTarget); GetCustomAttributes(typeInstance->mCustomAttributes, partialTypeDef->mTypeDeclaration->mAttributes, attrTarget);
} }
} }
else else
{
typeInstance->mCustomAttributes = GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, attrTarget); typeInstance->mCustomAttributes = GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, attrTarget);
}
} }
} }
} }
@ -3364,10 +3467,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
auto refNode = typeDef->GetRefNode(); auto refNode = typeDef->GetRefNode();
Fail(error, refNode); Fail(error, refNode);
if (mCompiler->mCEMachine->mCurFrame != NULL) if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurFrame != NULL))
mCompiler->mCEMachine->Fail(*mCompiler->mCEMachine->mCurFrame, error); mCompiler->mCEMachine->mCurContext->Fail(*mCompiler->mCEMachine->mCurContext->mCurFrame, error);
else else if (mCompiler->mCEMachine->mCurContext != NULL)
mCompiler->mCEMachine->Fail(error); mCompiler->mCEMachine->mCurContext->Fail(error);
} }
else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
{ {
@ -3906,7 +4009,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
typeInstance->mDefineState = BfTypeDefineState_Defined; typeInstance->mDefineState = BfTypeDefineState_Defined;
if (!typeInstance->IsBoxed()) if (!typeInstance->IsBoxed())
ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeDone, NULL); ExecuteCEOnCompile(NULL, typeInstance, BfCEOnCompileKind_TypeDone);
} }
if (typeInstance->mTypeFailed) if (typeInstance->mTypeFailed)

View file

@ -493,6 +493,8 @@ void BfParser::NewLine()
mLineStart = mSrcIdx; mLineStart = mSrcIdx;
mLineNum++; mLineNum++;
if (mJumpTable == NULL)
return;
int idx = (mSrcIdx / PARSER_JUMPTABLE_DIVIDE); int idx = (mSrcIdx / PARSER_JUMPTABLE_DIVIDE);
if (idx == 0) if (idx == 0)
return; return;
@ -575,7 +577,8 @@ void BfParser::SetSource(const char* data, int length)
mOrigSrcLength = length; mOrigSrcLength = length;
mSrcAllocSize = mSrcLength /*+ EXTRA_BUFFER_SIZE*/; mSrcAllocSize = mSrcLength /*+ EXTRA_BUFFER_SIZE*/;
char* ownedSrc = new char[mSrcAllocSize + 1]; char* ownedSrc = new char[mSrcAllocSize + 1];
memcpy(ownedSrc, data, length); if (data != NULL)
memcpy(ownedSrc, data, length);
ownedSrc[length] = 0; ownedSrc[length] = 0;
mSrc = ownedSrc; mSrc = ownedSrc;
mSrcIdx = 0; mSrcIdx = 0;
@ -3482,9 +3485,12 @@ void BfParser::Parse(BfPassInstance* passInstance)
mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first); mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first);
} }
for (int i = (startIdx / PARSER_JUMPTABLE_DIVIDE)+1; i < mJumpTableSize; i++) if (mJumpTable != NULL)
if (mJumpTable[i].mCharIdx == 0) {
mJumpTable[i] = mJumpTable[i - 1]; for (int i = (startIdx / PARSER_JUMPTABLE_DIVIDE) + 1; i < mJumpTableSize; i++)
if (mJumpTable[i].mCharIdx == 0)
mJumpTable[i] = mJumpTable[i - 1];
}
if (mPassInstance->HasFailed()) if (mPassInstance->HasFailed())
mParsingFailed = true; mParsingFailed = true;

View file

@ -2671,6 +2671,14 @@ BfCustomAttribute* BfCustomAttributes::Get(BfTypeDef * typeDef)
return NULL; return NULL;
} }
BfCustomAttribute* BfCustomAttributes::Get(BfType* type)
{
for (auto& customAttr : mAttributes)
if (customAttr.mType == type)
return &customAttr;
return NULL;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
BfResolvedTypeSet::~BfResolvedTypeSet() BfResolvedTypeSet::~BfResolvedTypeSet()

View file

@ -2410,6 +2410,7 @@ public:
Array<BfCustomAttribute> mAttributes; Array<BfCustomAttribute> mAttributes;
bool Contains(BfTypeDef* typeDef); bool Contains(BfTypeDef* typeDef);
BfCustomAttribute* Get(BfTypeDef* typeDef); BfCustomAttribute* Get(BfTypeDef* typeDef);
BfCustomAttribute* Get(BfType* type);
void ReportMemory(MemReporter* memReporter); void ReportMemory(MemReporter* memReporter);
}; };

View file

@ -696,7 +696,8 @@ void BfTypeDef::ClearEmitted()
for (int methodIdx = (int)mMethods.size() - 1; methodIdx >= 0; methodIdx--) for (int methodIdx = (int)mMethods.size() - 1; methodIdx >= 0; methodIdx--)
{ {
auto methodDef = mMethods[methodIdx]; auto methodDef = mMethods[methodIdx];
if ((methodDef->mMethodDeclaration != NULL) && (methodDef->mMethodDeclaration->IsEmitted())) if ((methodDef->mAddedAfterEmit) ||
((methodDef->mMethodDeclaration != NULL) && (methodDef->mMethodDeclaration->IsEmitted())))
{ {
delete methodDef; delete methodDef;
mMethods.RemoveAt(methodIdx); mMethods.RemoveAt(methodIdx);
@ -712,6 +713,16 @@ void BfTypeDef::ClearEmitted()
mFields.RemoveAt(fieldIdx); 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; 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 BfTypeDef::ToString()
{ {
String typeName(mName->ToString()); String typeName(mName->ToString());
@ -1753,7 +1774,7 @@ void BfPassInstance::TryFlushDeferredError()
if (moreInfo->mSource != NULL) if (moreInfo->mSource != NULL)
MessageAt(":error", " > " + moreInfo->mInfo, moreInfo->mSource, moreInfo->mSrcStart, moreInfo->mSrcEnd - moreInfo->mSrcStart); MessageAt(":error", " > " + moreInfo->mInfo, moreInfo->mSource, moreInfo->mSrcStart, moreInfo->mSrcEnd - moreInfo->mSrcStart);
else else
OutputLine(":error" + moreInfo->mInfo); OutputLine(":error " + moreInfo->mInfo);
} }
} }
} }

View file

@ -41,6 +41,7 @@ class BfSystem;
class BfTypeReference; class BfTypeReference;
class BfCompiler; class BfCompiler;
class BfProject; class BfProject;
class BfTypeDef;
struct BfTypeDefMapFuncs; struct BfTypeDefMapFuncs;
typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap; typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap;
@ -794,6 +795,7 @@ public:
bool mIsExtern; bool mIsExtern;
bool mIsNoDiscard; bool mIsNoDiscard;
bool mHasExplicitThis; bool mHasExplicitThis;
bool mAddedAfterEmit;
BfCommutableKind mCommutableKind; BfCommutableKind mCommutableKind;
BfCheckedKind mCheckedKind; BfCheckedKind mCheckedKind;
BfImportKind mImportKind; BfImportKind mImportKind;
@ -823,6 +825,7 @@ public:
mIsExtern = false; mIsExtern = false;
mIsNoDiscard = false; mIsNoDiscard = false;
mHasExplicitThis = false; mHasExplicitThis = false;
mAddedAfterEmit = false;
mBody = NULL; mBody = NULL;
mExplicitInterface = NULL; mExplicitInterface = NULL;
mReturnTypeRef = NULL; mReturnTypeRef = NULL;
@ -1054,6 +1057,7 @@ public:
int GetSelfGenericParamCount(); int GetSelfGenericParamCount();
String ToString(); String ToString();
BfMethodDef* GetMethodByName(const StringImpl& name, int paramCount = -1); BfMethodDef* GetMethodByName(const StringImpl& name, int paramCount = -1);
BfFieldDef* GetFieldByName(const StringImpl& name);
bool HasAutoProperty(BfPropertyDeclaration* propertyDeclaration); bool HasAutoProperty(BfPropertyDeclaration* propertyDeclaration);
String GetAutoPropertyName(BfPropertyDeclaration* propertyDeclaration); String GetAutoPropertyName(BfPropertyDeclaration* propertyDeclaration);
BfAstNode* GetRefNode(); BfAstNode* GetRefNode();

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,8 @@
NS_BF_BEGIN NS_BF_BEGIN
class BfParser;
class BfReducer;
class BfMethodInstance; class BfMethodInstance;
class BeModule; class BeModule;
class BeContext; class BeContext;
@ -23,8 +25,6 @@ class BeGlobalVariable;
class CeMachine; class CeMachine;
class CeFunction; class CeFunction;
typedef int addr_ce;
#define CEOP_SIZED(OPNAME) \ #define CEOP_SIZED(OPNAME) \
CeOp_##OPNAME##_8, \ CeOp_##OPNAME##_8, \
CeOp_##OPNAME##_16, \ CeOp_##OPNAME##_16, \
@ -251,6 +251,9 @@ enum CeFunctionKind
CeFunctionKind_DebugWrite_Int, CeFunctionKind_DebugWrite_Int,
CeFunctionKind_GetReflectType, CeFunctionKind_GetReflectType,
CeFunctionKind_GetReflectTypeById, CeFunctionKind_GetReflectTypeById,
CeFunctionKind_GetReflectTypeByName,
CeFunctionKind_GetReflectSpecializedType,
CeFunctionKind_Type_GetCustomAttribute,
CeFunctionKind_EmitDefinition, CeFunctionKind_EmitDefinition,
CeFunctionKind_Sleep, CeFunctionKind_Sleep,
CeFunctionKind_Char32_ToLower, CeFunctionKind_Char32_ToLower,
@ -368,6 +371,7 @@ public:
} }
~CeFunction(); ~CeFunction();
void Print();
}; };
enum CeEvalFlags enum CeEvalFlags
@ -424,8 +428,9 @@ public:
}; };
#define BF_CE_STACK_SIZE 4*1024*1024 #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_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 #define BF_CE_MAX_CARRYOVER_HEAP 1024*1024
enum CeOperandInfoKind enum CeOperandInfoKind
@ -518,6 +523,7 @@ public:
Dictionary<BeConstant*, int> mConstDataMap; Dictionary<BeConstant*, int> mConstDataMap;
Dictionary<BeFunction*, int> mInnerFunctionMap; Dictionary<BeFunction*, int> mInnerFunctionMap;
Dictionary<BeGlobalVariable*, int> mStaticFieldMap; Dictionary<BeGlobalVariable*, int> mStaticFieldMap;
Dictionary<String, BfFieldInstance*> mStaticFieldInstanceMap;
public: public:
CeBuilder() CeBuilder()
@ -586,13 +592,11 @@ public:
class CeStaticFieldInfo class CeStaticFieldInfo
{ {
public: public:
BfFieldInstance* mFieldInstance;
addr_ce mAddr; addr_ce mAddr;
public: public:
CeStaticFieldInfo() CeStaticFieldInfo()
{ {
mFieldInstance = NULL;
mAddr = 0; 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 class CeMachine
{ {
public: public:
@ -624,63 +684,37 @@ public:
Dictionary<String, CeFunctionInfo*> mNamedFunctionMap; Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit
Array<CeContext*> mContextList;
BfCompiler* mCompiler; BfCompiler* mCompiler;
BfModule* mCeModule; BfModule* mCeModule;
int mRevision; int mRevision;
int mRevisionExecuteTime; int mRevisionExecuteTime;
int mExecuteId;
int mCurFunctionId; int mCurFunctionId;
int mExecuteId;
// 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;
CeAppendAllocInfo* mAppendAllocInfo; CeAppendAllocInfo* mAppendAllocInfo;
CeContext* mCurContext;
CeEmitContext* mCurEmitContext; CeEmitContext* mCurEmitContext;
CeEvalFlags mCurEvalFlags;
CeBuilder* mCurBuilder; CeBuilder* mCurBuilder;
CeFunction* mPreparingFunction; CeFunction* mPreparingFunction;
CeFrame* mCurFrame;
BfAstNode* mCurTargetSrc; BfParser* mTempParser;
BfMethodInstance* mCurMethodInstance; BfReducer* mTempReducer;
BfModule* mCurModule; BfPassInstance* mTempPassInstance;
BfType* mCurExpectingType;
public: public:
CeMachine(BfCompiler* compiler); CeMachine(BfCompiler* compiler);
~CeMachine(); ~CeMachine();
BfError* Fail(const StringImpl& error);
BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
void Init(); 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(); BeContext* GetBeContext();
BeModule* GetBeModule(); BeModule* GetBeModule();
void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo); void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
void RemoveMethod(BfMethodInstance* methodInstance); 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); 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 PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder);
void MapFunctionId(CeFunction* ceFunction); void MapFunctionId(CeFunction* ceFunction);
@ -699,6 +733,8 @@ public:
void SetAppendAllocInfo(BfModule* module, BfIRValue allocValue, BfIRValue appendSizeValue); void SetAppendAllocInfo(BfModule* module, BfIRValue allocValue, BfIRValue appendSizeValue);
void ClearAppendAllocInfo(); void ClearAppendAllocInfo();
CeContext* AllocContext();
void ReleaseContext(CeContext* context);
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType); BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
}; };

View 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);
}
}
}

View file

@ -211,9 +211,26 @@ namespace Tests
MethodA(list); MethodA(list);
} }
public static void MethodC()
{
}
public static void MethodD(delegate void() dlg)
{
}
public static void MethodD<T1>(delegate void(T1) dlg)
{
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
MethodD(scope => MethodC);
List<Entry> list = scope .(); List<Entry> list = scope .();
list.Sort(); list.Sort();