; *** Variables ***
; A list of words for each member of the A-Z range.
.equ	VAR_TBL		VAR_RAMSTART
.equ	VAR_RAMEND	@+52

; *** Code ***

varInit:
	ld	b, VAR_RAMEND-VAR_RAMSTART
	ld	hl, VAR_RAMSTART
	xor	a
.loop:
	ld	(hl), a
	inc	hl
	djnz	.loop
	ret

; Check if A is a valid variable letter (a-z or A-Z). If it is, set A to a
; valid VAR_TBL index and set Z. Otherwise, unset Z (and A is destroyed)
varChk:
	call	upcase
	sub	'A'
	ret	c	; Z unset
	cp	27	; 'Z' + 1
	jr	c, .isVar
	; A > 'Z'
	dec	a	; unset Z
	ret
.isVar:
	cp	a	; set Z
	ret

; Try to interpret line at (HL) and see if it's a variable assignment. If it
; is, proceed with the assignment and set Z. Otherwise, NZ.
varTryAssign:
	inc	hl
	ld	a, (hl)
	dec	hl
	cp	'='
	ret	nz
	ld	a, (hl)
	call	varChk
	ret	nz
	; We have a variable! Its table index is currently in A.
	push	ix	; --> lvl 1
	push	hl	; --> lvl 2
	push	de	; --> lvl 3
	push	af	; --> lvl 4. save for later
	; Let's put that expression to read in scratchpad
	inc	hl \ inc hl
	ld	de, SCRATCHPAD
	call	rdWord
	ex	de, hl
	; Now, evaluate that expression now in (HL)
	call	parseExpr	; --> number in IX
	jr	nz, .exprErr
	pop	af	; <-- lvl 4
	push	ix \ pop de	; send number to DE
	call	varAssign
	xor	a	; ensure Z
.end:
	pop	de	; <-- lvl 3
	pop	hl	; <-- lvl 2
	pop	ix	; <-- lvl 1
	ret
.exprErr:
	pop	af	; <-- lvl 4
	jr	.end

; Given a variable **index** in A (call varChk to transform) and a value in
; DE, assign that value in the proper cell in VAR_TBL.
; No checks are made.
varAssign:
	push	hl
	add	a, a	; * 2 because each element is a word
	ld	hl, VAR_TBL
	call	addHL
	; HL placed, write number
	ld	(hl), e
	inc	hl
	ld	(hl), d
	pop	hl
	ret

; Check if value at (HL) is a variable. If yes, returns its associated value.
; Otherwise, jump to parseLiteral.
parseLiteralOrVar:
	inc	hl
	ld	a, (hl)
	dec	hl
	or	a
	; if more than one in length, it can't be a variable
	jp	nz, parseLiteral
	ld	a, (hl)
	call	varChk
	jp	nz, parseLiteral
	; It's a variable, resolve!
	add	a, a	; * 2 because each element is a word
	push	hl	; --> lvl 1
	ld	hl, VAR_TBL
	call	addHL
	push	de	; --> lvl 2
	ld	e, (hl)
	inc	hl
	ld	d, (hl)
	push	de \ pop ix
	pop	de	; <-- lvl 2
	pop	hl	; <-- lvl 1
	cp	a	; ensure Z
	ret