programs.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /* Copyright (C) 2001, 2009, 2010, 2011, 2012, 2013 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 "srcprop.h" /* scm_sym_filename */
  28. #include "vm.h"
  29. static SCM write_program = SCM_BOOL_F;
  30. SCM_DEFINE (scm_make_program, "make-program", 1, 2, 0,
  31. (SCM objcode, SCM objtable, SCM free_variables),
  32. "")
  33. #define FUNC_NAME s_scm_make_program
  34. {
  35. SCM_VALIDATE_OBJCODE (1, objcode);
  36. if (SCM_UNLIKELY (SCM_UNBNDP (objtable)))
  37. objtable = SCM_BOOL_F;
  38. else if (scm_is_true (objtable))
  39. SCM_VALIDATE_VECTOR (2, objtable);
  40. if (SCM_UNBNDP (free_variables) || scm_is_false (free_variables))
  41. {
  42. SCM ret = scm_words (scm_tc7_program, 3);
  43. SCM_SET_CELL_OBJECT_1 (ret, objcode);
  44. SCM_SET_CELL_OBJECT_2 (ret, objtable);
  45. return ret;
  46. }
  47. else
  48. {
  49. size_t i, len;
  50. SCM ret;
  51. SCM_VALIDATE_VECTOR (3, free_variables);
  52. len = scm_c_vector_length (free_variables);
  53. if (SCM_UNLIKELY (len >> 16))
  54. SCM_OUT_OF_RANGE (3, free_variables);
  55. ret = scm_words (scm_tc7_program | (len<<16), 3 + len);
  56. SCM_SET_CELL_OBJECT_1 (ret, objcode);
  57. SCM_SET_CELL_OBJECT_2 (ret, objtable);
  58. for (i = 0; i < len; i++)
  59. SCM_SET_CELL_OBJECT (ret, 3+i,
  60. SCM_SIMPLE_VECTOR_REF (free_variables, i));
  61. return ret;
  62. }
  63. }
  64. #undef FUNC_NAME
  65. SCM_DEFINE (scm_make_rtl_program, "make-rtl-program", 1, 2, 0,
  66. (SCM bytevector, SCM byte_offset, SCM free_variables),
  67. "")
  68. #define FUNC_NAME s_scm_make_rtl_program
  69. {
  70. scm_t_uint8 *code;
  71. scm_t_uint32 offset;
  72. if (!scm_is_bytevector (bytevector))
  73. scm_wrong_type_arg (FUNC_NAME, 1, bytevector);
  74. if (SCM_UNBNDP (byte_offset))
  75. offset = 0;
  76. else
  77. {
  78. offset = scm_to_uint32 (byte_offset);
  79. if (offset > SCM_BYTEVECTOR_LENGTH (bytevector))
  80. SCM_OUT_OF_RANGE (2, byte_offset);
  81. }
  82. code = (scm_t_uint8*) SCM_BYTEVECTOR_CONTENTS (bytevector) + offset;
  83. if (((scm_t_uintptr) code) % 4)
  84. SCM_OUT_OF_RANGE (2, byte_offset);
  85. if (SCM_UNBNDP (free_variables) || scm_is_false (free_variables))
  86. return scm_cell (scm_tc7_rtl_program, (scm_t_bits) code);
  87. else
  88. abort ();
  89. }
  90. #undef FUNC_NAME
  91. SCM_DEFINE (scm_rtl_program_code, "rtl-program-code", 1, 0, 0,
  92. (SCM program),
  93. "")
  94. #define FUNC_NAME s_scm_rtl_program_code
  95. {
  96. SCM_VALIDATE_RTL_PROGRAM (1, program);
  97. /* FIXME: we need scm_from_uintptr (). */
  98. return scm_from_size_t ((size_t) SCM_RTL_PROGRAM_CODE (program));
  99. }
  100. #undef FUNC_NAME
  101. SCM
  102. scm_i_rtl_program_name (SCM program)
  103. {
  104. static SCM rtl_program_name = SCM_BOOL_F;
  105. if (scm_is_false (rtl_program_name) && scm_module_system_booted_p)
  106. rtl_program_name =
  107. scm_c_private_variable ("system vm program", "rtl-program-name");
  108. return scm_call_1 (scm_variable_ref (rtl_program_name), program);
  109. }
  110. SCM
  111. scm_i_rtl_program_documentation (SCM program)
  112. {
  113. static SCM rtl_program_documentation = SCM_BOOL_F;
  114. if (scm_is_false (rtl_program_documentation) && scm_module_system_booted_p)
  115. rtl_program_documentation =
  116. scm_c_private_variable ("system vm program",
  117. "rtl-program-documentation");
  118. return scm_call_1 (scm_variable_ref (rtl_program_documentation), program);
  119. }
  120. SCM
  121. scm_i_rtl_program_properties (SCM program)
  122. {
  123. static SCM rtl_program_properties = SCM_BOOL_F;
  124. if (scm_is_false (rtl_program_properties) && scm_module_system_booted_p)
  125. rtl_program_properties =
  126. scm_c_private_variable ("system vm program", "rtl-program-properties");
  127. return scm_call_1 (scm_variable_ref (rtl_program_properties), program);
  128. }
  129. void
  130. scm_i_program_print (SCM program, SCM port, scm_print_state *pstate)
  131. {
  132. static int print_error = 0;
  133. if (scm_is_false (write_program) && scm_module_system_booted_p)
  134. write_program = scm_c_private_variable ("system vm program",
  135. "write-program");
  136. if (SCM_PROGRAM_IS_CONTINUATION (program))
  137. {
  138. /* twingliness */
  139. scm_puts_unlocked ("#<continuation ", port);
  140. scm_uintprint (SCM_UNPACK (program), 16, port);
  141. scm_putc_unlocked ('>', port);
  142. }
  143. else if (SCM_PROGRAM_IS_PARTIAL_CONTINUATION (program))
  144. {
  145. /* twingliness */
  146. scm_puts_unlocked ("#<partial-continuation ", port);
  147. scm_uintprint (SCM_UNPACK (program), 16, port);
  148. scm_putc_unlocked ('>', port);
  149. }
  150. else if (scm_is_false (write_program) || print_error)
  151. {
  152. if (SCM_RTL_PROGRAM_P (program))
  153. {
  154. scm_puts_unlocked ("#<rtl-program ", port);
  155. scm_uintprint (SCM_UNPACK (program), 16, port);
  156. scm_putc_unlocked (' ', port);
  157. scm_uintprint ((scm_t_uintptr) SCM_RTL_PROGRAM_CODE (program), 16, port);
  158. scm_putc_unlocked ('>', port);
  159. }
  160. else
  161. {
  162. scm_puts_unlocked ("#<program ", port);
  163. scm_uintprint (SCM_UNPACK (program), 16, port);
  164. scm_putc_unlocked ('>', port);
  165. }
  166. }
  167. else
  168. {
  169. print_error = 1;
  170. scm_call_2 (SCM_VARIABLE_REF (write_program), program, port);
  171. print_error = 0;
  172. }
  173. }
  174. /*
  175. * Scheme interface
  176. */
  177. SCM_DEFINE (scm_program_p, "program?", 1, 0, 0,
  178. (SCM obj),
  179. "")
  180. #define FUNC_NAME s_scm_program_p
  181. {
  182. return scm_from_bool (SCM_PROGRAM_P (obj));
  183. }
  184. #undef FUNC_NAME
  185. SCM_DEFINE (scm_rtl_program_p, "rtl-program?", 1, 0, 0,
  186. (SCM obj),
  187. "")
  188. #define FUNC_NAME s_scm_rtl_program_p
  189. {
  190. return scm_from_bool (SCM_RTL_PROGRAM_P (obj));
  191. }
  192. #undef FUNC_NAME
  193. SCM_DEFINE (scm_program_base, "program-base", 1, 0, 0,
  194. (SCM program),
  195. "")
  196. #define FUNC_NAME s_scm_program_base
  197. {
  198. const struct scm_objcode *c_objcode;
  199. SCM_VALIDATE_PROGRAM (1, program);
  200. c_objcode = SCM_PROGRAM_DATA (program);
  201. return scm_from_unsigned_integer ((scm_t_bits) SCM_C_OBJCODE_BASE (c_objcode));
  202. }
  203. #undef FUNC_NAME
  204. SCM_DEFINE (scm_program_objects, "program-objects", 1, 0, 0,
  205. (SCM program),
  206. "")
  207. #define FUNC_NAME s_scm_program_objects
  208. {
  209. SCM_VALIDATE_PROGRAM (1, program);
  210. return SCM_PROGRAM_OBJTABLE (program);
  211. }
  212. #undef FUNC_NAME
  213. SCM_DEFINE (scm_program_module, "program-module", 1, 0, 0,
  214. (SCM program),
  215. "")
  216. #define FUNC_NAME s_scm_program_module
  217. {
  218. SCM objs, mod;
  219. SCM_VALIDATE_PROGRAM (1, program);
  220. objs = SCM_PROGRAM_OBJTABLE (program);
  221. /* If a program is the result of compiling GLIL to assembly, then if
  222. it has an objtable, the first entry will be a module. But some
  223. programs are hand-coded trampolines, like boot programs and
  224. primitives and the like. So if a program happens to have a
  225. non-module in the first slot of the objtable, assume that it is
  226. such a trampoline, and just return #f for the module. */
  227. mod = scm_is_true (objs) ? scm_c_vector_ref (objs, 0) : SCM_BOOL_F;
  228. return SCM_MODULEP (mod) ? mod : SCM_BOOL_F;
  229. }
  230. #undef FUNC_NAME
  231. SCM_DEFINE (scm_program_meta, "program-meta", 1, 0, 0,
  232. (SCM program),
  233. "")
  234. #define FUNC_NAME s_scm_program_meta
  235. {
  236. SCM metaobj;
  237. SCM_VALIDATE_PROGRAM (1, program);
  238. metaobj = scm_objcode_meta (SCM_PROGRAM_OBJCODE (program));
  239. if (scm_is_true (metaobj))
  240. return scm_make_program (metaobj, SCM_PROGRAM_OBJTABLE (program),
  241. SCM_BOOL_F);
  242. else
  243. return SCM_BOOL_F;
  244. }
  245. #undef FUNC_NAME
  246. SCM_DEFINE (scm_program_bindings, "program-bindings", 1, 0, 0,
  247. (SCM program),
  248. "")
  249. #define FUNC_NAME s_scm_program_bindings
  250. {
  251. SCM meta;
  252. SCM_VALIDATE_PROGRAM (1, program);
  253. meta = scm_program_meta (program);
  254. if (scm_is_false (meta))
  255. return SCM_BOOL_F;
  256. return scm_car (scm_call_0 (meta));
  257. }
  258. #undef FUNC_NAME
  259. SCM_DEFINE (scm_program_sources, "program-sources", 1, 0, 0,
  260. (SCM program),
  261. "")
  262. #define FUNC_NAME s_scm_program_sources
  263. {
  264. SCM meta, sources, ret, filename;
  265. SCM_VALIDATE_PROGRAM (1, program);
  266. meta = scm_program_meta (program);
  267. if (scm_is_false (meta))
  268. return SCM_EOL;
  269. filename = SCM_BOOL_F;
  270. ret = SCM_EOL;
  271. for (sources = scm_cadr (scm_call_0 (meta)); !scm_is_null (sources);
  272. sources = scm_cdr (sources))
  273. {
  274. SCM x = scm_car (sources);
  275. if (scm_is_pair (x))
  276. {
  277. if (scm_is_number (scm_car (x)))
  278. {
  279. SCM addr = scm_car (x);
  280. ret = scm_acons (addr, scm_cons (filename, scm_cdr (x)),
  281. ret);
  282. }
  283. else if (scm_is_eq (scm_car (x), scm_sym_filename))
  284. filename = scm_cdr (x);
  285. }
  286. }
  287. return scm_reverse_x (ret, SCM_UNDEFINED);
  288. }
  289. #undef FUNC_NAME
  290. SCM_DEFINE (scm_program_arities, "program-arities", 1, 0, 0,
  291. (SCM program),
  292. "")
  293. #define FUNC_NAME s_scm_program_arities
  294. {
  295. SCM meta;
  296. SCM_VALIDATE_PROGRAM (1, program);
  297. meta = scm_program_meta (program);
  298. if (scm_is_false (meta))
  299. return SCM_BOOL_F;
  300. return scm_caddr (scm_call_0 (meta));
  301. }
  302. #undef FUNC_NAME
  303. SCM
  304. scm_i_program_properties (SCM program)
  305. #define FUNC_NAME "%program-properties"
  306. {
  307. SCM meta;
  308. SCM_VALIDATE_PROGRAM (1, program);
  309. meta = scm_program_meta (program);
  310. if (scm_is_false (meta))
  311. return SCM_EOL;
  312. return scm_cdddr (scm_call_0 (meta));
  313. }
  314. #undef FUNC_NAME
  315. static SCM
  316. program_source (SCM program, size_t ip, SCM sources)
  317. {
  318. SCM source = SCM_BOOL_F;
  319. while (!scm_is_null (sources)
  320. && scm_to_size_t (scm_caar (sources)) <= ip)
  321. {
  322. source = scm_car (sources);
  323. sources = scm_cdr (sources);
  324. }
  325. return source; /* (addr . (filename . (line . column))) */
  326. }
  327. SCM_DEFINE (scm_program_source, "program-source", 2, 1, 0,
  328. (SCM program, SCM ip, SCM sources),
  329. "")
  330. #define FUNC_NAME s_scm_program_source
  331. {
  332. SCM_VALIDATE_PROGRAM (1, program);
  333. if (SCM_UNBNDP (sources))
  334. sources = scm_program_sources (program);
  335. return program_source (program, scm_to_size_t (ip), sources);
  336. }
  337. #undef FUNC_NAME
  338. extern SCM
  339. scm_c_program_source (SCM program, size_t ip)
  340. {
  341. return program_source (program, ip, scm_program_sources (program));
  342. }
  343. SCM_DEFINE (scm_program_num_free_variables, "program-num-free-variables", 1, 0, 0,
  344. (SCM program),
  345. "")
  346. #define FUNC_NAME s_scm_program_num_free_variables
  347. {
  348. if (SCM_RTL_PROGRAM_P (program)) {
  349. return scm_from_ulong (SCM_RTL_PROGRAM_NUM_FREE_VARIABLES (program));
  350. }
  351. SCM_VALIDATE_PROGRAM (1, program);
  352. return scm_from_ulong (SCM_PROGRAM_NUM_FREE_VARIABLES (program));
  353. }
  354. #undef FUNC_NAME
  355. SCM_DEFINE (scm_program_free_variable_ref, "program-free-variable-ref", 2, 0, 0,
  356. (SCM program, SCM i),
  357. "")
  358. #define FUNC_NAME s_scm_program_free_variable_ref
  359. {
  360. unsigned long idx;
  361. if (SCM_RTL_PROGRAM_P (program)) {
  362. SCM_VALIDATE_ULONG_COPY (2, i, idx);
  363. if (idx >= SCM_RTL_PROGRAM_NUM_FREE_VARIABLES (program))
  364. SCM_OUT_OF_RANGE (2, i);
  365. return SCM_RTL_PROGRAM_FREE_VARIABLE_REF (program, idx);
  366. }
  367. SCM_VALIDATE_PROGRAM (1, program);
  368. SCM_VALIDATE_ULONG_COPY (2, i, idx);
  369. if (idx >= SCM_PROGRAM_NUM_FREE_VARIABLES (program))
  370. SCM_OUT_OF_RANGE (2, i);
  371. return SCM_PROGRAM_FREE_VARIABLE_REF (program, idx);
  372. }
  373. #undef FUNC_NAME
  374. SCM_DEFINE (scm_program_free_variable_set_x, "program-free-variable-set!", 3, 0, 0,
  375. (SCM program, SCM i, SCM x),
  376. "")
  377. #define FUNC_NAME s_scm_program_free_variable_set_x
  378. {
  379. unsigned long idx;
  380. if (SCM_RTL_PROGRAM_P (program)) {
  381. SCM_VALIDATE_ULONG_COPY (2, i, idx);
  382. if (idx >= SCM_RTL_PROGRAM_NUM_FREE_VARIABLES (program))
  383. SCM_OUT_OF_RANGE (2, i);
  384. SCM_RTL_PROGRAM_FREE_VARIABLE_SET (program, idx, x);
  385. return SCM_UNSPECIFIED;
  386. }
  387. SCM_VALIDATE_PROGRAM (1, program);
  388. SCM_VALIDATE_ULONG_COPY (2, i, idx);
  389. if (idx >= SCM_PROGRAM_NUM_FREE_VARIABLES (program))
  390. SCM_OUT_OF_RANGE (2, i);
  391. SCM_PROGRAM_FREE_VARIABLE_SET (program, idx, x);
  392. return SCM_UNSPECIFIED;
  393. }
  394. #undef FUNC_NAME
  395. SCM_DEFINE (scm_program_objcode, "program-objcode", 1, 0, 0,
  396. (SCM program),
  397. "Return a @var{program}'s object code.")
  398. #define FUNC_NAME s_scm_program_objcode
  399. {
  400. SCM_VALIDATE_PROGRAM (1, program);
  401. return SCM_PROGRAM_OBJCODE (program);
  402. }
  403. #undef FUNC_NAME
  404. /* procedure-minimum-arity support. */
  405. static void
  406. parse_arity (SCM arity, int *req, int *opt, int *rest)
  407. {
  408. SCM x = scm_cddr (arity);
  409. if (scm_is_pair (x))
  410. {
  411. *req = scm_to_int (scm_car (x));
  412. x = scm_cdr (x);
  413. if (scm_is_pair (x))
  414. {
  415. *opt = scm_to_int (scm_car (x));
  416. x = scm_cdr (x);
  417. if (scm_is_pair (x))
  418. *rest = scm_is_true (scm_car (x));
  419. else
  420. *rest = 0;
  421. }
  422. else
  423. *opt = *rest = 0;
  424. }
  425. else
  426. *req = *opt = *rest = 0;
  427. }
  428. static int
  429. scm_i_rtl_program_minimum_arity (SCM program, int *req, int *opt, int *rest)
  430. {
  431. static SCM rtl_program_minimum_arity = SCM_BOOL_F;
  432. SCM l;
  433. if (scm_is_false (rtl_program_minimum_arity) && scm_module_system_booted_p)
  434. rtl_program_minimum_arity =
  435. scm_c_private_variable ("system vm program",
  436. "rtl-program-minimum-arity");
  437. l = scm_call_1 (scm_variable_ref (rtl_program_minimum_arity), program);
  438. if (scm_is_false (l))
  439. return 0;
  440. *req = scm_to_int (scm_car (l));
  441. *opt = scm_to_int (scm_cadr (l));
  442. *rest = scm_is_true (scm_caddr (l));
  443. return 1;
  444. }
  445. int
  446. scm_i_program_arity (SCM program, int *req, int *opt, int *rest)
  447. {
  448. SCM arities;
  449. if (SCM_RTL_PROGRAM_P (program))
  450. return scm_i_rtl_program_minimum_arity (program, req, opt, rest);
  451. arities = scm_program_arities (program);
  452. if (!scm_is_pair (arities))
  453. return 0;
  454. parse_arity (scm_car (arities), req, opt, rest);
  455. arities = scm_cdr (arities);
  456. for (; scm_is_pair (arities); arities = scm_cdr (arities))
  457. {
  458. int thisreq, thisopt, thisrest;
  459. parse_arity (scm_car (arities), &thisreq, &thisopt, &thisrest);
  460. if (thisreq < *req
  461. || (thisreq == *req
  462. && ((thisrest && (!*rest || thisopt > *opt))
  463. || (!thisrest && !*rest && thisopt > *opt))))
  464. {
  465. *req = thisreq;
  466. *opt = thisopt;
  467. *rest = thisrest;
  468. }
  469. }
  470. return 1;
  471. }
  472. void
  473. scm_bootstrap_programs (void)
  474. {
  475. scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
  476. "scm_init_programs",
  477. (scm_t_extension_init_func)scm_init_programs, NULL);
  478. }
  479. void
  480. scm_init_programs (void)
  481. {
  482. #ifndef SCM_MAGIC_SNARFER
  483. #include "libguile/programs.x"
  484. #endif
  485. }
  486. /*
  487. Local Variables:
  488. c-file-style: "gnu"
  489. End:
  490. */