Skip to content

Commit df4639f

Browse files
mbruknerkcozens
authored andcommitted
feat: add STEP support for FOR loops
Port STEP functionality from Kevin Cozens' patch. FOR loops now support an optional STEP value (e.g., FOR i = 0 TO 100 STEP 5). Stack frame grows from 18 to 22 bytes to hold the 4-byte step value. STEP token uses sort_last to get ID $e0, preserving existing TEXT ($de) and TO ($df) token assignments. Rename simple.asm to addsub.asm so AddTopTwoStack/SubTopTwoStack sort before scompare/shifts in the auto-generated build, keeping them in main block 1 ($8000-$9FFF) where they remain mapped when modules are banked in. Tail-call optimizations in for.asm and clear.asm reclaim 10 bytes. Co-authored-by: Kevin Cozens <kevin@ve3syb.ca>
1 parent 7d636fa commit df4639f

9 files changed

Lines changed: 97 additions & 53 deletions

File tree

modules/tokeniser/__kwdtext.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ KeywordSet0:
9999
.text 6,$d7,"SPRITE" ; $dd SPRITE
100100
.text 4,$45,"TEXT" ; $de TEXT
101101
.text 2,$a3,"TO" ; $df TO
102+
.text 4,$3c,"STEP" ; $e0 STEP
102103
.text $FF
103104
KeywordSet1:
104105
.text 0,$65,"" ; $80 !0:EOF

source/common/commands/for.asm

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
; ************************************************************************************************
1111
; ************************************************************************************************
1212
;
13-
; +16 Step (1 or 255)
14-
; +12..+15 Terminal value ((in 2's complement format.)
13+
; +16..+19 Step value (in 2's complement format.)
14+
; +12..+15 Terminal value (in 2's complement format.)
1515
; +8..+11 Value of index variable (in 2's complement format.)
1616
; +6..+7 Address of index variable
1717
; +1..5 Loop back address
@@ -27,8 +27,8 @@
2727
; ************************************************************************************************
2828

2929
ForCommand: ;; [for]
30-
lda #STK_FOR+9 ; allocate 18 bytes on the return stack (see above).
31-
jsr StackOpen
30+
lda #STK_FOR+11 ; allocate 22 bytes on the return stack (see above).
31+
jsr StackOpen
3232
;
3333
; Get an integer reference to Stack[0] - this is the loop variable.
3434
;
@@ -40,19 +40,19 @@ ForCommand: ;; [for]
4040
;
4141
; = character
4242
;
43-
lda #KWD_EQUAL ; =
43+
lda #KWD_EQUAL ; =
4444
jsr CheckNextA
4545
;
4646
; The Initial value to Stack[1]
4747
;
4848
inx
4949
jsr EvaluateInteger ; <from> in +1
5050
;
51-
; TO or DOWNTO put on stack
51+
; Save TO or DOWNTO in temporary memory
5252
;
5353
.cget ; next should be DOWNTO or TO
54+
pha ; save keyword for later
5455
iny ; consume it
55-
pha ; save on stack for later
5656
cmp #KWD_DOWNTO
5757
beq _FCNoSyntax
5858
cmp #KWD_TO
@@ -62,23 +62,28 @@ _FCNoSyntax:
6262
; The Terminal value to Stack[2]
6363
;
6464
inx
65-
jsr EvaluateInteger
65+
jsr EvaluateInteger
6666
;
67-
; Now set up the FOR Structure, starting with the code position
68-
;
69-
jsr STKSaveCodePosition ; save loop back position
70-
;
71-
; Now the TO or DOWNTO
67+
; Now set the +1 or -1 default step for the TO or DOWNTO
7268
;
7369
pla ; restore DOWNTO or TO
74-
phy ; save Y on the stack
7570
eor #KWD_DOWNTO ; 0 if DOWNTO, #0 if TO
7671
beq _FCNotDownTo
77-
lda #2
72+
lda #2
7873
_FCNotDownTo: ; 0 if DOWNTO 2 if TO
79-
dec a ; 255 if DOWNTO, 1 if TO
74+
phy ; save current position
8075
ldy #16
81-
sta (basicStack),y ; copy that out to the Basic Stack.
76+
dec a ; 255 if DOWNTO, 1 if TO
77+
sta (basicStack),y ; store low byte of step
78+
bmi _FCNegativeStep
79+
lda #0 ; next bytes are 0 for a step of 1
80+
_FCNegativeStep:
81+
iny
82+
sta (basicStack),y ; store rest of step in Basic Stack
83+
iny
84+
sta (basicStack),y
85+
iny
86+
sta (basicStack),y
8287
;
8388
; Copy the reference where the index goes.
8489
;
@@ -98,11 +103,31 @@ _FCNotDownTo: ; 0 if DOWNTO 2 if TO
98103
ldx #2
99104
jsr FCIntegerToStack
100105
;
101-
; Now copy the current value to the index reference, in standard format.
106+
; Handle optional STEP value
102107
;
103-
jsr CopyIndexToReference
104108
ply ; restore position
105-
rts
109+
.cget ; check for optional STEP keyword
110+
cmp #KWD_STEP
111+
bne _FCNoStep
112+
iny ; consume STEP
113+
;
114+
ldx #0
115+
jsr EvaluateInteger ; get the step value
116+
;
117+
phy ; save the new position
118+
ldy #16 ; set the step value
119+
ldx #0
120+
jsr FCIntegerToStack
121+
ply ; restore position
122+
_FCNoStep:
123+
;
124+
; Now set up the FOR Structure, starting with the code position
125+
;
126+
jsr STKSaveCodePosition ; save loop back position
127+
;
128+
; Now copy the current value to the index reference, in standard format.
129+
;
130+
jmp CopyIndexToReference
106131

107132
_FCError:
108133
jmp TypeError
@@ -121,7 +146,7 @@ FCIntegerToStack:
121146
jsr NSMNegateMantissa ; if so 2's complement the mantissa
122147
_FCNotNegative:
123148
lda NSMantissa0,x ; copy out to the basic stack
124-
sta (basicStack),y
149+
sta (basicStack),y
125150
iny
126151
lda NSMantissa1,x
127152
sta (basicStack),y
@@ -141,7 +166,7 @@ _FCNotNegative:
141166

142167
CopyIndexToReference:
143168
phy
144-
;
169+
;
145170
ldy #6 ; copy address-8 to write to zTemp0
146171
sec ; (because we copy from offset 8)
147172
lda (basicStack),y
@@ -159,7 +184,7 @@ CopyIndexToReference:
159184
asl a ; into carry
160185

161186
ldy #8 ; where to copy from.
162-
bcc _CITRNormal
187+
bcc _CITRNormal
163188
;
164189
; Copy out -ve
165190
;
@@ -169,8 +194,8 @@ _CITRNegative: ; copy and negate simultaneously.
169194
sbc (basicStack),y
170195
sta (zTemp0),y
171196
iny
172-
dex
173-
bne _CITRNegative
197+
dex
198+
bne _CITRNegative
174199
dey ; look at MSB of mantissa
175200

176201
lda (zTemp0),y ; set the MSB as negative packed.
@@ -185,7 +210,7 @@ _CITRNormal:
185210
lda (basicStack),y ; copy without negation.
186211
sta (zTemp0),y
187212
iny
188-
dex
213+
dex
189214
bne _CITRNormal
190215
ply ; and exit.
191216
rts
@@ -197,29 +222,35 @@ _CITRNormal:
197222
; ************************************************************************************************
198223

199224
NextCommand: ;; [next]
200-
lda #STK_FOR+9 ; check FOR is TOS
225+
lda #STK_FOR+11 ; check FOR is TOS
201226
ldx #ERRID_FOR ; this error
202-
jsr StackCheckFrame
227+
jsr StackCheckFrame
203228

204229
phy
205-
ldy #16 ; get the step count
206-
lda (basicStack),y
207-
sta zTemp0 ; this is the sign extend
208-
bmi _NCStepNeg
209-
stz zTemp0 ; which is 0 or 255
210-
_NCStepNeg:
230+
;
231+
; Set up a pointer to step value (basicStack+16) via zTemp1
232+
; We use (zTemp1),y with the same y offsets as (basicStack),y
233+
; so that index[y] + step[y] works (both at y=8..11, offset by 8)
234+
;
235+
lda basicStack ; zTemp1 = basicStack + 8
236+
clc
237+
adc #8
238+
sta zTemp1
239+
lda basicStack+1
240+
adc #0
241+
sta zTemp1+1
211242
;
212243
; Bump the index, and update the index variable
213244
;
214245
ldy #8 ; offset to bump
215-
ldx #4 ; count to bump
246+
ldx #4 ; four bytes to add
216247
clc
217248
_NCBump:
218-
adc (basicStack),y ; add it
249+
lda (basicStack),y ; get index
250+
adc (zTemp1),y ; add step
219251
sta (basicStack),y
220-
lda zTemp0 ; get sign extend for next time.
221252
iny ; next byte
222-
dex ; do four times
253+
dex ; are we done yet?
223254
bne _NCBump
224255
jsr CopyIndexToReference ; copy it to the reference variable.
225256
;
@@ -228,7 +259,7 @@ _NCBump:
228259
; if TO , exit if terminal < index (e.g. 10 < 11)
229260
; if DOWNTO, exit if index < terminal (e.g. -3 < -2)
230261
;
231-
ldy #16 ; get step count again
262+
ldy #19 ; get MSB of step value
232263
lda (basicStack),y
233264
asl a ; sign bit to carry
234265
;
@@ -237,13 +268,13 @@ _NCBump:
237268
bcc _NCCompRev ; use if step is +ve
238269
lda #8 ; now the LHS = index value
239270
_NCCompRev:
240-
sta zTemp1 ; so zTemp0 is the index for LHS
241-
eor #(8^12) ; and zTemp0+1 is the index for RHS
271+
sta zTemp1 ; so zTemp1 is the index for LHS
272+
eor #(8^12) ; and zTemp1+1 is the index for RHS
242273
sta zTemp1+1
243274
ldx #4 ; bytes to compare
244275
sec
245276

246-
_NCCompare:
277+
_NCCompare:
247278
ldy zTemp1 ; do compare using the two indices
248279
lda (basicStack),y
249280
ldy zTemp1+1
@@ -261,12 +292,10 @@ _NCNoOverflow:
261292
asl a ; is bit 7 set.
262293
bcc _NCLoopBack ; if no , >= so loop back
263294
;
264-
jsr StackClose ; exit the loop
265-
rts
295+
jmp StackClose ; exit the loop
266296

267297
_NCLoopBack:
268-
jsr STKLoadCodePosition ; loop back
269-
rts
298+
jmp STKLoadCodePosition ; loop back
270299

271300
.send code
272301

@@ -278,5 +307,6 @@ _NCLoopBack:
278307
;
279308
; Date Notes
280309
; ==== =====
310+
; 01/03/26 Added support for optional use of STEP (from Kevin Cozens' patch)
281311
;
282312
; ************************************************************************************************

source/common/commands/run.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ Unused1: ;; [proc]
175175
Unused2: ;; [to]
176176
Unused3: ;; [downto]
177177
Unused4: ;; [then]
178+
Unused5: ;; [step]
178179
jmp SyntaxError
179180

180181
; ************************************************************************************************

source/common/commands/utilities/clear.asm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,10 @@ _ClearZeroEnd:
100100
; Reset bitmap/sprites/tiles pages
101101
;
102102
.if graphicsIntegrated==1
103-
jsr ResetBitmapSpritesTiles
104-
.endif
103+
jmp ResetBitmapSpritesTiles
104+
.else
105105
rts
106+
.endif
106107

107108
.send code
108109

source/common/expressions/binary/simple.asm renamed to source/common/expressions/binary/addsub.asm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
; ************************************************************************************************
22
; ************************************************************************************************
33
;
4-
; Name: simple.asm
5-
; Purpose: Simple binary operations
4+
; Name: addsub.asm
5+
; Purpose: Simple binary operations (add, subtract, bitwise, indirection)
66
; Created: 21st September 2022
77
; Reviewed: 27th November 2022
88
; Author: Paul Robson (paul@robsons.org.uk)

source/common/generated/kwdconst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ KWD_SOUND = $dc; $dc SOUND
156156
KWD_SPRITE = $dd; $dd SPRITE
157157
KWD_TEXT = $de; $de TEXT
158158
KWD_TO = $df; $df TO
159+
KWD_STEP = $e0; $e0 STEP
159160
KWD1_ASSEMBLE = $83; $83 ASSEMBLE
160161
KWD1_ASSERT = $84; $84 ASSERT
161162
KWD1_BITMAP = $85; $85 BITMAP

source/common/generated/kwdtext.dat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ KeywordSet0:
9999
.text 6,$d7,"SPRITE" ; $dd SPRITE
100100
.text 4,$45,"TEXT" ; $de TEXT
101101
.text 2,$a3,"TO" ; $df TO
102+
.text 4,$3c,"STEP" ; $e0 STEP
102103
.text $FF
103104
KeywordSet1:
104105
.text 0,$65,"" ; $80 !0:EOF

source/common/generated/vectors.dat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ VectorSet0:
163163
.word SpriteCommand ; $dd SPRITE
164164
.word TextCommand ; $de TEXT
165165
.word Unused2 ; $df TO
166+
.word Unused5 ; $e0 STEP
166167
VectorSet1:
167168
.word SyntaxError ; $80 !0:EOF
168169
.word SyntaxError ; $81 !1:SH1

source/scripts/tokens.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def get(self):
5151
colour solid outline gfx image at
5252
from plot on off palette sound
5353
poke pokew pokel poked memcopy clear
54+
step~
5455
5556
{1} // Set 1
5657
end new list run stop
@@ -80,15 +81,19 @@ def get(self):
8081

8182

8283
class Token(object):
83-
def __init__(self, name, set):
84+
def __init__(self, name, set, sort_last=False):
8485
self.name = name.upper().strip()
8586
self.set = set
8687
self.id = None
8788
self.label = None
89+
self._sort_last = sort_last
8890

8991
#
9092
def sortKey(self):
91-
return "9" + str(self.set) + self.name
93+
prefix = "9" + str(self.set)
94+
if self._sort_last:
95+
prefix += "~"
96+
return prefix + self.name
9297

9398
#
9499
def getName(self):
@@ -195,7 +200,10 @@ def loadTokens(self):
195200
w = w[:-1]
196201
newToken = UnaryToken(w, sort_last=sort_last)
197202
else: # The rest
198-
newToken = Token(w, int(cClass))
203+
sort_last = w.endswith("~")
204+
if sort_last:
205+
w = w[:-1]
206+
newToken = Token(w, int(cClass), sort_last=sort_last)
199207
self.addToken(w, newToken)
200208
self.tokenList.sort(key=lambda x: x.sortKey()) # sort into the correct order
201209

0 commit comments

Comments
 (0)