Remove "compiled closures" ("cclos") in favor of a simpler mechanism.
[bpt/guile.git] / libguile / stacks.c
CommitLineData
782d171c 1/* Representation of stack frame debug information
e20d7001 2 * Copyright (C) 1996,1997,2000,2001, 2006, 2007, 2008, 2009 Free Software Foundation
782d171c 3 *
73be1d9e
MV
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
782d171c 8 *
73be1d9e 9 * This library is distributed in the hope that it will be useful,
782d171c 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
782d171c 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
92205699 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
1bbd0b84 19
782d171c 20\f
dbb605f5
LC
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
782d171c 24
a0599745
MD
25#include "libguile/_scm.h"
26#include "libguile/eval.h"
27#include "libguile/debug.h"
28#include "libguile/continuations.h"
29#include "libguile/struct.h"
30#include "libguile/macros.h"
31#include "libguile/procprop.h"
32#include "libguile/modules.h"
33#include "libguile/root.h"
34#include "libguile/strings.h"
35
36#include "libguile/validate.h"
37#include "libguile/stacks.h"
22fc179a
HWN
38#include "libguile/private-options.h"
39
782d171c
MD
40
41\f
42/* {Frames and stacks}
43 *
44 * The debugging evaluator creates debug frames on the stack. These
45 * are linked from the innermost frame and outwards. The last frame
46 * created can always be accessed as SCM_LAST_DEBUG_FRAME.
47 * Continuations contain a pointer to the innermost debug frame on the
48 * continuation stack.
49 *
50 * Each debug frame contains a set of flags and information about one
51 * or more stack frames. The case of multiple frames occurs due to
52 * tail recursion. The maximal number of stack frames which can be
53 * recorded in one debug frame can be set dynamically with the debug
54 * option FRAMES.
55 *
56 * Stack frame information is of two types: eval information (the
57 * expression being evaluated and its environment) and apply
58 * information (the procedure being applied and its arguments). A
59 * stack frame normally corresponds to an eval/apply pair, but macros
60 * and special forms (which are implemented as macros in Guile) only
61 * have eval information and apply calls leads to apply only frames.
62 *
63 * Since we want to record the total stack information and later
64 * manipulate this data at the scheme level in the debugger, we need
65 * to transform it into a new representation. In the following code
66 * section you'll find the functions implementing this data type.
67 *
68 * Representation:
69 *
7115d1e4 70 * The stack is represented as a struct with an id slot and a tail
92c2555f 71 * array of scm_t_info_frame structs.
782d171c
MD
72 *
73 * A frame is represented as a pair where the car contains a stack and
74 * the cdr an inum. The inum is an index to the first SCM value of
92c2555f 75 * the scm_t_info_frame struct.
782d171c
MD
76 *
77 * Stacks
78 * Constructor
79 * make-stack
7115d1e4
MD
80 * Selectors
81 * stack-id
782d171c
MD
82 * stack-ref
83 * Inspector
84 * stack-length
85 *
86 * Frames
87 * Constructor
88 * last-stack-frame
89 * Selectors
90 * frame-number
91 * frame-source
92 * frame-procedure
93 * frame-arguments
94 * frame-previous
95 * frame-next
96 * Predicates
97 * frame-real?
98 * frame-procedure?
99 * frame-evaluating-args?
7115d1e4 100 * frame-overflow? */
782d171c
MD
101
102\f
103
104/* Some auxiliary functions for reading debug frames off the stack.
105 */
106
c0ab1b8d 107/* Stacks often contain pointers to other items on the stack; for
92c2555f 108 example, each scm_t_debug_frame structure contains a pointer to the
c0ab1b8d
JB
109 next frame out. When we capture a continuation, we copy the stack
110 into the heap, and just leave all the pointers unchanged. This
111 makes it simple to restore the continuation --- just copy the stack
112 back! However, if we retrieve a pointer from the heap copy to
113 another item that was originally on the stack, we have to add an
114 offset to the pointer to discover the new referent.
115
116 If PTR is a pointer retrieved from a continuation, whose original
117 target was on the stack, and OFFSET is the appropriate offset from
118 the original stack to the continuation, then RELOC_MUMBLE (PTR,
119 OFFSET) is a pointer to the copy in the continuation of the
120 original referent, cast to an scm_debug_MUMBLE *. */
121#define RELOC_INFO(ptr, offset) \
92c2555f 122 ((scm_t_debug_info *) ((SCM_STACKITEM *) (ptr) + (offset)))
c0ab1b8d 123#define RELOC_FRAME(ptr, offset) \
92c2555f 124 ((scm_t_debug_frame *) ((SCM_STACKITEM *) (ptr) + (offset)))
c0ab1b8d
JB
125
126
782d171c
MD
127/* Count number of debug info frames on a stack, beginning with
128 * DFRAME. OFFSET is used for relocation of pointers when the stack
129 * is read from a continuation.
130 */
92c2555f 131static scm_t_bits
7f12a943
MV
132stack_depth (scm_t_debug_frame *dframe, scm_t_ptrdiff offset,
133 SCM *id, int *maxp)
782d171c 134{
c014a02e
ML
135 long n;
136 long max_depth = SCM_BACKTRACE_MAXDEPTH;
782d171c 137 for (n = 0;
66f45472 138 dframe && !SCM_VOIDFRAMEP (*dframe) && n < max_depth;
c0ab1b8d 139 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
140 {
141 if (SCM_EVALFRAMEP (*dframe))
142 {
7f12a943
MV
143 scm_t_debug_info *info = RELOC_INFO (dframe->info, offset);
144 scm_t_debug_info *vect = RELOC_INFO (dframe->vect, offset);
145 n += (info - vect) / 2 + 1;
782d171c 146 /* Data in the apply part of an eval info frame comes from previous
92c2555f 147 stack frame if the scm_t_debug_info vector is overflowed. */
7f12a943 148 if ((((info - vect) & 1) == 0)
782d171c
MD
149 && SCM_OVERFLOWP (*dframe)
150 && !SCM_UNBNDP (info[1].a.proc))
151 ++n;
152 }
153 else
154 ++n;
155 }
66f45472 156 if (dframe && SCM_VOIDFRAMEP (*dframe))
7f12a943 157 *id = RELOC_INFO(dframe->vect, offset)[0].id;
66f45472 158 else if (dframe)
782d171c
MD
159 *maxp = 1;
160 return n;
161}
162
163/* Read debug info from DFRAME into IFRAME.
164 */
782d171c 165static void
7f12a943
MV
166read_frame (scm_t_debug_frame *dframe, scm_t_ptrdiff offset,
167 scm_t_info_frame *iframe)
782d171c 168{
92c2555f 169 scm_t_bits flags = SCM_UNPACK (SCM_INUM0); /* UGh. */
782d171c
MD
170 if (SCM_EVALFRAMEP (*dframe))
171 {
7f12a943
MV
172 scm_t_debug_info *info = RELOC_INFO (dframe->info, offset);
173 scm_t_debug_info *vect = RELOC_INFO (dframe->vect, offset);
174 if ((info - vect) & 1)
782d171c
MD
175 {
176 /* Debug.vect ends with apply info. */
177 --info;
54778cd3 178 if (!SCM_UNBNDP (info[1].a.proc))
782d171c
MD
179 {
180 flags |= SCM_FRAMEF_PROC;
181 iframe->proc = info[1].a.proc;
182 iframe->args = info[1].a.args;
183 if (!SCM_ARGS_READY_P (*dframe))
184 flags |= SCM_FRAMEF_EVAL_ARGS;
185 }
186 }
6629eb1c 187 iframe->source = scm_make_memoized (info[0].e.exp, info[0].e.env);
782d171c
MD
188 }
189 else
190 {
7f12a943 191 scm_t_debug_info *vect = RELOC_INFO (dframe->vect, offset);
782d171c 192 flags |= SCM_FRAMEF_PROC;
7f12a943
MV
193 iframe->proc = vect[0].a.proc;
194 iframe->args = vect[0].a.args;
782d171c
MD
195 }
196 iframe->flags = flags;
197}
198
7a13c3ae
MD
199/* Look up the first body form of the apply closure. We'll use this
200 below to prevent it from being displayed.
201*/
202static SCM
203get_applybody ()
204{
86d31dfe
MV
205 SCM var = scm_sym2var (scm_sym_apply, SCM_BOOL_F, SCM_BOOL_F);
206 if (SCM_VARIABLEP (var) && SCM_CLOSUREP (SCM_VARIABLE_REF (var)))
f9450cdb 207 return SCM_CAR (SCM_CLOSURE_BODY (SCM_VARIABLE_REF (var)));
7a13c3ae
MD
208 else
209 return SCM_UNDEFINED;
210}
7115d1e4
MD
211
212#define NEXT_FRAME(iframe, n, quit) \
d3a6bc94 213do { \
13dcb666 214 if (SCM_MEMOIZEDP (iframe->source) \
bc36d050 215 && scm_is_eq (SCM_MEMOIZED_EXP (iframe->source), applybody)) \
7a13c3ae
MD
216 { \
217 iframe->source = SCM_BOOL_F; \
7888309b 218 if (scm_is_false (iframe->proc)) \
7a13c3ae
MD
219 { \
220 --iframe; \
221 ++n; \
222 } \
223 } \
7115d1e4
MD
224 ++iframe; \
225 if (--n == 0) \
226 goto quit; \
d3a6bc94 227} while (0)
7115d1e4
MD
228
229
92c2555f 230/* Fill the scm_t_info_frame vector IFRAME with data from N stack frames
7a13c3ae
MD
231 * starting with the first stack frame represented by debug frame
232 * DFRAME.
233 */
234
92c2555f 235static scm_t_bits
7f12a943
MV
236read_frames (scm_t_debug_frame *dframe, scm_t_ptrdiff offset,
237 long n, scm_t_info_frame *iframes)
782d171c 238{
92c2555f 239 scm_t_info_frame *iframe = iframes;
7f12a943 240 scm_t_debug_info *info, *vect;
7a13c3ae 241 static SCM applybody = SCM_UNDEFINED;
782d171c 242
7a13c3ae
MD
243 /* The value of applybody has to be setup after r4rs.scm has executed. */
244 if (SCM_UNBNDP (applybody))
245 applybody = get_applybody ();
782d171c 246 for (;
66f45472 247 dframe && !SCM_VOIDFRAMEP (*dframe) && n > 0;
c0ab1b8d 248 dframe = RELOC_FRAME (dframe->prev, offset))
782d171c
MD
249 {
250 read_frame (dframe, offset, iframe);
251 if (SCM_EVALFRAMEP (*dframe))
252 {
6629eb1c
MD
253 /* If current frame is a macro during expansion, we should
254 skip the previously recorded macro transformer
255 application frame. */
256 if (SCM_MACROEXPP (*dframe) && iframe > iframes)
7c939801
MD
257 {
258 *(iframe - 1) = *iframe;
259 --iframe;
260 }
c0ab1b8d 261 info = RELOC_INFO (dframe->info, offset);
7f12a943
MV
262 vect = RELOC_INFO (dframe->vect, offset);
263 if ((info - vect) & 1)
782d171c
MD
264 --info;
265 /* Data in the apply part of an eval info frame comes from
13dcb666
DH
266 previous stack frame if the scm_t_debug_info vector is
267 overflowed. */
782d171c
MD
268 else if (SCM_OVERFLOWP (*dframe)
269 && !SCM_UNBNDP (info[1].a.proc))
270 {
7115d1e4 271 NEXT_FRAME (iframe, n, quit);
f1267706 272 iframe->flags = SCM_UNPACK(SCM_INUM0) | SCM_FRAMEF_PROC;
782d171c
MD
273 iframe->proc = info[1].a.proc;
274 iframe->args = info[1].a.args;
275 }
276 if (SCM_OVERFLOWP (*dframe))
277 iframe->flags |= SCM_FRAMEF_OVERFLOW;
278 info -= 2;
7115d1e4 279 NEXT_FRAME (iframe, n, quit);
7f12a943 280 while (info >= vect)
782d171c
MD
281 {
282 if (!SCM_UNBNDP (info[1].a.proc))
283 {
f1267706 284 iframe->flags = SCM_UNPACK(SCM_INUM0) | SCM_FRAMEF_PROC;
782d171c
MD
285 iframe->proc = info[1].a.proc;
286 iframe->args = info[1].a.args;
287 }
288 else
f1267706 289 iframe->flags = SCM_UNPACK (SCM_INUM0);
782d171c
MD
290 iframe->source = scm_make_memoized (info[0].e.exp,
291 info[0].e.env);
292 info -= 2;
7115d1e4 293 NEXT_FRAME (iframe, n, quit);
782d171c
MD
294 }
295 }
296 else
297 {
7115d1e4 298 NEXT_FRAME (iframe, n, quit);
782d171c
MD
299 }
300 quit:
301 if (iframe > iframes)
302 (iframe - 1) -> flags |= SCM_FRAMEF_REAL;
303 }
7c939801 304 return iframe - iframes; /* Number of frames actually read */
782d171c
MD
305}
306
c3a6c6f9
MD
307/* Narrow STACK by cutting away stackframes (mutatingly).
308 *
309 * Inner frames (most recent) are cut by advancing the frames pointer.
310 * Outer frames are cut by decreasing the recorded length.
311 *
312 * Cut maximally INNER inner frames and OUTER outer frames using
313 * the keys INNER_KEY and OUTER_KEY.
314 *
315 * Frames are cut away starting at the end points and moving towards
316 * the center of the stack. The key is normally compared to the
317 * operator in application frames. Frames up to and including the key
318 * are cut.
319 *
320 * If INNER_KEY is #t a different scheme is used for inner frames:
321 *
322 * Frames up to but excluding the first source frame originating from
323 * a user module are cut, except for possible application frames
324 * between the user frame and the last system frame previously
325 * encountered.
326 */
327
7115d1e4 328static void
34d19ef6 329narrow_stack (SCM stack, long inner, SCM inner_key, long outer, SCM outer_key)
7115d1e4 330{
92c2555f 331 scm_t_stack *s = SCM_STACK (stack);
13dcb666 332 unsigned long int i;
c014a02e 333 long n = s->length;
7115d1e4
MD
334
335 /* Cut inner part. */
bc36d050 336 if (scm_is_eq (inner_key, SCM_BOOL_T))
c3a6c6f9 337 {
13dcb666 338 /* Cut all frames up to user module code */
c3a6c6f9
MD
339 for (i = 0; inner; ++i, --inner)
340 {
341 SCM m = s->frames[i].source;
13dcb666
DH
342 if (SCM_MEMOIZEDP (m)
343 && !SCM_IMP (SCM_MEMOIZED_ENV (m))
7888309b 344 && scm_is_false (scm_system_module_env_p (SCM_MEMOIZED_ENV (m))))
c3a6c6f9
MD
345 {
346 /* Back up in order to include any non-source frames */
13dcb666 347 while (i > 0)
c3a6c6f9 348 {
13dcb666
DH
349 m = s->frames[i - 1].source;
350 if (SCM_MEMOIZEDP (m))
351 break;
352
353 m = s->frames[i - 1].proc;
7888309b
MV
354 if (scm_is_true (scm_procedure_p (m))
355 && scm_is_true (scm_procedure_property
13dcb666
DH
356 (m, scm_sym_system_procedure)))
357 break;
358
c3a6c6f9
MD
359 --i;
360 ++inner;
361 }
362 break;
363 }
364 }
365 }
366 else
367 /* Use standard cutting procedure. */
368 {
369 for (i = 0; inner; --inner)
bc36d050 370 if (scm_is_eq (s->frames[i++].proc, inner_key))
c3a6c6f9
MD
371 break;
372 }
7115d1e4
MD
373 s->frames = &s->frames[i];
374 n -= i;
375
376 /* Cut outer part. */
377 for (; n && outer; --outer)
bc36d050 378 if (scm_is_eq (s->frames[--n].proc, outer_key))
7115d1e4
MD
379 break;
380
381 s->length = n;
382}
383
782d171c
MD
384\f
385
386/* Stacks
387 */
388
762e289a 389SCM scm_stack_type;
66f45472 390
a1ec6916 391SCM_DEFINE (scm_stack_p, "stack?", 1, 0, 0,
1bbd0b84 392 (SCM obj),
b380b885 393 "Return @code{#t} if @var{obj} is a calling stack.")
1bbd0b84 394#define FUNC_NAME s_scm_stack_p
66f45472 395{
7888309b 396 return scm_from_bool(SCM_STACKP (obj));
66f45472 397}
1bbd0b84 398#undef FUNC_NAME
66f45472 399
af45e3b0
DH
400SCM_DEFINE (scm_make_stack, "make-stack", 1, 0, 1,
401 (SCM obj, SCM args),
67941e3c
MG
402 "Create a new stack. If @var{obj} is @code{#t}, the current\n"
403 "evaluation stack is used for creating the stack frames,\n"
404 "otherwise the frames are taken from @var{obj} (which must be\n"
baffb19f
NJ
405 "either a debug object or a continuation).\n\n"
406 "@var{args} should be a list containing any combination of\n"
407 "integer, procedure and @code{#t} values.\n\n"
408 "These values specify various ways of cutting away uninteresting\n"
409 "stack frames from the top and bottom of the stack that\n"
410 "@code{make-stack} returns. They come in pairs like this:\n"
411 "@code{(@var{inner_cut_1} @var{outer_cut_1} @var{inner_cut_2}\n"
412 "@var{outer_cut_2} @dots{})}.\n\n"
413 "Each @var{inner_cut_N} can be @code{#t}, an integer, or a\n"
414 "procedure. @code{#t} means to cut away all frames up to but\n"
415 "excluding the first user module frame. An integer means to cut\n"
416 "away exactly that number of frames. A procedure means to cut\n"
417 "away all frames up to but excluding the application frame whose\n"
418 "procedure matches the specified one.\n\n"
419 "Each @var{outer_cut_N} can be an integer or a procedure. An\n"
420 "integer means to cut away that number of frames. A procedure\n"
421 "means to cut away frames down to but excluding the application\n"
422 "frame whose procedure matches the specified one.\n\n"
423 "If the @var{outer_cut_N} of the last pair is missing, it is\n"
424 "taken as 0.")
1bbd0b84 425#define FUNC_NAME s_scm_make_stack
782d171c 426{
c014a02e 427 long n, size;
1be6b49c 428 int maxp;
13dcb666 429 scm_t_debug_frame *dframe;
92c2555f 430 scm_t_info_frame *iframe;
c014a02e 431 long offset = 0;
66f45472 432 SCM stack, id;
af45e3b0 433 SCM inner_cut, outer_cut;
f6f88e0d
MD
434
435 /* Extract a pointer to the innermost frame of whatever object
436 scm_make_stack was given. */
bc36d050 437 if (scm_is_eq (obj, SCM_BOOL_T))
782d171c 438 {
9de87eea 439 dframe = scm_i_last_debug_frame ();
13dcb666
DH
440 }
441 else if (SCM_DEBUGOBJP (obj))
442 {
443 dframe = SCM_DEBUGOBJ_FRAME (obj);
444 }
445 else if (SCM_CONTINUATIONP (obj))
446 {
7f12a943
MV
447 scm_t_contregs *cont = SCM_CONTREGS (obj);
448 offset = cont->offset;
449 dframe = RELOC_FRAME (cont->dframe, offset);
13dcb666
DH
450 }
451 else
452 {
453 SCM_WRONG_TYPE_ARG (SCM_ARG1, obj);
454 /* not reached */
782d171c
MD
455 }
456
f6f88e0d
MD
457 /* Count number of frames. Also get stack id tag and check whether
458 there are more stackframes than we want to record
459 (SCM_BACKTRACE_MAXDEPTH). */
66f45472
MD
460 id = SCM_BOOL_F;
461 maxp = 0;
7115d1e4 462 n = stack_depth (dframe, offset, &id, &maxp);
782d171c
MD
463 size = n * SCM_FRAME_N_SLOTS;
464
f6f88e0d 465 /* Make the stack object. */
e11e83f3 466 stack = scm_make_struct (scm_stack_type, scm_from_long (size), SCM_EOL);
66f45472 467 SCM_STACK (stack) -> id = id;
7115d1e4
MD
468 iframe = &SCM_STACK (stack) -> tail[0];
469 SCM_STACK (stack) -> frames = iframe;
7115d1e4 470
f6f88e0d 471 /* Translate the current chain of stack frames into debugging information. */
7f12a943 472 n = read_frames (dframe, offset, n, iframe);
7c939801 473 SCM_STACK (stack) -> length = n;
7115d1e4 474
f6f88e0d 475 /* Narrow the stack according to the arguments given to scm_make_stack. */
af45e3b0 476 SCM_VALIDATE_REST_ARGUMENT (args);
d2e53ed6 477 while (n > 0 && !scm_is_null (args))
f6f88e0d
MD
478 {
479 inner_cut = SCM_CAR (args);
480 args = SCM_CDR (args);
d2e53ed6 481 if (scm_is_null (args))
af45e3b0 482 {
13dcb666 483 outer_cut = SCM_INUM0;
af45e3b0
DH
484 }
485 else
f6f88e0d
MD
486 {
487 outer_cut = SCM_CAR (args);
488 args = SCM_CDR (args);
489 }
f6f88e0d
MD
490
491 narrow_stack (stack,
e11e83f3
MV
492 scm_is_integer (inner_cut) ? scm_to_int (inner_cut) : n,
493 scm_is_integer (inner_cut) ? 0 : inner_cut,
494 scm_is_integer (outer_cut) ? scm_to_int (outer_cut) : n,
495 scm_is_integer (outer_cut) ? 0 : outer_cut);
f6f88e0d
MD
496
497 n = SCM_STACK (stack) -> length;
498 }
499
7115d1e4 500 if (n > 0)
f6f88e0d
MD
501 {
502 if (maxp)
503 iframe[n - 1].flags |= SCM_FRAMEF_OVERFLOW;
504 return stack;
505 }
7115d1e4
MD
506 else
507 return SCM_BOOL_F;
782d171c 508}
1bbd0b84 509#undef FUNC_NAME
782d171c 510
a1ec6916 511SCM_DEFINE (scm_stack_id, "stack-id", 1, 0, 0,
1bbd0b84 512 (SCM stack),
b380b885 513 "Return the identifier given to @var{stack} by @code{start-stack}.")
1bbd0b84 514#define FUNC_NAME s_scm_stack_id
66f45472 515{
92c2555f 516 scm_t_debug_frame *dframe;
c014a02e 517 long offset = 0;
bc36d050 518 if (scm_is_eq (stack, SCM_BOOL_T))
7115d1e4 519 {
9de87eea 520 dframe = scm_i_last_debug_frame ();
13dcb666
DH
521 }
522 else if (SCM_DEBUGOBJP (stack))
523 {
524 dframe = SCM_DEBUGOBJ_FRAME (stack);
525 }
526 else if (SCM_CONTINUATIONP (stack))
527 {
7f12a943
MV
528 scm_t_contregs *cont = SCM_CONTREGS (stack);
529 offset = cont->offset;
530 dframe = RELOC_FRAME (cont->dframe, offset);
13dcb666
DH
531 }
532 else if (SCM_STACKP (stack))
533 {
534 return SCM_STACK (stack) -> id;
7115d1e4 535 }
13dcb666
DH
536 else
537 {
538 SCM_WRONG_TYPE_ARG (1, stack);
539 }
540
7115d1e4 541 while (dframe && !SCM_VOIDFRAMEP (*dframe))
c0ab1b8d 542 dframe = RELOC_FRAME (dframe->prev, offset);
7115d1e4 543 if (dframe && SCM_VOIDFRAMEP (*dframe))
7f12a943 544 return RELOC_INFO (dframe->vect, offset)[0].id;
7115d1e4 545 return SCM_BOOL_F;
66f45472 546}
1bbd0b84 547#undef FUNC_NAME
66f45472 548
a1ec6916 549SCM_DEFINE (scm_stack_ref, "stack-ref", 2, 0, 0,
13dcb666
DH
550 (SCM stack, SCM index),
551 "Return the @var{index}'th frame from @var{stack}.")
1bbd0b84 552#define FUNC_NAME s_scm_stack_ref
782d171c 553{
13dcb666
DH
554 unsigned long int c_index;
555
556 SCM_VALIDATE_STACK (1, stack);
a55c2b68 557 c_index = scm_to_unsigned_integer (index, 0, SCM_STACK_LENGTH(stack)-1);
13dcb666 558 return scm_cons (stack, index);
782d171c 559}
1bbd0b84 560#undef FUNC_NAME
782d171c 561
3b3b36dd 562SCM_DEFINE (scm_stack_length, "stack-length", 1, 0, 0,
67941e3c
MG
563 (SCM stack),
564 "Return the length of @var{stack}.")
1bbd0b84 565#define FUNC_NAME s_scm_stack_length
782d171c 566{
34d19ef6 567 SCM_VALIDATE_STACK (1, stack);
e11e83f3 568 return scm_from_int (SCM_STACK_LENGTH (stack));
782d171c 569}
1bbd0b84 570#undef FUNC_NAME
782d171c
MD
571
572/* Frames
573 */
574
a1ec6916 575SCM_DEFINE (scm_frame_p, "frame?", 1, 0, 0,
1bbd0b84 576 (SCM obj),
67941e3c 577 "Return @code{#t} if @var{obj} is a stack frame.")
1bbd0b84 578#define FUNC_NAME s_scm_frame_p
66f45472 579{
7888309b 580 return scm_from_bool(SCM_FRAMEP (obj));
66f45472 581}
1bbd0b84 582#undef FUNC_NAME
66f45472 583
3b3b36dd 584SCM_DEFINE (scm_last_stack_frame, "last-stack-frame", 1, 0, 0,
67941e3c 585 (SCM obj),
b0b0deff
NJ
586 "Return the last (innermost) frame of @var{obj}, which must be\n"
587 "either a debug object or a continuation.")
1bbd0b84 588#define FUNC_NAME s_scm_last_stack_frame
782d171c 589{
92c2555f 590 scm_t_debug_frame *dframe;
c014a02e 591 long offset = 0;
7115d1e4 592 SCM stack;
782d171c 593
782d171c 594 if (SCM_DEBUGOBJP (obj))
13dcb666
DH
595 {
596 dframe = SCM_DEBUGOBJ_FRAME (obj);
597 }
5f144b10 598 else if (SCM_CONTINUATIONP (obj))
782d171c 599 {
7f12a943
MV
600 scm_t_contregs *cont = SCM_CONTREGS (obj);
601 offset = cont->offset;
602 dframe = RELOC_FRAME (cont->dframe, offset);
782d171c 603 }
3323ad08
JB
604 else
605 {
276dd677
DH
606 SCM_WRONG_TYPE_ARG (1, obj);
607 /* not reached */
3323ad08 608 }
782d171c 609
66f45472 610 if (!dframe || SCM_VOIDFRAMEP (*dframe))
782d171c
MD
611 return SCM_BOOL_F;
612
e11e83f3 613 stack = scm_make_struct (scm_stack_type, scm_from_int (SCM_FRAME_N_SLOTS),
c0ab1b8d 614 SCM_EOL);
7115d1e4
MD
615 SCM_STACK (stack) -> length = 1;
616 SCM_STACK (stack) -> frames = &SCM_STACK (stack) -> tail[0];
c0ab1b8d 617 read_frame (dframe, offset,
92c2555f 618 (scm_t_info_frame *) &SCM_STACK (stack) -> frames[0]);
782d171c 619
13dcb666 620 return scm_cons (stack, SCM_INUM0);
782d171c 621}
1bbd0b84 622#undef FUNC_NAME
782d171c 623
3b3b36dd 624SCM_DEFINE (scm_frame_number, "frame-number", 1, 0, 0,
67941e3c
MG
625 (SCM frame),
626 "Return the frame number of @var{frame}.")
1bbd0b84 627#define FUNC_NAME s_scm_frame_number
782d171c 628{
34d19ef6 629 SCM_VALIDATE_FRAME (1, frame);
e11e83f3 630 return scm_from_int (SCM_FRAME_NUMBER (frame));
782d171c 631}
1bbd0b84 632#undef FUNC_NAME
782d171c 633
3b3b36dd 634SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
67941e3c
MG
635 (SCM frame),
636 "Return the source of @var{frame}.")
1bbd0b84 637#define FUNC_NAME s_scm_frame_source
782d171c 638{
34d19ef6 639 SCM_VALIDATE_FRAME (1, frame);
782d171c
MD
640 return SCM_FRAME_SOURCE (frame);
641}
1bbd0b84 642#undef FUNC_NAME
782d171c 643
3b3b36dd 644SCM_DEFINE (scm_frame_procedure, "frame-procedure", 1, 0, 0,
67941e3c
MG
645 (SCM frame),
646 "Return the procedure for @var{frame}, or @code{#f} if no\n"
647 "procedure is associated with @var{frame}.")
1bbd0b84 648#define FUNC_NAME s_scm_frame_procedure
782d171c 649{
34d19ef6 650 SCM_VALIDATE_FRAME (1, frame);
782d171c 651 return (SCM_FRAME_PROC_P (frame)
afa92d19
TP
652 ? SCM_FRAME_PROC (frame)
653 : SCM_BOOL_F);
782d171c 654}
1bbd0b84 655#undef FUNC_NAME
782d171c 656
3b3b36dd 657SCM_DEFINE (scm_frame_arguments, "frame-arguments", 1, 0, 0,
67941e3c
MG
658 (SCM frame),
659 "Return the arguments of @var{frame}.")
1bbd0b84 660#define FUNC_NAME s_scm_frame_arguments
782d171c 661{
34d19ef6 662 SCM_VALIDATE_FRAME (1, frame);
782d171c
MD
663 return SCM_FRAME_ARGS (frame);
664}
1bbd0b84 665#undef FUNC_NAME
782d171c 666
3b3b36dd 667SCM_DEFINE (scm_frame_previous, "frame-previous", 1, 0, 0,
67941e3c
MG
668 (SCM frame),
669 "Return the previous frame of @var{frame}, or @code{#f} if\n"
670 "@var{frame} is the first frame in its stack.")
1bbd0b84 671#define FUNC_NAME s_scm_frame_previous
782d171c 672{
13dcb666
DH
673 unsigned long int n;
674 SCM_VALIDATE_FRAME (1, frame);
e11e83f3 675 n = scm_to_ulong (SCM_CDR (frame)) + 1;
782d171c
MD
676 if (n >= SCM_STACK_LENGTH (SCM_CAR (frame)))
677 return SCM_BOOL_F;
678 else
e11e83f3 679 return scm_cons (SCM_CAR (frame), scm_from_ulong (n));
782d171c 680}
1bbd0b84 681#undef FUNC_NAME
782d171c 682
3b3b36dd 683SCM_DEFINE (scm_frame_next, "frame-next", 1, 0, 0,
1bbd0b84 684 (SCM frame),
67941e3c
MG
685 "Return the next frame of @var{frame}, or @code{#f} if\n"
686 "@var{frame} is the last frame in its stack.")
1bbd0b84 687#define FUNC_NAME s_scm_frame_next
782d171c 688{
13dcb666
DH
689 unsigned long int n;
690 SCM_VALIDATE_FRAME (1, frame);
e11e83f3 691 n = scm_to_ulong (SCM_CDR (frame));
13dcb666 692 if (n == 0)
782d171c
MD
693 return SCM_BOOL_F;
694 else
e11e83f3 695 return scm_cons (SCM_CAR (frame), scm_from_ulong (n - 1));
782d171c 696}
1bbd0b84 697#undef FUNC_NAME
782d171c 698
3b3b36dd 699SCM_DEFINE (scm_frame_real_p, "frame-real?", 1, 0, 0,
67941e3c
MG
700 (SCM frame),
701 "Return @code{#t} if @var{frame} is a real frame.")
1bbd0b84 702#define FUNC_NAME s_scm_frame_real_p
782d171c 703{
34d19ef6 704 SCM_VALIDATE_FRAME (1, frame);
7888309b 705 return scm_from_bool(SCM_FRAME_REAL_P (frame));
782d171c 706}
1bbd0b84 707#undef FUNC_NAME
782d171c 708
3b3b36dd 709SCM_DEFINE (scm_frame_procedure_p, "frame-procedure?", 1, 0, 0,
67941e3c
MG
710 (SCM frame),
711 "Return @code{#t} if a procedure is associated with @var{frame}.")
1bbd0b84 712#define FUNC_NAME s_scm_frame_procedure_p
782d171c 713{
34d19ef6 714 SCM_VALIDATE_FRAME (1, frame);
7888309b 715 return scm_from_bool(SCM_FRAME_PROC_P (frame));
782d171c 716}
1bbd0b84 717#undef FUNC_NAME
782d171c 718
3b3b36dd 719SCM_DEFINE (scm_frame_evaluating_args_p, "frame-evaluating-args?", 1, 0, 0,
67941e3c
MG
720 (SCM frame),
721 "Return @code{#t} if @var{frame} contains evaluated arguments.")
1bbd0b84 722#define FUNC_NAME s_scm_frame_evaluating_args_p
782d171c 723{
34d19ef6 724 SCM_VALIDATE_FRAME (1, frame);
7888309b 725 return scm_from_bool(SCM_FRAME_EVAL_ARGS_P (frame));
782d171c 726}
1bbd0b84 727#undef FUNC_NAME
782d171c 728
3b3b36dd 729SCM_DEFINE (scm_frame_overflow_p, "frame-overflow?", 1, 0, 0,
67941e3c
MG
730 (SCM frame),
731 "Return @code{#t} if @var{frame} is an overflow frame.")
1bbd0b84 732#define FUNC_NAME s_scm_frame_overflow_p
782d171c 733{
34d19ef6 734 SCM_VALIDATE_FRAME (1, frame);
7888309b 735 return scm_from_bool(SCM_FRAME_OVERFLOW_P (frame));
782d171c 736}
1bbd0b84 737#undef FUNC_NAME
782d171c
MD
738
739\f
740
741void
742scm_init_stacks ()
743{
b3aa4626
KR
744 scm_stack_type =
745 scm_permanent_object
746 (scm_make_vtable (scm_from_locale_string (SCM_STACK_LAYOUT),
747 SCM_UNDEFINED));
cc95e00a
MV
748 scm_set_struct_vtable_name_x (scm_stack_type,
749 scm_from_locale_symbol ("stack"));
a0599745 750#include "libguile/stacks.x"
782d171c 751}
89e00824
ML
752
753/*
754 Local Variables:
755 c-file-style: "gnu"
756 End:
757*/