antoine-source/appleworksgs/Macros/m16.bob

1 line
10 KiB
Plaintext
Executable File
Raw Blame History

;..............................................................................;
;
; 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 = '<27>') GOTO .dole
IF (&test = '<27>') GOTO .doge
IF (&test = '<27>') GOTO .done
macerr 'IF_: unrecognized comparison <20>',&test,'<27> (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