// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information. #ifndef INCLUDED_GRAS_DETAIL_CALLABLE_HPP #define INCLUDED_GRAS_DETAIL_CALLABLE_HPP #include //PMCList namespace gras { /*********************************************************************** * Registration entry base class **********************************************************************/ struct GRAS_API CallableRegistryEntry { CallableRegistryEntry(void); virtual ~CallableRegistryEntry(void); virtual PMCC call(const PMCC &args) = 0; }; #for $NARGS in range($MAX_ARGS) /*********************************************************************** * Registration for return with $NARGS args **********************************************************************/ template struct CallableRegistryEntryImpl$(NARGS) : CallableRegistryEntry { typedef ReturnType(ClassType::*Fcn)($expand('const A%d &', $NARGS)); CallableRegistryEntryImpl$(NARGS)(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); if (a.size() < $NARGS) throw a; return PMC_M((_obj->*_fcn)($expand('a[%d].safe_as()', $NARGS))); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &name, ReturnType(ClassType::*fcn)($expand('const A%d &', $NARGS))) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImpl$(NARGS)(obj, fcn); _register_call(name, fr); } template struct CallableRegistryEntryImplVoid$(NARGS) : CallableRegistryEntry { typedef void(ClassType::*Fcn)($expand('const A%d &', $NARGS)); CallableRegistryEntryImplVoid$(NARGS)(ClassType *obj, Fcn fcn): _obj(obj), _fcn(fcn){} PMCC call(const PMCC &args) { const PMCList &a = args.as(); if (a.size() < $NARGS) throw a; (_obj->*_fcn)($expand('a[%d].safe_as()', $NARGS)); return PMCC(); } ClassType *_obj; Fcn _fcn; }; template void Callable::register_call(const std::string &name, void(ClassType::*fcn)($expand('const A%d &', $NARGS))) { ClassType *obj = dynamic_cast(this); void *fr = new CallableRegistryEntryImplVoid$(NARGS)(obj, fcn); _register_call(name, fr); } #end for #for $NARGS in range($MAX_ARGS) /*********************************************************************** * Call implementations with $NARGS args **********************************************************************/ template ReturnType Callable::x(const std::string &name, $expand('const A%d &a%d', $NARGS)) { PMCList args($NARGS); #for $i in range($NARGS): args[$i] = PMC_M(a$i); #end for PMCC r = _handle_call(name, PMC_M(args)); return r.safe_as(); } template <$expand('typename A%d', $NARGS)> void Callable::x(const std::string &name, $expand('const A%d &a%d', $NARGS)) { PMCList args($NARGS); #for $i in range($NARGS): args[$i] = PMC_M(a$i); #end for _handle_call(name, PMC_M(args)); } #end for } //namespace gras #endif /*INCLUDED_GRAS_DETAIL_CALLABLE_HPP*/