Newer
Older
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/* -*- mode: c -*- */
/*
cmpaux.c -- Auxiliaries used in compiled Lisp code.
*/
/*
Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
Copyright (c) 1990, Giuseppe Attardi.
Copyright (c) 2001, Juan Jose Garcia Ripoll.
Copyright (c) 2010-2012, Jean-Claude Beaudoin.
MKCL 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.
See file '../../Copyright' for full details.
*/
#include <mkcl/mkcl-cmp.h>
#include <mkcl/mkcl-inl.h>
#include <mkcl/internal.h>
#include <string.h>
mkcl_object
mk_si_specialp(MKCL, mkcl_object sym)
{
@(return ((mkcl_symbol_type(env, sym) & mkcl_stp_special) ? mk_cl_Ct : mk_cl_Cnil));
}
mkcl_word
mkcl_ifloor(MKCL, mkcl_word x, mkcl_word y)
{
if (y == 0)
mkcl_FEerror(env, "Zero divizor", 0);
else if (y > 0)
if (x >= 0)
return(x/y);
else
return(-((-x+y-1))/y);
else
if (x >= 0)
return(-((x-y-1)/(-y)));
else
return((-x)/(-y));
}
mkcl_word
mkcl_imod(MKCL, mkcl_word x, mkcl_word y)
{
return(x - mkcl_ifloor(env, x, y)*y);
}
/*
* ----------------------------------------------------------------------
* Conversions to C
* ----------------------------------------------------------------------
*/
char
mkcl_to_char(MKCL, mkcl_object x)
{
switch (mkcl_type_of(x))
{
case mkcl_t_fixnum:
return mkcl_fixnum_to_word(x);
case mkcl_t_character:
return MKCL_CHAR_CODE(x);
default:
mkcl_FEerror(env, "~S cannot be coerced to a C char.", 1, x);
}
}
mkcl_word
mkcl_number_to_word(MKCL, mkcl_object x)
{
switch (mkcl_type_of(x))
{
case mkcl_t_fixnum:
case mkcl_t_bignum:
return mkcl_integer_to_word(env, x);
case mkcl_t_ratio:
return (mkcl_word)mkcl_to_double(env, x);
case mkcl_t_singlefloat:
return (mkcl_word)mkcl_single_float(x);
case mkcl_t_doublefloat:
return (mkcl_word)mkcl_double_float(x);
#ifdef MKCL_LONG_FLOAT
case mkcl_t_longfloat:
return (mkcl_word)mkcl_long_float(x);
#endif
default:
mkcl_FEerror(env, "~S cannot be coerced to a C int.", 1, x);
}
}
mkcl_index
mkcl_to_unsigned_integer(MKCL, mkcl_object x)
{
switch (mkcl_type_of(x))
{
case mkcl_t_fixnum:
case mkcl_t_bignum:
return mkcl_integer_to_index(env, x);
case mkcl_t_ratio:
return (mkcl_index)mkcl_to_double(env, x);
case mkcl_t_singlefloat:
return (mkcl_index)mkcl_single_float(x);
case mkcl_t_doublefloat:
return (mkcl_index)mkcl_double_float(x);
#ifdef MKCL_LONG_FLOAT
case mkcl_t_longfloat:
return (mkcl_index)mkcl_long_float(x);
#endif
default:
mkcl_FEerror(env, "~S cannot be coerced to a C unsigned int.", 1, x);
}
}
void
mkcl_throw(MKCL, mkcl_object tag)
{
mkcl_call_stack_check(env);
mkcl_frame_ptr fr = mkcl_frs_sch(env, tag);
if (fr == NULL)
mkcl_FEcontrol_error(env, "THROW: The catch ~S is undefined.", 1, tag);
mkcl_unwind(env, fr);
}
void
mkcl_return_from(MKCL, mkcl_object block_id, mkcl_object block_name)
{
mkcl_call_stack_check(env);
mkcl_frame_ptr fr = mkcl_frs_sch(env, block_id);
if (fr == NULL)
mkcl_FEcontrol_error(env, "RETURN-FROM: The block ~S is missing.", 1, block_name);
mkcl_unwind(env, fr);
}
void
mkcl_go(MKCL, mkcl_object tag_id, mkcl_index label_index)
{
mkcl_call_stack_check(env);
mkcl_frame_ptr fr = mkcl_frs_sch(env, tag_id);
if (fr == NULL)
mkcl_FEcontrol_error(env, "GO: The tagbody is missing for label ~S.", 1, MKCL_MAKE_FIXNUM(label_index));
env->go_label_index = label_index;
mkcl_unwind(env, fr);
}
mkcl_object
mkcl_grab_rest_args(MKCL, mkcl_va_list args, bool dynamic)
{
mkcl_object rest = mk_cl_Cnil;
mkcl_object *r = &rest;
mkcl_object (*conser)(MKCL, mkcl_object, mkcl_object) = (dynamic ? mk_si_dyn_cons : mkcl_cons);
mkcl_call_stack_check(env);
while (args[0].narg) {
*r = conser(env, mkcl_va_arg(args), mk_cl_Cnil);
r = &MKCL_CONS_CDR(*r);
}
return rest;
}
void
mkcl_parse_key(MKCL,
mkcl_va_list args, /* actual args */
int nkey, /* number of keywords */
mkcl_object *keys, /* keywords for the function */
mkcl_object *vars, /* where to put values (vars[0..nkey-1])
and suppliedp (vars[nkey..2*nkey-1]) */
mkcl_object *rest, /* if rest != NULL, where to collect rest values */
bool allow_other_keys, /* whether other key are allowed */
bool dynamic)
{
int i;
mkcl_object supplied_allow_other_keys = MKCL_OBJNULL;
mkcl_object unknown_keyword = MKCL_OBJNULL;
mkcl_object (*conser)(MKCL, mkcl_object, mkcl_object) = (dynamic ? mk_si_dyn_cons : mkcl_cons);
if (rest != NULL) *rest = mk_cl_Cnil;
for (i = 0; i < 2*nkey; i++)
vars[i] = mk_cl_Cnil; /* default values: NIL, supplied: NIL */
if (args[0].narg <= 0) return;
for (; args[0].narg > 1; ) {
mkcl_object keyword = mkcl_va_arg(args);
mkcl_object value = mkcl_va_arg(args);
if (!MKCL_SYMBOLP(keyword))
mkcl_FEprogram_error(env, "LAMBDA: Keyword expected, got ~S.", 1, keyword);
if (rest != NULL) {
rest = &MKCL_CONS_CDR(*rest = conser(env, keyword, mk_cl_Cnil));
rest = &MKCL_CONS_CDR(*rest = conser(env, value, mk_cl_Cnil));
}
for (i = 0; i < nkey; i++) {
if (keys[i] == keyword) {
if (vars[nkey+i] == mk_cl_Cnil) {
vars[i] = value;
vars[nkey+i] = mk_cl_Ct;
}
goto goon;
}
}
/* the key is a new one */
if (keyword == @':allow-other-keys') {
if (supplied_allow_other_keys == MKCL_OBJNULL)
supplied_allow_other_keys = value;
} else if (unknown_keyword == MKCL_OBJNULL)
unknown_keyword = keyword;
goon:;
}
if (args[0].narg != 0)
mkcl_FEprogram_error(env, "Odd number of keys", 0);
if (unknown_keyword != MKCL_OBJNULL && !allow_other_keys &&
(supplied_allow_other_keys == mk_cl_Cnil ||
supplied_allow_other_keys == MKCL_OBJNULL))
mkcl_FEprogram_error(env, "Unknown keyword ~S", 1, unknown_keyword);
}
static mkcl_object convert_cmp_lexical_info(MKCL, mkcl_object cmp_env)
{
mkcl_object lex_env = mk_cl_Cnil;
unsigned long i;
if (cmp_env != mk_cl_Cnil)
{
unsigned long nb_locations = cmp_env->cmp_dbg_lex.nb_locations;
const struct mkcl_lex_var_info * var_desc = cmp_env->cmp_dbg_lex.var_descriptors;
void * const * var_locs = cmp_env->cmp_dbg_lex.var_locations;
lex_env = convert_cmp_lexical_info(env, cmp_env->cmp_dbg_lex.parent);
for (i = 0; i < nb_locations; i++)
{
#if 0
mkcl_object var_name = mkcl_make_simple_base_string(env, (char *) var_desc[i].name);
#else
size_t var_name_len = strlen(var_desc[i].name);
mkcl_UTF_8_object_sized(var_name_obj, (char *) var_desc[i].name, var_name_len);
mkcl_object var_name = mkcl_utf_8_to_string(env, (mkcl_object) &var_name_obj);
#endif
mkcl_object var_value;
switch (var_desc[i].type)
{
case _mkcl_object_loc:
var_value = *((mkcl_object *) var_locs[i]);
break;
case _mkcl_word_loc:
var_value = MKCL_MAKE_FIXNUM(*((mkcl_word *) var_locs[i]));
break;
case _mkcl_base_char_loc:
var_value = MKCL_CODE_CHAR(*((mkcl_base_char *) var_locs[i]));
break;
case _mkcl_uni_char_loc:
var_value = MKCL_CODE_CHAR(*((mkcl_character *) var_locs[i]));
break;
case _mkcl_float_loc:
var_value = mkcl_make_singlefloat(env, *((float *) var_locs[i]));
break;
case _mkcl_double_loc:
var_value = mkcl_make_doublefloat(env, *((double *) var_locs[i]));
break;
case _mkcl_long_double_loc:
var_value = mkcl_make_longfloat(env, *((long double *) var_locs[i]));
break;
case _mkcl_closure_var_loc:
var_value = *((mkcl_object *) var_locs[i]);
break;
case _mkcl_float128_loc: /* not implemented yet. */
default:
mkcl_lose(env, "Invalid locative type");
break;
}
lex_env = MKCL_CONS(env, MKCL_CONS(env, var_name, var_value), lex_env);
}
}
return lex_env;
}
mkcl_object mk_si_convert_cmp_lexical_info(MKCL, mkcl_object cmp_env)
{
mkcl_call_stack_check(env);
if ( mkcl_type_of(cmp_env) != mkcl_t_cmp_dbg_lex_level )
{ mkcl_lose(env, "Invalid compiler debug information"); }
else
{
mkcl_object lex_env = convert_cmp_lexical_info(env, cmp_env);
@(return lex_env);
}
}