Routines |
Prev: 27B0 | Up: Map | Next: 28AB |
Used by the routine at S_FN.
This subroutine evaluates a user defined function which occurs in a BASIC line. The subroutine can be considered in four stages:
|
||||
S_FN_SBRN | 27BD | CALL SYNTAX_Z | Unless syntax is being checked, a jump is made to SF_RUN. | |
27C0 | JR NZ,SF_RUN | |||
27C2 | RST $20 | Get the first character of the name. | ||
27C3 | CALL ALPHA | If it is not alphabetic, then report the error. | ||
27C6 | JP NC,REPORT_C | |||
27C9 | RST $20 | Get the next character. | ||
27CA | CP "$" | Is it a '$'? | ||
27CC | PUSH AF | Save the zero flag on the stack. | ||
27CD | JR NZ,SF_BRKT_1 | Jump if it was not a '$'. | ||
27CF | RST $20 | But get the next character if it was. | ||
SF_BRKT_1 | 27D0 | CP "(" | If the character is not a '(', then report the error. | |
27D2 | JR NZ,SF_RPRT_C | |||
27D4 | RST $20 | Get the next character. | ||
27D5 | CP ")" | Is it a ')'? | ||
27D7 | JR Z,SF_FLAG_6 | Jump if it is; there are no arguments. | ||
SF_ARGMTS | 27D9 | CALL SCANNING | Within the loop, call SCANNING to check the syntax of each argument and to insert floating-point numbers. | |
27DC | RST $18 | Get the character which follows the argument; if it is not a ',' then jump - no more arguments. | ||
27DD | CP "," | |||
27DF | JR NZ,SF_BRKT_2 | |||
27E1 | RST $20 | Get the first character in the next argument. | ||
27E2 | JR SF_ARGMTS | Loop back to consider this argument. | ||
SF_BRKT_2 | 27E4 | CP ")" | Is the current character a ')'? | |
SF_RPRT_C | 27E6 | JP NZ,REPORT_C | Report the error if it is not. | |
SF_FLAG_6 | 27E9 | RST $20 | Point to the next character in the BASIC line. | |
27EA | LD HL,$5C3B | Assume a string-valued function and reset bit 6 of FLAGS. | ||
27ED | RES 6,(HL) | |||
27EF | POP AF | Restore the zero flag, jump if the FN is indeed string-valued. | ||
27F0 | JR Z,SF_SYN_EN | |||
27F2 | SET 6,(HL) | Otherwise, set bit 6 of FLAGS. | ||
SF_SYN_EN | 27F4 | JP S_CONT_2 | Jump back to continue scanning the line. | |
ii. During line execution, a search must first be made for a DEF FN statement.
|
||||
SF_RUN | 27F7 | RST $20 | Get the first character of the name. | |
27F8 | AND $DF | Reset bit 5 for upper case. | ||
27FA | LD B,A | Copy the name to B. | ||
27FB | RST $20 | Get the next character. | ||
27FC | SUB "$" | Subtract +24, the code for '$'. | ||
27FE | LD C,A | Copy the result to C (zero for a string, non-zero for a numerical function). | ||
27FF | JR NZ,SF_ARGMT1 | Jump if non-zero: numerical function. | ||
2801 | RST $20 | Get the next character, the '('. | ||
SF_ARGMT1 | 2802 | RST $20 | Get 1st character of 1st argument. | |
2803 | PUSH HL | Save the pointer to it on the stack. | ||
2804 | LD HL,($5C53) | Point to the start of the program (PROG). | ||
2807 | DEC HL | Go back one location. | ||
SF_FND_DF | 2808 | LD DE,$00CE | The search will be for 'DEF FN'. | |
280B | PUSH BC | Save the name and 'string status'. | ||
280C | CALL LOOK_PROG | Search the program now. | ||
280F | POP BC | Restore the name and status. | ||
2810 | JR NC,SF_CP_DEF | Jump if a DEF FN statement found. | ||
Report P - FN without DEF.
|
||||
2812 | RST $08 | Call the error handling routine. | ||
2813 | DEFB $18 | |||
When a DEF FN statement is found, the name and status of the two functions are compared; if they do not match, the search is resumed.
|
||||
SF_CP_DEF | 2814 | PUSH HL | Save the pointer to the DEF FN character in case the search has to be resumed. | |
2815 | CALL FN_SKPOVR | Get the name of the DEF FN function. | ||
2818 | AND $DF | Reset bit 5 for upper case. | ||
281A | CP B | Does it match the FN name? | ||
281B | JR NZ,SF_NOT_FD | Jump if it does not match. | ||
281D | CALL FN_SKPOVR | Get the next character in the DEF FN. | ||
2820 | SUB "$" | Subtract +24, the code for '$'. | ||
2822 | CP C | Compare the status with that of FN. | ||
2823 | JR Z,SF_VALUES | Jump if complete match now found. | ||
SF_NOT_FD | 2825 | POP HL | Restore the pointer to the 'DEF FN'. | |
2826 | DEC HL | Step back one location. | ||
2827 | LD DE,$0200 | Use the search routine to find the end of the DEF FN statement, preparing for the next search; save the name and status meanwhile. | ||
282A | PUSH BC | |||
282B | CALL EACH_STMT | |||
282E | POP BC | |||
282F | JR SF_FND_DF | Jump back for a further search. | ||
iii. The correct DEF FN statement has now been found. The arguments of the FN statement will be evaluated by repeated calls of SCANNING, and their 5 byte values (or parameters, for strings) will be inserted into the DEF FN statement in the spaces made there at syntax checking. HL will be used to point along the DEF FN statement (calling FN_SKPOVR as needed) while CH-ADD points along the FN statement (calling NEXT_CHAR as needed).
|
||||
SF_VALUES | 2831 | AND A | If HL is now pointing to a '$', move on to the '('. | |
2832 | CALL Z,FN_SKPOVR | |||
2835 | POP DE | Discard the pointer to 'DEF FN'. | ||
2836 | POP DE | Get the pointer to the first argument of FN, and copy it to CH-ADD. | ||
2837 | LD ($5C5D),DE | |||
283B | CALL FN_SKPOVR | Move past the '(' now. | ||
283E | PUSH HL | Save this pointer on the stack. | ||
283F | CP ")" | Is it pointing to a ')'? | ||
2841 | JR Z,SF_R_BR_2 | If so, jump: FN has no arguments. | ||
SF_ARG_LP | 2843 | INC HL | Point to the next code. | |
2844 | LD A,(HL) | Put the code into A. | ||
2845 | CP $0E | Is it the 'number marker' code, +0E? | ||
2847 | LD D,$40 | Set bit 6 of D for a numerical argument. | ||
2849 | JR Z,SF_ARG_VL | Jump on zero: numerical argument. | ||
284B | DEC HL | Now ensure that HL is pointing to the '$' character (not e.g. to a control code). | ||
284C | CALL FN_SKPOVR | |||
284F | INC HL | HL now points to the 'number marker'. | ||
2850 | LD D,$00 | Bit 6 of D is reset: string argument. | ||
SF_ARG_VL | 2852 | INC HL | Point to the 1st of the 5 bytes in DEF FN. | |
2853 | PUSH HL | Save this pointer on the stack. | ||
2854 | PUSH DE | Save the 'string status' of the argument. | ||
2855 | CALL SCANNING | Now evaluate the argument. | ||
2858 | POP AF | Get the no./string flag into A. | ||
2859 | XOR (IY+$01) | Test bit 6 of it against the result of SCANNING (bit 6 of FLAGS). | ||
285C | AND $40 | |||
285E | JR NZ,REPORT_Q | Give report Q if they did not match. | ||
2860 | POP HL | Get the pointer to the first of the 5 spaces in DEF FN into DE. | ||
2861 | EX DE,HL | |||
2862 | LD HL,($5C65) | Point HL at STKEND. | ||
2865 | LD BC,$0005 | BC will count 5 bytes to be moved. | ||
2868 | SBC HL,BC | First, decrease STKEND by 5, so deleting the 'last value' from the stack. | ||
286A | LD ($5C65),HL | |||
286D | LDIR | Copy the 5 bytes into the spaces in DEF FN. | ||
286F | EX DE,HL | Point HL at the next code. | ||
2870 | DEC HL | Ensure that HL points to the character after the 5 bytes. | ||
2871 | CALL FN_SKPOVR | |||
2874 | CP ")" | Is it a ')'? | ||
2876 | JR Z,SF_R_BR_2 | Jump if it is: no more arguments in the DEF FN statement. | ||
2878 | PUSH HL | It is a ',': save the pointer to it. | ||
2879 | RST $18 | Get the character after the last argument that was evaluated from FN. | ||
287A | CP "," | If it is not a ',' jump: mismatched arguments of FN and DEF FN. | ||
287C | JR NZ,REPORT_Q | |||
287E | RST $20 | Point CH-ADD to the next argument of FN. | ||
287F | POP HL | Point HL to the ',' in DEF FN again. | ||
2880 | CALL FN_SKPOVR | Move HL on to the next argument in DEF FN. | ||
2883 | JR SF_ARG_LP | Jump back to consider this argument. | ||
SF_R_BR_2 | 2885 | PUSH HL | Save the pointer to the ')' in DEF FN. | |
2886 | RST $18 | Get the character after the last argument in FN. | ||
2887 | CP ")" | Is it a ')'? | ||
2889 | JR Z,SF_VALUE | If so, jump to evaluate the function; but if not, give report Q. | ||
Report Q - Parameter error.
|
||||
REPORT_Q | 288B | RST $08 | Call the error handling routine. | |
288C | DEFB $19 | |||
iv. Finally, the function itself is evaluated by calling SCANNING, after first setting DEFADD to hold the address of the arguments as they occur in the DEF FN statement. This ensures that LOOK_VARS, when called by SCANNING, will first search these arguments for the required values, before making a search of the variables area.
|
||||
SF_VALUE | 288D | POP DE | Restore pointer to ')' in DEF FN. | |
288E | EX DE,HL | Get this pointer into HL. | ||
288F | LD ($5C5D),HL | Insert it into CH-ADD. | ||
2892 | LD HL,($5C0B) | Get the old value of DEFADD. | ||
2895 | EX (SP),HL | Stack it, and get the start address of the arguments area of DEF FN into DEFADD. | ||
2896 | LD ($5C0B),HL | |||
2899 | PUSH DE | Save address of ')' in FN. | ||
289A | RST $20 | Move CH-ADD on past ')' and '=' to the start of the expression for the function in DEF FN. | ||
289B | RST $20 | |||
289C | CALL SCANNING | Now evaluate the function. | ||
289F | POP HL | Restore the address of ')' in FN. | ||
28A0 | LD ($5C5D),HL | Store it in CH-ADD. | ||
28A3 | POP HL | Restore original value of DEFADD. | ||
28A4 | LD ($5C0B),HL | Put it back into DEFADD. | ||
28A7 | RST $20 | Get the next character in the BASIC line. | ||
28A8 | JP S_CONT_2 | Jump back to continue scanning. |
Prev: 27B0 | Up: Map | Next: 28AB |