diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b1f2093b..4accd037 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -19262,6 +19262,8 @@ void BfExprEvaluator::PopulateDeferrredTupleAssignData(BfTupleExpression* tupleE DeferredTupleAssignData::Entry entry; entry.mExprEvaluator = NULL; entry.mInnerTuple = NULL; + entry.mVarType = NULL; + entry.mVarNameNode = NULL; BfExpression* valueExpr = tupleExpr->mValues[valueIdx]; entry.mExpr = valueExpr; @@ -19295,6 +19297,23 @@ void BfExprEvaluator::PopulateDeferrredTupleAssignData(BfTupleExpression* tupleE if (resultType == NULL) resultType = mModule->GetPrimitiveType(BfTypeCode_Var); } + entry.mVarType = resultType; + } + + if (auto binOpExpr = BfNodeDynCast(valueExpr)) + { + if (binOpExpr->mOp == BfBinaryOp_Multiply) + { + SetAndRestoreValue prevIgnoreError(mModule->mIgnoreErrors, true); + auto resolvedType = mModule->ResolveTypeRef(binOpExpr->mLeft, NULL); + prevIgnoreError.Restore(); + if (resolvedType != NULL) + { + resultType = mModule->CreatePointerType(resolvedType); + entry.mVarType = resultType; + entry.mVarNameNode = binOpExpr->mRight; + } + } } if (resultType == NULL) @@ -19383,11 +19402,19 @@ void BfExprEvaluator::AssignDeferrredTupleAssignData(BfAssignmentExpression* ass } } - if (auto varDecl = BfNodeDynCast(child.mExpr)) + if (child.mVarType != NULL) { - if (!elementValue) - elementValue = mModule->GetDefaultTypedValue(fieldInstance->GetResolvedType()); - mModule->HandleVariableDeclaration(varDecl, elementValue); + if (auto varDecl = BfNodeDynCast(child.mExpr)) + { + if (!elementValue) + elementValue = mModule->GetDefaultTypedValue(fieldInstance->GetResolvedType()); + mModule->HandleVariableDeclaration(varDecl, elementValue); + } + else + { + // This handles the 'a*b' disambiguated variable decl case + mModule->HandleVariableDeclaration(child.mVarType, child.mVarNameNode, elementValue); + } } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 4b4bcfc5..95b49914 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -341,6 +341,8 @@ struct DeferredTupleAssignData struct Entry { BfExpression* mExpr; + BfType* mVarType; + BfAstNode* mVarNameNode; BfExprEvaluator* mExprEvaluator; DeferredTupleAssignData* mInnerTuple; }; diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 2c2568fa..10baa57d 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1893,6 +1893,7 @@ public: BfTypedValue HandleCaseBind(BfTypedValue enumVal, const BfTypedValue& tagVal, BfEnumCaseBindExpression* bindExpr, BfIRBlock* eqBlock = NULL, BfIRBlock* notEqBlock = NULL, BfIRBlock* matchBlock = NULL, int* outEnumIdx = NULL); void TryInitVar(BfAstNode* checkNode, BfLocalVariable* varDecl, BfTypedValue initValue, BfTypedValue& checkResult); BfLocalVariable* HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfExprEvaluator* exprEvaluator = NULL); + BfLocalVariable* HandleVariableDeclaration(BfType* type, BfAstNode* nameNode, BfTypedValue val, bool updateSrcLoc = true, bool forceAddr = false); BfLocalVariable* HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfTypedValue val, bool updateSrcLoc = true, bool forceAddr = false); void CheckVariableDef(BfLocalVariable* variableDef); BfScopeData* FindScope(BfAstNode* scopeName, BfMixinState* curMixinState, bool allowAcrossDeferredBlock); diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index 1d3f7014..788d1ea9 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -1598,14 +1598,6 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat if (isTuple) isLocalVariable = true; } - else if (endingToken == BfToken_Star) - { - // Check spacing for "a* b" to determine if it's a pointer definition or a multiply - auto beforeStarNode = mVisitorPos.Get(outEndNode - 2); - if ((endingTokenNode->GetSrcStart() == beforeStarNode->GetSrcEnd()) && - (identifierNode->GetSrcStart() > endingTokenNode->GetSrcEnd())) - isLocalVariable = true; - } else if ((endingToken != BfToken_Star) && (endingToken != BfToken_Question)) isLocalVariable = true; } diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 9dc2fc18..7580a651 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -1932,6 +1932,40 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD return localVar; } +BfLocalVariable* BfModule::HandleVariableDeclaration(BfType* type, BfAstNode* nameNode, BfTypedValue val, bool updateSrcLoc, bool forceAddr) +{ + BfLocalVariable* localDef = new BfLocalVariable(); + nameNode->ToString(localDef->mName); + localDef->mNameNode = BfNodeDynCast(nameNode); + localDef->mResolvedType = type; + localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional; + localDef->mValue = val.mValue; + + if ((!localDef->mIsReadOnly) || (mHasFullDebugInfo)) + { + localDef->mAddr = AllocLocalVariable(localDef->mResolvedType, localDef->mName); + if ((val.mValue) && (!localDef->mResolvedType->IsValuelessType()) && (!localDef->mResolvedType->IsVar())) + { + if (localDef->mResolvedType->IsRef()) + val = MakeAddressable(val, true, true); + + if (val.IsSplat()) + { + AggregateSplatIntoAddr(val, localDef->mAddr); + } + else + mBfIRBuilder->CreateAlignedStore(val.mValue, localDef->mAddr, localDef->mResolvedType->mAlign); + } + } + + CheckVariableDef(localDef); + + if (nameNode->GetSourceData() != NULL) + UpdateSrcPos(nameNode); + localDef->Init(); + return AddLocalVariableDef(localDef, true); +} + BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfTypedValue val, bool updateSrcLoc, bool forceAddr) { if (varDecl->mEqualsNode != NULL) @@ -2337,6 +2371,31 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr continue; } + if (auto binOpExpr = BfNodeDynCast(expr)) + { + if (binOpExpr->mOp == BfBinaryOp_Multiply) + { + SetAndRestoreValue prevIgnoreError(mIgnoreErrors, true); + auto resolvedType = ResolveTypeRef(binOpExpr->mLeft, NULL); + prevIgnoreError.Restore(); + if (resolvedType != NULL) + { + resolvedType = CreatePointerType(resolvedType); + + PopulateType(tupleElement.mType); + tupleElement = LoadValue(tupleElement); + tupleElement = Cast(binOpExpr->mLeft, tupleElement, resolvedType); + + if (prevHadFallthrough) + Fail("Destructuring cannot be used when the previous case contains a fallthrough", expr); + + auto localVar = HandleVariableDeclaration(resolvedType, binOpExpr->mRight, tupleElement, false, true); + localVar->mReadFromId = 0; // Don't give usage errors for binds + continue; + } + } + } + if (auto uninitExpr = BfNodeDynCast(expr)) { continue;