diff --git a/IDEHelper/Backend/BeContext.h b/IDEHelper/Backend/BeContext.h index 83e9f5e8..6b82a9d1 100644 --- a/IDEHelper/Backend/BeContext.h +++ b/IDEHelper/Backend/BeContext.h @@ -202,7 +202,7 @@ class BeFunctionType : public BeType public: String mName; BeType* mReturnType; - std::vector mParams; + Array mParams; bool mIsVarArg; virtual void HashContent(BeHashContext& hashCtx) override diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 7dae4675..3a37b134 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -1935,7 +1935,7 @@ void BeIRCodeGen::HandleNextCmd() } break; case BfIRCmd_CreateFunctionType: - { + { CMD_PARAM(BeType*, resultType); CMD_PARAM(CmdParamVec, paramTypes); CMD_PARAM(bool, isVarArg); diff --git a/IDEHelper/Backend/BeModule.cpp b/IDEHelper/Backend/BeModule.cpp index 0a190e6e..306f923a 100644 --- a/IDEHelper/Backend/BeModule.cpp +++ b/IDEHelper/Backend/BeModule.cpp @@ -1960,6 +1960,14 @@ String BeModule::ToString(BeFunction* wantFunc) dc.mSeenNames[param.mName] = 0; str += "%" + param.mName; } + + if (funcType->mIsVarArg) + { + if (!funcType->mParams.IsEmpty()) + str += ", "; + str += "..."; + } + str += ")"; if (func->mAlwaysInline) @@ -2917,6 +2925,14 @@ void BeModule::ToString(StringImpl& str, BeType* type) str += ", "; ToString(str, funcType->mParams[paramIdx].mType); } + + if (funcType->mIsVarArg) + { + if (!funcType->mParams.IsEmpty()) + str += ", "; + str += "..."; + } + str += ")"; return; } diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 01a324e6..26498a77 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -211,7 +211,7 @@ void BfStructuralVisitor::Visit(BfQualifiedTypeReference* qualifiedTypeRef) Visit(qualifiedTypeRef->ToBase()); } -void BfStructuralVisitor::Visit(BfDotTypeReference * typeRef) +void BfStructuralVisitor::Visit(BfDotTypeReference* typeRef) { Visit(typeRef->ToBase()); } @@ -1411,6 +1411,8 @@ const char* Beefy::BfTokenToString(BfToken token) return "."; case BfToken_DotDot: return ".."; + case BfToken_DotDotDot: + return "..."; case BfToken_QuestionDot: return "?."; case BfToken_QuestionLBracket: diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 4fd8660a..4065fcfb 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -215,6 +215,7 @@ enum BfToken : uint8 BfToken_Comma, BfToken_Dot, BfToken_DotDot, + BfToken_DotDotDot, BfToken_QuestionDot, BfToken_QuestionLBracket, BfToken_AutocompleteDot, diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index f7f30c20..ec823f97 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -597,7 +597,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio bool didDefaultsError = false; bool hadParams = false; bool hasDefault = false; - for (int paramIdx = 0; paramIdx < (int) methodDeclaration->mParams.size(); paramIdx++) + for (int paramIdx = 0; paramIdx < (int)methodDeclaration->mParams.size(); paramIdx++) { BfParameterDeclaration* paramDecl = methodDeclaration->mParams[paramIdx]; @@ -612,6 +612,17 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio else // paramDef->mParamKind = BfParamKind_Params; + if (auto dotTypeRef = BfNodeDynCast(paramDef->mTypeRef)) + { + if (dotTypeRef->mDotToken->mToken == BfToken_DotDotDot) + { + if (paramIdx == (int)methodDeclaration->mParams.size() - 1) + paramDef->mParamKind = BfParamKind_VarArgs; + else + Fail("Varargs specifier must be the last parameter", methodDef->mParams[paramIdx - 1]->mParamDeclaration); + } + } + if (paramDef->mParamDeclaration != NULL) { if (paramDef->mParamKind == BfParamKind_Params) @@ -622,7 +633,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio { methodDef->mParams[paramIdx - 1]->mParamKind = BfParamKind_Normal; hadParams = false; - Fail("Params parameter must be the last parameter", methodDef->mParams[paramIdx - 1]->mParamDeclaration); + Fail("Params parameter must be the last parameter", methodDef->mParams[paramIdx - 1]->mParamDeclaration); } if (paramDef->mParamDeclaration->mInitializer != NULL) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 2e40bb92..9df71f8c 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -1434,12 +1434,12 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che } } } - - //TODO: Does this ever get hit? - // Not enough arguments? + + // Too many arguments (not all incoming arguments processed) if (argIdx < (int)mArguments.size()) { - goto NoMatch; + if (!methodInstance->IsVarArgs()) + goto NoMatch; } if ((genericArgumentsSubstitute != NULL) && (genericArgumentsSubstitute->size() != 0)) @@ -4431,8 +4431,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV argIdx++; } + int paramCount = methodInstance->GetParamCount(); + for ( ; argIdx < (int)irArgs.size(); /*argIdx++*/) - { + { + if (argIdx >= paramCount) + break; + auto _HandleParamType = [&] (BfType* paramType) { if (paramType->IsStruct()) @@ -4986,6 +4991,31 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu if (paramIdx >= (int)methodInstance->GetParamCount()) { + if (methodInstance->IsVarArgs()) + { + if (argIdx >= (int)argValues.size()) + break; + + BfTypedValue argValue = ResolveArgValue(argValues[argIdx], NULL); + if (argValue) + { + auto typeInst = argValue.mType->ToTypeInstance(); + + if (argValue.mType == mModule->GetPrimitiveType(BfTypeCode_Single)) + argValue = mModule->Cast(argValues[argIdx].mExpression, argValue, mModule->GetPrimitiveType(BfTypeCode_Double)); + + if ((typeInst != NULL) && (typeInst->mTypeDef == mModule->mCompiler->mStringTypeDef)) + { + BfType* charType = mModule->GetPrimitiveType(BfTypeCode_Char8); + BfType* charPtrType = mModule->CreatePointerType(charType); + argValue = mModule->Cast(argValues[argIdx].mExpression, argValue, charPtrType); + } + PushArg(argValue, irArgs, true, false); + } + argIdx++; + continue; + } + if (argIdx < (int)argValues.size()) { BfAstNode* errorRef = argValues[argIdx].mExpression; @@ -5632,41 +5662,10 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType BfEvalExprFlags flags = BfEvalExprFlags_NoCast; if ((paramKind == BfParamKind_Params) || (paramKind == BfParamKind_DelegateParam)) flags = (BfEvalExprFlags)(flags | BfEvalExprFlags_AllowParamsExpr); -// if ((mModule->mCurMethodInstance->mHadGenericDelegateParams) && (!mModule->mCurMethodInstance->mIsUnspecialized)) -// flags = (BfEvalExprFlags)(flags | BfEvalExprFlags_AllowParamsExpr); argValue = mModule->CreateValueFromExpression(exprEvaluator, expr, wantType, flags); -// if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0) -// { -// if ((mModule->mCurMethodState != NULL) && (exprEvaluator.mResultLocalVar != NULL) && (exprEvaluator.mResultLocalVarRefNode != NULL)) -// { -// auto localVar = exprEvaluator.mResultLocalVar; -// int fieldIdx = mResultLocalVarField - 1; -// auto methodState = mModule->mCurMethodState->GetMethodStateForLocal(localVar); -// if (localVar->mCompositeCount >= 0) -// { -// for (int compositeIdx = 0; compositeIdx < localVar->mCompositeCount; compositeIdx++) -// { -// BfResolvedArg compositeResolvedArg; -// auto compositeLocalVar = methodState->mLocals[localVar->mLocalVarIdx + compositeIdx + 1]; -// auto argValue = exprEvaluator.LoadLocal(compositeLocalVar); -// if (argValue) -// { -// if (argValue.mType->IsRef()) -// argValue.mKind = BfTypedValueKind_Value; -// else if (!argValue.mType->IsStruct()) -// argValue = mModule->LoadValue(argValue, NULL, exprEvaluator.mIsVolatileReference); -// } -// resolvedArg.mTypedValue = argValue; -// resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_FromParamComposite); -// return resolvedArg.mTypedValue; -// } -// } -// } -// } - - if ((argValue) && (argValue.mType != wantType)) + if ((argValue) && (argValue.mType != wantType) && (wantType != NULL)) { if ((mDeferScopeAlloc != NULL) && (wantType == mModule->mContext->mBfObjectType)) { @@ -5686,7 +5685,7 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType auto expr = BfNodeDynCast(resolvedArg.mExpression); BF_ASSERT(expr != NULL); argValue = mModule->CreateValueFromExpression(expr, wantType, (BfEvalExprFlags)(BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr)); - if (argValue) + if ((argValue) && (wantType != NULL)) argValue = mModule->Cast(expr, argValue, wantType); } else if ((resolvedArg.mArgFlags & (BfArgFlag_UntypedDefault)) != 0) @@ -5748,8 +5747,6 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType CheckVariableDeclaration(resolvedArg.mExpression, false, false, false); argValue = BfTypedValue(localVar->mAddr, mModule->CreateRefType(variableType, BfRefType::RefKind_Out)); - - //argValue = mModule->GetDefaultTypedValue(wantType); } return argValue; } diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index b6ee184b..1fd7ec05 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -4257,7 +4257,7 @@ BfIRFunctionType BfIRBuilder::MapMethod(BfMethodInstance* methodInstance) SizedArray paramTypes; methodInstance->GetIRFunctionInfo(mModule, retType, paramTypes); - auto funcType = CreateFunctionType(retType, paramTypes, false); + auto funcType = CreateFunctionType(retType, paramTypes, methodInstance->IsVarArgs()); if (useCache) mMethodTypeMap[methodInstance] = funcType; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 35b3666d..5f28ed57 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -8794,6 +8794,11 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr if (mCompiler->IsSkippingExtraResolveChecks()) return BfIRValue(); + if (methodInstance->mMethodDef->mName == "Check") + { + NOP; + } + if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface()) { //BF_ASSERT(!methodInstance->mIRFunction); @@ -8841,7 +8846,7 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr BfIRType returnType; SizedArray paramTypes; methodInstance->GetIRFunctionInfo(this, returnType, paramTypes); - auto funcType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes); + auto funcType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, methodInstance->IsVarArgs()); auto func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName); auto callingConv = GetIRCallingConvention(methodInstance); @@ -13859,7 +13864,7 @@ BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, b SizedArray paramTypes; methodInstance->GetIRFunctionInfo(this, returnType, paramTypes); - BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, false); + BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, methodInstance->IsVarArgs()); auto ptrType = mBfIRBuilder->GetPointerTo(externFunctionType); BfIRValue initVal; @@ -13907,14 +13912,14 @@ void BfModule::CreateDllImportMethod() BfIRType returnType; SizedArray paramTypes; - mCurMethodInstance->GetIRFunctionInfo(this, returnType, paramTypes); + mCurMethodInstance->GetIRFunctionInfo(this, returnType, paramTypes, mCurMethodInstance->IsVarArgs()); SizedArray args; for (int i = 0; i < (int)paramTypes.size(); i++) args.push_back(mBfIRBuilder->GetArgument(i)); - BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, false); + BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, mCurMethodInstance->IsVarArgs()); if (isHotCompile) { @@ -18115,7 +18120,7 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth BfIRFunctionType funcType; auto voidType = GetPrimitiveType(BfTypeCode_None); SizedArray paramTypes; - funcType = mBfIRBuilder->CreateFunctionType(mBfIRBuilder->MapType(voidType), paramTypes, false); + funcType = mBfIRBuilder->CreateFunctionType(mBfIRBuilder->MapType(voidType), paramTypes, methodInstance->IsVarArgs()); mBfIRBuilder->SaveDebugLocation(); auto prevInsertBlock = mBfIRBuilder->GetInsertBlock(); @@ -19229,6 +19234,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool if (hadParams) break; + if ((paramDef != NULL) && (paramDef->mParamKind == BfParamKind_VarArgs)) + continue; + if ((paramDef != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (paramDef->mParamKind != BfParamKind_AppendIdx)) mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(paramDef->mTypeRef, false); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index e1fb624a..f3833f18 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -6470,7 +6470,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula if (auto dotType = BfNodeDynCastExact(typeRef)) { - Fail("Invalid use of '.'", typeRef); + Fail(StrFormat("Invalid use of '%s'", BfTokenToString(dotType->mDotToken->mToken)), typeRef); return NULL; } diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index 15016b4a..ea3db6a3 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -2068,10 +2068,20 @@ void BfParser::NextToken(int endIdx) case '.': if (mSrc[mSrcIdx] == '.') { - mSrcIdx++; - mTokenEnd = mSrcIdx; - mToken = BfToken_DotDot; - mSyntaxToken = BfSyntaxToken_Token; + if (mSrc[mSrcIdx + 1] == '.') + { + mSrcIdx += 2; + mTokenEnd = mSrcIdx; + mToken = BfToken_DotDotDot; + mSyntaxToken = BfSyntaxToken_Token; + } + else + { + mSrcIdx++; + mTokenEnd = mSrcIdx; + mToken = BfToken_DotDot; + mSyntaxToken = BfSyntaxToken_Token; + } } else { diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 9b4c0587..b2fd1791 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -4440,13 +4440,21 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF { int token = tokenNode->GetToken(); if (token == BfToken_Dot) + { + auto dotTypeRef = mAlloc->Alloc(); + ReplaceNode(firstNode, dotTypeRef); + dotTypeRef->mDotToken = tokenNode; + firstNode = dotTypeRef; + isHandled = true; + } + else if (token == BfToken_DotDotDot) { auto dotTypeRef = mAlloc->Alloc(); ReplaceNode(firstNode, dotTypeRef); dotTypeRef->mDotToken = tokenNode; firstNode = dotTypeRef; isHandled = true; - //return dotTypeRef; + return dotTypeRef; } else if ((token == BfToken_Star) && (mAllowTypeWildcard)) { @@ -8402,7 +8410,8 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImplGetToken(); if ((token == BfToken_Var) || (token == BfToken_LParen) || - (token == BfToken_Delegate) || (token == BfToken_Function)) + (token == BfToken_Delegate) || (token == BfToken_Function) || + (token == BfToken_DotDotDot)) { mVisitorPos.MoveNext(); typeRef = CreateTypeRef(tokenNode); @@ -8517,6 +8527,9 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImplmToken == BfToken_DotDotDot)) + continue; + bool allowNameFail = false; bool nextIsName = false; auto afterNameTokenNode = BfNodeDynCast(mVisitorPos.Get(mVisitorPos.mReadPos + 2)); diff --git a/IDEHelper/Compiler/BfReducer.h b/IDEHelper/Compiler/BfReducer.h index 68e1846f..8c260c8e 100644 --- a/IDEHelper/Compiler/BfReducer.h +++ b/IDEHelper/Compiler/BfReducer.h @@ -215,8 +215,7 @@ public: BfTypeReference* DoCreateTypeRef(BfAstNode* identifierNode, CreateTypeRefFlags createTypeRefFlags = CreateTypeRefFlags_None); BfTypeReference* CreateTypeRef(BfAstNode* identifierNode, CreateTypeRefFlags createTypeRefFlags = CreateTypeRefFlags_None); BfTypeReference* CreateTypeRefAfter(BfAstNode* astNode, CreateTypeRefFlags createTypeRefFlags = CreateTypeRefFlags_None); - BfTypeReference* CreateRefTypeRef(BfTypeReference* elementType, BfTokenNode* refToken); - BfTypeReference* CreateConstTypeRef(BfTypeReference* elementType, BfTokenNode* refToken); + BfTypeReference* CreateRefTypeRef(BfTypeReference* elementType, BfTokenNode* refToken); bool ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayImpl* params, SizedArrayImpl* commas, bool alwaysIncludeBlock = false); BfGenericArgumentsNode* CreateGenericArguments(BfTokenNode* tokenNode); BfGenericParamsDeclaration* CreateGenericParamsDeclaration(BfTokenNode* tokenNode); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 3017b2d4..db268e7d 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -628,6 +628,13 @@ bool BfMethodInstance::IsSkipCall(bool bypassVirtual) return false; } +bool BfMethodInstance::IsVarArgs() +{ + if (mMethodDef->mParams.IsEmpty()) + return false; + return mMethodDef->mParams.back()->mParamKind == BfParamKind_VarArgs; +} + bool BfMethodInstance::AlwaysInline() { return mAlwaysInline; @@ -855,12 +862,7 @@ int BfMethodInstance::DbgGetVirtualMethodNum() } void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl& paramTypes, bool forceStatic) -{ - if ((mMethodDef->mNoSplat) && (GetOwner()->GetLoweredType() != BfTypeCode_None)) - { - NOP; - } - +{ module->PopulateType(mReturnType); if (mReturnType->IsValuelessType()) { @@ -904,7 +906,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, else { checkType = GetParamType(paramIdx); - } + } if ((paramIdx != -1) || (!mMethodDef->mNoSplat && !mMethodDef->mIsMutating)) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 1c44a34a..ec6445f8 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -810,6 +810,7 @@ public: bool HasSelf(); bool IsAutocompleteMethod() { /*return mIdHash == -1;*/ return mIsAutocompleteMethod; } bool IsSkipCall(bool bypassVirtual = false); + bool IsVarArgs(); bool AlwaysInline(); BfImportCallKind GetImportCallKind(); bool IsTestMethod(); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index baae4286..e553aaff 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -456,6 +456,7 @@ enum BfParamKind : uint8 BfParamKind_DelegateParam, BfParamKind_ImplicitCapture, BfParamKind_AppendIdx, + BfParamKind_VarArgs }; class BfParameterDef