From 6c86838d1853599b940422577bc5b675d3696fb2 Mon Sep 17 00:00:00 2001 From: rmkaplan Date: Wed, 29 Jan 2025 22:57:37 -0800 Subject: [PATCH] Macros for multi-level alists --- lispusers/MULTI-ALIST | 239 ++++++++++++++++++++++++++++++++++++ lispusers/MULTI-ALIST.LCOM | Bin 0 -> 5016 bytes lispusers/MULTI-ALIST.TEDIT | Bin 0 -> 10436 bytes 3 files changed, 239 insertions(+) create mode 100644 lispusers/MULTI-ALIST create mode 100644 lispusers/MULTI-ALIST.LCOM create mode 100644 lispusers/MULTI-ALIST.TEDIT diff --git a/lispusers/MULTI-ALIST b/lispusers/MULTI-ALIST new file mode 100644 index 00000000..f07050de --- /dev/null +++ b/lispusers/MULTI-ALIST @@ -0,0 +1,239 @@ +(DEFINE-FILE-INFO PACKAGE "INTERLISP" READTABLE "INTERLISP" BASE 10) + +(FILECREATED "29-Jan-2025 19:34:13" {WMEDLEY}MULTI-ALIST.;15 12223 + + :EDIT-BY rmk + + :CHANGES-TO (FNS MAPMULTI) + + :PREVIOUS-DATE "25-Jan-2025 15:04:13" {WMEDLEY}MULTI-ALIST.;14) + + +(PRETTYCOMPRINT MULTI-ALISTCOMS) + +(RPAQQ MULTI-ALISTCOMS + ((MACROS GETMULTI PUTMULTI PUTMULTI-D PUTMULTI-NEW PUTMULTI-COUNT PUTMULTI-SUM REMOVEMULTI + REMOVEMULTIALL) + (MACROS FGETMULTI FPUTMULTI FPUTMULTI-D FPUTMULTI-NEW) + (FNS MAPMULTI MAPMULTI1 COLLECTMULTI) + (FNS GETMULTI.EXPAND PUTMULTI.EXPAND REMOVEMULTI.EXPAND) + (MACROS ADDTOMULTI) + (FNS ADDTOMULTI1) + (LOCALVARS . T))) +(DECLARE%: EVAL@COMPILE + +(PUTPROPS GETMULTI MACRO (ARGS (GETMULTI.EXPAND 'SASSOC ARGS))) + +(PUTPROPS PUTMULTI MACRO (ARGS (PUTMULTI.EXPAND 'SASSOC ARGS))) + +(PUTPROPS PUTMULTI-D MACRO (ARGS (PUTMULTI.EXPAND 'SASSOC ARGS NIL T))) + +(PUTPROPS PUTMULTI-NEW MACRO (ARGS (PUTMULTI.EXPAND 'SASSOC ARGS))) + +(PUTPROPS PUTMULTI-COUNT MACRO (ARGS (PUTMULTI.EXPAND 'SASSOC (APPEND ARGS '(1)) + NIL NIL T))) + +(PUTPROPS PUTMULTI-SUM MACRO (ARGS (PUTMULTI.EXPAND 'SASSOC ARGS NIL NIL T))) + +(PUTPROPS REMOVEMULTI MACRO (ARGS (REMOVEMULTI.EXPAND ARGS))) + +(PUTPROPS REMOVEMULTIALL MACRO (ARGS (REMOVEMULTI.EXPAND ARGS T))) +) +(DECLARE%: EVAL@COMPILE + +(PUTPROPS FGETMULTI MACRO (ARGS (GETMULTI.EXPAND 'FASSOC ARGS))) + +(PUTPROPS FPUTMULTI MACRO (ARGS (PUTMULTI.EXPAND 'FASSOC ARGS))) + +(PUTPROPS FPUTMULTI-D MACRO (ARGS (PUTMULTI.EXPAND 'FASSOC ARGS NIL T))) + +(PUTPROPS FPUTMULTI-NEW MACRO (ARGS (PUTMULTI.EXPAND 'FASSOC ARGS))) +) +(DEFINEQ + +(MAPMULTI + [LAMBDA (MULTIALIST MAPFN) (* ; "Edited 29-Jan-2025 19:33 by rmk") + (* ; "Edited 25-Jan-2025 14:51 by rmk") + (* ; "Edited 16-Jan-2025 10:32 by rmk") + (* ; "Edited 6-Jan-2020 10:15 by rmk:") + + (* ;; "MAPMULTI applies a mapping function of N args to each item in an N-way item in the multi-alist at MULTIALIST. If an item C is inserted by (PUTMULTI FOO A B C), then MAPFN should be a 3 argument function and it will be applied to A B C. The caller is responsible for making sure the arities of the index and the mapfn correspond.") + + (DECLARE (SPECVARS MAPFN)) + (LET ($$LISTFORARGS$$) + (DECLARE (SPECVARS $$LISTFORARGS$$)) + (SETQ $$LISTFORARGS$$ (FOR I FROM 1 TO (NARGS MAPFN) COLLECT NIL)) + (MAPMULTI1 MULTIALIST $$LISTFORARGS$$ (NARGS MAPFN]) + +(MAPMULTI1 + [LAMBDA (SUBALIST ARGLIST NREMAINING) (* ; "Edited 25-Jan-2025 15:03 by rmk") + (* ; "Edited 22-Jan-2025 23:42 by rmk") + (* ; "Edited 16-Jan-2025 10:29 by rmk") + (* ; "Edited 6-Jan-2020 10:21 by rmk:") + (DECLARE (USEDFREE $$LISTFORARGS$$ MAPFN)) + (if [AND (IGREATERP NREMAINING 1) + (LISTP (CAR (LISTP SUBALIST] + then + (* ;; "Still a list of alists.") + + (for SI in SUBALIST do (RPLACA ARGLIST (CAR SI)) + (MAPMULTI1 (CDR SI) + (CDR ARGLIST) + (SUB1 NREMAINING))) + else (for ITEM inside SUBALIST do (RPLACA ARGLIST ITEM) + (APPLY MAPFN $$LISTFORARGS$$]) + +(COLLECTMULTI + [LAMBDA (MULTIALIST MAPFN) (* ; "Edited 25-Jan-2025 15:00 by rmk") + (* ; "Edited 22-Jan-2025 23:44 by rmk") + (* ; "Edited 6-Jan-2020 10:15 by rmk:") + (LET ($$COLLECT) + (DECLARE (SPECVARS $$COLLECT)) + (MAPMULTI MULTIALIST MAPFN) + $$COLLECT]) +) +(DEFINEQ + +(GETMULTI.EXPAND + [LAMBDA (ASSOCFN ARGS) (* ; "Edited 16-Jan-2025 10:27 by rmk") + (* ; "Edited 19-Jul-2020 00:38 by rmk:") + (* ; "Edited 22-Mar-2020 13:21 by rmk:") + (* ; "Edited 27-Feb-2020 13:44 by rmk:") + (* ; "Edited 30-Dec-2019 20:50 by rmk:") + + (* ;; "If SUM, returns the value after the last argument, paired with PUTMULTISUM") + + (IF (CDR ARGS) + THEN `(LET ($$CELL$$) + (DECLARE (LOCALVARS $$CELL$$)) + ,@[FOR ATAIL (HEAD _ (CAR ARGS)) ON (CDR ARGS) + COLLECT (PROG1 `[SETQ $$CELL$$ (CDR (,ASSOCFN ,(CAR ATAIL) + ,HEAD] + (SETQ HEAD '$$CELL$$))] + $$CELL$$) + ELSE (CAR ARGS]) + +(PUTMULTI.EXPAND + [LAMBDA (ASSOCFN ARGS ALLOWREPEATS SINGLEVALUE SUM) (* ; "Edited 23-Jan-2025 09:40 by rmk") + (* ; "Edited 16-Jan-2025 10:18 by rmk") + (* ; "Edited 17-Aug-2020 14:09 by rmk:") + + (* ;; "If ALLOWREPEATS, doesn't test (MEMBER) for preexisting values, just accumulates") + + (* ;; "If SINGLEVALUE, new value smashes out old") + + (* ;; "For SUM, the last argument is the increment to be added to the current value, and the incremented value is returned for PUTMULTISUM and for GETMULT") + + (* ;; "") + + (* ;; "We get the setf method so that any expressions in the form will be evaluated only once.") + + (CL:MULTIPLE-VALUE-BIND + (TEMPVARS VALFORMS STOREVARS STOREFORM ACCESSFORM) + (CL:GET-SETF-METHOD (CAR ARGS)) + (CL:IF (CDR ARGS) + `(LET* + ,(FOR VF IN VALFORMS AS TV IN TEMPVARS COLLECT (LIST TV VF)) + (DECLARE (LOCALVARS ,@TEMPVARS)) + (LET + ($$ARG1$$ $$ARG2$$) + (DECLARE (LOCALVARS $$ARG1$$ $$ARG2$$)) + ,@[FOR ATAIL (HEAD _ ACCESSFORM) ON ARGS WHILE (CDR ATAIL) + JOIN + (IF (AND SUM (NULL (CDDR ATAIL))) + THEN (POP ATAIL) + `[(CL:UNLESS ,HEAD (RPLACD $$ARG1$$ 0)) + (SETQ $$ARG2$$ (ADD ,HEAD ,(CAR ATAIL] + ELSE + (PROG1 `[(SETQ $$ARG2$$ ,(CADR ATAIL)) + ,(IF (CDDR ATAIL) + THEN `[SETQ $$ARG1$$ (OR (,ASSOCFN $$ARG2$$ ,HEAD) + (CAR (CL:PUSH (CONS $$ARG2$$) + ,HEAD] + ELSEIF ALLOWREPEATS + THEN `(push ,HEAD $$ARG2$$) + ELSEIF SINGLEVALUE + THEN `(RPLACD $$ARG2$$) + ELSE `(OR (MEMBER $$ARG2$$ ,HEAD) + (push ,HEAD $$ARG2$$] + (SETQ HEAD '(CDR $$ARG1$$)))] + $$ARG2$$)) + (CAR ARGS))]) + +(REMOVEMULTI.EXPAND + [LAMBDA (ARGS ALLFLAG) (* ; "Edited 16-Jan-2025 10:34 by rmk") + (* ; "Edited 17-Aug-2020 15:12 by rmk:") + (* ; "Edited 17-May-2020 17:25 by rmk:") + (* ; "Edited 14-Feb-2020 11:24 by rmk:") + (* ; "Edited 25-Dec-2019 09:57 by rmk:") + + (* ;; "If ALLFLAG, then all data after the last of ARGS, if any, is removed. That is, if there are 3 keys to the index, and REMOVEMULTIALL is invoked with 2 keys, then it's as if no entries were made for any of the third keys after those first two. In the case of REMOVEMULTIALL, it returns the previous tail.") + + (* ;; "No point in distinguishing FASSOC from SASSOC here.") + + (CL:MULTIPLE-VALUE-BIND + (TEMPVARS VALFORMS STOREVARS STOREFORM ACCESSFORM) + (CL:GET-SETF-METHOD (CAR ARGS)) + (CL:IF (CDR ARGS) + `(LET* + ,(FOR VF IN VALFORMS AS TV IN TEMPVARS COLLECT (LIST TV VF)) + (DECLARE (LOCALVARS ,@TEMPVARS)) + (LET + ($$ARG1$$ $$ARG2$$) + (DECLARE (LOCALVARS $$ARG1$$ $$ARG2$$)) + ,@[FOR ATAIL (HEAD _ ACCESSFORM) ON ARGS WHILE (CDR ATAIL) + JOIN (PROG1 `[(SETQ $$ARG2$$ ,(CADR ATAIL)) + ,(IF (CDDR ATAIL) + THEN `(SETQ $$ARG1$$ (SASSOC $$ARG2$$ ,HEAD)) + ELSEIF ALLFLAG + THEN `(CL:WHEN (SETQ $$ARG1$$ (SASSOC $$ARG2$$ ,HEAD)) + (SETQ $$ARG2$$ (CDR $$ARG1$$)) + (RPLACD $$ARG1$$)) + ELSE `(AND (SETQ $$ARG2$$ (MEMBER $$ARG2$$ ,HEAD)) + (RPLACD $$ARG1$$ (DREMOVE (SETQ $$ARG2$$ (CAR $$ARG2$$)) + ,HEAD] + (SETQ HEAD '(CDR $$ARG1$$)))] + $$ARG2$$)) + (CAR ARGS))]) +) +(DECLARE%: EVAL@COMPILE + +(PUTPROPS ADDTOMULTI MACRO [ARGS (CL:MULTIPLE-VALUE-BIND + (TEMPVARS VALFORMS STOREVARS STOREFORM ACCESSFORM) + (CL:GET-SETF-METHOD (CAR ARGS)) + `(LET* [,@(FOR VF IN VALFORMS AS TV IN TEMPVARS + COLLECT (LIST TV VF)) + ($$KEYS ,(CADR ARGS] + (DECLARE (LOCALVARS $$KEYS ,@TEMPVARS)) + (COND + [(LISTP $$KEYS) + (CL:UNLESS (SASSOC (CAR $$KEYS) + ,ACCESSFORM) + (CL:PUSH (CONS (CAR $$KEYS)) + ,ACCESSFORM)) + (ADDTOMULTI1 ,ACCESSFORM $$KEYS ,(CADDR ARGS] + (T (CL:SETF ,ACCESSFORM ,(CADDR ARGS]) +) +(DEFINEQ + +(ADDTOMULTI1 + [LAMBDA (PLACE KEYS VAL) (* ; "Edited 22-Jan-2025 23:47 by rmk") + (* ; "Edited 17-Aug-2020 15:05 by rmk:") + + (* ;; "This allows the keys to be provided in a single list rather than as separate arguments.") + + (FOR I (P _ PLACE) IN KEYS DO [SETQ P (OR (SASSOC I P) + (CAR (PUSH (CDR P) + (CONS I] FINALLY (PUSH (CDR P) + VAL)) + VAL]) +) +(DECLARE%: DOEVAL@COMPILE DONTCOPY + +(LOCALVARS . T) +) +(DECLARE%: DONTCOPY + (FILEMAP (NIL (1837 4449 (MAPMULTI 1847 . 2915) (MAPMULTI1 2917 . 3974) (COLLECTMULTI 3976 . 4447)) ( +4450 10311 (GETMULTI.EXPAND 4460 . 5581) (PUTMULTI.EXPAND 5583 . 7995) (REMOVEMULTI.EXPAND 7997 . +10309)) (11461 12146 (ADDTOMULTI1 11471 . 12144))))) +STOP diff --git a/lispusers/MULTI-ALIST.LCOM b/lispusers/MULTI-ALIST.LCOM new file mode 100644 index 0000000000000000000000000000000000000000..d4cd756cab62d054aec4ec7821d8103a67e9d4e4 GIT binary patch literal 5016 zcmcIoOK%(373K`9k!*wnc+iZ1A~{tp*YgK%o)m->p(~%BNUXx zhTQ@MimtloqN@T$R$b)}lvXOBt{wAFbW;?_uIReWBFLugcket&%dHeN0z}?9_nzlH z-#KTfjLfm+nvJn#n+?kyd-SHyj9s>EQq6Khb81_GU!ymtCL4upXs?lnEHFuJ)=MRY zOE7ROG)Gj^dX1fTK5A%9txamLuebWDUL&RU-n|d+AANB5knVj%HTwBY#~j(_{x9D8 z;OOD~pFX_%;Nf*=W`|aTL2bDCBeh+pQcdgTgmwBY$ZOW<-3ND5X?K5i|G~rW_Q_$s z;HM*qAJ1%?^1Pdyn>9Lo=O<8qrqEWcel9o8VK%9nrs>o-M^@Mv?$d)0kEw4=n7eHT zjnFHRGIoR1+&cCBskvu)v!F3T01>}-&gFK$8O85^D{j?GX$<r~kKcA+3w$_4gv0e{C8?b43*#UHNhZrmD7BHAl_ zqx_kD`l>Up-g&Zf{O8+?&z);e7he_>T~D1-N!ucqYoPeMUUDtFq+}+ll-Q_|J2f3< zxt6;PW5C5NgsH)77#lt&Ei#hEq_4XG!yQ>J6o<$EI8g?NMX7jFTT~CFid0||>GkDA zX7cd(FT(UIa`E)<^YWllktT;HUmX@dc|8B6^mrowky)=Vr$LGPw_N z_ykbFg1|FyYmj)vuZIdlh!0m`47c4S(} z7YEr9AdPHukJ&R5S;K7GyE!#|)TSUxuGQd4zeZkMVv@*s@lj#ln(&OcEj`(hWm$TP z$bRxjdOwP-wObjM+~R5RSJJ_2OQ(1`@h)#`Lt==b&8ttyh*my^ixM zH^IYQElb{OSR8CDz4GZ5Z)09PC?8y2y7Dte{%r9ZZ{ylQdAazfcX@R37Np3ZcJK+3 zP~{4FvEIxU*DFh0c>MpU@Nu>WZn4K@opdw0SPjId%lWb$p+nF>pH~;X;qRhjVq>vs zd>k#lm$9sgNz9Dx5yzj2e1xYk zf!rE595bAFJQwwLhtNyrq_;XqA(RpgS*f>xOw$>fQ_}SgdH7OW(K)Rr6!^1Xf|AuH zgH6#k+8M9b>2U_F(~4*+EqY*Nj!ywshCOFvYaocCE zZ3d{08b<}8*kq~S=~4m+7>@1l3)FNwq;PNvkual9I^YH*MH=v^^+=ieHZw-4UQPwT zvO`)AXhLu~!V*T6(^fdSm(6;;gpdpHB`14OnAo-gRvh3wsmwZUbz`-w^b$(Fw`Yn1 zc}8us?Xk_ad3i(c0QRMK0Z)1G-{3hA@Vx%D;W_w!!ZS<$6@@huyrJFBA-M_yhP={3e+Nf*xXcXNm>CHS)dOeC0l7lPB4j>IJ zG6Li(*t%%?yjf_SHu0{fwPI-;#+nY;iMEGjUJLR*;?i0iS~n-AOPb2(geY%;#I2OG z8Pj=Msy)y}bL#f8(`py3gi|j7PGEl>oG3Ah5R;mr@amF0A-T0SI^lC?@({1D0va}d zGoVDd3O#|z{8)w_ik7)+?(>$(>x#*zjm=`AP-KJ3hCC^rmaL&ASKkq~#sywMU0d-j6tTtxFn*3rs99rxkN6Y6lKcl^Gm0w! literal 0 HcmV?d00001 diff --git a/lispusers/MULTI-ALIST.TEDIT b/lispusers/MULTI-ALIST.TEDIT new file mode 100644 index 0000000000000000000000000000000000000000..fa2ba6f5729c73046f1ffe58d38b948cbcd64c71 GIT binary patch literal 10436 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 B56%Dp literal 0 HcmV?d00001