1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +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++) 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; BfAstNode* argExpr = NULL;
if (argIdx < (int)arguments.size()) if (argIdx < (int)arguments.size())
{ {
@ -314,16 +315,13 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
} }
auto foreignDefaultVal = methodInstance->mDefaultValues[argIdx]; auto foreignDefaultVal = methodInstance->mDefaultValues[argIdx];
auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(methodInstance->mDefaultValues[argIdx]); auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(foreignDefaultVal.mValue);
auto constVal = mModule->ConstantToCurrent(foreignConst, methodInstance->GetOwner()->mConstHolder, wantType); argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, foreignDefaultVal.mType);
llvmArgs.push_back(constVal);
argIdx++;
paramIdx++;
continue;
} }
auto argValue = arguments[argIdx].mTypedValue; if ((!argValue) && (argIdx < arguments.size()))
{
argValue = arguments[argIdx].mTypedValue;
auto& arg = arguments[argIdx]; auto& arg = arguments[argIdx];
if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0) if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0)
{ {
@ -335,7 +333,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
argValue = Resolve(expr, mExpectingType); argValue = Resolve(expr, mExpectingType);
arg.mArgFlags = BfArgFlag_None; arg.mArgFlags = BfArgFlag_None;
} }
}
if (!argValue) if (!argValue)
return BfTypedValue(); return BfTypedValue();

View file

@ -5417,7 +5417,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
} }
auto foreignDefaultVal = methodInstance->mDefaultValues[argIdx]; 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) if (foreignConst->mConstType == BfConstType_AggZero)
{ {
@ -5433,7 +5433,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (!argValue) if (!argValue)
{ {
argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, wantType); argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, foreignDefaultVal.mType);
if (!argValue) if (!argValue)
mModule->Fail("Default parameter value failed", targetSrc); mModule->Fail("Default parameter value failed", targetSrc);
} }
@ -5500,15 +5500,19 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
failed = true; failed = true;
} }
if ((argValue) && (arg != NULL)) if (argValue)
{ {
BfAstNode* refNode = arg;
if (refNode == NULL)
refNode = targetSrc;
if (mModule->mCurMethodState != NULL) if (mModule->mCurMethodState != NULL)
{ {
SetAndRestoreValue<BfScopeData*> prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData); SetAndRestoreValue<BfScopeData*> prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData);
argValue = mModule->Cast(arg, argValue, wantType); argValue = mModule->Cast(refNode, argValue, wantType);
} }
else else
argValue = mModule->Cast(arg, argValue, wantType); argValue = mModule->Cast(refNode, argValue, wantType);
if (!argValue) if (!argValue)
{ {
@ -5806,7 +5810,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
auto intPtrRefType = mModule->CreateRefType(intPtrType); auto intPtrRefType = mModule->CreateRefType(intPtrType);
if (target.mValue.IsFake()) if (target.mValue.IsFake())
{ {
resolvedArg.mTypedValue = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), intPtrType); resolvedArg.mTypedValue = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), intPtrRefType);
} }
else else
{ {
@ -6163,9 +6167,21 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
// NOP; // 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 // Temporarily disable so we don't capture calls in params
SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(mFunctionBindResult, NULL); SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(mFunctionBindResult, NULL);
SetAndRestoreValue<bool> prevAllowVariableDeclarations(mModule->mCurMethodState->mCurScope->mAllowVariableDeclarations, false); // Don't allow variable declarations in arguments
sInvocationIdx++; sInvocationIdx++;
@ -12243,7 +12259,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
{ {
BfTypedValue constExprVal; BfTypedValue constExprVal;
constExprVal.mType = genericParam->mTypeConstraint; 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); constExprVal.mValue = mModule->ConstantToCurrent(constant, curTypeInst->mConstHolder, genericParam->mTypeConstraint);
genericArg = mModule->CreateConstExprValueType(constExprVal); genericArg = mModule->CreateConstExprValueType(constExprVal);
} }

View file

@ -14797,7 +14797,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
{ {
auto localVar = mCurMethodState->GetRootMethodState()->mLocals[1]; auto localVar = mCurMethodState->GetRootMethodState()->mLocals[1];
BF_ASSERT(localVar->mName == "appendIdx"); BF_ASSERT(localVar->mName == "appendIdx");
auto intRefType = CreateRefType(localVar->mResolvedType); auto intRefType = localVar->mResolvedType;
appendIdxVal = BfTypedValue(localVar->mValue, intRefType); appendIdxVal = BfTypedValue(localVar->mValue, intRefType);
mCurMethodState->mCurAppendAlign = 1; // Don't make any assumptions about how the base leaves the alignment 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()); BF_ASSERT(defaultValue.mValue.IsConst());
while ((int)mCurMethodInstance->mDefaultValues.size() < paramDefIdx) while ((int)mCurMethodInstance->mDefaultValues.size() < paramDefIdx)
mCurMethodInstance->mDefaultValues.Add(BfIRValue()); mCurMethodInstance->mDefaultValues.Add(BfTypedValue());
CurrentAddToConstHolder(defaultValue.mValue); CurrentAddToConstHolder(defaultValue.mValue);
mCurMethodInstance->mDefaultValues.Add(defaultValue.mValue); mCurMethodInstance->mDefaultValues.Add(defaultValue);
} }
} }
} }

View file

@ -752,7 +752,7 @@ public:
BfMethodDef* mMethodDef; BfMethodDef* mMethodDef;
BfType* mReturnType; BfType* mReturnType;
Array<BfMethodParam> mParams; Array<BfMethodParam> mParams;
Array<BfIRValue> mDefaultValues; // ConstIdx Array<BfTypedValue> mDefaultValues;
BfModule* mDeclModule; BfModule* mDeclModule;
BfMethodProcessRequest* mMethodProcessRequest; BfMethodProcessRequest* mMethodProcessRequest;
BfMethodInfoEx* mMethodInfoEx; 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);
}
}
}