24#ifndef PXR_USD_SDF_PREDICATE_PROGRAM_H
25#define PXR_USD_SDF_PREDICATE_PROGRAM_H
28#include "pxr/usd/sdf/api.h"
31#include "pxr/base/tf/functionTraits.h"
32#include "pxr/base/vt/value.h"
34#include "pxr/usd/sdf/predicateExpression.h"
35#include "pxr/usd/sdf/predicateLibrary.h"
36#include "pxr/usd/sdf/invoke.hpp"
38#include <initializer_list>
43PXR_NAMESPACE_OPEN_SCOPE
46template <
class DomainType>
50template <
class DomainType>
67template <
class DomainType>
71 using PredicateFunction =
75 SdfLinkPredicateExpression<DomainType>(
80 explicit operator bool()
const {
90 auto funcIter = _funcs.cbegin();
91 auto opIter = _ops.cbegin(), opEnd = _ops.cend();
113 auto shortCircuit = [&]() {
114 const int origNest = nest;
115 for (; opIter != opEnd; ++opIter) {
117 case Call: ++funcIter;
break;
118 case Not:
case And:
case Or:
break;
119 case Open: ++nest;
break;
121 if (--nest == origNest) {
131 for (; opIter != opEnd; ++opIter) {
136 case Not: result = !result;
break;
138 const bool decidingValue = *opIter != And;
141 if (result == decidingValue) {
146 case Open: ++nest;
break;
147 case Close: --nest;
break;
154 enum _Op { Call, Not, Open, Close, And, Or };
155 std::vector<_Op> _ops;
156 std::vector<PredicateFunction> _funcs;
163template <
class DomainType>
176 auto exprToProgramOp = [](Expr::Op op) {
178 case Expr::Call:
return Program::Call;
179 case Expr::Not:
return Program::Not;
180 case Expr::ImpliedAnd:
case Expr::And:
return Program::And;
181 case Expr::Or:
return Program::Or;
183 return static_cast<typename Program::_Op
>(-1);
186 auto translateLogic = [&](Expr::Op op,
int argIndex) {
190 prog._ops.push_back(Program::Not);
193 case Expr::ImpliedAnd:
197 prog._ops.push_back(exprToProgramOp(op));
198 prog._ops.push_back(Program::Open);
200 else if (argIndex == 2) {
201 prog._ops.push_back(Program::Close);
209 auto translateCall = [&](Expr::FnCall
const &call) {
212 if (
auto fn = lib._BindCall(call.funcName, call.args)) {
213 prog._funcs.push_back(std::move(fn));
214 prog._ops.push_back(Program::Call);
220 errs +=
"Failed to bind call of " + call.funcName;
225 expr.
Walk(translateLogic, translateCall);
234PXR_NAMESPACE_CLOSE_SCOPE
Low-level utilities for informing users of various internal and external diagnostic conditions.
Represents a logical expression syntax tree consisting of predicate function calls joined by the logi...
SDF_API void Walk(TfFunctionRef< void(Op, int)> logic, TfFunctionRef< void(FnCall const &)> call) const
Walk this expression's syntax tree in depth-first order, calling call with the current function call ...
Represents the result of a predicate function: a pair of the boolean result and a Constancy token ind...
static SdfPredicateFunctionResult MakeConstant(bool value)
Create with value and 'ConstantOverDescendants'.
void SetAndPropagateConstancy(SdfPredicateFunctionResult other)
Set this result's value to other's value, and propagate constancy; if both this and other are Constan...
Represents a library of predicate functions for use with SdfPredicateExpression.
std::function< SdfPredicateFunctionResult(DomainType const &)> PredicateFunction
The type of a bound function, the result of binding passed arguments.
Represents a callable "program", the result of linking an SdfPredicateExpression with an SdfPredicate...
friend SdfPredicateProgram SdfLinkPredicateExpression(SdfPredicateExpression const &expr, SdfPredicateLibrary< DomainType > const &lib)
Link expr with lib and return a callable program that evaluates expr on given objects of the DomainTy...
SdfPredicateFunctionResult operator()(DomainType const &obj) const
Run the predicate program on obj, and return the result.
#define TF_RUNTIME_ERROR(fmt, args)
Issue a generic runtime error, but continue execution.