programs.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013, 2014, 2017 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public License
  5. * as published by the Free Software Foundation; either version 3 of
  6. * the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. * 02110-1301 USA
  17. */
  18. #if HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21. #include <string.h>
  22. #include "_scm.h"
  23. #include "instructions.h"
  24. #include "modules.h"
  25. #include "programs.h"
  26. #include "procprop.h" /* scm_sym_name */
  27. #include "vm.h"
  28. static SCM write_program = SCM_BOOL_F;
  29. SCM_DEFINE (scm_program_code, "program-code", 1, 0, 0,
  30. (SCM program),
  31. "")
  32. #define FUNC_NAME s_scm_program_code
  33. {
  34. SCM_VALIDATE_PROGRAM (1, program);
  35. return scm_from_uintptr_t ((scm_t_uintptr) SCM_PROGRAM_CODE (program));
  36. }
  37. #undef FUNC_NAME
  38. SCM
  39. scm_i_program_name (SCM program)
  40. {
  41. static SCM program_name = SCM_BOOL_F;
  42. if (SCM_PRIMITIVE_P (program))
  43. return SCM_SUBR_NAME (program);
  44. if (scm_is_false (program_name) && scm_module_system_booted_p)
  45. program_name =
  46. scm_c_private_variable ("system vm program", "program-name");
  47. return scm_call_1 (scm_variable_ref (program_name), program);
  48. }
  49. SCM
  50. scm_i_program_documentation (SCM program)
  51. {
  52. static SCM program_documentation = SCM_BOOL_F;
  53. if (SCM_PRIMITIVE_P (program))
  54. return SCM_BOOL_F;
  55. if (scm_is_false (program_documentation) && scm_module_system_booted_p)
  56. program_documentation =
  57. scm_c_private_variable ("system vm program", "program-documentation");
  58. return scm_call_1 (scm_variable_ref (program_documentation), program);
  59. }
  60. SCM
  61. scm_i_program_properties (SCM program)
  62. {
  63. static SCM program_properties = SCM_BOOL_F;
  64. if (SCM_PRIMITIVE_P (program))
  65. {
  66. SCM name = scm_i_program_name (program);
  67. if (scm_is_false (name))
  68. return SCM_EOL;
  69. return scm_acons (scm_sym_name, name, SCM_EOL);
  70. }
  71. if (scm_is_false (program_properties) && scm_module_system_booted_p)
  72. program_properties =
  73. scm_c_private_variable ("system vm program", "program-properties");
  74. return scm_call_1 (scm_variable_ref (program_properties), program);
  75. }
  76. void
  77. scm_i_program_print (SCM program, SCM port, scm_print_state *pstate)
  78. {
  79. static int print_error = 0;
  80. if (scm_is_false (write_program) && scm_module_system_booted_p)
  81. write_program = scm_c_private_variable ("system vm program",
  82. "write-program");
  83. if (SCM_PROGRAM_IS_CONTINUATION (program))
  84. {
  85. /* twingliness */
  86. scm_puts ("#<continuation ", port);
  87. scm_uintprint (SCM_UNPACK (program), 16, port);
  88. scm_putc ('>', port);
  89. }
  90. else if (SCM_PROGRAM_IS_PARTIAL_CONTINUATION (program))
  91. {
  92. /* twingliness */
  93. scm_puts ("#<partial-continuation ", port);
  94. scm_uintprint (SCM_UNPACK (program), 16, port);
  95. scm_putc ('>', port);
  96. }
  97. else if (scm_is_false (write_program) || print_error)
  98. {
  99. scm_puts ("#<program ", port);
  100. scm_uintprint (SCM_UNPACK (program), 16, port);
  101. scm_putc (' ', port);
  102. scm_uintprint ((scm_t_uintptr) SCM_PROGRAM_CODE (program), 16, port);
  103. scm_putc ('>', port);
  104. }
  105. else
  106. {
  107. print_error = 1;
  108. scm_call_2 (SCM_VARIABLE_REF (write_program), program, port);
  109. print_error = 0;
  110. }
  111. }
  112. /*
  113. * Scheme interface
  114. */
  115. SCM_DEFINE (scm_program_p, "program?", 1, 0, 0,
  116. (SCM obj),
  117. "")
  118. #define FUNC_NAME s_scm_program_p
  119. {
  120. return scm_from_bool (SCM_PROGRAM_P (obj));
  121. }
  122. #undef FUNC_NAME
  123. SCM_DEFINE (scm_primitive_code_p, "primitive-code?", 1, 0, 0,
  124. (SCM code),
  125. "")
  126. #define FUNC_NAME s_scm_primitive_code_p
  127. {
  128. const scm_t_uint32 * ptr = (const scm_t_uint32 *) scm_to_uintptr_t (code);
  129. return scm_from_bool (scm_i_primitive_code_p (ptr));
  130. }
  131. #undef FUNC_NAME
  132. SCM_DEFINE (scm_primitive_call_ip, "primitive-call-ip", 1, 0, 0,
  133. (SCM prim),
  134. "")
  135. #define FUNC_NAME s_scm_primitive_call_ip
  136. {
  137. SCM_MAKE_VALIDATE (1, prim, PRIMITIVE_P);
  138. return scm_from_uintptr_t (scm_i_primitive_call_ip (prim));
  139. }
  140. #undef FUNC_NAME
  141. SCM
  142. scm_find_source_for_addr (SCM ip)
  143. {
  144. static SCM source_for_addr = SCM_BOOL_F;
  145. if (scm_is_false (source_for_addr)) {
  146. if (!scm_module_system_booted_p)
  147. return SCM_BOOL_F;
  148. source_for_addr =
  149. scm_c_private_variable ("system vm program", "source-for-addr");
  150. }
  151. return scm_call_1 (scm_variable_ref (source_for_addr), ip);
  152. }
  153. SCM
  154. scm_program_address_range (SCM program)
  155. {
  156. static SCM program_address_range = SCM_BOOL_F;
  157. if (scm_is_false (program_address_range) && scm_module_system_booted_p)
  158. program_address_range =
  159. scm_c_private_variable ("system vm program", "program-address-range");
  160. return scm_call_1 (scm_variable_ref (program_address_range), program);
  161. }
  162. SCM_DEFINE (scm_program_num_free_variables, "program-num-free-variables", 1, 0, 0,
  163. (SCM program),
  164. "")
  165. #define FUNC_NAME s_scm_program_num_free_variables
  166. {
  167. SCM_VALIDATE_PROGRAM (1, program);
  168. return scm_from_ulong (SCM_PROGRAM_NUM_FREE_VARIABLES (program));
  169. }
  170. #undef FUNC_NAME
  171. SCM_DEFINE (scm_program_free_variable_ref, "program-free-variable-ref", 2, 0, 0,
  172. (SCM program, SCM i),
  173. "")
  174. #define FUNC_NAME s_scm_program_free_variable_ref
  175. {
  176. unsigned long idx;
  177. SCM_VALIDATE_PROGRAM (1, program);
  178. SCM_VALIDATE_ULONG_COPY (2, i, idx);
  179. if (idx >= SCM_PROGRAM_NUM_FREE_VARIABLES (program))
  180. SCM_OUT_OF_RANGE (2, i);
  181. return SCM_PROGRAM_FREE_VARIABLE_REF (program, idx);
  182. }
  183. #undef FUNC_NAME
  184. SCM_DEFINE (scm_program_free_variable_set_x, "program-free-variable-set!", 3, 0, 0,
  185. (SCM program, SCM i, SCM x),
  186. "")
  187. #define FUNC_NAME s_scm_program_free_variable_set_x
  188. {
  189. unsigned long idx;
  190. SCM_VALIDATE_PROGRAM (1, program);
  191. SCM_VALIDATE_ULONG_COPY (2, i, idx);
  192. if (idx >= SCM_PROGRAM_NUM_FREE_VARIABLES (program))
  193. SCM_OUT_OF_RANGE (2, i);
  194. SCM_PROGRAM_FREE_VARIABLE_SET (program, idx, x);
  195. return SCM_UNSPECIFIED;
  196. }
  197. #undef FUNC_NAME
  198. /* It's hacky, but it manages to cover all of the non-keyword cases. */
  199. static int
  200. try_parse_arity (SCM program, int *req, int *opt, int *rest)
  201. {
  202. scm_t_uint32 *code = SCM_PROGRAM_CODE (program);
  203. scm_t_uint32 slots, min;
  204. switch (code[0] & 0xff) {
  205. case scm_op_assert_nargs_ee:
  206. slots = code[0] >> 8;
  207. *req = slots - 1;
  208. *opt = 0;
  209. *rest = 0;
  210. return 1;
  211. case scm_op_assert_nargs_ee_locals:
  212. slots = (code[0] >> 8) & 0xfff;
  213. *req = slots - 1;
  214. *opt = 0;
  215. *rest = 0;
  216. return 1;
  217. case scm_op_assert_nargs_le:
  218. slots = code[0] >> 8;
  219. *req = 0;
  220. *opt = slots - 1;
  221. *rest = 0;
  222. return 1;
  223. case scm_op_bind_rest:
  224. slots = code[0] >> 8;
  225. *req = 0;
  226. *opt = slots - 1;
  227. *rest = 1;
  228. return 1;
  229. case scm_op_assert_nargs_ge:
  230. min = code[0] >> 8;
  231. switch (code[1] & 0xff) {
  232. case scm_op_assert_nargs_le:
  233. slots = code[1] >> 8;
  234. *req = min - 1;
  235. *opt = slots - 1 - *req;
  236. *rest = 0;
  237. return 1;
  238. case scm_op_bind_rest:
  239. slots = code[1] >> 8;
  240. *req = min - 1;
  241. *opt = slots - min;
  242. *rest = 1;
  243. return 1;
  244. default:
  245. return 0;
  246. }
  247. case scm_op_continuation_call:
  248. case scm_op_compose_continuation:
  249. *req = 0;
  250. *opt = 0;
  251. *rest = 1;
  252. return 1;
  253. default:
  254. return 0;
  255. }
  256. }
  257. int
  258. scm_i_program_arity (SCM program, int *req, int *opt, int *rest)
  259. {
  260. static SCM program_minimum_arity = SCM_BOOL_F;
  261. SCM l;
  262. if (try_parse_arity (program, req, opt, rest))
  263. return 1;
  264. if (scm_is_false (program_minimum_arity) && scm_module_system_booted_p)
  265. program_minimum_arity =
  266. scm_c_private_variable ("system vm program", "program-minimum-arity");
  267. l = scm_call_1 (scm_variable_ref (program_minimum_arity), program);
  268. if (scm_is_false (l))
  269. return 0;
  270. *req = scm_to_int (scm_car (l));
  271. *opt = scm_to_int (scm_cadr (l));
  272. *rest = scm_is_true (scm_caddr (l));
  273. return 1;
  274. }
  275. void
  276. scm_bootstrap_programs (void)
  277. {
  278. scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
  279. "scm_init_programs",
  280. (scm_t_extension_init_func)scm_init_programs, NULL);
  281. }
  282. void
  283. scm_init_programs (void)
  284. {
  285. #ifndef SCM_MAGIC_SNARFER
  286. #include "libguile/programs.x"
  287. #endif
  288. }
  289. /*
  290. Local Variables:
  291. c-file-style: "gnu"
  292. End:
  293. */