diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 8e2f6840..8cf8e71a 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -1435,6 +1435,8 @@ const char* Beefy::BfTokenToString(BfToken token) return "|="; case BfToken_XorEquals: return "^="; + case BfToken_NullCoalsceEquals: + return "??="; case BfToken_LBrace: return "{"; case BfToken_RBrace: @@ -1546,6 +1548,8 @@ BfBinaryOp Beefy::BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp) return BfBinaryOp_BitwiseOr; case BfAssignmentOp_ExclusiveOr: return BfBinaryOp_ExclusiveOr; + case BfAssignmentOp_NullCoalesce: + return BfBinaryOp_NullCoalesce; default: break; } @@ -1789,6 +1793,8 @@ BfAssignmentOp Beefy::BfTokenToAssignmentOp(BfToken token) return BfAssignmentOp_BitwiseOr; case BfToken_XorEquals: return BfAssignmentOp_ExclusiveOr; + case BfToken_NullCoalsceEquals: + return BfAssignmentOp_NullCoalesce; default: return BfAssignmentOp_None; } diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index eda368d0..acaca210 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -198,6 +198,7 @@ enum BfToken : uint8 BfToken_PlusEquals, BfToken_MinusEquals, BfToken_MultiplyEquals, + BfToken_DivideEquals, BfToken_ModulusEquals, BfToken_ShiftLeftEquals, @@ -205,6 +206,7 @@ enum BfToken : uint8 BfToken_AndEquals, BfToken_OrEquals, BfToken_XorEquals, + BfToken_NullCoalsceEquals, BfToken_LBrace, BfToken_RBrace, BfToken_LParen, @@ -1753,7 +1755,8 @@ enum BfAssignmentOp BfAssignmentOp_ShiftRight, BfAssignmentOp_BitwiseAnd, BfAssignmentOp_BitwiseOr, - BfAssignmentOp_ExclusiveOr + BfAssignmentOp_ExclusiveOr, + BfAssignmentOp_NullCoalesce }; enum BfUnaryOp diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 8fc89232..20225363 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4382,6 +4382,11 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_ParamsExpr); } } + else if (auto uninitExpr = BfNodeDynCast(argExpr)) + { + resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_UninitializedExpr); + handled = true; + } /*else if (auto castExpr = BfNodeDynCast(argExpr)) { @@ -5983,11 +5988,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu else if (argExprIdx >= 0) { BfParamKind paramKind = BfParamKind_Normal; + BfIdentifierNode* paramNameNode = NULL; if (paramIdx < methodInstance->GetParamCount()) + { paramKind = methodInstance->GetParamKind(paramIdx); + paramNameNode = methodInstance->GetParamNameNode(paramIdx); + } 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(); 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) { @@ -6364,8 +6373,8 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou 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; 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); } - else if ((resolvedArg.mArgFlags & (BfArgFlag_VariableDeclaration)) != 0) + else if ((resolvedArg.mArgFlags & (BfArgFlag_VariableDeclaration | BfArgFlag_UninitializedExpr)) != 0) { auto variableDeclaration = BfNodeDynCast(resolvedArg.mExpression); auto variableType = wantType; - bool isLet = variableDeclaration->mTypeRef->IsExact(); - bool isVar = variableDeclaration->mTypeRef->IsExact(); + bool isLet = (variableDeclaration != NULL) && (variableDeclaration->mTypeRef->IsExact()); + bool isVar = (variableDeclaration == NULL) || (variableDeclaration->mTypeRef->IsExact()); if (mModule->mCurMethodState->mPendingNullConditional != NULL) { @@ -6439,18 +6448,31 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType 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->CreateValueFromExpression(variableDeclaration->mInitializer, variableType, BfEvalExprFlags_NoCast); } - - if (variableDeclaration->mNameNode == NULL) - return argValue; - + BfLocalVariable* localVar = new BfLocalVariable(); - localVar->mName = variableDeclaration->mNameNode->ToString(); - localVar->mNameNode = BfNodeDynCast(variableDeclaration->mNameNode); + if ((variableDeclaration != NULL) && (variableDeclaration->mNameNode != NULL)) + { + localVar->mName = variableDeclaration->mNameNode->ToString(); + localVar->mNameNode = BfNodeDynCast(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; if (!variableType->IsValuelessType()) localVar->mAddr = mModule->CreateAlloca(variableType); @@ -16196,6 +16218,13 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool if (!mModule->CanCast(rightValue, paramType)) 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()); BfExprEvaluator exprEvaluator(mModule); diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 4fb73734..c38d76dd 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -17,7 +17,8 @@ enum BfArgFlags BfArgFlag_DeferredEval = 0x40, BfArgFlag_ExpectedTypeCast = 0x80, BfArgFlag_VariableDeclaration = 0x100, - BfArgFlag_ParamsExpr = 0x200 + BfArgFlag_ParamsExpr = 0x200, + BfArgFlag_UninitializedExpr = 0x400 }; enum BfResolveArgFlags @@ -347,7 +348,7 @@ public: void ResolveGenericType(); void ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveArgFlags flags = BfResolveArgFlag_None); 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); BfModuleMethodInstance GetPropertyMethodInstance(BfMethodDef* methodDef); void CheckPropFail(BfMethodDef* propMethodDef, BfMethodInstance* methodInstance, bool checkProt); diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index fe80ef6f..801d2079 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -1494,8 +1494,14 @@ void BfParser::NextToken(int endIdx) case '?': if (mSrc[mSrcIdx] == '?') { - mToken = BfToken_DblQuestion; mTokenEnd = ++mSrcIdx; + if (mSrc[mSrcIdx] == '=') + { + mToken = BfToken_NullCoalsceEquals; + mTokenEnd = ++mSrcIdx; + } + else + mToken = BfToken_DblQuestion; } else if (mSrc[mSrcIdx] == '.') {