gsubr.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* Copyright (C) 1995,1996,1997,1998, 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. #include <stdio.h>
  42. #include "libguile/_scm.h"
  43. #include "libguile/procprop.h"
  44. #include "libguile/root.h"
  45. #include "libguile/vectors.h"
  46. #include "libguile/gsubr.h"
  47. /*
  48. * gsubr.c
  49. * Provide `gsubrs' -- subrs taking a prescribed number of required, optional,
  50. * and rest arguments.
  51. */
  52. /* #define GSUBR_TEST */
  53. SCM scm_sym_name;
  54. SCM scm_f_gsubr_apply;
  55. SCM
  56. scm_make_gsubr(const char *name,int req,int opt,int rst,SCM (*fcn)())
  57. {
  58. switch SCM_GSUBR_MAKTYPE(req, opt, rst) {
  59. case SCM_GSUBR_MAKTYPE(0, 0, 0): return scm_make_subr(name, scm_tc7_subr_0, fcn);
  60. case SCM_GSUBR_MAKTYPE(1, 0, 0): return scm_make_subr(name, scm_tc7_subr_1, fcn);
  61. case SCM_GSUBR_MAKTYPE(0, 1, 0): return scm_make_subr(name, scm_tc7_subr_1o, fcn);
  62. case SCM_GSUBR_MAKTYPE(1, 1, 0): return scm_make_subr(name, scm_tc7_subr_2o, fcn);
  63. case SCM_GSUBR_MAKTYPE(2, 0, 0): return scm_make_subr(name, scm_tc7_subr_2, fcn);
  64. case SCM_GSUBR_MAKTYPE(3, 0, 0): return scm_make_subr(name, scm_tc7_subr_3, fcn);
  65. case SCM_GSUBR_MAKTYPE(0, 0, 1): return scm_make_subr(name, scm_tc7_lsubr, fcn);
  66. case SCM_GSUBR_MAKTYPE(2, 0, 1): return scm_make_subr(name, scm_tc7_lsubr_2, fcn);
  67. default:
  68. {
  69. SCM symcell = scm_sysintern (name, SCM_UNDEFINED);
  70. SCM cclo = scm_makcclo (scm_f_gsubr_apply, 3L);
  71. if (SCM_GSUBR_MAX < req + opt + rst) {
  72. fprintf (stderr,
  73. "ERROR in scm_c_make_gsubr: too many args (%d) to %s\n",
  74. req + opt + rst, name);
  75. exit (1);
  76. }
  77. SCM_GSUBR_PROC (cclo) = scm_make_subr_opt (name, scm_tc7_subr_0, fcn, 0);
  78. SCM_GSUBR_TYPE (cclo) = SCM_MAKINUM (SCM_GSUBR_MAKTYPE (req, opt, rst));
  79. SCM_SETCDR (symcell, cclo);
  80. #ifdef DEBUG_EXTENSIONS
  81. if (SCM_REC_PROCNAMES_P)
  82. scm_set_procedure_property_x (cclo, scm_sym_name, SCM_CAR (symcell));
  83. #endif
  84. return cclo;
  85. }
  86. }
  87. }
  88. SCM
  89. scm_make_gsubr_with_generic (const char *name,
  90. int req,
  91. int opt,
  92. int rst,
  93. SCM (*fcn)(),
  94. SCM *gf)
  95. {
  96. switch SCM_GSUBR_MAKTYPE(req, opt, rst) {
  97. case SCM_GSUBR_MAKTYPE(0, 0, 0):
  98. return scm_make_subr_with_generic(name, scm_tc7_subr_0, fcn, gf);
  99. case SCM_GSUBR_MAKTYPE(1, 0, 0):
  100. return scm_make_subr_with_generic(name, scm_tc7_subr_1, fcn, gf);
  101. case SCM_GSUBR_MAKTYPE(0, 1, 0):
  102. return scm_make_subr_with_generic(name, scm_tc7_subr_1o, fcn, gf);
  103. case SCM_GSUBR_MAKTYPE(1, 1, 0):
  104. return scm_make_subr_with_generic(name, scm_tc7_subr_2o, fcn, gf);
  105. case SCM_GSUBR_MAKTYPE(2, 0, 0):
  106. return scm_make_subr_with_generic(name, scm_tc7_subr_2, fcn, gf);
  107. case SCM_GSUBR_MAKTYPE(3, 0, 0):
  108. return scm_make_subr_with_generic(name, scm_tc7_subr_3, fcn, gf);
  109. case SCM_GSUBR_MAKTYPE(0, 0, 1):
  110. return scm_make_subr_with_generic(name, scm_tc7_lsubr, fcn, gf);
  111. case SCM_GSUBR_MAKTYPE(2, 0, 1):
  112. return scm_make_subr_with_generic(name, scm_tc7_lsubr_2, fcn, gf);
  113. default:
  114. ;
  115. }
  116. scm_misc_error ("scm_make_gsubr_with_generic",
  117. "can't make primitive-generic with this arity",
  118. SCM_EOL);
  119. return SCM_BOOL_F; /* never reached */
  120. }
  121. SCM
  122. scm_gsubr_apply (SCM args)
  123. {
  124. SCM self = SCM_CAR(args);
  125. SCM (*fcn)() = SCM_SUBRF(SCM_GSUBR_PROC(self));
  126. SCM v[10]; /* must agree with greatest supported arity */
  127. int typ = SCM_INUM(SCM_GSUBR_TYPE(self));
  128. int i, n = SCM_GSUBR_REQ(typ) + SCM_GSUBR_OPT(typ) + SCM_GSUBR_REST(typ);
  129. #if 0
  130. SCM_ASSERT(n <= sizeof(v)/sizeof(SCM),
  131. self, "internal programming error", FUNC_NAME);
  132. #endif
  133. args = SCM_CDR(args);
  134. for (i = 0; i < SCM_GSUBR_REQ(typ); i++) {
  135. #ifndef SCM_RECKLESS
  136. if (SCM_IMP(args))
  137. wnargs: scm_wrong_num_args (SCM_SNAME(SCM_GSUBR_PROC(self)));
  138. #endif
  139. v[i] = SCM_CAR(args);
  140. args = SCM_CDR(args);
  141. }
  142. for (; i < SCM_GSUBR_REQ(typ) + SCM_GSUBR_OPT(typ); i++) {
  143. if (SCM_NIMP(args)) {
  144. v[i] = SCM_CAR(args);
  145. args = SCM_CDR(args);
  146. }
  147. else
  148. v[i] = SCM_UNDEFINED;
  149. }
  150. if (SCM_GSUBR_REST(typ))
  151. v[i] = args;
  152. else
  153. SCM_ASRTGO(SCM_NULLP(args), wnargs);
  154. switch (n) {
  155. case 2: return (*fcn)(v[0], v[1]);
  156. case 3: return (*fcn)(v[0], v[1], v[2]);
  157. case 4: return (*fcn)(v[0], v[1], v[2], v[3]);
  158. case 5: return (*fcn)(v[0], v[1], v[2], v[3], v[4]);
  159. case 6: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5]);
  160. case 7: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6]);
  161. case 8: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
  162. case 9: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
  163. case 10: return (*fcn)(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]);
  164. }
  165. return SCM_BOOL_F; /* Never reached. */
  166. }
  167. #ifdef GSUBR_TEST
  168. /* A silly example, taking 2 required args, 1 optional, and
  169. a scm_list of rest args
  170. */
  171. SCM
  172. gsubr_21l(SCM req1, SCM req2, SCM opt, SCM rst)
  173. {
  174. scm_puts ("gsubr-2-1-l:\n req1: ", scm_cur_outp);
  175. scm_display(req1, scm_cur_outp);
  176. scm_puts ("\n req2: ", scm_cur_outp);
  177. scm_display(req2, scm_cur_outp);
  178. scm_puts ("\n opt: ", scm_cur_outp);
  179. scm_display(opt, scm_cur_outp);
  180. scm_puts ("\n rest: ", scm_cur_outp);
  181. scm_display(rst, scm_cur_outp);
  182. scm_newline(scm_cur_outp);
  183. return SCM_UNSPECIFIED;
  184. }
  185. #endif
  186. void
  187. scm_init_gsubr()
  188. {
  189. /* GJB:FIXME:MD: Use scm_make_subr_opt instead -- gsubr-apply should not be a
  190. published primitive available at the Scheme level */
  191. scm_f_gsubr_apply = scm_make_subr_opt("gsubr-apply", scm_tc7_lsubr, scm_gsubr_apply, 0);
  192. scm_sym_name = SCM_CAR (scm_sysintern ("name", SCM_UNDEFINED));
  193. scm_permanent_object (scm_sym_name);
  194. #ifdef GSUBR_TEST
  195. scm_make_gsubr("gsubr-2-1-l", 2, 1, 1, gsubr_21l); /* example */
  196. #endif
  197. }
  198. /*
  199. Local Variables:
  200. c-file-style: "gnu"
  201. End:
  202. */