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

Generic constructors

This commit is contained in:
Brian Fiete 2024-11-06 07:31:55 -05:00
parent 64d646e130
commit 04ea8a6634
13 changed files with 267 additions and 37 deletions

View file

@ -116,6 +116,11 @@ void BfStructuralVisitor::Visit(BfGenericArgumentsNode* genericArgumentsNode)
Visit(genericArgumentsNode->ToBase());
}
void BfStructuralVisitor::Visit(BfCtorExplicitNode* ctorExplicitNode)
{
Visit(ctorExplicitNode->ToBase());
}
void BfStructuralVisitor::Visit(BfStatement* stmt)
{
Visit(stmt->ToBase());

View file

@ -337,6 +337,7 @@ class BfScopeNode;
class BfNewNode;
class BfLabeledBlock;
class BfGenericArgumentsNode;
class BfCtorExplicitNode;
class BfStatement;
class BfLabelableStatement;
class BfExpression;
@ -529,6 +530,7 @@ public:
virtual void Visit(BfGenericOperatorConstraint* genericConstraints);
virtual void Visit(BfGenericConstraintsDeclaration* genericConstraints);
virtual void Visit(BfGenericArgumentsNode* genericArgumentsNode);
virtual void Visit(BfCtorExplicitNode* genericArgumentsNode);
virtual void Visit(BfEmptyStatement* emptyStmt);
virtual void Visit(BfTokenNode* tokenNode);
@ -2911,6 +2913,16 @@ public:
BfAstNode* mStatement;
}; BF_AST_DECL(BfAttributedStatement, BfStatement);
class BfCtorExplicitNode : public BfAstNode
{
public:
BF_AST_TYPE(BfCtorExplicitNode, BfAstNode);
BfAstNode* mDotToken;
BfTokenNode* mThisToken;
BfGenericArgumentsNode* mGenericArgs;
}; BF_AST_DECL(BfCtorExplicitNode, BfAstNode);
class BfObjectCreateExpression : public BfMethodBoundExpression
{
public:
@ -2919,6 +2931,7 @@ public:
BfAstNode* mNewNode;
BfTokenNode* mStarToken;
BfTypeReference* mTypeRef;
BfCtorExplicitNode* mCtorExplicit;
BfTokenNode* mOpenToken;
BfTokenNode* mCloseToken;
BfSizedArray<BfExpression*> mArguments;

View file

@ -604,7 +604,8 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
if ((methodDef->mMethodType == BfMethodType_Normal) ||
(methodDef->mMethodType == BfMethodType_Operator) ||
(methodDef->mMethodType == BfMethodType_Mixin) ||
(methodDef->mMethodType == BfMethodType_Extension))
(methodDef->mMethodType == BfMethodType_Extension) ||
(methodDef->mMethodType == BfMethodType_Ctor))
{
bool isGeneric = (methodDeclaration->mGenericParams != NULL) || (!mCurTypeDef->mGenericParamDefs.IsEmpty());
ParseGenericParams(methodDeclaration->mGenericParams, methodDeclaration->mGenericConstraintsDeclaration, methodDef->mGenericParams, &methodDef->mExternalConstraints, outerGenericSize, isGeneric);
@ -2085,6 +2086,14 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
methodDef->mParams.push_back(newParam);
}
for (auto genericParam : method->mGenericParams)
{
BfGenericParamDef* newGenericParam = new BfGenericParamDef();
*newGenericParam = *genericParam;
methodDef->mGenericParams.Add(newGenericParam);
}
methodDef->mExternalConstraints = method->mExternalConstraints;
// Insert a 'appendIdx'
BfParameterDef* newParam = new BfParameterDef();
newParam->mName = "appendIdx";

View file

@ -114,6 +114,15 @@ void BfElementVisitor::Visit(BfGenericArgumentsNode* genericArgumentsNode)
VisitChild(genericArgumentsNode->mCloseChevron);
}
void BfElementVisitor::Visit(BfCtorExplicitNode* ctorExplicitNode)
{
Visit(ctorExplicitNode->ToBase());
VisitChild(ctorExplicitNode->mDotToken);
VisitChild(ctorExplicitNode->mThisToken);
VisitChild(ctorExplicitNode->mGenericArgs);
}
void BfElementVisitor::Visit(BfStatement* stmt)
{
Visit(stmt->ToBase());
@ -627,6 +636,7 @@ void BfElementVisitor::Visit(BfObjectCreateExpression* newExpr)
VisitChild(newExpr->mNewNode);
VisitChild(newExpr->mStarToken);
VisitChild(newExpr->mTypeRef);
VisitChild(newExpr->mCtorExplicit);
VisitChild(newExpr->mOpenToken);
VisitChild(newExpr->mCloseToken);
for (auto& val : newExpr->mArguments)

View file

@ -33,6 +33,7 @@ public:
virtual void Visit(BfGenericOperatorConstraint* genericConstraints);
virtual void Visit(BfGenericConstraintsDeclaration* genericConstraints);
virtual void Visit(BfGenericArgumentsNode* genericArgumentsNode);
virtual void Visit(BfCtorExplicitNode* genericArgumentsNode);
virtual void Visit(BfEmptyStatement* emptyStmt);
virtual void Visit(BfTokenNode* tokenNode);

View file

@ -7977,7 +7977,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
arrayType, false);
BfResolvedArgs resolvedArgs;
MatchConstructor(targetSrc, NULL, expandedParamsArray, arrayType, resolvedArgs, false, false);
MatchConstructor(targetSrc, NULL, expandedParamsArray, arrayType, resolvedArgs, false, BfMethodGenericArguments(), false);
//TODO: Assert 'length' var is at slot 1
auto arrayBits = mModule->mBfIRBuilder->CreateBitCast(expandedParamsArray.mValue, mModule->mBfIRBuilder->MapType(arrayType->mBaseType));
@ -8742,7 +8742,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
return callResult;
}
BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, BfTypeInstance* targetType, BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue)
BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, BfTypeInstance* targetType, BfResolvedArgs& argValues, bool callCtorBodyOnly,
const BfMethodGenericArguments& methodGenericArguments, bool allowAppendAlloc, BfTypedValue* appendIndexValue)
{
// Temporarily disable so we don't capture calls in params
SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(mFunctionBindResult, NULL);
@ -8750,7 +8751,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
static int sCtorCount = 0;
sCtorCount++;
BfMethodMatcher methodMatcher(targetSrc, mModule, "", argValues.mResolvedArgs, BfMethodGenericArguments());
BfMethodMatcher methodMatcher(targetSrc, mModule, "", argValues.mResolvedArgs, methodGenericArguments);
methodMatcher.mBfEvalExprFlags = mBfEvalExprFlags;
BfTypeVector typeGenericArguments;
@ -8842,11 +8843,13 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
// There should always be a constructor
BF_ASSERT(methodMatcher.mBestMethodDef != NULL);
auto moduleMethodInstance = mModule->GetMethodInstance(methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher.mBestMethodGenericArguments);
if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc))
{
//auto moduleMethodInstance = mModule->GetMethodInstance(methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher.mBestMethodGenericArguments);
auto moduleMethodInstance = GetSelectedMethod(methodMatcher);
if (!moduleMethodInstance)
return BfTypedValue();
if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc))
return BfTypedValue();
}
BfAutoComplete* autoComplete = GetAutoComplete();
if (autoComplete != NULL)
@ -10142,7 +10145,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
mResultLocalVar = NULL;
mResultFieldInstance = NULL;
mResultLocalVarRefNode = NULL;
auto result = MatchConstructor(targetSrc, methodBoundExpr, structInst, resolvedTypeInstance, argValues, false, resolvedTypeInstance->IsObject());
auto result = MatchConstructor(targetSrc, methodBoundExpr, structInst, resolvedTypeInstance, argValues, false, BfMethodGenericArguments(), resolvedTypeInstance->IsObject());
if ((result) && (!result.mType->IsVoid()))
return result;
mModule->ValidateAllocation(resolvedTypeInstance, targetSrc);
@ -14042,7 +14045,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
}
BfResolvedArgs resolvedArgs;
MatchConstructor(delegateBindExpr, delegateBindExpr, mResult, useTypeInstance, resolvedArgs, false, false);
MatchConstructor(delegateBindExpr, delegateBindExpr, mResult, useTypeInstance, resolvedArgs, false, BfMethodGenericArguments(), false);
auto baseDelegateType = VerifyBaseDelegateType(delegateTypeInstance->mBaseType);
auto baseDelegate = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->MapType(baseDelegateType, BfIRPopulateType_Full));
@ -15490,6 +15493,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
}
BfMethodGenericArguments methodGenericArguments;
if ((objCreateExpr != NULL) && (objCreateExpr->mCtorExplicit != NULL) && (objCreateExpr->mCtorExplicit->mGenericArgs != NULL))
methodGenericArguments.mArguments = &objCreateExpr->mCtorExplicit->mGenericArgs->mGenericArgs;
CheckObjectCreateTypeRef(mExpectingType, allocNode);
BfAttributeState attributeState;
@ -15499,12 +15506,18 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
BfAllocTarget allocTarget;
ResolveAllocTarget(allocTarget, allocNode, newToken, &attributeState.mCustomAttributes);
bool isScopeAlloc = newToken->GetToken() == BfToken_Scope;
bool isAppendAlloc = newToken->GetToken() == BfToken_Append;
bool isStackAlloc = (newToken->GetToken() == BfToken_Stack) || (isScopeAlloc);
bool isStructAlloc = newToken == NULL;
bool isScopeAlloc = (newToken != NULL) && (newToken->GetToken() == BfToken_Scope);
bool isAppendAlloc = (newToken != NULL) && (newToken->GetToken() == BfToken_Append);
bool isStackAlloc = ((newToken != NULL) && (newToken->GetToken() == BfToken_Stack)) || (isScopeAlloc) || (isStructAlloc);
bool isArrayAlloc = false;// (objCreateExpr->mArraySizeSpecifier != NULL);
bool isRawArrayAlloc = (objCreateExpr != NULL) && (objCreateExpr->mStarToken != NULL);
if ((objCreateExpr != NULL) && (objCreateExpr->mCtorExplicit != NULL) && (objCreateExpr->mCtorExplicit->mThisToken != NULL))
{
mModule->SetElementType(objCreateExpr->mCtorExplicit->mThisToken, BfSourceElementType_Method);
}
if (isScopeAlloc)
{
if ((mBfEvalExprFlags & BfEvalExprFlags_FieldInitializer) != 0)
@ -15579,6 +15592,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
unresolvedTypeRef = mExpectingType->GetUnderlyingType();
}
else if (mExpectingType->IsStruct())
{
unresolvedTypeRef = mExpectingType;
}
else if (mExpectingType->IsVar())
unresolvedTypeRef = mExpectingType;
}
@ -16114,11 +16131,11 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
if (rawAutoComplete != NULL)
{
SetAndRestoreValue<bool> prevCapturing(rawAutoComplete->mIsCapturingMethodMatchInfo, false);
MatchConstructor(refNode, objCreateExpr, arrayValue, arrayType, resolvedArgs, false, false);
MatchConstructor(refNode, objCreateExpr, arrayValue, arrayType, resolvedArgs, false, methodGenericArguments, false);
}
else
{
MatchConstructor(refNode, objCreateExpr, arrayValue, arrayType, resolvedArgs, false, false);
MatchConstructor(refNode, objCreateExpr, arrayValue, arrayType, resolvedArgs, false, methodGenericArguments, false);
}
//TODO: Assert 'length' var is at slot 1
@ -16294,7 +16311,11 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
auto wasCapturingMethodInfo = autoComplete->mIsCapturingMethodMatchInfo;
autoComplete->CheckInvocation(objCreateExpr, objCreateExpr->mOpenToken, objCreateExpr->mCloseToken, objCreateExpr->mCommas);
MatchConstructor(objCreateExpr->mTypeRef, objCreateExpr, emtpyThis, typeInstance, argValues, false, true);
BfAstNode* refNode = objCreateExpr->mTypeRef;
if ((objCreateExpr->mCtorExplicit != NULL) && (objCreateExpr->mCtorExplicit->mThisToken != NULL))
refNode = objCreateExpr->mCtorExplicit->mThisToken;
MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, methodGenericArguments, true);
if ((wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo))
{
if (autoComplete->mMethodMatchInfo != NULL)
@ -16308,7 +16329,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
auto refNode = allocNode;
if (objCreateExpr != NULL)
refNode = objCreateExpr->mTypeRef;
MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, true);
MatchConstructor(refNode, objCreateExpr, emtpyThis, typeInstance, argValues, false, methodGenericArguments, true);
}
if (objCreateExpr != NULL)
mModule->ValidateAllocation(typeInstance, objCreateExpr->mTypeRef);
@ -16329,7 +16350,16 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
else
{
auto calcAppendMethodModule = mModule->GetMethodInstanceAtIdx(bindResult.mMethodInstance->GetOwner(), bindResult.mMethodInstance->mMethodDef->mIdx + 1, BF_METHODNAME_CALCAPPEND);
//auto calcAppendMethodModule = mModule->GetMethodInstanceAtIdx(bindResult.mMethodInstance->GetOwner(), bindResult.mMethodInstance->mMethodDef->mIdx + 1, BF_METHODNAME_CALCAPPEND);
BfTypeVector methodGenericArguments;
if (bindResult.mMethodInstance->mMethodInfoEx != NULL)
methodGenericArguments = bindResult.mMethodInstance->mMethodInfoEx->mMethodGenericArguments;
auto methodOwner = bindResult.mMethodInstance->GetOwner();
auto calcAppendMethodDef = methodOwner->mTypeDef->mMethods[bindResult.mMethodInstance->mMethodDef->mIdx + 1];
BF_ASSERT(calcAppendMethodDef->mName == BF_METHODNAME_CALCAPPEND);
auto calcAppendMethodModule = mModule->GetMethodInstance(methodOwner, calcAppendMethodDef, methodGenericArguments);
SizedArray<BfIRValue, 2> irArgs;
if (bindResult.mIRArgs.size() > 1)
@ -16523,6 +16553,17 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
mModule->mCompiler->mCeMachine->ClearAppendAllocInfo();
}
if ((mResult) && (isStructAlloc))
{
if (mResult.mType->IsPointer())
{
mResult = mModule->LoadValue(mResult);
mResult = BfTypedValue(mResult.mValue, mResult.mType->GetUnderlyingType(), true);
}
else
mModule->Fail(StrFormat("Allocation specifier such as 'new' is required for reference type '%s'", mModule->TypeToString(mResult.mType).c_str()), objCreateExpr);
}
}
void BfExprEvaluator::Visit(BfBoxExpression* boxExpr)
@ -16612,7 +16653,13 @@ void BfExprEvaluator::ResolveAllocTarget(BfAllocTarget& allocTarget, BfAstNode*
allocTarget.mRefNode = allocNode;
newToken = BfNodeDynCast<BfTokenNode>(allocNode);
if (newToken == NULL)
if (allocNode == NULL)
{
// Scope
if (mModule->mCurMethodState != NULL)
allocTarget.mScopeData = mModule->mCurMethodState->mCurScope->GetTargetable();
}
else if (newToken == NULL)
{
if (auto scopeNode = BfNodeDynCast<BfScopeNode>(allocNode))
{
@ -18269,7 +18316,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
else
mResult = BfTypedValue(mModule->CreateAlloca(expectingType), expectingType, BfTypedValueKind_TempAddr);
auto ctorResult = MatchConstructor(target, methodBoundExpr, mResult, expectingType->ToTypeInstance(), argValues, false, false);
auto ctorResult = MatchConstructor(target, methodBoundExpr, mResult, expectingType->ToTypeInstance(), argValues, false, BfMethodGenericArguments(), false);
if ((ctorResult) && (!ctorResult.mType->IsVoid()))
mResult = ctorResult;
mModule->ValidateAllocation(expectingType, invocationExpr->mTarget);
@ -23591,7 +23638,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
mResult = BfTypedValue(alloca, allocType, true);
auto result = MatchConstructor(opToken, NULL, mResult, allocType, argValues, true, false);
auto result = MatchConstructor(opToken, NULL, mResult, allocType, argValues, true, BfMethodGenericArguments(), false);
if ((result) && (!result.mType->IsVoid()))
mResult = result;

View file

@ -497,7 +497,7 @@ public:
void PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& irArgs, bool disableSplat = false, bool disableLowering = false, bool isIntrinsic = false, bool createCompositeCopy = false);
void PushThis(BfAstNode* targetSrc, BfTypedValue callTarget, BfMethodInstance* methodInstance, SizedArrayImpl<BfIRValue>& irArgs, bool skipMutCheck = false);
BfTypedValue MatchConstructor(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, BfTypeInstance* targetType,
BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue = NULL);
BfResolvedArgs& argValues, bool callCtorBodyOnly, const BfMethodGenericArguments& methodGenericArguments, bool allowAppendAlloc, BfTypedValue* appendIndexValue = NULL);
BfTypedValue CheckEnumCreation(BfAstNode* targetSrc, BfTypeInstance* enumType, const StringImpl& caseName, BfResolvedArgs& argValues);
BfTypedValue MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& name,
BfResolvedArgs& argValue, const BfMethodGenericArguments& methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet);

View file

@ -778,7 +778,7 @@ public:
if (typeInst != NULL)
{
exprEvaluator.ResolveArgValues(argValues);
exprEvaluator.MatchConstructor(objCreateExpr->mTypeRef, objCreateExpr, emtpyThis, typeInst, argValues, false, true);
exprEvaluator.MatchConstructor(objCreateExpr->mTypeRef, objCreateExpr, emtpyThis, typeInst, argValues, false, BfMethodGenericArguments(), true);
}
exprEvaluator.mFunctionBindResult = NULL;
@ -4765,7 +4765,7 @@ void BfModule::AppendedObjectInit(BfFieldInstance* fieldInst)
mBfIRBuilder->CreateStore(GetConstValue8(BfObjectFlag_AppendAlloc), thisFlagsPtr);
}
exprEvaluator.MatchConstructor(fieldDef->GetNameNode(), NULL, thisValue, fieldInst->mResolvedType->ToTypeInstance(), resolvedArgs, false, true, &indexVal);
exprEvaluator.MatchConstructor(fieldDef->GetNameNode(), NULL, thisValue, fieldInst->mResolvedType->ToTypeInstance(), resolvedArgs, false, BfMethodGenericArguments(), true, &indexVal);
}
void BfModule::CheckInterfaceMethod(BfMethodInstance* methodInstance)
@ -17149,7 +17149,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(exprEvaluator.mFunctionBindResult, &bindResult);
exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, true);
exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, BfMethodGenericArguments(), true);
}
if (bindResult.mMethodInstance == NULL)
@ -17196,7 +17196,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
bindResult.mSkipThis = true;
bindResult.mWantsArgs = true;
SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(exprEvaluator.mFunctionBindResult, &bindResult);
exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, true);
exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, BfMethodGenericArguments(), true);
BF_ASSERT(bindResult.mIRArgs[0].IsFake());
bindResult.mIRArgs.RemoveAt(0);
calcAppendArgs = bindResult.mIRArgs;
@ -18704,7 +18704,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
appendIdxVal = BfTypedValue(localVar->mValue, intRefType);
mCurMethodState->mCurAppendAlign = 1; // Don't make any assumptions about how the base leaves the alignment
}
exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, methodDef->mHasAppend, &appendIdxVal);
exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, BfMethodGenericArguments(), methodDef->mHasAppend, &appendIdxVal);
if (autoComplete != NULL)
{

View file

@ -5537,7 +5537,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
BfTypedValue emptyThis(mBfIRBuilder->GetFakeVal(), resolvedTypeRef, resolvedTypeRef->IsStruct());
exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_Comptime;
auto ctorResult = exprEvaluator.MatchConstructor(nameRefNode, NULL, emptyThis, fieldTypeInst, resolvedArgs, false, true);
auto ctorResult = exprEvaluator.MatchConstructor(nameRefNode, NULL, emptyThis, fieldTypeInst, resolvedArgs, false, BfMethodGenericArguments(), true);
if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->mHasAppend))
{

View file

@ -1913,6 +1913,7 @@ void BfPrinter::Visit(BfObjectCreateExpression* newExpr)
ExpectSpace();
VisitChild(newExpr->mTypeRef);
VisitChild(newExpr->mCtorExplicit);
if (newExpr->mStarToken != NULL)
{
@ -2497,6 +2498,7 @@ void BfPrinter::Visit(BfConstructorDeclaration* ctorDeclaration)
{
QueueVisitChild(ctorDeclaration->mThisToken);
}
QueueVisitChild(ctorDeclaration->mGenericParams);
QueueVisitChild(ctorDeclaration->mOpenParen);
for (int i = 0; i < (int) ctorDeclaration->mParams.size(); i++)
@ -2513,6 +2515,8 @@ void BfPrinter::Visit(BfConstructorDeclaration* ctorDeclaration)
QueueVisitChild(ctorDeclaration->mInitializerColonToken);
ExpectSpace();
QueueVisitChild(ctorDeclaration->mInitializer);
ExpectSpace();
QueueVisitChild(ctorDeclaration->mGenericConstraintsDeclaration);
if (ctorDeclaration->mFatArrowToken != NULL)
{

View file

@ -2052,16 +2052,29 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
}
else if (token == BfToken_Dot) // Abbreviated dot syntax ".EnumVal"
{
// Initializer ".{ x = 1, y = 2 }"
bool handled = false;
if (auto nextTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
{
if (nextTokenNode->mToken == BfToken_This)
{
auto invocationExpr = CreateObjectCreateExpression(NULL, tokenNode);
if (invocationExpr == NULL)
return exprLeft;
exprLeft = invocationExpr;
handled = true;
}
}
if (auto blockNode = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
{
// Initializer ".{ x = 1, y = 2 }"
auto typeRef = CreateTypeRef(mVisitorPos.GetCurrent());
if (typeRef)
{
exprLeft = TryCreateInitializerExpression(typeRef);
}
}
else
else if (!handled)
{
auto memberReferenceExpr = mAlloc->Alloc<BfMemberReferenceExpression>();
ReplaceNode(tokenNode, memberReferenceExpr);
@ -2933,6 +2946,29 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
BF_ASSERT(tokenNode->GetToken() == token);
if (token == BfToken_Dot)
{
if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
{
if (nextToken->mToken == BfToken_This)
{
int outNodeIdx = -1;
bool isGenericType;
bool isTypeRef = ((IsTypeReference(exprLeft, BfToken_This, -1, &outNodeIdx, NULL, &isGenericType)) &&
(outNodeIdx != -1));
if (isTypeRef)
{
auto invocationExpr = CreateObjectCreateExpression(NULL, exprLeft);
if (invocationExpr == NULL)
return exprLeft;
exprLeft = invocationExpr;
continue;
}
}
}
}
// Not a binary op, it's a 'close'
if (token == BfToken_Bang)
{
@ -4875,6 +4911,11 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
}
firstNode = qualifiedTypeRef;
}
else if (auto typeRef = BfNodeDynCast<BfTypeReference>(firstNode))
{
// Already a typeRef
return typeRef;
}
else
{
bool isHandled = false;
@ -5169,6 +5210,15 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
BfToken token = tokenNode->GetToken();
if (token == BfToken_Dot)
{
if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
{
if (nextToken->mToken == BfToken_This)
{
// Don't encode '.this' in type ref
break;
}
}
BfQualifiedTypeReference* qualifiedTypeRef = mAlloc->Alloc<BfQualifiedTypeReference>();
ReplaceNode(typeRef, qualifiedTypeRef);
qualifiedTypeRef->mLeft = typeRef;
@ -5216,6 +5266,15 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
{
if (tokenNode->GetToken() == BfToken_Dot)
{
if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
{
if (nextToken->mToken == BfToken_This)
{
// Don't encode '.this' in type ref
break;
}
}
BfQualifiedTypeReference* outerQualifiedTypeRef = mAlloc->Alloc<BfQualifiedTypeReference>();
ReplaceNode(qualifiedTypeRef, outerQualifiedTypeRef);
outerQualifiedTypeRef->mLeft = qualifiedTypeRef;
@ -5578,6 +5637,11 @@ BfIdentifierNode* BfReducer::CompactQualifiedName(BfAstNode* leftNode)
{
if (auto rightToken = BfNodeDynCast<BfTokenNode>(nextNextToken))
{
if (rightToken->mToken == BfToken_This)
{
return leftIdentifier;
}
if (BfTokenIsKeyword(rightToken->mToken))
{
rightIdentifier = mAlloc->Alloc<BfIdentifierNode>();
@ -8122,14 +8186,26 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
return allocToken;
}
BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* allocNode)
BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* allocNode, BfAstNode* targetNode)
{
auto objectCreateExpr = mAlloc->Alloc<BfObjectCreateExpression>();
BfDeferredAstSizedArray<BfExpression*> arguments(objectCreateExpr->mArguments, mAlloc);
BfDeferredAstSizedArray<BfTokenNode*> commas(objectCreateExpr->mCommas, mAlloc);
BfTypeReference* typeRef = NULL;
if (allocNode != NULL)
{
ReplaceNode(allocNode, objectCreateExpr);
MEMBER_SET(objectCreateExpr, mNewNode, allocNode);
}
else
{
ReplaceNode(targetNode, objectCreateExpr);
typeRef = CreateTypeRef(targetNode);
if (typeRef == NULL)
return NULL;
}
auto nextNode = mVisitorPos.GetNext();
@ -8145,7 +8221,8 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all
// }
// }
auto typeRef = CreateTypeRefAfter(objectCreateExpr);
if (typeRef == NULL)
typeRef = CreateTypeRefAfter(objectCreateExpr);
if (typeRef == NULL)
return objectCreateExpr;
@ -8206,6 +8283,42 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all
}
else
{
auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
auto nextNextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2));
if ((nextToken != NULL) && (nextToken->mToken == BfToken_Dot) &&
(nextNextToken != NULL) && (nextNextToken->mToken == BfToken_This))
{
auto ctorExplicitNode = mAlloc->Alloc<BfCtorExplicitNode>();
ReplaceNode(nextToken, ctorExplicitNode);
ctorExplicitNode->mDotToken = nextToken;
MEMBER_SET(ctorExplicitNode, mThisToken, nextNextToken);
mVisitorPos.MoveNext();
mVisitorPos.MoveNext();
MEMBER_SET(objectCreateExpr, mCtorExplicit, ctorExplicitNode);
}
else if ((nextToken != NULL) && (nextToken->mToken == BfToken_This))
{
auto ctorExplicitNode = mAlloc->Alloc<BfCtorExplicitNode>();
ReplaceNode(nextToken, ctorExplicitNode);
ctorExplicitNode->mThisToken = nextToken;
mVisitorPos.MoveNext();
MEMBER_SET(objectCreateExpr, mCtorExplicit, ctorExplicitNode);
}
if (objectCreateExpr->mCtorExplicit != NULL)
{
nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
if ((nextToken->mToken != NULL) && (nextToken->mToken == BfToken_LChevron))
{
mVisitorPos.MoveNext();
auto genericParamsDecl = CreateGenericArguments(nextToken, true);
if (genericParamsDecl == NULL)
return objectCreateExpr;
MEMBER_SET(objectCreateExpr->mCtorExplicit, mGenericArgs, genericParamsDecl);
objectCreateExpr->mSrcEnd = objectCreateExpr->mCtorExplicit->mSrcEnd;
}
}
// Note- if there WERE an LBracket here then we'd have an 'isArray' case. We pass this in here for
// error display purposes
tokenNode = ExpectTokenAfter(objectCreateExpr, BfToken_LParen, BfToken_LBracket);
@ -8308,6 +8421,12 @@ BfMemberReferenceExpression* BfReducer::CreateMemberReferenceExpression(BfAstNod
MEMBER_SET(memberReferenceExpr, mMemberName, attrIdentifier);
}
}
if (tokenNode->GetToken() == BfToken_This)
{
mVisitorPos.MoveNext();
MEMBER_SET(memberReferenceExpr, mMemberName, tokenNode);
}
}
if (memberReferenceExpr->mMemberName == NULL)

View file

@ -204,7 +204,7 @@ public:
BfLambdaBindExpression* CreateLambdaBindExpression(BfAstNode* allocNode, BfTokenNode* parenToken = NULL);
BfCollectionInitializerExpression* CreateCollectionInitializerExpression(BfBlock* block);
BfCollectionInitializerExpression* CreateCollectionInitializerExpression(BfTokenNode* openToken);
BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode);
BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode, BfAstNode* targetNode = NULL);
BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
BfInitializerExpression* TryCreateInitializerExpression(BfAstNode* target);

View file

@ -385,7 +385,22 @@ namespace Tests
public class InnerB
{
public T mVal;
public this<T3>(T3 val) where T : operator implicit T3
{
mVal = (.)val;
}
}
public struct InnerC
{
public T mVal;
public this<T3>(T3 val) where T : operator implicit T3
{
mVal = (.)val;
}
}
public static OuterA<int,float>.Inner<int16> sVal;
@ -491,6 +506,13 @@ namespace Tests
Test.Assert(specializedType.UnspecializedType == typeof(Dictionary<,>.Enumerator));
var t = typeof(Array2<>);
t = typeof(ClassH<,>.Inner<>);
var innerB = new OuterA<int, float>.InnerB.this<int32>(123);
Test.Assert(innerB.mVal == 123);
delete innerB;
var innerC = OuterA<int, float>.InnerC.this<int32>(123);
Test.Assert(innerC.mVal == 123);
}
}