1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.
#ifndef INCLUDED_GRAS_DETAIL_CALLABLE_HPP
#define INCLUDED_GRAS_DETAIL_CALLABLE_HPP
#include <PMC/Containers.hpp> //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 <typename ClassType, typename ReturnType, $expand('typename A%d', $NARGS)>
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<PMCList>();
if (a.size() < $NARGS) throw a;
return PMC_M((_obj->*_fcn)($expand('a[%d].safe_as<A%d>()', $NARGS)));
}
ClassType *_obj; Fcn _fcn;
};
template <typename ClassType, typename ReturnType, $expand('typename A%d', $NARGS)>
void Callable::register_call(const std::string &name, ReturnType(ClassType::*fcn)($expand('const A%d &', $NARGS)))
{
ClassType *obj = dynamic_cast<ClassType *>(this);
void *fr = new CallableRegistryEntryImpl$(NARGS)<ClassType, ReturnType, $expand('A%d', $NARGS)>(obj, fcn);
_register_call(name, fr);
}
template <typename ClassType, $expand('typename A%d', $NARGS)>
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<PMCList>();
if (a.size() < $NARGS) throw a;
(_obj->*_fcn)($expand('a[%d].safe_as<A%d>()', $NARGS)); return PMCC();
}
ClassType *_obj; Fcn _fcn;
};
template <typename ClassType, $expand('typename A%d', $NARGS)>
void Callable::register_call(const std::string &name, void(ClassType::*fcn)($expand('const A%d &', $NARGS)))
{
ClassType *obj = dynamic_cast<ClassType *>(this);
void *fr = new CallableRegistryEntryImplVoid$(NARGS)<ClassType, $expand('A%d', $NARGS)>(obj, fcn);
_register_call(name, fr);
}
#end for
#for $NARGS in range($MAX_ARGS)
/***********************************************************************
* Call implementations with $NARGS args
**********************************************************************/
template <typename ReturnType, $expand('typename A%d', $NARGS)>
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<ReturnType>();
}
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*/
|