;..............................................................................; ; ; If - expression, test, value, goto ; ; This macro implements an if construct. The expression will be evaluated, ; its value compared to the given value, and if the test succeeds execution ; continues at 'goto'. Otherwise execution will continue until an EndWhile ; macro is encountered. ; ; The expression may be a register, simple variable, or complex expression. ; If the 'goto' label is preceeded by a '!' then it is assumed that a long ; branch is necessary. ; ; Sample calls: ; ; If X,'<>',#50,DoneIf - if x<>50 then goto DoneIf ; If Var1,'=',Var2,!DoneIf - if var1=var2 then branch long to DoneIf ; If '(Var1.+Var2)','>',Var3,Quit - if var1+var2>var3 then goto Quit ; ; The following test conditions are supported and must be quoted: ; ; '=', '>', '>=', '<', '<=', '<>' ; ; A complex expression must be quoted and placed in paranthesis to work ; correctly. ; ;..............................................................................; MACRO &lab IF_ &exp,&test,&value,&goto &lab ; lclc &cc lclc &first lclc &newexp lclc &WorkAroundApplesBuggyAssembler &newexp setc &exp &first setc &substr(&newexp,1,1) IF (&newexp = 'x') or (&newexp = 'y') or (&newexp = 'a') GOTO .register IF (&newexp = 'X') or (&newexp = 'Y') or (&newexp = 'A') GOTO .register IF (&first = '(') GOTO .expression .simplevar lda &newexp cmp &value GOTO .dotest mexit .expression &newexp setc &substr(&newexp,2,&len(&newexp)-2) eval &newexp cmp &value GOTO .dotest .register &WorkAroundApplesBuggyAssembler setc &concat('cp',&newexp) .; cp&newexp &value **SIGH!!!!!!** &WorkAroundApplesBuggyAssembler &value GOTO .dotest .dotest IF (&test = '=') GOTO .doeq IF (&test = '<') GOTO .dolt IF (&test = '>=') GOTO .doge IF (&test = '<>') GOTO .done IF (&test = '<=') GOTO .dole IF (&test = '>') GOTO .dogt IF (&test = '²') GOTO .dole IF (&test = '³') GOTO .doge IF (&test = '­') GOTO .done macerr 'IF_: unrecognized comparison Ò',&test,'Ó (make sure it's not in quotes).' mexit .doeq &cc setc 'eq' GOTO .goto .dolt &cc setc 'lt' GOTO .goto .doge &cc setc 'ge' GOTO .goto .done &cc setc 'ne' GOTO .goto .dole &cc setc 'le' GOTO .goto .dogt &cc setc 'gt' GOTO .goto mexit .goto jump &cc,&goto mexit MEND ;..............................................................................; ; ; jump - Branch on condition code to short/long label ; ; Generic jump macro. If label starts with ! will do long jump else short. ; ;..............................................................................; MACRO &lab jump &cc,&label &lab ; lclc &a &a setc &substr(&label,1,1) IF (&a = '!') GOTO .long b&cc &label mexit .long &a setc &substr(&label,2,&len(&label)-1) j&cc &a mexit MEND ;..............................................................................; ; ; While - expression, test, value, resume ; ; This macro implements a while construct. The expression will be evaluated, ; its value compared to the given value, and if the test fails execution will ; continue at 'resume'. Otherwise execution will continue until an EndWhile ; macro is encountered. ; ; The expression may be a register, simple variable, or complex expression. ; If the 'resume' label is preceeded by a '!' then it is assumed that a long ; branch is necessary. ; ; Sample calls: ; ; While X,'<>',#50 - loop until x register = 50 ; While Var1,'=',Var2 - loop until var1<>var2, then jump long ; While '(Var1.+Var2)','>',Var3 - loop until var1+var2<=var3 ; ; The following test conditions are supported and must be quoted: ; ; '=', '>', '>=', '<', '<=', '<>' ; ; A complex expression must be quoted and placed in paranthesis to work ; correctly. ; ; Note: Up to 10 levels of local while nesting are supported. ; ;..............................................................................; MACRO &lab while_ &exp,&test,&value &lab ; lclc &long .; IF (&nbr(&wcnt) > 0) GOTO .past gbla &wcnt gblc &while[10] gbla &wnum[10] IF (&wcnt = 10) THEN macerr 'Too many levels of nested While_'s (max. 10).' mexit ENDIF .past &wcnt seta &wcnt+1 &while[&wcnt] setc &concat('~A',&i2s(&sysindex)) &wnum[&wcnt] seta &wnum[&wcnt]+1 ~A&i2s(&sysindex) ; if_ &exp,&test,&value,&concat('~B',&i2s(&sysindex)) brl &concat('~W',&concat(&i2s(&wcnt),&i2s(&wnum[&wcnt]))) ~B&i2s(&sysindex) ; mexit MEND ;..............................................................................; ; ; EndWhile ; ; This macro will return control back to the latest while loop encountered. ;..............................................................................; MACRO &lab endwhile_ &lab ; gbla &wcnt gblc &while[10] gbla &wnum[10] IF (&wcnt = 0) THEN macerr 'Unexpected EndWhile_.' mexit ENDIF brl &while[&wcnt] ~W&i2s(&wcnt)&i2s(&wnum[&wcnt]) ; &wcnt seta &wcnt-1 mexit MEND ;..............................................................................; ; ; Repeat ; ; This macro will set a label to the start of a repeat/until loop for the ; current lexical level. ;..............................................................................; MACRO &lab repeat_ &lab ; .; IF (&nbr(&rcnt) > 0) GOTO .past gbla &rcnt gblc &repeat[10] .past &rcnt seta &rcnt+1 &repeat[&rcnt] setc &concat('~A',&i2s(&sysindex)) ~A&i2s(&sysindex) ; mexit MEND ;..............................................................................; ; ; Until &exp,&test,&value ; ; If the expression evaluates to true then exit else return to the ; last seen repeat. ;..............................................................................; MACRO &lab until_ &exp,&test,&value &lab ; gbla &rcnt gblc &repeat[10] if_ &exp,&test,&value,&concat('~B',&i2s(&sysindex)) brl &repeat[&rcnt] ~B&i2s(&sysindex) ; &rcnt seta &rcnt-1 mexit MEND ;..............................................................................; ; ; FOR variable, initial value, final value, step size ; ; This macros implements a primitive FOR type construct. The specified ; variable may be either a register ('X','Y','A') or a memory location. The ; variable is currently assumed to be of word size. It will get loaded with ; the initial value specified. Execution will loop between the FOR and NEXT ; macros until the variable exceeds the final value, each pass through the ; loop the variable or register as the case may be is offset by the given ; step size. Step size may be positive or negative but must be word size. ;..............................................................................; MACRO &lab for_ &var,&init,&final,&step &lab ; .; IF (&nbr(&fcnt) > 0) GOTO .past gbla &fcnt gblc &for[10] gblc &forstep[10] gblc &forfinal[10] gblc &forvar[10] .past &fcnt seta &fcnt+1 &for[&fcnt] setc &concat('~A',&i2s(&sysindex)) &forstep[&fcnt] setc &step &forfinal[&fcnt] setc &final IF (&var = 'x') or (&var = 'X') GOTO .initx IF (&var = 'y') or (&var = 'Y') GOTO .inity lda &init &forvar[&fcnt] setc 'A' IF (&var = 'a') or (&var = 'A') GOTO .quit sta &var &forvar[&fcnt] setc &var GOTO .quit .initx ldx &init &forvar[&fcnt] setc 'X' GOTO .quit .inity ldy &init &forvar[&fcnt] setc 'Y' .quit ~A&i2s(&sysindex) ; mexit MEND ;..............................................................................; ; ; NEXT ; ; See description under FOR. ; ;..............................................................................; MACRO &lab next_ &lab ; gbla &fcnt gblc &for[10] gblc &forstep[10] gblc &forfinal[10] gblc &forvar[10] IF (&forvar[&fcnt] = 'A') GOTO .nextA IF (&forvar[&fcnt] = 'X') GOTO .nextX IF (&forvar[&fcnt] = 'Y') GOTO .nextY lda &forvar[&fcnt] GOTO .nextA .nextX txa GOTO .nextA .nextY tya .nextA IF (&forstep[&fcnt] = '#1') GOTO .incA IF (&forstep[&fcnt] = '#-1') GOTO .decA clc adc &forstep[&fcnt] GOTO .donextA .decA dec a GOTO .donextA .incA inc a .donextA IF (&forvar[&fcnt] = 'X') GOTO .setx IF (&forvar[&fcnt] = 'Y') GOTO .sety IF (&forvar[&fcnt] = 'A') GOTO .checkit sta &forvar[&fcnt] GOTO .checkit .setx tax GOTO .checkit .sety tay GOTO .checkit .checkit cmp &forfinal[&fcnt] bgt ~F&i2s(&sysindex) brl &for[&fcnt] .quit ~F&i2s(&sysindex) ; &fcnt seta &fcnt-1 mexit MEND