1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Operator '??=', '?' out discard

This commit is contained in:
Brian Fiete 2020-09-07 15:24:42 -07:00
parent f3074986ea
commit e70394bbf6
5 changed files with 63 additions and 18 deletions

View file

@ -1435,6 +1435,8 @@ const char* Beefy::BfTokenToString(BfToken token)
return "|="; return "|=";
case BfToken_XorEquals: case BfToken_XorEquals:
return "^="; return "^=";
case BfToken_NullCoalsceEquals:
return "??=";
case BfToken_LBrace: case BfToken_LBrace:
return "{"; return "{";
case BfToken_RBrace: case BfToken_RBrace:
@ -1546,6 +1548,8 @@ BfBinaryOp Beefy::BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp)
return BfBinaryOp_BitwiseOr; return BfBinaryOp_BitwiseOr;
case BfAssignmentOp_ExclusiveOr: case BfAssignmentOp_ExclusiveOr:
return BfBinaryOp_ExclusiveOr; return BfBinaryOp_ExclusiveOr;
case BfAssignmentOp_NullCoalesce:
return BfBinaryOp_NullCoalesce;
default: default:
break; break;
} }
@ -1789,6 +1793,8 @@ BfAssignmentOp Beefy::BfTokenToAssignmentOp(BfToken token)
return BfAssignmentOp_BitwiseOr; return BfAssignmentOp_BitwiseOr;
case BfToken_XorEquals: case BfToken_XorEquals:
return BfAssignmentOp_ExclusiveOr; return BfAssignmentOp_ExclusiveOr;
case BfToken_NullCoalsceEquals:
return BfAssignmentOp_NullCoalesce;
default: default:
return BfAssignmentOp_None; return BfAssignmentOp_None;
} }

View file

@ -198,6 +198,7 @@ enum BfToken : uint8
BfToken_PlusEquals, BfToken_PlusEquals,
BfToken_MinusEquals, BfToken_MinusEquals,
BfToken_MultiplyEquals, BfToken_MultiplyEquals,
BfToken_DivideEquals, BfToken_DivideEquals,
BfToken_ModulusEquals, BfToken_ModulusEquals,
BfToken_ShiftLeftEquals, BfToken_ShiftLeftEquals,
@ -205,6 +206,7 @@ enum BfToken : uint8
BfToken_AndEquals, BfToken_AndEquals,
BfToken_OrEquals, BfToken_OrEquals,
BfToken_XorEquals, BfToken_XorEquals,
BfToken_NullCoalsceEquals,
BfToken_LBrace, BfToken_LBrace,
BfToken_RBrace, BfToken_RBrace,
BfToken_LParen, BfToken_LParen,
@ -1753,7 +1755,8 @@ enum BfAssignmentOp
BfAssignmentOp_ShiftRight, BfAssignmentOp_ShiftRight,
BfAssignmentOp_BitwiseAnd, BfAssignmentOp_BitwiseAnd,
BfAssignmentOp_BitwiseOr, BfAssignmentOp_BitwiseOr,
BfAssignmentOp_ExclusiveOr BfAssignmentOp_ExclusiveOr,
BfAssignmentOp_NullCoalesce
}; };
enum BfUnaryOp enum BfUnaryOp

View file

@ -4382,6 +4382,11 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_ParamsExpr); resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_ParamsExpr);
} }
} }
else if (auto uninitExpr = BfNodeDynCast<BfUninitializedExpression>(argExpr))
{
resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_UninitializedExpr);
handled = true;
}
/*else if (auto castExpr = BfNodeDynCast<BfCastExpression>(argExpr)) /*else if (auto castExpr = BfNodeDynCast<BfCastExpression>(argExpr))
{ {
@ -5983,11 +5988,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
else if (argExprIdx >= 0) else if (argExprIdx >= 0)
{ {
BfParamKind paramKind = BfParamKind_Normal; BfParamKind paramKind = BfParamKind_Normal;
BfIdentifierNode* paramNameNode = NULL;
if (paramIdx < methodInstance->GetParamCount()) if (paramIdx < methodInstance->GetParamCount())
{
paramKind = methodInstance->GetParamKind(paramIdx); paramKind = methodInstance->GetParamKind(paramIdx);
paramNameNode = methodInstance->GetParamNameNode(paramIdx);
}
argValues[argExprIdx].mExpectedType = wantType; argValues[argExprIdx].mExpectedType = wantType;
argValue = ResolveArgValue(argValues[argExprIdx], wantType, NULL, paramKind); argValue = ResolveArgValue(argValues[argExprIdx], wantType, NULL, paramKind, paramNameNode);
} }
} }
@ -6103,7 +6112,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
{ {
mModule->AssertErrorState(); mModule->AssertErrorState();
auto argValue = argValues[argIdx].mTypedValue; auto argValue = argValues[argIdx].mTypedValue;
if ((argValues[argIdx].mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval | BfArgFlag_VariableDeclaration)) != 0) if ((argValues[argIdx].mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval | BfArgFlag_VariableDeclaration | BfArgFlag_UninitializedExpr)) != 0)
{ {
if (!argValue) if (!argValue)
{ {
@ -6364,8 +6373,8 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
static int sInvocationIdx = 0; static int sInvocationIdx = 0;
BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType* wantType, BfTypedValue* receivingValue, BfParamKind paramKind) BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType* wantType, BfTypedValue* receivingValue, BfParamKind paramKind, BfIdentifierNode* paramNameNode)
{ {
BfTypedValue argValue = resolvedArg.mTypedValue; BfTypedValue argValue = resolvedArg.mTypedValue;
if ((resolvedArg.mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval)) != 0) if ((resolvedArg.mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt | BfArgFlag_DeferredEval)) != 0)
{ {
@ -6410,14 +6419,14 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
{ {
argValue = mModule->GetDefaultTypedValue(wantType); argValue = mModule->GetDefaultTypedValue(wantType);
} }
else if ((resolvedArg.mArgFlags & (BfArgFlag_VariableDeclaration)) != 0) else if ((resolvedArg.mArgFlags & (BfArgFlag_VariableDeclaration | BfArgFlag_UninitializedExpr)) != 0)
{ {
auto variableDeclaration = BfNodeDynCast<BfVariableDeclaration>(resolvedArg.mExpression); auto variableDeclaration = BfNodeDynCast<BfVariableDeclaration>(resolvedArg.mExpression);
auto variableType = wantType; auto variableType = wantType;
bool isLet = variableDeclaration->mTypeRef->IsExact<BfLetTypeReference>(); bool isLet = (variableDeclaration != NULL) && (variableDeclaration->mTypeRef->IsExact<BfLetTypeReference>());
bool isVar = variableDeclaration->mTypeRef->IsExact<BfVarTypeReference>(); bool isVar = (variableDeclaration == NULL) || (variableDeclaration->mTypeRef->IsExact<BfVarTypeReference>());
if (mModule->mCurMethodState->mPendingNullConditional != NULL) if (mModule->mCurMethodState->mPendingNullConditional != NULL)
{ {
@ -6439,18 +6448,31 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
variableType = refType->mElementType; variableType = refType->mElementType;
} }
if (variableDeclaration->mInitializer != NULL) if ((variableDeclaration != NULL) && (variableDeclaration->mInitializer != NULL))
{ {
mModule->Fail("Initializers cannot be used when declaring variables for 'out' parameters", variableDeclaration->mEqualsNode); mModule->Fail("Initializers cannot be used when declaring variables for 'out' parameters", variableDeclaration->mEqualsNode);
mModule->CreateValueFromExpression(variableDeclaration->mInitializer, variableType, BfEvalExprFlags_NoCast); mModule->CreateValueFromExpression(variableDeclaration->mInitializer, variableType, BfEvalExprFlags_NoCast);
} }
if (variableDeclaration->mNameNode == NULL)
return argValue;
BfLocalVariable* localVar = new BfLocalVariable(); BfLocalVariable* localVar = new BfLocalVariable();
localVar->mName = variableDeclaration->mNameNode->ToString(); if ((variableDeclaration != NULL) && (variableDeclaration->mNameNode != NULL))
localVar->mNameNode = BfNodeDynCast<BfIdentifierNode>(variableDeclaration->mNameNode); {
localVar->mName = variableDeclaration->mNameNode->ToString();
localVar->mNameNode = BfNodeDynCast<BfIdentifierNode>(variableDeclaration->mNameNode);
}
else
{
if (paramNameNode != NULL)
{
localVar->mName = "__";
paramNameNode->ToString(localVar->mName);
localVar->mName += "_";
localVar->mName += StrFormat("%d", mModule->mCurMethodState->GetRootMethodState()->mCurLocalVarId);
}
else
localVar->mName = "__" + StrFormat("%d", mModule->mCurMethodState->GetRootMethodState()->mCurLocalVarId);
}
localVar->mResolvedType = variableType; localVar->mResolvedType = variableType;
if (!variableType->IsValuelessType()) if (!variableType->IsValuelessType())
localVar->mAddr = mModule->CreateAlloca(variableType); localVar->mAddr = mModule->CreateAlloca(variableType);
@ -16196,6 +16218,13 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
if (!mModule->CanCast(rightValue, paramType)) if (!mModule->CanCast(rightValue, paramType))
continue; continue;
mModule->SetElementType(assignExpr->mOpToken, BfSourceElementType_Method);
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(assignExpr->mOpToken)))
{
if (operatorDef->mOperatorDeclaration != NULL)
autoComplete->SetDefinitionLocation(operatorDef->mOperatorDeclaration->mOpTypeToken);
}
auto moduleMethodInstance = mModule->GetMethodInstance(checkTypeInst, operatorDef, BfTypeVector()); auto moduleMethodInstance = mModule->GetMethodInstance(checkTypeInst, operatorDef, BfTypeVector());
BfExprEvaluator exprEvaluator(mModule); BfExprEvaluator exprEvaluator(mModule);

View file

@ -17,7 +17,8 @@ enum BfArgFlags
BfArgFlag_DeferredEval = 0x40, BfArgFlag_DeferredEval = 0x40,
BfArgFlag_ExpectedTypeCast = 0x80, BfArgFlag_ExpectedTypeCast = 0x80,
BfArgFlag_VariableDeclaration = 0x100, BfArgFlag_VariableDeclaration = 0x100,
BfArgFlag_ParamsExpr = 0x200 BfArgFlag_ParamsExpr = 0x200,
BfArgFlag_UninitializedExpr = 0x400
}; };
enum BfResolveArgFlags enum BfResolveArgFlags
@ -347,7 +348,7 @@ public:
void ResolveGenericType(); void ResolveGenericType();
void ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveArgFlags flags = BfResolveArgFlag_None); void ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveArgFlags flags = BfResolveArgFlag_None);
BfAllocTarget ResolveAllocTarget(BfAstNode* newNode, BfTokenNode*& newToken, BfCustomAttributes** outCustomAttributes = NULL); BfAllocTarget ResolveAllocTarget(BfAstNode* newNode, BfTokenNode*& newToken, BfCustomAttributes** outCustomAttributes = NULL);
BfTypedValue ResolveArgValue(BfResolvedArg& resolvedArg, BfType* wantType, BfTypedValue* receivingValue = NULL, BfParamKind paramKind = BfParamKind_Normal); BfTypedValue ResolveArgValue(BfResolvedArg& resolvedArg, BfType* wantType, BfTypedValue* receivingValue = NULL, BfParamKind paramKind = BfParamKind_Normal, BfIdentifierNode* paramNameNode = NULL);
BfMethodDef* GetPropertyMethodDef(BfPropertyDef* propDef, BfMethodType methodType, BfCheckedKind checkedKind, BfTypedValue propTarget); BfMethodDef* GetPropertyMethodDef(BfPropertyDef* propDef, BfMethodType methodType, BfCheckedKind checkedKind, BfTypedValue propTarget);
BfModuleMethodInstance GetPropertyMethodInstance(BfMethodDef* methodDef); BfModuleMethodInstance GetPropertyMethodInstance(BfMethodDef* methodDef);
void CheckPropFail(BfMethodDef* propMethodDef, BfMethodInstance* methodInstance, bool checkProt); void CheckPropFail(BfMethodDef* propMethodDef, BfMethodInstance* methodInstance, bool checkProt);

View file

@ -1494,8 +1494,14 @@ void BfParser::NextToken(int endIdx)
case '?': case '?':
if (mSrc[mSrcIdx] == '?') if (mSrc[mSrcIdx] == '?')
{ {
mToken = BfToken_DblQuestion;
mTokenEnd = ++mSrcIdx; mTokenEnd = ++mSrcIdx;
if (mSrc[mSrcIdx] == '=')
{
mToken = BfToken_NullCoalsceEquals;
mTokenEnd = ++mSrcIdx;
}
else
mToken = BfToken_DblQuestion;
} }
else if (mSrc[mSrcIdx] == '.') else if (mSrc[mSrcIdx] == '.')
{ {