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