K2 BASIC

labels, no line numbers.
functions.
procedures.
Comment:	#


data types:
  int, float, str, array

constants:
  const a = 0
  const b = 0.0
  const d = "foobar"

variables:
  int
  num		float
  str   	dyn. sized
  int[]		array of int, fixed size
  num[] 	array of float
  str[]		array of strings

num a = 0.0
int b = 0
int c = 'A'
str d = "beta"
int[123] f


# these make only sense in command line mode:
new			# clear program and variables
clear	  	# clear variables
stop	  	# stop running program. user input prompt.
continue  	# continue where stopped
run			# start program at start


# i/o:
print <arguments>	# print misc. data
input <variable>	# input variable, format depends, blocking
inkey 				# function: return input character or 0


# bare memory, machine code:
peek(<address>)		# read memory at address
poke <addr>,<value>	# write data to memory
call <address>		# call machine code


# simple jumping:
label:					# simple label for goto and gosub
goto <label>			# goto label
gosub <label>			# store program position and goto sub program
on <value> goto <list>	# calculated branch
on <value> gosub <list>	# calculated branch
return					# return from sub program
every <time> gosub <label>	# timer or event interrupt



# program structures:

if <cond> <instructions>
if <cond> <instructions> else <instructions>

if <cond>
	<instructions>
elif <cond>
	<instructions>
else
	<instructions>
endif

do <instructions>
for ... do <instructions>

for <name> = <value> to <value> [ step <value> ] do
do
	<instructions>
	while <cond>
	next [<name>]
	exit
loop


# Functions:
<type> <name> ( <args> ) = <expression>		user function

#e.g.:
int max ( int a, int b ) = a>b?a:b

<type> <name> ( <args> )					user function
	<instructions>
	return <value>
end

proc <name> ( <args> ) 						user procedure
	<instructions>
	return
end


# operators:
	+ - * / % << >> & | ^ == >= > < <= != && || ?:
	+ - ! ~

# functions:
	sqrt sin cos

################### EXAMLES ################

num a = 1
int b = 22
const hello = "Hello Kio !"

print cls, hello, tab, "a = ", a, tab, "b = ", b, nl

do
	on a gosub L_hello, L_stop
	a = a+1
loop

num max (num a, num b) = a > b ? a : b

proc print_max ( int a, int b )		# int only
	if a > b
		print "a>b, max=", a, nl
	else
		print "b>a, max=", b, nl
	endif
end

num maximum ( num a, b )
	if a > b
		return a
	endif
	return b
end


################ XXX ################

enum BasicToken {
	int num str const proc do loop if elif else endif on goto gosub
	tDP tPlus tMinus tMult tDiv tREM tSHIFTLEFT tSHIFTRIGHT ... ((operators))
	tRKauf ...
	tASSIGN tRETURN tEXIT tNEXT tFOR tFROM tSTEP
}

L_max::		; ( de:int hl:int -- hl:int )
	and a
	sbc hl,de
	ex hl,de
	ret c
	add hl,de
	ret

; int max ( int a, int b ) = a >= b ? a : b
L_max::
	ld	(L_max__a),de	; store argument 1 in lvar
	ld	(L_max__b),hl	; store argument 2 in lvar
L_max__quick::
	ld	hl,(L_max__a)	; a
	ld	de,(L_max__b)	; b
	cmp_hl_de			; >=
	jr	cy, 1$			; cy => hl-de < 0 => a-b<0 return b
	ld	hl,(L_max__a)	; a
	ret
1$:	ld	hl,(L_max__b)	; b
	ret
; allocate local variables
; as max() calls no other function, max() is an 'innermost' function
; and variables are allocated directly at TOP (or BASE?)
L_max__a = LVAR_level0_base+0		; or allocate at MEMBASE++ ?
L_max__b = LVAR_level0_base+2
LVAR_level0_base = min (LVAR_level0_base, MEMTOP-4)

; int minmax( int a, int n, int e) = max(a,min(n,e))
L_minmax::
	ld	(L_minmax__n),de	; store argument 2 in lvar
	ld	(L_minmax__e),hl	; store argument 3 in lvar
	pop	hl
	ex	hl,(sp)
	ld 	(L_minmax__a),hl	; store arg 1 in lvar
L_minmax_quick::
	ld	hl,(L_minmax__a)
	ex	hl,de
	ld	hl,(L_minmax__n)
	push de
	ex hl,de
	ld	hl,(L_minmax__e)
	call L_min
	pop de
	call L_max
	ret



L_minmax::
	; store the arguments from stack to local variables:
	; ((neglecting return address on stack))
	lset	L_minmax__e
	lset	L_minmax__n
	lset	L_minmax__a

	; expression:
	lget	L_minmax__a
	lget	L_minmax__n
	lget	L_minmax__e
	fcall	L_min
	fcall	L_max
	return_hl


	;lget	L_minmax__a		( void -- int )
	ld	hl,(L_minmax__a)

	;lget	L_minmax__n
	push	hl
	ld	hl,(L_minmax__n)	( … int -- int int … )

	;lget	L_minmax__e
	push	hl
	ld	hl,(L_minmax__e)	( … int -- int int … )

	;fcall	L_min			( … int int -- int … )
	call	L_min

	;fcall	L_max			( int int -- int )
	call	L_max

	;return_hl
	ret						( -- int )



int minmax ( int a, int n, int e ) = max(a,min(n,e))
-->

level0_support:
level0_return::
	ld	sp,0		; <-- modified
	ret

// level 0, first local int:
int01 = $+1
get_int01_de::	ld	de,0 \ ret			; <-- modified
get_int01_hl::	ld	hl,(int01) \ ret
set_int01::    	ld 	(int01),hl \ ret

// level 0, 2nd local int:
int02 = $+1
get_int02_de::	ld	de,0 \ ret
get_int02_hl::	ld	hl,(int02) \ ret
set_int02::    	ld 	(int02),hl \ ret

// level 0, 3nd local int:
int03 = $+1
get_int03_de::	ld	de,0 \ ret
get_int03_hl::	ld	hl,(int03) \ ret
set_int03::    	ld 	(int03),hl \ ret



; -------------------------------------------
; int minmax ( int a, int n, int e ) = max(a,min(n,e))
; -------------------------------------------

num_int1 = max(num_int1,3)		; this level1 function uses 3 local int variables

#local
get_de_a = get_int11_de
get_hl_a = get_int11_hl
set_a    = set_int11

get_de_n = get_int12_de
get_hl_n = get_int12_hl
set_n    = set_int12

get_de_e = get_int13_de
get_hl_e = get_int13_hl
set_e    = set_int13

f_minmax::
	ld	(level1_return + 1),sp
	ld	sp,$+4
	ret
	.dw	set_a_bc	; todo: caller?
;	.dw	set_n_de
;	.dw	set_e_hl	; store hl -> e
;	.dw	get_de_n
;	.dw	get_hl_e
	.dw	f_min		; level0 function
	.dw	get_de_a
	.dw	f_max		; level0 function
	.dw	level1_return
#endlocal

; -------------------------------------------
; int max ( int a, int b ) = a >= b ? a : b
; -------------------------------------------

num_int0 = max(num_int0,2)		; this level0 function uses 2 local int variables

#local
get_de_a = get_int01_de
get_hl_a = get_int01_hl
set_a    = set_int01

get_de_b = get_int02_de
get_hl_b = get_int02_hl
set_b    = set_int02

f_max::
	ld	(level0_return + 1),sp
	ld	sp,$+4
	ret
	.dw	set_a_de	; store de -> a
	.dw	set_b_hl	; store hl -> b
;	.dw	get_de_a
;	.dw	get_hl_b
	.dw	ge_cy			; built-in, no local variables in memory
	.dw	jp_cy, L1
	.dw	get_hl_a
	.dw	level0_return
L1:	.dw	get_hl_b
	.dw	level0_return
#endlocal


; -------------------------------------------
; built-in
; -------------------------------------------

le_nc::				; compare de-hl and set cy=0 if de <= hl
	and	a
	sbc	hl,de		;
	ret

ge_cy::				; compare de-hl and set cy=1 if de >= hl
	and	a
	sbc	hl,de		;
	ret

jp_cy::
	pop	hl			; todo: use hl possible?
	ret	nc
	jp	hl

f_add::
	add	hl,de
	ret

f_sub::
	ex	hl,de
f_rsub::
	and	a
	sbc	hl,de
	ret

f_mul::
	ld	bc,hl
	xor	a,a
	ld	l,a
	or	a,b
	ld	b,16
	jr	nz,2$
	ld	b,8
	ld	a,c
1$:	add	hl,hl
2$:	rl	c
	rla
	jr	 nc,3$
	add	 hl,de
3$:	djnz 1$
	ret







################### LATER: ####################
for <name> in <array> do
data type 'list'
const c = {1,2,3,4,5,"foo",1.0};		variadic
list		array of variadic type, dyn. sized
list[]
list e = {};

switch <value>
case <const>: <instructions>
case <const>:
	<instructions>

[<label>:] for <instr> ; <cond> ; <instr> do
[<label>:] for <name> in <array> do




