0

I'm (still) porting code from Franz Lisp to Common LISP. Now I seem to have pushed the interpreter into a strange corner where it blows up.

[11]> (setq fff (cadr contextstack))    
*** - Program stack overflow. RESET

Now how can that cause a stack overflow? Where's the recursion?

I can take the length OK:

[12]> (length contextstack)
79

describe works. This is just the beginning of long "describe" output.

[13]> (describe (cadr contextstack))

(# . #1=#) is a cons.

 #<FUNCTION POPPATTERN (NODE) (DECLARE (SYSTEM::IN-DEFUN POPPATTERN)) (BLOCK POPPATTERN (MAPONE # #) (XEPATTERN NODE #))> is an interpreted
 function.
 Argument list: (NODE)

 #1=# is a structure of type ENODE.
 Slots:
   EROOT           =
  #1=#S(ENODE :EROOT #1# :EQCLASS #1# :ESUCCESSORS ALLTRUE! :ESLENGTH NIL :EPREDECESSORS NIL :ECONGRUENT NIL :EDEMON NIL :EMERGEDEMON NIL
        :EPATTERN

;;; much more

But almost anything else applied to contextstack blows up with the stack overflow message.

The structure ENODE contains links to other ENODE items, and there is circularity which could make some code loop. But cadr? How is that even possible?

The original code used "hunks", a MacLISP feature from the 1970s. I converted it to use Common LISP structs, and may have broken something.

This is all running interpretive; I haven't compiled anything. Safety level is the default. I tried adding (proclaim '(optimize (safety 3))) to force more checking, but it didn't change anything.

If you want to reproduce this, download the code in

https://github.com/John-Nagle/pasv/tree/master/src/CPC4

start "clisp", do (load 'setup), and then start looking at contextstack. Whatever is breaking is happening early, as the program is initializing.

0

1 Answer 1

1

How you got the error

Chances are, the error is in printing, not cadr. You can verify it by doing

(progn (cadr contextstack) nil)

which should work just fine.

If it still blows up, you should check if cadr raises an exception (and then the error message would contain a circular object and blow up):

(and (consp contextstack)
     (consp (cdr contextstack)))

How to avoid the error

CLISP FAQ says:

You will always get a stack overflow when you try to print a circular object (LIST, STRUCTURE-OBJECT, VECTOR etc) and *PRINT-CIRCLE* is NIL. Just set *PRINT-CIRCLE* to T.

Note that this is not CLISP-specific, you should get the same error with any ANSI Common Lisp when *print-circle* is nil.

In your specific case, look closely at the output of (describe (cadr contextstack)):

(# . #1=#) is a cons.

This #= notation is used by the printer to avoid stack overflows when printing circular objects.

PS. You now owe me 10 zorkmids :-)

Sign up to request clarification or add additional context in comments.

3 Comments

Right. What's happening is that "cadr" is being applied to a non-list, which triggers an error message, which tries to print a circular list, which blows the stack.
@JohnNagle: this actually can be construed as a bug in CLISP: error reporting should just work.
It's sort of a bug. The built-in pretty printer is triggered by a break, goes into a recursive loop, and doesn't print anything. Then it hits the stack limit and the entire stack is discarded. So there's no indication of what the problem is and the stack has been lost. If it printed something while descending the data structure, or had a length limit by default when triggered by a break, it would be clear what's going on. That's poor default behavior. But the last release of clisp was in 2010, so submitting bug reports is kind of pointless now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.