1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Added comptype

This commit is contained in:
Brian Fiete 2021-01-15 14:28:21 -08:00
parent bb12a4ec20
commit 4890303508
27 changed files with 382 additions and 157 deletions

View file

@ -4947,7 +4947,7 @@ namespace IDE.ui
{ {
if (mHoverResolveTask == null) if (mHoverResolveTask == null)
{ {
if ((!handlingHoverResolveTask) && (!ResolveCompiler.mThreadWorkerHi.mThreadRunning)) if ((!handlingHoverResolveTask) && (!ResolveCompiler.mThreadWorkerHi.mThreadRunning) && (gApp.mSettings.mEditorSettings.mHiliteCursorReferences))
{ {
ResolveParams resolveParams = new .(); ResolveParams resolveParams = new .();
resolveParams.mOverrideCursorPos = (int32)textIdx; resolveParams.mOverrideCursorPos = (int32)textIdx;

View file

@ -1986,6 +1986,12 @@ void BeCOFFObject::Generate(BeModule* module)
{ {
auto globalVar = module->mGlobalVariables[globalVarIdx]; auto globalVar = module->mGlobalVariables[globalVarIdx];
if ((globalVar->mRefCount == 0) && (globalVar->mInitializer == NULL))
{
globalVarSyms.push_back(NULL);
continue;
}
BeMCSymbol* sym = mSymbols.Alloc(); BeMCSymbol* sym = mSymbols.Alloc();
sym->mType = globalVar->mType; sym->mType = globalVar->mType;
sym->mName = globalVar->mName; sym->mName = globalVar->mName;
@ -2001,6 +2007,10 @@ void BeCOFFObject::Generate(BeModule* module)
for (int globalVarIdx = 0; globalVarIdx < (int)module->mGlobalVariables.size(); globalVarIdx++) for (int globalVarIdx = 0; globalVarIdx < (int)module->mGlobalVariables.size(); globalVarIdx++)
{ {
auto globalVar = module->mGlobalVariables[globalVarIdx]; auto globalVar = module->mGlobalVariables[globalVarIdx];
if ((globalVar->mRefCount == 0) && (globalVar->mInitializer == NULL))
continue;
auto sym = globalVarSyms[globalVarIdx]; auto sym = globalVarSyms[globalVarIdx];
if (globalVar->mInitializer != NULL) if (globalVar->mInitializer != NULL)

View file

@ -710,6 +710,7 @@ void BeIRCodeGen::Read(BeValue*& beValue)
} }
else else
beValue = GetBeValue(streamId); beValue = GetBeValue(streamId);
beValue->mRefCount++;
BE_MEM_END("ParamType_Const_GlobalVar"); BE_MEM_END("ParamType_Const_GlobalVar");
return; return;
} }

View file

@ -291,7 +291,7 @@ void BfStructuralVisitor::Visit(BfDelegateTypeRef* typeRef)
Visit(typeRef->ToBase()); Visit(typeRef->ToBase());
} }
void BfStructuralVisitor::Visit(BfDeclTypeRef* declTypeRef) void BfStructuralVisitor::Visit(BfExprModTypeRef* declTypeRef)
{ {
Visit(declTypeRef->ToBase()); Visit(declTypeRef->ToBase());
} }
@ -1307,6 +1307,8 @@ const char* Beefy::BfTokenToString(BfToken token)
return "checked"; return "checked";
case BfToken_Class: case BfToken_Class:
return "class"; return "class";
case BfToken_Comptype:
return "comptype";
case BfToken_Concrete: case BfToken_Concrete:
return "concrete"; return "concrete";
case BfToken_Const: case BfToken_Const:

View file

@ -122,6 +122,7 @@ enum BfToken : uint8
BfToken_Catch, BfToken_Catch,
BfToken_Checked, BfToken_Checked,
BfToken_Class, BfToken_Class,
BfToken_Comptype,
BfToken_Concrete, BfToken_Concrete,
BfToken_Const, BfToken_Const,
BfToken_Continue, BfToken_Continue,
@ -308,7 +309,7 @@ class BfLetTypeReference;
class BfGenericInstanceTypeRef; class BfGenericInstanceTypeRef;
class BfTupleTypeRef; class BfTupleTypeRef;
class BfDelegateTypeRef; class BfDelegateTypeRef;
class BfDeclTypeRef; class BfExprModTypeRef;
class BfCommentNode; class BfCommentNode;
class BfIfStatement; class BfIfStatement;
class BfParenthesizedExpression; class BfParenthesizedExpression;
@ -473,8 +474,8 @@ public:
virtual void Visit(BfArrayTypeRef* typeRef); virtual void Visit(BfArrayTypeRef* typeRef);
virtual void Visit(BfGenericInstanceTypeRef* typeRef); virtual void Visit(BfGenericInstanceTypeRef* typeRef);
virtual void Visit(BfTupleTypeRef* typeRef); virtual void Visit(BfTupleTypeRef* typeRef);
virtual void Visit(BfDelegateTypeRef* typeRef); virtual void Visit(BfDelegateTypeRef* typeRef);
virtual void Visit(BfDeclTypeRef* declTypeRef); virtual void Visit(BfExprModTypeRef* declTypeRef);
virtual void Visit(BfPointerTypeRef* typeRef); virtual void Visit(BfPointerTypeRef* typeRef);
virtual void Visit(BfNullableTypeRef* typeRef); virtual void Visit(BfNullableTypeRef* typeRef);
virtual void Visit(BfVariableDeclaration* varDecl); virtual void Visit(BfVariableDeclaration* varDecl);
@ -2543,16 +2544,16 @@ public:
BfAstNode* mCloseParen; BfAstNode* mCloseParen;
}; BF_AST_DECL(BfDelegateTypeRef, BfTypeReference); }; BF_AST_DECL(BfDelegateTypeRef, BfTypeReference);
class BfDeclTypeRef : public BfTypeReference class BfExprModTypeRef : public BfTypeReference
{ {
public: public:
BF_AST_TYPE(BfDeclTypeRef, BfTypeReference); BF_AST_TYPE(BfExprModTypeRef, BfTypeReference);
BfTokenNode* mToken; BfTokenNode* mToken;
BfTokenNode* mOpenParen; BfTokenNode* mOpenParen;
BfExpression* mTarget; BfExpression* mTarget;
BfTokenNode* mCloseParen; BfTokenNode* mCloseParen;
}; BF_AST_DECL(BfDeclTypeRef, BfTypeReference); }; BF_AST_DECL(BfExprModTypeRef, BfTypeReference);
enum BfGenericParamKind enum BfGenericParamKind
{ {

View file

@ -1708,6 +1708,8 @@ bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken
// Statics, inner types // Statics, inner types
auto checkType = targetValue.mType; auto checkType = targetValue.mType;
if (checkType->IsConcreteInterfaceType())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam()) if (checkType->IsGenericParam())
{ {

View file

@ -7296,7 +7296,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
if ((mCEMachine != NULL) && (!mIsResolveOnly) && (mCEMachine->mRevisionExecuteTime > 0)) if ((mCEMachine != NULL) && (!mIsResolveOnly) && (mCEMachine->mRevisionExecuteTime > 0))
{ {
mPassInstance->OutputLine(StrFormat(":med Const evaluation time: %0.2fs", mCEMachine->mRevisionExecuteTime / 1000.0f)); mPassInstance->OutputLine(StrFormat(":med Comptime execution time: %0.2fs", mCEMachine->mRevisionExecuteTime / 1000.0f));
} }
BpLeave(); BpLeave();

View file

@ -103,7 +103,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
wantIgnoreWrites = true; wantIgnoreWrites = true;
} }
SetAndRestoreValue<bool> ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, wantIgnoreWrites); SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, wantIgnoreWrites);
auto prevInsertBlock = mModule->mBfIRBuilder->GetInsertBlock(); auto prevInsertBlock = mModule->mBfIRBuilder->GetInsertBlock();
@ -139,7 +139,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
{ {
if ((flags & BfConstResolveFlag_RemapFromStringId) != 0) if ((flags & BfConstResolveFlag_RemapFromStringId) != 0)
{ {
ignoreWrites.Restore(); prevIgnoreWrites.Restore();
mModule->mBfIRBuilder->PopulateType(mResult.mType); mModule->mBfIRBuilder->PopulateType(mResult.mType);
return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType); return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType);
} }
@ -203,7 +203,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
{ {
auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue); auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue);
if ((constant->mConstType == BfConstType_GlobalVar) && ((mBfEvalExprFlags & BfConstResolveFlag_AllowGlobalVariable) != 0)) if ((constant->mConstType == BfConstType_GlobalVar) && ((mBfEvalExprFlags & BfConstResolveFlag_AllowGlobalVariable) != 0))
isConst = false; isConst = false;
} }
if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0)) if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0))
@ -232,6 +232,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
}*/ }*/
mModule->FixIntUnknown(mResult); mModule->FixIntUnknown(mResult);
mModule->FixValueActualization(mResult);
return mResult; return mResult;
} }

View file

@ -44,6 +44,7 @@ BfContext::BfContext(BfCompiler* compiler) :
mMappedObjectRevision = 0; mMappedObjectRevision = 0;
mDeleting = false; mDeleting = false;
mLockModules = false; mLockModules = false;
mAllowLockYield = true;
mCurTypeState = NULL; mCurTypeState = NULL;
mCurConstraintState = NULL; mCurConstraintState = NULL;
@ -255,9 +256,15 @@ void BfContext::EnsureHotMangledVirtualMethodNames()
} }
} }
void BfContext::CheckLockYield()
{
if (mAllowLockYield)
mSystem->CheckLockYield();
}
bool BfContext::IsCancellingAndYield() bool BfContext::IsCancellingAndYield()
{ {
mSystem->CheckLockYield(); CheckLockYield();
return mCompiler->mCanceling; return mCompiler->mCanceling;
} }

View file

@ -309,6 +309,8 @@ public:
BfType* mLeftType; BfType* mLeftType;
BfType* mRightType; BfType* mRightType;
BfConstraintState* mPrevState; BfConstraintState* mPrevState;
BfMethodInstance* mMethodInstance;
BfTypeVector* mMethodGenericArgsOverride;
public: public:
BfConstraintState() BfConstraintState()
@ -316,6 +318,8 @@ public:
mGenericParamInstance = NULL; mGenericParamInstance = NULL;
mLeftType = NULL; mLeftType = NULL;
mRightType = NULL; mRightType = NULL;
mMethodInstance = NULL;
mMethodGenericArgsOverride = NULL;
mPrevState = NULL; mPrevState = NULL;
} }
@ -343,6 +347,7 @@ public:
BfSystem* mSystem; BfSystem* mSystem;
BfCompiler* mCompiler; BfCompiler* mCompiler;
bool mAllowLockYield;
bool mLockModules; bool mLockModules;
BfModule* mScratchModule; BfModule* mScratchModule;
BfModule* mUnreifiedModule; BfModule* mUnreifiedModule;
@ -433,6 +438,7 @@ public:
void ReportMemory(MemReporter* memReporter); void ReportMemory(MemReporter* memReporter);
void ProcessMethod(BfMethodInstance* methodInstance); void ProcessMethod(BfMethodInstance* methodInstance);
int GetStringLiteralId(const StringImpl& str); int GetStringLiteralId(const StringImpl& str);
void CheckLockYield();
bool IsCancellingAndYield(); bool IsCancellingAndYield();
void QueueFinishModule(BfModule * module); void QueueFinishModule(BfModule * module);
void CancelWorkItems(); void CancelWorkItems();

View file

@ -414,7 +414,7 @@ void BfElementVisitor::Visit(BfTupleTypeRef* typeRef)
VisitChild(typeRef->mCloseParen); VisitChild(typeRef->mCloseParen);
} }
void BfElementVisitor::Visit(BfDeclTypeRef* typeRef) void BfElementVisitor::Visit(BfExprModTypeRef* typeRef)
{ {
Visit(typeRef->ToBase()); Visit(typeRef->ToBase());

View file

@ -61,7 +61,7 @@ public:
virtual void Visit(BfArrayTypeRef* typeRef); virtual void Visit(BfArrayTypeRef* typeRef);
virtual void Visit(BfGenericInstanceTypeRef* typeRef); virtual void Visit(BfGenericInstanceTypeRef* typeRef);
virtual void Visit(BfTupleTypeRef* typeRef); virtual void Visit(BfTupleTypeRef* typeRef);
virtual void Visit(BfDeclTypeRef* typeRef); virtual void Visit(BfExprModTypeRef* typeRef);
virtual void Visit(BfDelegateTypeRef* typeRef); virtual void Visit(BfDelegateTypeRef* typeRef);
virtual void Visit(BfPointerTypeRef* typeRef); virtual void Visit(BfPointerTypeRef* typeRef);
virtual void Visit(BfNullableTypeRef* typeRef); virtual void Visit(BfNullableTypeRef* typeRef);

View file

@ -588,54 +588,41 @@ bool BfGenericInferContext::InferGenericArgument(BfMethodInstance* methodInstanc
return true; return true;
} }
bool BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance, int srcGenericIdx)
{
auto& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx];
if (srcGenericArg == NULL)
return false;
int startInferCount = mInferredCount;
auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx];
for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
{
if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
{
InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue());
auto typeInstance = srcGenericArg->ToTypeInstance();
if (typeInstance != NULL)
{
for (auto ifaceEntry : typeInstance->mInterfaces)
InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
}
}
}
return mInferredCount != startInferCount;
}
void BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance) void BfGenericInferContext::InferGenericArguments(BfMethodInstance* methodInstance)
{ {
// Attempt to infer from other generic args // Attempt to infer from other generic args
for (int srcGenericIdx = 0; srcGenericIdx < (int)mCheckMethodGenericArguments->size(); srcGenericIdx++) for (int srcGenericIdx = 0; srcGenericIdx < (int)mCheckMethodGenericArguments->size(); srcGenericIdx++)
{ {
auto& srcGenericArg = (*mCheckMethodGenericArguments)[srcGenericIdx]; InferGenericArguments(methodInstance, srcGenericIdx);
if (srcGenericArg == NULL)
continue;
auto srcGenericParam = methodInstance->mMethodInfoEx->mGenericParams[srcGenericIdx];
for (auto ifaceConstraint : srcGenericParam->mInterfaceConstraints)
{
if ((ifaceConstraint->IsUnspecializedTypeVariation()) && (ifaceConstraint->IsGenericTypeInstance()))
{
InferGenericArgument(methodInstance, srcGenericArg, ifaceConstraint, BfIRValue());
auto typeInstance = srcGenericArg->ToTypeInstance();
if (typeInstance != NULL)
{
for (auto ifaceEntry : typeInstance->mInterfaces)
InferGenericArgument(methodInstance, ifaceEntry.mInterfaceType, ifaceConstraint, BfIRValue());
}
}
}
} }
} }
// void BfGenericInferContext::PropogateInference(BfType* resolvedType, BfType* unresovledType)
// {
// if (!unresovledType->IsUnspecializedTypeVariation())
// return;
//
// auto resolvedTypeInstance = resolvedType->ToTypeInstance();
// auto unresolvedTypeInstance = unresovledType->ToTypeInstance();
//
// if ((resolvedTypeInstance == NULL) || (unresolvedTypeInstance == NULL))
// return;
// if (resolvedTypeInstance->mTypeDef != unresolvedTypeInstance->mTypeDef)
// return;
//
// if (unres)
//
// if (resolvedType->IsGenericTypeInstance())
// {
//
//
// }
// }
int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs) int BfMethodMatcher::GetMostSpecificType(BfType* lhs, BfType* rhs)
{ {
if ((lhs->IsRef()) && (rhs->IsRef())) if ((lhs->IsRef()) && (rhs->IsRef()))
@ -1440,10 +1427,10 @@ bool BfMethodMatcher::WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInst
return true; return true;
} }
bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs) bool BfMethodMatcher::InferFromGenericConstraints(BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs)
{ {
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals) == 0) // if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Equals) == 0)
return false; // return false;
if (!genericParamInst->mExternType->IsGenericParam()) if (!genericParamInst->mExternType->IsGenericParam())
return false; return false;
@ -1490,6 +1477,9 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
if (checkOpConstraint.mBinaryOp != BfBinaryOp_None) if (checkOpConstraint.mBinaryOp != BfBinaryOp_None)
{ {
if ((leftType == NULL) || (rightType == NULL))
continue;
BfExprEvaluator exprEvaluator(mModule); BfExprEvaluator exprEvaluator(mModule);
BfTypedValue leftValue(mModule->mBfIRBuilder->GetFakeVal(), leftType); BfTypedValue leftValue(mModule->mBfIRBuilder->GetFakeVal(), leftType);
@ -1507,6 +1497,9 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
} }
else else
{ {
if (rightType == NULL)
continue;
BfTypedValue rightValue(mModule->mBfIRBuilder->GetFakeVal(), rightType); BfTypedValue rightValue(mModule->mBfIRBuilder->GetFakeVal(), rightType);
StringT<128> failedOpName; StringT<128> failedOpName;
@ -1537,6 +1530,28 @@ bool BfMethodMatcher::InferFromGenericConstraints(BfGenericParamInstance* generi
} }
} }
if ((checkArgType == NULL) && ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_ComptypeExpr) != 0))
{
for (auto comptypeConstraint : genericParamInst->mComptypeConstraint)
{
BfConstraintState constraintSet;
constraintSet.mPrevState = mModule->mContext->mCurConstraintState;
constraintSet.mGenericParamInstance = genericParamInst;
constraintSet.mMethodInstance = methodInstance;
constraintSet.mMethodGenericArgsOverride = methodGenericArgs;
SetAndRestoreValue<BfConstraintState*> prevConstraintSet(mModule->mContext->mCurConstraintState, &constraintSet);
if (!mModule->CheckConstraintState(NULL))
return false;
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mModule->mCurMethodInstance, methodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mModule->mCurTypeInstance, methodInstance->GetOwner());
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
checkArgType = mModule->ResolveTypeRef(comptypeConstraint);
}
}
if (checkArgType == NULL) if (checkArgType == NULL)
return false; return false;
if (checkArgType->IsVar()) if (checkArgType->IsVar())
@ -1857,23 +1872,55 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
} }
paramIdx++; paramIdx++;
}
}
//
for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++)
{
auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
if (genericArg == NULL)
{
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx];
InferFromGenericConstraints(genericParam, &mCheckMethodGenericArguments);
if (genericArg != NULL)
continue;
if (!allowEmptyGenericSet.Contains(genericArgIdx))
goto NoMatch;
} }
} }
// while (true)
// {
//
// }
//
bool failed = false;
bool inferredAllGenericArguments = false;
for (int pass = 0; true; pass++)
{
bool madeProgress = false;
bool hasUninferred = false;
failed = false;
for (int genericArgIdx = uniqueGenericStartIdx; genericArgIdx < (int)checkMethod->mGenericParams.size(); genericArgIdx++)
{
auto& genericArg = mCheckMethodGenericArguments[genericArgIdx];
if (genericArg == NULL)
{
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericArgIdx];
InferFromGenericConstraints(methodInstance, genericParam, &mCheckMethodGenericArguments);
if (genericArg != NULL)
{
if (inferredAllGenericArguments)
genericInferContext.InferGenericArguments(methodInstance, genericArgIdx);
madeProgress = true;
}
hasUninferred = true;
if (!allowEmptyGenericSet.Contains(genericArgIdx))
failed = true;
}
}
if (!hasUninferred)
break;
if (inferredAllGenericArguments)
{
if (!madeProgress)
break;
}
genericInferContext.InferGenericArguments(methodInstance);
inferredAllGenericArguments = true;
}
if (failed)
goto NoMatch;
} }
if (checkMethod->mMethodType == BfMethodType_Extension) if (checkMethod->mMethodType == BfMethodType_Extension)
@ -2538,7 +2585,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
if ((mModule->mCompiler->IsAutocomplete()) || (mModule->mContext->mResolvingVarField)) if ((mModule->mCompiler->IsAutocomplete()) || (mModule->mContext->mResolvingVarField))
return; return;
if (mModule->mBfIRBuilder->mIgnoreWrites) if ((mModule->mBfIRBuilder->mIgnoreWrites) && (!mBestMethodDef->mIsConcrete))
return; return;
if (mBestMethodTypeInstance->IsInterface()) if (mBestMethodTypeInstance->IsInterface())
@ -5169,6 +5216,17 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
auto _GetDefaultReturnValue = [&]() auto _GetDefaultReturnValue = [&]()
{ {
if (methodInstance->mVirtualTableIdx == -1)
{
if (methodInstance->GetOwner()->IsInterface())
{
// We're attempting to directly invoke a non-virtual interface method, if we're return an interface then
// it is a concrete interface
if (returnType->IsInterface())
returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance());
}
}
if ((returnType->IsVar()) && (mExpectingType != NULL)) if ((returnType->IsVar()) && (mExpectingType != NULL))
returnType = mExpectingType; returnType = mExpectingType;
if (returnType->IsRef()) if (returnType->IsRef())
@ -5241,19 +5299,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (wantQuickEval) if (wantQuickEval)
{ {
// In an autocomplete pass we may have stale method references that need to be resolved // In an autocomplete pass we may have stale method references that need to be resolved
// in the full classify pass, and in the full classify pass while just refreshing internals, we // in the full classify pass, and in the full classify pass while just refreshing internals, we
// may have NULL funcs temporarily. We simply skip generating the method call here. // may have NULL funcs temporarily. We simply skip generating the method call here.
if (methodInstance->mVirtualTableIdx == -1)
{
if (methodInstance->GetOwner()->IsInterface())
{
// We're attempting to directly invoke a non-virtual interface method, if we're return an interface then
// it is a concrete interface
if (returnType->IsInterface())
returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance());
}
}
if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
{ {
if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
@ -5348,6 +5395,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
} }
else else
{ {
if (returnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
{
if (mExpectingType->IsUndefSizedArray())
{
if (returnType->GetUnderlyingType() == mExpectingType->GetUnderlyingType())
return mModule->GetDefaultTypedValue(mExpectingType, true, BfDefaultValueKind_Undef);
}
}
return mModule->GetDefaultTypedValue(returnType, true, BfDefaultValueKind_Undef); return mModule->GetDefaultTypedValue(returnType, true, BfDefaultValueKind_Undef);
} }
@ -6148,7 +6204,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (!mModule->mCompiler->mIsResolveOnly) if (!mModule->mCompiler->mIsResolveOnly)
sCallIdx++; sCallIdx++;
int callIdx = sCallIdx; int callIdx = sCallIdx;
if (callIdx == 1177) if (callIdx == 0x000020F9)
{ {
NOP; NOP;
} }
@ -7594,8 +7650,7 @@ bool BfExprEvaluator::CheckGenericCtor(BfGenericParamType* genericParamType, BfR
{ {
mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc); mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false; success = false;
} }
return success; return success;
} }
@ -7618,9 +7673,12 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
BF_ASSERT(!mFunctionBindResult->mOrigTarget); BF_ASSERT(!mFunctionBindResult->mOrigTarget);
mFunctionBindResult->mOrigTarget = origTarget; mFunctionBindResult->mOrigTarget = origTarget;
} }
if (target) if (target)
{ {
if (target.mType->IsConcreteInterfaceType())
target.mType = target.mType->GetUnderlyingType();
// Turn T* into a T, if we can // Turn T* into a T, if we can
if ((target.mType->IsPointer()) && (target.mType->GetUnderlyingType()->IsGenericParam())) if ((target.mType->IsPointer()) && (target.mType->GetUnderlyingType()->IsGenericParam()))
{ {
@ -9790,7 +9848,6 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr)
} }
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mResult = BfTypedValue(mModule->CreateTypeDataRef(type), typeType); mResult = BfTypedValue(mModule->CreateTypeDataRef(type), typeType);
} }
@ -15580,6 +15637,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
} }
} }
} }
else if (expectingType->IsVar())
{
// Silently allow
gaveUnqualifiedDotError = true;
}
else else
{ {
gaveUnqualifiedDotError = true; gaveUnqualifiedDotError = true;

View file

@ -142,6 +142,7 @@ public:
{ {
return (int)mCheckMethodGenericArguments->size() - mInferredCount; return (int)mCheckMethodGenericArguments->size() - mInferredCount;
} }
bool InferGenericArguments(BfMethodInstance* methodInstance, int srcGenericIdx);
void InferGenericArguments(BfMethodInstance* methodInstance); void InferGenericArguments(BfMethodInstance* methodInstance);
}; };
@ -212,7 +213,7 @@ public:
public: public:
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute, BfType *origCheckType = NULL, BfResolveArgFlags flags = BfResolveArgFlag_None); BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute, BfType *origCheckType = NULL, BfResolveArgFlags flags = BfResolveArgFlag_None);
bool InferFromGenericConstraints(BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs); bool InferFromGenericConstraints(BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs);
void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute, void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute,
BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute, BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute,
bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail); bool* outNewIsBetter, bool* outNewIsWorse, bool allowSpecializeFail);

View file

@ -3962,7 +3962,7 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance*
BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfFieldDef* field) BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfFieldDef* field)
{ {
bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact<BfDeclTypeRef>(field->mFieldDeclaration->mTypeRef) != NULL; bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact<BfExprModTypeRef>(field->mFieldDeclaration->mTypeRef) != NULL;
auto fieldType = fieldInstance->GetResolvedType(); auto fieldType = fieldInstance->GetResolvedType();
if ((field->mIsConst) && (!isDeclType)) if ((field->mIsConst) && (!isDeclType))
@ -7280,9 +7280,16 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
else else
{ {
bool checkEquality = false; bool checkEquality = false;
if (constraintType->IsPrimitiveType()) if (constraintType->IsVar())
{ {
// From a `comptype` generic undef resolution. Ignore.
genericParamInstance->mGenericParamFlags |= BfGenericParamFlag_ComptypeExpr;
genericParamInstance->mComptypeConstraint.Add(constraintTypeRef);
continue;
}
else if (constraintType->IsPrimitiveType())
{
if (isUnspecialized) if (isUnspecialized)
{ {
Fail("Primitive constraints are not allowed unless preceded with 'const'", constraintTypeRef); Fail("Primitive constraints are not allowed unless preceded with 'const'", constraintTypeRef);
@ -7336,7 +7343,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
{ {
auto constraintTypeInst = constraintType->ToTypeInstance(); auto constraintTypeInst = constraintType->ToTypeInstance();
if (genericParamInstance->mTypeConstraint != NULL) if (genericParamInstance->mTypeConstraint != NULL)
{ {
if ((constraintTypeInst != NULL) && (TypeIsSubTypeOf(constraintTypeInst, genericParamInstance->mTypeConstraint->ToTypeInstance(), false))) if ((constraintTypeInst != NULL) && (TypeIsSubTypeOf(constraintTypeInst, genericParamInstance->mTypeConstraint->ToTypeInstance(), false)))
{ {
// Allow more specific type // Allow more specific type
@ -8079,6 +8086,8 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator,
if ((flags & BfEvalExprFlags_AllowIntUnknown) == 0) if ((flags & BfEvalExprFlags_AllowIntUnknown) == 0)
FixIntUnknown(typedVal); FixIntUnknown(typedVal);
if (!mBfIRBuilder->mIgnoreWrites)
FixValueActualization(typedVal);
exprEvaluator.CheckResultForReading(typedVal); exprEvaluator.CheckResultForReading(typedVal);
if ((wantTypeRef == NULL) || (!wantTypeRef->IsRef())) if ((wantTypeRef == NULL) || (!wantTypeRef->IsRef()))
@ -8098,7 +8107,7 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator,
if (!allowRef) if (!allowRef)
typedVal = RemoveRef(typedVal); typedVal = RemoveRef(typedVal);
} }
} }
if ((!typedVal.mType->IsComposite()) && (!typedVal.mType->IsGenericParam())) // Load non-structs by default if ((!typedVal.mType->IsComposite()) && (!typedVal.mType->IsGenericParam())) // Load non-structs by default
{ {
@ -8115,7 +8124,7 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator,
if (outOrigType != NULL) if (outOrigType != NULL)
*outOrigType = typedVal.mType; *outOrigType = typedVal.mType;
if ((flags & BfEvalExprFlags_NoCast) == 0) if (((flags & BfEvalExprFlags_NoCast) == 0) && (!wantTypeRef->IsVar()))
{ {
BfCastFlags castFlags = ((flags & BfEvalExprFlags_ExplicitCast) != 0) ? BfCastFlags_Explicit : BfCastFlags_None; BfCastFlags castFlags = ((flags & BfEvalExprFlags_ExplicitCast) != 0) ? BfCastFlags_Explicit : BfCastFlags_None;
if ((flags & BfEvalExprFlags_FieldInitializer) != 0) if ((flags & BfEvalExprFlags_FieldInitializer) != 0)
@ -8125,9 +8134,6 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator,
return typedVal; return typedVal;
} }
//WTF- why did we have this?
/*if ((flags & BfEvalExprFlags_ExplicitCast) == 0)
typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference);*/
if (exprEvaluator.mIsVolatileReference) if (exprEvaluator.mIsVolatileReference)
typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference); typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference);
} }
@ -13252,9 +13258,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
// if ((flags & BfGetMethodInstanceFlag_NoReference) != 0) // if ((flags & BfGetMethodInstanceFlag_NoReference) != 0)
// addToWorkList = false; // addToWorkList = false;
declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList); declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList);
if (processNow) if (processNow)
{ {
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL); SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
@ -13805,6 +13811,16 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli
isByAddr = true; isByAddr = true;
} }
if (diValue.IsConst())
{
auto constant = mBfIRBuilder->GetConstant(diValue);
if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData))
{
// Ignore for now
return;
}
}
auto diType = mBfIRBuilder->DbgGetType(localVarDef->mResolvedType); auto diType = mBfIRBuilder->DbgGetType(localVarDef->mResolvedType);
bool didConstToMem = false; bool didConstToMem = false;
@ -13882,7 +13898,7 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli
if (isByAddr) if (isByAddr)
localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertDeclare(diValue, diVariable, declareBefore); localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertDeclare(diValue, diVariable, declareBefore);
else if (diValue) else if (diValue)
{ {
localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(diValue, diVariable); localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(diValue, diVariable);
} }
else if (mCompiler->mOptions.mToolsetType != BfToolsetType_GNU) // DWARF chokes on this: else if (mCompiler->mOptions.mToolsetType != BfToolsetType_GNU) // DWARF chokes on this:
@ -17390,7 +17406,7 @@ void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx)
} }
delete deferredLocalMethod; delete deferredLocalMethod;
mSystem->CheckLockYield(); mContext->CheckLockYield();
} }
} }
@ -17455,7 +17471,7 @@ void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx)
} }
} }
mSystem->CheckLockYield(); mContext->CheckLockYield();
} }
} }
@ -21169,7 +21185,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
// We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here // We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here
// to effectively make mIgnoreWrites method-scoped // to effectively make mIgnoreWrites method-scoped
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized || mCurTypeInstance->mResolvingVarField); SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized || mCurTypeInstance->mResolvingVarField);
SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo; SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
SetAndRestoreValue<bool> prevAllowLockYield(mContext->mAllowLockYield, false);
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL); SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
if (mCompiler->IsAutocomplete()) if (mCompiler->IsAutocomplete())
prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false); prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false);
@ -21314,28 +21331,18 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
else else
{ {
auto externConstraintDef = genericParam->GetExternConstraintDef(); auto externConstraintDef = genericParam->GetExternConstraintDef();
// if (unspecializedTypeInstance == NULL)
// unspecializedTypeInstance = GetUnspecializedTypeInstance(mCurTypeInstance);
//
// // Resolve in the unspecialized type, then resolve the generic later. This fixes ambiguity where the type is specialized by a method generic arg
// {
// SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, unspecializedTypeInstance);
// genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
// }
genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef); genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
auto autoComplete = mCompiler->GetAutoComplete(); auto autoComplete = mCompiler->GetAutoComplete();
if (autoComplete != NULL) if (autoComplete != NULL)
autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false); autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false);
if (genericParam->mExternType != NULL) if (genericParam->mExternType != NULL)
{ {
// //
} }
else else
genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
} }
ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized); ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized);
@ -21486,7 +21493,8 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric); BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric);
if (((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) && (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>())) if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod))
&& (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
resolvedReturnType = GetPrimitiveType(BfTypeCode_Var); resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
else else
resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags); resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags);

View file

@ -1762,6 +1762,7 @@ public:
BfType* FixIntUnknown(BfType* type); BfType* FixIntUnknown(BfType* type);
void FixIntUnknown(BfTypedValue& typedVal, BfType* matchType = NULL); void FixIntUnknown(BfTypedValue& typedVal, BfType* matchType = NULL);
void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs); void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs);
void FixValueActualization(BfTypedValue& typedVal);
bool TypeEquals(BfTypedValue& val, BfType* type); bool TypeEquals(BfTypedValue& val, BfType* type);
BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef, BfType** outType = NULL, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef, BfType** outType = NULL, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);

View file

@ -3515,7 +3515,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
fieldInstance->mIsEnumPayloadCase = true; fieldInstance->mIsEnumPayloadCase = true;
} }
} }
else if ((field->mTypeRef != NULL) && ((field->mTypeRef->IsExact<BfVarTypeReference>()) || (field->mTypeRef->IsExact<BfLetTypeReference>()) || (field->mTypeRef->IsExact<BfDeclTypeRef>()))) else if ((field->mTypeRef != NULL) && ((field->mTypeRef->IsExact<BfVarTypeReference>()) || (field->mTypeRef->IsExact<BfLetTypeReference>()) || (field->mTypeRef->IsExact<BfExprModTypeRef>())))
{ {
resolvedFieldType = GetPrimitiveType(BfTypeCode_Var); resolvedFieldType = GetPrimitiveType(BfTypeCode_Var);
@ -5153,7 +5153,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField)) if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField))
{ {
disableYield.Release(); disableYield.Release();
mSystem->CheckLockYield(); mContext->CheckLockYield();
disableYield.Acquire(); disableYield.Acquire();
} }
} }
@ -6258,6 +6258,21 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
FixIntUnknown(rhs); FixIntUnknown(rhs);
} }
void BfModule::FixValueActualization(BfTypedValue& typedVal)
{
if (!typedVal.mValue.IsConst())
return;
if (mBfIRBuilder->mIgnoreWrites)
return;
auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
if (constant->mConstType == BfConstType_TypeOf)
{
auto constTypeOf = (BfTypeOf_Const*)constant;
AddDependency(constTypeOf->mType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
typedVal.mValue = CreateTypeDataRef(constTypeOf->mType);
}
}
BfTypeInstance* BfModule::GetPrimitiveStructType(BfTypeCode typeCode) BfTypeInstance* BfModule::GetPrimitiveStructType(BfTypeCode typeCode)
{ {
BfTypeInstance* typeInst = NULL; BfTypeInstance* typeInst = NULL;
@ -7858,7 +7873,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
{ {
baseNode = qualifiedNameNode->mRight; baseNode = qualifiedNameNode->mRight;
} }
else if (auto declTypeRef = BfNodeDynCast<BfDeclTypeRef>(baseNode)) else if (auto declTypeRef = BfNodeDynCast<BfExprModTypeRef>(baseNode))
{ {
baseNode = NULL; baseNode = NULL;
break; break;
@ -8868,6 +8883,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
return GetGenericParamType(BfGenericParamKind_Method, genericParamIdx); return GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
else else
{ {
if ((mContext->mCurConstraintState != NULL) && (mContext->mCurConstraintState->mMethodInstance == checkMethodInstance) &&
(mContext->mCurConstraintState->mMethodGenericArgsOverride != NULL))
{
return ResolveTypeResult(typeRef, (*mContext->mCurConstraintState->mMethodGenericArgsOverride)[genericParamIdx], populateType, resolveFlags);
}
SetAndRestoreValue<BfGetSymbolReferenceKind> prevSymbolRefKind; SetAndRestoreValue<BfGetSymbolReferenceKind> prevSymbolRefKind;
if (mCompiler->mResolvePassData != NULL) // Don't add these typeRefs, they are indirect if (mCompiler->mResolvePassData != NULL) // Don't add these typeRefs, they are indirect
prevSymbolRefKind.Init(mCompiler->mResolvePassData->mGetSymbolReferenceKind, BfGetSymbolReferenceKind_None); prevSymbolRefKind.Init(mCompiler->mResolvePassData->mGetSymbolReferenceKind, BfGetSymbolReferenceKind_None);
@ -9334,10 +9355,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
lookupCtx.mRootTypeDef = typeDef; lookupCtx.mRootTypeDef = typeDef;
lookupCtx.mModule = this; lookupCtx.mModule = this;
BfResolvedTypeSet::Entry* resolvedEntry = NULL; BfResolvedTypeSet::Entry* resolvedEntry = NULL;
auto inserted = mContext->mResolvedTypes.Insert(typeRef, &lookupCtx, &resolvedEntry); auto inserted = mContext->mResolvedTypes.Insert(typeRef, &lookupCtx, &resolvedEntry);
if (resolvedEntry == NULL) if (resolvedEntry == NULL)
{ {
if (lookupCtx.mHadVar)
return ResolveTypeResult(typeRef, GetPrimitiveType(BfTypeCode_Var), populateType, resolveFlags);
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
} }
@ -9620,7 +9643,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
for (auto genericArgRef : genericArguments) for (auto genericArgRef : genericArguments)
{ {
auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue)); auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue));
if (genericArg == NULL) if ((genericArg == NULL) || (genericArg->IsVar()))
{ {
mContext->mResolvedTypes.RemoveEntry(resolvedEntry); mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);

View file

@ -2889,6 +2889,10 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
if (SrcPtrHasToken("class")) if (SrcPtrHasToken("class"))
mToken = BfToken_Class; mToken = BfToken_Class;
break; break;
case TOKEN_HASH('c', 'o', 'm', 'p'):
if ((!mCompatMode) && (SrcPtrHasToken("comptype")))
mToken = BfToken_Comptype;
break;
case TOKEN_HASH('c', 'o', 'n', 'c'): case TOKEN_HASH('c', 'o', 'n', 'c'):
if ((!mCompatMode) && (SrcPtrHasToken("concrete"))) if ((!mCompatMode) && (SrcPtrHasToken("concrete")))
mToken = BfToken_Concrete; mToken = BfToken_Concrete;

View file

@ -270,7 +270,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
{ {
// Tuple start // Tuple start
} }
else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) else if ((checkToken == BfToken_Comptype) || (checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable))
{ {
// Decltype start // Decltype start
} }
@ -777,7 +777,7 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
checkIdx = funcEndNode; checkIdx = funcEndNode;
continue; continue;
} }
else if ((checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable)) else if ((checkToken == BfToken_Comptype) || (checkToken == BfToken_Decltype) || (checkToken == BfToken_AllocType) || (checkToken == BfToken_RetType) || (checkToken == BfToken_Nullable))
{ {
int endNodeIdx = checkIdx + 1; int endNodeIdx = checkIdx + 1;
@ -2231,7 +2231,7 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
} }
} }
} }
else if (tokenNode->GetToken() == BfToken_Decltype) else if ((tokenNode->GetToken() == BfToken_Comptype) || (tokenNode->GetToken() == BfToken_Decltype))
{ {
auto typeRef = CreateTypeRef(tokenNode, CreateTypeRefFlags_EarlyExit); auto typeRef = CreateTypeRef(tokenNode, CreateTypeRefFlags_EarlyExit);
if (typeRef != NULL) if (typeRef != NULL)
@ -4755,9 +4755,9 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
if ((createTypeRefFlags & CreateTypeRefFlags_EarlyExit) != 0) if ((createTypeRefFlags & CreateTypeRefFlags_EarlyExit) != 0)
return delegateTypeRef; return delegateTypeRef;
} }
else if (token == BfToken_Decltype) else if ((token == BfToken_Comptype) || (token == BfToken_Decltype))
{ {
auto declTypeRef = mAlloc->Alloc<BfDeclTypeRef>(); auto declTypeRef = mAlloc->Alloc<BfExprModTypeRef>();
ReplaceNode(tokenNode, declTypeRef); ReplaceNode(tokenNode, declTypeRef);
declTypeRef->mToken = tokenNode; declTypeRef->mToken = tokenNode;
tokenNode = ExpectTokenAfter(declTypeRef, BfToken_LParen); tokenNode = ExpectTokenAfter(declTypeRef, BfToken_LParen);
@ -5064,6 +5064,7 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
(token == BfToken_LParen) || (token == BfToken_LParen) ||
(token == BfToken_Delegate) || (token == BfToken_Delegate) ||
(token == BfToken_Function) || (token == BfToken_Function) ||
(token == BfToken_Comptype) ||
(token == BfToken_Decltype) || (token == BfToken_Decltype) ||
((token == BfToken_Star) && (mAllowTypeWildcard)))) ((token == BfToken_Star) && (mAllowTypeWildcard))))
doAddType = true; doAddType = true;
@ -6521,6 +6522,7 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, int depth, BfAstNode* defe
(token == BfToken_AllocType) || (token == BfToken_AllocType) ||
(token == BfToken_RetType) || (token == BfToken_RetType) ||
(token == BfToken_Nullable) || (token == BfToken_Nullable) ||
(token == BfToken_Comptype) ||
(token == BfToken_Decltype) || (token == BfToken_Decltype) ||
(token == BfToken_LParen)) (token == BfToken_LParen))
{ {

View file

@ -126,7 +126,7 @@ BfAstNode* BfResolvePassData::FindBaseNode(BfAstNode* node)
{ {
baseNode = qualifiedNameNode->mRight; baseNode = qualifiedNameNode->mRight;
} }
else if (auto declTypeRef = BfNodeDynCast<BfDeclTypeRef>(baseNode)) else if (auto declTypeRef = BfNodeDynCast<BfExprModTypeRef>(baseNode))
{ {
baseNode = NULL; baseNode = NULL;
break; break;

View file

@ -3408,12 +3408,12 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
} }
return hashVal; return hashVal;
} }
else if (auto declTypeRef = BfNodeDynCastExact<BfDeclTypeRef>(typeRef)) else if (auto exprModTypeRef = BfNodeDynCastExact<BfExprModTypeRef>(typeRef))
{ {
if (ctx->mResolvedType == NULL) if (ctx->mResolvedType == NULL)
{ {
if (declTypeRef->mTarget != NULL) if (exprModTypeRef->mTarget != NULL)
{ {
BfTypedValue result; BfTypedValue result;
// //
@ -3427,9 +3427,34 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
SetAndRestoreValue<bool> ignoreWrites(ctx->mModule->mBfIRBuilder->mIgnoreWrites, true); SetAndRestoreValue<bool> ignoreWrites(ctx->mModule->mBfIRBuilder->mIgnoreWrites, true);
SetAndRestoreValue<bool> allowUninitReads(ctx->mModule->mCurMethodState->mAllowUinitReads, true); SetAndRestoreValue<bool> allowUninitReads(ctx->mModule->mCurMethodState->mAllowUinitReads, true);
result = ctx->mModule->CreateValueFromExpression(declTypeRef->mTarget); if (exprModTypeRef->mToken->mToken == BfToken_Comptype)
result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget, ctx->mModule->ResolveTypeDef(ctx->mModule->mCompiler->mTypeTypeDef), BfEvalExprFlags_Comptime);
else
result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget);
} }
ctx->mResolvedType = result.mType;
if ((result) && (exprModTypeRef->mToken->mToken == BfToken_Comptype))
{
auto constant = ctx->mModule->mBfIRBuilder->GetConstant(result.mValue);
if (constant != NULL)
{
if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData))
{
auto typeOf = (BfTypeOf_Const*)constant;
ctx->mResolvedType = typeOf->mType;
}
else if (constant->mConstType == BfConstType_Undef)
{
ctx->mHadVar = true;
ctx->mResolvedType = ctx->mModule->GetPrimitiveType(BfTypeCode_Var);
}
}
if (ctx->mResolvedType == NULL)
ctx->mModule->Fail("Constant System.Type value required", exprModTypeRef->mTarget);
}
else
ctx->mResolvedType = result.mType;
} }
} }
@ -3875,7 +3900,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
} }
} }
if (auto declTypeRef = BfNodeDynCastExact<BfDeclTypeRef>(rhs)) if (auto declTypeRef = BfNodeDynCastExact<BfExprModTypeRef>(rhs))
{ {
BF_ASSERT(ctx->mResolvedType != NULL); BF_ASSERT(ctx->mResolvedType != NULL);
return lhs == ctx->mResolvedType; return lhs == ctx->mResolvedType;

View file

@ -1104,6 +1104,7 @@ public:
BfType* mExternType; BfType* mExternType;
Array<BfTypeInstance*> mInterfaceConstraints; Array<BfTypeInstance*> mInterfaceConstraints;
Array<BfGenericOperatorConstraintInstance> mOperatorConstraints; Array<BfGenericOperatorConstraintInstance> mOperatorConstraints;
Array<BfTypeReference*> mComptypeConstraint;
BfType* mTypeConstraint; BfType* mTypeConstraint;
int mRefCount; int mRefCount;
@ -2428,7 +2429,7 @@ public:
{ {
BfHashFlag_None = 0, BfHashFlag_None = 0,
BfHashFlag_AllowRef = 1, BfHashFlag_AllowRef = 1,
BfHashFlag_AllowGenericParamConstValue = 2 BfHashFlag_AllowGenericParamConstValue = 2
}; };
class LookupContext class LookupContext
@ -2440,6 +2441,7 @@ public:
BfTypeInstance* mRootOuterTypeInstance; BfTypeInstance* mRootOuterTypeInstance;
BfType* mResolvedType; BfType* mResolvedType;
BfResolveTypeRefFlags mResolveFlags; BfResolveTypeRefFlags mResolveFlags;
bool mHadVar;
bool mFailed; bool mFailed;
public: public:
@ -2451,6 +2453,7 @@ public:
mModule = NULL; mModule = NULL;
mResolvedType = NULL; mResolvedType = NULL;
mFailed = false; mFailed = false;
mHadVar = false;
mResolveFlags = BfResolveTypeRefFlag_None; mResolveFlags = BfResolveTypeRefFlag_None;
} }
@ -2488,10 +2491,10 @@ public:
int tryCount = 0; int tryCount = 0;
ctx->mFailed = false; ctx->mFailed = false;
int hashVal = Hash(findType, ctx, BfHashFlag_AllowRef); int hashVal = Hash(findType, ctx, BfHashFlag_AllowRef);
if (ctx->mFailed) if ((ctx->mFailed) || (ctx->mHadVar))
{ {
return false; return false;
} }
int bucket = (hashVal & 0x7FFFFFFF) % mHashSize; int bucket = (hashVal & 0x7FFFFFFF) % mHashSize;
auto checkEntry = mHashHeads[bucket]; auto checkEntry = mHashHeads[bucket];
while (checkEntry != NULL) while (checkEntry != NULL)

View file

@ -3420,8 +3420,8 @@ void BfModule::VisitCodeBlock(BfBlock* block)
} }
else else
child->Accept(this); child->Accept(this);
mSystem->CheckLockYield(); mContext->CheckLockYield();
++itr; ++itr;
} }
@ -3437,7 +3437,7 @@ void BfModule::VisitCodeBlock(BfBlock* block)
//?? //??
auto moduleMethodInstance = GetLocalMethodInstance(localMethod, BfTypeVector(), NULL, true); auto moduleMethodInstance = GetLocalMethodInstance(localMethod, BfTypeVector(), NULL, true);
} }
mSystem->CheckLockYield(); mContext->CheckLockYield();
} }
while ((int)mCurMethodState->mLocalMethods.size() > startLocalMethod) while ((int)mCurMethodState->mLocalMethods.size() > startLocalMethod)
@ -4967,7 +4967,11 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
BfType* expectingReturnType = retType; BfType* expectingReturnType = retType;
if ((expectingReturnType != NULL) && (expectingReturnType->IsVar())) if ((expectingReturnType != NULL) && (expectingReturnType->IsVar()))
expectingReturnType = NULL; {
NOP;
// expectingReturnType = NULL;
}
BfType* origType; BfType* origType;
BfExprEvaluator exprEvaluator(this); BfExprEvaluator exprEvaluator(this);

View file

@ -637,7 +637,8 @@ enum BfGenericParamFlags : uint16
BfGenericParamFlag_Equals = 0x400, BfGenericParamFlag_Equals = 0x400,
BfGenericParamFlag_Equals_Op = 0x800, BfGenericParamFlag_Equals_Op = 0x800,
BfGenericParamFlag_Equals_Type = 0x1000, BfGenericParamFlag_Equals_Type = 0x1000,
BfGenericParamFlag_Equals_IFace = 0x2000 BfGenericParamFlag_Equals_IFace = 0x2000,
BfGenericParamFlag_ComptypeExpr = 0x4000
}; };
class BfConstraintDef class BfConstraintDef

View file

@ -3480,6 +3480,19 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
return BfIRValue(); return BfIRValue();
} }
if (typeInst->IsInstanceOf(ceModule->mCompiler->mTypeTypeDef))
{
addr_ce addr = *(addr_ce*)(instData);
int typeId = GetTypeIdFromType(addr);
if (typeId <= 0)
{
Fail("Unable to locate return type type");
return BfIRValue();
}
return module->CreateTypeDataRef(module->mContext->mTypes[typeId]);
}
if (typeInst->IsObjectOrInterface()) if (typeInst->IsObjectOrInterface())
{ {
Fail(StrFormat("Reference type '%s' return value not allowed", module->TypeToString(typeInst).c_str())); Fail(StrFormat("Reference type '%s' return value not allowed", module->TypeToString(typeInst).c_str()));
@ -3846,7 +3859,12 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
memStart = &mMemory[0]; memStart = &mMemory[0];
addr_ce retInstAddr = retAddr; addr_ce retInstAddr = retAddr;
if ((returnType->IsObject()) || (returnType->IsPointer()))
if (returnType->IsInstanceOf(mCeMachine->mCompiler->mTypeTypeDef))
{
// Allow
}
else if ((returnType->IsObject()) || (returnType->IsPointer()))
{ {
// Or pointer? // Or pointer?
retInstAddr = *(addr_ce*)(memStart + retAddr); retInstAddr = *(addr_ce*)(memStart + retAddr);

View file

@ -955,7 +955,7 @@ DbgType* DbgExprEvaluator::ResolveTypeRef(BfTypeReference* typeRef)
} }
} }
if (auto declTypeRef = BfNodeDynCastExact<BfDeclTypeRef>(typeRef)) if (auto declTypeRef = BfNodeDynCastExact<BfExprModTypeRef>(typeRef))
{ {
mResult = DbgTypedValue(); mResult = DbgTypedValue();
VisitChild(declTypeRef->mTarget); VisitChild(declTypeRef->mTarget);

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using System.Collections;
namespace Tests namespace Tests
{ {
@ -73,6 +74,40 @@ namespace Tests
} }
struct DoublingEnumerator<TElem, TEnum> : IEnumerator<TElem>
where TElem : operator TElem + TElem
where TEnum : concrete, IEnumerator<TElem>
{
TEnum mEnum;
public this(TEnum e)
{
mEnum = e;
}
public Result<TElem> GetNext() mut
{
switch (mEnum.GetNext())
{
case .Ok(let val): return .Ok(val + val);
case .Err: return .Err;
}
}
}
static Type GetConcreteEnumerator<TCollection, TElem>() where TCollection : IEnumerable<TElem>
{
TCollection col = ?;
return col.GetEnumerator().GetType();
}
public static DoublingEnumerator<TElem, comptype(GetConcreteEnumerator<TCollection, TElem>())> GetDoublingEnumerator<TCollection, TElem>(this TCollection it)
where TCollection: concrete, IEnumerable<TElem>
where TElem : operator TElem + TElem
{
return .(it.GetEnumerator());
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -88,6 +123,14 @@ namespace Tests
MethodA(34, 45); MethodA(34, 45);
Debug.Assert(LogAttribute.gLog == "Called Tests.Comptime.MethodA(int a, int b) 34 45"); Debug.Assert(LogAttribute.gLog == "Called Tests.Comptime.MethodA(int a, int b) 34 45");
List<float> fList = scope .() { 1, 2, 3 };
var e = fList.GetDoublingEnumerator();
Test.Assert(e.GetNext().Value == 2);
Test.Assert(e.GetNext().Value == 4);
Test.Assert(e.GetNext().Value == 6);
//Test.Assert(fList.DoubleVals() == 12);
} }
} }
} }