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_Out: return "out";
|
||||||
case BfUnaryOp_Mut: return "mut";
|
case BfUnaryOp_Mut: return "mut";
|
||||||
case BfUnaryOp_Params: return "params";
|
case BfUnaryOp_Params: return "params";
|
||||||
|
case BfUnaryOp_Cascade: return "..";
|
||||||
default: return "???";
|
default: return "???";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1759,6 +1760,8 @@ BfUnaryOp Beefy::BfTokenToUnaryOp(BfToken token)
|
||||||
return BfUnaryOp_Out;
|
return BfUnaryOp_Out;
|
||||||
case BfToken_Params:
|
case BfToken_Params:
|
||||||
return BfUnaryOp_Params;
|
return BfUnaryOp_Params;
|
||||||
|
case BfToken_DotDot:
|
||||||
|
return BfUnaryOp_Cascade;
|
||||||
default:
|
default:
|
||||||
return BfUnaryOp_None;
|
return BfUnaryOp_None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1834,7 +1834,8 @@ enum BfUnaryOp
|
||||||
BfUnaryOp_Ref,
|
BfUnaryOp_Ref,
|
||||||
BfUnaryOp_Out,
|
BfUnaryOp_Out,
|
||||||
BfUnaryOp_Mut,
|
BfUnaryOp_Mut,
|
||||||
BfUnaryOp_Params,
|
BfUnaryOp_Params,
|
||||||
|
BfUnaryOp_Cascade
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfTokenNode : public BfAstNode
|
class BfTokenNode : public BfAstNode
|
||||||
|
|
|
@ -4616,8 +4616,7 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
||||||
SizedArray<BfExpression*, 8> deferredArgs;
|
SizedArray<BfExpression*, 8> deferredArgs;
|
||||||
|
|
||||||
int argIdx = 0;
|
int argIdx = 0;
|
||||||
//for (int argIdx = 0; argIdx < argCount ; argIdx++)
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
//printf("Args: %p %p %d\n", resolvedArgs.mArguments, resolvedArgs.mArguments->mVals, resolvedArgs.mArguments->mSize);
|
//printf("Args: %p %p %d\n", resolvedArgs.mArguments, resolvedArgs.mArguments->mVals, resolvedArgs.mArguments->mSize);
|
||||||
|
@ -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;
|
bool deferParamEval = false;
|
||||||
if ((flags & BfResolveArgsFlag_DeferParamEval) != 0)
|
if ((flags & BfResolveArgsFlag_DeferParamEval) != 0)
|
||||||
{
|
{
|
||||||
|
@ -5899,6 +5907,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
BF_ASSERT(returnType->IsInterface());
|
BF_ASSERT(returnType->IsInterface());
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
Array<BfTypedValue> argCascades;
|
||||||
BfTypedValue target = inTarget;
|
BfTypedValue target = inTarget;
|
||||||
|
|
||||||
if (!skipThis)
|
if (!skipThis)
|
||||||
|
@ -6607,6 +6616,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
argValue = mModule->LoadValue(argValue);
|
argValue = mModule->LoadValue(argValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((argExprIdx != -1) && (argExprIdx < (int)argValues.size()) && ((argValues[argExprIdx].mArgFlags & BfArgFlag_Cascade) != 0))
|
||||||
|
argCascades.Add(argValue);
|
||||||
|
|
||||||
if (expandedParamsArray)
|
if (expandedParamsArray)
|
||||||
{
|
{
|
||||||
|
@ -6773,8 +6784,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
}
|
}
|
||||||
|
|
||||||
auto func = moduleMethodInstance.mFunc;
|
auto func = moduleMethodInstance.mFunc;
|
||||||
BfTypedValue result = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
|
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
|
||||||
return result;
|
|
||||||
|
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)
|
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;
|
break;
|
||||||
|
case BfUnaryOp_Cascade:
|
||||||
|
{
|
||||||
|
mModule->Fail("Illegal use of argument cascade expression", opToken);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
mModule->Fail("INTERNAL ERROR: Unhandled unary operator", unaryOpExpr);
|
mModule->Fail("INTERNAL ERROR: Unhandled unary operator", unaryOpExpr);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -20,7 +20,8 @@ enum BfArgFlags
|
||||||
BfArgFlag_ParamsExpr = 0x200,
|
BfArgFlag_ParamsExpr = 0x200,
|
||||||
BfArgFlag_UninitializedExpr = 0x400,
|
BfArgFlag_UninitializedExpr = 0x400,
|
||||||
BfArgFlag_StringInterpolateFormat = 0x800,
|
BfArgFlag_StringInterpolateFormat = 0x800,
|
||||||
BfArgFlag_StringInterpolateArg = 0x1000
|
BfArgFlag_StringInterpolateArg = 0x1000,
|
||||||
|
BfArgFlag_Cascade = 0x2000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfResolveArgsFlags
|
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)
|
void BfModule::CheckVariableDef(BfLocalVariable* variableDef)
|
||||||
{
|
{
|
||||||
if (variableDef->mName.IsEmpty())
|
if (variableDef->mName.IsEmpty())
|
||||||
|
|
|
@ -1737,6 +1737,7 @@ public:
|
||||||
bool TryLocalVariableInit(BfLocalVariable* localVar);
|
bool TryLocalVariableInit(BfLocalVariable* localVar);
|
||||||
void LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit);
|
void LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit);
|
||||||
void CreateDIRetVal();
|
void CreateDIRetVal();
|
||||||
|
BfTypedValue CreateTuple(const Array<BfTypedValue>& values, const Array<String>& fieldNames);
|
||||||
void CheckTupleVariableDeclaration(BfTupleExpression* tupleExpr, BfType* initType);
|
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, BfTupleExpression* tupleExpr, BfTypedValue initTupleValue, bool isReadOnly, bool isConst, bool forceAddr, BfIRBlock* declBlock = NULL);
|
||||||
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl);
|
void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl);
|
||||||
|
|
|
@ -2250,8 +2250,15 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
unaryOpExpr->mOp = unaryOp;
|
unaryOpExpr->mOp = unaryOp;
|
||||||
unaryOpExpr->mOpToken = tokenNode;
|
unaryOpExpr->mOpToken = tokenNode;
|
||||||
ReplaceNode(tokenNode, unaryOpExpr);
|
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
|
// 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)
|
if (unaryOpExpr->mExpression == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
MoveNode(unaryOpExpr->mExpression, unaryOpExpr);
|
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