Skip to content

Commit 59af723

Browse files
mbrukneragurtovoy
authored andcommitted
feat: add user-defined functions (fn/endfn) (#115)
- Add single-line (`fn square(x) = x * x`) and multi-line (`fn`/`endfn`) user-defined functions - `return` inside a function body evaluates and returns an expression - Functions are called by name as expressions (e.g. `print square(5)`) — no `fn` keyword needed - Supports nested function calls (e.g. `print add(square(2), square(3))`) - Supports parameter localisation, control structures within function bodies, and up to 8 levels of nesting - Eval stack is saved/restored on hardware stack for multi-line calls - Nesting stacks protect against corruption from recursive calls - `list` supports `fn` definitions (single-line and multi-line) - String return values are copied to temp storage before local unwind - Move error text strings to module page 1 to free ROM space for the new code
1 parent bea4257 commit 59af723

26 files changed

Lines changed: 1042 additions & 336 deletions

File tree

modules/tokeniser/__kwdtext.asm

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -52,54 +52,56 @@ KeywordSet0:
5252
.text 4,$40,"TRUE" ; $ae TRUE
5353
.text 4,$0b,"VAL(" ; $af VAL(
5454
.text 4,$05,"FRE(" ; $b0 FRE(
55-
.text 3,$e7,"FOR" ; $b1 FOR
56-
.text 2,$8f,"IF" ; $b2 IF
57-
.text 4,$34,"PROC" ; $b3 PROC
58-
.text 6,$c1,"REPEAT" ; $b4 REPEAT
59-
.text 5,$79,"WHILE" ; $b5 WHILE
60-
.text 5,$66,"ENDIF" ; $b6 ENDIF
61-
.text 7,$0b,"ENDPROC" ; $b7 ENDPROC
62-
.text 4,$3f,"NEXT" ; $b8 NEXT
63-
.text 4,$2f,"THEN" ; $b9 THEN
64-
.text 5,$8c,"UNTIL" ; $ba UNTIL
65-
.text 4,$2e,"WEND" ; $bb WEND
66-
.text 2,$95,"AT" ; $bc AT
67-
.text 2,$9b,"BY" ; $bd BY
68-
.text 4,$1c,"CALL" ; $be CALL
69-
.text 6,$b2,"CIRCLE" ; $bf CIRCLE
70-
.text 5,$67,"CLEAR" ; $c0 CLEAR
71-
.text 5,$7f,"COLOR" ; $c1 COLOR
72-
.text 6,$d4,"COLOUR" ; $c2 COLOUR
73-
.text 4,$1a,"DATA" ; $c3 DATA
74-
.text 3,$da,"DIM" ; $c4 DIM
75-
.text 6,$db,"DOWNTO" ; $c5 DOWNTO
76-
.text 4,$29,"ELSE" ; $c6 ELSE
77-
.text 4,$34,"FROM" ; $c7 FROM
78-
.text 3,$e5,"GFX" ; $c8 GFX
79-
.text 4,$24,"HERE" ; $c9 HERE
80-
.text 5,$63,"IMAGE" ; $ca IMAGE
81-
.text 3,$e5,"LET" ; $cb LET
82-
.text 4,$28,"LINE" ; $cc LINE
83-
.text 5,$6b,"LOCAL" ; $cd LOCAL
84-
.text 7,$1a,"MEMCOPY" ; $ce MEMCOPY
85-
.text 3,$db,"OFF" ; $cf OFF
86-
.text 2,$9d,"ON" ; $d0 ON
87-
.text 7,$20,"OUTLINE" ; $d1 OUTLINE
88-
.text 7,$0f,"PALETTE" ; $d2 PALETTE
89-
.text 4,$3f,"PLOT" ; $d3 PLOT
90-
.text 4,$2f,"POKE" ; $d4 POKE
91-
.text 5,$73,"POKED" ; $d5 POKED
92-
.text 5,$7b,"POKEL" ; $d6 POKEL
93-
.text 5,$86,"POKEW" ; $d7 POKEW
94-
.text 4,$1c,"READ" ; $d8 READ
95-
.text 4,$2e,"RECT" ; $d9 RECT
96-
.text 3,$e4,"REM" ; $da REM
97-
.text 5,$7b,"SOLID" ; $db SOLID
98-
.text 5,$89,"SOUND" ; $dc SOUND
99-
.text 6,$d7,"SPRITE" ; $dd SPRITE
100-
.text 4,$45,"TEXT" ; $de TEXT
101-
.text 2,$a3,"TO" ; $df TO
102-
.text 4,$3c,"STEP" ; $e0 STEP
55+
.text 2,$94,"FN" ; $b1 FN
56+
.text 3,$e7,"FOR" ; $b2 FOR
57+
.text 2,$8f,"IF" ; $b3 IF
58+
.text 4,$34,"PROC" ; $b4 PROC
59+
.text 6,$c1,"REPEAT" ; $b5 REPEAT
60+
.text 5,$79,"WHILE" ; $b6 WHILE
61+
.text 5,$6b,"ENDFN" ; $b7 ENDFN
62+
.text 5,$66,"ENDIF" ; $b8 ENDIF
63+
.text 7,$0b,"ENDPROC" ; $b9 ENDPROC
64+
.text 4,$3f,"NEXT" ; $ba NEXT
65+
.text 4,$2f,"THEN" ; $bb THEN
66+
.text 5,$8c,"UNTIL" ; $bc UNTIL
67+
.text 4,$2e,"WEND" ; $bd WEND
68+
.text 2,$95,"AT" ; $be AT
69+
.text 2,$9b,"BY" ; $bf BY
70+
.text 4,$1c,"CALL" ; $c0 CALL
71+
.text 6,$b2,"CIRCLE" ; $c1 CIRCLE
72+
.text 5,$67,"CLEAR" ; $c2 CLEAR
73+
.text 5,$7f,"COLOR" ; $c3 COLOR
74+
.text 6,$d4,"COLOUR" ; $c4 COLOUR
75+
.text 4,$1a,"DATA" ; $c5 DATA
76+
.text 3,$da,"DIM" ; $c6 DIM
77+
.text 6,$db,"DOWNTO" ; $c7 DOWNTO
78+
.text 4,$29,"ELSE" ; $c8 ELSE
79+
.text 4,$34,"FROM" ; $c9 FROM
80+
.text 3,$e5,"GFX" ; $ca GFX
81+
.text 4,$24,"HERE" ; $cb HERE
82+
.text 5,$63,"IMAGE" ; $cc IMAGE
83+
.text 3,$e5,"LET" ; $cd LET
84+
.text 4,$28,"LINE" ; $ce LINE
85+
.text 5,$6b,"LOCAL" ; $cf LOCAL
86+
.text 7,$1a,"MEMCOPY" ; $d0 MEMCOPY
87+
.text 3,$db,"OFF" ; $d1 OFF
88+
.text 2,$9d,"ON" ; $d2 ON
89+
.text 7,$20,"OUTLINE" ; $d3 OUTLINE
90+
.text 7,$0f,"PALETTE" ; $d4 PALETTE
91+
.text 4,$3f,"PLOT" ; $d5 PLOT
92+
.text 4,$2f,"POKE" ; $d6 POKE
93+
.text 5,$73,"POKED" ; $d7 POKED
94+
.text 5,$7b,"POKEL" ; $d8 POKEL
95+
.text 5,$86,"POKEW" ; $d9 POKEW
96+
.text 4,$1c,"READ" ; $da READ
97+
.text 4,$2e,"RECT" ; $db RECT
98+
.text 3,$e4,"REM" ; $dc REM
99+
.text 5,$7b,"SOLID" ; $dd SOLID
100+
.text 5,$89,"SOUND" ; $de SOUND
101+
.text 6,$d7,"SPRITE" ; $df SPRITE
102+
.text 4,$45,"TEXT" ; $e0 TEXT
103+
.text 2,$a3,"TO" ; $e1 TO
104+
.text 4,$3c,"STEP" ; $e2 STEP
103105
.text $FF
104106
KeywordSet1:
105107
.text 0,$65,"" ; $80 !0:EOF

source/Makefile

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ MODULES = +hardware +tokeniser +kernel +graphics:2 +sound:2
2929
BUILD_OUT = $(BUILDDIR)basic.rom
3030
SCRIPTDIR = scripts$(S)
3131
MAME_PATH=../../mame
32-
IMAGE_PATH := sd
33-
IMAGE := $(IMAGE_PATH).img
3432
BASIC_TESTS_PATH=$(PWD)/../test
33+
IMAGE := $(BASIC_TESTS_PATH)/.output/tests.img
3534

3635
all: build
3736

@@ -95,9 +94,6 @@ build: prelim
9594
# Scripts run in advance generating tables etc.
9695
#
9796
prelim:
98-
@echo "Building submodules"
99-
$(Q)$(MAKE) -B -C ..$(S)modules clean all
100-
10197
@echo "Generating assembly sources"
10298
$(Q)$(PYTHON) $(SCRIPTDIR)errors.py $(LANGUAGE)
10399
$(Q)$(PYTHON) $(SCRIPTDIR)opcodes.py >common$(S)generated$(S)asmcore.asm
@@ -106,6 +102,9 @@ prelim:
106102
$(Q)$(PYTHON) $(SCRIPTDIR)constants.py
107103
$(Q)$(PYTHON) $(SCRIPTDIR)version.py $(VERSION)
108104

105+
@echo "Building submodules"
106+
$(Q)$(MAKE) -B -C ..$(S)modules clean all
107+
109108
#
110109
# Print base version to console
111110
#
@@ -192,9 +191,10 @@ flash: build
192191
# Test in emulator
193192
#
194193
emu: build $(IMAGE)
195-
cp $(BUILDDIR)/sb*.bin $(MAME_PATH)/roms/f256k
194+
$(Q)$(CCOPY) $(BUILDDIR)/sb*.bin $(MAME_PATH)/roms/f256k
195+
$(Q)$(CDEL) $(MAME_PATH)/nvram/f256k/flash
196196
cd $(MAME_PATH) && ./f256k f256k -window -resolution 1280x720 -skip_gameinfo -harddisk $(BASIC_TESTS_PATH)/.output/tests.img -rompath roms
197-
#cd $(MAME_PATH) && ./f256k f256k -window -resolution 1280x720 -skip_gameinfo -harddisk $(BASIC_TESTS_PATH)/.output/tests.img -rompath roms -script $(LAUNCH_SCRIPT) -log
198197

199-
$(IMAGE): $(BASIC_TESTS_PATH)/ashanghai
200-
$(BASIC_TESTS_PATH)/prepare-disk.py -t $<
198+
$(IMAGE): $(BASIC_TESTS_PATH)/fnproc
199+
$(PYTHON) $(BASIC_TESTS_PATH)/prepare-disk.py -t $<
200+

source/_basic.asm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
.include "./common/commands/assert.asm"
3636
.include "./common/commands/call.asm"
3737
.include "./common/commands/data.asm"
38+
.include "./common/commands/def.asm"
3839
.include "./common/commands/dim.asm"
3940
.include "./common/commands/end.asm"
4041
.include "./common/commands/for.asm"
@@ -150,6 +151,7 @@
150151
.include "./common/stack/setup.asm"
151152
.include "./common/strings/concrete.asm"
152153
.include "./common/strings/stringalloc.asm"
154+
.include "./common/expressions/unary/fn.asm"
153155

154156

155157
.section code
@@ -163,6 +165,9 @@ StartModuleCode:
163165
.include "../modules/.build/tokeniser.module.asm"
164166
.include "../modules/.build/kernel.module.asm"
165167

168+
; --- Error text in module page 1 ---
169+
.include "./common/generated/_errortext.asm"
170+
166171
; --- Header data in boot section ($6000-$7FFF) ---
167172
.include "../modules/hardware/header/.build/headerdata.dat"
168173

source/common/aa.system/04data.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ NSMantissa3:
7676
NSExponent: ; Exponent , 0 = Mantissa is integer
7777
.fill MathStackSize
7878

79+
fnStackLevel: ; saved stack level for function evaluation
80+
.fill 1
81+
7982
.send zeropref
8083

8184

@@ -151,6 +154,8 @@ listIndent: ; list indent level.
151154
.fill 1
152155
listElseFound: ; flag set when ELSE found on line (for indent fix)
153156
.fill 1
157+
listEndToken: ; closing token for LIST proc/fn
158+
.fill 1
154159
lcLastCharacter: ; last character output.
155160
.fill 1
156161
isPrintFlag: ; zero if input, non-zero if print, bit 6 zero = character print

0 commit comments

Comments
 (0)