From 1cf795a40f4468fa65e802d37d5fa11d7d59177b Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 17 Dec 2019 09:10:35 +0100 Subject: [PATCH] ENH: use exprString expansions for #eval - follows the principle of least surprise if the expansion behaviour for #eval and expressions (eg, exprFixedValue) are the same. This is possible now that we harness the regular stringOps::expand() within exprString::expand() --- applications/test/dictionary/testDictEval2 | 39 +++++++- src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C | 3 + .../functionEntries/evalEntry/evalEntry.C | 8 +- .../expressions/exprEntry/expressionEntry.C | 22 ++++- .../expressions/exprEntry/expressionEntry.H | 9 +- .../expressions/exprString/exprString.H | 13 ++- .../primitives/strings/stringOps/stringOps.C | 2 +- .../primitives/strings/stringOps/stringOps.H | 99 ++++++++++++------- 8 files changed, 142 insertions(+), 53 deletions(-) diff --git a/applications/test/dictionary/testDictEval2 b/applications/test/dictionary/testDictEval2 index 5f53157740..d965c935d0 100644 --- a/applications/test/dictionary/testDictEval2 +++ b/applications/test/dictionary/testDictEval2 @@ -47,10 +47,10 @@ eval6b #eval " pi() * 2 * ${{ ${unknown:-0} * ${{ 15 * 3 }} }} + 5"; eval6c #eval " pi() * 2 * ${{ -${unknown:-0} * ${{ 15 * 3 }} }} + 5"; // Even this work -eval7a #eval " pi() * 1 * ${factor${{2*5}}:-100}"; +eval7a #eval " pi() * 1 * ${factor${{2*5}}:-100}"; // Even this work -eval7b #eval " pi() * 1 * ${factorXYZ${{2*5}}:-100}"; +eval7b #eval " pi() * 1 * ${factorXYZ${{2*5}}:-100}"; index 10; @@ -58,7 +58,40 @@ eval8a #eval " pi() * 2 * ${{ ${factor$index} + ${factor10} }}"; eval8b #eval " pi() * 2 * $factor * ${{ 100 }}"; -eval10a #eval "vector(1,2,3) * 5"; +eval10a #eval "vector(1,2,3) * 5"; +// Slightly stranger ideas: + +axis1 (1 0 0); +axis2 (0 1 0); +axis3 (0 0 1); +index 100; + +location #eval #{ + 400 * + + // Numerator: use the index to get relevant suffix [1,2,3] + // to form the lookup of axis1,axis2,... + // Treat the lookup as a vector within the expression evaluation + + $[(vector) axis${{ + ($index % 3) + 1 /* Evaluates: 1,2,3 from index */ }} + ] + + // Denominator: divide by index with zero-division protection + / ${{max(1, $index)}} + + // Same thing, but using expressions-syntax for variable lookup + / ${{max(1, $[index])}} +#}; + + +// This is still a rather clunky syntax +length #eval{ cbrt(mag($[(vector) location])) }; + + +// Remove evidence of some variables +#remove ("axis[0-9]*" index) + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C b/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C index be9998a0e8..f61de4c53b 100644 --- a/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C +++ b/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C @@ -231,6 +231,9 @@ std::string Foam::ITstream::toString() const label len = tokens.size(); + // NOTE: may wish to have special handling if there is a single token + // and it is already a string or word + for (const token& tok : tokens) { buf << tok; diff --git a/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C b/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C index 9fbb48b394..b1a40df9a6 100644 --- a/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C +++ b/src/OpenFOAM/db/dictionary/functionEntries/evalEntry/evalEntry.C @@ -105,10 +105,10 @@ Foam::tokenList Foam::functionEntries::evalEntry::evaluate << "input: " << s << endl; #endif - // Expanding with env-variables, with empty - - stringOps::inplaceRemoveComments(s); - stringOps::inplaceExpand(s, parentDict, true, true); + // Expand with env=true, empty=true, subDict=false + // with comments stripped. + // Special handling of $[...] syntax enabled. + expressions::exprString::inplaceExpand(s, parentDict, true); stringOps::inplaceTrim(s); // An extraneous trailing ';' is a common input error, catch it now. diff --git a/src/OpenFOAM/expressions/exprEntry/expressionEntry.C b/src/OpenFOAM/expressions/exprEntry/expressionEntry.C index a350c3ed18..6e83f0b738 100644 --- a/src/OpenFOAM/expressions/exprEntry/expressionEntry.C +++ b/src/OpenFOAM/expressions/exprEntry/expressionEntry.C @@ -223,12 +223,15 @@ void Foam::exprTools::expressionEntry::inplaceExpand stringOps::inplaceTrim(varName); // Allow recursive plain expansion for the *variable* name. - // This means "$[(vector) var${index] ]" should work - stringOps::inplaceExpand(varName, dict); + // This means "$[(vector) var${index} ]" should work + + // Expand with env=true, empty=true, subDict=false + stringOps::inplaceExpand(varName, dict, true, true, false); // Length of original text to replace (incl. decorators) const auto replaceLen = (varEnd - varBeg + 1); + // Get primitiveEntry with env=false, subDict=false const entry* eptr = getVariableOrDie(varName, dict); std::string varValue; @@ -236,7 +239,17 @@ void Foam::exprTools::expressionEntry::inplaceExpand if (castTo.empty()) { // Serialized with spaces - varValue = eptr->stream().toString(); + ITstream& its = eptr->stream(); + + if (its.size() == 1 && its[0].isStringType()) + { + // Already a string-type (WORD, STRING, ...). Just copy. + varValue = its[0].stringToken(); + } + else + { + varValue = its.toString(); + } } else { @@ -258,7 +271,8 @@ void Foam::exprTools::expressionEntry::inplaceExpand // - this is done second such that $[(vector) xyz] entries will have // been properly expanded by this stage - stringOps::inplaceExpand(s, dict); + // Expand with env=true, empty=true, subDict=false + stringOps::inplaceExpand(s, dict, true, true, false); } diff --git a/src/OpenFOAM/expressions/exprEntry/expressionEntry.H b/src/OpenFOAM/expressions/exprEntry/expressionEntry.H index b42c8efd94..7c1f983928 100644 --- a/src/OpenFOAM/expressions/exprEntry/expressionEntry.H +++ b/src/OpenFOAM/expressions/exprEntry/expressionEntry.H @@ -134,7 +134,14 @@ public: //- Generic concatenate tokens to space-separated string. inline static string evaluate(const entry& e); - //- Inplace expand expression with dictionary entries + //- Inplace expand expression with dictionary variables/entries + // + // \par Expansion behaviour + // - alternatives = True + // - environment = True + // - allow empty = True + // - subDict = False + // . static void inplaceExpand ( std::string& s, diff --git a/src/OpenFOAM/expressions/exprString/exprString.H b/src/OpenFOAM/expressions/exprString/exprString.H index 612022d0fe..a7aa13f577 100644 --- a/src/OpenFOAM/expressions/exprString/exprString.H +++ b/src/OpenFOAM/expressions/exprString/exprString.H @@ -118,7 +118,14 @@ public: // Static Member Functions //- Inplace expansion with dictionary variables, - //- and strip C/C++ comments from the input + //- and strip C/C++ comments from the input. + // + // \par Expansion behaviour + // - alternatives = True + // - environment = True + // - allow empty = True + // - subDict = False + // . static void inplaceExpand ( std::string& str, @@ -127,7 +134,9 @@ public: ); //- Get and expand expression with dictionary entries, - //- optionally strip C/C++ comments from the input + //- optionally strip C/C++ comments from the input. + // + // Expansion behaviour as per inplaceExpand static exprString getExpression ( const word& name, diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C index f0823bad14..dc3a12d84b 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.C +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.C @@ -252,7 +252,7 @@ static inline std::string entryToString if (pe.size() == 1 && pe[0].isStringType()) { - // Already a string-type. Just copy. + // Already a string-type (WORD, STRING, ...). Just copy. str = pe[0].stringToken(); } else diff --git a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H index 9b12511191..51d3a4e37d 100644 --- a/src/OpenFOAM/primitives/strings/stringOps/stringOps.H +++ b/src/OpenFOAM/primitives/strings/stringOps/stringOps.H @@ -28,8 +28,7 @@ Namespace Foam::stringOps Description - Collection of static functions to do various simple string-related - operations + Collection of static functions for various string-related operations SourceFiles stringOps.C @@ -93,34 +92,37 @@ namespace stringOps //- Does \b not use environment values. // // Expansion includes: - // -# variables + // -# Variables // - \c $VAR // - \c ${VAR} - // - \c ${VAR:-defValue} - // - \c ${VAR:+altValue} // - // Default and alternative values as per the POSIX shell: - // \code - // 1. ${parameter:-defValue} - // 2. ${parameter:+altValue} - // \endcode - // -# If parameter is unset or null, the \c defValue is substituted. - // Otherwise, the value of parameter is substituted. - // -# If parameter is unset or null, nothing is substituted. - // Otherwise the \c altValue is substituted. + // -# Default and alternative values as per the POSIX shell: + // - \c ${parameter:-defValue} + // If parameter is unset or null, the \c defValue is substituted. + // Otherwise, the value of parameter is substituted. + // - \c ${parameter:+altValue} + // If parameter is unset or null, nothing is substituted. + // Otherwise the \c altValue is substituted. // . // // General behaviour: // - Unknown entries are removed silently. - // - Malformed entries (eg, brace mismatch, sigil followed by bad chars) - // are left as is. - // - // Currently only used by dynamicCode. + // - Malformed entries (eg, brace mismatch, sigil followed by unknown + // characters) are left as is. // // \param[in,out] s The string to modify inplace. // \param mapping The lookup table // \param sigil The leading sigil. Can be changed to avoid conflict // with other string expansions. (default: '$') + // + // \par Expansion behaviour + // - alternatives = True + // - environment = False + // - allow empty = True + // - subDict = Not applicable + // . + // + // \note Currently only used by Foam::dynamicCode. void inplaceExpand ( std::string& s, @@ -133,17 +135,17 @@ namespace stringOps //- and (optionally) environment variables. // // Expansion includes: - // -# dictionary variables and (optionally) environment variables + // -# Dictionary variables and (optionally) environment variables // - \c $VAR // - \c ${VAR} // - \c ${VAR:-defValue} // - \c ${VAR:+altValue} - // -# mathematical evaluation using stringOps::evaluate + // -# Mathematical evaluation using stringOps::evaluate // - \c ${{EXPR}} - // -# current directory + // -# Current directory // - leading "./" // : the current directory - Foam::cwd() - // -# leading tag expansion for commonly used directories + // -# Leading tag expansion for commonly used directories // - \/ // : user/group/other OpenFOAM etc directory // - \[ugoa]+)\>/ @@ -154,24 +156,21 @@ namespace stringOps // : The \c $FOAM_CASE/constant directory // - \/ // : The \c $FOAM_CASE/system directory - // -# tilde expansion + // -# Tilde expansion // - leading "~/" : home directory // - leading "~user" : home directory for specified user - // - // Default and alternative values as per the POSIX shell: - // \code - // 1. ${parameter:-defValue} - // 2. ${parameter:+altValue} - // \endcode - // -# If parameter is unset or null, the \c defValue is substituted. - // Otherwise, the value of parameter is substituted. - // -# If parameter is unset or null, nothing is substituted. - // Otherwise the \c altValue is substituted. + // -# Default and alternative values as per the POSIX shell: + // - \c ${parameter:-defValue} + // If parameter is unset or null, the \c defValue is substituted. + // Otherwise, the value of parameter is substituted. + // - \c ${parameter:+altValue} + // If parameter is unset or null, nothing is substituted. + // Otherwise the \c altValue is substituted. // . // // General behaviour: - // - Malformed entries (eg, brace mismatch, sigil followed by bad chars) - // are left as is. + // - Malformed entries (eg, brace mismatch, sigil followed by unknown + // characters) are left as is. // - Supports recursive variable expansions. // For example, "${var${num}}" and "${{100 + ${var}}}" // @@ -186,7 +185,14 @@ namespace stringOps // // \sa Foam::findEtcEntry(), Foam::findEtcEntries(), stringOps::evaluate() // - // \note this function has too many parameters and should generally + // \par Expansion behaviour + // - alternatives = True + // - environment = Given by parameter + // - allow empty = Given by parameter + // - subDict = Given by parameter (default: False) + // . + // + // \note This function has too many parameters and should generally // be avoided in user coding. void inplaceExpand ( @@ -217,7 +223,16 @@ namespace stringOps // Empty expansions are allowed. // Serialization of subDict entries is permitted. // - // \sa stringOps::inplaceExpand(std::string&, const dictionary&, bool, bool, bool, char) + // \sa + // stringOps::inplaceExpand + // (std::string&, const dictionary&, bool, bool, bool, char) + // + // \par Expansion behaviour + // - alternatives = True + // - environment = True + // - allow empty = True + // - subDict = True + // . void inplaceExpand ( std::string& s, @@ -242,9 +257,17 @@ namespace stringOps //- variables // // The expansion behaviour is identical to - // stringOps::inplaceExpand(std::string&, const dictionary&, bool, bool, bool, char) + // stringOps::inplaceExpand + // (std::string&, const dictionary&, bool, bool, bool, char) // except that there is no dictionary and the environment variables // are always enabled. + // + // \par Expansion behaviour + // - alternatives = True + // - environment = True + // - allow empty = Given by parameter (default: False) + // - subDict = Not applicable + // . void inplaceExpand ( std::string& s,