[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

AAAARRRRRrrrggggghhhhhhh!!!!!!!



CC: (BUG LISP) at MIT-AI, GLS at MIT-AI, GJS at MIT-AI, nil at MIT-MC

In system 29.95 NWS, with microcode 669, on LISP Machine Eight:

RETURN-FROM is incorrectly implemented, I claim.
Consider this piece of code:

(DEFUN FOO ()
  (PROG ()
	(PRINT 'A)
	(PROG T ()
	      (PRINT 'B)
	      (RETURN-FROM T (PROGN (PRINT 'C) (RETURN)))
	      (PRINT 'D))
	(PRINT 'E)))

The LISP Machine Manual claims that a PROG with name T is
invisible to the RETURN function, and can be returned from
only with RETURN-FROM T.  Therefore, I would expect FOO to
print the symbols A, B, and C, and then return from the
outer PROG.  However, it prints A, B, C, and E!  Evidently
the fact that RETURN occurs within an argument to RETURN-FROM T
causes it to exit the inner PROG, not the outer.

This is an **enormous** screw, and wasted over an hour of my time.
I have a macro, which I believe is written according to the approved
stype, using PROG T:

(defmacro select! (item . clauses)
  `(prog t (%%item%%)
	 (setq %%item%% ,item)
      retry-select!
	 (select %%item%%
	   ,@(forlist (clause clauses)
	       `(,(car clause) (return-from t (progn ,@(cdr clause)))))
	   (otherwise
	       (setq %%item%%
		     (cerror t () ':wrong-type-argument
			     "The selector ~S was not found in a SELECT! construct."
			     %%item%%))
	       (go retry-select!)))))

This is a version of SELECT that provides its own OTHERWISE clause
and arranges to retry with a correctable error if the key is not known.
I need a PROG to make a loop.  However, if a RETURN occurs in a clause
to SELECT!, I want it to return from whatever PROG surrounds SELECT!

In the interpreter, the problem is that RETURN-FROM binds RETPROGDESC
and then cretinously calls EVAL, giving it a consed-up RETURN form.
Of course, if the argument to the consed-up RETURN form contains a RETURN,
as here, things get really fouled up.  The fix is that RETURN-FROM
should evaluate its argument **first**, before binding RETPROGDESC,
and then cons up a form (RETURN '<the-result>) to eval if it must be done
that kludgy way.

I have no idea how the compiler manages to screw up the same way.