mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Initializer expressions
This commit is contained in:
parent
f6e31e4976
commit
229a5aa5c5
17 changed files with 305 additions and 18 deletions
|
@ -196,6 +196,11 @@ void BfStructuralVisitor::Visit(BfSizedArrayCreateExpression* createExpr)
|
||||||
Visit(createExpr->ToBase());
|
Visit(createExpr->ToBase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfStructuralVisitor::Visit(BfInitializerExpression* initExpr)
|
||||||
|
{
|
||||||
|
Visit(initExpr->ToBase());
|
||||||
|
}
|
||||||
|
|
||||||
void BfStructuralVisitor::Visit(BfCollectionInitializerExpression* collectionInitExpr)
|
void BfStructuralVisitor::Visit(BfCollectionInitializerExpression* collectionInitExpr)
|
||||||
{
|
{
|
||||||
Visit(collectionInitExpr->ToBase());
|
Visit(collectionInitExpr->ToBase());
|
||||||
|
|
|
@ -354,6 +354,7 @@ class BfStrideOfExpression;
|
||||||
class BfDefaultExpression;
|
class BfDefaultExpression;
|
||||||
class BfUninitializedExpression;
|
class BfUninitializedExpression;
|
||||||
class BfConditionalExpression;
|
class BfConditionalExpression;
|
||||||
|
class BfInitializerExpression;
|
||||||
class BfCollectionInitializerExpression;
|
class BfCollectionInitializerExpression;
|
||||||
class BfSizedArrayCreateExpression;
|
class BfSizedArrayCreateExpression;
|
||||||
class BfEmptyStatement;
|
class BfEmptyStatement;
|
||||||
|
@ -435,6 +436,7 @@ public:
|
||||||
virtual void Visit(BfBaseExpression* baseExpr);
|
virtual void Visit(BfBaseExpression* baseExpr);
|
||||||
virtual void Visit(BfMixinExpression* thisExpr);
|
virtual void Visit(BfMixinExpression* thisExpr);
|
||||||
virtual void Visit(BfSizedArrayCreateExpression* createExpr);
|
virtual void Visit(BfSizedArrayCreateExpression* createExpr);
|
||||||
|
virtual void Visit(BfInitializerExpression* collectionInitExpr);
|
||||||
virtual void Visit(BfCollectionInitializerExpression* collectionInitExpr);
|
virtual void Visit(BfCollectionInitializerExpression* collectionInitExpr);
|
||||||
virtual void Visit(BfTypeReference* typeRef);
|
virtual void Visit(BfTypeReference* typeRef);
|
||||||
virtual void Visit(BfNamedTypeReference* typeRef);
|
virtual void Visit(BfNamedTypeReference* typeRef);
|
||||||
|
@ -2017,6 +2019,18 @@ public:
|
||||||
BfVariant mValue;
|
BfVariant mValue;
|
||||||
}; BF_AST_DECL(BfLiteralExpression, BfExpression);
|
}; BF_AST_DECL(BfLiteralExpression, BfExpression);
|
||||||
|
|
||||||
|
class BfInitializerExpression : public BfExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_AST_TYPE(BfInitializerExpression, BfExpression);
|
||||||
|
|
||||||
|
BfExpression* mTarget;
|
||||||
|
BfTokenNode* mOpenBrace;
|
||||||
|
BfSizedArray<BfExpression*> mValues;
|
||||||
|
BfSizedArray<BfTokenNode*> mCommas;
|
||||||
|
BfTokenNode* mCloseBrace;
|
||||||
|
}; BF_AST_DECL(BfInitializerExpression, BfExpression);
|
||||||
|
|
||||||
class BfCollectionInitializerExpression : public BfExpression
|
class BfCollectionInitializerExpression : public BfExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1920,9 +1920,13 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
|
||||||
|
|
||||||
if ((needsDefaultCtor) && (!hasDefaultCtor))
|
if ((needsDefaultCtor) && (!hasDefaultCtor))
|
||||||
{
|
{
|
||||||
|
BfProtection prot = hasCtor ? BfProtection_Hidden : BfProtection_Public;
|
||||||
|
if (mCurTypeDef->mName == mSystem->mEmptyAtom)
|
||||||
|
prot = BfProtection_Hidden;
|
||||||
|
|
||||||
// Create default constructor. If it's the only constructor then make it public,
|
// Create default constructor. If it's the only constructor then make it public,
|
||||||
// otherwise make it private so we can still internally use it but the user can't
|
// otherwise make it private so we can still internally use it but the user can't
|
||||||
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, hasCtor ? BfProtection_Hidden : BfProtection_Public, false, "");
|
auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, prot, false, "");
|
||||||
methodDef->mIsMutating = true;
|
methodDef->mIsMutating = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,6 +244,19 @@ void BfElementVisitor::Visit(BfSizedArrayCreateExpression* createExpr)
|
||||||
VisitChild(createExpr->mInitializer);
|
VisitChild(createExpr->mInitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfElementVisitor::Visit(BfInitializerExpression* initExpr)
|
||||||
|
{
|
||||||
|
Visit(initExpr->ToBase());
|
||||||
|
|
||||||
|
VisitChild(initExpr->mTarget);
|
||||||
|
VisitChild(initExpr->mOpenBrace);
|
||||||
|
for (auto& val : initExpr->mValues)
|
||||||
|
VisitChild(val);
|
||||||
|
for (auto& val : initExpr->mCommas)
|
||||||
|
VisitChild(val);
|
||||||
|
VisitChild(initExpr->mCloseBrace);
|
||||||
|
}
|
||||||
|
|
||||||
void BfElementVisitor::Visit(BfCollectionInitializerExpression* collectionInitExpr)
|
void BfElementVisitor::Visit(BfCollectionInitializerExpression* collectionInitExpr)
|
||||||
{
|
{
|
||||||
Visit(collectionInitExpr->ToBase());
|
Visit(collectionInitExpr->ToBase());
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
virtual void Visit(BfBaseExpression* baseExpr);
|
virtual void Visit(BfBaseExpression* baseExpr);
|
||||||
virtual void Visit(BfMixinExpression* thisExpr);
|
virtual void Visit(BfMixinExpression* thisExpr);
|
||||||
virtual void Visit(BfSizedArrayCreateExpression* createExpr);
|
virtual void Visit(BfSizedArrayCreateExpression* createExpr);
|
||||||
|
virtual void Visit(BfInitializerExpression* initExpr);
|
||||||
virtual void Visit(BfCollectionInitializerExpression* collectionInitExpr);
|
virtual void Visit(BfCollectionInitializerExpression* collectionInitExpr);
|
||||||
virtual void Visit(BfTypeReference* typeRef);
|
virtual void Visit(BfTypeReference* typeRef);
|
||||||
virtual void Visit(BfNamedTypeReference* typeRef);
|
virtual void Visit(BfNamedTypeReference* typeRef);
|
||||||
|
|
|
@ -8433,6 +8433,111 @@ void BfExprEvaluator::Visit(BfSizedArrayCreateExpression* createExpr)
|
||||||
InitializedSizedArray(arrayType, createExpr->mInitializer->mOpenBrace, createExpr->mInitializer->mValues, createExpr->mInitializer->mCommas, createExpr->mInitializer->mCloseBrace);
|
InitializedSizedArray(arrayType, createExpr->mInitializer->mOpenBrace, createExpr->mInitializer->mValues, createExpr->mInitializer->mCommas, createExpr->mInitializer->mCloseBrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
||||||
|
{
|
||||||
|
VisitChild(initExpr->mTarget);
|
||||||
|
if (!mResult)
|
||||||
|
mResult = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
|
||||||
|
|
||||||
|
BfTypedValue initValue = GetResult(true);
|
||||||
|
bool isFirstAdd = true;
|
||||||
|
BfFunctionBindResult addFunctionBindResult;
|
||||||
|
addFunctionBindResult.mWantsArgs = true;
|
||||||
|
|
||||||
|
for (auto elementExpr : initExpr->mValues)
|
||||||
|
{
|
||||||
|
bool wasValidInitKind = false;
|
||||||
|
|
||||||
|
if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(elementExpr))
|
||||||
|
{
|
||||||
|
BfTypedValue fieldResult;
|
||||||
|
if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(assignExpr->mLeft))
|
||||||
|
{
|
||||||
|
StringT<128> findName;
|
||||||
|
identifierNode->ToString(findName);
|
||||||
|
fieldResult = LookupField(identifierNode, initValue, findName, BfLookupFieldFlag_IsImplicitThis);
|
||||||
|
if (fieldResult.mKind == BfTypedValueKind_TempAddr)
|
||||||
|
fieldResult.mKind = BfTypedValueKind_Addr;
|
||||||
|
|
||||||
|
wasValidInitKind = true;
|
||||||
|
|
||||||
|
if ((fieldResult) || (mPropDef != NULL))
|
||||||
|
{
|
||||||
|
mResult = fieldResult;
|
||||||
|
PerformAssignment(assignExpr, true, BfTypedValue());
|
||||||
|
mResult = BfTypedValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mModule->Fail(StrFormat("'%s' does not contain a definition for '%s'", mModule->TypeToString(initValue.mType).c_str(),
|
||||||
|
findName.c_str()), identifierNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto autoComplete = GetAutoComplete();
|
||||||
|
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(elementExpr)))
|
||||||
|
{
|
||||||
|
if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(elementExpr))
|
||||||
|
{
|
||||||
|
auto typeInstance = initValue.mType->ToTypeInstance();
|
||||||
|
if (typeInstance != NULL)
|
||||||
|
{
|
||||||
|
String filter;
|
||||||
|
identiferNode->ToString(filter);
|
||||||
|
autoComplete->AddTypeMembers(typeInstance, false, true, filter, typeInstance, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wasFirstAdd = isFirstAdd;
|
||||||
|
if (isFirstAdd)
|
||||||
|
{
|
||||||
|
BfExprEvaluator exprEvaluator(mModule);
|
||||||
|
exprEvaluator.mFunctionBindResult = &addFunctionBindResult;
|
||||||
|
SizedArray<BfExpression*, 2> argExprs;
|
||||||
|
argExprs.push_back(elementExpr);
|
||||||
|
BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
|
||||||
|
BfResolvedArgs argValues(&sizedArgExprs);
|
||||||
|
exprEvaluator.ResolveArgValues(argValues);
|
||||||
|
exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, NULL);
|
||||||
|
|
||||||
|
if (addFunctionBindResult.mMethodInstance != NULL)
|
||||||
|
CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs);
|
||||||
|
|
||||||
|
isFirstAdd = false;
|
||||||
|
}
|
||||||
|
else if ((addFunctionBindResult.mMethodInstance == NULL) || (addFunctionBindResult.mMethodInstance->GetParamCount() == 0))
|
||||||
|
{
|
||||||
|
mModule->CreateValueFromExpression(elementExpr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto argValue = mModule->CreateValueFromExpression(elementExpr, addFunctionBindResult.mMethodInstance->GetParamType(0));
|
||||||
|
if ((argValue) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
||||||
|
{
|
||||||
|
SizedArray<BfIRValue, 2> irArgs;
|
||||||
|
PushThis(elementExpr, initValue, addFunctionBindResult.mMethodInstance, irArgs);
|
||||||
|
PushArg(argValue, irArgs);
|
||||||
|
for (int argIdx = (int)irArgs.size(); argIdx < (int)addFunctionBindResult.mIRArgs.size(); argIdx++)
|
||||||
|
irArgs.Add(addFunctionBindResult.mIRArgs[argIdx]);
|
||||||
|
CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, irArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wasValidInitKind = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasValidInitKind)
|
||||||
|
{
|
||||||
|
mModule->Fail("Invalid initializer member declarator", initExpr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mResult = initValue;
|
||||||
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::Visit(BfCollectionInitializerExpression* arrayInitExpr)
|
void BfExprEvaluator::Visit(BfCollectionInitializerExpression* arrayInitExpr)
|
||||||
{
|
{
|
||||||
mModule->Fail("Collection initializer not usable here", arrayInitExpr);
|
mModule->Fail("Collection initializer not usable here", arrayInitExpr);
|
||||||
|
@ -13369,7 +13474,6 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
}
|
}
|
||||||
curMethodState->AddScope(&scopeData);
|
curMethodState->AddScope(&scopeData);
|
||||||
curMethodState->mCurScope->mMixinDepth++;
|
curMethodState->mCurScope->mMixinDepth++;
|
||||||
curMethodState->mIsEmbedded = false;
|
|
||||||
// We can't flush scope state because we extend params in as arbitrary values
|
// We can't flush scope state because we extend params in as arbitrary values
|
||||||
mModule->NewScopeState(true, false);
|
mModule->NewScopeState(true, false);
|
||||||
|
|
||||||
|
|
|
@ -436,6 +436,7 @@ public:
|
||||||
virtual void Visit(BfBaseExpression* baseExpr) override;
|
virtual void Visit(BfBaseExpression* baseExpr) override;
|
||||||
virtual void Visit(BfMixinExpression* mixinExpr) override;
|
virtual void Visit(BfMixinExpression* mixinExpr) override;
|
||||||
virtual void Visit(BfSizedArrayCreateExpression* createExpr) override;
|
virtual void Visit(BfSizedArrayCreateExpression* createExpr) override;
|
||||||
|
virtual void Visit(BfInitializerExpression* initExpr) override;
|
||||||
virtual void Visit(BfCollectionInitializerExpression* initExpr) override;
|
virtual void Visit(BfCollectionInitializerExpression* initExpr) override;
|
||||||
virtual void Visit(BfTypeOfExpression* typeOfExpr) override;
|
virtual void Visit(BfTypeOfExpression* typeOfExpr) override;
|
||||||
virtual void Visit(BfSizeOfExpression* sizeOfExpr) override;
|
virtual void Visit(BfSizeOfExpression* sizeOfExpr) override;
|
||||||
|
|
|
@ -910,7 +910,6 @@ public:
|
||||||
BfIRBlock mIRExitBlock;
|
BfIRBlock mIRExitBlock;
|
||||||
BfBreakData* mBreakData;
|
BfBreakData* mBreakData;
|
||||||
int mBlockNestLevel; // 0 = top level
|
int mBlockNestLevel; // 0 = top level
|
||||||
bool mIsEmbedded; // Is an embedded statement (ie: if () stmt) not wrapped in a block
|
|
||||||
bool mIgnoreObjectAccessCheck;
|
bool mIgnoreObjectAccessCheck;
|
||||||
bool mDisableChecks;
|
bool mDisableChecks;
|
||||||
BfMixinState* mMixinState;
|
BfMixinState* mMixinState;
|
||||||
|
@ -970,7 +969,6 @@ public:
|
||||||
mInPostReturn = false;
|
mInPostReturn = false;
|
||||||
mCrossingMixin = false;
|
mCrossingMixin = false;
|
||||||
mNoBind = false;
|
mNoBind = false;
|
||||||
mIsEmbedded = false;
|
|
||||||
mIgnoreObjectAccessCheck = false;
|
mIgnoreObjectAccessCheck = false;
|
||||||
mDisableChecks = false;
|
mDisableChecks = false;
|
||||||
mInConditionalBlock = false;
|
mInConditionalBlock = false;
|
||||||
|
|
|
@ -1206,6 +1206,25 @@ void BfPrinter::Visit(BfSizedArrayCreateExpression* createExpr)
|
||||||
VisitChildWithPrecedingSpace(createExpr->mInitializer);
|
VisitChildWithPrecedingSpace(createExpr->mInitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfPrinter::Visit(BfInitializerExpression* initExpr)
|
||||||
|
{
|
||||||
|
Visit(initExpr->ToBase());
|
||||||
|
|
||||||
|
VisitChild(initExpr->mTarget);
|
||||||
|
ExpectSpace();
|
||||||
|
VisitChild(initExpr->mOpenBrace);
|
||||||
|
for (int i = 0; i < (int)initExpr->mValues.size(); i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
VisitChild(initExpr->mCommas[i - 1]);
|
||||||
|
ExpectSpace();
|
||||||
|
}
|
||||||
|
VisitChild(initExpr->mValues[i]);
|
||||||
|
}
|
||||||
|
VisitChild(initExpr->mCloseBrace);
|
||||||
|
}
|
||||||
|
|
||||||
void BfPrinter::Visit(BfCollectionInitializerExpression* initExpr)
|
void BfPrinter::Visit(BfCollectionInitializerExpression* initExpr)
|
||||||
{
|
{
|
||||||
Visit(initExpr->ToBase());
|
Visit(initExpr->ToBase());
|
||||||
|
|
|
@ -130,6 +130,7 @@ public:
|
||||||
virtual void Visit(BfBaseExpression* baseExpr) override;
|
virtual void Visit(BfBaseExpression* baseExpr) override;
|
||||||
virtual void Visit(BfMixinExpression* mixinExpr) override;
|
virtual void Visit(BfMixinExpression* mixinExpr) override;
|
||||||
virtual void Visit(BfSizedArrayCreateExpression* createExpr) override;
|
virtual void Visit(BfSizedArrayCreateExpression* createExpr) override;
|
||||||
|
virtual void Visit(BfInitializerExpression* initExpr) override;
|
||||||
virtual void Visit(BfCollectionInitializerExpression* initExpr) override;
|
virtual void Visit(BfCollectionInitializerExpression* initExpr) override;
|
||||||
virtual void Visit(BfTypeReference* typeRef) override;
|
virtual void Visit(BfTypeReference* typeRef) override;
|
||||||
virtual void Visit(BfNamedTypeReference* typeRef) override;
|
virtual void Visit(BfNamedTypeReference* typeRef) override;
|
||||||
|
|
|
@ -1750,7 +1750,11 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
else if (isDelegateBind)
|
else if (isDelegateBind)
|
||||||
exprLeft = CreateDelegateBindExpression(allocNode);
|
exprLeft = CreateDelegateBindExpression(allocNode);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
exprLeft = CreateObjectCreateExpression(allocNode);
|
exprLeft = CreateObjectCreateExpression(allocNode);
|
||||||
|
if (auto initExpr = TryCreateInitializerExpression(exprLeft))
|
||||||
|
exprLeft = initExpr;
|
||||||
|
}
|
||||||
|
|
||||||
if (token == BfToken_Append)
|
if (token == BfToken_Append)
|
||||||
{
|
{
|
||||||
|
@ -2642,6 +2646,8 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
else if (token == BfToken_LParen)
|
else if (token == BfToken_LParen)
|
||||||
{
|
{
|
||||||
exprLeft = CreateInvocationExpression(exprLeft, (CreateExprFlags)(createExprFlags & ~(CreateExprFlags_NoCast)));
|
exprLeft = CreateInvocationExpression(exprLeft, (CreateExprFlags)(createExprFlags & ~(CreateExprFlags_NoCast)));
|
||||||
|
if (auto initExpr = TryCreateInitializerExpression(exprLeft))
|
||||||
|
exprLeft = initExpr;
|
||||||
}
|
}
|
||||||
else if ((token == BfToken_LBracket) || (token == BfToken_QuestionLBracket))
|
else if ((token == BfToken_LBracket) || (token == BfToken_QuestionLBracket))
|
||||||
{
|
{
|
||||||
|
@ -6900,6 +6906,60 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target,
|
||||||
return invocationExpr;
|
return invocationExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfInitializerExpression * BfReducer::TryCreateInitializerExpression(BfExpression* target)
|
||||||
|
{
|
||||||
|
auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
|
||||||
|
if (block == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mVisitorPos.MoveNext();
|
||||||
|
|
||||||
|
auto initializerExpr = mAlloc->Alloc<BfInitializerExpression>();
|
||||||
|
ReplaceNode(target, initializerExpr);
|
||||||
|
initializerExpr->mTarget = target;
|
||||||
|
MEMBER_SET(initializerExpr, mOpenBrace, block->mOpenBrace);
|
||||||
|
|
||||||
|
SetAndRestoreValue<BfVisitorPos> prevVisitorPos(mVisitorPos, BfVisitorPos(block));
|
||||||
|
|
||||||
|
bool isDone = !mVisitorPos.MoveNext();
|
||||||
|
|
||||||
|
BfDeferredAstSizedArray<BfExpression*> values(initializerExpr->mValues, mAlloc);
|
||||||
|
BfDeferredAstSizedArray<BfTokenNode*> commas(initializerExpr->mCommas, mAlloc);
|
||||||
|
|
||||||
|
BfAstNode* nextNode = NULL;
|
||||||
|
while (!isDone)
|
||||||
|
{
|
||||||
|
BfAstNode* node = mVisitorPos.GetCurrent();
|
||||||
|
|
||||||
|
auto expr = CreateExpression(node);
|
||||||
|
isDone = !mVisitorPos.MoveNext();
|
||||||
|
if (expr != NULL)
|
||||||
|
values.Add(expr);
|
||||||
|
|
||||||
|
if (!isDone)
|
||||||
|
{
|
||||||
|
bool foundComma = false;
|
||||||
|
|
||||||
|
node = mVisitorPos.GetCurrent();
|
||||||
|
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(node))
|
||||||
|
{
|
||||||
|
if (tokenNode->mToken == BfToken_Comma)
|
||||||
|
{
|
||||||
|
foundComma = true;
|
||||||
|
commas.Add(tokenNode);
|
||||||
|
mVisitorPos.MoveNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mVisitorPos.Trim();
|
||||||
|
|
||||||
|
MEMBER_SET(initializerExpr, mCloseBrace, block->mCloseBrace);
|
||||||
|
|
||||||
|
return initializerExpr;
|
||||||
|
}
|
||||||
|
|
||||||
BfDelegateBindExpression* BfReducer::CreateDelegateBindExpression(BfAstNode* allocNode)
|
BfDelegateBindExpression* BfReducer::CreateDelegateBindExpression(BfAstNode* allocNode)
|
||||||
{
|
{
|
||||||
auto delegateBindExpr = mAlloc->Alloc<BfDelegateBindExpression>();
|
auto delegateBindExpr = mAlloc->Alloc<BfDelegateBindExpression>();
|
||||||
|
@ -8606,15 +8666,16 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
|
||||||
|
|
||||||
if (typeRef == NULL)
|
if (typeRef == NULL)
|
||||||
{
|
{
|
||||||
auto typeIdentifierNode = ExpectIdentifierAfter(nameAfterNode, "parameter type");
|
auto nextNode = mVisitorPos.GetNext();
|
||||||
if (typeIdentifierNode == NULL)
|
if (nextNode == NULL)
|
||||||
{
|
{
|
||||||
mVisitorPos.mReadPos = paramStartReadPos;
|
FailAfter("Type expected", nameAfterNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mVisitorPos.MoveNext();
|
||||||
|
|
||||||
typeRef = CreateTypeRef(typeIdentifierNode);
|
typeRef = CreateTypeRef(nextNode);
|
||||||
if (typeRef == NULL)
|
if (typeRef == NULL)
|
||||||
{
|
{
|
||||||
mVisitorPos.mReadPos = paramStartReadPos;
|
mVisitorPos.mReadPos = paramStartReadPos;
|
||||||
|
|
|
@ -199,6 +199,7 @@ public:
|
||||||
BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode);
|
BfObjectCreateExpression* CreateObjectCreateExpression(BfAstNode* allocNode);
|
||||||
BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
|
BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
|
||||||
BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
|
BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
|
||||||
|
BfInitializerExpression* TryCreateInitializerExpression(BfExpression* target);
|
||||||
BfExpression* CreateIndexerExpression(BfExpression* target);
|
BfExpression* CreateIndexerExpression(BfExpression* target);
|
||||||
BfMemberReferenceExpression* CreateMemberReferenceExpression(BfAstNode* target);
|
BfMemberReferenceExpression* CreateMemberReferenceExpression(BfAstNode* target);
|
||||||
BfTupleExpression* CreateTupleExpression(BfTokenNode* newNode, BfExpression* innerExpr = NULL);
|
BfTupleExpression* CreateTupleExpression(BfTokenNode* newNode, BfExpression* innerExpr = NULL);
|
||||||
|
|
|
@ -3092,7 +3092,6 @@ void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEval
|
||||||
{
|
{
|
||||||
bool isIgnore = mBfIRBuilder->mIgnoreWrites;
|
bool isIgnore = mBfIRBuilder->mIgnoreWrites;
|
||||||
|
|
||||||
SetAndRestoreValue<bool> prevEmbedded(mCurMethodState->mIsEmbedded, block == NULL);
|
|
||||||
mCurMethodState->mInHeadScope = false;
|
mCurMethodState->mInHeadScope = false;
|
||||||
|
|
||||||
BfScopeData scopeData;
|
BfScopeData scopeData;
|
||||||
|
@ -3122,7 +3121,14 @@ void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEval
|
||||||
VisitCodeBlock(block);
|
VisitCodeBlock(block);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (auto varDecl = BfNodeDynCast<BfVariableDeclaration>(stmt))
|
||||||
|
{
|
||||||
|
Fail("Variable declarations must be wrapped in a block statement", varDecl);
|
||||||
|
}
|
||||||
|
|
||||||
VisitChild(stmt);
|
VisitChild(stmt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((block != NULL) && (closeBrace != NULL))
|
if ((block != NULL) && (closeBrace != NULL))
|
||||||
|
@ -3720,9 +3726,6 @@ void BfModule::Visit(BfVariableDeclaration* varDecl)
|
||||||
|
|
||||||
UpdateSrcPos(varDecl);
|
UpdateSrcPos(varDecl);
|
||||||
|
|
||||||
if (mCurMethodState->mIsEmbedded)
|
|
||||||
Fail("Variable declarations must be wrapped in a block statement", varDecl);
|
|
||||||
|
|
||||||
BfTupleExpression* tupleVariableDeclaration = BfNodeDynCast<BfTupleExpression>(varDecl->mNameNode);
|
BfTupleExpression* tupleVariableDeclaration = BfNodeDynCast<BfTupleExpression>(varDecl->mNameNode);
|
||||||
if (tupleVariableDeclaration != NULL)
|
if (tupleVariableDeclaration != NULL)
|
||||||
{
|
{
|
||||||
|
|
44
IDEHelper/Tests/src/Initializers.bf
Normal file
44
IDEHelper/Tests/src/Initializers.bf
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Tests
|
||||||
|
{
|
||||||
|
class Initializers
|
||||||
|
{
|
||||||
|
struct StructA
|
||||||
|
{
|
||||||
|
public int mA = 123;
|
||||||
|
public int mB;
|
||||||
|
public int mC;
|
||||||
|
public int mD;
|
||||||
|
|
||||||
|
public int ValC
|
||||||
|
{
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
mC = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(float val, float? val2 = 234) mut
|
||||||
|
{
|
||||||
|
mD += (int)val;
|
||||||
|
mD += (int)val2 * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(int val)
|
||||||
|
{
|
||||||
|
Test.FatalError("Shouldn't be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public static void TestBasics()
|
||||||
|
{
|
||||||
|
StructA sa = .() { mB = 345, ValC = 456, 567.8f, 789};
|
||||||
|
Test.Assert(sa.mA == 123);
|
||||||
|
Test.Assert(sa.mB == 345);
|
||||||
|
Test.Assert(sa.mC == 456);
|
||||||
|
Test.Assert(sa.mD == 6036);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -263,12 +263,21 @@ namespace Tests
|
||||||
const String cStr1 = "A" + "B";
|
const String cStr1 = "A" + "B";
|
||||||
const String cStr2 = cStr1 + "C" + cStrD;
|
const String cStr2 = cStr1 + "C" + cStrD;
|
||||||
Test.Assert(cStr2 == "ABCD");
|
Test.Assert(cStr2 == "ABCD");
|
||||||
|
Test.Assert(cStr2 === "ABCD");
|
||||||
|
|
||||||
const char8* cStr3 = "A" + "B";
|
const char8* cStr3 = "A" + "B";
|
||||||
const char8* cStr4 = cStr1 + "C" + cStrPD;
|
const char8* cStr4 = cStr1 + "C" + cStrPD;
|
||||||
Test.Assert(StringView(cStr4) == "ABCD");
|
Test.Assert(StringView(cStr4) == "ABCD");
|
||||||
|
|
||||||
TestDefaults();
|
TestDefaults();
|
||||||
|
|
||||||
|
String strA = scope String("ABCD");
|
||||||
|
Test.Assert(strA == cStr2);
|
||||||
|
Test.Assert(strA !== cStr1);
|
||||||
|
|
||||||
|
let strTup = (strA, strA);
|
||||||
|
Test.Assert(strTup == (cStr2, cStr2));
|
||||||
|
Test.Assert(strTup !== (cStr2, cStr2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TTo Convert<TFrom, TTo>(TFrom val) where TTo : operator explicit TFrom
|
public static TTo Convert<TFrom, TTo>(TFrom val) where TTo : operator explicit TFrom
|
||||||
|
|
|
@ -6,6 +6,12 @@ namespace Tests
|
||||||
{
|
{
|
||||||
class Tuples
|
class Tuples
|
||||||
{
|
{
|
||||||
|
public static void Add(ref (int32, float) val)
|
||||||
|
{
|
||||||
|
val.0 += 100;
|
||||||
|
val.1 += 200;
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasic()
|
public static void TestBasic()
|
||||||
{
|
{
|
||||||
|
@ -21,6 +27,9 @@ namespace Tests
|
||||||
|
|
||||||
let v0 = tVal1.0;
|
let v0 = tVal1.0;
|
||||||
Test.Assert(v0 == 2);
|
Test.Assert(v0 == 2);
|
||||||
|
|
||||||
|
Add(ref tVal1);
|
||||||
|
Test.Assert(tVal1 == (a: 102, b: 203));
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValClass
|
class ValClass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue