function.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /* Declarations for the function types.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #ifndef __KP_FUNCTION__
  14. #define __KP_FUNCTION__ 1
  15. #include "interp.hpp"
  16. KP_DECLS_BEGIN
  17. struct function_base : public varobj
  18. {
  19. static const int native_flag = 1 << 16;
  20. static const int artificial_flag = 1 << 17;
  21. static const int kwargs_flag = 1 << 18;
  22. static const int genericfn_flag = 1 << 19;
  23. static const int code = typecode::FCT;
  24. int min_argc;
  25. int max_argc;
  26. object name;
  27. result<bool> test_nargs (interpreter *interp, uint32_t n,
  28. bool raise = true) const
  29. {
  30. if (n >= (uint32_t)this->min_argc && n <= (uint32_t)this->max_argc)
  31. return (true);
  32. else if (!raise)
  33. return (false);
  34. return (interp->raise_nargs (this->name, this->min_argc,
  35. this->max_argc, n));
  36. }
  37. void local_init ()
  38. {
  39. this->vo_full = 0;
  40. this->vo_type = typecode::FCT;
  41. }
  42. };
  43. struct native_function : public function_base
  44. {
  45. typedef result<object> (*fn_type) (interpreter *, object *, int);
  46. fn_type fct;
  47. result<object> call (interpreter *interp, object *argv, int argc)
  48. {
  49. return (this->fct (interp, argv, argc));
  50. }
  51. result<object> call (interpreter *interp, int argc)
  52. {
  53. call_guard g (interp, argc + 1);
  54. KP_VTRY (interp->push_frame (NIL, argc, 0),
  55. this->test_nargs (interp, argc));
  56. return (this->fct (interp, interp->stkend - argc -
  57. interpreter::frame_size, argc));
  58. }
  59. };
  60. struct function : public function_base
  61. {
  62. int max_sp;
  63. object bcode;
  64. object vals;
  65. object env;
  66. int max_stack () const;
  67. void copy_into (function *fp)
  68. {
  69. fp->vo_full |= this->vo_full;
  70. fp->max_sp = this->max_sp;
  71. fp->min_argc = this->min_argc;
  72. fp->max_argc = this->max_argc;
  73. fp->bcode = this->bcode;
  74. fp->vals = this->vals;
  75. fp->env = this->env;
  76. }
  77. };
  78. inline function* as_fct (object obj)
  79. {
  80. return ((function *)unmask (obj));
  81. }
  82. #ifdef KP_ARCH_WIDE
  83. inline constexpr bool fct_p (object obj)
  84. {
  85. return (itype (obj) == typecode::FCT);
  86. }
  87. #else
  88. inline bool fct_p (object obj)
  89. {
  90. return (varobj_p (obj) && as_varobj(obj)->vo_type == typecode::FCT);
  91. }
  92. #endif
  93. inline object& fct_bcode (object obj)
  94. {
  95. return (as_fct(obj)->bcode);
  96. }
  97. inline object& fct_vals (object obj)
  98. {
  99. return (as_fct(obj)->vals);
  100. }
  101. inline object& fct_env (object obj)
  102. {
  103. return (as_fct(obj)->env);
  104. }
  105. inline native_function* as_native_fct (object obj)
  106. {
  107. return ((native_function *)unmask (obj));
  108. }
  109. inline bool native_fct_p (object obj)
  110. {
  111. return (fct_p (obj) &&
  112. as_fct(obj)->flagged_p (function_base::native_flag));
  113. }
  114. inline object& fct_name (object obj)
  115. {
  116. return (((function_base *)unmask (obj))->name);
  117. }
  118. // Get the name of FCT as a C-string.
  119. KP_EXPORT const char* fct_sname (object fct);
  120. // Allocate a function with flags FLAGS.
  121. KP_EXPORT result<object> alloc_fct (interpreter *interp, uint32_t flags = 0);
  122. // Test for function equality.
  123. KP_EXPORT bool eq_xx (interpreter *interp, object x, object y);
  124. // Compile the expression EXPR and return a thunk.
  125. KP_EXPORT result<object> compile_expr (interpreter *interp, object expr);
  126. // Evaluate the expression EXPR.
  127. KP_EXPORT result<object> eval (interpreter *interp, object expr);
  128. // Return the single macro-expansion of EXPR in environment ENV.
  129. KP_EXPORT result<object> macroexp_1 (interpreter *interp,
  130. object expr, object env = NIL);
  131. // Return the full macro-expansion of EXPR in environment ENV.
  132. KP_EXPORT result<object> macroexp (interpreter *interp,
  133. object expr, object env = NIL);
  134. // Call function after having pushed it and its N arguments on the stack.
  135. KP_EXPORT result<object> call_n (interpreter *interp, uint32_t n);
  136. // Compute the needed stack size for function FCT.
  137. KP_EXPORT int fct_stacksize (object fct);
  138. // Write a function to a stream.
  139. KP_EXPORT result<int64_t> write_x (interpreter *interp,
  140. stream *strm, object obj, io_info& info);
  141. // Serialize a function in a stream.
  142. KP_EXPORT result<int64_t> pack_x (interpreter *interp,
  143. stream *strm, object obj, pack_info& info);
  144. // Deserialize a function in a stream.
  145. KP_EXPORT result<object> unpack_x (interpreter *interp,
  146. stream *strm, pack_info& info, bool save);
  147. // Disassemble the function FN and write the instructions to OUT.
  148. KP_EXPORT result<void> disasm (interpreter *interp, object fn, object out);
  149. // Get the builtin index for function named NAME.
  150. KP_EXPORT int builtin_idx (interpreter *interp, const char *name);
  151. // Return the builtin function for NAME.
  152. KP_EXPORT object builtin_fct (interpreter *interp, const char *name);
  153. // Return the builtin function with index IDX.
  154. KP_EXPORT object builtin_fct (interpreter *interp, int idx);
  155. // Helper for the implementation of multimethods.
  156. KP_EXPORT result<object> p_meth_ctl (interpreter *interp,
  157. object *argv, int argc);
  158. // Try to call method with ARGC arguments on the stack.
  159. KP_EXPORT result<bool> method_call (interpreter *interp, uint32_t argc);
  160. // Helpers for the KP_CALL macro.
  161. inline int push_all_helper (interpreter *)
  162. {
  163. return (0);
  164. }
  165. template <typename A1, typename ...Args>
  166. inline result<void> push_all_helper (interpreter *interp, A1 a1, Args... args)
  167. {
  168. object tmp = KP_TRY (a1 ());
  169. *interp->stkend++ = tmp;
  170. KP_VTRY (push_all_helper (interp, args...));
  171. return (0);
  172. }
  173. template <typename ...Args>
  174. result<void> push_all (interpreter *interp, Args... args)
  175. {
  176. KP_VTRY (interp->growstk (sizeof... (args)));
  177. return (push_all_helper (interp, args...));
  178. }
  179. template <typename ...Args>
  180. result<object> call_helper (interpreter *interp, object fn, Args... args)
  181. {
  182. uint32_t sp = interp->stklen ();
  183. KP_VTRY (interp->growstk (1 + sizeof... (args)));
  184. *interp->stkend++ = fn;
  185. KP_VTRY (push_all_helper (interp, args...));
  186. return (call_n (interp, interp->stklen () - sp - 1));
  187. }
  188. template <typename ...Args>
  189. result<object> call_helper (interpreter *interp, native_function::fn_type fn,
  190. Args... args)
  191. {
  192. sp_guard sg { interp };
  193. uint32_t sp = interp->stklen ();
  194. KP_VTRY (push_all (interp, args...));
  195. return (fn (interp, interp->stack + sp, interp->stklen () - sp));
  196. }
  197. #define KP_CALL0(Interp, Base, Fn) \
  198. Base ((Interp), (Fn))
  199. #define KP_CALL1(Interp, Base, Fn, A1) \
  200. Base ((Interp), (Fn), [&] () { return (A1); })
  201. #define KP_CALL2(Interp, Base, Fn, A1, A2) \
  202. Base ((Interp), (Fn), \
  203. [&] () { return (A1); }, \
  204. [&] () { return (A2); })
  205. #define KP_CALL3(Interp, Base, Fn, A1, A2, A3) \
  206. Base ((Interp), (Fn), \
  207. [&] () { return (A1); }, \
  208. [&] () { return (A2); }, \
  209. [&] () { return (A3); })
  210. #define KP_CALL4(Interp, Base, Fn, A1, A2, A3, A4) \
  211. Base ((Interp), (Fn), \
  212. [&] () { return (A1); }, \
  213. [&] () { return (A2); }, \
  214. [&] () { return (A3); }, \
  215. [&] () { return (A4); })
  216. #define KP_CALL5(Interp, Base, Fn, A1, A2, A3, A4, A5) \
  217. Base ((Interp), (Fn), \
  218. [&] () { return (A1); }, \
  219. [&] () { return (A2); }, \
  220. [&] () { return (A3); }, \
  221. [&] () { return (A4); }, \
  222. [&] () { return (A5); })
  223. #define KP_CALL6(Interp, Base, Fn, A1, A2, A3, A4, A5, A6) \
  224. Base ((Interp), (Fn), \
  225. [&] () { return (A1); }, \
  226. [&] () { return (A2); }, \
  227. [&] () { return (A3); }, \
  228. [&] () { return (A4); }, \
  229. [&] () { return (A5); }, \
  230. [&] () { return (A6); })
  231. #define KP_CALL7(Interp, Base, Fn, A1, A2, A3, A4, A5, A6, A7) \
  232. Base ((Interp), (Fn), \
  233. [&] () { return (A1); }, \
  234. [&] () { return (A2); }, \
  235. [&] () { return (A3); }, \
  236. [&] () { return (A4); }, \
  237. [&] () { return (A5); }, \
  238. [&] () { return (A6); }, \
  239. [&] () { return (A7); })
  240. #define KP_CALL8(Interp, Base, Fn, A1, A2, A3, A4, A5, A6, A8) \
  241. Base ((Interp), (Fn), \
  242. [&] () { return (A1); }, \
  243. [&] () { return (A2); }, \
  244. [&] () { return (A3); }, \
  245. [&] () { return (A4); }, \
  246. [&] () { return (A5); }, \
  247. [&] () { return (A6); }, \
  248. [&] () { return (A7); }, \
  249. [&] () { return (A8); })
  250. #define KP_CALL9(Interp, Base, Fn, A1, A2, A3, A4, A5, A6, A8, A9) \
  251. Base ((Interp), (Fn), \
  252. [&] () { return (A1); }, \
  253. [&] () { return (A2); }, \
  254. [&] () { return (A3); }, \
  255. [&] () { return (A4); }, \
  256. [&] () { return (A5); }, \
  257. [&] () { return (A6); }, \
  258. [&] () { return (A7); }, \
  259. [&] () { return (A8); }, \
  260. [&] () { return (A9); })
  261. #define KP_CALL(Interp, Fn, ...) \
  262. KP_CALL_DISP (KP_CALL, (Interp), call_helper, (Fn), ##__VA_ARGS__)
  263. #define KP_PUSH_ALL(Interp, Expr, ...) \
  264. KP_VTRY (KP_CALL_DISP (KP_CALL, (Interp), push_all, \
  265. [&] () { return (Expr); }, ##__VA_ARGS__))
  266. struct kwpair
  267. {
  268. union
  269. {
  270. const char *name;
  271. object *obj;
  272. };
  273. bool is_name;
  274. kwpair (const char *cs) : name (cs), is_name (true)
  275. {
  276. }
  277. kwpair (object *ptr) : obj (ptr), is_name (false)
  278. {
  279. }
  280. };
  281. KP_EXPORT result<void> kwargs_parse_pairs (interpreter *interp, object *argv,
  282. int argc, kwpair *pairs, int npairs);
  283. template <typename ...Args>
  284. result<void> kwargs_parse (interpreter *interp, object *argv,
  285. int argc, Args... args)
  286. {
  287. kwpair pairs[] = { args... };
  288. return (kwargs_parse_pairs (interp, argv, argc, pairs, KP_NELEM (pairs)));
  289. }
  290. KP_DECLS_END
  291. #endif