diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index e294bdce..792b0ed8 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -984,7 +984,12 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array& test { for (int defaultIdx = 0; defaultIdx < (int)methodInstance->mDefaultValues.size(); defaultIdx++) { - irArgs.Add(methodInstance->mDefaultValues[defaultIdx]); + auto castedVal = bfModule->Cast(methodInstance->mMethodDef->GetRefNode(), methodInstance->mDefaultValues[defaultIdx], methodInstance->GetParamType(defaultIdx)); + if (castedVal) + { + BfExprEvaluator exprEvaluator(bfModule); + exprEvaluator.PushArg(castedVal, irArgs); + } } } } diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 70a7f91f..4753e722 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -264,6 +264,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch } } + BfTypedValue argValue; BfAstNode* argExpr = NULL; if (argIdx < (int)arguments.size()) { @@ -314,28 +315,25 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch } auto foreignDefaultVal = methodInstance->mDefaultValues[argIdx]; - auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(methodInstance->mDefaultValues[argIdx]); - auto constVal = mModule->ConstantToCurrent(foreignConst, methodInstance->GetOwner()->mConstHolder, wantType); - llvmArgs.push_back(constVal); - argIdx++; - paramIdx++; - continue; + auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(foreignDefaultVal.mValue); + argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, foreignDefaultVal.mType); } - auto argValue = arguments[argIdx].mTypedValue; - - auto& arg = arguments[argIdx]; - if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0) + if ((!argValue) && (argIdx < arguments.size())) { - mExpectingType = arg.mExpectedType; - if (mExpectingType == NULL) - mExpectingType = wantType; + argValue = arguments[argIdx].mTypedValue; + auto& arg = arguments[argIdx]; + if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0) + { + mExpectingType = arg.mExpectedType; + if (mExpectingType == NULL) + mExpectingType = wantType; - if (auto expr = BfNodeDynCast(argExpr)) - argValue = Resolve(expr, mExpectingType); - arg.mArgFlags = BfArgFlag_None; + if (auto expr = BfNodeDynCast(argExpr)) + argValue = Resolve(expr, mExpectingType); + arg.mArgFlags = BfArgFlag_None; + } } - if (!argValue) return BfTypedValue(); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index d004ebfd..3464a78d 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -5324,7 +5324,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu hadMissingArg = true; BfTypedValue argValue; - + if (hadMissingArg) { if (expandedParamsArray) @@ -5417,7 +5417,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu } auto foreignDefaultVal = methodInstance->mDefaultValues[argIdx]; - auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(methodInstance->mDefaultValues[argIdx]); + auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(foreignDefaultVal.mValue); if (foreignConst->mConstType == BfConstType_AggZero) { @@ -5433,7 +5433,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu if (!argValue) { - argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, wantType); + argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, foreignDefaultVal.mType); if (!argValue) mModule->Fail("Default parameter value failed", targetSrc); } @@ -5500,15 +5500,19 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu failed = true; } - if ((argValue) && (arg != NULL)) + if (argValue) { + BfAstNode* refNode = arg; + if (refNode == NULL) + refNode = targetSrc; + if (mModule->mCurMethodState != NULL) { SetAndRestoreValue prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData); - argValue = mModule->Cast(arg, argValue, wantType); + argValue = mModule->Cast(refNode, argValue, wantType); } else - argValue = mModule->Cast(arg, argValue, wantType); + argValue = mModule->Cast(refNode, argValue, wantType); if (!argValue) { @@ -5806,7 +5810,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou auto intPtrRefType = mModule->CreateRefType(intPtrType); if (target.mValue.IsFake()) { - resolvedArg.mTypedValue = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), intPtrType); + resolvedArg.mTypedValue = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), intPtrRefType); } else { @@ -6163,10 +6167,22 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp // NOP; // } + bool prevAllowVariableDeclarations = true; + if (mModule->mCurMethodState != NULL) + { + // Don't allow variable declarations in arguments for this method call + prevAllowVariableDeclarations = mModule->mCurMethodState->mCurScope->mAllowVariableDeclarations; + mModule->mCurMethodState->mCurScope->mAllowVariableDeclarations = false; + } + defer + ( + if (mModule->mCurMethodState != NULL) + mModule->mCurMethodState->mCurScope->mAllowVariableDeclarations = prevAllowVariableDeclarations; + ); + // Temporarily disable so we don't capture calls in params SetAndRestoreValue prevBindResult(mFunctionBindResult, NULL); - SetAndRestoreValue prevAllowVariableDeclarations(mModule->mCurMethodState->mCurScope->mAllowVariableDeclarations, false); // Don't allow variable declarations in arguments - + sInvocationIdx++; bool wantCtor = methodName.IsEmpty(); @@ -12243,7 +12259,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, { BfTypedValue constExprVal; constExprVal.mType = genericParam->mTypeConstraint; - auto constant = curTypeInst->mConstHolder->GetConstant(defaultVal); + auto constant = curTypeInst->mConstHolder->GetConstant(defaultVal.mValue); constExprVal.mValue = mModule->ConstantToCurrent(constant, curTypeInst->mConstHolder, genericParam->mTypeConstraint); genericArg = mModule->CreateConstExprValueType(constExprVal); } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index feb28ce3..ed22586a 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -14797,7 +14797,7 @@ void BfModule::EmitCtorBody(bool& skipBody) { auto localVar = mCurMethodState->GetRootMethodState()->mLocals[1]; BF_ASSERT(localVar->mName == "appendIdx"); - auto intRefType = CreateRefType(localVar->mResolvedType); + auto intRefType = localVar->mResolvedType; appendIdxVal = BfTypedValue(localVar->mValue, intRefType); mCurMethodState->mCurAppendAlign = 1; // Don't make any assumptions about how the base leaves the alignment } @@ -19599,10 +19599,10 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { BF_ASSERT(defaultValue.mValue.IsConst()); while ((int)mCurMethodInstance->mDefaultValues.size() < paramDefIdx) - mCurMethodInstance->mDefaultValues.Add(BfIRValue()); + mCurMethodInstance->mDefaultValues.Add(BfTypedValue()); CurrentAddToConstHolder(defaultValue.mValue); - mCurMethodInstance->mDefaultValues.Add(defaultValue.mValue); + mCurMethodInstance->mDefaultValues.Add(defaultValue); } } } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index ca29c457..7e8fdf61 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -752,7 +752,7 @@ public: BfMethodDef* mMethodDef; BfType* mReturnType; Array mParams; - Array mDefaultValues; // ConstIdx + Array mDefaultValues; BfModule* mDeclModule; BfMethodProcessRequest* mMethodProcessRequest; BfMethodInfoEx* mMethodInfoEx; diff --git a/IDEHelper/Tests/src/Defaults.bf b/IDEHelper/Tests/src/Defaults.bf new file mode 100644 index 00000000..288b49e7 --- /dev/null +++ b/IDEHelper/Tests/src/Defaults.bf @@ -0,0 +1,47 @@ +using System; + +namespace Tests +{ + class Defaults + { + struct StructA + { + public int mA = 123; + public int mB = 234; + + public static implicit operator StructA(float f) + { + StructA val = .(); + val.mA = (.)f; + return val; + } + + public static implicit operator StructA(float[2] f) + { + StructA val = default; + val.mA = (.)f[0]; + val.mB = (.)f[1]; + return val; + } + } + + public static int Default0(StructA sa = 45.6f) + { + return sa.mA + sa.mB * 1000; + } + + public static int Default1(StructA sa = float[2](12.3f, 23.4f)) + { + return sa.mA + sa.mB * 1000; + } + + [Test] + public static void CheckBasics() + { + int val = Default0(); + Test.Assert(val == 23012); + val = Default1(); + Test.Assert(val == 23012); + } + } +}