diff options
-rw-r--r-- | formula/source/core/api/FormulaCompiler.cxx | 33 | ||||
-rw-r--r-- | formula/source/core/api/token.cxx | 3 | ||||
-rw-r--r-- | formula/source/ui/dlg/formula.cxx | 1 | ||||
-rw-r--r-- | include/formula/paramclass.hxx | 8 | ||||
-rw-r--r-- | sc/source/core/tool/compiler.cxx | 3 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/parclass.cxx | 56 |
8 files changed, 76 insertions, 36 deletions
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index b0938aa630be..ccf4562fec9d 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -2693,6 +2693,13 @@ formula::ParamClass FormulaCompiler::GetForceArrayParameter( const FormulaToken* void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) { + if (rCurr->GetInForceArray() != ParamClass::Unknown) + // Already set, unnecessary to evaluate again. This happens by calls to + // CurrentFactor::operator=() while descending through Factor() and + // then ascending back (and down and up, ...), + // CheckSetForceArrayParameter() and later PutCode(). + return; + if (!pCurrentFactorToken || (pCurrentFactorToken.get() == rCurr.get())) return; @@ -2700,27 +2707,37 @@ void FormulaCompiler::ForceArrayOperator( FormulaTokenRef const & rCurr ) return; // Inherited parameter class. - formula::ParamClass eType = pCurrentFactorToken->GetInForceArray(); - if (eType == formula::ParamClass::ForceArray) - { - rCurr->SetInForceArray( eType); + const formula::ParamClass eForceType = pCurrentFactorToken->GetInForceArray(); + if (eForceType == ParamClass::ForceArray || eForceType == ParamClass::ReferenceOrRefArray) + { + // ReferenceOrRefArray was set only if in ForceArray context already, + // it is valid for the one function only to indicate the preferred + // return type. Propagate as ForceArray if not another parameter + // handling ReferenceOrRefArray. + if (nCurrentFactorParam > 0 + && (GetForceArrayParameter( pCurrentFactorToken.get(), static_cast<sal_uInt16>(nCurrentFactorParam - 1)) + == ParamClass::ReferenceOrRefArray)) + rCurr->SetInForceArray( ParamClass::ReferenceOrRefArray); + else + rCurr->SetInForceArray( ParamClass::ForceArray); return; } - else if (eType == formula::ParamClass::ReferenceOrForceArray) + else if (eForceType == ParamClass::ReferenceOrForceArray) { // Inherit further only if the return class of the nested function is // not Reference. Else flag as suppressed. if (GetForceArrayParameter( rCurr.get(), SAL_MAX_UINT16) != ParamClass::Reference) - rCurr->SetInForceArray( eType); + rCurr->SetInForceArray( eForceType); else - rCurr->SetInForceArray( formula::ParamClass::SuppressedReferenceOrForceArray); + rCurr->SetInForceArray( ParamClass::SuppressedReferenceOrForceArray); return; } if (nCurrentFactorParam > 0) { // Actual current parameter's class. - eType = GetForceArrayParameter( pCurrentFactorToken.get(), static_cast<sal_uInt16>(nCurrentFactorParam - 1)); + const formula::ParamClass eType = GetForceArrayParameter( + pCurrentFactorToken.get(), static_cast<sal_uInt16>(nCurrentFactorParam - 1)); if (eType == ParamClass::ForceArray) rCurr->SetInForceArray( eType); else if (eType == ParamClass::ReferenceOrForceArray) diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx index cefab324fd53..aa3dbec8c8ef 100644 --- a/formula/source/core/api/token.cxx +++ b/formula/source/core/api/token.cxx @@ -150,7 +150,8 @@ bool FormulaToken::IsRef() const bool FormulaToken::IsInForceArray() const { ParamClass eParam = GetInForceArray(); - return eParam == ParamClass::ForceArray || eParam == ParamClass::ReferenceOrForceArray; + return eParam == ParamClass::ForceArray || eParam == ParamClass::ReferenceOrForceArray + || eParam == ParamClass::ReferenceOrRefArray; } bool FormulaToken::operator==( const FormulaToken& rToken ) const diff --git a/formula/source/ui/dlg/formula.cxx b/formula/source/ui/dlg/formula.cxx index c324be63a943..55135ebc11cf 100644 --- a/formula/source/ui/dlg/formula.cxx +++ b/formula/source/ui/dlg/formula.cxx @@ -753,6 +753,7 @@ void FormulaDlg_Impl::MakeTree( StructPage* _pTree, SvTreeListEntry* pParent, co aUnforcedResult.clear(); break; case ParamClass::Reference: + case ParamClass::ReferenceOrRefArray: case ParamClass::Array: case ParamClass::ForceArray: case ParamClass::ReferenceOrForceArray: diff --git a/include/formula/paramclass.hxx b/include/formula/paramclass.hxx index a22854fc890c..a1e564819457 100644 --- a/include/formula/paramclass.hxx +++ b/include/formula/paramclass.hxx @@ -36,6 +36,14 @@ namespace formula PopDoubleRefOrSingleRef() should not have this. */ Reference, + /** Like Reference but the function accepts also a list of references + (ocUnion svRefList) as one argument AND handles the special case of + an array of references in array mode. Then the resulting argument + for a parameter in JumpMatrix context may be an array of references + which then is to be preferred over a result matrix. This final + behaviour is the opposite of SuppressedReferenceOrForceArray. */ + ReferenceOrRefArray, + /** In array formula: convert area reference to array. Function will be called only once if no Value type is involved. Functions able to handle a svMatrix parameter but not a formula::svDoubleRef parameter as area diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 3c86ad2f5591..556cd49b39c3 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -5809,7 +5809,8 @@ bool ScCompiler::SkipImplicitIntersectionOptimization(const FormulaToken* token) formula::ParamClass paramClass = token->GetInForceArray(); if (paramClass == formula::ForceArray || paramClass == formula::ReferenceOrForceArray - || paramClass == formula::SuppressedReferenceOrForceArray) + || paramClass == formula::SuppressedReferenceOrForceArray + || paramClass == formula::ReferenceOrRefArray) { return true; } diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 38e56deb52f7..b83406223a17 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -835,8 +835,10 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) { // We're done with it, throw away jump matrix, keep result. // For an intermediate result of Reference use the array of references // if there are more than one reference and the current ForceArray - // context is not ForceArray or related, suppressed, ..., - // else (also for a final result of Reference) use the matrix. + // context is not ForceArray or suppressed. Note that also + // ReferenceOrRefArray forces the array of references as result if + // there is more than one reference. + // Else (also for a final result of Reference) use the matrix. // Treat the result of a jump command as final and use the matrix (see // tdf#115493 for why). ParamClass eParamClass; diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index a1eb180683db..3bb3cf83c350 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -1490,6 +1490,7 @@ bool ScInterpreter::ConvertMatrixParameters() { formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i); if ( eType != formula::ParamClass::Reference && + eType != formula::ParamClass::ReferenceOrRefArray && eType != formula::ParamClass::ReferenceOrForceArray && // For scalar Value: convert to Array/JumpMatrix // only if in array formula context, else (function @@ -1554,6 +1555,7 @@ bool ScInterpreter::ConvertMatrixParameters() { formula::ParamClass eType = ScParameterClassification::GetParameterType( pCur, nParams - i); if ( eType != formula::ParamClass::Reference && + eType != formula::ParamClass::ReferenceOrRefArray && eType != formula::ParamClass::ReferenceOrForceArray && eType != formula::ParamClass::ForceArray) { diff --git a/sc/source/core/tool/parclass.cxx b/sc/source/core/tool/parclass.cxx index 9f79da716a40..46179fe552f8 100644 --- a/sc/source/core/tool/parclass.cxx +++ b/sc/source/core/tool/parclass.cxx @@ -99,25 +99,25 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocTableOp, {{ Value, Value, Value, Value, Value }, 0, Value }}, // Operators and functions. { ocAdd, {{ Array, Array }, 0, Value }}, - { ocAggregate, {{ Value, Value, Reference }, 1, Value }}, + { ocAggregate, {{ Value, Value, ReferenceOrRefArray }, 1, Value }}, { ocAmpersand, {{ Array, Array }, 0, Value }}, { ocAnd, {{ Reference }, 1, Value }}, { ocAreas, {{ Reference }, 0, Value }}, { ocAveDev, {{ Reference }, 1, Value }}, - { ocAverage, {{ Reference }, 1, Value }}, - { ocAverageA, {{ Reference }, 1, Value }}, - { ocAverageIf, {{ Reference, Value, Reference }, 0, Value }}, - { ocAverageIfs, {{ Reference, Reference, Value }, 2, Value }}, + { ocAverage, {{ ReferenceOrRefArray }, 1, Value }}, + { ocAverageA, {{ ReferenceOrRefArray }, 1, Value }}, + { ocAverageIf, {{ ReferenceOrRefArray, Value, Reference }, 0, Value }}, + { ocAverageIfs, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }}, { ocCell, {{ Value, Reference }, 0, Value }}, { ocColumn, {{ Reference }, 0, Value }}, { ocColumns, {{ Reference }, 1, Value }}, { ocConcat_MS, {{ Reference }, 1, Value }}, { ocCorrel, {{ ForceArray, ForceArray }, 0, Value }}, - { ocCount, {{ Reference }, 1, Value }}, - { ocCount2, {{ Reference }, 1, Value }}, - { ocCountEmptyCells, {{ Reference }, 0, Value }}, - { ocCountIf, {{ Reference, Value }, 0, Value }}, - { ocCountIfs, {{ Reference, Value }, 2, Value }}, + { ocCount, {{ ReferenceOrRefArray }, 1, Value }}, + { ocCount2, {{ ReferenceOrRefArray }, 1, Value }}, + { ocCountEmptyCells, {{ ReferenceOrRefArray }, 0, Value }}, + { ocCountIf, {{ ReferenceOrRefArray, Value }, 0, Value }}, + { ocCountIfs, {{ ReferenceOrRefArray, Value }, 2, Value }}, { ocCovar, {{ ForceArray, ForceArray }, 0, Value }}, { ocCovarianceP, {{ ForceArray, ForceArray }, 0, Value }}, { ocCovarianceS, {{ ForceArray, ForceArray }, 0, Value }}, @@ -176,11 +176,13 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocMatTrans, {{ Array }, 0, Value }}, // strange, but Xcl doesn't force MatTrans array { ocMatValue, {{ Reference, Value, Value }, 0, Value }}, { ocMatch, {{ Value, ReferenceOrForceArray, Value }, 0, Value }}, - { ocMax, {{ Reference }, 1, Value }}, - { ocMaxA, {{ Reference }, 1, Value }}, + { ocMax, {{ ReferenceOrRefArray }, 1, Value }}, + { ocMaxA, {{ ReferenceOrRefArray }, 1, Value }}, + { ocMaxIfs_MS, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }}, { ocMedian, {{ Reference }, 1, Value }}, - { ocMin, {{ Reference }, 1, Value }}, - { ocMinA, {{ Reference }, 1, Value }}, + { ocMin, {{ ReferenceOrRefArray }, 1, Value }}, + { ocMinA, {{ ReferenceOrRefArray }, 1, Value }}, + { ocMinIfs_MS, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }}, { ocModalValue, {{ ForceArray }, 1, Value }}, { ocModalValue_MS, {{ ForceArray }, 1, Value }}, { ocModalValue_Multi,{{ ForceArray }, 1, Value }}, @@ -206,7 +208,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocPow, {{ Array, Array }, 0, Value }}, { ocPower, {{ Array, Array }, 0, Value }}, { ocProb, {{ ForceArray, ForceArray, Value, Value }, 0, Value }}, - { ocProduct, {{ Reference }, 1, Value }}, + { ocProduct, {{ ReferenceOrRefArray }, 1, Value }}, { ocQuartile, {{ Reference, Value }, 0, Value }}, { ocQuartile_Exc, {{ Reference, Value }, 0, Value }}, { ocQuartile_Inc, {{ Reference, Value }, 0, Value }}, @@ -231,12 +233,12 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocStDevP_MS, {{ Reference }, 1, Value }}, { ocStDevS, {{ Reference }, 1, Value }}, { ocSub, {{ Array, Array }, 0, Value }}, - { ocSubTotal, {{ Value, Reference }, 1, Value }}, - { ocSum, {{ Reference }, 1, Value }}, - { ocSumIf, {{ Reference, Value, Reference }, 0, Value }}, - { ocSumIfs, {{ Reference, Reference, Value }, 2, Value }}, + { ocSubTotal, {{ Value, ReferenceOrRefArray }, 1, Value }}, + { ocSum, {{ ReferenceOrRefArray }, 1, Value }}, + { ocSumIf, {{ ReferenceOrRefArray, Value, Reference }, 0, Value }}, + { ocSumIfs, {{ ReferenceOrRefArray, ReferenceOrRefArray, Value }, 2, Value }}, { ocSumProduct, {{ ForceArray }, 1, Value }}, - { ocSumSQ, {{ Reference }, 1, Value }}, + { ocSumSQ, {{ ReferenceOrRefArray }, 1, Value }}, { ocSumX2DY2, {{ ForceArray, ForceArray }, 0, Value }}, { ocSumX2MY2, {{ ForceArray, ForceArray }, 0, Value }}, { ocSumXMY2, {{ ForceArray, ForceArray }, 0, Value }}, @@ -246,10 +248,10 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] = { ocTrimMean, {{ Reference, Value }, 0, Value }}, { ocUnion, {{ Reference, Reference }, 0, Reference }}, { ocVLookup, {{ Value, ReferenceOrForceArray, Value, Value }, 0, Value }}, - { ocVar, {{ Reference }, 1, Value }}, - { ocVarA, {{ Reference }, 1, Value }}, - { ocVarP, {{ Reference }, 1, Value }}, - { ocVarPA, {{ Reference }, 1, Value }}, + { ocVar, {{ ReferenceOrRefArray }, 1, Value }}, + { ocVarA, {{ ReferenceOrRefArray }, 1, Value }}, + { ocVarP, {{ ReferenceOrRefArray }, 1, Value }}, + { ocVarPA, {{ ReferenceOrRefArray }, 1, Value }}, { ocVarP_MS, {{ Reference }, 1, Value }}, { ocVarS, {{ Reference }, 1, Value }}, { ocWorkday_MS, {{ Value, Value, Value, Reference }, 0, Value }}, @@ -613,6 +615,9 @@ void ScParameterClassification::GenerateDocumentation() case Reference : aStr.append(" Reference"); break; + case ReferenceOrRefArray : + aStr.append(" ReferenceOrRefArray"); + break; case Array : aStr.append(" Array"); break; @@ -664,6 +669,9 @@ void ScParameterClassification::GenerateDocumentation() case Reference : aStr.append(" -> Reference"); break; + case ReferenceOrRefArray : + aStr.append(" -> ReferenceOrRefArray"); + break; case Array : aStr.append(" -> Array"); break; |