| Routines

09929: THE 'SCANNING VARIABLE' ROUTINE

Used by the routine at S_ALPHNUM. When a variable name has been identified a call is made to LOOK_VARS which looks through those variables that already exist in the variables area (or in the program area at DEF FN statements for a user-defined function FN). If an appropriate numeric value is found then it is copied to the calculator stack using STACK_NUM. However a string or string array entry has to have the appropriate parameters passed to the calculator stack by STK_VAR (or in the case of a user-defined function, by STK_F_ARG as called from LOOK_VARS).
S_LETTER | 09929 | CALL LOOK_VARS | Look in the existing variables for the matching entry.
| 09932 | JP C,REPORT_2 | An error is reported if there is no existing entry.
| 09935 | CALL Z,STK_VAR | Stack the parameters of the string entry/return numeric element base address.
| 09938 | LD A,(23611) | Fetch FLAGS.
| 09941 | CP 192 | Test bits 6 and 7 together.
| 09943 | JR C,S_CONT_1 | Jump if one or both bits are reset.
| 09945 | INC HL | A numeric value is to be stacked.
| 09946 | CALL STACK_NUM | Move the number.
This entry point is used by the routine at S_DECIMAL.
S_CONT_1 | 09949 | JR S_CONT_2 | Jump forward.
This entry point is used by the routine at S_ALPHNUM. The character is tested against the code for '-', thus identifying the 'unary minus' operation. Before the actual test the B register is set to hold the priority 9 and the C register the operation code 219 that are required for this operation.
S_NEGATE | 09951 | LD BC,2523 | Priority 9, operation code 219.
| 09954 | CP "-" | Is it a '-'?
| 09956 | JR Z,S_PUSH_PO | Jump forward if it is 'unary minus'.
Next the character is tested against the code for 'VAL$', with priority 16 and operation code 24.
| 09958 | LD BC,4120 | Priority 16, operation code 24.
| 09961 | CP 174 | Is it 'VAL$'?
| 09963 | JR Z,S_PUSH_PO | Jump forward if it is 'VAL$'.
The present character must now represent one of the functions CODE to NOT, with codes 175 to 195.
| 09965 | SUB 175 | The range of the functions is changed from 175 to 195 to range 0 to 20.
| 09967 | JP C,REPORT_C | Report an error if out of range.
The function 'NOT' is identified and dealt with separately from the others.
| 09970 | LD BC,1264 | Priority 4, operation code 240.
| 09973 | CP 20 | Is it the function 'NOT'?
| 09975 | JR Z,S_PUSH_PO | Jump if it is so.
| 09977 | JP NC,REPORT_C | Check the range again.
The remaining functions have priority 16. The operation codes for these functions are now calculated. Functions that operate on strings need bit 6 reset and functions that give string results need bit 7 reset in their operation codes.
| 09980 | LD B,16 | Priority 16.
| 09982 | ADD A,220 | The function range is now 220 to 239.
| 09984 | LD C,A | Transfer the operation code.
| 09985 | CP 223 | Separate CODE, VAL and LEN which operate on strings to give numerical results.
| 09987 | JR NC,S_NO_TO_S
| 09989 | RES 6,C
S_NO_TO_S | 09991 | CP 238 | Separate STR$ and CHR$ which operate on numbers to give string results.
| 09993 | JR C,S_PUSH_PO
| 09995 | RES 7,C | Mark the operation codes. The other operation codes have bits 6 and 7 both set.
This entry point is used by the routine at S_INKEY. The priority code and the operation code for the function being considered are now pushed on to the machine stack. A hierarchy of operations is thereby built up.
S_PUSH_PO | 09997 | PUSH BC | Stack the priority and operation codes before moving on to consider the next part of the expression.
| 09998 | RST 32
| 09999 | JP S_LOOP_1
This entry point is used by the routines at S_QUOTE, S_BRACKET, S_INKEY and S_FN_SBRN. The scanning of the line now continues. The present argument may be followed by a '(', a binary operator or, if the end of the expression has been reached, then e.g. a carriage return character or a colon, a separator or a 'THEN'.
S_CONT_2 | 10002 | RST 24 | Fetch the present character.
S_CONT_3 | 10003 | CP "(" | Jump forward if it is not a '(', which indicates a parenthesised expression.
| 10005 | JR NZ,S_OPERTR
If the 'last value' is numeric then the parenthesised expression is a true sub-expression and must be evaluated by itself. However if the 'last value' is a string then the parenthesised expression represents an element of an array or a slice of a string. A call to SLICING modifies the parameters of the string as required.
| 10007 | BIT 6,(IY+1) | Jump forward if dealing with a numeric parenthesised expression (bit 6 of FLAGS set).
| 10011 | JR NZ,S_LOOP
| 10013 | CALL SLICING | Modify the parameters of the 'last value'.
| 10016 | RST 32 | Move on to consider the next character.
| 10017 | JR S_CONT_3
If the present character is indeed a binary operator it will be given an operation code in the range 195 to 207, and the appropriate priority code.
S_OPERTR | 10019 | LD B,0 | Original code to BC to index into the table of operators.
| 10021 | LD C,A
| 10022 | LD HL,10133 | The pointer to the table.
| 10025 | CALL INDEXER | Index into the table.
| 10028 | JR NC,S_LOOP | Jump forward if no operation found.
| 10030 | LD C,(HL) | Get required code from the table.
| 10031 | LD HL,9965 | The pointer to the priority table (9965+195 gives PRIORITIES as the first address).
| 10034 | ADD HL,BC | Index into the table.
| 10035 | LD B,(HL) | Fetch the appropriate priority.
The main loop of this subroutine is now entered. At this stage there are: i. A 'last value' on the calculator stack. ii. The starting priority marker on the machine stack below a hierarchy, of unknown size, of function and binary operation codes. This hierarchy may be null. iii. The BC register pair holding the 'present' operation and priority, which if the end of an expression has been reached will be priority zero. Initially the 'last' operation and priority are taken off the machine stack and compared against the 'present' operation and priority.
S_LOOP | 10036 | POP DE | Get the 'last' operation and priority.
| 10037 | LD A,D | The priority goes to the A register.
| 10038 | CP B | Compare 'last' against 'present'.
| 10039 | JR C,S_TIGHTER | Exit to wait for the argument.
| 10041 | AND A | Are both priorities zero?
| 10042 | JP Z,GET_CHAR | Exit via GET_CHAR thereby making 'last value' the required result.
Before the 'last' operation is performed, the 'USR' function is separated into 'USR number' and 'USR string' according as bit 6 of FLAGS was set or reset when the argument of the function was stacked as the 'last value'.
| 10045 | PUSH BC | Stack the 'present' values.
| 10046 | LD HL,23611 | This is FLAGS.
| 10049 | LD A,E | The 'last' operation is compared with the code for USR, which will give 'USR number' unless modified; jump if not 'USR'.
| 10050 | CP 237
| 10052 | JR NZ,S_STK_LST
| 10054 | BIT 6,(HL) | Test bit 6 of FLAGS.
| 10056 | JR NZ,S_STK_LST | Jump if it is set ('USR number').
| 10058 | LD E,153 | Modify the 'last' operation code: 'offset' 25, plus 128 for string input and numerical result ('USR string').
S_STK_LST | 10060 | PUSH DE | Stack the 'last' values briefly.
| 10061 | CALL SYNTAX_Z | Do not perform the actual operation if syntax is being checked.
| 10064 | JR Z,S_SYNTEST
| 10066 | LD A,E | The 'last' operation code.
| 10067 | AND 63 | Strip off bits 6 and 7 to convert the operation code to a calculator offset.
| 10069 | LD B,A
| 10070 | RST 40 | Now use the calculator.
| 10071 | DEFB 59 | fp_calc_2: (perform the actual operation)
| 10072 | DEFB 56 | end_calc
| 10073 | JR S_RUNTEST | Jump forward.
An important part of syntax checking involves the testing of the operation to ensure that the nature of the 'last value' is of the correct type for the operation under consideration.
S_SYNTEST | 10075 | LD A,E | Get the 'last' operation code.
| 10076 | XOR (IY+1) | This tests the nature of the 'last value' (bit 6 of FLAGS) against the requirement of the operation. They are to be the same for correct syntax.
| 10079 | AND 64
S_RPORT_C_2 | 10081 | JP NZ,REPORT_C | Jump if syntax fails.
Before jumping back to go round the loop again the nature of the 'last value' must be recorded in FLAGS.
S_RUNTEST | 10084 | POP DE | Get the 'last' operation code.
| 10085 | LD HL,23611 | This is FLAGS.
| 10088 | SET 6,(HL) | Assume result to be numeric.
| 10090 | BIT 7,E | Jump forward if the nature of 'last value' is numeric.
| 10092 | JR NZ,S_LOOPEND
| 10094 | RES 6,(HL) | It is a string.
S_LOOPEND | 10096 | POP BC | Get the 'present' values into BC.
| 10097 | JR S_LOOP | Jump back.
Whenever the 'present' operation binds tighter, the 'last' and the 'present' values go back on the machine stack. However if the 'present' operation requires a string as its operand then the operation code is modified to indicate this requirement.
S_TIGHTER | 10099 | PUSH DE | The 'last' values go on the stack.
| 10100 | LD A,C | Get the 'present' operation code.
| 10101 | BIT 6,(IY+1) | Do not modify the operation code if dealing with a numeric operand (bit 6 of FLAGS set).
| 10105 | JR NZ,S_NEXT
| 10107 | AND 63 | Clear bits 6 and 7.
| 10109 | ADD A,8 | Increase the code by 8.
| 10111 | LD C,A | Return the code to the C register.
| 10112 | CP 16 | Is the operation 'AND'?
| 10114 | JR NZ,S_NOT_AND | Jump if it is not so.
| 10116 | SET 6,C | 'AND' requires a numeric operand.
| 10118 | JR S_NEXT | Jump forward.
S_NOT_AND | 10120 | JR C,S_RPORT_C_2 | The operations -, *, /, ↑ and OR are not possible between strings.
| 10122 | CP 23 | Is the operation a '+'?
| 10124 | JR Z,S_NEXT | Jump if it is so.
| 10126 | SET 7,C | The other operations yield a numeric result.
S_NEXT | 10128 | PUSH BC | The 'present' values go on the machine stack.
| 10129 | RST 32 | Consider the next character.
| 10130 | JP S_LOOP_1 | Go around the loop again.