Commit 9c43baa8 authored by Jason Rhinelander's avatar Jason Rhinelander

Split def/non-def priority glue; use pybind11 hasattr

There's little point in doing the priority override most of the time, so
this splits the two and only uses the full priority-overriding glue
class if the class actually has a ..._priority method; otherwise a
simpler class that doesn't override priority is used.

Switched to pybind's `hasattr` method rather than the now-deprecated
`.attr()`-in-bool-context code.
parent 4a32b96d
......@@ -3,20 +3,25 @@
namespace pyeris { namespace core {
void OptimizerGlue::applyGlue(std::shared_ptr<eris::Simulation> sim, eris::SharedMember<Member> shmem, const py::object &member) {
#define IF_CALLABLE_THEN_SPAWN(METHOD, CLASS) \
if (py::function(member.attr(#METHOD)).check()) sim->spawn<CLASS>(shmem);
#define IF_TYPE_THEN_SPAWN(METHOD, CLASS) \
if (hasattr(member, #METHOD)) { \
if (hasattr(member, #METHOD "_priority")) \
sim->spawn<CLASS##_Pri>(shmem); \
else \
sim->spawn<CLASS>(shmem); \
}
IF_CALLABLE_THEN_SPAWN(inter_begin, InterBeginGlue);
IF_CALLABLE_THEN_SPAWN(inter_optimize, InterOptimizeGlue);
IF_CALLABLE_THEN_SPAWN(inter_apply, InterApplyGlue);
IF_CALLABLE_THEN_SPAWN(inter_advance, InterAdvanceGlue);
IF_CALLABLE_THEN_SPAWN(intra_initialize, IntraInitializeGlue);
IF_TYPE_THEN_SPAWN(inter_begin, InterBeginGlue);
IF_TYPE_THEN_SPAWN(inter_optimize, InterOptimizeGlue);
IF_TYPE_THEN_SPAWN(inter_apply, InterApplyGlue);
IF_TYPE_THEN_SPAWN(inter_advance, InterAdvanceGlue);
IF_TYPE_THEN_SPAWN(intra_initialize, IntraInitializeGlue);
IF_CALLABLE_THEN_SPAWN(intra_reset, IntraResetGlue);
IF_CALLABLE_THEN_SPAWN(intra_optimize, IntraOptimizeGlue);
IF_CALLABLE_THEN_SPAWN(intra_reoptimize, IntraReoptimizeGlue);
IF_CALLABLE_THEN_SPAWN(intra_apply, IntraApplyGlue);
IF_CALLABLE_THEN_SPAWN(intra_finish, IntraFinishGlue);
IF_TYPE_THEN_SPAWN(intra_reset, IntraResetGlue);
IF_TYPE_THEN_SPAWN(intra_optimize, IntraOptimizeGlue);
IF_TYPE_THEN_SPAWN(intra_reoptimize, IntraReoptimizeGlue);
IF_TYPE_THEN_SPAWN(intra_apply, IntraApplyGlue);
IF_TYPE_THEN_SPAWN(intra_finish, IntraFinishGlue);
}
}}
......@@ -34,12 +34,6 @@ protected:
}
/// Returns the parent (i.e. the member we are glue for), cast to a py::object
py::object parent() const { return py::cast(parent_.get()); }
/** Returns a py::function object that, when called, calls the given (python) method on the
* parent. Call `.check()` on the returned object to determine whether the method actually
* exists--invoking the function without checking will trigger an exception for non-existent
* methods.
*/
py::function method(const char* name) const { return py::function(parent().attr(name)); }
private:
SharedMember<Member> parent_;
};
......@@ -49,34 +43,40 @@ private:
// (but using method_naming instead of methodNaming). The inter_whatever_priority method is
// optional: if it isn't defined, we dispatch to the base class default value instead.
// Macro parameters:
// NAME - the class name
// NAME - the class name (will be used as is, and have version with "_Pri" appended for classes that
// override priority)
// ERIS_BASE - the eris optimizer base class (e.g. eris::interopt::Begin)
// PYTHON_METHOD - the python method name, e.g. inter_begin
// ERIS_METHOD - the eris method name, e.g. interBegin
// TYPE - the return type of ERIS_METHOD, e.g. void for most; bool for intraReoptimize
#define OPTIMIZER_GLUE_CLASS(NAME, ERIS_BASE, PYTHON_METHOD, ERIS_METHOD, TYPE) \
class NAME final : public OptimizerGlue, public ERIS_BASE { \
#define OPTIMIZER_GLUE_CLASSES(NAME, ERIS_BASE, PYTHON_METHOD, ERIS_METHOD, TYPE) \
class NAME : public OptimizerGlue, public ERIS_BASE { \
public: \
using OptimizerGlue::OptimizerGlue; \
virtual TYPE ERIS_METHOD() override { return method(#PYTHON_METHOD)().cast<TYPE>(); } \
virtual double ERIS_METHOD##Priority() const override { \
auto m = method(#PYTHON_METHOD "_priority"); \
return m.check() ? m().cast<double>() : ERIS_BASE::ERIS_METHOD##Priority(); \
TYPE ERIS_METHOD() override { return parent().attr(#PYTHON_METHOD)().cast<TYPE>(); } \
}; \
class NAME##_Pri : public NAME { \
public: \
using NAME::NAME; \
double ERIS_METHOD##Priority() const override { \
if (py::hasattr(parent(), #PYTHON_METHOD "_priority")) \
return parent().attr(#PYTHON_METHOD "_priority")().cast<double>(); \
return ERIS_BASE::ERIS_METHOD##Priority(); \
} \
}
OPTIMIZER_GLUE_CLASS(InterBeginGlue, eris::interopt::Begin, inter_begin, interBegin, void);
OPTIMIZER_GLUE_CLASS(InterOptimizeGlue, eris::interopt::Optimize, inter_optimize, interOptimize, void);
OPTIMIZER_GLUE_CLASS(InterApplyGlue, eris::interopt::Apply, inter_apply, interApply, void);
OPTIMIZER_GLUE_CLASS(InterAdvanceGlue, eris::interopt::Advance, inter_advance, interAdvance, void);
OPTIMIZER_GLUE_CLASS(IntraInitializeGlue, eris::intraopt::Initialize, intra_initialize, intraInitialize, void);
OPTIMIZER_GLUE_CLASSES(InterBeginGlue, eris::interopt::Begin, inter_begin, interBegin, void);
OPTIMIZER_GLUE_CLASSES(InterOptimizeGlue, eris::interopt::Optimize, inter_optimize, interOptimize, void);
OPTIMIZER_GLUE_CLASSES(InterApplyGlue, eris::interopt::Apply, inter_apply, interApply, void);
OPTIMIZER_GLUE_CLASSES(InterAdvanceGlue, eris::interopt::Advance, inter_advance, interAdvance, void);
OPTIMIZER_GLUE_CLASSES(IntraInitializeGlue, eris::intraopt::Initialize, intra_initialize, intraInitialize, void);
OPTIMIZER_GLUE_CLASS(IntraResetGlue, eris::intraopt::Reset, intra_reset, intraReset, void);
OPTIMIZER_GLUE_CLASS(IntraOptimizeGlue, eris::intraopt::Optimize, intra_optimize, intraOptimize, void);
OPTIMIZER_GLUE_CLASS(IntraReoptimizeGlue, eris::intraopt::Reoptimize, intra_reoptimize, intraReoptimize, bool);
OPTIMIZER_GLUE_CLASS(IntraApplyGlue, eris::intraopt::Apply, intra_apply, intraApply, void);
OPTIMIZER_GLUE_CLASS(IntraFinishGlue, eris::intraopt::Finish, intra_finish, intraFinish, void);
OPTIMIZER_GLUE_CLASSES(IntraResetGlue, eris::intraopt::Reset, intra_reset, intraReset, void);
OPTIMIZER_GLUE_CLASSES(IntraOptimizeGlue, eris::intraopt::Optimize, intra_optimize, intraOptimize, void);
OPTIMIZER_GLUE_CLASSES(IntraReoptimizeGlue, eris::intraopt::Reoptimize, intra_reoptimize, intraReoptimize, bool);
OPTIMIZER_GLUE_CLASSES(IntraApplyGlue, eris::intraopt::Apply, intra_apply, intraApply, void);
OPTIMIZER_GLUE_CLASSES(IntraFinishGlue, eris::intraopt::Finish, intra_finish, intraFinish, void);
#undef OPTIMIZER_GLUE_CLASS
#undef OPTIMIZER_GLUE_CLASSES
}}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment