![]() |
Routines |
| Prev: 268D | Up: Map | Next: 2795 |
|
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 | 26C9 | CALL LOOK_VARS | Look in the existing variables for the matching entry. | |
| 26CC | JP C,REPORT_2 | An error is reported if there is no existing entry. | ||
| 26CF | CALL Z,STK_VAR | Stack the parameters of the string entry/return numeric element base address. | ||
| 26D2 | LD A,($5C3B) | Fetch FLAGS. | ||
| 26D5 | CP $C0 | Test bits 6 and 7 together. | ||
| 26D7 | JR C,S_CONT_1 | Jump if one or both bits are reset. | ||
| 26D9 | INC HL | A numeric value is to be stacked. | ||
| 26DA | CALL STACK_NUM | Move the number. | ||
|
This entry point is used by the routine at S_DECIMAL.
|
||||
| S_CONT_1 | 26DD | 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 +09 and the C register the operation code +DB that are required for this operation.
|
||||
| S_NEGATE | 26DF | LD BC,$09DB | Priority +09, operation code +DB. | |
| 26E2 | CP "-" | Is it a '-'? | ||
| 26E4 | JR Z,S_PUSH_PO | Jump forward if it is 'unary minus'. | ||
|
Next the character is tested against the code for 'VAL$', with priority +10 and operation code +18.
|
||||
| 26E6 | LD BC,$1018 | Priority +10, operation code +18. | ||
| 26E9 | CP $AE | Is it 'VAL$'? | ||
| 26EB | 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 +AF to +C3.
|
||||
| 26ED | SUB $AF | The range of the functions is changed from +AF to +C3 to range +00 to +14. | ||
| 26EF | JP C,REPORT_C | Report an error if out of range. | ||
|
The function 'NOT' is identified and dealt with separately from the others.
|
||||
| 26F2 | LD BC,$04F0 | Priority +04, operation code +F0. | ||
| 26F5 | CP $14 | Is it the function 'NOT'? | ||
| 26F7 | JR Z,S_PUSH_PO | Jump if it is so. | ||
| 26F9 | JP NC,REPORT_C | Check the range again. | ||
|
The remaining functions have priority +10. 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.
|
||||
| 26FC | LD B,$10 | Priority +10. | ||
| 26FE | ADD A,$DC | The function range is now +DC to +EF. | ||
| 2700 | LD C,A | Transfer the operation code. | ||
| 2701 | CP $DF | Separate CODE, VAL and LEN which operate on strings to give numerical results. | ||
| 2703 | JR NC,S_NO_TO_S | |||
| 2705 | RES 6,C | |||
| S_NO_TO_S | 2707 | CP $EE | Separate STR$ and CHR$ which operate on numbers to give string results. | |
| 2709 | JR C,S_PUSH_PO | |||
| 270B | 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 | 270D | PUSH BC | Stack the priority and operation codes before moving on to consider the next part of the expression. | |
| 270E | RST $20 | |||
| 270F | JP S_LOOP_1 | |||
|
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 | 2712 | RST $18 | Fetch the present character. | |
| S_CONT_3 | 2713 | CP "(" | Jump forward if it is not a '(', which indicates a parenthesised expression. | |
| 2715 | 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.
|
||||
| 2717 | BIT 6,(IY+$01) | Jump forward if dealing with a numeric parenthesised expression (bit 6 of FLAGS set). | ||
| 271B | JR NZ,S_LOOP | |||
| 271D | CALL SLICING | Modify the parameters of the 'last value'. | ||
| 2720 | RST $20 | Move on to consider the next character. | ||
| 2721 | JR S_CONT_3 | |||
|
If the present character is indeed a binary operator it will be given an operation code in the range +C3 to +CF, and the appropriate priority code.
|
||||
| S_OPERTR | 2723 | LD B,$00 | Original code to BC to index into the table of operators. | |
| 2725 | LD C,A | |||
| 2726 | LD HL,$2795 | The pointer to the table. | ||
| 2729 | CALL INDEXER | Index into the table. | ||
| 272C | JR NC,S_LOOP | Jump forward if no operation found. | ||
| 272E | LD C,(HL) | Get required code from the table. | ||
| 272F | LD HL,$26ED | The pointer to the priority table (26ED+C3 gives PRIORITIES as the first address). | ||
| 2732 | ADD HL,BC | Index into the table. | ||
| 2733 | LD B,(HL) | Fetch the appropriate priority. | ||
|
The main loop of this subroutine is now entered. At this stage there are:
Initially the 'last' operation and priority are taken off the machine stack and compared against the 'present' operation and priority.
|
||||
| S_LOOP | 2734 | POP DE | Get the 'last' operation and priority. | |
| 2735 | LD A,D | The priority goes to the A register. | ||
| 2736 | CP B | Compare 'last' against 'present'. | ||
| 2737 | JR C,S_TIGHTER | Exit to wait for the argument. | ||
| 2739 | AND A | Are both priorities zero? | ||
| 273A | 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'.
|
||||
| 273D | PUSH BC | Stack the 'present' values. | ||
| 273E | LD HL,$5C3B | This is FLAGS. | ||
| 2741 | LD A,E | The 'last' operation is compared with the code for USR, which will give 'USR number' unless modified; jump if not 'USR'. | ||
| 2742 | CP $ED | |||
| 2744 | JR NZ,S_STK_LST | |||
| 2746 | BIT 6,(HL) | Test bit 6 of FLAGS. | ||
| 2748 | JR NZ,S_STK_LST | Jump if it is set ('USR number'). | ||
| 274A | LD E,$99 | Modify the 'last' operation code: 'offset' +19, plus +80 for string input and numerical result ('USR string'). | ||
| S_STK_LST | 274C | PUSH DE | Stack the 'last' values briefly. | |
| 274D | CALL SYNTAX_Z | Do not perform the actual operation if syntax is being checked. | ||
| 2750 | JR Z,S_SYNTEST | |||
| 2752 | LD A,E | The 'last' operation code. | ||
| 2753 | AND $3F | Strip off bits 6 and 7 to convert the operation code to a calculator offset. | ||
| 2755 | LD B,A | |||
| 2756 | RST $28 | Now use the calculator. | ||
| 2757 | DEFB $3B | fp_calc_2: (perform the actual operation) | ||
| 2758 | DEFB $38 | end_calc | ||
| 2759 | 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 | 275B | LD A,E | Get the 'last' operation code. | |
| 275C | XOR (IY+$01) | 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. | ||
| 275F | AND $40 | |||
| S_RPORT_C_2 | 2761 | 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 | 2764 | POP DE | Get the 'last' operation code. | |
| 2765 | LD HL,$5C3B | This is FLAGS. | ||
| 2768 | SET 6,(HL) | Assume result to be numeric. | ||
| 276A | BIT 7,E | Jump forward if the nature of 'last value' is numeric. | ||
| 276C | JR NZ,S_LOOPEND | |||
| 276E | RES 6,(HL) | It is a string. | ||
| S_LOOPEND | 2770 | POP BC | Get the 'present' values into BC. | |
| 2771 | 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 | 2773 | PUSH DE | The 'last' values go on the stack. | |
| 2774 | LD A,C | Get the 'present' operation code. | ||
| 2775 | BIT 6,(IY+$01) | Do not modify the operation code if dealing with a numeric operand (bit 6 of FLAGS set). | ||
| 2779 | JR NZ,S_NEXT | |||
| 277B | AND $3F | Clear bits 6 and 7. | ||
| 277D | ADD A,$08 | Increase the code by +08. | ||
| 277F | LD C,A | Return the code to the C register. | ||
| 2780 | CP $10 | Is the operation 'AND'? | ||
| 2782 | JR NZ,S_NOT_AND | Jump if it is not so. | ||
| 2784 | SET 6,C | 'AND' requires a numeric operand. | ||
| 2786 | JR S_NEXT | Jump forward. | ||
| S_NOT_AND | 2788 | JR C,S_RPORT_C_2 | The operations -, *, /, ↑ and OR are not possible between strings. | |
| 278A | CP $17 | Is the operation a '+'? | ||
| 278C | JR Z,S_NEXT | Jump if it is so. | ||
| 278E | SET 7,C | The other operations yield a numeric result. | ||
| S_NEXT | 2790 | PUSH BC | The 'present' values go on the machine stack. | |
| 2791 | RST $20 | Consider the next character. | ||
| 2792 | JP S_LOOP_1 | Go around the loop again. | ||
| Prev: 268D | Up: Map | Next: 2795 |