mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Named arguments
This commit is contained in:
parent
d204922403
commit
79320652e3
15 changed files with 341 additions and 37 deletions
|
@ -1017,6 +1017,77 @@ namespace IDE.ui
|
|||
if (cursorSection >= textSections.Count - 1)
|
||||
cursorSection = textSections.Count - 2;
|
||||
|
||||
if (cursorSection < mAutoComplete.mInvokeSrcPositions.Count)
|
||||
{
|
||||
var argText = mAutoComplete.mTargetEditWidget.mEditWidgetContent.ExtractString(mAutoComplete.mInvokeSrcPositions[cursorSection - 1],
|
||||
mAutoComplete.mInvokeSrcPositions[cursorSection] - mAutoComplete.mInvokeSrcPositions[cursorSection - 1], .. scope .());
|
||||
|
||||
int colonPos = argText.IndexOf(':');
|
||||
|
||||
if (colonPos != -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
bool foundSep = false;
|
||||
int nameStart = -1;
|
||||
for (int i = colonPos - 1; i >= 0; i--)
|
||||
{
|
||||
char8 c = argText[i];
|
||||
if (nameStart == -1)
|
||||
{
|
||||
if ((c != '_') && (!c.IsLetterOrDigit))
|
||||
nameStart = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!c.IsWhiteSpace)
|
||||
{
|
||||
if ((!foundSep) &&
|
||||
((c == ',') || (c == '(')))
|
||||
foundSep = true;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nameStart == -1)
|
||||
break;
|
||||
|
||||
var argParamName = argText.Substring(nameStart, colonPos - nameStart);
|
||||
for (int checkSectionIdx = 1; checkSectionIdx < textSections.Count; checkSectionIdx++)
|
||||
{
|
||||
var sectionStr = textSections[checkSectionIdx];
|
||||
|
||||
var checkParamName = sectionStr;
|
||||
if (checkParamName.EndsWith(','))
|
||||
checkParamName.RemoveFromEnd(1);
|
||||
|
||||
for (int checkIdx = checkParamName.Length - 1; checkIdx >= 0; checkIdx--)
|
||||
{
|
||||
char8 c = checkParamName[checkIdx];
|
||||
if (c.IsWhiteSpace)
|
||||
{
|
||||
checkParamName.RemoveFromStart(checkIdx + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkParamName == argParamName)
|
||||
{
|
||||
cursorSection = checkSectionIdx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if ((argText.StartsWith('(')) || (argText.StartsWith(',')))
|
||||
argText.Remove(0, 1);
|
||||
argText.Trim();
|
||||
Debug.WriteLine($"ArgText: {argText}");*/
|
||||
}
|
||||
|
||||
float paramX = 0;
|
||||
for (int sectionIdx = 0; sectionIdx < textSections.Count; sectionIdx++)
|
||||
{
|
||||
|
|
|
@ -141,6 +141,11 @@ void BfStructuralVisitor::Visit(BfExpressionStatement* exprStmt)
|
|||
Visit(exprStmt->ToBase());
|
||||
}
|
||||
|
||||
void BfStructuralVisitor::Visit(BfNamedExpression* namedExpr)
|
||||
{
|
||||
Visit(namedExpr->ToBase());
|
||||
}
|
||||
|
||||
void BfStructuralVisitor::Visit(BfAttributedExpression* attribExpr)
|
||||
{
|
||||
Visit(attribExpr->ToBase());
|
||||
|
|
|
@ -278,6 +278,7 @@ class BfStatement;
|
|||
class BfLabelableStatement;
|
||||
class BfExpression;
|
||||
class BfExpressionStatement;
|
||||
class BfNamedExpression;
|
||||
class BfAttributedExpression;
|
||||
class BfAttributedStatement;
|
||||
class BfLiteralExpression;
|
||||
|
@ -447,6 +448,7 @@ public:
|
|||
virtual void Visit(BfLabeledBlock* labeledBlock);
|
||||
virtual void Visit(BfExpression* expr);
|
||||
virtual void Visit(BfExpressionStatement* exprStmt);
|
||||
virtual void Visit(BfNamedExpression* namedExpr);
|
||||
virtual void Visit(BfAttributedExpression* attribExpr);
|
||||
virtual void Visit(BfStatement* stmt);
|
||||
virtual void Visit(BfAttributedStatement* attribStmt);
|
||||
|
@ -2812,6 +2814,16 @@ public:
|
|||
BfFieldDtorDeclaration* mDtor;
|
||||
}; BF_AST_DECL(BfLambdaBindExpression, BfExpression);
|
||||
|
||||
class BfNamedExpression : public BfExpression
|
||||
{
|
||||
public:
|
||||
BF_AST_TYPE(BfNamedExpression, BfExpression);
|
||||
|
||||
BfIdentifierNode* mNameNode;
|
||||
BfTokenNode* mColonToken;
|
||||
BfExpression* mExpression;
|
||||
}; BF_AST_DECL(BfNamedExpression, BfExpression);
|
||||
|
||||
class BfAttributedExpression : public BfExpression
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -13,6 +13,12 @@ BfDeferEvalChecker::BfDeferEvalChecker()
|
|||
|
||||
void BfDeferEvalChecker::Check(BfAstNode* node)
|
||||
{
|
||||
if (auto namedNode = BfNodeDynCastExact<BfNamedExpression>(node))
|
||||
node = namedNode->mExpression;
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
SetAndRestoreValue<BfAstNode*> rootNode(mRootNode, node);
|
||||
node->Accept(this);
|
||||
}
|
||||
|
@ -22,6 +28,11 @@ void BfDeferEvalChecker::Visit(BfAstNode* attribExpr)
|
|||
mNeedsDeferEval = false;
|
||||
}
|
||||
|
||||
void BfDeferEvalChecker::Visit(BfAttributedExpression* attributedExpr)
|
||||
{
|
||||
VisitChild(attributedExpr->mExpression);
|
||||
}
|
||||
|
||||
void BfDeferEvalChecker::Visit(BfInitializerExpression* collectionInitExpr)
|
||||
{
|
||||
VisitChild(collectionInitExpr->mTarget);
|
||||
|
|
|
@ -19,8 +19,9 @@ public:
|
|||
void Check(BfAstNode* node);
|
||||
|
||||
virtual void Visit(BfAstNode* node) override;
|
||||
|
||||
virtual void Visit(BfInitializerExpression* collectionInitExpr);
|
||||
|
||||
virtual void Visit(BfAttributedExpression* attributedExpr) override;
|
||||
virtual void Visit(BfInitializerExpression* collectionInitExpr) override;
|
||||
virtual void Visit(BfLiteralExpression* literalExpr) override;
|
||||
virtual void Visit(BfCastExpression* castExpr) override;
|
||||
virtual void Visit(BfParenthesizedExpression* parenExpr) override;
|
||||
|
|
|
@ -185,6 +185,15 @@ void BfElementVisitor::Visit(BfExpressionStatement* exprStmt)
|
|||
VisitChild(exprStmt->mExpression);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfNamedExpression* namedExpr)
|
||||
{
|
||||
Visit(namedExpr->ToBase());
|
||||
|
||||
VisitChild(namedExpr->mNameNode);
|
||||
VisitChild(namedExpr->mColonToken);
|
||||
VisitChild(namedExpr->mExpression);
|
||||
}
|
||||
|
||||
void BfElementVisitor::Visit(BfAttributedExpression* attribExpr)
|
||||
{
|
||||
Visit(attribExpr->ToBase());
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
virtual void Visit(BfLabeledBlock* labeledBlock);
|
||||
virtual void Visit(BfExpression* expr);
|
||||
virtual void Visit(BfExpressionStatement* exprStmt);
|
||||
virtual void Visit(BfNamedExpression* namedExpr);
|
||||
virtual void Visit(BfAttributedExpression* attribExpr);
|
||||
virtual void Visit(BfStatement* stmt);
|
||||
virtual void Visit(BfAttributedStatement* attribStmt);
|
||||
|
|
|
@ -173,6 +173,7 @@ void BfMethodMatcher::Init(const BfMethodGenericArguments& methodGenericArgument
|
|||
mSelfType = NULL;
|
||||
mMethodType = BfMethodType_Normal;
|
||||
mCheckReturnType = NULL;
|
||||
mHasArgNames = false;
|
||||
mHadExplicitGenericArguments = false;
|
||||
mHadOpenGenericArguments = methodGenericArguments.mIsOpen;
|
||||
mHadPartialGenericArguments = methodGenericArguments.mIsPartial;
|
||||
|
@ -206,6 +207,9 @@ void BfMethodMatcher::Init(const BfMethodGenericArguments& methodGenericArgument
|
|||
mHasVarArguments = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg.mNameNode != NULL)
|
||||
mHasArgNames = true;
|
||||
}
|
||||
|
||||
if (methodGenericArguments.mArguments != NULL)
|
||||
|
@ -1644,7 +1648,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
|||
// because on structs we know the exact type
|
||||
if ((checkMethod->mIsOverride) && (!mBypassVirtual) && (!typeInstance->IsValueType()))
|
||||
return false;
|
||||
|
||||
|
||||
mMethodCheckCount++;
|
||||
|
||||
BfMethodInstance* methodInstance = mModule->GetRawMethodInstance(typeInstance, checkMethod);
|
||||
|
@ -1741,6 +1745,40 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
|||
goto NoMatch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mHasArgNames)
|
||||
{
|
||||
checkMethod->BuildParamNameMap();
|
||||
|
||||
bool prevWasNull = false;
|
||||
for (int argIdx = (int)mArguments.mSize - 1; argIdx >= 0; argIdx--)
|
||||
{
|
||||
auto& arg = mArguments[argIdx];
|
||||
if (arg.mNameNode != NULL)
|
||||
{
|
||||
if (prevWasNull)
|
||||
{
|
||||
if (argIdx >= checkMethod->mParams.mSize)
|
||||
goto NoMatch;
|
||||
if (checkMethod->mParams[argIdx]->mName != arg.mNameNode->ToStringView())
|
||||
goto NoMatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!checkMethod->mParamNameMap->ContainsKey(arg.mNameNode->ToStringView()))
|
||||
goto NoMatch;
|
||||
}
|
||||
|
||||
prevWasNull = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevWasNull = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto& checkGenericArgRef : mCheckMethodGenericArguments)
|
||||
checkGenericArgRef = NULL;
|
||||
|
@ -3364,6 +3402,12 @@ void BfExprEvaluator::Visit(BfAttributedExpression* attribExpr)
|
|||
mModule->FinishAttributeState(&attributeState);
|
||||
}
|
||||
|
||||
void BfExprEvaluator::Visit(BfNamedExpression* namedExpr)
|
||||
{
|
||||
if (namedExpr->mExpression != NULL)
|
||||
VisitChild(namedExpr->mExpression);
|
||||
}
|
||||
|
||||
void BfExprEvaluator::Visit(BfBlock* blockExpr)
|
||||
{
|
||||
if (mModule->mCurMethodState == NULL)
|
||||
|
@ -5753,6 +5797,12 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
|||
bool handled = false;
|
||||
bool evaluated = false;
|
||||
|
||||
if (auto namedExpression = BfNodeDynCastExact<BfNamedExpression>(argExpr))
|
||||
{
|
||||
resolvedArg.mNameNode = namedExpression->mNameNode;
|
||||
argExpr = namedExpression->mExpression;
|
||||
}
|
||||
|
||||
if (auto interpolateExpr = BfNodeDynCastExact<BfStringInterpolationExpression>(argExpr))
|
||||
{
|
||||
if ((interpolateExpr->mAllocNode == NULL) || ((flags & BfResolveArgsFlag_InsideStringInterpolationAlloc) != 0))
|
||||
|
@ -7308,6 +7358,81 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
return mModule->GetDefaultTypedValue(returnType);
|
||||
}
|
||||
|
||||
bool hasNamedArgs = false;
|
||||
for (auto& arg : argValues)
|
||||
if (arg.mNameNode != NULL)
|
||||
hasNamedArgs = true;
|
||||
if (hasNamedArgs)
|
||||
{
|
||||
methodDef->BuildParamNameMap();
|
||||
|
||||
BfIdentifierNode* outOfPlaceName = NULL;
|
||||
int curParamIdx = 0;
|
||||
|
||||
SizedArrayImpl<BfResolvedArg> origArgValues = argValues;
|
||||
argValues.Clear();
|
||||
|
||||
for (int argIdx = 0; argIdx < origArgValues.mSize; argIdx++)
|
||||
{
|
||||
int paramIdx = curParamIdx;
|
||||
|
||||
auto& argValue = origArgValues[argIdx];
|
||||
if (argValue.mNameNode != NULL)
|
||||
{
|
||||
int namedParamIdx = -1;
|
||||
if (methodDef->mParamNameMap->TryGetValue(argValue.mNameNode->ToStringView(), &namedParamIdx))
|
||||
{
|
||||
paramIdx = namedParamIdx;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
{
|
||||
mModule->Fail(StrFormat("The best overload for '%s' does not have a parameter named '%s'", methodInstance->mMethodDef->mName.c_str(),
|
||||
argValue.mNameNode->ToString().c_str()), argValue.mNameNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (paramIdx != curParamIdx)
|
||||
outOfPlaceName = argValue.mNameNode;
|
||||
}
|
||||
else if (outOfPlaceName != NULL)
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
mModule->Fail(StrFormat("Named argument '%s' is used out-of-position but is followed by an unnamed argument", outOfPlaceName->ToString().c_str()), outOfPlaceName);
|
||||
outOfPlaceName = NULL;
|
||||
}
|
||||
|
||||
if ((paramIdx < methodInstance->GetParamCount()) && (paramIdx != argIdx))
|
||||
{
|
||||
if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Normal)
|
||||
{
|
||||
auto wantType = methodInstance->GetParamType(paramIdx);
|
||||
auto resolvedValue = ResolveArgValue(argValue, wantType);
|
||||
if (resolvedValue)
|
||||
{
|
||||
argValue.mTypedValue = resolvedValue;
|
||||
argValue.mArgFlags = (BfArgFlags)(argValue.mArgFlags | BfArgFlag_Finalized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (paramIdx >= argValues.mSize)
|
||||
argValues.Add(BfResolvedArg());
|
||||
if (argValues[paramIdx].mExpression != NULL)
|
||||
{
|
||||
if (argValue.mNameNode != NULL)
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
mModule->Fail(StrFormat("Named argument '%s' cannot be specified multiple times", argValue.mNameNode->ToString().c_str()), argValue.mNameNode);
|
||||
}
|
||||
}
|
||||
argValues[paramIdx] = argValue;
|
||||
|
||||
curParamIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
int argIdx = 0;
|
||||
int paramIdx = 0;
|
||||
|
||||
|
@ -7608,7 +7733,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
mModule->Warn(BfWarning_BF4205_StringInterpolationParam, "Expanded string interpolation argument not used as 'params'. If string allocation was intended then consider adding a specifier such as 'scope'.", errorRef);
|
||||
}
|
||||
|
||||
if ((arg == NULL) && (argValues[argExprIdx].mExpression != NULL))
|
||||
|
||||
// if ((arg == NULL) && (argValues[argExprIdx].mExpression != NULL))
|
||||
// hadMissingArg = true;
|
||||
|
||||
if ((arg == NULL) && (!argValues[argExprIdx].mTypedValue))
|
||||
hadMissingArg = true;
|
||||
}
|
||||
else
|
||||
|
@ -7710,7 +7839,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
if (mModule->PreFail())
|
||||
{
|
||||
if (error == NULL)
|
||||
error = mModule->Fail(StrFormat("Not enough parameters specified, expected %d more.", methodInstance->GetParamCount() - paramIdx), refNode);
|
||||
{
|
||||
if (hasNamedArgs)
|
||||
error = mModule->Fail(StrFormat("There is no argument given that corresponds to the required formal parameter '%s' of '%s'.",
|
||||
methodInstance->GetParamName(paramIdx).c_str(), mModule->MethodToString(methodInstance).c_str()), refNode);
|
||||
else
|
||||
error = mModule->Fail(StrFormat("Not enough parameters specified, expected %d more.", methodInstance->GetParamCount() - paramIdx), refNode);
|
||||
}
|
||||
if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL))
|
||||
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
|
||||
}
|
||||
|
@ -8439,6 +8574,9 @@ static int sInvocationIdx = 0;
|
|||
BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType* wantType, BfTypedValue* receivingValue, BfParamKind paramKind, BfIdentifierNode* paramNameNode)
|
||||
{
|
||||
BfTypedValue argValue = resolvedArg.mTypedValue;
|
||||
if ((resolvedArg.mArgFlags & BfArgFlag_Finalized) != 0)
|
||||
return argValue;
|
||||
|
||||
if ((resolvedArg.mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval)) != 0)
|
||||
{
|
||||
if ((!argValue) || (argValue.mValue.IsFake()) || (resolvedArg.mWantsRecalc))
|
||||
|
|
|
@ -22,7 +22,8 @@ enum BfArgFlags
|
|||
BfArgFlag_StringInterpolateFormat = 0x800,
|
||||
BfArgFlag_StringInterpolateArg = 0x1000,
|
||||
BfArgFlag_Cascade = 0x2000,
|
||||
BfArgFlag_Volatile = 0x8000
|
||||
BfArgFlag_Volatile = 0x8000,
|
||||
BfArgFlag_Finalized = 0x10000,
|
||||
};
|
||||
|
||||
enum BfResolveArgsFlags
|
||||
|
@ -58,6 +59,7 @@ class BfResolvedArg
|
|||
public:
|
||||
BfTypedValue mTypedValue;
|
||||
BfTypedValue mUncastedTypedValue;
|
||||
BfIdentifierNode* mNameNode;
|
||||
BfType* mResolvedType;
|
||||
BfAstNode* mExpression;
|
||||
BfArgFlags mArgFlags;
|
||||
|
@ -68,6 +70,7 @@ public:
|
|||
public:
|
||||
BfResolvedArg()
|
||||
{
|
||||
mNameNode = NULL;
|
||||
mResolvedType = NULL;
|
||||
mExpression = NULL;
|
||||
mArgFlags = BfArgFlag_None;
|
||||
|
@ -211,6 +214,7 @@ public:
|
|||
BfType* mCheckReturnType;
|
||||
BfMethodType mMethodType;
|
||||
BfCheckedKind mCheckedKind;
|
||||
bool mHasArgNames;
|
||||
bool mHadExplicitGenericArguments;
|
||||
bool mHadOpenGenericArguments;
|
||||
bool mHadPartialGenericArguments;
|
||||
|
@ -243,7 +247,7 @@ public:
|
|||
BfTypeVector mBestMethodGenericArguments;
|
||||
BfTypeVector mExplicitMethodGenericArguments;
|
||||
bool mFakeConcreteTarget;
|
||||
Array<BfAmbiguousEntry> mAmbiguousEntries;
|
||||
Array<BfAmbiguousEntry> mAmbiguousEntries;
|
||||
|
||||
public:
|
||||
BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute, BfType *origCheckType = NULL, BfResolveArgFlags flags = BfResolveArgFlag_None);
|
||||
|
@ -534,6 +538,7 @@ public:
|
|||
virtual void Visit(BfErrorNode* errorNode) override;
|
||||
virtual void Visit(BfTypeReference* typeRef) override;
|
||||
virtual void Visit(BfAttributedExpression* attribExpr) override;
|
||||
virtual void Visit(BfNamedExpression* namedExpr) override;
|
||||
virtual void Visit(BfBlock* blockExpr) override;
|
||||
virtual void Visit(BfVariableDeclaration* varDecl) override;
|
||||
virtual void Visit(BfCaseExpression* caseExpr) override;
|
||||
|
|
|
@ -1033,6 +1033,16 @@ void BfPrinter::Visit(BfExpressionStatement* exprStmt)
|
|||
VisitChild(exprStmt->mTrailingSemicolon);
|
||||
}
|
||||
|
||||
void BfPrinter::Visit(BfNamedExpression* namedExpr)
|
||||
{
|
||||
Visit(namedExpr->ToBase());
|
||||
|
||||
VisitChild(namedExpr->mNameNode);
|
||||
VisitChild(namedExpr->mColonToken);
|
||||
ExpectSpace();
|
||||
VisitChild(namedExpr->mExpression);
|
||||
}
|
||||
|
||||
void BfPrinter::Visit(BfAttributedExpression* attribExpr)
|
||||
{
|
||||
Visit(attribExpr->ToBase());
|
||||
|
|
|
@ -128,6 +128,7 @@ public:
|
|||
virtual void Visit(BfNewNode * newNode) override;
|
||||
virtual void Visit(BfExpression* expr) override;
|
||||
virtual void Visit(BfExpressionStatement* exprStmt) override;
|
||||
virtual void Visit(BfNamedExpression* namedExpr) override;
|
||||
virtual void Visit(BfAttributedExpression* attribExpr) override;
|
||||
virtual void Visit(BfStatement* stmt) override;
|
||||
virtual void Visit(BfLabelableStatement* labelableStmt) override;
|
||||
|
|
|
@ -5806,6 +5806,8 @@ BfTokenNode* BfReducer::ReadArguments(BfAstNode* parentNode, BfAstNode* afterNod
|
|||
}
|
||||
}
|
||||
|
||||
BfExpression* argumentExpr = NULL;
|
||||
|
||||
if (allowSkippedArgs)
|
||||
{
|
||||
auto nextNode = mVisitorPos.GetNext();
|
||||
|
@ -5824,9 +5826,33 @@ BfTokenNode* BfReducer::ReadArguments(BfAstNode* parentNode, BfAstNode* afterNod
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto identifierNode = BfNodeDynCastExact<BfIdentifierNode>(nextNode))
|
||||
{
|
||||
if (auto nextNextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2)))
|
||||
{
|
||||
if (nextNextToken->mToken == BfToken_Colon)
|
||||
{
|
||||
auto namedExpr = mAlloc->Alloc<BfNamedExpression>();
|
||||
ReplaceNode(identifierNode, namedExpr);
|
||||
MEMBER_SET(namedExpr, mNameNode, identifierNode);
|
||||
MEMBER_SET(namedExpr, mColonToken, nextNextToken)
|
||||
mVisitorPos.MoveNext();
|
||||
mVisitorPos.MoveNext();
|
||||
|
||||
auto innerExpr = CreateExpressionAfter(namedExpr, CreateExprFlags_AllowVariableDecl);
|
||||
if (innerExpr != NULL)
|
||||
{
|
||||
MEMBER_SET(namedExpr, mExpression, innerExpr);
|
||||
}
|
||||
argumentExpr = namedExpr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto argumentExpr = CreateExpressionAfter(afterNode, CreateExprFlags_AllowVariableDecl);
|
||||
if (argumentExpr == NULL)
|
||||
argumentExpr = CreateExpressionAfter(afterNode, CreateExprFlags_AllowVariableDecl);
|
||||
if ((argumentExpr != NULL) || (endToken != BfToken_None))
|
||||
arguments->push_back(argumentExpr);
|
||||
if (argumentExpr == NULL)
|
||||
|
@ -7409,32 +7435,6 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target,
|
|||
{
|
||||
if (nextToken->GetToken() == BfToken_Colon)
|
||||
{
|
||||
/*auto scopedInvocationTarget = mAlloc->Alloc<BfScopedInvocationTarget>();
|
||||
ReplaceNode(invocationExpr->mTarget, scopedInvocationTarget);
|
||||
scopedInvocationTarget->mTarget = invocationExpr->mTarget;
|
||||
invocationExpr->mTarget = scopedInvocationTarget;
|
||||
MEMBER_SET(scopedInvocationTarget, mColonToken, nextToken);
|
||||
|
||||
mVisitorPos.MoveNext();
|
||||
if (auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()))
|
||||
{
|
||||
if ((nextToken->GetToken() == BfToken_Colon) || (nextToken->GetToken() == BfToken_Mixin))
|
||||
{
|
||||
MEMBER_SET(scopedInvocationTarget, mScopeName, nextToken);
|
||||
mVisitorPos.MoveNext();
|
||||
}
|
||||
}
|
||||
else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(mVisitorPos.GetNext()))
|
||||
{
|
||||
MEMBER_SET(scopedInvocationTarget, mScopeName, identifier);
|
||||
mVisitorPos.MoveNext();
|
||||
}
|
||||
|
||||
if (scopedInvocationTarget->mScopeName == NULL)
|
||||
{
|
||||
FailAfter("Expected scope name", scopedInvocationTarget);
|
||||
}*/
|
||||
|
||||
auto scopedInvocationTarget = CreateScopedInvocationTarget(invocationExpr->mTarget, nextToken);
|
||||
invocationExpr->SetSrcEnd(scopedInvocationTarget->GetSrcEnd());
|
||||
}
|
||||
|
|
|
@ -542,6 +542,7 @@ void BfMethodDef::FreeMembers()
|
|||
for (auto genericParam : mGenericParams)
|
||||
delete genericParam;
|
||||
mGenericParams.Clear();
|
||||
delete mParamNameMap;
|
||||
}
|
||||
|
||||
BfMethodDeclaration* BfMethodDef::GetMethodDeclaration()
|
||||
|
@ -660,6 +661,16 @@ int BfMethodDef::GetExplicitParamCount()
|
|||
return (int)mParams.size();
|
||||
}
|
||||
|
||||
void BfMethodDef::BuildParamNameMap()
|
||||
{
|
||||
if (mParamNameMap != NULL)
|
||||
return;
|
||||
|
||||
mParamNameMap = new Dictionary<StringView, int>();
|
||||
for (int i = 0; i < mParams.mSize; i++)
|
||||
(*mParamNameMap)[mParams[i]->mName] = i;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
void BfTypeDef::Reset()
|
||||
|
|
|
@ -873,6 +873,7 @@ public:
|
|||
Array<BfParameterDef*> mParams;
|
||||
Array<BfGenericParamDef*> mGenericParams;
|
||||
Array<BfExternalConstraintDef> mExternalConstraints;
|
||||
Dictionary<StringView, int>* mParamNameMap;
|
||||
BfMethodDef* mNextWithSameName;
|
||||
Val128 mFullHash;
|
||||
|
||||
|
@ -934,8 +935,8 @@ public:
|
|||
mAddedAfterEmit = false;
|
||||
mBody = NULL;
|
||||
mExplicitInterface = NULL;
|
||||
mReturnTypeRef = NULL;
|
||||
mMethodDeclaration = NULL;
|
||||
mReturnTypeRef = NULL;
|
||||
mMethodDeclaration = NULL;
|
||||
mCodeChanged = false;
|
||||
mWantsBody = true;
|
||||
mCommutableKind = BfCommutableKind_None;
|
||||
|
@ -944,7 +945,8 @@ public:
|
|||
mMethodType = BfMethodType_Normal;
|
||||
mCallingConvention = BfCallingConvention_Unspecified;
|
||||
mHasAppend = false;
|
||||
mAlwaysInline = false;
|
||||
mAlwaysInline = false;
|
||||
mParamNameMap = NULL;
|
||||
mNextWithSameName = NULL;
|
||||
}
|
||||
|
||||
|
@ -965,6 +967,7 @@ public:
|
|||
bool IsCtorOrInit();
|
||||
String ToString();
|
||||
int GetExplicitParamCount();
|
||||
void BuildParamNameMap();
|
||||
};
|
||||
|
||||
class BfOperatorDef : public BfMethodDef
|
||||
|
|
|
@ -182,6 +182,24 @@ namespace Tests
|
|||
saPtr.mA += 1000;
|
||||
}
|
||||
|
||||
static int Named(int p1, float p2, int p3)
|
||||
{
|
||||
return 10000 + p1*100 + (int)p2*10 + p3;
|
||||
}
|
||||
|
||||
static int Named(int p0, int p1, float p2)
|
||||
{
|
||||
return 20000 + p0*100 + p1*10 + (.)p2;
|
||||
}
|
||||
|
||||
static int Named(int p0=1, int p1=2, double p2=3)
|
||||
{
|
||||
return 30000 + p0*100 + p1*10 + (.)p2;
|
||||
}
|
||||
|
||||
static int sIdx = 0;
|
||||
static int GetNext() => ++sIdx;
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
@ -239,6 +257,14 @@ namespace Tests
|
|||
Test.Assert(sa4.mA == 400);
|
||||
InStructA(sa4);
|
||||
Test.Assert(sa4.mA == 1400);
|
||||
|
||||
Test.Assert(Named(1, 2, p3:3) == 10123);
|
||||
Test.Assert(Named(p1: 1, 2, p3: 3) == 10123);
|
||||
Test.Assert(Named(p0: 1, 2, 3) == 20123);
|
||||
Test.Assert(Named(1, p1:2, 3) == 20123);
|
||||
Test.Assert(Named(p3:GetNext(), p2:GetNext(), p1:GetNext()) == 10321);
|
||||
Test.Assert(Named(p2:GetNext(), p1:GetNext(), p0:GetNext()) == 20654);
|
||||
Test.Assert(Named(p1:9) == 30193);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue