objects.c 11 KB

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