Declares an array. Note that the start of this function handler is some way down in the block (at 0716).
Get next program character and return if null byte at end of line has been reached. | ||||
0711 | 2B | DimContd | DCX H | |
0712 | D7 | RST NextChar | ||
0713 | C8 | RZ | ||
Syntax check for a comma. | ||||
0714 | CF | RST SyntaxCheck | ||
0715 | 2C | ',' | ||
Set return address to DimContd above. | ||||
0716 | 011107 | Dim | LXI B,DimContd | |
0719 | C5 | PUSH B | ||
Set A to a non-zero number before falling into GetVar+1. This indicates to GetVar that we're declaring rather than accessing an array. | ||||
071A | F6AF | ORI AF |
Given that HL points to a variable name that's been encountered during program interpretation, this function will return in DE a pointer to that variable's value. If the variable does not exist, then (space permitting) this function also allocates and initialises it.
??? Signalling this is a real call to GetVar, not dropped in from DIM | ||||
071B | AF | GetVar | XRA A | |
071C | 325B01 | STA DIM_OR_EVAL | ||
Get variable name into BC, B=first char and C=(optional) second char. Notice we Syntax Error out if the first character is not alphabetic. | ||||
071F | 46 | MOV B,M | ||
0720 | CD8004 | CALL CharIsAlpha | ||
0723 | DAD001 | JC SyntaxError | ||
0726 | AF | XRA A | ||
0727 | 4F | MOV C,A | ||
0728 | D7 | RST NextChar | ||
0729 | D22E07 | JNC 072E | ||
072C | 4F | MOV C,A | ||
072D | D7 | RST NextChar | ||
If next char is '(' then we're dealing with an array and so jump to GetArrayVar (the following block) to deal with it. | ||||
072E | D628 | SUI '(' | ||
0730 | CA8A07 | JZ GetArrayVar | ||
Preserve program ptr on stack, and get VAR_ARRAY_BASE into DE and VAR_BASE into HL. This is where we iterate through the stored variables (ie from VAR_BASE to VAR_ARRAY_BASE) to see if the variable has already been declared. | ||||
0733 | E5 | PUSH H | ||
0734 | 2A6901 | LHLD VAR_ARRAY_BASE | ||
0737 | EB | XCHG | ||
0738 | 2A6701 | LHLD VAR_BASE | ||
Loop to find the variable if it's already been allocated. If HL==DE then we've reached VAR_ARRAY_BASE without finding it, and so can jump ahead to allocate a new variable. | ||||
073B | E7 | FindVarLoop | RST CompareHLDE | |
073C | CA5207 | JZ AllocNewVar | ||
073F | 79 | MOV A,C | ||
0740 | 96 | SUB M | ||
0741 | 23 | INX H | ||
0742 | C24707 | JNZ 0747 | ||
0745 | 78 | MOV A,B | ||
0746 | 96 | SUB M | ||
0747 | 23 | INX H | ||
0748 | CA8207 | JZ 0782 | ||
074B | 23 | INX H | ||
074C | 23 | INX H | ||
074D | 23 | INX H | ||
074E | 23 | INX H | ||
074F | C33B07 | JMP FindVarLoop | ||
Prepare to alloc a new variable, but first we have to do something slightly bizarre... we check the return address to see if it's the expression evaluator that's called us, and if it is then we exit without allocating. Notice that (assuming we haven't been called by the evaluator) the prog ptr on the stack is kept in place. | ||||
0752 | E1 | AllocNewVar | POP H | HL=prog ptr |
0753 | E3 | XTHL | (SP)=prog ptr, HL=ret.addr. | |
0754 | D5 | PUSH D | ||
0755 | 11F606 | LXI D,06F6 | an address inside EvalTerm | |
0758 | E7 | RST CompareHLDE | ||
0759 | D1 | POP D | ||
075A | CA8507 | JZ AlreadyAllocd | ||
075D | E3 | XTHL | (SP)=ret.addr, HL=prog ptr. | |
075E | E5 | PUSH H | Prog ptr back on stack | |
Allocate memory for the variable. We need a space of 6 bytes to be inserted before the array variables storage pointed to by VAR_ARRAY_BASE, so we copy that block up 6 bytes in memory. | ||||
075F | C5 | PUSH B | Preserve var name on stack | |
0760 | 010600 | LXI B,0006 | ||
0763 | 2A6B01 | LHLD VAR_TOP | ||
0766 | E5 | PUSH H | ||
0767 | 09 | DAD B | ||
0768 | C1 | POP B | ||
0769 | E5 | PUSH H | ||
076A | CDA701 | CALL CopyMemoryUp | ||
076D | E1 | POP H | ||
076E | 226B01 | SHLD VAR_TOP | ||
Update VAR_ARRAY_BASE cos the array block has been moved up 6 bytes. | ||||
0771 | 60 | MOV H,B | ||
0772 | 69 | MOV L,C | ||
0773 | 226901 | SHLD VAR_ARRAY_BASE | ||
Initialise the new variable to zero. | ||||
0776 | 2B | InitVarLoop | DCX H | |
0777 | 3600 | MVI M,00 | ||
0779 | E7 | RST CompareHLDE | ||
077A | C27607 | JNZ InitVarLoop | ||
Restore variable name to DE and write it to the first 2 bytes of the variable's storage. | ||||
077D | D1 | POP D | ||
077E | 73 | MOV M,E | ||
077F | 23 | INX H | ||
0780 | 72 | MOV M,D | ||
0781 | 23 | INX H | ||
Swap HL and DE so that DE points to the variable value, then restore the prog ptr to HL and return | ||||
0782 | EB | XCHG | ||
0783 | E1 | POP H | ||
0784 | C9 | RET | ||
Function exit for when called by EvalTerm. Here we set FACCUM to zero (don't know why), restore the prog ptr to HL and return. | ||||
0785 | 327201 | AlreadyAllocd | STA FACCUM+3 | A was set to zero at 075A. |
0788 | E1 | POP H | ||
0789 | C9 | RET |
Preserve variable name on stack. | ||||
078A | C5 | GetArrayVar | PUSH B | |
Push declare-or-access flag on stag | ||||
078B | 3A5B01 | LDA DIM_OR_EVAL | ||
078E | F5 | PUSH PSW | ||
Get array subscript into CDE | ||||
078F | CD8804 | CALL GetSubscript | ||
Syntax check for closing bracket ')' | ||||
0792 | CF | RST SyntaxCheck | ||
0793 | 29 | ')' | ||
Restore declare-or-access flag | ||||
0794 | F1 | POP PSW | ||
0795 | 325B01 | STA DIM_OR_EVAL | ||
Get variable name from stack into DE; HL becomes the subscript previously in DE; previous value of HL goes on stack. | ||||
0798 | E3 | XTHL | ||
0799 | EB | XCHG | ||
Multiply the subscript by 4 and stick it on the stack. | ||||
079A | 29 | DAD H | ||
079B | 29 | DAD H | ||
079C | E5 | PUSH H | ||
Load HL with the base of array storage and LXI into FindArray+2 | ||||
079D | 2A6901 | LHLD VAR_ARRAY_BASE | ||
07A0 | 01C109 | LXI B,.... | ||
Find the array loop. First thing we do is advance the array ptr by {subscript} | ||||
07A1 | C1 | FindArray | POP B | |
07A2 | 09 | DAD B | ||
07A3 | EB | XCHG | ||
If we've reached VAR_TOP then we know the array has not already been declared, so we can jump forward to allocate it. | ||||
07A4 | E5 | PUSH H | ||
07A5 | 2A6B01 | LHLD VAR_TOP | ||
07A8 | E7 | RST CompareHLDE | ||
07A9 | EB | XCHG | ||
07AA | D1 | POP D | ||
07AB | CACD07 | JZ AllocArray | ||
Advance to the next array in the block. | ||||
07AE | F7 | RST PushNextWord | ||
07AF | E3 | XTHL | ||
07B0 | E7 | RST CompareHLDE | ||
07B1 | E1 | POP H | ||
07B2 | F7 | RST PushNextWord | ||
07B3 | C2A107 | JNZ FindArray | ||
Array found. If we're in a DIM statement then this is a duplicate definition error. You can only DIM an array the once. | ||||
07B6 | 3A5B01 | LDA DIM_OR_READ | ||
07B9 | B7 | ORA A | ||
07BA | 1E12 | MVI E,12 | ||
07BC | C2D501 | JNZ Error | ||
Array element retrieval. First we ??? | ||||
07BF | D1 | POP D | ||
07C0 | 1B | DCX D | ||
07C1 | E3 | XTHL | ||
If the subscript is greater than or equal to the number of array elements, then 'Bad Subscript' error. | ||||
07C2 | E7 | RST CompareHLDE | ||
07C3 | 1E10 | MVI E,10 | ||
07C5 | D2D501 | JNC Error | ||
Return with DE pointing to the element value, and HL the prog ptr. | ||||
07C8 | D1 | POP D | ||
07C9 | 19 | DAD D | ||
07CA | D1 | POP D | ||
07CB | EB | XCHG | ||
07CC | C9 | RET | ||
Allocate space for the array. Here, DE holds the array name and HL points to where it is going to be stored. We start by storing the array name. | ||||
07CD | 73 | AllocArray | MOV M,E | |
07CE | 23 | INX H | ||
07CF | 72 | MOV M,D | ||
07D0 | 23 | INX H | ||
If DIM_OR_EVAL is zero (indicating array access), then jump ahead with DE=???? | ||||
07D1 | 112C00 | LXI D,002C | ||
07D4 | 3A5B01 | LDA 015B | ||
07D7 | B7 | ORA A | ||
07D8 | CAE107 | JZ 07E1 | ||
DIM_OR_EVAL is not zero, therefore we're declaring the array. Here we restore the array elements size to DE, save it again, add 4, and write that value to follow the array name. | ||||
07DB | D1 | POP D | ||
07DC | D5 | PUSH D | ||
07DD | 13 | INX D | ||
07DE | 13 | INX D | ||
07DF | 13 | INX D | ||
07E0 | 13 | INX D | ||
Write out array size. | ||||
07E1 | D5 | PUSH D | ||
07E2 | 73 | MOV M,E | ||
07E3 | 23 | INX H | ||
07E4 | 72 | MOV M,D | ||
07E5 | 23 | INX H | ||
07E6 | E5 | PUSH H | ||
Check the new VAR_TOP won't interfere with the stack, and update VAR_TOP. | ||||
07E7 | 19 | DAD D | ||
07E8 | CDC301 | CALL CheckEnoughMem | ||
07EB | 226B01 | SHLD VAR_TOP | ||
Initialise all array elements to 0. | ||||
07EE | D1 | POP D | ||
07EF | 2B | InitElements | DCX H | |
07F0 | 3600 | MVI M,00 | ||
07F2 | E7 | RST 4 | ||
07F3 | C2EF07 | JNZ InitElements | ||
07F6 | C3BF07 | JMP 07BF |