1
0
Fork 0
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:
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)]
public struct ComptimeAttribute : Attribute
{

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -8573,9 +8573,7 @@ int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
if (dotPos == -1)
return -1;
String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);
int revisionId = (int)atoi(typeIdStr.c_str());
String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);
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;
}

View file

@ -365,8 +365,9 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
autoComplete->CheckEmptyStart(prevNode, wantType);
}
}
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;
}

View file

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

View file

@ -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);
@ -1192,7 +1193,8 @@ BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType
methodDef->mIdx = (int)typeDef->mMethods.size();
typeDef->mMethods.push_back(methodDef);
methodDef->mDeclaringType = typeDef;
methodDef->mMethodType = methodType;
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)
{
@ -2014,7 +2023,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
newParam->mName = "appendIdx";
newParam->mTypeRef = mSystem->mDirectRefIntTypeRef;
newParam->mParamKind = BfParamKind_AppendIdx;
method->mParams.Insert(0, newParam);
method->mParams.Insert(0, newParam);
}
}
}
@ -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, "");
methodDef->mIsMutating = true;
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))
@ -2325,9 +2338,10 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mName = BF_METHODNAME_DEFAULT_EQUALS;
methodDef->mReturnTypeRef = mSystem->mDirectBoolTypeRef;
methodDef->mProtection = BfProtection_Private;
methodDef->mIsStatic = true;
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;

View file

@ -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);

View file

@ -2092,36 +2092,39 @@ Done:
void BfMethodMatcher::FlushAmbiguityError()
{
if (!mAmbiguousEntries.empty())
{
BfError* error;
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)
{
if (mModule->PreFail())
{
auto unspecializedType = mModule->GetUnspecializedTypeInstance(mBestMethodTypeInstance);
BfMethodInstance* bestMethodInstance = mModule->GetRawMethodInstance(unspecializedType, mBestMethodDef);
BfTypeVector* typeGenericArguments = NULL;
if (mBestMethodTypeInstance->mGenericTypeInfo != NULL)
typeGenericArguments = &mBestMethodTypeInstance->mGenericTypeInfo->mTypeGenericArguments;
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)
BfError* error;
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 typeInstance = ambiguousEntry.mMethodInstance->GetOwner();
auto unspecTypeMethodInstance = mModule->GetUnspecializedMethodInstance(ambiguousEntry.mMethodInstance, true);
auto unspecializedType = mModule->GetUnspecializedTypeInstance(mBestMethodTypeInstance);
BfMethodInstance* bestMethodInstance = mModule->GetRawMethodInstance(unspecializedType, mBestMethodDef);
BfTypeVector* typeGenericArguments = NULL;
if (typeInstance->mGenericTypeInfo != NULL)
typeGenericArguments = &typeInstance->mGenericTypeInfo->mTypeGenericArguments;
if (mBestMethodTypeInstance->mGenericTypeInfo != NULL)
typeGenericArguments = &mBestMethodTypeInstance->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());
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 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());
}
}
}
@ -3758,8 +3761,14 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
}
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;
@ -4314,14 +4323,17 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
return retVal;
}
else if (!target)
{
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()),
targetSrc);
else if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend))
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);
{
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()),
targetSrc);
else if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend))
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);
}
@ -4501,12 +4513,15 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
if (matchedProp != NULL)
{
auto error = mModule->Fail(StrFormat("Ambiguous reference to property '%s.%s'", mModule->TypeToString(curCheckType).c_str(), fieldName.c_str()), targetSrc);
if (error != NULL)
if (mModule->PreFail())
{
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;
auto error = mModule->Fail(StrFormat("Ambiguous reference to property '%s.%s'", mModule->TypeToString(curCheckType).c_str(), fieldName.c_str()), targetSrc);
if (error != NULL)
{
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;
}
}
}
@ -6201,32 +6216,35 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
}
if (argExprIdx < (int)argValues.size())
{
BfAstNode* errorRef = argValues[argExprIdx].mExpression;
if (errorRef == NULL)
errorRef = targetSrc;
{
if (mModule->PreFail())
{
BfAstNode* errorRef = argValues[argExprIdx].mExpression;
if (errorRef == NULL)
errorRef = targetSrc;
BfError* error;
if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
{
int checkIdx = argExprIdx - 1;
while (checkIdx >= 0)
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;
break;
if ((argValues[checkIdx].mArgFlags & BfArgFlag_StringInterpolateFormat) != 0)
{
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;
break;
}
@ -6488,8 +6506,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (showCtorError)
{
error = mModule->Fail(StrFormat("No parameterless constructor is available for base class. Consider calling base constructor '%s'.",
mModule->MethodToString(methodInstance).c_str()), refNode);
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 (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());
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;
}

View file

@ -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>();

View file

@ -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);

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()
{
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));
@ -2886,19 +2894,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)
{
BfError* bfError = mCompiler->mPassInstance->DeferFail(errorString, refNode);
if (bfError != NULL)
bfError->mIsWhileSpecializing = isWhileSpecializing;
return bfError;
}
// 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) || (deferError))
{
BfError* bfError = mCompiler->mPassInstance->DeferFail(errorString, refNode);
if (bfError != NULL)
bfError->mIsWhileSpecializing = isWhileSpecializing;
return bfError;
}
if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())))
@ -3720,7 +3728,7 @@ void BfModule::CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLo
mBfIRBuilder->GlobalVar_SetStorageKind(globalVar, storageKind);
BF_ASSERT(globalVar);
mStaticFieldRefs[fieldInstance] = globalVar;
mStaticFieldRefs[fieldInstance] = globalVar;
}
}
}
@ -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)
{
@ -10633,14 +10641,17 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
if (constant->mTypeCode == BfTypeCode_StringId)
{
if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) ||
((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
if (!allowStringId)
{
const StringImpl& str = mContext->mStringObjectIdMap[constant->mInt32].mString;
BfIRValue stringObjConst = GetStringObjectValue(str);
if (wantType->IsPointer())
return GetStringCharPtr(stringObjConst);
return stringObjConst;
if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) ||
((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
{
const StringImpl& str = mContext->mStringObjectIdMap[constant->mInt32].mString;
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);
@ -10836,8 +10847,25 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
if (mCurTypeInstance != NULL)
AddDependency(attrTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_CustomAttribute);
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);
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
@ -19764,7 +19796,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
}
else if (wantsRemoveBody)
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
// We don't want to hold on to pointers to LLVMFunctions of unspecialized types.
// This allows us to delete the mScratchModule LLVM module without rebuilding all

View file

@ -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);

View file

@ -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();
@ -1976,7 +1978,7 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
parser->SetSource(src.c_str(), src.mLength);
}
else
{
{
int idx = activeTypeDef->mEmitParser->AllocChars(src.mLength + 1);
memcpy((uint8*)activeTypeDef->mEmitParser->mSrc + idx, src.c_str(), src.mLength + 1);
activeTypeDef->mEmitParser->mSrcIdx = idx;
@ -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)
{
if (!typeInstance->mTypeDef->mHasCEOnCompile)
return;
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes)
{
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,13 +2106,37 @@ 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; });
auto onCompileAttribute = customAttributes->Get(mCompiler->mOnCompileAttributeTypeDef);
if (onCompileAttribute == NULL)
continue;
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes);
if (onCompileAttribute->mCtorArgs.size() < 1)
continue;
auto constant = typeInstance->mConstHolder->GetConstant(onCompileAttribute->mCtorArgs[0]);
@ -2061,8 +2157,7 @@ void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKin
continue;
}
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext);
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,19 +3117,17 @@ 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);
if (typeInstance->mCustomAttributes == NULL)
typeInstance->mCustomAttributes = new BfCustomAttributes();
GetCustomAttributes(typeInstance->mCustomAttributes, partialTypeDef->mTypeDeclaration->mAttributes, attrTarget);
}
}
else
{
typeInstance->mCustomAttributes = GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, attrTarget);
}
}
}
}
@ -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)
{
@ -3688,7 +3791,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (isUnion)
{
fieldInstance->mDataIdx = curFieldDataIdx;
}
}
}
}
@ -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)

View file

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

View file

@ -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()

View file

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

View file

@ -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());
@ -1753,7 +1774,7 @@ void BfPassInstance::TryFlushDeferredError()
if (moreInfo->mSource != NULL)
MessageAt(":error", " > " + moreInfo->mInfo, moreInfo->mSource, moreInfo->mSrcStart, moreInfo->mSrcEnd - moreInfo->mSrcStart);
else
OutputLine(":error" + moreInfo->mInfo);
OutputLine(":error " + moreInfo->mInfo);
}
}
}

View file

@ -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

View file

@ -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()
@ -585,14 +591,12 @@ public:
class CeStaticFieldInfo
{
public:
BfFieldInstance* mFieldInstance;
public:
addr_ce mAddr;
public:
CeStaticFieldInfo()
{
mFieldInstance = NULL;
mAddr = 0;
}
};
@ -617,70 +621,100 @@ 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:
Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
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;
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;
CeAppendAllocInfo* mAppendAllocInfo;
int mRevisionExecuteTime;
int mCurFunctionId;
int mExecuteId;
CeAppendAllocInfo* mAppendAllocInfo;
CeEmitContext* mCurEmitContext;
CeEvalFlags mCurEvalFlags;
CeContext* mCurContext;
CeEmitContext* mCurEmitContext;
CeBuilder* mCurBuilder;
CeFunction* mPreparingFunction;
CeFrame* mCurFrame;
BfAstNode* mCurTargetSrc;
BfMethodInstance* mCurMethodInstance;
BfModule* mCurModule;
BfType* mCurExpectingType;
CeFunction* mPreparingFunction;
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);
~CeMachine();
void Init();
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);
void RemoveMethod(BfMethodInstance* methodInstance);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext);
void PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder);
void MapFunctionId(CeFunction* ceFunction);
@ -688,17 +722,19 @@ public:
void CheckFunctions();
CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
public:
void CompileStarted();
void CompileDone();
void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
void QueueMethod(BfModuleMethodInstance moduleMethodInstance);
void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName);
void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName);
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);
};

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