objects.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /* Copyright (C) 1995, 1996, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. * Boston, MA 02110-1301 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice. */
  41. /* This file and objects.h contains those minimal pieces of the Guile
  42. * Object Oriented Programming System which need to be included in
  43. * libguile. See the comments in objects.h.
  44. */
  45. #include "libguile/_scm.h"
  46. #include "libguile/struct.h"
  47. #include "libguile/procprop.h"
  48. #include "libguile/chars.h"
  49. #include "libguile/keywords.h"
  50. #include "libguile/smob.h"
  51. #include "libguile/eval.h"
  52. #include "libguile/alist.h"
  53. #include "libguile/ports.h"
  54. #include "libguile/strings.h"
  55. #include "libguile/vectors.h"
  56. #include "libguile/validate.h"
  57. #include "libguile/objects.h"
  58. SCM scm_metaclass_standard;
  59. SCM scm_metaclass_operator;
  60. /* These variables are filled in by the object system when loaded. */
  61. SCM scm_class_boolean, scm_class_char, scm_class_pair;
  62. SCM scm_class_procedure, scm_class_string, scm_class_symbol;
  63. SCM scm_class_procedure_with_setter, scm_class_primitive_generic;
  64. SCM scm_class_vector, scm_class_null;
  65. SCM scm_class_integer, scm_class_real, scm_class_complex;
  66. SCM scm_class_unknown;
  67. SCM *scm_port_class = 0;
  68. SCM *scm_smob_class = 0;
  69. int scm_classes_initialized = 0;
  70. SCM scm_no_applicable_method;
  71. /* This function is used for efficient type dispatch. */
  72. SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
  73. (SCM x),
  74. "Return the class of @var{x}.")
  75. #define FUNC_NAME s_scm_class_of
  76. {
  77. if (!scm_classes_initialized)
  78. scm_misc_error (FUNC_NAME, "GOOPS not loaded yet.", SCM_EOL);
  79. switch (SCM_ITAG3 (x))
  80. {
  81. case scm_tc3_int_1:
  82. case scm_tc3_int_2:
  83. return scm_class_integer;
  84. case scm_tc3_imm24:
  85. if (SCM_CHARP (x))
  86. return scm_class_char;
  87. else
  88. {
  89. switch (SCM_ISYMNUM (x))
  90. {
  91. case SCM_ISYMNUM (SCM_BOOL_F):
  92. case SCM_ISYMNUM (SCM_BOOL_T):
  93. return scm_class_boolean;
  94. case SCM_ISYMNUM (SCM_EOL):
  95. return scm_class_null;
  96. default:
  97. return scm_class_unknown;
  98. }
  99. }
  100. case scm_tc3_cons:
  101. switch (SCM_TYP7 (x))
  102. {
  103. case scm_tcs_cons_nimcar:
  104. return scm_class_pair;
  105. case scm_tcs_closures:
  106. return scm_class_procedure;
  107. case scm_tc7_symbol:
  108. return scm_class_symbol;
  109. case scm_tc7_vector:
  110. case scm_tc7_wvect:
  111. #ifdef HAVE_ARRAYS
  112. case scm_tc7_bvect:
  113. case scm_tc7_byvect:
  114. case scm_tc7_svect:
  115. case scm_tc7_ivect:
  116. case scm_tc7_uvect:
  117. case scm_tc7_fvect:
  118. case scm_tc7_dvect:
  119. case scm_tc7_cvect:
  120. #endif
  121. return scm_class_vector;
  122. case scm_tc7_string:
  123. case scm_tc7_substring:
  124. return scm_class_string;
  125. case scm_tc7_asubr:
  126. case scm_tc7_subr_0:
  127. case scm_tc7_subr_1:
  128. case scm_tc7_cxr:
  129. case scm_tc7_subr_3:
  130. case scm_tc7_subr_2:
  131. case scm_tc7_rpsubr:
  132. case scm_tc7_subr_1o:
  133. case scm_tc7_subr_2o:
  134. case scm_tc7_lsubr_2:
  135. case scm_tc7_lsubr:
  136. if (SCM_SUBR_GENERIC (x) && *SCM_SUBR_GENERIC (x))
  137. return scm_class_primitive_generic;
  138. else
  139. return scm_class_procedure;
  140. case scm_tc7_cclo:
  141. return scm_class_procedure;
  142. case scm_tc7_pws:
  143. return scm_class_procedure_with_setter;
  144. case scm_tc7_smob:
  145. {
  146. scm_t_bits type = SCM_TYP16 (x);
  147. if (type != scm_tc16_port_with_ps)
  148. return scm_smob_class[SCM_TC2SMOBNUM (type)];
  149. x = SCM_PORT_WITH_PS_PORT (x);
  150. /* fall through to ports */
  151. }
  152. case scm_tc7_port:
  153. return scm_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
  154. ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
  155. ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
  156. : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
  157. : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
  158. case scm_tcs_cons_gloc:
  159. /* must be a struct */
  160. if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
  161. return SCM_CLASS_OF (x);
  162. else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
  163. {
  164. /* Goops object */
  165. if (! SCM_FALSEP (SCM_OBJ_CLASS_REDEF (x)))
  166. scm_change_object_class (x,
  167. SCM_CLASS_OF (x), /* old */
  168. SCM_OBJ_CLASS_REDEF (x)); /* new */
  169. return SCM_CLASS_OF (x);
  170. }
  171. else
  172. {
  173. /* ordinary struct */
  174. SCM handle = scm_struct_create_handle (SCM_STRUCT_VTABLE (x));
  175. if (!SCM_FALSEP (SCM_STRUCT_TABLE_CLASS (SCM_CDR (handle))))
  176. return SCM_STRUCT_TABLE_CLASS (SCM_CDR (handle));
  177. else
  178. {
  179. SCM name = SCM_STRUCT_TABLE_NAME (SCM_CDR (handle));
  180. SCM class = scm_make_extended_class (!SCM_FALSEP (name)
  181. ? SCM_SYMBOL_CHARS (name)
  182. : 0);
  183. SCM_SET_STRUCT_TABLE_CLASS (SCM_CDR (handle), class);
  184. return class;
  185. }
  186. }
  187. default:
  188. if (SCM_CONSP (x))
  189. return scm_class_pair;
  190. else
  191. return scm_class_unknown;
  192. }
  193. case scm_tc3_cons_gloc:
  194. case scm_tc3_tc7_1:
  195. case scm_tc3_tc7_2:
  196. case scm_tc3_closure:
  197. /* Never reached */
  198. break;
  199. }
  200. return scm_class_unknown;
  201. }
  202. #undef FUNC_NAME
  203. /* The cache argument for scm_mcache_lookup_cmethod has one of two possible
  204. * formats:
  205. *
  206. * Format #1:
  207. * (SCM_IM_DISPATCH ARGS N-SPECIALIZED
  208. * #((TYPE1 ... ENV FORMALS FORM ...) ...)
  209. * GF)
  210. *
  211. * Format #2:
  212. * (SCM_IM_HASH_DISPATCH ARGS N-SPECIALIZED HASHSET MASK
  213. * #((TYPE1 ... ENV FORMALS FORM ...) ...)
  214. * GF)
  215. *
  216. * ARGS is either a list of expressions, in which case they
  217. * are interpreted as the arguments of an application, or
  218. * a non-pair, which is interpreted as a single expression
  219. * yielding all arguments.
  220. *
  221. * SCM_IM_DISPATCH expressions in generic functions always
  222. * have ARGS = the symbol `args' or the iloc #@0-0.
  223. *
  224. * Need FORMALS in order to support varying arity. This
  225. * also avoids the need for renaming of bindings.
  226. *
  227. * We should probably not complicate this mechanism by
  228. * introducing "optimizations" for getters and setters or
  229. * primitive methods. Getters and setter will normally be
  230. * compiled into @slot-[ref|set!] or a procedure call.
  231. * They rely on the dispatch performed before executing
  232. * the code which contains them.
  233. *
  234. * We might want to use a more efficient representation of
  235. * this form in the future, perhaps after we have introduced
  236. * low-level support for syntax-case macros.
  237. */
  238. SCM
  239. scm_mcache_lookup_cmethod (SCM cache, SCM args)
  240. {
  241. long i, n, end, mask;
  242. SCM ls, methods, z = SCM_CDDR (cache);
  243. n = SCM_INUM (SCM_CAR (z)); /* maximum number of specializers */
  244. methods = SCM_CADR (z);
  245. if (SCM_INUMP (methods))
  246. {
  247. /* cache format #2: compute a hash value */
  248. long hashset = SCM_INUM (methods);
  249. long j = n;
  250. z = SCM_CDDR (z);
  251. mask = SCM_INUM (SCM_CAR (z));
  252. methods = SCM_CADR (z);
  253. i = 0;
  254. ls = args;
  255. if (!SCM_NULLP (ls))
  256. do
  257. {
  258. i += SCM_STRUCT_DATA (scm_class_of (SCM_CAR (ls)))
  259. [scm_si_hashsets + hashset];
  260. ls = SCM_CDR (ls);
  261. }
  262. while (j-- && !SCM_NULLP (ls));
  263. i &= mask;
  264. end = i;
  265. }
  266. else /* SCM_VECTORP (methods) */
  267. {
  268. /* cache format #1: prepare for linear search */
  269. mask = -1;
  270. i = 0;
  271. end = SCM_VECTOR_LENGTH (methods);
  272. }
  273. /* Search for match */
  274. do
  275. {
  276. long j = n;
  277. z = SCM_VELTS (methods)[i];
  278. ls = args; /* list of arguments */
  279. if (!SCM_NULLP (ls))
  280. do
  281. {
  282. /* More arguments than specifiers => CLASS != ENV */
  283. if (! SCM_EQ_P (scm_class_of (SCM_CAR (ls)), SCM_CAR (z)))
  284. goto next_method;
  285. ls = SCM_CDR (ls);
  286. z = SCM_CDR (z);
  287. }
  288. while (j-- && !SCM_NULLP (ls));
  289. /* Fewer arguments than specifiers => CAR != ENV */
  290. if (SCM_NULLP (SCM_CAR (z)) || SCM_CONSP (SCM_CAR (z)))
  291. return z;
  292. next_method:
  293. i = (i + 1) & mask;
  294. } while (i != end);
  295. return SCM_BOOL_F;
  296. }
  297. SCM
  298. scm_mcache_compute_cmethod (SCM cache, SCM args)
  299. {
  300. SCM cmethod = scm_mcache_lookup_cmethod (cache, args);
  301. if (SCM_FALSEP (cmethod))
  302. /* No match - memoize */
  303. return scm_memoize_method (cache, args);
  304. return cmethod;
  305. }
  306. SCM
  307. scm_apply_generic (SCM gf, SCM args)
  308. {
  309. SCM cmethod = scm_mcache_compute_cmethod (SCM_ENTITY_PROCEDURE (gf), args);
  310. return scm_eval_body (SCM_CDR (SCM_CMETHOD_CODE (cmethod)),
  311. SCM_EXTEND_ENV (SCM_CAR (SCM_CMETHOD_CODE (cmethod)),
  312. args,
  313. SCM_CMETHOD_ENV (cmethod)));
  314. }
  315. SCM
  316. scm_call_generic_0 (SCM gf)
  317. {
  318. return scm_apply_generic (gf, SCM_EOL);
  319. }
  320. SCM
  321. scm_call_generic_1 (SCM gf, SCM a1)
  322. {
  323. return scm_apply_generic (gf, scm_list_1 (a1));
  324. }
  325. SCM
  326. scm_call_generic_2 (SCM gf, SCM a1, SCM a2)
  327. {
  328. return scm_apply_generic (gf, scm_list_2 (a1, a2));
  329. }
  330. SCM
  331. scm_call_generic_3 (SCM gf, SCM a1, SCM a2, SCM a3)
  332. {
  333. return scm_apply_generic (gf, scm_list_3 (a1, a2, a3));
  334. }
  335. SCM_DEFINE (scm_entity_p, "entity?", 1, 0, 0,
  336. (SCM obj),
  337. "Return @code{#t} if @var{obj} is an entity.")
  338. #define FUNC_NAME s_scm_entity_p
  339. {
  340. return SCM_BOOL(SCM_STRUCTP (obj) && SCM_I_ENTITYP (obj));
  341. }
  342. #undef FUNC_NAME
  343. SCM_DEFINE (scm_operator_p, "operator?", 1, 0, 0,
  344. (SCM obj),
  345. "Return @code{#t} if @var{obj} is an operator.")
  346. #define FUNC_NAME s_scm_operator_p
  347. {
  348. return SCM_BOOL(SCM_STRUCTP (obj)
  349. && SCM_I_OPERATORP (obj)
  350. && !SCM_I_ENTITYP (obj));
  351. }
  352. #undef FUNC_NAME
  353. /* XXX - What code requires the object procedure to be only of certain
  354. types? */
  355. SCM_DEFINE (scm_valid_object_procedure_p, "valid-object-procedure?", 1, 0, 0,
  356. (SCM proc),
  357. "Return @code{#t} iff @var{proc} is a procedure that can be used "
  358. "with @code{set-object-procedure}. It is always valid to use "
  359. "a closure constructed by @code{lambda}.")
  360. #define FUNC_NAME s_scm_valid_object_procedure_p
  361. {
  362. if (SCM_IMP (proc))
  363. return SCM_BOOL_F;
  364. switch (SCM_TYP7 (proc))
  365. {
  366. default:
  367. return SCM_BOOL_F;
  368. case scm_tcs_closures:
  369. case scm_tc7_subr_1:
  370. case scm_tc7_subr_2:
  371. case scm_tc7_subr_3:
  372. case scm_tc7_lsubr_2:
  373. return SCM_BOOL_T;
  374. }
  375. }
  376. #undef FUNC_NAME
  377. SCM_DEFINE (scm_set_object_procedure_x, "set-object-procedure!", 2, 0, 0,
  378. (SCM obj, SCM proc),
  379. "Set the object procedure of @var{obj} to @var{proc}.\n"
  380. "@var{obj} must be either an entity or an operator.")
  381. #define FUNC_NAME s_scm_set_object_procedure_x
  382. {
  383. SCM_ASSERT (SCM_STRUCTP (obj)
  384. && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
  385. || (SCM_I_ENTITYP (obj)
  386. && !(SCM_OBJ_CLASS_FLAGS (obj)
  387. & SCM_CLASSF_PURE_GENERIC))),
  388. obj,
  389. SCM_ARG1,
  390. FUNC_NAME);
  391. SCM_ASSERT (scm_valid_object_procedure_p (proc), proc, SCM_ARG2, FUNC_NAME);
  392. if (SCM_I_ENTITYP (obj))
  393. SCM_SET_ENTITY_PROCEDURE (obj, proc);
  394. else
  395. SCM_OPERATOR_CLASS (obj)->procedure = proc;
  396. return SCM_UNSPECIFIED;
  397. }
  398. #undef FUNC_NAME
  399. #ifdef GUILE_DEBUG
  400. SCM_DEFINE (scm_object_procedure, "object-procedure", 1, 0, 0,
  401. (SCM obj),
  402. "Return the object procedure of @var{obj}. @var{obj} must be\n"
  403. "an entity or an operator.")
  404. #define FUNC_NAME s_scm_object_procedure
  405. {
  406. SCM_ASSERT (SCM_STRUCTP (obj)
  407. && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
  408. || SCM_I_ENTITYP (obj)),
  409. obj, SCM_ARG1, FUNC_NAME);
  410. return (SCM_I_ENTITYP (obj)
  411. ? SCM_ENTITY_PROCEDURE (obj)
  412. : SCM_OPERATOR_CLASS (obj)->procedure);
  413. }
  414. #undef FUNC_NAME
  415. #endif /* GUILE_DEBUG */
  416. /* The following procedures are not a part of Goops but a minimal
  417. * object system built upon structs. They are here for those who
  418. * want to implement their own object system.
  419. */
  420. SCM
  421. scm_i_make_class_object (SCM meta,
  422. SCM layout_string,
  423. unsigned long flags)
  424. {
  425. SCM c;
  426. SCM layout = scm_make_struct_layout (layout_string);
  427. c = scm_make_struct (meta,
  428. SCM_INUM0,
  429. scm_list_4 (layout, SCM_BOOL_F, SCM_EOL, SCM_EOL));
  430. SCM_SET_CLASS_FLAGS (c, flags);
  431. return c;
  432. }
  433. SCM_DEFINE (scm_make_class_object, "make-class-object", 2, 0, 0,
  434. (SCM metaclass, SCM layout),
  435. "Create a new class object of class @var{metaclass}, with the\n"
  436. "slot layout specified by @var{layout}.")
  437. #define FUNC_NAME s_scm_make_class_object
  438. {
  439. unsigned long flags = 0;
  440. SCM_VALIDATE_STRUCT (1,metaclass);
  441. SCM_VALIDATE_STRING (2,layout);
  442. if (SCM_EQ_P (metaclass, scm_metaclass_operator))
  443. flags = SCM_CLASSF_OPERATOR;
  444. return scm_i_make_class_object (metaclass, layout, flags);
  445. }
  446. #undef FUNC_NAME
  447. SCM_DEFINE (scm_make_subclass_object, "make-subclass-object", 2, 0, 0,
  448. (SCM class, SCM layout),
  449. "Create a subclass object of @var{class}, with the slot layout\n"
  450. "specified by @var{layout}.")
  451. #define FUNC_NAME s_scm_make_subclass_object
  452. {
  453. SCM pl;
  454. SCM_VALIDATE_STRUCT (1,class);
  455. SCM_VALIDATE_STRING (2,layout);
  456. pl = SCM_PACK (SCM_STRUCT_DATA (class) [scm_vtable_index_layout]);
  457. /* Convert symbol->string */
  458. pl = scm_mem2string (SCM_SYMBOL_CHARS (pl), SCM_SYMBOL_LENGTH (pl));
  459. return scm_i_make_class_object (SCM_STRUCT_VTABLE (class),
  460. scm_string_append (scm_list_2 (pl, layout)),
  461. SCM_CLASS_FLAGS (class));
  462. }
  463. #undef FUNC_NAME
  464. void
  465. scm_init_objects ()
  466. {
  467. SCM ms = scm_makfrom0str (SCM_METACLASS_STANDARD_LAYOUT);
  468. SCM mt = scm_make_vtable_vtable (ms, SCM_INUM0,
  469. scm_list_3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
  470. SCM os = scm_makfrom0str (SCM_METACLASS_OPERATOR_LAYOUT);
  471. SCM ot = scm_make_vtable_vtable (os, SCM_INUM0,
  472. scm_list_3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
  473. SCM es = scm_makfrom0str (SCM_ENTITY_LAYOUT);
  474. SCM el = scm_make_struct_layout (es);
  475. SCM et = scm_make_struct (mt, SCM_INUM0,
  476. scm_list_4 (el, SCM_BOOL_F, SCM_EOL, SCM_EOL));
  477. scm_c_define ("<class>", mt);
  478. scm_metaclass_standard = mt;
  479. scm_c_define ("<operator-class>", ot);
  480. scm_metaclass_operator = ot;
  481. SCM_SET_CLASS_FLAGS (et, SCM_CLASSF_OPERATOR | SCM_CLASSF_ENTITY);
  482. SCM_SET_CLASS_DESTRUCTOR (et, scm_struct_free_entity);
  483. scm_c_define ("<entity>", et);
  484. #include "libguile/objects.x"
  485. }
  486. /*
  487. Local Variables:
  488. c-file-style: "gnu"
  489. End:
  490. */