objects.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /* Copyright (C) 1995,1996,1999,2000,2001, 2003, 2004, 2006, 2008 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
  5. * License as published by the Free Software Foundation; either
  6. * version 2.1 of the License, or (at your option) any later version.
  7. *
  8. * This library 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 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 02110-1301 USA
  16. */
  17. /* This file and objects.h contains those minimal pieces of the Guile
  18. * Object Oriented Programming System which need to be included in
  19. * libguile. See the comments in objects.h.
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. # include <config.h>
  23. #endif
  24. #include "libguile/_scm.h"
  25. #include "libguile/struct.h"
  26. #include "libguile/procprop.h"
  27. #include "libguile/chars.h"
  28. #include "libguile/keywords.h"
  29. #include "libguile/smob.h"
  30. #include "libguile/eval.h"
  31. #include "libguile/alist.h"
  32. #include "libguile/ports.h"
  33. #include "libguile/strings.h"
  34. #include "libguile/vectors.h"
  35. #include "libguile/validate.h"
  36. #include "libguile/objects.h"
  37. #include "libguile/goops.h"
  38. SCM scm_metaclass_standard;
  39. SCM scm_metaclass_operator;
  40. /* The cache argument for scm_mcache_lookup_cmethod has one of two possible
  41. * formats:
  42. *
  43. * Format #1:
  44. * (SCM_IM_DISPATCH ARGS N-SPECIALIZED
  45. * #((TYPE1 ... ENV FORMALS FORM ...) ...)
  46. * GF)
  47. *
  48. * Format #2:
  49. * (SCM_IM_HASH_DISPATCH ARGS N-SPECIALIZED HASHSET MASK
  50. * #((TYPE1 ... ENV FORMALS FORM ...) ...)
  51. * GF)
  52. *
  53. * ARGS is either a list of expressions, in which case they
  54. * are interpreted as the arguments of an application, or
  55. * a non-pair, which is interpreted as a single expression
  56. * yielding all arguments.
  57. *
  58. * SCM_IM_DISPATCH expressions in generic functions always
  59. * have ARGS = the symbol `args' or the iloc #@0-0.
  60. *
  61. * Need FORMALS in order to support varying arity. This
  62. * also avoids the need for renaming of bindings.
  63. *
  64. * We should probably not complicate this mechanism by
  65. * introducing "optimizations" for getters and setters or
  66. * primitive methods. Getters and setter will normally be
  67. * compiled into @slot-[ref|set!] or a procedure call.
  68. * They rely on the dispatch performed before executing
  69. * the code which contains them.
  70. *
  71. * We might want to use a more efficient representation of
  72. * this form in the future, perhaps after we have introduced
  73. * low-level support for syntax-case macros.
  74. */
  75. SCM
  76. scm_mcache_lookup_cmethod (SCM cache, SCM args)
  77. {
  78. unsigned long i, mask, n, end;
  79. SCM ls, methods, z = SCM_CDDR (cache);
  80. n = scm_to_ulong (SCM_CAR (z)); /* maximum number of specializers */
  81. methods = SCM_CADR (z);
  82. if (scm_is_simple_vector (methods))
  83. {
  84. /* cache format #1: prepare for linear search */
  85. mask = -1;
  86. i = 0;
  87. end = SCM_SIMPLE_VECTOR_LENGTH (methods);
  88. }
  89. else
  90. {
  91. /* cache format #2: compute a hash value */
  92. unsigned long hashset = scm_to_ulong (methods);
  93. long j = n;
  94. z = SCM_CDDR (z);
  95. mask = scm_to_ulong (SCM_CAR (z));
  96. methods = SCM_CADR (z);
  97. i = 0;
  98. ls = args;
  99. if (!scm_is_null (ls))
  100. do
  101. {
  102. i += SCM_STRUCT_DATA (scm_class_of (SCM_CAR (ls)))
  103. [scm_si_hashsets + hashset];
  104. ls = SCM_CDR (ls);
  105. }
  106. while (j-- && !scm_is_null (ls));
  107. i &= mask;
  108. end = i;
  109. }
  110. /* Search for match */
  111. do
  112. {
  113. long j = n;
  114. z = SCM_SIMPLE_VECTOR_REF (methods, i);
  115. ls = args; /* list of arguments */
  116. if (!scm_is_null (ls))
  117. do
  118. {
  119. /* More arguments than specifiers => CLASS != ENV */
  120. if (! scm_is_eq (scm_class_of (SCM_CAR (ls)), SCM_CAR (z)))
  121. goto next_method;
  122. ls = SCM_CDR (ls);
  123. z = SCM_CDR (z);
  124. }
  125. while (j-- && !scm_is_null (ls));
  126. /* Fewer arguments than specifiers => CAR != ENV */
  127. if (scm_is_null (SCM_CAR (z)) || scm_is_pair (SCM_CAR (z)))
  128. return z;
  129. next_method:
  130. i = (i + 1) & mask;
  131. } while (i != end);
  132. return SCM_BOOL_F;
  133. }
  134. SCM
  135. scm_mcache_compute_cmethod (SCM cache, SCM args)
  136. {
  137. SCM cmethod = scm_mcache_lookup_cmethod (cache, args);
  138. if (scm_is_false (cmethod))
  139. /* No match - memoize */
  140. return scm_memoize_method (cache, args);
  141. return cmethod;
  142. }
  143. SCM
  144. scm_apply_generic (SCM gf, SCM args)
  145. {
  146. SCM cmethod = scm_mcache_compute_cmethod (SCM_ENTITY_PROCEDURE (gf), args);
  147. return scm_eval_body (SCM_CDR (SCM_CMETHOD_CODE (cmethod)),
  148. SCM_EXTEND_ENV (SCM_CAR (SCM_CMETHOD_CODE (cmethod)),
  149. args,
  150. SCM_CMETHOD_ENV (cmethod)));
  151. }
  152. SCM
  153. scm_call_generic_0 (SCM gf)
  154. {
  155. return scm_apply_generic (gf, SCM_EOL);
  156. }
  157. SCM
  158. scm_call_generic_1 (SCM gf, SCM a1)
  159. {
  160. return scm_apply_generic (gf, scm_list_1 (a1));
  161. }
  162. SCM
  163. scm_call_generic_2 (SCM gf, SCM a1, SCM a2)
  164. {
  165. return scm_apply_generic (gf, scm_list_2 (a1, a2));
  166. }
  167. SCM
  168. scm_call_generic_3 (SCM gf, SCM a1, SCM a2, SCM a3)
  169. {
  170. return scm_apply_generic (gf, scm_list_3 (a1, a2, a3));
  171. }
  172. SCM_DEFINE (scm_entity_p, "entity?", 1, 0, 0,
  173. (SCM obj),
  174. "Return @code{#t} if @var{obj} is an entity.")
  175. #define FUNC_NAME s_scm_entity_p
  176. {
  177. return scm_from_bool(SCM_STRUCTP (obj) && SCM_I_ENTITYP (obj));
  178. }
  179. #undef FUNC_NAME
  180. SCM_DEFINE (scm_operator_p, "operator?", 1, 0, 0,
  181. (SCM obj),
  182. "Return @code{#t} if @var{obj} is an operator.")
  183. #define FUNC_NAME s_scm_operator_p
  184. {
  185. return scm_from_bool(SCM_STRUCTP (obj)
  186. && SCM_I_OPERATORP (obj)
  187. && !SCM_I_ENTITYP (obj));
  188. }
  189. #undef FUNC_NAME
  190. /* XXX - What code requires the object procedure to be only of certain
  191. types? */
  192. SCM_DEFINE (scm_valid_object_procedure_p, "valid-object-procedure?", 1, 0, 0,
  193. (SCM proc),
  194. "Return @code{#t} iff @var{proc} is a procedure that can be used "
  195. "with @code{set-object-procedure}. It is always valid to use "
  196. "a closure constructed by @code{lambda}.")
  197. #define FUNC_NAME s_scm_valid_object_procedure_p
  198. {
  199. if (SCM_IMP (proc))
  200. return SCM_BOOL_F;
  201. switch (SCM_TYP7 (proc))
  202. {
  203. default:
  204. return SCM_BOOL_F;
  205. case scm_tcs_closures:
  206. case scm_tc7_subr_1:
  207. case scm_tc7_subr_2:
  208. case scm_tc7_subr_3:
  209. case scm_tc7_lsubr_2:
  210. return SCM_BOOL_T;
  211. }
  212. }
  213. #undef FUNC_NAME
  214. SCM_DEFINE (scm_set_object_procedure_x, "set-object-procedure!", 2, 0, 0,
  215. (SCM obj, SCM proc),
  216. "Set the object procedure of @var{obj} to @var{proc}.\n"
  217. "@var{obj} must be either an entity or an operator.")
  218. #define FUNC_NAME s_scm_set_object_procedure_x
  219. {
  220. SCM_ASSERT (SCM_STRUCTP (obj)
  221. && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
  222. || (SCM_I_ENTITYP (obj)
  223. && !(SCM_OBJ_CLASS_FLAGS (obj)
  224. & SCM_CLASSF_PURE_GENERIC))),
  225. obj,
  226. SCM_ARG1,
  227. FUNC_NAME);
  228. SCM_ASSERT (scm_valid_object_procedure_p (proc), proc, SCM_ARG2, FUNC_NAME);
  229. if (SCM_I_ENTITYP (obj))
  230. SCM_SET_ENTITY_PROCEDURE (obj, proc);
  231. else
  232. SCM_OPERATOR_CLASS (obj)->procedure = proc;
  233. return SCM_UNSPECIFIED;
  234. }
  235. #undef FUNC_NAME
  236. #ifdef GUILE_DEBUG
  237. SCM_DEFINE (scm_object_procedure, "object-procedure", 1, 0, 0,
  238. (SCM obj),
  239. "Return the object procedure of @var{obj}. @var{obj} must be\n"
  240. "an entity or an operator.")
  241. #define FUNC_NAME s_scm_object_procedure
  242. {
  243. SCM_ASSERT (SCM_STRUCTP (obj)
  244. && ((SCM_CLASS_FLAGS (obj) & SCM_CLASSF_OPERATOR)
  245. || SCM_I_ENTITYP (obj)),
  246. obj, SCM_ARG1, FUNC_NAME);
  247. return (SCM_I_ENTITYP (obj)
  248. ? SCM_ENTITY_PROCEDURE (obj)
  249. : SCM_OPERATOR_CLASS (obj)->procedure);
  250. }
  251. #undef FUNC_NAME
  252. #endif /* GUILE_DEBUG */
  253. /* The following procedures are not a part of Goops but a minimal
  254. * object system built upon structs. They are here for those who
  255. * want to implement their own object system.
  256. */
  257. SCM
  258. scm_i_make_class_object (SCM meta,
  259. SCM layout_string,
  260. unsigned long flags)
  261. {
  262. SCM c;
  263. SCM layout = scm_make_struct_layout (layout_string);
  264. c = scm_make_struct (meta,
  265. SCM_INUM0,
  266. scm_list_4 (layout, SCM_BOOL_F, SCM_EOL, SCM_EOL));
  267. SCM_SET_CLASS_FLAGS (c, flags);
  268. return c;
  269. }
  270. SCM_DEFINE (scm_make_class_object, "make-class-object", 2, 0, 0,
  271. (SCM metaclass, SCM layout),
  272. "Create a new class object of class @var{metaclass}, with the\n"
  273. "slot layout specified by @var{layout}.")
  274. #define FUNC_NAME s_scm_make_class_object
  275. {
  276. unsigned long flags = 0;
  277. SCM_VALIDATE_STRUCT (1, metaclass);
  278. SCM_VALIDATE_STRING (2, layout);
  279. if (scm_is_eq (metaclass, scm_metaclass_operator))
  280. flags = SCM_CLASSF_OPERATOR;
  281. return scm_i_make_class_object (metaclass, layout, flags);
  282. }
  283. #undef FUNC_NAME
  284. SCM_DEFINE (scm_make_subclass_object, "make-subclass-object", 2, 0, 0,
  285. (SCM class, SCM layout),
  286. "Create a subclass object of @var{class}, with the slot layout\n"
  287. "specified by @var{layout}.")
  288. #define FUNC_NAME s_scm_make_subclass_object
  289. {
  290. SCM pl;
  291. SCM_VALIDATE_STRUCT (1, class);
  292. SCM_VALIDATE_STRING (2, layout);
  293. pl = SCM_PACK (SCM_STRUCT_DATA (class) [scm_vtable_index_layout]);
  294. pl = scm_symbol_to_string (pl);
  295. return scm_i_make_class_object (SCM_STRUCT_VTABLE (class),
  296. scm_string_append (scm_list_2 (pl, layout)),
  297. SCM_CLASS_FLAGS (class));
  298. }
  299. #undef FUNC_NAME
  300. void
  301. scm_init_objects ()
  302. {
  303. SCM ms = scm_from_locale_string (SCM_METACLASS_STANDARD_LAYOUT);
  304. SCM mt = scm_make_vtable_vtable (ms, SCM_INUM0,
  305. scm_list_3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
  306. SCM os = scm_from_locale_string (SCM_METACLASS_OPERATOR_LAYOUT);
  307. SCM ot = scm_make_vtable_vtable (os, SCM_INUM0,
  308. scm_list_3 (SCM_BOOL_F, SCM_EOL, SCM_EOL));
  309. SCM es = scm_from_locale_string (SCM_ENTITY_LAYOUT);
  310. SCM el = scm_make_struct_layout (es);
  311. SCM et = scm_make_struct (mt, SCM_INUM0,
  312. scm_list_4 (el, SCM_BOOL_F, SCM_EOL, SCM_EOL));
  313. scm_c_define ("<class>", mt);
  314. scm_metaclass_standard = mt;
  315. scm_c_define ("<operator-class>", ot);
  316. scm_metaclass_operator = ot;
  317. SCM_SET_CLASS_FLAGS (et, SCM_CLASSF_OPERATOR | SCM_CLASSF_ENTITY);
  318. SCM_SET_CLASS_DESTRUCTOR (et, scm_struct_free_entity);
  319. scm_c_define ("<entity>", et);
  320. #include "libguile/objects.x"
  321. }
  322. /*
  323. Local Variables:
  324. c-file-style: "gnu"
  325. End:
  326. */