LEX 'SWAPLEX' TITLE - BASIC Utilities, J.J. Moreau <86/02/16> * * 64 Ave de la paix * 93150 le Blanc-Mesnil * ID #E1 PARIS-ROM MSG 0 POLL 0 ENTRY Swap CHAR #D programmable anywhere KEY 'SWAP' TOKEN 71 ARRYCK EQU #0366A AVE=D1 EQU #18BB8 COMCK+ EQU #032AE D1MSTK EQU #1954E DEST EQU #0F7B0 DSTRDC EQU #05280 EOLCK EQU #02A7E EXPEX- EQU #0F178 EXPEXC EQU #0F186 IVVARe EQU #02E66 NTOKEN EQU #0493B NXTSTM EQU #08A48 POPMTH EQU #1B3DB POPUPD EQU #08F3E PSHUPD EQU #08F0D RESPTR EQU #03172 STORE EQU #0F5F8 SVTRC EQU #0FA35 SYNTXe EQU #02E2B VARP EQU #0350E ENDTXT * * Compile the command SWAP: * tSWAP tVAR VAR tCOMMA tVAR VAR * that is to say SWAP var1,var2 * Ex: SWAP Z9$ , C0 , A$ , U5(I) * Swapp GOSUB Swap+ compile 1 variable GOSBVL NTOKEN find token following above variable GOSBVL COMCK+ is it a comma? GONC Syntxe no, error-out GOSUB Swap+ yes, compile 2nd variable GOSBVL EOLCK is if followed by tEOL, tTHEN or t! ? GONC Syntxe no GOVLNG RESPTR yes, everythin is fine Swap+ ST=0 8 GOSBVL VARP GOC Swap+5 ST=1 8 Swap+5 ?ST=0 2 RTNYES GOSBVL ARRYCK ?ST=0 8 RTNYES B=B-1 A ?B=0 P RTNYES Syntxe GOVLNG SYNTXe * Decompile a series of variables: * tVAR VAR1 tCOMMA tVAR VAR2 tCOMMA ...... tCOMMA tVAR VARN * (VAR1,VAR2,.......,VARN) * Example: [DIM] A,B,C2$,....,U9$(10) Swapd GOVLNG DSTRDC decompile variable list REL(5) Swapd REL(5) Swapp Swap GOSUB Swapt Initialize the TRACE VARS mode GOSBVL EXPEX- put the value of the first variable on the stack * resets AVMEME GOSBVL DEST save the addresses for the second variable D0=D0+ 2 jump over tCOMMA AD0EX save input pointer R0=A GOSBVL PSHUPD in R0 and in the BASIC subroutine return stack A=R0 restore pointer D0=A GOSBVL EXPEXC evaluate the second variable * Note that EXPEX- does not preserve whatever might be found under AVEMEME. * It considers that AVEMEME=FORSTK. * EXPEXC, on the other hand does not touch anything between AVMEME & FORSTK, * which is quite useful if you want to preserve stuff pulled on the stack. * note that both routines redefine AVMEME as required GOSBVL STORE store var2 into var1 (see RECALL, IDS vol.3) GOSBVL POPUPD reclaim the output pointer C=D A D0=C * * remember that EXPEX- left on the stack information relative to var1, and * EXPEXC those about var2 & above. Since we are no longer interested, we will * get rid of them by incrementing AVMEME * GOSUB Swaps destroy the data we no longer need GOSBVL AVE=D1 and adjust AVMEME GOSUB Swapt initialize the TRACE VARS mode GOSBVL EXPEXC recall that D0 @ output pointer * * this last line seems useless, since it puts on the stack the value of the * 2nd var, which we just got rid of. However, EXPEXC also initialize the CPU * registers for DEST. * replacing this call to EXPEXC with a call to RECALL or ADDRSS should help * speed-up SWAP GOSBVL DEST prepare for storing var2 GOSUB Swaps get rid of the useless data once and for all A=DAT1 W initialize A(W) GOSBVL STORE GOVLNG NXTSTM Swaps GOSBVL D1MSTK D1 @ AVMEME GOVLNG POPMTH jump over the first item on the stack Swapt ?ST=0 15 TRACE mode? RTNYES no... GOVLNG SVTRC yes, lets go do more work * * The operating system has a small number of very powerful routines for * handling variables. That's why SWAPLEX is only about 100 bytes long. * * SWAP A,B replaces C=A @ A=B @ B=C * SWAP A$,B$ also replaces the equivalent code for strings * the parse routine will allow SWAP A,B$. However, at run time, this will * cause a DATA TYPE error. * * SWAP can handle INTEGER, SHORT, REAL, COMPLEX, COMPLEX SHORT * variables, as well as strings, array variables & string array variables. * >>> when you execute SWAP VAR1,VAR2 you will automatically redimension * VAR2 to the same size as VAR1 * VAR2 dimensions must be greater or equal to that of VAR1... * * typical application is sorting data: * FOR I=1 TO N@FOR J=I+1 TO N * IF A$(I)>A$(J) THEN SWAP A$(I),A$(J) * NEXT J @ NEXT I * * SWAP is rougly 10% faster with numeric variables, and about 30% faster with * string variables with 100 bytes length. (Disapointing!)