/******************************************************************************* * * MIT License * * Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #pragma once #include #include #include #include #include #include namespace TensileLite { /** * \ingroup Tensile * \defgroup Properties Properties and Predicates * * @brief Abstract expression evaluation * * Property: \copydoc TensileLite::Property * * Predicate: \copydoc TensileLite::Predicates::Predicate */ /** * \addtogroup Properties * @{ */ /** * @brief Simplifies implementation of `ToString()` for Property subclasses * which may have `index` and/or `value` members. */ template struct PropertyHelper { }; template struct PropertyHelper { static std::string ToString(Class const& obj) { return obj.type(); } }; template struct PropertyHelper { static std::string ToString(Class const& obj) { return concatenate(obj.type(), "(", obj.value, ")"); } }; template struct PropertyHelper { static std::string ToString(Class const& obj) { return concatenate(obj.type(), "(", obj.index, ")"); } }; template struct PropertyHelper { static std::string ToString(Class const& obj) { return concatenate(obj.type(), "(index=", obj.index, ", value=", obj.value, ")"); } }; /** * Abstract object which retrieves a value from another object. */ template class Property { public: /** * Name which uniquely identifies each subclass. */ virtual std::string type() const = 0; virtual ~Property() = default; /** * Retrieve the value from the specified object. */ virtual Value operator()(Object const& object) const = 0; virtual std::string toString() const = 0; /** * Retrieve the value from the specified object, while printing * relevant debug information to the specified stream. */ virtual Value debugEval(Object const& object, std::ostream& stream) const { Value rv = (*this)(object); stream << *this << ": " << rv; return rv; } template void debugEvalCmpBuildDetails(std::ostringstream& ss, Tp prob, Tpv prob_val, Tc cmp, Ts sol, Tsv sol_val, T... args) const { ss << prob << "=" << prob_val << " " << cmp << " " << sol << "=" << sol_val; if constexpr(sizeof...(args) >= 5) { ss << ", "; debugEvalCmpBuildDetails(ss, args...); } } /// Formats comparison-based predicate debug output via PredicateDebugger::printRow. /// Usage: debugEvalCmp(obj, stream, "prob", val1, "==", "sol", val2, ...) template Value debugEvalCmp(Object const& object, std::ostream& stream, T... args) const { Value rv = (*this)(object); std::ostringstream details; debugEvalCmpBuildDetails(details, args...); PredicateDebugger::printRow(stream, rv, this->type(), details.str()); return rv; } }; /** * @brief CRTP helper class which simplifies implementation of Property * subclasses. * * Implements the `type()` and `toString()` methods automatically. * * The subclass must: * - Implement a `static std::string Type()` function which returns a * unique name for the class. * - Have `HasIndex` and `HasValue` value definitions which match the * reality of if it has `index` and/or `value` members. * * \see https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ template class Property_CRTP : public Property { public: virtual std::string type() const final { return Class::Type(); } virtual std::string toString() const { Class const& this_typed = dynamic_cast(*this); return PropertyHelper::ToString(this_typed); } }; template inline std::ostream& operator<<(std::ostream& stream, Property const& prop) { return stream << prop.toString(); } template inline std::ostream& operator<<(std::ostream& stream, std::vector>> const& props) { stream << "("; bool first = true; for(auto const& v : props) { if(!first) stream << ", "; first = false; stream << *v; } stream << ")"; return stream; } /** * @} */ /** * \ingroup Properties * \defgroup PropertyClasses Property Classes * * @brief Individual Property classes */ } // namespace TensileLite