objects.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /* Copyright (C) 1995, 1996, 1999, 2000, 2002 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., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 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. SCM scm_no_applicable_method;
  70. SCM (*scm_make_extended_class) (char *type_name);
  71. void (*scm_make_port_classes) (int ptobnum, char *type_name);
  72. void (*scm_change_object_class) (SCM, SCM, SCM);
  73. /* This function is used for efficient type dispatch. */
  74. SCM
  75. scm_class_of (SCM x)
  76. {
  77. switch (SCM_ITAG3 (x))
  78. {
  79. case scm_tc3_int_1:
  80. case scm_tc3_int_2:
  81. return scm_class_integer;
  82. case scm_tc3_imm24:
  83. if (SCM_CHARP (x))
  84. return scm_class_char;
  85. else
  86. {
  87. switch (SCM_ISYMNUM (x))
  88. {
  89. case SCM_ISYMNUM (SCM_BOOL_F):
  90. case SCM_ISYMNUM (SCM_BOOL_T):
  91. return scm_class_boolean;
  92. case SCM_ISYMNUM (SCM_EOL):
  93. return scm_class_null;
  94. default:
  95. return scm_class_unknown;
  96. }
  97. }
  98. case scm_tc3_cons:
  99. switch (SCM_TYP7 (x))
  100. {
  101. case scm_tcs_cons_nimcar:
  102. return scm_class_pair;
  103. case scm_tcs_closures:
  104. return scm_class_procedure;
  105. case scm_tcs_symbols:
  106. return scm_class_symbol;
  107. case scm_tc7_vector:
  108. case scm_tc7_wvect:
  109. #ifdef HAVE_ARRAYS
  110. case scm_tc7_bvect:
  111. case scm_tc7_byvect:
  112. case scm_tc7_svect:
  113. case scm_tc7_ivect:
  114. case scm_tc7_uvect:
  115. case scm_tc7_fvect:
  116. case scm_tc7_dvect:
  117. case scm_tc7_cvect:
  118. #endif
  119. return scm_class_vector;
  120. case scm_tc7_string:
  121. case scm_tc7_substring:
  122. return scm_class_string;
  123. case scm_tc7_asubr:
  124. case scm_tc7_subr_0:
  125. case scm_tc7_subr_1:
  126. case scm_tc7_cxr:
  127. case scm_tc7_subr_3:
  128. case scm_tc7_subr_2:
  129. case scm_tc7_rpsubr:
  130. case scm_tc7_subr_1o:
  131. case scm_tc7_subr_2o:
  132. case scm_tc7_lsubr_2:
  133. case scm_tc7_lsubr:
  134. if (SCM_SUBR_GENERIC (x) && *SCM_SUBR_GENERIC (x))
  135. return scm_class_primitive_generic;
  136. else
  137. return scm_class_procedure;
  138. case scm_tc7_cclo:
  139. return scm_class_procedure;
  140. case scm_tc7_pws:
  141. return scm_class_procedure_with_setter;
  142. case scm_tc7_smob:
  143. {
  144. long type = SCM_TYP16 (x);
  145. if (type != scm_tc16_port_with_ps)
  146. return scm_smob_class[SCM_TC2SMOBNUM (type)];
  147. x = SCM_PORT_WITH_PS_PORT (x);
  148. /* fall through to ports */
  149. }
  150. case scm_tc7_port:
  151. return scm_port_class[(SCM_WRTNG & SCM_CELL_WORD_0 (x)
  152. ? (SCM_RDNG & SCM_CELL_WORD_0 (x)
  153. ? SCM_INOUT_PCLASS_INDEX | SCM_PTOBNUM (x)
  154. : SCM_OUT_PCLASS_INDEX | SCM_PTOBNUM (x))
  155. : SCM_IN_PCLASS_INDEX | SCM_PTOBNUM (x))];
  156. case scm_tcs_cons_gloc:
  157. /* must be a struct */
  158. if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS_VALID)
  159. return SCM_CLASS_OF (x);
  160. else if (SCM_OBJ_CLASS_FLAGS (x) & SCM_CLASSF_GOOPS)
  161. {
  162. /* Goops object */
  163. if (! SCM_FALSEP (SCM_OBJ_CLASS_REDEF (x)))
  164. scm_change_object_class (x,
  165. SCM_CLASS_OF (x), /* old */
  166. SCM_OBJ_CLASS_REDEF (x)); /* new */
  167. return SCM_CLASS_OF (x);
  168. }
  169. else
  170. {
  171. /* ordinary struct */
  172. SCM handle = scm_struct_create_handle (SCM_STRUCT_VTABLE (x));
  173. if (SCM_NFALSEP (SCM_STRUCT_TABLE_CLASS (SCM_CDR (handle))))
  174. return SCM_STRUCT_TABLE_CLASS (SCM_CDR (handle));
  175. else
  176. {
  177. SCM name = SCM_STRUCT_TABLE_NAME (SCM_CDR (handle));
  178. SCM class = scm_make_extended_class (SCM_NFALSEP (name)
  179. ? SCM_ROCHARS (name)
  180. : 0);
  181. SCM_SET_STRUCT_TABLE_CLASS (SCM_CDR (handle), class);
  182. return class;
  183. }
  184. }
  185. default:
  186. if (SCM_CONSP (x))
  187. return scm_class_pair;
  188. else
  189. return scm_class_unknown;
  190. }
  191. case scm_tc3_cons_gloc:
  192. case scm_tc3_tc7_1:
  193. case scm_tc3_tc7_2:
  194. case scm_tc3_closure:
  195. /* Never reached */
  196. break;
  197. }
  198. return scm_class_unknown;
  199. }
  200. /* (SCM_IM_DISPATCH ARGS N-SPECIALIZED
  201. * #((TYPE1 ... ENV FORMALS FORM ...) ...)
  202. * GF)
  203. *
  204. * (SCM_IM_HASH_DISPATCH ARGS N-SPECIALIZED HASHSET MASK
  205. * #((TYPE1 ... ENV FORMALS FORM ...) ...)
  206. * GF)
  207. *
  208. * ARGS is either a list of expressions, in which case they
  209. * are interpreted as the arguments of an application, or
  210. * a non-pair, which is interpreted as a single expression
  211. * yielding all arguments.
  212. *
  213. * SCM_IM_DISPATCH expressions in generic functions always
  214. * have ARGS = the symbol `args' or the iloc #@0-0.
  215. *
  216. * Need FORMALS in order to support varying arity. This
  217. * also avoids the need for renaming of bindings.
  218. *
  219. * We should probably not complicate this mechanism by
  220. * introducing "optimizations" for getters and setters or
  221. * primitive methods. Getters and setter will normally be
  222. * compiled into @slot-[ref|set!] or a procedure call.
  223. * They rely on the dispatch performed before executing
  224. * the code which contains them.
  225. *
  226. * We might want to use a more efficient representation of
  227. * this form in the future, perhaps after we have introduced
  228. * low-level support for syntax-case macros.
  229. */
  230. SCM
  231. scm_mcache_lookup_cmethod (SCM cache, SCM args)
  232. {
  233. int i, n, end, mask;
  234. SCM ls, methods, z = SCM_CDDR (cache);
  235. n = SCM_INUM (SCM_CAR (z)); /* maximum number of specializers */
  236. methods = SCM_CADR (z);
  237. if (SCM_NIMP (methods))
  238. {
  239. /* Prepare for linear search */
  240. mask = -1;
  241. i = 0;
  242. end = SCM_LENGTH (methods);
  243. }
  244. else
  245. {
  246. /* Compute a hash value */
  247. int hashset = SCM_INUM (methods);
  248. int j = n;
  249. mask = SCM_INUM (SCM_CAR (z = SCM_CDDR (z)));
  250. methods = SCM_CADR (z);
  251. i = 0;
  252. ls = args;
  253. if (SCM_NIMP (ls))
  254. do
  255. {
  256. i += SCM_STRUCT_DATA (scm_class_of (SCM_CAR (ls)))
  257. [scm_si_hashsets + hashset];
  258. ls = SCM_CDR (ls);
  259. }
  260. while (--j && SCM_NIMP (ls));
  261. i &= mask;
  262. end = i;
  263. }
  264. /* Search for match */
  265. do
  266. {
  267. int j = n;
  268. z = SCM_VELTS (methods)[i];
  269. ls = args; /* list of arguments */
  270. if (SCM_NIMP (ls))
  271. do
  272. {
  273. /* More arguments than specifiers => CLASS != ENV */
  274. if (! SCM_EQ_P (scm_class_of (SCM_CAR (ls)), SCM_CAR (z)))
  275. goto next_method;
  276. ls = SCM_CDR (ls);
  277. z = SCM_CDR (z);
  278. }
  279. while (--j && SCM_NIMP (ls));
  280. /* Fewer arguments than specifiers => CAR != ENV */
  281. if (!(SCM_IMP (SCM_CAR (z)) || SCM_CONSP (SCM_CAR (z))))
  282. goto next_method;
  283. return z;
  284. next_method:
  285. i = (i + 1) & mask;
  286. } while (i != end);
  287. return SCM_BOOL_F;
  288. }
  289. SCM
  290. scm_mcache_compute_cmethod (SCM cache, SCM args)
  291. {
  292. SCM cmethod = scm_mcache_lookup_cmethod (cache, args);
  293. if (SCM_IMP (cmethod))
  294. /* No match - memoize */
  295. return scm_memoize_method (cache, args);
  296. return cmethod;
  297. }
  298. SCM
  299. scm_apply_generic (SCM gf, SCM args)
  300. {
  301. SCM cmethod = scm_mcache_compute_cmethod (SCM_ENTITY_PROCEDURE (gf), args);
  302. return scm_eval_body (SCM_CDR (SCM_CMETHOD_CODE (cmethod)),
  303. SCM_EXTEND_ENV (SCM_CAR (SCM_CMETHOD_CODE (cmethod)),
  304. args,
  305. SCM_CMETHOD_ENV (cmethod)));
  306. }
  307. SCM
  308. scm_call_generic_0 (SCM gf)
  309. {
  310. return scm_apply_generic (gf, SCM_EOL);
  311. }
  312. SCM
  313. scm_call_generic_1 (SCM gf, SCM a1)
  314. {
  315. return scm_apply_generic (gf, SCM_LIST1 (a1));
  316. }
  317. SCM
  318. scm_call_generic_2 (SCM gf, SCM a1, SCM a2)
  319. {
  320. return scm_apply_generic (gf, SCM_LIST2 (a1, a2));
  321. }
  322. SCM
  323. scm_call_generic_3 (SCM gf, SCM a1, SCM a2, SCM a3)
  324. {
  325. return scm_apply_generic (gf, SCM_LIST3 (a1, a2, a3));
  326. }
  327. SCM_DEFINE (scm_entity_p, "entity?", 1, 0, 0,
  328. (SCM obj),
  329. "")
  330. #define FUNC_NAME s_scm_entity_p
  331. {
  332. return SCM_BOOL(SCM_STRUCTP (obj) && SCM_I_ENTITYP (obj));
  333. }
  334. #undef FUNC_NAME
  335. SCM_DEFINE (scm_operator_p, "operator?", 1, 0, 0,
  336. (SCM obj),
  337. "")
  338. #define FUNC_NAME s_scm_operator_p
  339. {
  340. return SCM_BOOL(SCM_STRUCTP (obj)
  341. && SCM_I_OPERATORP (obj)
  342. && !SCM_I_ENTITYP (obj));
  343. }
  344. #undef FUNC_NAME
  345. SCM_DEFINE (scm_set_object_procedure_x, "set-object-procedure!", 2, 0, 0,
  346. (SCM obj, SCM proc),
  347. "")
  348. #define FUNC_NAME s_scm_set_object_procedure_x
  349. {
  350. SCM_ASSERT (SCM_STRUCTP (obj)
  351. && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
  352. || (SCM_I_ENTITYP (obj)
  353. && !(SCM_OBJ_CLASS_FLAGS (obj)
  354. & SCM_CLASSF_PURE_GENERIC))),
  355. obj,
  356. SCM_ARG1,
  357. FUNC_NAME);
  358. SCM_VALIDATE_PROC (2,proc);
  359. if (SCM_I_ENTITYP (obj))
  360. SCM_SET_ENTITY_PROCEDURE (obj, proc);
  361. else
  362. SCM_OPERATOR_CLASS (obj)->procedure = proc;
  363. return SCM_UNSPECIFIED;
  364. }
  365. #undef FUNC_NAME
  366. #ifdef GUILE_DEBUG
  367. SCM_DEFINE (scm_object_procedure, "object-procedure", 1, 0, 0,
  368. (SCM obj),
  369. "")
  370. #define FUNC_NAME s_scm_object_procedure
  371. {
  372. SCM_ASSERT (SCM_STRUCTP (obj)
  373. && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
  374. || SCM_I_ENTITYP (obj)),
  375. obj, SCM_ARG1, FUNC_NAME);
  376. return (SCM_I_ENTITYP (obj)
  377. ? SCM_ENTITY_PROCEDURE (obj)
  378. : SCM_OPERATOR_CLASS (obj)->procedure);
  379. }
  380. #undef FUNC_NAME
  381. #endif /* GUILE_DEBUG */
  382. /* The following procedures are not a part of Goops but a minimal
  383. * object system built upon structs. They are here for those who
  384. * want to implement their own object system.
  385. */
  386. SCM
  387. scm_i_make_class_object (SCM meta,
  388. SCM layout_string,
  389. unsigned long flags)
  390. {
  391. SCM c;
  392. SCM layout = scm_make_struct_layout (layout_string);
  393. c = scm_make_struct (meta,
  394. SCM_INUM0,
  395. SCM_LIST4 (layout, SCM_BOOL_F, SCM_EOL, SCM_EOL));
  396. SCM_SET_CLASS_FLAGS (c, flags);
  397. return c;
  398. }
  399. SCM_DEFINE (scm_make_class_object, "make-class-object", 2, 0, 0,
  400. (SCM metaclass, SCM layout),
  401. "")
  402. #define FUNC_NAME s_scm_make_class_object
  403. {
  404. unsigned long flags = 0;
  405. SCM_VALIDATE_STRUCT (1,metaclass);
  406. SCM_VALIDATE_STRING (2,layout);
  407. if (SCM_EQ_P (metaclass, scm_metaclass_operator))
  408. flags = SCM_CLASSF_OPERATOR;
  409. return scm_i_make_class_object (metaclass, layout, flags);
  410. }
  411. #undef FUNC_NAME
  412. SCM_DEFINE (scm_make_subclass_object, "make-subclass-object", 2, 0, 0,
  413. (SCM class, SCM layout),
  414. "")
  415. #define FUNC_NAME s_scm_make_subclass_object
  416. {
  417. SCM pl;
  418. SCM_VALIDATE_STRUCT (1,class);
  419. SCM_VALIDATE_STRING (2,layout);
  420. pl = SCM_PACK (SCM_STRUCT_DATA (class) [scm_vtable_index_layout]);
  421. /* Convert symbol->string */
  422. pl = scm_makfromstr (SCM_CHARS (pl), (scm_sizet) SCM_LENGTH (pl), 0);
  423. return scm_i_make_class_object (SCM_STRUCT_VTABLE (class),
  424. scm_string_append (SCM_LIST2 (pl, layout)),
  425. SCM_CLASS_FLAGS (class));
  426. }
  427. #undef FUNC_NAME
  428. void
  429. scm_init_objects ()
  430. {
  431. SCM ms = scm_makfrom0str (SCM_METACLASS_STANDARD_LAYOUT);
  432. SCM ml = scm_make_struct_layout (ms);
  433. SCM mt = scm_make_vtable_vtable (ml, SCM_INUM0,
  434. SCM_LIST3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
  435. SCM os = scm_makfrom0str (SCM_METACLASS_OPERATOR_LAYOUT);
  436. SCM ol = scm_make_struct_layout (os);
  437. SCM ot = scm_make_vtable_vtable (ol, SCM_INUM0,
  438. SCM_LIST3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
  439. SCM es = scm_makfrom0str (SCM_ENTITY_LAYOUT);
  440. SCM el = scm_make_struct_layout (es);
  441. SCM et = scm_make_struct (mt, SCM_INUM0,
  442. SCM_LIST4 (el, SCM_BOOL_F, SCM_EOL, SCM_EOL));
  443. scm_sysintern ("<class>", mt);
  444. scm_metaclass_standard = mt;
  445. scm_sysintern ("<operator-class>", ot);
  446. scm_metaclass_operator = ot;
  447. SCM_SET_CLASS_FLAGS (et, SCM_CLASSF_OPERATOR | SCM_CLASSF_ENTITY);
  448. SCM_SET_CLASS_DESTRUCTOR (et, scm_struct_free_entity);
  449. scm_sysintern ("<entity>", et);
  450. #include "libguile/objects.x"
  451. }
  452. /*
  453. Local Variables:
  454. c-file-style: "gnu"
  455. End:
  456. */