mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Improved param defaults, allowing for implicit cast operators
This commit is contained in:
parent
ea072ad77b
commit
5bbffe268b
6 changed files with 98 additions and 32 deletions
|
@ -984,7 +984,12 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<BfExpression>(argExpr))
|
||||
argValue = Resolve(expr, mExpectingType);
|
||||
arg.mArgFlags = BfArgFlag_None;
|
||||
if (auto expr = BfNodeDynCast<BfExpression>(argExpr))
|
||||
argValue = Resolve(expr, mExpectingType);
|
||||
arg.mArgFlags = BfArgFlag_None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!argValue)
|
||||
return BfTypedValue();
|
||||
|
|
|
@ -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<BfScopeData*> 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<BfFunctionBindResult*> prevBindResult(mFunctionBindResult, NULL);
|
||||
SetAndRestoreValue<bool> 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -752,7 +752,7 @@ public:
|
|||
BfMethodDef* mMethodDef;
|
||||
BfType* mReturnType;
|
||||
Array<BfMethodParam> mParams;
|
||||
Array<BfIRValue> mDefaultValues; // ConstIdx
|
||||
Array<BfTypedValue> mDefaultValues;
|
||||
BfModule* mDeclModule;
|
||||
BfMethodProcessRequest* mMethodProcessRequest;
|
||||
BfMethodInfoEx* mMethodInfoEx;
|
||||
|
|
47
IDEHelper/Tests/src/Defaults.bf
Normal file
47
IDEHelper/Tests/src/Defaults.bf
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue