mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Argument cascades
This commit is contained in:
parent
0692fb44a4
commit
2dbcca8ca4
8 changed files with 98 additions and 8 deletions
|
@ -1672,6 +1672,7 @@ const char* Beefy::BfGetOpName(BfUnaryOp unaryOp)
|
|||
case BfUnaryOp_Out: return "out";
|
||||
case BfUnaryOp_Mut: return "mut";
|
||||
case BfUnaryOp_Params: return "params";
|
||||
case BfUnaryOp_Cascade: return "..";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
@ -1759,6 +1760,8 @@ BfUnaryOp Beefy::BfTokenToUnaryOp(BfToken token)
|
|||
return BfUnaryOp_Out;
|
||||
case BfToken_Params:
|
||||
return BfUnaryOp_Params;
|
||||
case BfToken_DotDot:
|
||||
return BfUnaryOp_Cascade;
|
||||
default:
|
||||
return BfUnaryOp_None;
|
||||
}
|
||||
|
|
|
@ -1835,6 +1835,7 @@ enum BfUnaryOp
|
|||
BfUnaryOp_Out,
|
||||
BfUnaryOp_Mut,
|
||||
BfUnaryOp_Params,
|
||||
BfUnaryOp_Cascade
|
||||
};
|
||||
|
||||
class BfTokenNode : public BfAstNode
|
||||
|
|
|
@ -4616,7 +4616,6 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
|||
SizedArray<BfExpression*, 8> deferredArgs;
|
||||
|
||||
int argIdx = 0;
|
||||
//for (int argIdx = 0; argIdx < argCount ; argIdx++)
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
@ -4683,6 +4682,15 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
|||
}
|
||||
}
|
||||
|
||||
if (auto unaryOpExpr = BfNodeDynCastExact<BfUnaryOperatorExpression>(argExpr))
|
||||
{
|
||||
if (unaryOpExpr->mOp == BfUnaryOp_Cascade)
|
||||
{
|
||||
resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_Cascade);
|
||||
argExpr = unaryOpExpr->mExpression;
|
||||
}
|
||||
}
|
||||
|
||||
bool deferParamEval = false;
|
||||
if ((flags & BfResolveArgsFlag_DeferParamEval) != 0)
|
||||
{
|
||||
|
@ -5899,6 +5907,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
BF_ASSERT(returnType->IsInterface());
|
||||
}*/
|
||||
|
||||
Array<BfTypedValue> argCascades;
|
||||
BfTypedValue target = inTarget;
|
||||
|
||||
if (!skipThis)
|
||||
|
@ -6607,6 +6616,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
argValue = mModule->LoadValue(argValue);
|
||||
}
|
||||
|
||||
if ((argExprIdx != -1) && (argExprIdx < (int)argValues.size()) && ((argValues[argExprIdx].mArgFlags & BfArgFlag_Cascade) != 0))
|
||||
argCascades.Add(argValue);
|
||||
|
||||
if (expandedParamsArray)
|
||||
{
|
||||
|
@ -6773,8 +6784,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
}
|
||||
|
||||
auto func = moduleMethodInstance.mFunc;
|
||||
BfTypedValue result = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
|
||||
return result;
|
||||
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
|
||||
|
||||
if (argCascades.mSize == 1)
|
||||
return argCascades[0];
|
||||
if (argCascades.mSize > 1)
|
||||
return mModule->CreateTuple(argCascades, {});
|
||||
|
||||
return callResult;
|
||||
}
|
||||
|
||||
BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, BfTypeInstance* targetType, BfResolvedArgs& argValues, bool callCtorBodyOnly, bool allowAppendAlloc, BfTypedValue* appendIndexValue)
|
||||
|
@ -19376,7 +19393,11 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BfUnaryOp_Cascade:
|
||||
{
|
||||
mModule->Fail("Illegal use of argument cascade expression", opToken);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mModule->Fail("INTERNAL ERROR: Unhandled unary operator", unaryOpExpr);
|
||||
break;
|
||||
|
|
|
@ -20,7 +20,8 @@ enum BfArgFlags
|
|||
BfArgFlag_ParamsExpr = 0x200,
|
||||
BfArgFlag_UninitializedExpr = 0x400,
|
||||
BfArgFlag_StringInterpolateFormat = 0x800,
|
||||
BfArgFlag_StringInterpolateArg = 0x1000
|
||||
BfArgFlag_StringInterpolateArg = 0x1000,
|
||||
BfArgFlag_Cascade = 0x2000
|
||||
};
|
||||
|
||||
enum BfResolveArgsFlags
|
||||
|
|
|
@ -13830,6 +13830,29 @@ void BfModule::CreateDIRetVal()
|
|||
}
|
||||
}
|
||||
|
||||
BfTypedValue BfModule::CreateTuple(const Array<BfTypedValue>& values, const Array<String>& fieldNames)
|
||||
{
|
||||
BfTypeVector fieldTypes;
|
||||
for (auto arg : values)
|
||||
fieldTypes.Add(arg.mType);
|
||||
|
||||
auto tupleType = CreateTupleType(fieldTypes, fieldNames);
|
||||
|
||||
auto tupleTypedValue = BfTypedValue(CreateAlloca(tupleType), tupleType, true);
|
||||
for (int fieldIdx = 0; fieldIdx < tupleType->mFieldInstances.size(); fieldIdx++)
|
||||
{
|
||||
auto& fieldInstance = tupleType->mFieldInstances[fieldIdx];
|
||||
if (fieldInstance.mDataIdx <= 0)
|
||||
continue;
|
||||
|
||||
auto typedVal = values[fieldIdx];
|
||||
typedVal = LoadOrAggregateValue(typedVal);
|
||||
mBfIRBuilder->CreateAlignedStore(typedVal.mValue, mBfIRBuilder->CreateInBoundsGEP(tupleTypedValue.mValue, 0, fieldInstance.mDataIdx), typedVal.mType->mAlign);
|
||||
}
|
||||
|
||||
return tupleTypedValue;
|
||||
}
|
||||
|
||||
void BfModule::CheckVariableDef(BfLocalVariable* variableDef)
|
||||
{
|
||||
if (variableDef->mName.IsEmpty())
|
||||
|
|
|
@ -1737,6 +1737,7 @@ public:
|
|||
bool TryLocalVariableInit(BfLocalVariable* localVar);
|
||||
void LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit);
|
||||
void CreateDIRetVal();
|
||||
BfTypedValue CreateTuple(const Array<BfTypedValue>& values, const Array<String>& fieldNames);
|
||||
void CheckTupleVariableDeclaration(BfTupleExpression* tupleExpr, BfType* initType);
|
||||
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl, BfTupleExpression* tupleExpr, BfTypedValue initTupleValue, bool isReadOnly, bool isConst, bool forceAddr, BfIRBlock* declBlock = NULL);
|
||||
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl);
|
||||
|
|
|
@ -2250,8 +2250,15 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
|||
unaryOpExpr->mOp = unaryOp;
|
||||
unaryOpExpr->mOpToken = tokenNode;
|
||||
ReplaceNode(tokenNode, unaryOpExpr);
|
||||
|
||||
CreateExprFlags innerFlags = (CreateExprFlags)(rhsCreateExprFlags | CreateExprFlags_EarlyExit);
|
||||
if (unaryOp == BfUnaryOp_Cascade)
|
||||
{
|
||||
innerFlags = (CreateExprFlags)(innerFlags | (createExprFlags & CreateExprFlags_AllowVariableDecl));
|
||||
}
|
||||
|
||||
// Don't attempt binary or unary operations- they will always be lower precedence
|
||||
unaryOpExpr->mExpression = CreateExpressionAfter(unaryOpExpr, (CreateExprFlags)(rhsCreateExprFlags | CreateExprFlags_EarlyExit));
|
||||
unaryOpExpr->mExpression = CreateExpressionAfter(unaryOpExpr, innerFlags);
|
||||
if (unaryOpExpr->mExpression == NULL)
|
||||
return NULL;
|
||||
MoveNode(unaryOpExpr->mExpression, unaryOpExpr);
|
||||
|
|
33
IDEHelper/Tests/src/Cascades.bf
Normal file
33
IDEHelper/Tests/src/Cascades.bf
Normal file
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
class Cascades
|
||||
{
|
||||
public static void MethodA(int a, float b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void MethodB(int a, out float b)
|
||||
{
|
||||
b = 100;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
int a = MethodA(.. 12, 2.3f);
|
||||
Test.Assert(a == 12);
|
||||
var (b, c) = MethodA(.. 12, .. 2.3f);
|
||||
Test.Assert(b == 12);
|
||||
Test.Assert(c == 2.3f);
|
||||
var d = MethodA(.. 12, .. 2.3f);
|
||||
Test.Assert(d == (12, 2.3f));
|
||||
var f = ref MethodB(12, .. var e);
|
||||
e += 23;
|
||||
Test.Assert(e == (int)123);
|
||||
Test.Assert(f == (int)123);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue