(FILECREATED " 9-Mar-84 00:52:58" {INDIGO}<LOOPS>SOURCES>LOOPSMETHODS.;21 35096  

      changes to:  (VARS LOOPSMETHODSCOMS)

      previous date: "29-Feb-84 15:58:33" {INDIGO}<LOOPS>SOURCES>LOOPSMETHODS.;20)


(PRETTYCOMPRINT LOOPSMETHODSCOMS)

(RPAQQ LOOPSMETHODSCOMS [(* Copyright (c)
			    1983 by Xerox Corporation)
			 (MACROS * METHODMACROS)
			 (MACROS * OTHERLOOPSMACROS)
			 (FNS * METHODSFNS)
			 (GLOBALVARS UseMethodCacheFlg ClassBlock SelectorBlock MethodBlock)
			 [VARS (LoopsDebugFlg T)
			       (UseMethodCacheFlg T)
			       (ClassBlock (NCREATE (QUOTE VMEMPAGEP)))
			       (SelectorBlock (NCREATE (QUOTE VMEMPAGEP)))
			       (MethodBlock (NCREATE (QUOTE VMEMPAGEP]
			 (P (MOVD (QUOTE ←)
				  (QUOTE SEND)))
			 (P (ADDTOVAR NLAMA ←← ←Super ←! ← ←SuperFringe DoMethod DoFringeMethods))
			 (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS
				   (ADDVARS (NLAMA ←← ←Super ←! ← ←SuperFringe METH DoMethod 
						   DoFringeMethods)
					    (NLAML)
					    (LAMA])



(* Copyright (c) 1983 by Xerox Corporation)


(RPAQQ METHODMACROS (AVApply* DOAPPLY* DoMethod FetchMethod FindSelectorIndex MapSupersForm? SEND 
			      SENDSUPER ← ←! ←IV ←New ←Proto ←Super ←Try))
(DECLARE: EVAL@COMPILE 

(PUTPROPS AVApply* MACRO [(FRST . REST)
			  (COND
			    ((LISTP FRST)
			      (EVAL FRST))
			    (T (DOAPPLY* FRST . REST])

(PUTPROPS DOAPPLY* MACRO (arg (CONS (QUOTE APPLY*)
				    arg)))

(PUTPROPS DoMethod MACRO [(obj action class . args)
			  (PROG ((obj%  obj))
			        (RETURN (DOAPPLY*(OR (FetchMethod (OR class (fetch CLASS
									       of obj% ))
								  action)
						     (ERROR action "not found for DoMethod"))
					  obj%  . args])

(PUTPROPS FetchMethod MACRO (OPENLAMBDA (classRec selector)
                                                             (* dgb: " 9-JUN-83 22:27")
                                                             (* Returns the function for selector or NIL)
					(PROG (pos meth index supers (class classRec))
					      (OR (type? class classRec)
						  (RETURN))
					      (OR UseMethodCacheFlg (GO ON))
					      [SETQ pos (LOGAND 254 (LOGXOR (\LOLOC classRec)
									    (\LOLOC selector]
                                                             (* pos is an even postion on the page, computed from the
							     xor of the selector and the classRec addresses)
					      [COND
						((AND (EQ classRec (\GETBASEPTR ClassBlock pos))
						      (EQ selector (\GETBASEPTR SelectorBlock pos)))
						  (RETURN (\GETBASEPTR MethodBlock pos]
					  ON  (SETQ supers (fetch supers of classRec))
					  LP  (COND
						((SETQ index (FindSelectorIndex class selector))
						  (GO OUT))
						((SETQ class (pop supers))
						  (GO LP))
						(T (RETURN NIL)))
					  OUT (SETQ meth (GetNthMethod class index))
					      (COND
						(UseMethodCacheFlg (\PUTBASEPTR ClassBlock pos 
										classRec)
								   (\PUTBASEPTR SelectorBlock pos 
										selector)
								   (\PUTBASEPTR MethodBlock pos meth))
						)
					      (RETURN meth))))

(PUTPROPS FindSelectorIndex MACRO [OPENLAMBDA (class selector)
					      (PROG NIL      (* Prog is only so one can bomb out in case of NIL 
							     selectors of class)
						    (RETURN (\FindEntryIndex selector
									     (OR (fetch selectors
										    of class)
										 (RETURN])

(PUTPROPS MapSupersForm? MACRO ((mappingForm classRec . progArgs)
                                                             (* dgb: "12-JAN-82 14:55")

          (* Maps through a class and its supers in order. Returns if form has return statement, or NIL when finished %.
	  form can use class as free variable)


				(PROG (supers (class classRec) . progArgs)
				      (COND
					((NULL class)
					  (RETURN NIL)))
				      (SETQ supers (Supers class))
				  LP
				  mappingForm                (* this is where the substitution goes)
				  ON  (COND
					((SETQ class (pop supers))
                                                             (* If there is a Super, iterate around the Loop)
					  (GO LP)))          (* Returns NotSetValue if not found)
				      (RETURN NotSetValue))))

(PUTPROPS SEND MACRO ((obj action . args)
		      (← obj action . args)))

(PUTPROPS SENDSUPER MACRO ((obj action . args)
			   (←Super
			     obj action . args)))

(PUTPROPS ← MACRO (messForm (DWIMIFY [BQUOTE (PROG ((oBj , (CAR messForm)))
					           (DECLARE (LOCALVARS oBj))
					           (RETURN (APPLY* (FetchMethodOrHelp
								     oBj
								     (QUOTE , (CADR messForm)))
								   oBj ,. (CDDR messForm]
				     T)))

(PUTPROPS ←! MACRO [(obj action . args)
		    (PROG ((oBj obj))
		          (RETURN (PROG (classForMethod)
				        (RETURN (DOAPPLY*(FetchMethodOrHelp oBj action)
						  oBj . args])

(PUTPROPS ←IV MACRO (messForm (DWIMIFY [BQUOTE (PROG ((oBj , (CAR messForm)))
						     (DECLARE (LOCALVARS oBj))
						     (RETURN (APPLY* (IVFunction oBj
										 (QUOTE ,
											(CADR 
											 messForm)))
								     oBj ,. (CDDR messForm]
				       T)))

(PUTPROPS ←New MACRO [form (COND
			     ((NULL (CDR form))
			       (LIST (QUOTE ←)
				     (CAR form)
				     (QUOTE New)))
			     (T (SUBPAIR (QUOTE (obj action . args))
					 form
					 (QUOTE (PROG (classForMethod (obj%  (← obj New)))
						      (DOAPPLY*(FetchMethodOrHelp obj%  (QUOTE action)
										  )
							obj%  . args)
						      (RETURN obj% ])

(PUTPROPS ←Proto MACRO ((obj . args)
			(← (← obj Prototype) . args)))

(PUTPROPS ←Super MACRO [(obj action . args)
			(PROG ((obj%  obj))
			      (DECLARE (LOCALVARS . T))
			      (RETURN (DOAPPLY*(GetSuperMethod obj%  (QUOTE action))
					obj%  . args])

(PUTPROPS ←Try MACRO [(obj action . args)
		      (PROG ((obj%  obj))
			    (RETURN (DOAPPLY*(OR (FetchMethod obj%  (QUOTE action))
						 (RETURN (QUOTE NotSent)))
				      obj%  . args])
)

(RPAQQ OTHERLOOPSMACROS (ExtractObj MapSupersForm MapSupersUnlessBadList MenuGetOrCreate 
				    NextSuperClass))
(DECLARE: EVAL@COMPILE 

(PUTPROPS ExtractObj MACRO ((datum)
			    (OR (CAR (LISTP datum))
				datum)))

(PUTPROPS MapSupersForm MACRO ((mappingForm classRec . progArgs)
                                                             (* dgb: "12-JAN-82 14:55")

          (* Maps through a class and its supers in order. Returns if form has return statement, or NIL when finished %.
	  form can use class as free variable)


			       (PROG (supers (class classRec) . progArgs)
				     (COND
				       ((NULL class)
					 (RETURN NIL)))
				     (SETQ supers (Supers class))
				 LP
				 mappingForm                 (* this is where the substitution goes)
				 ON  (COND
				       ((SETQ class (pop supers))
                                                             (* If there is a Super, iterate around the Loop)
					 (GO LP)))           (* Returns NIL if not found)
				     (RETURN NIL))))

(PUTPROPS MapSupersUnlessBadList MACRO ((badList mappingForm classRec . progArgs)
                                                             (* dgb: "12-JAN-82 14:55")

          (* Maps through a class and its supers in order. Returns if form has return statement, or NIL when finished %.
	  form can use class as free variable)


					(PROG (supers (class classRec) . progArgs)
					      (COND
						((NULL class)
						  (RETURN NIL)))
					      (SETQ supers (Supers class))
					  LP                 (* Skip if super is on badList.)
					      (OR (FMEMB (ClassName class)
							 badList)
						  mappingForm)
                                                             (* this is where the substitution goes)
					  ON  (COND
						((SETQ class (pop supers))
						  (GO LP)))
                                                             (* Returns NIL if not found)
					      (RETURN NIL))))

(PUTPROPS MenuGetOrCreate MACRO [(name items)
				 (COND
				   ((type? MENU (GETTOPVAL (QUOTE name)))
				     name)
				   (T (SETTOPVAL (QUOTE name)
						 (create MENU
							 CHANGEOFFSETFLG ← T
							 ITEMS ← items])

(PUTPROPS NextSuperClass MACRO [NIL (COND
				      ((SETQ class (pop supers))

          (* * This code assumes that LP is a defined PROG label and supers and class are bound)

                                                             (* If there is a Super, iterate around the Loop)
					(GO LP])
)

(RPAQQ METHODSFNS (AddMethod ApplyMethod ApplyMethodInTtyProcess DefMethObj DefineMethod DeleteMethod 
			     DoFringeMethods DoMethod IVFunction InstallMethod LoopsHelp METH 
			     RenameMethod ←SuperFringe FindLocalMethod FindSelectorIndex Fix@$ 
			     FlushMethodCache FullInstallMethod FetchMethod FetchMethodOrHelp 
			     GetCallerClass GetNthMethod GetSuperMethod PrintMeths PutMethodNth ← ←! 
			     ←Super ←← DCM))
(DEFINEQ

(AddMethod
  [LAMBDA (class selector method)                            (* dgb: "28-Feb-84 17:19")
                                                             (* Adds a method to a class, or replaces the function 
							     named if selecor is already local to class)
    (PROG (index freePos sels)
          (RETURN (COND
		    ((SETQ index (FindSelectorIndex class selector))
                                                             (* already in class)
		      (PutMethodNth class index method))
		    (T (FlushMethodCache)
		       (UNINTERRUPTABLY
                           [SETQ freePos (\FreeEntryIndex (SETQ sels (fetch selectors of class]
			   (replace selectors of class with (\AddBlockEntry sels selector freePos))
			   (replace methods of class with (\AddBlockEntry (fetch methods
									     of class)
									  method freePos)))])

(ApplyMethod
  [LAMBDA (object selector argList class)                    (* dgb: "29-Feb-84 08:49")
                                                             (* Apply the selected method to the already evaluated 
							     args in argList.)
    (PROG (classForMethod)
          (RETURN (APPLY [OR (FetchMethod (OR class (fetch CLASS of object))
					  selector)
			     (ERROR selector (CONCAT "not a selector in "
						     (OR class (fetch CLASS of object]
			 (CONS object argList])

(ApplyMethodInTtyProcess
  [LAMBDA (object selector argList class waitFlg)            (* dgb: " 2-MAR-83 12:50")
                                                             (* Apply the selected method to the already evaluated 
							     args in argList as a tty process.)
    (EVAL.IN.TTY.PROCESS (BQUOTE (ApplyMethod , object (QUOTE , selector)
					      (QUOTE , argList)
					      , class))
			 waitFlg])

(DefMethObj
  [LAMBDA (cName sel fn arg dcm methodProps otherIVs)        (* dgb: " 7-DEC-83 14:45")
    (PROG (self (methName (MethName cName sel)))
          [SETQ self (OR (GetObjectRec methName)
			 (BlankInstance ($ Method]
          (NameObject self (LIST methName))
          (←@
	    className cName)
          (←@
	    selector sel)
          (←@
	    args arg)
          (←@
	    doc dcm)
          (←@
	    method fn)
          (AND methodProps (for p on methodProps do (PutValue self (QUOTE method)
							      (CADR p)
							      (CAR p))
			      by (CDDR p)))

          (* method is filled by fn. all the other IVs which the method can have are in oth, and will be filled into the 
	  instance)


          (AND otherIVs (FillInst otherIVs self))
          (InstallMethod self])

(DefineMethod
  [LAMBDA (class selector argsOrFn expr)                     (* dgb: " 2-JAN-84 17:24")

          (* * Define a new method (or replace an old one). If expr is NIL then argsOrFn should be a function Name, else it 
	  should be a list of arguments, and expr should be the function definition)


    (COND
      ((NOT (LITATOM selector))
	(ERROR selector "is not a LIATOM, so cannot be a selector")))
    (PROG (fnName file editFlg methName methObj (className (ClassName class)))
                                                             (* methName is name of object for method)
          (SETQ methName (PACK* className (QUOTE %.)
				selector))
          (SETQ methObj (GetMethodObj class selector T))
          [COND
	    ((SETQ editFlg (NOT (OR argsOrFn expr)))
	      (SETQ argsOrFn (LIST (QUOTE self)))
	      (SETQ expr (COPY (QUOTE (                      (* New method template)
					self]
          [COND
	    ((AND argsOrFn (LITATOM argsOrFn))
	      (SETQ fnName argsOrFn))
	    (T [COND
		 ((NULL expr)                                (* Here if argsOrFn left out)
		   (SETQ expr argsOrFn)
		   (SETQ argsOrFn (LIST (QUOTE self]
	       [COND
		 ([AND (LISTP expr)
		       (NOT (LISTP (CAR expr]                (* This is a single expression, not an implicit PROGN)
		   (SETQ expr (LIST expr]
	       [SETQ expr (FIXEDITDATE (CONS (QUOTE LAMBDA)
					     (CONS argsOrFn expr]
	       (SETQ fnName methName)
	       (DEFINE (LIST (LIST fnName expr]
          (AddMethod class selector fnName)
          (←@
	    \methObj:method fnName)
          [COND
	    ([AND (NULL (WHEREIS methName (QUOTE METHODS)))
		  (SETQ file (CAR (WHEREIS className (QUOTE CLASSES]
	      (ADDTOFILE methName (QUOTE METHODS)
			 file))
	    (T (MARKASCHANGED methName (QUOTE METHODS]
          (COND
	    (editFlg (← class EditMethod selector)))
          (← class CommentMethods (LIST selector)
	     T)
          (RETURN (SETQ LASTWORD fnName])

(DeleteMethod
  [LAMBDA (class selector prop)                              (* dgb: "28-Feb-84 17:20")
    (PROG (methObj index pl fn freePos sel)
      TRYAGAIN
          (SETQ index (FindSelectorIndex (SETQ class (GetClassRec class))
					 selector))
          (COND
	    ((NULL index)
	      (SETQ selector (HELPCHECK class " does not contain the selector " selector 
					"Type
RETURN 'selectorName
to try again"))
	      (GO TRYAGAIN)))
          [COND
	    ((EQ prop T)                                     (* T is special Flag for deleteing the function 
							     definition too)
	      (SETQ prop NIL)
	      (CLEARW PROMPTWINDOW)
	      (printout PROMPTWINDOW (CHARACTER 7)
			"Deleting function definition for "
			(SETQ fn (GetMethod class selector))
			T)
	      (COND
		((NEQ fn (MethName class selector))
		  (DELDEF fn]
          (COND
	    [prop (SETQ methObj (GetMethodObj class selector))
		  (COND
		    ((FMEMB prop (GetClassValue methObj (QUOTE ivProperties)))
		      (PutValueOnly methObj prop NotSetValue))
		    (T (DeleteIV methObj (QUOTE method)
				 prop]
	    (T                                               (* \DeleteNthEntry requires knowing the freePos.
							     Must compute it from selectors because it checks for 
							     occurrence of NIL in block to mark end)
	       (DELFROMFILE (MethName class selector)
			    (QUOTE METHODS))
	       (FlushMethodCache)
	       (UNINTERRUPTABLY
                   [SETQ freePos (\FreeEntryIndex (SETQ sel (fetch selectors of class]
		   (\DeleteNthEntry sel index freePos)
		   (\DeleteNthEntry (fetch methods of class)
				    index freePos))])

(DoFringeMethods
  [NLAMBDA obj% selector% ..args                             (* dgb: "29-Feb-84 08:49")
                                                             (* This calls all the methods of an object in the 
							     immediate supers of the object.
							     selector is evaluated.)
    (PROG [selector object objClass fn (argList (MAPCAR obj% selector% ..args (FUNCTION EVAL]
          (DECLARE (LOCALVARS . T))
          (SETQ object (CAR argList))
          (SETQ selector (CADR argList))
          (SETQ argList (CONS object (CDDR argList)))
          (SETQ objClass (Class object))
          (COND
	    ((SETQ fn (FetchMethod objClass selector))
	      (APPLY fn argList))
	    (T (for cls in (fetch localSupers of objClass) do (COND
								((SETQ fn (FetchMethod cls selector))
								  (APPLY fn argList])

(DoMethod
  [NLAMBDA obj% selector% class% ..args                      (* dgb: "29-Feb-84 08:49")
                                                             (* Function for macro so that args are known)
    (DECLARE (LOCALVARS . T)
	     (SPECVARS classForMethod))
    (PROG (classForMethod allArgs oBj)
          (SETQ allArgs (MAPCAR obj% selector% class% ..args (FUNCTION EVAL)))
          (SETQ oBj (pop allArgs))
          (RETURN (APPLY [OR (FetchMethod (OR (CADR allArgs)
					      (Class oBj))
					  (CAR allArgs))
			     (ERROR (CAR allArgs)
				    (CONCAT "not a selector for " (OR (CADR allArgs)
								      (Class oBj]
			 (CONS oBj (CDDR allArgs])

(IVFunction
  [LAMBDA (obj ivName)                                       (* dgb: "29-Feb-84 15:21")
    (PROG ((fnName (GetValue obj ivName)))
          (RETURN (COND
		    ((DEFINEDP fnName)
		      fnName))
		  (T (LoopsHelp "No iv function" obj ivName fnName])

(InstallMethod
  [LAMBDA (self)                                             (* dgb: " 1-NOV-83 11:27")
                                                             (* Used in kernel system to add methods.
							     Replace by FullInstallMethod after LOOPSKERNEL is 
							     loaded)
    (AddMethod (GetObjectRec (@ className))
	       (@ selector)
	       (@ method])

(LoopsHelp
  [LAMBDA (mess1 mess2 mess3 mess4)                          (* dgb: "29-Feb-84 15:26")
    (COND
      ((NULL LoopsDebugFlg)
	(ERROR mess1 mess2)))
    (AND mess1 (PRIN2 mess1)
	 (TERPRI))
    (AND mess2 (PRIN2 mess2)
	 (TERPRI))
    (AND mess3 (PRIN2 mess3)
	 (TERPRI))
    (AND mess4 (PRIN2 mess4)
	 (TERPRI))
    (HELP "Loops Help"])

(METH
  [NLAMBDA methDescr                                         (* dgb: " 7-DEC-83 14:46")

          (* * Put out by the class method. Contains in order the (className selector methName (if different from 
	  className.selector) args doc . other-properties))


    (PROG (self cName sel fnName methName (descr methDescr))
          (SETQ cName (pop descr))
          (SETQ sel (pop descr))
          (SETQ methName (MethName cName sel))
          (COND
	    ((AND (SETQ fnName (CAR descr))
		  (LITATOM fnName))                          (* Method name which is not identical to methName)
	      (SETQ descr (CDR descr)))
	    (T (SETQ fnName methName)))
          (DefMethObj cName sel fnName (CAR descr)
		      (CADR descr)
		      NIL
		      (CDDR descr])

(RenameMethod
  [LAMBDA (classOrName oldSelector newSelector)              (* dgb: " 2-JAN-84 17:28")

          (* * Rename selector in class, and rename method also if it is composite. If oldClassName is given, then class has
	  been renamed, and not selector changed.)


    (PROG (className class newLocalFn oldDef localFn fnPair newMethName)
          [COND
	    ((type? class classOrName)
	      (SETQ class classOrName)
	      (SETQ className (ClassName class)))
	    (T (SETQ className (GoodClassName classOrName NIL T))
	       (SETQ class (GetClassRec className]
          (SETQ localFn (FindLocalMethod class oldSelector))
          (COND
	    ((NULL localFn)
	      (printout T oldSelector " not found in " className)
	      (RETURN)))                                     (* Rename Method Object so thatold one goes away)
          [COND
	    ((EQ [CAR (SETQ fnPair (SplitAtom localFn (QUOTE %.]
		 className)
	      (OR (SETQ oldDef (CDR (GETDEF localFn)))
		  (ERROR localFn " defn cannot be found for RenameMethod"]
          (← (GetMethodObj class oldSelector T)
	     ChangeName
	     (MethName class oldSelector)
	     (SETQ newMethName (MethName className newSelector))
	     newSelector)
          (COND
	    (oldDef (DeleteMethod class oldSelector)
		    (DM className newSelector (CAR oldDef)
			(CDR oldDef)))
	    (T (DeleteMethod class oldSelector)
	       (DM className newSelector localFn)))
          (RETURN newMethName])

(←SuperFringe
  [NLAMBDA obj% selector% ..args                             (* dgb: "29-Feb-84 08:49")
                                                             (* This calls all the methods of an object in the 
							     immediate supers of the object.
							     selector is not evaluated.)
    (PROG (callerClass fn object selector argList)
          (DECLARE (LOCALVARS . T))
          (SETQ object (EVAL (CAR obj% selector% ..args)))
          (SETQ selector (CADR obj% selector% ..args))
          (SETQ argList (MAPCAR (CDDR obj% selector% ..args)
				(FUNCTION EVAL)))
          (SETQ argList (CONS object argList))
          (SETQ callerClass (GetCallerClass object selector (QUOTE ←SuperFringe)))
          (for cls in (fetch localSupers of callerClass) do (COND
							      ((SETQ fn (FetchMethod cls selector))
								(APPLY fn argList])

(FindLocalMethod
  [LAMBDA (class selector)                                   (* dgb: " 9-JUN-83 22:27")
                                                             (* Return function handling method in this class, or NIL
							     if there is none)
    (PROG ((index (FindSelectorIndex class selector)))
          (RETURN (AND index (GetNthMethod class index])

(FindSelectorIndex
  [LAMBDA (class selector)                                   (* dgb: " 9-JUN-83 22:27")
    (PROG NIL                                                (* Prog is only so one can bomb out in case of NIL 
							     selectors of class)
          (RETURN (\FindEntryIndex selector (OR (fetch selectors of class)
						(RETURN])

(Fix@$
  [LAMBDA (atom tail)                                        (* dgb: " 3-JUN-83 15:01")
    (PROG (FORM ATOM (FIRSTCHAR (NTHCHAR atom 1)))
          (SELECTQ FIRSTCHAR
		   [($ @)
		     (COND
		       ((SETQ ATOM (SUBATOM atom 2))         (* Used form $loopsName or @ivName)
			 (SETQ FORM (LIST FIRSTCHAR ATOM))
			 (AND (LISTP tail)
			      (RPLACA tail FORM)))
		       ((AND (EQ FIRSTCHAR (QUOTE @))
			     (LISTP tail)
			     (LISTP (CAR tail)))             (* Tried to use old form @ (FOO FIE). Put @ inside 
							     parens)
			 (SETQ FORM (CONS FIRSTCHAR (CAR tail)))
			 (RPLACA tail FORM)
			 (RPLACD tail (CDDR tail]
		   NIL)
          (RETURN FORM])

(FlushMethodCache
  [LAMBDA NIL                                                (* dgb: "29-Feb-84 11:55")
    (AND UseMethodCacheFlg (TYPENAMEP ClassBlock (QUOTE VMEMPAGEP))
	 (\ZEROWORDS ClassBlock (\ADDBASE ClassBlock 255])

(FullInstallMethod
  [LAMBDA (self)                                             (* dgb: " 1-NOV-83 08:02")
                                                             (* Used after kernel is installed.
							     Calls a method to install a method)
    (← self OldInstance])

(FetchMethod
  [LAMBDA (classRec selector)                                (* dgb: "28-Feb-84 17:48")
                                                             (* Returns the function for selector or NIL)
    (PROG (pos meth index supers (class classRec))
          (OR (type? class classRec)
	      (RETURN))
          (OR UseMethodCacheFlg (GO ON))
          [SETQ pos (LOGAND 254 (LOGXOR (\LOLOC classRec)
					(\LOLOC selector]    (* pos is an even postion on the page, computed from the
							     xor of the selector and the classRec addresses)
          [COND
	    ((AND (EQ classRec (\GETBASEPTR ClassBlock pos))
		  (EQ selector (\GETBASEPTR SelectorBlock pos)))
	      (RETURN (\GETBASEPTR MethodBlock pos]
      ON  (SETQ supers (fetch supers of classRec))
      LP  (COND
	    ((SETQ index (FindSelectorIndex class selector))
	      (GO OUT))
	    ((SETQ class (pop supers))
	      (GO LP))
	    (T (RETURN NIL)))
      OUT (SETQ meth (GetNthMethod class index))
          (COND
	    (UseMethodCacheFlg (\PUTBASEPTR ClassBlock pos classRec)
			       (\PUTBASEPTR SelectorBlock pos selector)
			       (\PUTBASEPTR MethodBlock pos meth)))
          (RETURN meth])

(FetchMethodOrHelp
  [LAMBDA (self selector)                                    (* dgb: "29-Feb-84 15:40")

          (* Searches for an selector up the supers chain. If UseMethodCacheFlg=T then searches first in the method cache.
	  If none found, searches for the MessageNotUnderstood action. If that is not found, causes a LISP break.)


    (PROG (class)
      TOP (SETQ class (Class self))
      LP  (RETURN (OR (AND class (OR (FetchMethod class selector)
				     (AND (FetchMethod class (QUOTE MessageNotUnderstood))
					  (SETQ selector (← self MessageNotUnderstood selector))
					  (GO LP))
				     (LoopsHelp (LIST (QUOTE ←)
						      (COND
							((EQ selector (QUOTE PrintOn))
							  (QUOTE ***))
							(T self))
						      selector
						      (QUOTE --))
						"not understood")))
		      (PROGN                                 (* Here if Object not found. Invokes the NoObjectForMsg 
							     message on the current value of the LISP global variable
							     DefaultObject. See Object.NoObjectForMsg.)
			     (SETQ LastDefaultValue (DoMethod self (QUOTE NoObjectForMsg)
							      DefaultObject selector))
			     (RETURN (QUOTE GetLastDefaultValue])

(GetCallerClass
  [LAMBDA (object selector fromCaller)                       (* dgb: "29-Feb-84 15:42")
                                                             (* Get the class of the caller for use by ←Super)
    (PROG (class fn index supersList stkPos (callerName fromCaller))
      SETCALLER
          (OR (SETQ stkPos (REALSTKNTH -1 (OR stkPos callerName)
				       NIL stkPos))
	      (LoopsHelp selector "No caller found in " (OR fromCaller "←Super")))
          (SETQ callerName (STKNAME stkPos))
      CALLERSET
          (SETQ class (Class object))
          (SETQ supersList (Supers class))
      LP  [COND
	    ((SETQ index (FindSelectorIndex class selector))
                                                             (* There is a method in this class)
	      (COND
		((EQ callerName (SETQ fn (GetNthMethod class index)))
                                                             (* Fn here is the same one I am in.
							     Return class as callerName of DoSuperMethods)
		  (RELSTK stkPos)
		  (RETURN class]
          (COND
	    ((SETQ class (pop supersList))                   (* Try next superClass)
	      (GO LP))
	    (T                                               (* Never found containing method -- Move Back one 
							     callerName)
	       (GO SETCALLER])

(GetNthMethod
  [LAMBDA (class n)                                          (* dgb: "28-APR-83 18:37")
    (PROG ((meths (fetch methods of class)))
          (RETURN (COND
		    ((LISTP meths)
		      (GetNth meths n))
		    (T (\GetNthEntry meths n])

(GetSuperMethod
  [LAMBDA (object selector callerName)                       (* dgb: "29-Feb-84 15:42")
                                                             (* Searches for an selector up the supers chain.
							     If none found, calls LISP HELP.)
    (PROG (index fn flg supersList class stkPos)
          [COND
	    (callerName                                      (* first time could be set by interpreted ←Super)
			(GO CALLERSET))
	    (T                                               (* Initialization for SETCALLER)
	       (SETQ callerName (QUOTE GetSuperMethod]
      SETCALLER
          (OR (SETQ stkPos (REALSTKNTH -1 (OR stkPos callerName)
				       NIL stkPos))
	      (PROGN (RELSTK stkPos)
		     (LoopsHelp "No caller found in ←Super for:
" selector)))
          (SETQ callerName (STKNAME stkPos))
      CALLERSET
          (SETQ class (Class object))
          (SETQ supersList (Supers class))
      LP  [COND
	    ((SETQ index (FindSelectorIndex class selector))
                                                             (* There is a response in this class)
	      (COND
		((EQ callerName (SETQ fn (GetNthMethod class index)))
                                                             (* Fn here is the same one I am in.
							     Mark caller as found by seting flg)
		  (SETQ flg T))
		(flg                                         (* found a response and have previously seen caller of 
							     ←Super)
		     (RELSTK stkPos)
		     (RETURN fn]
          (COND
	    ((SETQ class (pop supersList))                   (* Try next superClass)
	      (GO LP))
	    (flg                                             (* No super found, though method was found)
		 (LoopsHelp selector "not understood in ←Super"))
	    (T                                               (* Never found containing method -- Move Back one 
							     caller)
	       (GO SETCALLER])

(PrintMeths
  [LAMBDA (methList file)                                    (* dgb: "21-OCT-83 07:11")
    (printout file .FONT DEFAULTFONT "[DefMeths")
    (for name self in methList when (SETQ self (GetObjectRec name))
       do (printout file T "(" .FONT LAMBDAFONT name , .FONT DEFAULTFONT .PPFTL
		    [NCONC [COND
			     ((NEQ name (@ method))
			       (LIST (@ method]
			   (LIST (@ args)
				 (@ doc))
			   (CDR (FetchIVDescr self (QUOTE method]
		    ")" T))
    (printout file "] 

")
    methList])

(PutMethodNth
  [LAMBDA (class n fn)                                       (* edited: "31-MAY-83 15:45")
    (PROG ((meths (fetch methods of class)))
          (RETURN (COND
		    ((NULL meths)
		      (ERROR class "no methods in class"))
		    ((LISTP meths)
		      (PutNth meths n fn))
		    (T (\PutNthEntry meths n fn])

(←
  [NLAMBDA object% selector% ..args                          (* dgb: " 3-JUN-83 15:05")

          (* This is the function version of the macro. This function does more error checking than the MACRO and converts 
	  unbound atoms into names for classes and instances)


    (PROG (object↑ (objForm (CAR object% selector% ..args)))
          (DECLARE (LOCALVARS . T))
          [COND
	    [[AND (LITATOM objForm)
		  (EQ (QUOTE NOBIND)
		      (SETQ object↑ (EVALV objForm]
	      (SETQ object↑ (OR (EVAL (Fix@$ objForm object% selector% ..args))
				(PROGN 

          (* * This is a hack to help a user who has left off the $ from an atom)


				       (WRITE "Using $" objForm)
				       (GetObjectRec objForm]
	    (T (SETQ object↑ (EVAL objForm]
          (COND
	    ((NULL object↑)
	      (ERROR objForm "is NIL.")))
          (RETURN (APPLY (FetchMethodOrHelp object↑ (CADR object% selector% ..args))
			 (CONS object↑ (for X in (CDDR object% selector% ..args) collect
										  (EVAL X])

(←!
  [NLAMBDA object% selector% ..args                          (* dgb: "29-Feb-84 08:49")

          (* This is the function version of the macro. This function does more error checking than the MACRO and converts 
	  unbound atoms into names for classes and instances)


    (PROG (object↑ (objForm (CAR object% selector% ..args)))
          [COND
	    [(LITATOM objForm)

          (* * This is a hack to help a user who has left off the $ from an atom)


	      (COND
		((EQ (QUOTE NOBIND)
		     (SETQ object↑ (EVALV objForm)))
		  (WRITE "Using $" objForm)
		  (SETQ object↑ (GetObjectRec objForm]
	    (T (SETQ object↑ (EVAL objForm]
          (COND
	    ((NULL object↑)
	      (ERROR objForm "is NIL.")))
          (RETURN (PROG (classForMethod)                     (* ClassForMethod is set by FetchMethod for use by 
							     embedded ←Supers. It can not be set by ←! until the 
							     object↑ has been determined.)
		        (RETURN (APPLY (FetchMethodOrHelp object↑ (EVAL (CADR 
									 object% selector% ..args)))
				       (CONS object↑ (for X in (CDDR object% selector% ..args)
							collect (EVAL X])

(←Super
  [NLAMBDA FORM%@                                            (* dgb: " 1-JUN-83 11:58")
                                                             (* This is a form to do ←Super so that the macro 
							     expander does not mark as changed the function 
							     containing the ←Super)
    (PROG [(stkPos (REALSTKNTH -1 (QUOTE ←Super)))
	   (obj%  (EVAL (CAR FORM%@)))
	   (action (CADR FORM%@))
	   (args%  (MAPCAR (CDDR FORM%@)
			   (FUNCTION EVAL]
          (DECLARE (LOCALVARS . T))
          (RETURN (APPLY (GetSuperMethod obj%  action (PROG1 (STKNAME stkPos)
							     (RELSTK stkPos)))
			 (CONS obj%  args% ])

(←←
  [NLAMBDA SEND% FORM                                        (* dgb: "15-JAN-83 23:14")
                                                             (* This is the EVALQUOTE version of the ← function.
							     ←← quotes its arguments except for the object)
    (PROG (classForMethod obj (objForm (CAR SEND% FORM)))
          [COND
	    [(LITATOM objForm)

          (* * This is a hack to help a user who has left off the %$ from an atom)


	      (COND
		((EQ (QUOTE NOBIND)
		     (SETQ obj (EVALV objForm)))
		  (SETQ obj (GetObjectRec objForm]
	    (T (SETQ obj (EVAL objForm]
          (RETURN (APPLY (FetchMethodOrHelp obj (CADR SEND% FORM))
			 (CONS obj (for % X in (CDDR SEND% FORM) collect % X])

(DCM
  [LAMBDA (className selector)                               (* dgb: "10-JUN-83 11:55")
                                                             (* Combine methods from supers with ←SuperFringe)
    (PROG [(argList (ARGLIST (GetMethod (OR (GetClassRec className)
					    (ERROR className "not a defined class"))
					selector]
          (RETURN (DM className selector argList (SUBST (CDR argList)
							(QUOTE argL)
							(BQUOTE (
                                                             (* Combined method for , selector)
								 (←SuperFringe
								   self , selector . argL])
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS UseMethodCacheFlg ClassBlock SelectorBlock MethodBlock)
)

(RPAQQ LoopsDebugFlg T)

(RPAQQ UseMethodCacheFlg T)

(RPAQ ClassBlock (NCREATE (QUOTE VMEMPAGEP)))

(RPAQ SelectorBlock (NCREATE (QUOTE VMEMPAGEP)))

(RPAQ MethodBlock (NCREATE (QUOTE VMEMPAGEP)))
(MOVD (QUOTE ←)
      (QUOTE SEND))
(ADDTOVAR NLAMA ←← ←Super ←! ← ←SuperFringe DoMethod DoFringeMethods)
(DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS 

(ADDTOVAR NLAMA ←← ←Super ←! ← ←SuperFringe METH DoMethod DoFringeMethods)

(ADDTOVAR NLAML )

(ADDTOVAR LAMA )
)
(DECLARE: DONTCOPY
  (FILEMAP (NIL (9027 34446 (AddMethod 9037 . 9966) (ApplyMethod 9968 . 10496) (ApplyMethodInTtyProcess 
10498 . 10931) (DefMethObj 10933 . 11765) (DefineMethod 11767 . 13761) (DeleteMethod 13763 . 15448) (
DoFringeMethods 15450 . 16330) (DoMethod 16332 . 17024) (IVFunction 17026 . 17301) (InstallMethod 
17303 . 17695) (LoopsHelp 17697 . 18053) (METH 18055 . 18850) (RenameMethod 18852 . 20338) (
←SuperFringe 20340 . 21248) (FindLocalMethod 21250 . 21638) (FindSelectorIndex 21640 . 22006) (Fix@$ 
22008 . 22704) (FlushMethodCache 22706 . 22939) (FullInstallMethod 22941 . 23237) (FetchMethod 23239
 . 24461) (FetchMethodOrHelp 24463 . 25694) (GetCallerClass 25696 . 27047) (GetNthMethod 27049 . 27315
) (GetSuperMethod 27317 . 29294) (PrintMeths 29296 . 29842) (PutMethodNth 29844 . 30184) (← 30186 . 
31230) (←! 31232 . 32408) (←Super 32410 . 33074) (←← 33076 . 33824) (DCM 33826 . 34444)))))
STOP