make_binders.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. # -*- coding: ibm850 -*-
  2. template_typed = """
  3. #ifdef TYPED_METHOD_BIND
  4. template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
  5. class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind {
  6. public:
  7. $ifret R$ $ifnoret void$ (T::*method)($arg, P@$) $ifconst const$;
  8. #ifdef DEBUG_METHODS_ENABLED
  9. virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); }
  10. virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
  11. $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$
  12. $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA;
  13. $
  14. return GodotTypeInfo::METADATA_NONE;
  15. }
  16. Variant::Type _get_argument_type(int p_argument) const {
  17. $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$
  18. $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE;
  19. $
  20. return Variant::NIL;
  21. }
  22. virtual PropertyInfo _gen_argument_type_info(int p_argument) const {
  23. $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$
  24. $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info();
  25. $
  26. return PropertyInfo();
  27. }
  28. #endif
  29. virtual String get_instance_class() const {
  30. return T::get_class_static();
  31. }
  32. virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Variant::CallError& r_error) {
  33. T *instance=Object::cast_to<T>(p_object);
  34. r_error.error=Variant::CallError::CALL_OK;
  35. #ifdef DEBUG_METHODS_ENABLED
  36. ERR_FAIL_COND_V(!instance,Variant());
  37. if (p_arg_count>get_argument_count()) {
  38. r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
  39. r_error.argument=get_argument_count();
  40. return Variant();
  41. }
  42. if (p_arg_count<(get_argument_count()-get_default_argument_count())) {
  43. r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
  44. r_error.argument=get_argument_count()-get_default_argument_count();
  45. return Variant();
  46. }
  47. $arg CHECK_ARG(@);
  48. $
  49. #endif
  50. $ifret Variant ret = $(instance->*method)($arg, _VC(@)$);
  51. $ifret return Variant(ret);$
  52. $ifnoret return Variant();$
  53. }
  54. #ifdef PTRCALL_ENABLED
  55. virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) {
  56. T *instance=Object::cast_to<T>(p_object);
  57. $ifret PtrToArg<R>::encode( $ (instance->*method)($arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret)$ ;
  58. }
  59. #endif
  60. MethodBind$argc$$ifret R$$ifconst C$ () {
  61. #ifdef DEBUG_METHODS_ENABLED
  62. _set_const($ifconst true$$ifnoconst false$);
  63. _generate_argument_types($argc$);
  64. #else
  65. set_argument_count($argc$);
  66. #endif
  67. $ifret _set_returns(true); $
  68. };
  69. };
  70. template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
  71. MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) {
  72. MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) );
  73. a->method=p_method;
  74. return a;
  75. }
  76. #endif
  77. """
  78. template = """
  79. #ifndef TYPED_METHOD_BIND
  80. $iftempl template<$ $ifret class R$ $ifretargs ,$ $arg, class P@$ $iftempl >$
  81. class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind {
  82. public:
  83. StringName type_name;
  84. $ifret R$ $ifnoret void$ (__UnexistingClass::*method)($arg, P@$) $ifconst const$;
  85. #ifdef DEBUG_METHODS_ENABLED
  86. virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); }
  87. virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
  88. $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$
  89. $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA;
  90. $
  91. return GodotTypeInfo::METADATA_NONE;
  92. }
  93. Variant::Type _get_argument_type(int p_argument) const {
  94. $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$
  95. $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE;
  96. $
  97. return Variant::NIL;
  98. }
  99. virtual PropertyInfo _gen_argument_type_info(int p_argument) const {
  100. $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$
  101. $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info();
  102. $
  103. return PropertyInfo();
  104. }
  105. #endif
  106. virtual String get_instance_class() const {
  107. return type_name;
  108. }
  109. virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Variant::CallError& r_error) {
  110. __UnexistingClass *instance = (__UnexistingClass*)p_object;
  111. r_error.error=Variant::CallError::CALL_OK;
  112. #ifdef DEBUG_METHODS_ENABLED
  113. ERR_FAIL_COND_V(!instance,Variant());
  114. if (p_arg_count>get_argument_count()) {
  115. r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
  116. r_error.argument=get_argument_count();
  117. return Variant();
  118. }
  119. if (p_arg_count<(get_argument_count()-get_default_argument_count())) {
  120. r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
  121. r_error.argument=get_argument_count()-get_default_argument_count();
  122. return Variant();
  123. }
  124. $arg CHECK_ARG(@);
  125. $
  126. #endif
  127. $ifret Variant ret = $(instance->*method)($arg, _VC(@)$);
  128. $ifret return Variant(ret);$
  129. $ifnoret return Variant();$
  130. }
  131. #ifdef PTRCALL_ENABLED
  132. virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) {
  133. __UnexistingClass *instance = (__UnexistingClass*)p_object;
  134. $ifret PtrToArg<R>::encode( $ (instance->*method)($arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret) $ ;
  135. }
  136. #endif
  137. MethodBind$argc$$ifret R$$ifconst C$ () {
  138. #ifdef DEBUG_METHODS_ENABLED
  139. _set_const($ifconst true$$ifnoconst false$);
  140. _generate_argument_types($argc$);
  141. #else
  142. set_argument_count($argc$);
  143. #endif
  144. $ifret _set_returns(true); $
  145. };
  146. };
  147. template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
  148. MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) {
  149. MethodBind$argc$$ifret R$$ifconst C$ $iftempl <$ $ifret R$ $ifretargs ,$ $arg, P@$ $iftempl >$ * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$ $iftempl <$ $ifret R$ $ifretargs ,$ $arg, P@$ $iftempl >$) );
  150. union {
  151. $ifret R$ $ifnoret void$ (T::*sm)($arg, P@$) $ifconst const$;
  152. $ifret R$ $ifnoret void$ (__UnexistingClass::*dm)($arg, P@$) $ifconst const$;
  153. } u;
  154. u.sm=p_method;
  155. a->method=u.dm;
  156. a->type_name=T::get_class_static();
  157. return a;
  158. }
  159. #endif
  160. """
  161. template_typed_free_func = """
  162. #ifdef TYPED_METHOD_BIND
  163. template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
  164. class FunctionBind$argc$$ifret R$$ifconst C$ : public MethodBind {
  165. public:
  166. $ifret R$ $ifnoret void$ (*method) ($ifconst const$ T *$ifargs , $$arg, P@$);
  167. #ifdef DEBUG_METHODS_ENABLED
  168. virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); }
  169. virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const {
  170. $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$
  171. $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA;
  172. $
  173. return GodotTypeInfo::METADATA_NONE;
  174. }
  175. Variant::Type _get_argument_type(int p_argument) const {
  176. $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$
  177. $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE;
  178. $
  179. return Variant::NIL;
  180. }
  181. virtual PropertyInfo _gen_argument_type_info(int p_argument) const {
  182. $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$
  183. $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info();
  184. $
  185. return PropertyInfo();
  186. }
  187. #endif
  188. virtual String get_instance_class() const {
  189. return T::get_class_static();
  190. }
  191. virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Variant::CallError& r_error) {
  192. T *instance=Object::cast_to<T>(p_object);
  193. r_error.error=Variant::CallError::CALL_OK;
  194. #ifdef DEBUG_METHODS_ENABLED
  195. ERR_FAIL_COND_V(!instance,Variant());
  196. if (p_arg_count>get_argument_count()) {
  197. r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
  198. r_error.argument=get_argument_count();
  199. return Variant();
  200. }
  201. if (p_arg_count<(get_argument_count()-get_default_argument_count())) {
  202. r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
  203. r_error.argument=get_argument_count()-get_default_argument_count();
  204. return Variant();
  205. }
  206. $arg CHECK_ARG(@);
  207. $
  208. #endif
  209. $ifret Variant ret = $(method)(instance$ifargs , $$arg, _VC(@)$);
  210. $ifret return Variant(ret);$
  211. $ifnoret return Variant();$
  212. }
  213. #ifdef PTRCALL_ENABLED
  214. virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) {
  215. T *instance=Object::cast_to<T>(p_object);
  216. $ifret PtrToArg<R>::encode( $ (method)(instance$ifargs , $$arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret)$ ;
  217. }
  218. #endif
  219. FunctionBind$argc$$ifret R$$ifconst C$ () {
  220. #ifdef DEBUG_METHODS_ENABLED
  221. _set_const($ifconst true$$ifnoconst false$);
  222. _generate_argument_types($argc$);
  223. #else
  224. set_argument_count($argc$);
  225. #endif
  226. $ifret _set_returns(true); $
  227. };
  228. };
  229. template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$>
  230. MethodBind* create_method_bind($ifret R$ $ifnoret void$ (*p_method)($ifconst const$ T *$ifargs , $$arg, P@$) ) {
  231. FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) );
  232. a->method=p_method;
  233. return a;
  234. }
  235. #endif
  236. """
  237. def make_version(template, nargs, argmax, const, ret):
  238. intext = template
  239. from_pos = 0
  240. outtext = ""
  241. while True:
  242. to_pos = intext.find("$", from_pos)
  243. if to_pos == -1:
  244. outtext += intext[from_pos:]
  245. break
  246. else:
  247. outtext += intext[from_pos:to_pos]
  248. end = intext.find("$", to_pos + 1)
  249. if end == -1:
  250. break # ignore
  251. macro = intext[to_pos + 1 : end]
  252. cmd = ""
  253. data = ""
  254. if macro.find(" ") != -1:
  255. cmd = macro[0 : macro.find(" ")]
  256. data = macro[macro.find(" ") + 1 :]
  257. else:
  258. cmd = macro
  259. if cmd == "argc":
  260. outtext += str(nargs)
  261. if cmd == "ifret" and ret:
  262. outtext += data
  263. if cmd == "ifargs" and nargs:
  264. outtext += data
  265. if cmd == "ifretargs" and nargs and ret:
  266. outtext += data
  267. if cmd == "ifconst" and const:
  268. outtext += data
  269. elif cmd == "ifnoconst" and not const:
  270. outtext += data
  271. elif cmd == "ifnoret" and not ret:
  272. outtext += data
  273. elif cmd == "iftempl" and (nargs > 0 or ret):
  274. outtext += data
  275. elif cmd == "arg,":
  276. for i in range(1, nargs + 1):
  277. if i > 1:
  278. outtext += ", "
  279. outtext += data.replace("@", str(i))
  280. elif cmd == "arg":
  281. for i in range(1, nargs + 1):
  282. outtext += data.replace("@", str(i))
  283. elif cmd == "noarg":
  284. for i in range(nargs + 1, argmax + 1):
  285. outtext += data.replace("@", str(i))
  286. from_pos = end + 1
  287. return outtext
  288. def run(target, source, env):
  289. versions = 13
  290. versions_ext = 6
  291. text = ""
  292. text_ext = ""
  293. text_free_func = "#ifndef METHOD_BIND_FREE_FUNC_H\n#define METHOD_BIND_FREE_FUNC_H\n"
  294. text_free_func += "\n//including this header file allows method binding to use free functions\n"
  295. text_free_func += (
  296. "//note that the free function must have a pointer to an instance of the class as its first parameter\n"
  297. )
  298. for i in range(0, versions + 1):
  299. t = ""
  300. t += make_version(template, i, versions, False, False)
  301. t += make_version(template_typed, i, versions, False, False)
  302. t += make_version(template, i, versions, False, True)
  303. t += make_version(template_typed, i, versions, False, True)
  304. t += make_version(template, i, versions, True, False)
  305. t += make_version(template_typed, i, versions, True, False)
  306. t += make_version(template, i, versions, True, True)
  307. t += make_version(template_typed, i, versions, True, True)
  308. if i >= versions_ext:
  309. text_ext += t
  310. else:
  311. text += t
  312. text_free_func += make_version(template_typed_free_func, i, versions, False, False)
  313. text_free_func += make_version(template_typed_free_func, i, versions, False, True)
  314. text_free_func += make_version(template_typed_free_func, i, versions, True, False)
  315. text_free_func += make_version(template_typed_free_func, i, versions, True, True)
  316. text_free_func += "#endif"
  317. with open(target[0], "w") as f:
  318. f.write(text)
  319. with open(target[1], "w") as f:
  320. f.write(text_ext)
  321. with open(target[2], "w") as f:
  322. f.write(text_free_func)
  323. if __name__ == "__main__":
  324. from platform_methods import subprocess_main
  325. subprocess_main(globals())