123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- %
- % EASY-NON-SL.RED - Commonly used Non-Standard Lisp functions
- %
- % Author: Eric Benson
- % Symbolic Computation Group
- % Computer Science Dept.
- % University of Utah
- % Date: 18 August 1981
- % Copyright (c) 1981 University of Utah
- %
- % <PSL.KERNEL>EASY-NON-SL.RED.2, 17-Sep-82 16:10:18, Edit by BENSON
- % Added ChannelPrin2T, ChannelSpaces, ChannelTab, ChannelSpaces2
- % <PSL.INTERP>EASY-NON-SL.RED.7, 9-Jul-82 12:46:43, Edit by BENSON
- % Changed NTH to improve error reporting, using DoPNTH
- % <PSL.INTERP>EASY-NON-SL.RED.2, 19-Apr-82 23:05:35, Edit by BENSON
- % Changed order of tests in PNTH
- % <PSL.INTERP>EASY-NON-SL.RED.20, 23-Feb-82 21:36:36, Edit by BENSON
- % Added NE (not eq)
- % <PSL.INTERP>EASY-NON-SL.RED.19, 16-Feb-82 22:30:33, Edit by BENSON
- % made NEQ GEQ and LEQ back into EXPRs
- % <PSL.INTERP>EASY-NON-SL.RED.16, 15-Feb-82 18:01:14, Edit by BENSON
- % Made NEQ GEQ and LEQ into macros
- % <PSL.INTERP>EASY-NON-SL.RED.12, 18-Jan-82 12:28:13, Edit by BENSON
- % Added NexprP
- CompileTime flag('(DelqIP1 DeletIP1 SubstIP1 DelAscIP1 DelAtQIP1 DoPNTH),
- 'InternalFunction);
- % predicates
- expr procedure NEQ(U, V); %. not EQUAL (should be changed to not EQ)
- not(U = V);
- expr procedure NE(U, V); %. not EQ
- not(U eq V);
- expr procedure GEQ(U, V); %. greater than or equal to
- not(U < V);
- expr procedure LEQ(U, V); %. less than or equal to
- not(U > V);
- lisp procedure EqCar(U, V); %. car U eq V
- PairP U and car U eq V;
- lisp procedure ExprP U; %. Is U an EXPR?
- EqCar(U, 'LAMBDA) or CodeP U or EqCar(GetD U, 'EXPR);
- lisp procedure MacroP U; %. Is U a MACRO?
- EqCar(GetD U, 'MACRO);
- lisp procedure FexprP U; %. Is U an FEXPR?
- EqCar(GetD U, 'FEXPR);
- lisp procedure NexprP U; %. Is U an NEXPR?
- EqCar(GetD U, 'NEXPR);
- % Function definition
- lisp procedure CopyD(New, Old); %. FunDef New := FunDef Old;
- %
- % CopyD(New:id, Old:id):id
- % -----------------------
- % Type: EVAL, SPREAD
- % The function body and type for New become the same as Old. If no
- % definition exists for Old, the error
- %
- % ***** `Old' has no definition in CopyD
- %
- % occurs. New is returned.
- %
- begin scalar OldDef;
- OldDef := GetD Old;
- if PairP OldDef then
- PutD(New, car OldDef, cdr OldDef)
- else
- StdError BldMsg("%r has no definition in CopyD", Old);
- return New;
- end;
- % Numerical functions
- lisp procedure Recip N; %. Floating point reciprocal
- 1.0 / N;
- % Commonly used constructors
- lisp procedure MkQuote U; %. Eval MkQuote U eq U
- list('QUOTE, U);
- % Nicer names to access parts of a list
- macro procedure First U; %. First element of a list
- 'CAR . cdr U;
- macro procedure Second U; %. Second element of a list
- 'CADR . cdr U;
- macro procedure Third U; %. Third element of a list
- 'CADDR . cdr U;
- macro procedure Fourth U; %. Fourth element of a list
- 'CADDDR . cdr U;
- macro procedure Rest U; %. Tail of a list
- 'CDR . cdr U;
- % Destructive and EQ versions of Standard Lisp functions
- lisp procedure ReversIP U; %. Destructive REVERSE (REVERSe In Place)
- begin scalar X,Y;
- while PairP U do
- << X := cdr U;
- Y := RplacD(U, Y);
- U := X >>;
- return Y
- end;
- lisp procedure SubstIP1(A, X, L); % Auxiliary function for SubstIP
- << if X = car L then RplacA(L, A)
- else if PairP car L then SubstIP(A, X, car L);
- if PairP cdr L then SubstIP(A, X, cdr L) >>;
- lisp procedure SubstIP(A, X, L); %. Destructive version of Subst
- if null L then NIL
- else if X = L then A
- else if not PairP L then L
- else
- << SubstIP1(A, X, L);
- L >>;
- lisp procedure DeletIP1(U, V); % Auxiliary function for DeletIP
- if PairP cdr V then
- if U = cadr V then RplacD(V, cddr V)
- else DeletIP1(U, cdr V);
- lisp procedure DeletIP(U, V); %. Destructive DELETE
- if not PairP V then V
- else if U = car V then cdr V
- else
- << DeletIP1(U, V);
- V >>;
- lisp procedure DelQ(U, V); %. EQ version of DELETE
- if not PairP V then V
- else if car V eq U then cdr V
- else car V . DelQ(U, cdr V);
- lisp procedure Del(F, U, V); %. Generalized Delete, F is comparison function
- if not PairP V then V
- else if Apply(F, list(car V, U)) then cdr V
- else car V . Del(F, U, cdr V);
- lisp procedure DelqIP1(U, V); % Auxiliary function for DelqIP
- if PairP cdr V then
- if U eq cadr V then RplacD(V, cddr V)
- else DelqIP1(U, cdr V);
- lisp procedure DelqIP(U, V); %. Destructive DELQ
- if not PairP V then V
- else if U eq car V then cdr V
- else
- << DelqIP1(U, V);
- V >>;
- lisp procedure Atsoc(U, V); %. EQ version of ASSOC
- if not PairP V then NIL
- else if PairP car V and U eq caar V then car V
- else Atsoc(U, cdr V);
- lisp procedure Ass(F, U, V); %. Generalized Assoc, F is comparison function
- %
- % Not to be confused with Elbow
- %
- if not PairP V then NIL
- else if PairP car V and Apply(F, list(U, caar V)) then car V
- else Ass(F, U, cdr V);
- lisp procedure Mem(F, U, V); %. Generalized Member, F is comparison function
- if not PairP V then NIL
- else if Apply(F, list(U, car V)) then V
- else Mem(F, U, cdr V);
- lisp procedure RAssoc(U, V); %. Reverse Assoc, compare with cdr of entry
- if not PairP V then NIL
- else if PairP car V and U = cdar V then car V
- else RAssoc(U, cdr V);
- lisp procedure DelAsc(U, V); %. Remove first (U . xxx) from V
- if not PairP V then NIL
- else if PairP car V and U = caar V then cdr V
- else car V . DelAsc(U, cdr V);
- lisp procedure DelAscIP1(U, V); % Auxiliary function for DelAscIP
- if PairP cdr V then
- if PairP cadr V and U = caadr V then
- RplacD(V, cddr V)
- else DelAscIP1(U, cdr V);
- lisp procedure DelAscIP(U, V); %. Destructive DelAsc
- if not PairP V then NIL
- else if PairP car V and U = caar V then cdr V
- else
- << DelAscIP1(U, V);
- V >>;
- lisp procedure DelAtQ(U, V); %. EQ version of DELASC
- if not PairP V then NIL
- else if EqCar(car V, U) then cdr V
- else car V . DelAtQ(U, cdr V);
- lisp procedure DelAtQIP1(U, V); % Auxiliary function for DelAtQIP
- if PairP cdr V then
- if PairP cadr V and U eq caadr V then
- RplacD(V, cddr V)
- else DelAtQIP1(U, cdr V);
- lisp procedure DelAtQIP(U, V); %. Destructive DelAtQ
- if not PairP V then NIL
- else if PairP car V and U eq caar V then cdr V
- else
- << DelAtQIP1(U, V);
- V >>;
- lisp procedure SublA(U,V); %. EQ version of SubLis, replaces atoms only
- begin scalar X;
- return if not PairP U or null V then V
- else if atom V then
- if (X := Atsoc(V, U)) then cdr X else V
- else SublA(U, car V) . SublA(U, cdr V)
- end;
- lisp procedure RplacW(A, B); %. RePLACe Whole pair
- if PairP A then
- if PairP B then
- RplacA(RplacD(A,
- cdr B),
- car B)
- else
- NonPairError(B, 'RplacW)
- else
- NonPairError(A, 'RPlacW);
- lisp procedure LastCar X; %. last element of list
- if atom X then X else car LastPair X;
- lisp procedure LastPair X; %. last pair of list
- if atom X or atom cdr X then X else LastPair cdr X;
- lisp procedure Copy U; %. copy all pairs in S-Expr
- %
- % See also TotalCopy in COPIERS.RED
- %
- if PairP U then Copy car U . Copy cdr U else U; % blows up if circular
- lisp procedure NTH(U, N); %. N-th element of list
- (lambda(X);
- if PairP X then car X else RangeError(U, N, 'NTH))(DoPNTH(U, N));
- lisp procedure DoPNTH(U, N);
- if N = 1 or not PairP U then U
- else DoPNTH(cdr U, N - 1);
- lisp procedure PNTH(U, N); %. Pointer to N-th element of list
- if N = 1 then U
- else if not PairP U then
- RangeError(U, N, 'PNTH)
- else PNTH(cdr U, N - 1);
- lisp procedure AConc(U, V); %. destructively add element V to the tail of U
- NConc(U, list V);
- lisp procedure TConc(Ptr, Elem); %. AConc maintaining pointer to end
- %
- % ACONC with pointer to end of list
- % Ptr is (list . last CDR of list)
- % returns updated Ptr
- % Ptr should be initialized to (NIL . NIL) before calling the first time
- %
- << Elem := list Elem;
- if not PairP Ptr then % if PTR not initialized, return starting ptr
- Elem . Elem
- else if null cdr Ptr then % Nothing in the list yet
- RplacA(RplacD(Ptr, Elem), Elem)
- else
- << RplacD(cdr Ptr, Elem);
- RplacD(Ptr, Elem) >> >>;
- lisp procedure LConc(Ptr, Lst); %. NConc maintaining pointer to end
- %
- % NCONC with pointer to end of list
- % Ptr is (list . last CDR of list)
- % returns updated Ptr
- % Ptr should be initialized to NIL . NIL before calling the first time
- %
- if null Lst then Ptr
- else if atom Ptr then % if PTR not initialized, return starting ptr
- Lst . LastPair Lst
- else if null cdr Ptr then % Nothing in the list yet
- RplacA(RplacD(Ptr, LastPair Lst), Lst)
- else
- << RplacD(cdr Ptr, Lst);
- RplacD(Ptr, LastPair Lst) >>;
- % MAP functions of 2 arguments
- lisp procedure Map2(L, M, Fn); %. for each X, Y on L, M do Fn(X, Y);
- << while PairP L and PairP M do
- << Apply(Fn, list(L, M));
- L := cdr L;
- M := cdr M >>;
- if PairP L or PairP M then
- StdError "Different length lists in MAP2"
- else NIL >>;
- lisp procedure MapC2(L, M, Fn); %. for each X, Y in L, M do Fn(X, Y);
- << while PairP L and PairP M do
- << Apply(Fn, list(car L, car M));
- L := cdr L;
- M := cdr M >>;
- if PairP L or PairP M then
- StdError "Different length lists in MAPC2"
- else NIL >>;
- % Printing functions
- lisp procedure ChannelPrin2T(C, U); %. Prin2 and TerPri
- << ChannelPrin2(C, U);
- ChannelTerPri C;
- U >>;
- lisp procedure Prin2T U; %. Prin2 and TerPri
- ChannelPrin2T(OUT!*, U);
- lisp procedure ChannelSpaces(C, N); %. Prin2 N spaces
- for I := 1 step 1 until N do ChannelWriteChar(C, char BLANK);
- lisp procedure Spaces N; %. Prin2 N spaces
- ChannelSpaces(OUT!*, N);
- lisp procedure ChannelTAB(Chn, N); %. Spaces to column N
- begin scalar M;
- M := ChannelPosn Chn;
- if N < M then
- << ChannelTerPri Chn;
- M := 0 >>;
- ChannelSpaces(Chn, N - M);
- end;
- lisp procedure TAB N; %. Spaces to column N
- ChannelTAB(OUT!*, N);
- if_system(Dec20, <<
- lap '((!*entry FileP expr 1)
- (!*MOVE (REG 1) (REG 2))
- (hrli 2 8#010700) % make a byte pointer
- (hrlzi 1 2#001000000000000001) % gj%old + gj%sht
- (gtjfn)
- (jrst NotFile)
- (rljfn) % release it
- (jfcl)
- (!*MOVE (QUOTE T) (REG 1))
- (!*EXIT 0)
- NotFile
- (!*MOVE (QUOTE NIL) (REG 1))
- (!*EXIT 0)
- ); >>, <<
- lisp procedure FileP F; %. is F an existing file?
- %
- % This could be done more efficiently in a much more system-dependent way,
- % but efficiency probably doesn't matter too much here.
- %
- if PairP(F := ErrorSet(list('OPEN, MkQuote F, '(QUOTE INPUT)), NIL, NIL))
- then
- << Close car F;
- T >>
- else NIL; >>);
- % This doesn't belong anywhere and will be eliminated soon
- lisp procedure PutC(Name, Ind, Exp); %. Used by RLISP to define SMACROs
- << put(Name, Ind, Exp);
- Name >>;
- LoadTime <<
- PutD('Spaces2, 'EXPR, cdr GetD 'TAB); % For compatibility
- PutD('ChannelSpaces2, 'EXPR, cdr GetD 'ChannelTAB);
- >>;
- END;
|