mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Added auto-constructors (ie: 'struct Vec : this(float x, float y);')
This commit is contained in:
parent
ae0f3c5ebb
commit
9d1a5d9f3d
7 changed files with 155 additions and 9 deletions
|
@ -338,6 +338,7 @@ class BfMemberReferenceExpression;
|
||||||
class BfDynamicCastExpression;
|
class BfDynamicCastExpression;
|
||||||
class BfCheckTypeExpression;
|
class BfCheckTypeExpression;
|
||||||
class BfConstructorDeclaration;
|
class BfConstructorDeclaration;
|
||||||
|
class BfAutoConstructorDeclaration;
|
||||||
class BfDestructorDeclaration;
|
class BfDestructorDeclaration;
|
||||||
class BfQualifiedTypeReference;
|
class BfQualifiedTypeReference;
|
||||||
class BfUsingDirective;
|
class BfUsingDirective;
|
||||||
|
@ -2282,6 +2283,7 @@ public:
|
||||||
BfTokenNode* mTypeNode;
|
BfTokenNode* mTypeNode;
|
||||||
BfIdentifierNode* mNameNode;
|
BfIdentifierNode* mNameNode;
|
||||||
BfAstNode* mDefineNode;
|
BfAstNode* mDefineNode;
|
||||||
|
BfAutoConstructorDeclaration* mAutoCtor;
|
||||||
BfGenericParamsDeclaration* mGenericParams;
|
BfGenericParamsDeclaration* mGenericParams;
|
||||||
BfGenericConstraintsDeclaration* mGenericConstraintsDeclaration;
|
BfGenericConstraintsDeclaration* mGenericConstraintsDeclaration;
|
||||||
bool mIgnoreDeclaration;
|
bool mIgnoreDeclaration;
|
||||||
|
@ -2994,6 +2996,12 @@ public:
|
||||||
|
|
||||||
}; BF_AST_DECL(BfConstructorDeclaration, BfMethodDeclaration);
|
}; BF_AST_DECL(BfConstructorDeclaration, BfMethodDeclaration);
|
||||||
|
|
||||||
|
class BfAutoConstructorDeclaration : public BfConstructorDeclaration
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_AST_TYPE(BfAutoConstructorDeclaration, BfConstructorDeclaration);
|
||||||
|
}; BF_AST_DECL(BfAutoConstructorDeclaration, BfConstructorDeclaration);
|
||||||
|
|
||||||
class BfDestructorDeclaration : public BfMethodDeclaration
|
class BfDestructorDeclaration : public BfMethodDeclaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -489,6 +489,13 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
||||||
methodDef->mIsVirtual = true;
|
methodDef->mIsVirtual = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isAutoCtor = false;
|
||||||
|
if (auto autoCtorDeclaration = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
|
||||||
|
{
|
||||||
|
methodDef->mProtection = BfProtection_Public;
|
||||||
|
isAutoCtor = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
|
if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
|
||||||
{
|
{
|
||||||
methodDef->mIsMutating = true;
|
methodDef->mIsMutating = true;
|
||||||
|
@ -645,8 +652,16 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
||||||
paramDef->mMethodGenericParamIdx = mSystem->GetGenericParamIdx(methodDef->mGenericParams, paramDef->mTypeRef);
|
paramDef->mMethodGenericParamIdx = mSystem->GetGenericParamIdx(methodDef->mGenericParams, paramDef->mTypeRef);
|
||||||
if (paramDecl->mModToken == NULL)
|
if (paramDecl->mModToken == NULL)
|
||||||
paramDef->mParamKind = BfParamKind_Normal;
|
paramDef->mParamKind = BfParamKind_Normal;
|
||||||
else //
|
else if (paramDecl->mModToken->mToken == BfToken_Params)
|
||||||
paramDef->mParamKind = BfParamKind_Params;
|
paramDef->mParamKind = BfParamKind_Params;
|
||||||
|
else if ((paramDecl->mModToken->mToken == BfToken_ReadOnly) && (isAutoCtor))
|
||||||
|
{
|
||||||
|
// Readonly specifier
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Fail(StrFormat("Invalid use of '%s' specifier", BfTokenToString(paramDecl->mModToken->mToken)), paramDecl->mModToken);
|
||||||
|
}
|
||||||
|
|
||||||
if ((mCurTypeDef->mIsFunction) && (paramIdx == 0) && (paramDef->mName == "this"))
|
if ((mCurTypeDef->mIsFunction) && (paramIdx == 0) && (paramDef->mName == "this"))
|
||||||
{
|
{
|
||||||
|
@ -707,6 +722,23 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAutoCtor)
|
||||||
|
{
|
||||||
|
for (auto paramDef : methodDef->mParams)
|
||||||
|
{
|
||||||
|
auto fieldDef = new BfFieldDef();
|
||||||
|
fieldDef->mName = paramDef->mName;
|
||||||
|
fieldDef->mTypeRef = paramDef->mTypeRef;
|
||||||
|
fieldDef->mProtection = BfProtection_Public;
|
||||||
|
fieldDef->mDeclaringType = mCurTypeDef;
|
||||||
|
fieldDef->mIdx = mCurTypeDef->mFields.mSize;
|
||||||
|
if ((paramDef->mParamDeclaration->mModToken != NULL) &&
|
||||||
|
(paramDef->mParamDeclaration->mModToken->mToken == BfToken_ReadOnly))
|
||||||
|
fieldDef->mIsReadOnly = true;
|
||||||
|
mCurTypeDef->mFields.Add(fieldDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ParseAttributes(methodDeclaration->mAttributes, methodDef);
|
ParseAttributes(methodDeclaration->mAttributes, methodDef);
|
||||||
return methodDef;
|
return methodDef;
|
||||||
}
|
}
|
||||||
|
@ -1819,6 +1851,9 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeDeclaration->mAutoCtor != NULL)
|
||||||
|
VisitChildNoRef(typeDeclaration->mAutoCtor);
|
||||||
|
|
||||||
if (auto defineBlock = BfNodeDynCast<BfBlock>(typeDeclaration->mDefineNode))
|
if (auto defineBlock = BfNodeDynCast<BfBlock>(typeDeclaration->mDefineNode))
|
||||||
{
|
{
|
||||||
for (auto& member : *defineBlock)
|
for (auto& member : *defineBlock)
|
||||||
|
@ -1829,8 +1864,9 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
else if (auto defineTokenNode = BfNodeDynCast<BfTokenNode>(typeDeclaration->mDefineNode))
|
else if (auto defineTokenNode = BfNodeDynCast<BfTokenNode>(typeDeclaration->mDefineNode))
|
||||||
{
|
{
|
||||||
if (defineTokenNode->GetToken() == BfToken_Semicolon)
|
if (defineTokenNode->GetToken() == BfToken_Semicolon)
|
||||||
{
|
{
|
||||||
mCurTypeDef->mIsOpaque = true;
|
if (typeDeclaration->mAutoCtor == NULL)
|
||||||
|
mCurTypeDef->mIsOpaque = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1147,6 +1147,7 @@ void BfElementVisitor::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
VisitChild(typeDeclaration->mTypeNode);
|
VisitChild(typeDeclaration->mTypeNode);
|
||||||
VisitChild(typeDeclaration->mNameNode);
|
VisitChild(typeDeclaration->mNameNode);
|
||||||
VisitChild(typeDeclaration->mColonToken);
|
VisitChild(typeDeclaration->mColonToken);
|
||||||
|
VisitChild(typeDeclaration->mAutoCtor);
|
||||||
for (auto& baseClass : typeDeclaration->mBaseClasses)
|
for (auto& baseClass : typeDeclaration->mBaseClasses)
|
||||||
VisitChild(baseClass);
|
VisitChild(baseClass);
|
||||||
for (auto& comma : typeDeclaration->mBaseClassCommas)
|
for (auto& comma : typeDeclaration->mBaseClassCommas)
|
||||||
|
|
|
@ -3876,7 +3876,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 = BfNodeDynCastExact<BfDeclTypeRef>(field->mFieldDeclaration->mTypeRef) != NULL;
|
bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact<BfDeclTypeRef>(field->mFieldDeclaration->mTypeRef) != NULL;
|
||||||
|
|
||||||
auto fieldType = fieldInstance->GetResolvedType();
|
auto fieldType = fieldInstance->GetResolvedType();
|
||||||
if ((field->mIsConst) && (!isDeclType))
|
if ((field->mIsConst) && (!isDeclType))
|
||||||
|
@ -16155,7 +16155,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitInitBlocks(_CheckInitBlock);
|
EmitInitBlocks(_CheckInitBlock);
|
||||||
|
|
||||||
if (hadInlineInitBlock)
|
if (hadInlineInitBlock)
|
||||||
{
|
{
|
||||||
RestoreScopeState();
|
RestoreScopeState();
|
||||||
|
@ -16229,6 +16229,34 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!methodInstance->mIsAutocompleteMethod)
|
||||||
|
{
|
||||||
|
if (auto autoDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
|
||||||
|
{
|
||||||
|
BfExprEvaluator exprEvaluator(this);
|
||||||
|
for (int paramIdx = 0; paramIdx < methodDef->mParams.mSize; paramIdx++)
|
||||||
|
{
|
||||||
|
auto paramDef = methodDef->mParams[paramIdx];
|
||||||
|
auto& fieldInstance = mCurTypeInstance->mFieldInstances[paramIdx];
|
||||||
|
BF_ASSERT(paramDef->mName == fieldInstance.GetFieldDef()->mName);
|
||||||
|
if (fieldInstance.mDataIdx < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto localVar = mCurMethodState->mLocals[paramIdx + 1];
|
||||||
|
BF_ASSERT(localVar->mName == paramDef->mName);
|
||||||
|
auto localVal = exprEvaluator.LoadLocal(localVar);
|
||||||
|
|
||||||
|
if (paramDef->mParamKind != BfParamKind_Normal)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto thisVal = GetThis();
|
||||||
|
auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(thisVal.mValue, 0, fieldInstance.mDataIdx);
|
||||||
|
mBfIRBuilder->CreateAlignedStore(localVar->mValue, fieldPtr, localVar->mResolvedType->mAlign);
|
||||||
|
MarkFieldInitialized(&fieldInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call base ctor (if applicable)
|
// Call base ctor (if applicable)
|
||||||
BfTypeInstance* targetType = NULL;
|
BfTypeInstance* targetType = NULL;
|
||||||
BfAstNode* targetRefNode = NULL;
|
BfAstNode* targetRefNode = NULL;
|
||||||
|
@ -19521,7 +19549,11 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
|
|
||||||
for (auto localVar : mCurMethodState->mLocals)
|
for (auto localVar : mCurMethodState->mLocals)
|
||||||
{
|
{
|
||||||
if ((skipEndChecks) || (methodDef->mBody == NULL))
|
if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
else if ((skipEndChecks) || (methodDef->mBody == NULL))
|
||||||
break;
|
break;
|
||||||
LocalVariableDone(localVar, true);
|
LocalVariableDone(localVar, true);
|
||||||
}
|
}
|
||||||
|
@ -21751,7 +21783,12 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||||
{
|
{
|
||||||
if (methodDeclaration->mEndSemicolon == NULL)
|
if (methodDeclaration->mEndSemicolon == NULL)
|
||||||
{
|
{
|
||||||
AssertParseErrorState();
|
if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AssertParseErrorState();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -2758,6 +2758,7 @@ void BfPrinter::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
QueueVisitChild(typeDeclaration->mNameNode);
|
QueueVisitChild(typeDeclaration->mNameNode);
|
||||||
QueueVisitChild(typeDeclaration->mGenericParams);
|
QueueVisitChild(typeDeclaration->mGenericParams);
|
||||||
|
QueueVisitChild(typeDeclaration->mAutoCtor);
|
||||||
if (typeDeclaration->mColonToken != NULL)
|
if (typeDeclaration->mColonToken != NULL)
|
||||||
{
|
{
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
|
|
|
@ -8420,6 +8420,14 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
|
||||||
|
|
||||||
if (baseTypeIdx > 0)
|
if (baseTypeIdx > 0)
|
||||||
{
|
{
|
||||||
|
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode))
|
||||||
|
{
|
||||||
|
if (tokenNode->mToken == BfToken_Semicolon)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BfTokenNode* commaToken = NULL;
|
BfTokenNode* commaToken = NULL;
|
||||||
if (typeDeclaration->mGenericParams != NULL)
|
if (typeDeclaration->mGenericParams != NULL)
|
||||||
{
|
{
|
||||||
|
@ -8438,6 +8446,32 @@ BfAstNode* BfReducer::CreateTopLevelObject(BfTokenNode* tokenNode, BfAttributeDi
|
||||||
baseClassCommas.push_back(commaToken);
|
baseClassCommas.push_back(commaToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
|
||||||
|
{
|
||||||
|
if (tokenNode->mToken == BfToken_This)
|
||||||
|
{
|
||||||
|
mVisitorPos.MoveNext();
|
||||||
|
auto ctorDecl = mAlloc->Alloc<BfAutoConstructorDeclaration>();
|
||||||
|
BfDeferredAstSizedArray<BfParameterDeclaration*> params(ctorDecl->mParams, mAlloc);
|
||||||
|
BfDeferredAstSizedArray<BfTokenNode*> commas(ctorDecl->mCommas, mAlloc);
|
||||||
|
ctorDecl->mReturnType = NULL;
|
||||||
|
ReplaceNode(tokenNode, ctorDecl);
|
||||||
|
MEMBER_SET(ctorDecl, mThisToken, tokenNode);
|
||||||
|
ParseMethod(ctorDecl, ¶ms, &commas);
|
||||||
|
|
||||||
|
if (typeDeclaration->mAutoCtor == NULL)
|
||||||
|
{
|
||||||
|
MEMBER_SET(typeDeclaration, mAutoCtor, ctorDecl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Fail("Only one auto-constructor is allowed", ctorDecl);
|
||||||
|
AddErrorNode(ctorDecl);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto baseType = CreateTypeRefAfter(typeDeclaration);
|
auto baseType = CreateTypeRefAfter(typeDeclaration);
|
||||||
if (baseType == NULL)
|
if (baseType == NULL)
|
||||||
break;
|
break;
|
||||||
|
@ -8879,7 +8913,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
|
||||||
(token == BfToken_Delegate) || (token == BfToken_Function) ||
|
(token == BfToken_Delegate) || (token == BfToken_Function) ||
|
||||||
(token == BfToken_Params) || (token == BfToken_LParen) ||
|
(token == BfToken_Params) || (token == BfToken_LParen) ||
|
||||||
(token == BfToken_Var) || (token == BfToken_LBracket) ||
|
(token == BfToken_Var) || (token == BfToken_LBracket) ||
|
||||||
(token == BfToken_DotDotDot)))
|
(token == BfToken_ReadOnly) || (token == BfToken_DotDotDot)))
|
||||||
{
|
{
|
||||||
// These get picked up below
|
// These get picked up below
|
||||||
}
|
}
|
||||||
|
@ -8938,7 +8972,7 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((token != BfToken_Out) && (token != BfToken_Ref) && (token != BfToken_Mut) && (token != BfToken_Params))
|
if ((token != BfToken_Out) && (token != BfToken_Ref) && (token != BfToken_Mut) && (token != BfToken_Params) && (token != BfToken_ReadOnly))
|
||||||
{
|
{
|
||||||
Fail("Invalid token", tokenNode);
|
Fail("Invalid token", tokenNode);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -9341,6 +9375,9 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm
|
||||||
endToken = NULL;
|
endToken = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(ctorDecl))
|
||||||
|
return true;
|
||||||
|
|
||||||
if ((endToken != NULL) && (endToken->GetToken() == BfToken_Semicolon))
|
if ((endToken != NULL) && (endToken->GetToken() == BfToken_Semicolon))
|
||||||
{
|
{
|
||||||
MEMBER_SET_CHECKED_BOOL(methodDeclaration, mEndSemicolon, endToken);
|
MEMBER_SET_CHECKED_BOOL(methodDeclaration, mEndSemicolon, endToken);
|
||||||
|
|
|
@ -124,6 +124,17 @@ namespace Tests
|
||||||
Dictionary<int, StructK> dict;
|
Dictionary<int, StructK> dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StructL : this(int a, int b);
|
||||||
|
|
||||||
|
struct StructM : this(readonly int a, readonly int b)
|
||||||
|
{
|
||||||
|
public int c;
|
||||||
|
this
|
||||||
|
{
|
||||||
|
c = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
static void TestBasics()
|
static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -142,6 +153,21 @@ namespace Tests
|
||||||
sb0 = .{ mA = 3, mB = 4 };
|
sb0 = .{ mA = 3, mB = 4 };
|
||||||
Test.Assert(sb0.mA == 3);
|
Test.Assert(sb0.mA == 3);
|
||||||
Test.Assert(sb0.mB == 4);
|
Test.Assert(sb0.mB == 4);
|
||||||
|
|
||||||
|
StructL sl = .(12, 23);
|
||||||
|
Test.Assert(sl.a == 12);
|
||||||
|
Test.Assert(sl.b == 23);
|
||||||
|
|
||||||
|
StructM sm = .(12, 23);
|
||||||
|
[IgnoreErrors]
|
||||||
|
{
|
||||||
|
sm.a += 100;
|
||||||
|
sm.b += 100;
|
||||||
|
sm.c += 100;
|
||||||
|
}
|
||||||
|
Test.Assert(sm.a == 12);
|
||||||
|
Test.Assert(sm.b == 23);
|
||||||
|
Test.Assert(sm.c == 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue