12
12
See file '../Copyright' for full details.
15
16
#include <ecl/ecl.h>
16
17
#include <ecl/internal.h>
20
reshape_instance(cl_object x, int delta)
22
cl_fixnum size = x->instance.length + delta;
23
cl_object aux = ecl_allocate_instance(CLASS_OF(x), size);
24
memcpy(aux->instance.slots, x->instance.slots,
25
(delta < 0 ? aux->instance.length : x->instance.length) *
27
x->instance = aux->instance;
30
/* this turns any instance into a funcallable (apart from a builtin generic function)
31
or back into an ordinary instance */
19
si_set_funcallable(cl_object instance, cl_object flag)
34
si_set_raw_funcallable(cl_object instance, cl_object function)
21
36
if (type_of(instance) != t_instance)
22
37
FEwrong_type_argument(@'ext::instance', instance);
23
instance->instance.isgf = !Null(flag);
39
if (instance->instance.isgf == 2) {
40
int length = instance->instance.length-1;
41
cl_object *slots = (cl_object*)cl_alloc(sizeof(cl_object)*(length));
42
instance->instance.isgf = 2;
43
memcpy(slots, instance->instance.slots, sizeof(cl_object)*(length));
44
instance->instance.slots = slots;
45
instance->instance.length = length;
46
instance->instance.isgf = 0;
49
if (instance->instance.isgf == 0) {
50
int length = instance->instance.length+1;
51
cl_object *slots = (cl_object*)cl_alloc(sizeof(cl_object)*length);
52
memcpy(slots, instance->instance.slots, sizeof(cl_object)*(length-1));
53
instance->instance.slots = slots;
54
instance->instance.length = length;
55
instance->instance.isgf = 2;
57
instance->instance.slots[instance->instance.length-1] = function;
28
si_generic_function_p(cl_object instance)
30
@(return (((type_of(instance) != t_instance) &&
31
(instance->instance.isgf))? Ct : Cnil))
63
clos_set_funcallable_instance_function(cl_object x, cl_object function_or_t)
65
if (type_of(x) != t_instance)
66
FEwrong_type_argument(@'ext::instance', x);
67
if (x->instance.isgf == ECL_USER_DISPATCH) {
68
reshape_instance(x, -1);
69
x->instance.isgf = ECL_NOT_FUNCALLABLE;
71
if (function_or_t == Ct)
73
x->instance.isgf = ECL_STANDARD_DISPATCH;
74
} else if (function_or_t == Cnil) {
75
x->instance.isgf = ECL_NOT_FUNCALLABLE;
76
} else if (Null(cl_functionp(function_or_t))) {
77
FEwrong_type_argument(@'function', function_or_t);
79
reshape_instance(x, +1);
80
x->instance.slots[x->instance.length - 1] = function_or_t;
81
x->instance.isgf = ECL_USER_DISPATCH;
87
si_generic_function_p(cl_object x)
89
@(return (((type_of(x) != t_instance) &&
90
(x->instance.isgf))? Ct : Cnil))
96
compute_method(cl_narg narg, cl_object gf, cl_object *args)
155
standard_dispatch(cl_narg narg, cl_object gf, cl_object *args)
100
158
struct ecl_hashtable_entry *e;
101
159
cl_object spec_how_list = GFUN_SPEC(gf);
102
160
cl_object table = GFUN_HASH(gf);
104
cl_object argtype[narg]; /* __GNUC__ */
106
#define ARGTYPE_MAX 64
107
cl_object argtype[ARGTYPE_MAX];
108
if (narg > ARGTYPE_MAX)
109
FEerror("compute_method: Too many arguments, limited to ~A.", 1, MAKE_FIXNUM(ARGTYPE_MAX));
161
cl_object argtype[LAMBDA_PARAMETERS_LIMIT];
112
163
for (spec_no = 0; spec_how_list != Cnil;) {
113
164
cl_object spec_how = CAR(spec_how_list);
126
177
e = get_meth_hash(argtype, spec_no, table);
128
if (e->key == OBJNULL) {
179
if (e->key != OBJNULL) {
129
182
/* method not cached */
130
cl_object methods, arglist;
183
cl_object methods, arglist, func;
131
184
for (i = narg, arglist = Cnil; i-- > 0; ) {
132
185
arglist = CONS(args[i], arglist);
134
188
methods = funcall(3, @'compute-applicable-methods', gf,
136
190
if (methods == Cnil) {
137
VALUES(0) = funcall(3, @'no-applicable-method', gf,
191
func = funcall(3, @'no-applicable-method', gf,
141
196
func = funcall(4, @'clos::compute-effective-method', gf,
142
197
GFUN_COMB(gf), methods);
143
198
/* update cache */
144
199
set_meth_hash(argtype, spec_no, table, func);
146
/* method is already cached */
205
compute_method(cl_narg narg, cl_object gf, cl_object *args)
207
switch (gf->instance.isgf) {
208
case ECL_STANDARD_DISPATCH:
209
return standard_dispatch(narg, gf, args);
210
case ECL_USER_DISPATCH:
211
return gf->instance.slots[gf->instance.length - 1];
213
FEinvalid_function(gf);