mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Added support for indexer in initializer expression, reeval Add calls
This commit is contained in:
parent
ac6f58f118
commit
596dd2401d
7 changed files with 85 additions and 66 deletions
|
@ -11544,8 +11544,6 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
|||
|
||||
BfTypedValue initValue = GetResult(true);
|
||||
bool isFirstAdd = true;
|
||||
BfFunctionBindResult addFunctionBindResult;
|
||||
addFunctionBindResult.mWantsArgs = true;
|
||||
|
||||
for (auto elementExpr : initExpr->mValues)
|
||||
{
|
||||
|
@ -11604,6 +11602,26 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
|||
findName.c_str()), identifierNode);
|
||||
}
|
||||
}
|
||||
else if (auto indexerExpression = BfNodeDynCast<BfIndexerExpression>(assignExpr->mLeft))
|
||||
{
|
||||
if (indexerExpression->mTarget == NULL)
|
||||
{
|
||||
if ((initValue.mType->IsValueType()) && (!initValue.IsAddr()))
|
||||
{
|
||||
initValue = mModule->MakeAddressable(initValue, true, true);
|
||||
}
|
||||
|
||||
mResult = BfTypedValue();
|
||||
HandleIndexerExpression(indexerExpression, initValue);
|
||||
wasValidInitKind = true;
|
||||
|
||||
if ((mPropDef) || (mResult))
|
||||
{
|
||||
PerformAssignment(assignExpr, true, BfTypedValue());
|
||||
mResult = BfTypedValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -11622,40 +11640,13 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
|||
}
|
||||
}
|
||||
|
||||
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, BfResolveArgsFlag_DeferParamEval);
|
||||
exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, BfMethodGenericArguments());
|
||||
|
||||
if (addFunctionBindResult.mMethodInstance != NULL)
|
||||
CreateCall(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs);
|
||||
|
||||
isFirstAdd = false;
|
||||
}
|
||||
else if ((addFunctionBindResult.mMethodInstance == NULL) || (addFunctionBindResult.mMethodInstance->GetParamCount() == 0))
|
||||
{
|
||||
mModule->CreateValueFromExpression(elementExpr, NULL, (BfEvalExprFlags)(mBfEvalExprFlags& BfEvalExprFlags_InheritFlags));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto argValue = mModule->CreateValueFromExpression(elementExpr, addFunctionBindResult.mMethodInstance->GetParamType(0), (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags));
|
||||
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(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, irArgs);
|
||||
}
|
||||
}
|
||||
BfExprEvaluator exprEvaluator(mModule);
|
||||
SizedArray<BfExpression*, 2> argExprs;
|
||||
argExprs.push_back(elementExpr);
|
||||
BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
|
||||
BfResolvedArgs argValues(&sizedArgExprs);
|
||||
exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
|
||||
exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, BfMethodGenericArguments());
|
||||
|
||||
wasValidInitKind = true;
|
||||
}
|
||||
|
@ -21664,30 +21655,38 @@ void BfExprEvaluator::Visit(BfMemberReferenceExpression* memberRefExpr)
|
|||
|
||||
void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
||||
{
|
||||
BfTypedValue target;
|
||||
HandleIndexerExpression(indexerExpr, BfTypedValue());
|
||||
}
|
||||
|
||||
void BfExprEvaluator::HandleIndexerExpression(BfIndexerExpression* indexerExpr, BfTypedValue target)
|
||||
{
|
||||
bool wantStatic = false;
|
||||
// Try first as a non-static indexer, then as a static indexer
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
///
|
||||
{
|
||||
SetAndRestoreValue<BfEvalExprFlags> prevFlags(mBfEvalExprFlags, (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_NoLookupError | BfEvalExprFlags_AllowBase), pass == 0);
|
||||
VisitChild(indexerExpr->mTarget);
|
||||
}
|
||||
ResolveGenericType();
|
||||
target = GetResult(true);
|
||||
if (target)
|
||||
break;
|
||||
|
||||
if (pass == 0)
|
||||
if (!target)
|
||||
{
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, (mModule->mIgnoreErrors) || (pass == 0));
|
||||
auto staticType = mModule->ResolveTypeRef(indexerExpr->mTarget, {});
|
||||
if (staticType != NULL)
|
||||
///
|
||||
{
|
||||
wantStatic = true;
|
||||
target.mType = staticType;
|
||||
SetAndRestoreValue<BfEvalExprFlags> prevFlags(mBfEvalExprFlags, (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_NoLookupError | BfEvalExprFlags_AllowBase), pass == 0);
|
||||
VisitChild(indexerExpr->mTarget);
|
||||
}
|
||||
ResolveGenericType();
|
||||
target = GetResult(true);
|
||||
if (target)
|
||||
break;
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, (mModule->mIgnoreErrors) || (pass == 0));
|
||||
auto staticType = mModule->ResolveTypeRef(indexerExpr->mTarget, {});
|
||||
if (staticType != NULL)
|
||||
{
|
||||
wantStatic = true;
|
||||
target.mType = staticType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -538,6 +538,7 @@ public:
|
|||
void CheckDotToken(BfTokenNode* tokenNode);
|
||||
void DoMemberReference(BfMemberReferenceExpression* memberRefExpr, BfTypedValue* outCascadeValue);
|
||||
void CreateObject(BfObjectCreateExpression* objCreateExpr, BfAstNode* allocNode, BfType* allocType);
|
||||
void HandleIndexerExpression(BfIndexerExpression* indexerExpr, BfTypedValue target);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -2093,7 +2093,12 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
|||
}
|
||||
else if (token == BfToken_LBracket)
|
||||
{
|
||||
exprLeft = CreateAttributedExpression(tokenNode, false);
|
||||
if ((createExprFlags & CreateExprFlags_AllowAnonymousIndexer) != 0)
|
||||
{
|
||||
exprLeft = CreateIndexerExpression(NULL, tokenNode);
|
||||
}
|
||||
else
|
||||
exprLeft = CreateAttributedExpression(tokenNode, false);
|
||||
}
|
||||
else if (token == BfToken_FatArrow)
|
||||
{
|
||||
|
@ -7570,7 +7575,7 @@ BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfAstNode* ta
|
|||
BfAstNode* node = mVisitorPos.GetCurrent();
|
||||
initializerExpr->mSrcEnd = node->mSrcEnd;
|
||||
|
||||
auto expr = CreateExpression(node);
|
||||
auto expr = CreateExpression(node, BfReducer::CreateExprFlags_AllowAnonymousIndexer);
|
||||
isDone = !mVisitorPos.MoveNext();
|
||||
if (expr != NULL)
|
||||
values.Add(expr);
|
||||
|
@ -8167,15 +8172,24 @@ BfObjectCreateExpression* BfReducer::CreateObjectCreateExpression(BfAstNode* all
|
|||
return objectCreateExpr;
|
||||
}
|
||||
|
||||
BfExpression* BfReducer::CreateIndexerExpression(BfExpression* target)
|
||||
BfExpression* BfReducer::CreateIndexerExpression(BfExpression* target, BfTokenNode* openBracketNode)
|
||||
{
|
||||
auto tokenNode = ExpectTokenAfter(target, BfToken_LBracket, BfToken_QuestionLBracket);
|
||||
auto tokenNode = openBracketNode;
|
||||
if (openBracketNode == NULL)
|
||||
tokenNode = ExpectTokenAfter(target, BfToken_LBracket, BfToken_QuestionLBracket);
|
||||
|
||||
auto indexerExpr = mAlloc->Alloc<BfIndexerExpression>();
|
||||
BfDeferredAstSizedArray<BfExpression*> arguments(indexerExpr->mArguments, mAlloc);
|
||||
BfDeferredAstSizedArray<BfTokenNode*> commas(indexerExpr->mCommas, mAlloc);
|
||||
indexerExpr->mTarget = target;
|
||||
ReplaceNode(target, indexerExpr);
|
||||
if (target != NULL)
|
||||
{
|
||||
indexerExpr->mTarget = target;
|
||||
ReplaceNode(target, indexerExpr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplaceNode(openBracketNode, indexerExpr);
|
||||
}
|
||||
|
||||
indexerExpr->mOpenBracket = tokenNode;
|
||||
MoveNode(indexerExpr->mOpenBracket, indexerExpr);
|
||||
|
|
|
@ -27,7 +27,8 @@ public:
|
|||
CreateExprFlags_NoCheckBinOpPrecedence = 0x100,
|
||||
CreateExprFlags_BreakOnCascade = 0x200,
|
||||
CreateExprFlags_EarlyExit = 0x400, // Don't attempt binary or ternary operations
|
||||
CreateExprFlags_AllowEmpty = 0x800
|
||||
CreateExprFlags_AllowEmpty = 0x800,
|
||||
CreateExprFlags_AllowAnonymousIndexer = 0x1000
|
||||
};
|
||||
|
||||
enum CreateStmtFlags
|
||||
|
@ -206,7 +207,7 @@ public:
|
|||
BfScopedInvocationTarget* CreateScopedInvocationTarget(BfAstNode*& targetRef, BfTokenNode* colonToken);
|
||||
BfInvocationExpression* CreateInvocationExpression(BfAstNode* target, CreateExprFlags createExprFlags = CreateExprFlags_None);
|
||||
BfInitializerExpression* TryCreateInitializerExpression(BfAstNode* target);
|
||||
BfExpression* CreateIndexerExpression(BfExpression* target);
|
||||
BfExpression* CreateIndexerExpression(BfExpression* target, BfTokenNode* openBracketNode = NULL);
|
||||
BfMemberReferenceExpression* CreateMemberReferenceExpression(BfAstNode* target);
|
||||
BfTupleExpression* CreateTupleExpression(BfTokenNode* newNode, BfExpression* innerExpr = NULL);
|
||||
BfExpression* CreateExpression(BfAstNode* node, CreateExprFlags createExprFlags = CreateExprFlags_None);
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace System.Collections
|
|||
}
|
||||
}
|
||||
|
||||
extension Dictionary<K, V>
|
||||
extension Dictionary<TKey, TValue>
|
||||
{
|
||||
public static bool operator==(Self lhs, Self rhs)
|
||||
{
|
||||
|
|
|
@ -420,6 +420,10 @@ namespace Tests
|
|||
list.Sort();
|
||||
List<float> floatList = scope .() {1, 2, 3};
|
||||
|
||||
Dictionary<int, String> dict = scope .() { (1, "Foo"), [2]="Bar" };
|
||||
Test.Assert(dict[1] == "Foo");
|
||||
Test.Assert(dict[2] == "Bar");
|
||||
|
||||
ClassA ca = scope .();
|
||||
ClassB cb = scope .();
|
||||
Test.Assert(LibA.LibA0.GetVal(ca) == 123);
|
||||
|
|
|
@ -25,9 +25,9 @@ namespace Tests
|
|||
mD += (int)val2 * 10;
|
||||
}
|
||||
|
||||
public void Add(int val)
|
||||
public void Add(int val) mut
|
||||
{
|
||||
Test.FatalError("Shouldn't be called");
|
||||
mD += (int)val * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace Tests
|
|||
Test.Assert(sa.mA == 123);
|
||||
Test.Assert(sa.mB == 345);
|
||||
Test.Assert(sa.mC == 456);
|
||||
Test.Assert(sa.mD == 6036);
|
||||
Test.Assert(sa.mD == 791907);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue