summaryrefslogtreecommitdiff
path: root/libguile/procs.c
blob: bda6d34482f21202247e57f5ebf1ec212fef7ad2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* Copyright (C) 1995, 1996, 1997, 1999, 2000, 2001, 2006, 2008, 2009,
 *   2010, 2011, 2012, 2013 Free Software Foundation, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */



#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "libguile/_scm.h"

#include "libguile/strings.h"
#include "libguile/vectors.h"
#include "libguile/smob.h"
#include "libguile/deprecation.h"

#include "libguile/validate.h"
#include "libguile/procs.h"
#include "libguile/procprop.h"
#include "libguile/objcodes.h"
#include "libguile/programs.h"



/* {Procedures}
 */


SCM_DEFINE (scm_procedure_p, "procedure?", 1, 0, 0, 
	    (SCM obj),
	    "Return @code{#t} if @var{obj} is a procedure.")
#define FUNC_NAME s_scm_procedure_p
{
  return scm_from_bool (SCM_PROGRAM_P (obj)
                        || SCM_RTL_PROGRAM_P (obj)
                        || (SCM_STRUCTP (obj) && SCM_STRUCT_APPLICABLE_P (obj))
                        || (SCM_HAS_TYP7 (obj, scm_tc7_smob)
                            && SCM_SMOB_APPLICABLE_P (obj)));
}
#undef FUNC_NAME

SCM_DEFINE (scm_thunk_p, "thunk?", 1, 0, 0, 
	    (SCM obj),
	    "Return @code{#t} if @var{obj} is a thunk.")
#define FUNC_NAME s_scm_thunk_p
{
  int req, opt, rest;
  return scm_from_bool (scm_i_procedure_arity (obj, &req, &opt, &rest)
                        && req == 0);
}
#undef FUNC_NAME

SCM_GLOBAL_SYMBOL (scm_sym_documentation, "documentation");

SCM_DEFINE (scm_procedure_documentation, "procedure-documentation", 1, 0, 0, 
           (SCM proc),
	    "Return the documentation string associated with @code{proc}.  By\n"
	    "convention, if a procedure contains more than one expression and the\n"
	    "first expression is a string constant, that string is assumed to contain\n"
	    "documentation for that procedure.")
#define FUNC_NAME s_scm_procedure_documentation
{
  SCM_VALIDATE_PROC (SCM_ARG1, proc);
  return scm_procedure_property (proc, scm_sym_documentation);
}
#undef FUNC_NAME


/* Procedure-with-setter
 */

static SCM pws_vtable;


SCM_DEFINE (scm_procedure_with_setter_p, "procedure-with-setter?", 1, 0, 0, 
            (SCM obj),
	    "Return @code{#t} if @var{obj} is a procedure with an\n"
	    "associated setter procedure.")
#define FUNC_NAME s_scm_procedure_with_setter_p
{
  return scm_from_bool (SCM_STRUCTP (obj) && SCM_STRUCT_SETTER_P (obj));
}
#undef FUNC_NAME

SCM_DEFINE (scm_make_procedure_with_setter, "make-procedure-with-setter", 2, 0, 0, 
            (SCM procedure, SCM setter),
	    "Create a new procedure which behaves like @var{procedure}, but\n"
	    "with the associated setter @var{setter}.")
#define FUNC_NAME s_scm_make_procedure_with_setter
{
  SCM name, ret;
  SCM_VALIDATE_PROC (1, procedure);
  SCM_VALIDATE_PROC (2, setter);
  ret = scm_make_struct (pws_vtable, SCM_INUM0,
                         scm_list_2 (procedure, setter));

  /* don't use procedure_name, because don't care enough to do a reverse
     lookup */
  name = scm_procedure_property (procedure, scm_sym_name);
  if (scm_is_true (name))
    scm_set_procedure_property_x (ret, scm_sym_name, name);
  return ret;
}
#undef FUNC_NAME

SCM_DEFINE (scm_procedure, "procedure", 1, 0, 0, 
            (SCM proc),
	    "Return the procedure of @var{proc}, which must be an\n"
	    "applicable struct.")
#define FUNC_NAME s_scm_procedure
{
  SCM_ASSERT (SCM_STRUCTP (proc) && SCM_STRUCT_APPLICABLE_P (proc),
              proc, SCM_ARG1, FUNC_NAME);
  return SCM_STRUCT_PROCEDURE (proc);
}
#undef FUNC_NAME

SCM_PRIMITIVE_GENERIC (scm_setter, "setter", 1, 0, 0,
                       (SCM proc),
                       "Return the setter of @var{proc}, which must be an\n"
                       "applicable struct with a setter.")
#define FUNC_NAME s_scm_setter
{
  if (SCM_UNLIKELY (!SCM_STRUCTP (proc)))
    return scm_wta_dispatch_1 (g_scm_setter, proc, SCM_ARG1, FUNC_NAME);
  if (SCM_STRUCT_SETTER_P (proc))
    return SCM_STRUCT_SETTER (proc);
  if (SCM_PUREGENERICP (proc)
      && SCM_IS_A_P (proc, scm_class_generic_with_setter))
    /* FIXME: might not be an accessor */
    return SCM_GENERIC_SETTER (proc);
  return scm_wta_dispatch_1 (g_scm_setter, proc, SCM_ARG1, FUNC_NAME);
  return SCM_BOOL_F; /* not reached */
}
#undef FUNC_NAME


void
scm_init_procs ()
{
  pws_vtable =
    scm_c_make_struct (scm_applicable_struct_with_setter_vtable_vtable,
                       0,
                       1,
                       SCM_UNPACK (scm_from_latin1_symbol ("pwpw")));

#include "libguile/procs.x"
}

/*
  Local Variables:
  c-file-style: "gnu"
  End:
*/