| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
4.1 ECL stacks 4.2 Procedure Call Conventions 4.3 The lexical environment 4.4 The interpreter stack
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
ECL uses the following stacks:
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
NValues
to the number of Lisp values produced, it returns the first one and the
remaining ones are kept in a global (per thread) array (VALUES).
To show the argument/value passing mechanism, here we list the actual code for the Common-Lisp
clLcons(int narg, object car, object cdr)
{ object x;
check_arg(2);
x = alloc_object(t_cons);
CAR(x) = car;
CDR(x) = cdr;
NValues = 1;
return x;
}
|
ECL adopts the convention that the name of a function that implements a
Common-Lisp
si for SYSTEM, etc), followed by L, and followed by the name of
the Common-Lisp
Common-Lisp
to obey the syntax of C.)
check_arg(2) in the code of clLcons checks that exactly two
arguments are supplied to cons. That is, it checks that narg is
2, and otherwise, it causes an error. allocate_object(t_cons) allocates
a cons cell in the heap and returns the pointer to the cell. After the
CAR and the CDR fields of the cell are set, the cell pointer is
returned directly. The number assigned to NValues set by the function (1 in
this case) represents the number of values of the function.
In general, if one is to play with the C kernel of ECL there is no need to
know about all these conventions. There is a preprocessor that takes care of
the details, by using a lisp representation of the statements that output
values, and of the function definitions. For instance, the actual source code
for clLcons in `src/c/lists.d'
@(defun cons (car cdr)
@
@(return CONS(car, cdr))
@)
|
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The ECL interpreter uses two A-lists (Association lists) to represent lexical environments.
When a function closure is created, the current two A-lists are saved in the closure along with the lambda expression. Later, when the closure is invoked, the saved A-lists are used to recover the lexical environment.
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
However, one of the most important roles of the Interpreter Stack is to keep a log of the functions which are called during the execution of bytecodes. For each function invoked, the interpreter keeps three lisp objects on the stack:
+----------+------------------------------------------------+ | function | lexical environment | index to previous record | +----------+---------------------+--------------------------+ |
The first item is the object which is funcalled. It can be a bytecodes object, a compiled function or a generic function. In the last two cases the lexical environment is just NIL. In the first case, the second item on the stack is the lexical environment on which the code is executed. Each of these records are popped out of the stack after function invocation.
Let us see how these invocation records are used for debugging.
>(defun fact (x) ;;; Wrong definition of the
(if (= x 0) ;;; factorial function.
one ;;; one should be 1.
(* x (fact (1- x)))))
FACT
>(fact 3) ;;; Tries 3!
Error: The variable ONE is unbound.
Error signalled by IF.
Broken at IF.
>>:b ;;; Backtrace.
Backtrace: eval > fact > if > fact > if > fact > if > fact > IF
;;; Currently at the last IF.
>>:h ;;; Help.
Break commands:
:q(uit) Return to some previous break level.
:pop Pop to previous break level.
:c(ontinue) Continue execution.
:b(acktrace) Print backtrace.
:f(unction) Show current function.
:p(revious) Go to previous function.
:n(ext) Go to next function.
:g(o) Go to next function.
:fs Search forward for function.
:bs Search backward for function.
:v(ariables) Show local variables, functions, blocks, and tags.
:l(ocal) Return the nth local value on the stack.
:hide Hide function.
:unhide Unhide function.
:hp Hide package.
:unhp Unhide package.
:unhide-all Unhide all variables and packages.
:bds Show binding stack.
:m(essage) Show error message.
:hs Help stack.
Top level commands:
:cf Compile file.
:exit or ^D Exit Lisp.
:ld Load file.
:step Single step form.
:tr(ace) Trace function.
:untr(ace) Untrace function.
Help commands:
:apropos Apropos.
:doc(ument) Document.
:h(elp) or ? Help. Type ":help help" for more information.
>>:p ;;; Move to the last call of FACT.
Broken at IF.
>>:b
Backtrace: eval > fact > if > fact > if > fact > if > FACT > if
;;; Now at the last FACT.
>>:v ;;; The environment at the last call
Local variables: ;;; to FACT is recovered.
X: 0 ;;; X is the only bound variable.
Block names: FACT. ;;; The block FACT is established.
>>x
0 ;;; The value of x is 0.
>>(return-from fact 1) ;;; Return from the last call of
6 ;;; FACT with the value of 0.
;;; The execution is resumed and
> ;;; the value 6 is returned.
;;; Again at the top-level loop.
|
| [ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |