Action: if HL holds 3A colon jump on to LOOK P 2. _1D8B_LOOK_P_1 (the start address doesn't have a colon): if it holds 40h or more, return with carry set; this is a variable letter or the 80-byte, see 80-byte after the end of thealphabet - (on a line number) read the hi-lo line number and put it in 5C43 NEWPPC - read the length of the line from the two bytes following the line number - add it to the start address; the result is the start address of the next line - make a statement counter zero; it will be counted downwards. _1DA3_LOOK_P_2: call 198B EACH STMT, which decrements thestatement counter and returns with NC if the code in E is matched, not in quotes, within that statement - return on NC - (no match in this statement) jump back to LOOK P 1. Exit: RET, from LOOK P 2 if there was a "find" or LOOK P 1 if not. Output parameters: D holds the statement number as a negative value, FF for statement 1, FE for 2, etc - E is unchanged - 5C43 NEWPPC holds the line number - the carry flag shows C if no match was found anywhere,NC if one was found. Called from: 1D64 F LOOP 1DED READ 2808 SF FIND DEF LOOK P 1 1D8B (1D86 LOOK PROG) Exit from: 1DA3 LOOK P 2 (1D86 LOOK PROG) LOOK P 2 1DA3 (1D86 LOOK PROG) Exit from: 1D86 LOOK PROG look-up routines see tables LOOK VARS subroutine 28B2 In scanning a BASIC program for execution, it is necessary to find or create a variable in the variables area corresponding to a variable in assignment used in the BASIC, before a value can be assigned to it. The first byte of each variable in the variables area is coded to show its type, in thefirst 3 bits; the remaining bits indicate the letter, from 00001= "a" to 11010 = "z"; see the index entry variables, and pages 166-8 of the old Handbook, pages 144-6 of the Plus 2 handbook. This coding isn't done in the BASIC; there the letter bits will be the same, but they may be in upper or lower case, and the variable name may include spaces or colour controls, which are all cut out of the version in the variables area. The subroutines LOOK VARS and STK VAR, together with theexit routine VAR A 1 which sometimes intervenes, although formally distinct, are best considered together: in most cases calls to STK VAR directly follow calls to LOOK VARS, or VAR A 1 if it is interpolated. Their purpose is to look in the variablesarea for a variable letter matching the letter in the BASIC and with the correct flag bits for the type of variable, and then: - for a numeric variable, return the address in the variables area of the last letter of the variable name - for a numeric array, return the address in the variables area of the first byte of the specified element, a FP number - for a string or string array, put the string parametersof the specified element on the calculator stack, and carry out a slicing operation if this is called for;_all strings and string arrays are treated as arrays of single characters - check the syntax; STK VAR is called for this purpose only by 2C05 D RPORT C. NB 1. Finding an element in an array; the loop in SV COUNT. Ifthe element whose value is to be read is (x,y,z,...,r) in an array dimensioned (a,b,c,...,i), then - there are a*b*c*...*i elements in the string of elements in the variables area - in view of the way these elements are arranged, the onelooked for is serial (x - 1)*b*c...*i + (y - 1)*c*...*i + (z - 1)*...*i + ... + r This serial is built up in stages on each turn of the loop as X = zero * a + (x - 1) Y = X * b + (y - 1) = (x - 1)*b + (y - 1) Z = Y * c + (z - 1) = (x - 1)*b*c + (y - 1)*c + (z - 1) and finally R = (x - 1)*b*c...*i + (y - 1)*c*...*i + ... + r - 1 which is the serial of the element before the one sought for. NB 2. Repeated slicing: PRINT a$(7,3,4 TO 13)( TO 3)(2) is perfectly good syntax, and will be executed: in this case itwill print the second of the first three of characters four to thirteen of a$(7,3), ie the fifth character. This seems rather pointless, and isn't mentioned as far as I know in any of the handbooks. See SV SLICE. NB 3. There is an oddity in V SPACES, which perhaps should even be called an error: it doesn't skip over colour controls inthe BASIC. Colour controls are cut out of variable names when the variable is established in the variables area, but they are left in the BASIC. Colour controls at the_start of a variable name are skipped in the SCANNING loop, but not colour controls in the middle of the name. If you write 10 LET the yellow one=7 your variable is stored with the long name "theyellowone"; any colour controls you may have put in the BASIC, and the spaces, are cut out of it. If you now write 30 PRINT the yellow one with no colour controls, and RUN, the computer will correctly print 7. But if you put E-mode 6 before "yellow" and E-mode 7 after it in line 30, so that the word "yellow" prints in the BASIC with yellow PAPER - whether or not this matches what you put in line 10 - you will get the error report "Variable not found, 30:1", because the colour controls within the name don't match. And if you make your program 10 LET the yellow one=7 20 LET the yellow one=3046 30 PRINT the yellow one with colour controls in line 20 but none in 10 or 30, and RUN, the computer will print "7", apparently ignoring line 20. It hasmade a variable "theyellowone" for line 10 and given it the value 7; it has failed to match this with the variable in line 20, so has made a_second_variable_with_the_identical_name and given it the value 3046; but when it looks in the variables areafor the value to print it out, it finds the old one first, and ignores the second. If you enjoy crashing computers, try 1 LET the yellow one = 7: GO TO 1 with colour controls in the variable name. It will add more andmore variables all called "theyellowone" until it reports "Out of memory". NB 4. For the error in the output flagging of LOOK VARS, see 0672 SA V OLD under 0605 SAVE ETC. Input parameters (LOOK VARS): none - 5C5D CH ADD holds the address of the first byte of thevariable in the BASIC - 5C0B DEFADD will hold a DEF FN address if a user- defined FN is being evaluated; in this case variable values for simple variables from the corresponding DEF FN statement are to be used in preference to variables in the variables area. Otherwise 5C0B DEFADD holds zero. Arrays and long-name variablesaren't allowed in DEF FNs. Action: set bit 6 of FLAGS; provisionally a numeric variable - read the byte at the BASIC pointer and call 2CBD ALPHA - if it isn't a letter code report "Nonsense in BASIC" - AND it with 00011111b/1Fh to isolate the five bits zero -> 4 indicating the letter - keep the result, now the "discriminator byte" of the variable in assignment - read the next byte - if it is 28h (, jump on to V RUN/SYN; numeric array - set bit 6 of the discriminator byte; this is right forall kinds of variables except "long names" - if the byte just read is 24h $, jump on to V STR VAR - (not a string variable or array) set bit 5 of the discriminator byte; this is right for numeric variables including looping variables - call 2C88 ALPHANUM and if the last byte read isn't a letter or digit jump on to V TEST FN. _28D4_V_CHAR (long name of a numeric variable, flag bits 101): call ALPHANUM again and jump on to V RUN/SYN if on loopingback the byte isn't a letter or a digit - (more codes in the long name) zero bit 6 of the discriminator byte - read the next byte and loop back to V CHAR. _28DE_V_STR_VAR (byte 2 was 24h $): move on the BASIC pointer - zero bit 6 of FLAGS; "string" flag. _28E3_V_TEST_FN: if 5C0B DEFADD is zero, jump on to V RUN/SYN - (DEF FN is in use) jump on to STK F ARG; if it doesn'tfind a matching variable in the DEF FN statement it will jump back to V RUN/SYN. _28EF_V_RUN/SYN: in syntax checking, AND the discriminator byte with 11000000b/E0h and set its bit 7 for a syntax flag; now all its bits are zero except bit 7 and, if it isn't a long name or a number array, bit 6 - jump on to V SYNTAX. _28FD_V_RUN (run time): get the address of the start of the variables area from 5C4B VARS _2900_V_EACH: get the discriminator byte of the next variable in the variables area - AND it with 01111111b/7F - if this comes out zero, jump on to V 80 BYTE; it is the 80-byte marking the end of the variables area and there is no match to the variable in assignment. - (it isn't zero, and the only change has been in clearing its bit 7) check it with the discriminator byte constructed for the variable in assignment - if they don't match, jump on to V NEXT; because bit 7 isn't compared, this doesn't distinguish one-letter numeric variables (011) from looping variables (111), or simple strings (010) from string arrays (110) - (variable in assignment matches variable in variables area) rotate the discriminator byte left and double it; the original bit 6 goes into the carry and the original bit 5 goes to hi bit - if bit 5 was zero jump on to V FOUND 2; strings and all arrays - if bit 6 was set jump on to V FOUND 2; short names andloop variables. _2912_V_MATCHES (this leaves long names): move on the variables area pointer _2913_V_SPACES: read the BASIC pointer and move it on - if the BASIC byte is a space jump back to V SPACES; skip it - make the BASIC byte lower case - if it now matches the byte at the variables pointer jump back to V MATCHES; test another character. - try it with bit 7 set; the last character of the name in the variables area is so marked - if they still don't match jump on to V GET PTR; this isn't the right variable - (last character in the variables area matches the namein BASIC) test the next BASIC byte with 2C88 ALPHANUM - if it isn't alphanumeric jump on to V FOUND 1; but if there are more characters in the BASIC name, it doesn't count asa match. _2929_V_GET_PTR and_292A_V_NEXT (the variable names don'tmatch): put the variables pointer back on the discriminator byte - call 19B8 NEXT ONE; it puts the pointer on the discriminator byte of the next variable - jump back to V EACH to check this one with the discriminator byte in the BASIC. _2932_V_80_BYTE (nothing in the variables area matches the discriminator byte from BASIC) set the hi bit of the discriminator. _2934_V_SYNTAX: read the byte at the BASIC pointer; this was left after the last letter of the variable name in the BASIC, or after the "$" if there was one - if it is 28h (, jump on to V PASS; an array - set bit 5 of the discriminator; "simple variable" - jump on to V END. _293E_V_FOUND_1 and_293F_V_FOUND_2: clear the stack - restack the variables pointer - read the byte at the BASIC pointer; this was left after the last variable letter in BASIC, or the "$" if any. _2943_V_PASS: step on the BASIC pointer till it is on a byte which isn't a letter or digit [quite unnecessary, as the notes indicate]. _294B_V_END: recover the variables pointer - rotate the discriminator left and read what was bit 5 - return from LOOK VARS. (See STK VAR below.) _2951_STK_F_ARG (run time, and 5C0B DEFADD has a DEF FN address): set a pointer on the first variable letter on the leftside of the FN statement - if the pointer is on 29h ), jump back to V RUN SYN; the DEF FN has no arguments. _295A_SFA_LOOP: read the pointer and set bits 5 and 6 of the discriminator for a simple numeric variable - read the next byte, and if it is 0E number marker jumpon to SFA CP VR - (the variable is a string) call 28AB FN SKPOVER, whichputs the pointer on the "$", and move on one; now it is on the 0E marker just before the string parameters - zero bit 5 of the discriminator; "string". _296B_SFA_CP_VAR: check the DEF FN variable letter with the discriminator byte - if they match jump on to SFA MATCH - (no match yet) move the DEF FN pointer on five bytes and call 28AB FN SKPOVER; now it is on comma or 29h ) - if it is 29h ) jump back to V RUN/SYN; the variable isn't in the DEF FN statement - (it must be a comma) call 28AB FN SKPOVER again; now it is on the next variable letter - loop back to SFA LOOP. _2981_SFA_MATCH: check bit 5 of the discriminator byte and jump on to SFA END if it is set; this marks a numeric variable - (a string variable) move the pointer on to the first byte of the string parameters - set DE on the stack end and call 33C0 MOVE FP to copy the five string parameter bytes on to the end of the calculator stack. _2991_SFA_END: drop the top two values on the machine stack; they were the variables pointers - make flags for NC and NZ, signalling "variable found" and "no need to call STK VAR"; because the string parameters, ifit was a string, have been stacked already - return from LOOK VARS. At this point - HL holds a start address for the variable: if nothing was found to match in the variables area, the first letter of the variable name in the BASIC line, otherwise the last letter of the name in the variables area - C holds a discriminator byte "abcxxxxx": a is one for syntax checking, zero for run time bcxxxxx indicates what was being looked for, bc is 00 for number arrays 01 for number variables with long names 10 for strings and string arrays 11 for number variables with short names xxxxx indicate the variable letter in run time, all zero in syntax checking. - the zero flag shows Z to signal "looking for an array or string" or NZ to signal "simple numeric variable". It was made NZ in V END if bit 5 of B was set; this became bit 6 after the rotate instruction. This B is a version of the "abcxxxxx" byte copied from C in V RUN/SYN: its bit 5 was cleared in the first section of LOOK VARS, then set in the same section if no "(" followed the numeric variable letter in the BASIC, or in V SYNTAX if no "(" followed the "$" of the string variable letter.But V SYNTAX only operates in syntax checking, so in run time the flag will show Z for a simple string as well as an array - the carry flag in run time shows C if a matching variable wasn't found, NC if it was; in syntax checking it show carry anyway.