1
0
Fork 0
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:
Brian Fiete 2020-05-07 13:19:02 -07:00
parent ea072ad77b
commit 5bbffe268b
6 changed files with 98 additions and 32 deletions

View file

@ -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);
}
}
}
}

View file

@ -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();

View file

@ -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);
}

View file

@ -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);
}
}
}

View file

@ -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;

View 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);
}
}
}