Basic V Guide ~~~~~~~~~~~~~ Contents ~~~~~~~~ Introduction History Features Constants Variables Keywords Line Numbers Operators Assignment Operators Indirection Operators Array Operations Built-in Functions Pseudo Variables Procedures and Functions Error Handling Issuing Commands to the Underlying Operating System Statement Types Statements Commands The Program Environment Screen Output VDU Commands PLOT Codes Basic Keywords, Commands and Functions Introduction ~~~~~~~~~~~~ The following notes give a brief introduction to Basic V and to the environment that the interpreter emulates. They describe the entire language but not in any great detail; more attention is given to features specific to this version of Basic. Useful information can be found on the web site 'The BBC Lives!' where scanned version of manuals such as the 'BBC Microcomputer User Guide' can be found. The information in these manuals is not 100% relevant to Basic V but they are good for background information and many details of Basic II, the predecessor of (and to all intents and purposes, a strict subset of) Basic V. These notes describe the Basic language. The file 'use' contains information on how to use the interpreter and on the features and limitations of the different versions of the program. History ~~~~~~~ At the start of the 1980s the British Broadcasting Corporation was looking for a microcomputer to be used for their series 'The Computer Programme'. The machine chosen became known as the 'BBC Micro' and it was made by Acorn Computers. It was an extremely potent and flexible little computer that some people still use to this day. The dialect of Basic on it was called 'BBC Basic'. This was an extended Basic that added such features as procedures and multi-line functions. It was also one of the fastest Basic interpreters available on an eight-bit computer. The interpreter was well integrated with the rest of the machine: it was possible to directly call operating system functions from Basic programs and there was also a built-in assembler. If something could not be done in Basic or was too slow it was possible to write the code in assembler. Many programs were written that used a combination of Basic and assembler. Compilers and interpreters for languages such as BCPL, C and Pascal were written for the BBC Micro, but by far the most popular language was Basic. In 1987 Acorn brought out the Archimedes. This included a new version of the BBC Basic interpreter that had many additional features such as 'CASE' statements and multi-line 'IF' statements. It kept its reputation for speed. This version of Basic was called 'Basic V' and it is the dialect of the language implemented by this interpreter. The operating system that ran on the Archimedes and the machines that have succeeded it over the years is called 'RISC OS'. This was designed and written by Acorn Computers. Features ~~~~~~~~ The main features of Basic V are: 1) It is a structured Basic with a full range of statement types such as WHILE and REPEAT loops, a block IF statement and a CASE statement. 2) It has procedures and multi-line functions which can have local variables and arrays. 3) It has 'indirection operators' which allow data structures to be constructed and manipulated. Memory can be allocated from the Basic heap that can be referenced using these operators. (This is not to say that the dialect includes data structures per se but they can be set up and used in a way that appears to be reminiscent of BCPL.) 4) The Acorn-written interpreters include an assembler. Programs can be written using a mix of Basic and assembler. All the features of the Basic interpreter are available to the assembler, so that, for example, functions written in Basic are used as macros. 5) Speed: the interpreter is very fast. Notation ~~~~~~~~ A few words on the notation used in these notes might be in order. In describing the syntax of statements, parts of the statement are often put in angle brackets . The purpose of this is to say what goes at that part of the statement, for example: GOSUB This says that the keyword GOSUB is to be followed by a line number if a GOSUB statement is used in the program. Another example: ON ERROR This one says that in an 'ON ERROR' statement, the keywords 'ON ERROR' are followed by one or more Basic statements. In some cases, parts of a statement are in square brackets, for example: IF THEN [ ELSE ] This means that that part of the statement is optional. In the example, the '[ ELSE ]' part of the statement can be omitted. Constants ~~~~~~~~~ The interpreter supports five types of variable: - Decimal integer - Hexadecimal integer - Binary integer - Floating point - String Hexadecimal constants begin with a '&' and binary ones with a '%'. Strings are enclosed in '"'. It is possible to embed a '"' is a string by preceding it with another '"'. Examples: &FFFF &123456 %1001101 %1 "abcdefghij" "klmnop""qrst" Variables ~~~~~~~~~ The interpreter supports three main types: Integer e.g. abc% Floating point e.g. def String e.g. ghi$ Integer variables are 32 bits wide. A variable is denoted as being an integer by having a '%' at the end of the name. Floating point variables are 64 bits wide. If a variable does not have either a '%' or a '$' suffix then it is a floating point variable. String variables have a '$' suffix at the end of their name. They can refer to strings that have a maximum length of 65,536 characters. Note that it is possible for variables of different types to have the same name, for example, 'abc%', 'abc' and 'abc$' can all exist at the same time. The '%' and '$' are considered to be part of the name. Similarly, it is possible to have arrays and simple variables of the same name, for example: abcd$ <-- String variable abcd$() <-- String array What happens is that the '(' is considered to be part of the name of the array. Variable names are case sensitive, so that 'abcd' and 'AbCd' are different variables. Basic V has two classes of variables, the normal dynamic variables that are created when the program runs and a set of what are called 'static' variables which comprises of the integer variables A% to Z%. These variables are independent of any program in that their valaues are not reset or changed when a program is loaded or modified. They can, for example, be used to pass values from one program to another. Keywords ~~~~~~~~ Keywords are Basic's reserved words. They are split into two types in this interpreter, Basic keywords and Basic commands. Examples of the former are 'IF', 'ENDPROC' and 'WHILE'. Examples of commands are 'LOAD', 'LIST' and 'NEW'. A complete list of keywords is given at the end of these notes. Basic keywords have to be in upper case. On the other hand, commands can be given in either lower or upper case to make it more convenient to type them in. The interpreter tries to be clever with keywords. In general keywords cannot be used as variable names but there are cases where if a keyword is followed by a letter it is not identified as a keyword, for example, 'COUNT' on its own is a keyword but 'COUNTER' can be used as a variable without any problems. The keywords taht can are treated in this way are marked with a '*' in the keyword list at the end of the notes. Line Numbers ~~~~~~~~~~~~ Each line in a Basic program has a line number. This is used when editing a program at the command line and in the program by such statements as 'GOTO', 'GOSUB', 'ON GOTO', and 'RESTORE'. Basic V is a structured Basic and line numbers are largely superfluous if statement types such as these are not used. They are still needed to identify the line on which an error was detected when a program runs. Programs and libraries can be written without line numbers using a text editor such as 'vi'. Line numbers will automatically be added when the program is loaded. Similarly, programs can be saved without line numbers, although the default is to include them. Line numbers are in the range 0 to 65279. Operators ~~~~~~~~~ Basic V supports the usual range of operators. The following list details what is available. The operators are given in priority order, with operators of the same priority grouped together. From highest to lowest priority they are: ^ Exponentiation ------------------ * Multiplication / Division DIV Integer division MOD Integer modulus ------------------ + Addition and string concatenation - Subtraction ------------------ = Equals <> Not equals > Greater than < Less than >= Greater than or equal to <= Less than or equal to << Left shift >> Arithmetic right shift >>> Logical right shift ------------------ AND Logical AND ------------------ OR Logical OR EOR Exclusive OR There is a point to watch out for when using the comparison and shift operators. It is not possible to chain these together in an expression, for example: abc% >> 2 <= 10 will give an error. The solution is to put brackets around the first part of the expression thus: (abc% >> 2) <= 10 This is a feature of Basic V. Assignment Operators ~~~~~~~~~~~~~~~~~~~~ As well as using '=' for assignments in the normal way, Basic V has two other assignment operators: += -= '+=' adds to the variable and '-=' subtracts it. Examples: abc% += 1 ghi(N%) -= count xyz$ += "abcd" table%!offset% -= X% $(table%+name%) += "xyz" Indirection Operators ~~~~~~~~~~~~~~~~~~~~~ These are equivalent to 'peek' and 'poke' in other versions of Basic except that they are far more flexible and powerful. Strictly speaking these are not proper operators but language constructs. There are two types of operator, unary and dyadic. The unary ones are: ? Reference to a one byte integer ! Reference to a four byte integer | Reference to a floating point value $ Reference to a string The dyadic operators are: ? Reference to a one byte integer ! Reference to a four byte integer Note that there are not dyadic versions of '$' and '|'. Unary operators can be followed by a variable, array reference or an expression in parentheses. For dyadic operators, the item before the operator must be a variable or array reference. A variable, array reference or expression in parentheses follows the operator. Examples of unary operators: $pointer% !abc% ?(abc%+10) $text% $text% = "abc" Examples of dyadic operators: pointer%!offset% abc%?next% array%(N%)!field% The operators all work in the same way. The value of the expression after the operator (unary version) or of the variable before the operator (dyadic version) is interpreted as an address. The value after the operator in the dyadic version is a byte offset from that address. Indirection operators cannot be chained together, that is, they cannot be used in an expression such as: pointer%!offset%!field% In general, indirection operators can be used in the same way and places as normal variables and the two forms of reference can be freely mixed. Examples: IF $text%="quit" THEN STOP table%!offset% = table%!offset2 !(table%+offset%) = !(table%+offset2) abc = |address+1.0 PROCabcd(!table%, table%!4) FOR table%!8=1 TO 10: NEXT The interpreter limits the range of addresses that can be read from or written to using indirection operators to the Basic workspace. It is not possible to access any location outside this block of memory. Indirection operators can be used to built up and manipulate data structures. However they are not true data structures in the sense of structs in a C program and there are no checks on the legality of references (beyond ensuring that the addresses are in range). It is possible for a program to allocate memory from the Basic heap to be used used for data structures and accessed via the indirection operators. A special form of the DIM statement is used for this: DIM table% 100 Strictly speaking this allocates a byte array with indexes 0 to 100. From a more practical point of view, it allocates a 101 byte block of memory and puts its address in table%. This block can then be manipulated using the indirection operators as desired, for example: $table%="an error message" table%!0 = 0: table%!4 = 99 In fact, blocks of memory allocated this way can only be referenced via indirection operators. Array Operations ~~~~~~~~~~~~~~~~ The interpreter supports some arithmetic operations on entire arrays. There are some restrictions: the arrays have to be the same size (number of dimensions and size of each dimension) and of exactly the same type. Also, general expressions involving arrays are not allowed, nor is it possible to return an array as the result from a function. What is allowed is as follows: Assignment ---------- = The contents of are copied to = All elements of array are set to = , , ... , Each expression is evaluated and then assigned to the x'th element of the array . There can be fewer expressions than there are elements in the array, in which case the remaining array elements are left unchanged. += , -= Each element of is added to . += , -= The expression is evaluated and the result added to . Examples: abc%() = def%() ghi$() = "test" jkl() = 0.0, 1.1, 2.2, 3.3, FNxyz(4.4) abc%() += def%() jhl() -= PI Addition and Subtraction ------------------------ = + Add the corresponding elements of and and store the result in the same element in . = - Subtract the elements in from the corresponding element in array <2> and store the result in . = + = + Add to each element of , storing the result of each addition in the corresponding element of . = - = - Subtract from each element of , storing the result of each subtraction in the corresponding element of . Examples: abc%() = def%() + ghi%() jkl() = mno() - pqr() aaa$() = bbb$() + "ccc" + FNddd(eee$) abc%() = 1 - def%() Multiplication and Division --------------------------- = * Multiply each element of by the corresponding element in and store the result in . = / Divide each element of by the corresponding element in and store the result in . = DIV Carry out an integer division of each element of by the corresponding element in and store the result in . = MOD Carry out an integer division of each element of by the corresponding element in and store the remainder in . = * = * Multiply each element of by the value and store the result in the corresponding element in . = / Divide each element of by the value and store the result in the corresponding element in . = / Divide by each element of and store the result in the corresponding element in . = DIV Carry out an integer division of each element of by the value and store the result in the corresponding element in . = DIV Carry out an integer division of by each element of and store the result in the corresponding element in . = MOD Carry out an integer division of each element of by the value and store the remainder in the corresponding element in . = MOD Carry out an integer division of by each element of and store the remainder in the corresponding element in . Examples: abc() = def() * ghi() abc() = 10.0 * ghi() jkl%() = mno%() MOD 100 abc() = 1 / abc() Matrix Multiplication --------------------- = . Perform a matrix multiplication of and and store the result in . Note that '.' is used as the matrix multiplication operator. Built-in Functions ~~~~~~~~~~~~~~~~~~ The interpreter has a fairly standard set of functions. One feature of this dialect of Basic is that many of the functions look like monadic operators, for example, a call to the 'LEN' function can be written as 'LEN abc$' as well as 'LEN(abc$)'. Function names can often be abbreviated when typing them at the command line. The abbreviated version of the name is the first few characters of the name followed by a dot, for example, the 'LE' is the abbreviated form of 'LEFT$('. The names are given in full when the program is listed. Following is a list of functions implemented and a summary of their actions. More detailed information on the vast majority of them can be found in the manuals on the 'The BBC Lives!' web site. Entries marked with a '*' after the name are functions added in this interpreter. represents a simple expression that consists of just a variable name, array reference or constant or a complete expression in parentheses. is a full expression. Sometimes this is written as or to qualify the type of expression, or abbreviated to to reduce clutter. is a reference to a whole array. ABS Use: ABS Returns the absolute value of the numeric value ACS Use: ACS Returns the arccosine of the numeric value ADVAL Use: ADVAL This is an unsupported function. Either use of it is flagged as an error or it returns zero, depending on the options used to start the interpreter. ARGC * Use: ARGC Returns the number of parameters on the command line. This will be zero if there are no parameters. ARGV$ * Use: ARGV$ Returns parameter number on the command line as a string. ARGV$ 0 returns the name of the program. ARGV$ 1 is the first parameter, ARGV$ 2 the second and so forth. ARGV$ ARGC is the last parameter. ASN Use: ASN Returns the arcsine of the numeric value ATN Use: ATN Returns the arctan of the numeric value BEAT Use: BEAT Returns information from the RISC OS sound system. This function returns zero. BGET Use: BGET# Returns the next byte from the file with handle CHR$ Use: CHR$ Returns a string consisting of a single character with ASCII code COLOUR Use: COLOUR(, , ) This takes the colour with the specified colour components and returns a number that represents the closest match to that colour in the current screen mode. This value is for use with the 'COLOUR OF' and 'GCOL OF' statements. It has no meaning otherwise. Example: red = COLOUR(255, 0, 0): COLOUR OF red COS Use: COS Returns the cosine of the numeric value COUNT Use: COUNT Returns the number of characters printed on the current line by PRINT. DEG Use: DEG Converts the angle from radians to degrees. DIM Use: a) DIM() b) DIM(, ) a) returns the number of dimensions in array . b) returns the highest index of dimemsion of array . END Use: END Returns the address of the top of the Basic heap. EOF Use: EOF# Returns TRUE if the file with handle is at end of file. ERL Use: ERL Returns the number of the line that contained the last error encountered by the interpreter or zero if no error has been seen. ERR Use: ERR Returns the error number of the last error encountered by the interpreter or zero. EVAL Use: EVAL Evaluates the string as if it were an expression in a statement in the program and returns the result. EXP Use: EXP Returns the exponentional of the numeric value . FALSE Use: FALSE The function returns the value corresponding to 'false' in the interpreter (zero). GET Use: GET Returns the next character pressed on the keyboard as a number, waiting if there is not one available. GET$ Use: a) GET$ b) GET$# a) Returns the next character pressed on the keyboard as a one character string, waiting if there is not one available. b) Returns the next line from the open file with handle as a character string. INKEY Use: INKEY If numeric value is greater than or equal to zero, return the next character pressed on the keyboard as a number but only wait for centiseconds. Return -1 if no key pressed in that time. If numeric value is -256, return a number that identifies the operating system under which the program is running. (See the 'use' guide for the values returned.) If numeric factor is less than zero and greater than -256, return TRUE if the key with RISC OS internal key number is being pressed otherwise return FALSE. INKEY$ Use: INKEY$ This is the same as INKEY but returns its result as a single character string. In the case of a keyboard read with timeout, an empty string is returned if the time limit expires instead of -1. INSTR( Use: INSTR( , [, ]) Search string for the string returning the index (starting from 1) of the start of in if the string is found otherwise return zero. is an option expression that gives a starting point in at which to start looking for . INT Use: INT Returns the integer part of number , rounding down (towards minus infinity). LEN Use: LEN Returns the length of string . LISTO * Use: LISTO Returns the current LISTO setting. LN Use: LN Return the natural log of number . LOG Use: LOG Returns the base 10 log of number . MOD Use: MOD Returns the modulus (square root of the sum of the squares) of numeric array . MODE Use: MODE Returns the number of the current RISC OS screen mode. NOT Use: NOT Returns the logical negation (ones complement) of numeric value . OPENIN Use: OPENIN Opens the file named by the string for input and returns its numeric handle or zero if it cannot be opened. OPENOUT Use: OPENOUT Opens the file named by the string for output and returns its numeric handle. If the file exists already its length is reset to zero. OPENUP Use: OPENUP Opens the file named by the string for both input and output and returns its numeric handle. PI Use: PI Returns the value PI. POINT( Use: POINT(,) Returns the colour number of the point on the graphics screen with graphics coordinates (, ). POS Use: POS Returns the offset (from 0) of the text cursor from the left-hand side of the screen. QUIT Use: QUIT Returns TRUE if the interpreter was started with the option '-quit', that is, the interpreter will be exited from when the Basic program finishes running. RAD Use: RAD Convert the angle given in degrees to radians. REPORT$ Use: REPORT$ Returns the message for the last error encountered. RND Use: a) RND b) RND() c) RND(0) d) RND(1) e) RND() a) Return a pseudo-random number in the range -2147483648 to 2147483647 b) Initialises the random number generator with seed value . c) Returns the last number generated by RND(1). d) Returns a floating point number in the range 0 to 1. e) Returns an integer number in the range 1 to . SGN Use: SGN Returns -1 if the numeric value is less than zero, zero if it is zero or 1 if it is greater than zero. SIN Use: SIN Returns the sine of numeric value . SQR Use: SQR Returns the square root of numeric value . STR Use: a) STR b) STR~ a) Converts the numeric value to a decimal string. b) Converts the numeric value to a hexadecimal string. STRING$( Use: STRING$( , ) Returns a string made from the string repeated times. SUM Use: SUM If is a numeric array it returns the sum of all of the elements of the array. If is a string array it returns a string made from all of the elements of concatenated. SUM LEN Use: SUM LEN Returns the total length of all of the strings in string array . TAN Use: TAN Returns the tangent of numeric value TEMPO Use: TEMPO Unsupported RISC OS feature. The function returns zero or generates an error depending on intepreter command line options. TINT Use: TINT(,) Returns the TINT value of the position with x and y graphics coordinates and on the screen in 256 colour modes. TOP Use: TOP Returns the address of the first byte after the Basic program. TRACE Use: TRACE Returns the handle of the file to which TRACE output is being written or zero if a file is not being used. TRUE Use: TRUE Returns the value used by the interpreter for 'true' (-1). USR Use: USR Calls machine code at address . Not implemented this interpreter except in one special case. See the 'use' guide. VAL Use: VAL Converts the string to a number. VERIFY( * Use: VERIFY(, [, ] ) Returns the offset of the first character in string expression that is not in string or zero if all characters in are in . is the optional position at which to start the search. VDU Use: VDU Returns the value of the RISC OS mode variable given by . This can be used to determine such things as the screen width, the number of colours and so forth. Refer to the section 'Mode Variables' below for more details. VPOS Use: VPOS Returns the offset (from zero) from the top of the screen of the text cursor. WIDTH Use: WIDTH The function returns the current value of 'WIDTH' (the width of the current line as set by the program) or zero if a line width has not been defined via the WIDTH statement. XLATE$( * Use: a) XLATE$() b) XLATE$(, ) a) Returns the string expression with all upper case characters converted to lower case. b) Returns the string expression with the characters translated using string expression or string array . Characters in are replaced with the character in the position corresponding to the ASCII code of the original character. Pseudo Variables ~~~~~~~~~~~~~~~~ Pseudo variables are a half way house between a function and a variable. When they appear in the right hand side of an expression they are functions but they can also appear on the left hand side of an expression too. Pseudo variables cannot follow the keyword 'LET', that is, using them in statements such as: LET FILEPATH$="." is not permitted. Similarly, they can only be followed by '=', that is, assignments of the form '+=' are not allowed. EXT As a function: Use: EXT# Returns the size of the open file with the handle . Example: oldsize% = EXT#file% On left-hand side: Use: EXT# = Change the size of the open file with handle to bytes. Example: IF action$="delete" THEN EXT#file% = 0 FILEPATH$ As a function: Use: FILEPATH$ Returns the list of directories to search when trying to find a library or a program. Example: PRINT"Current search path: ";FILEPATH$ On left-hand side: Use: FILEPATH$ = Sets the directory list to the string expression . Note that there are no checks to make sure that the directory names are valid. Setting FILEPATH$ to an empty string is allowed. Example: FILEPATH$ = "/home/mine,/usr/local/basic" HIMEM As a function: Use: HIMEM Returns the address of the end of the Basic workspace. Example: PRINT "Top of workspace is at ";~HIMEM On left-hand side: Use: HIMEM = This sets the address of the top of the Basic workspace to the value of the numeric expression . If the new value of HIMEM puts it in the Basic program or outside the Basic workspace, the statement is ignored. Example: HIMEM = HIMEM-1000 The places where HIMEM can be changed are limited. It cannot be altered in a procedure, function or subroutine, nor in the body of a loop. The only safe place to change it is at the start of a program. LEFT$ As a function: Use: LEFT$( [, ) Returns the left-hand characters from the string . can be omitted, in which case with the last character removed is returned. Examples: LEFT$(abc$, 4) LEFT$($table%, 10) LEFT$(xyz$(X%)) On left-hand side: Use: LEFT$( [, ]) = This replaces the left-hand characters of string with the string expression . says how many characters to replace. If it is omitted then the length of is used. If this value exceeds the original length of then the length of is used instead. can be a normal string variable, an array reference or a string referenced by the string indirection operator. Examples: LEFT$(abc$)="1234" LEFT$(abc$, 2)="abcdefgh" LEFT$(xyz$(X%), 5)="123" LEFT$($table%, 3)="pqrst" LOMEM As a function: Use: LOMEM Returns the address of the start of the Basic heap Example: PRINT"Variables start at ";~LOMEM On left-hand side: Use: LOMEM = This changes the address of the start of the Basic heap to the numeric value . All of the variables created so far are discarded when LOMEM is changed. If the value is outside the range TOP to HIMEM it is ignored. The assignment is also ignored if LOMEM is changed in a function or procedure. Examples: LOMEM = LOMEM+1000 MID$ As a function: Use: MID$(, [, ] ) Returns a substring from the string starting at character position . The substring is of length characters. can be omitted, in which case the the string from the 'th character to the end of the string is returned. If is negative or exceeds the length of the string the empty string is returned. If is negative or exceeds the number of characters in the string, the original string is returned. Examples: A$ = MID$(B$, 10) A$ = MID$(B$, 10, 20) A$ = MID$($table%, 5, 10) On left-hand side: Use: MID$(, [, ] ) = The characters of the string starting at character position are overwritten by characters from string . is optional and says how many characters are to be taken from . If it is omitted then all of is used. Only the existing characters of are overwritten. The length of the string is never changed. If is negative then is overwritten from the start of the string. If it exceeds the length of then nothing is changed. If is negative then the length of is used instead. Examples: MID$(A$, 5) = "ABCD" MID$(A$, 10, 10) = X$ + "abcdefghijklmnop" MID$($table%, 10) = "12345" PAGE As a function: Use: PAGE Returns the address of the start of the Basic program. Example: PRINT"The program starts at ";~PAGE On left-hand side: Use: PAGE = This sets the address of the start of the Basic program in memory to . Any program currently loaded is discarded. The change is ignored if the value of is outside the range of the value of PAGE when the interpreter was started to HIMEM. Note: one trick possible with the Acorn interpreter is to hold several programs in memory at the same time and to switch between them by altering PAGE. This does not work with the current version of this interpreter. Example: PAGE = PAGE + 1000 PTR As a function: Use: PTR# Returns the value of the offset in bytes of the file pointer in the open file with handle . Example: place = PTR# thefile% On left-hand side: Use: PTR# = Sets the file pointer of the open file with handle to . This is offset into the file in bytes. Example: PTR# thefile% = 0 RIGHT$ As a function: Use: RIGHT$( [, ] ) Returns a string containing the right-most characters from the string . It is possible to omit , when just the last character is returned. If is zero or negative, the empty string is returned. If it exceeds the length of , the original string is returned. Examples: RIGHT$(A$, 5) RIGHT$(X%) + RIGHT$(Y$) Om left-hand side: Use: RIGHT$( [, ]) = The right-most characters of the string are overwritten with character from . If is omitted, the length of the string is used instead. If it is zero or negative, is left unchanged. The length of the string is never changed. Examples: RIGHT$(A$) = "1234" RIGHT$(A$, 5) = "abcdefgh" RIGHT$($table%, 1) = A$ TIME As a function: Use: TIME Returns the current value of the centisecond counter. This is a 32-bit timer updated one hundred times per second, although the real accuracy depends on the underlying operating system. Example: newtime = TIME+100 On left-hand side: Use: TIME = Sets the centisecond counter to . Example: TIME = 0 TIME$ As a function: Use: TIME$ Returns the current date and time as a string in the form: "www,dd mmm yyyy.hh:mm:ss" Example: now$ = TIME$ On left-hand side: Use: TIME$ = Sets the date and time to the string expression . This feature is not implemented. Procedures and Functions ~~~~~~~~~~~~~~~~~~~~~~~~ Basic V has both procedures and multi-line functions. They can both take parameters of any sort, including arrays, and it is possible to return values via parameters. They can also have local variables. Procedures and functions are declared in the same way: Procedures: DEF PROC [ ( ) ] Functions: DEF FN [ ( ) ] is the name of the procedure or function. The keywords 'PROC' and 'FN' are considered to be part of the name. is the list of variables to be used as formal parameters. There can be any number of these. Names are separated by commas. Parameters where values are to be returned are preceded by the keyword RETURN. Examples: DEF PROCabc DEF PROCxyz(aa$) DEF FNpqr(X%, abc%, def$) DEF PROCijk(RETURN X%, RETURN Y%) DEF FNmno(array()) DEF PROCpqr(array1$(), RETURN array2$()) When a procedure or function is called, the current values of the variables that are to be used as parameters are saved before they are set to the values they will take for the call. When the call ends their old values are restored. All of the parameters are evaluated before the values are assigned to the parameter variables. Procedures and functions are called in the normal way, for example: PROCxyz("abcd") value = FNpqr(A%+1, B%+2, C$+"3") Calls to procedures are ended with ENDPROC. Calls to functions end with an '=' followed by the value the function is to return, for example: DEF PROCabc(X%) IF X%=0 THEN ENDPROC Y% = Y% DIV X% ENDPROC DEF FNxyz(X%) IF X%=0 THEN = 0 = Y% DIV X% Note that the name of a function does not include the type of the result it will return. It is possible for the same function to return both string and numeric values, but this is of very limited use. (The only place it will not give an error is in a PRINT statement.) Recursive calls to procedures and functions are allowed. The only limit on the depth of the recursion is the amount of memory available. Procedures and functions can have local variables. These are defined by means of the LOCAL statement. The format of this is: LOCAL for example: LOCAL abc%, def, ghi$, jkl$ Any number of local variables can be declared. It is also possible to have local arrays. These are slightly more complicated in that the array is declared to be local and its dimensions defined separately, thus: LOCAL array() DIM array(100) The scope of local variables is dynamic, that is, they are not restricted to the procedure or function in which they were defined. It is perhaps easier to understand this by considering what happens: when a variable is declared to be local, its value (if the variable exists already) is saved and the value reset to zero (or the empty string). When the procedure or function is returned from, the old value is restored. Declaring a variable to be local does not create a new version of that variable. The same variable is still used but its old value is saved first. Error Handling ~~~~~~~~~~~~~~ Basic V provides two statements for dealing with errors, ON ERROR and ON ERROR LOCAL. ON ERROR is the less sophisticated of the two. If an error is detected, the interpreter ends all loops and returns from all procedures, functions and subroutines before continuing with the statements after ON ERROR. It is not possible to recover from the error and restart the program at the point where it occured. Most of the time all that can be done is to tidy up and abort the program. ON ERROR LOCAL gives more control in that when an error occurs, the statements after the ON ERROR LOCAL are executed but everything is left as it was at the time of the error. This means it is possible to trap errors and recover from them. The statement 'ON ERROR OFF' turns off the trapping of errors in the program. This should be used at the start of an error handler to prevent errors in the error handler causing an infinite loop. To allow for finer control over errors, Basic V also has two statements that allow different error handlers to be used at different points in the program, LOCAL ERROR and RESTORE error. LOCAL ERROR stores details of any existing error handler and allows a new one to be set up. RESTORE ERROR restores the error handler to the saved one. If LOCAL ERROR is used in a function or procedure, the old error handler is restored when the function or procedured calls ends. Care should be taken if using ON ERROR LOCAL within the body of a loop. If an error is detected once the program has exited from the loop, it will branch back into it when the interpreter goes to the statements after ON ERROR LOCAL. The interpreter is unaware of the context of the error handler (that is, it has back into the body of a loop) and unpredictable results might ensue. The function REPORT$ returns the last error message. ERR returns the number of that error and ERL the number of the line in which it occured. Note that this does not say whether the error occured in the program or a library. The REPORT statement displays the last error message. The ERROR statement can be used to report user-generated errors. The interpreter allows the use of the LIST command in programs, so it is possible for error handlers to list the line in which the error occured by the statement LIST ERL Note that the line listed will always be in the Basic program so if the error occured in a library the wrong line will be shown. Some of the errors that the interpreter flags are classed as 'fatal', for example, running out of memory. The Basic program is always abandoned if a fatal error occurs. It is not possible to trap them with ON ERROR or ON ERROR LOCAL. Issuing Commands to the Underlying Operating System ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are two ways in which commands can be send to the operating system on which the interpreter is running. The most flexible way is the OSCLI statement. The second way is to put the command on a line preceded by a '*', for example: 10 *date 20 IF flag THEN *help Whatever follows the '*' up to the end of the line is passed as the command. There is no restriction on the commands that can be issued this way. Statement Types ~~~~~~~~~~~~~~~ Statements are broken into two types, executable statements that can appear in a program and commands that, in general, can only be used on the command line. Many of the keywords and commands can be abbreviated when they are typed in. They will be shown in their complete form when the program is listed. The rule is to type in the minimum number of characters of the keyword and then follow it with a dot, for example: P. can be type instead of 'PRINT'. The minimum abbreviation for each keyword and command is given in the section 'Basic Keywords, Commands and Functions' at the end of these notes. All of the Basic V statement types are described below. However, not all versions of the Basic V interpreter support all of them, in particular, the graphics statements might not be available. Statements ~~~~~~~~~~ In the following: represents a simple expression that consists of just a variable name, array reference or constant or a complete expression in parentheses. is a full expression. Sometimes this is written as or to qualify the type of expression, or abbreviated to to reduce clutter. is a reference to a whole array. is one or more Basic statements. Items in square brackets are optional. BEATS Unsupported statement for controlling the RISC OS sound system. BPUT Syntax: a) BPUT#, [;] b) BPUT#, , , ... , [;] BPUT is used to write data to a file. The handle of the file is given by . is the value to be written. If is numeric, the result of the expression modulo 256 (that is, the least significant byte) is written to the file. If is a string, the complete string is written to the file. If the string expression is followed by a ';' that is all that happens. If the ';' is absent, a 'newline' character (ASCII code 10) is also written to the file after the string. The second form of the BPUT statement is the same as the first except that a list of items to be written separated by commas can be supplied. If the last item is a string expression then a new line character is also written to the file unless the expression is followed by a ';'. Examples: BPUT#outfile, X% BPUT#outfile, A$ IF TRACE THEN BPUT#TRACE, "Result so far is "+STR$X% BPUT#outfile, 1, 2, 3, 4, 5 BPUT#outfile, STR$A%, " ", STR$B% CALL This is an unsupported statement that allows machine code subroutines to be called. CASE Syntax: CASE OF This marks the start of a CASE statement. This statement must be the last one on a line. The complete syntax of a CASE statement is: CASE OF WHEN : WHEN : OTHERWISE: ENDCASE The expression is evaluated. The interpreter then searches for 'WHEN' statements and evaluates each expression after the 'WHEN' in turn and compares it to the result of . If they are equal it starts executing the statements after the 'WHEN' from that point to the next 'WHEN', 'OTHERWISE' or 'ENDCASE'. At this point it jumps to the statements after the ENDCASE. Any number of expressions (limited by the length of the line) can follow the WHEN keyword. They are separated by commas. The expressions after the WHEN keyword do not have to be constants. Any type of expression is allowed and they can be of numeric or string types. The WHEN keyword must be the first item on a line after the line number (except for any intervening blanks). The same goes for the OTHERWISE and ENDCASE keywords. CASE statements can be nested to any depth. Examples: CASE day$ OF WHEN "Monday": PRINT"It is Monday" WHEN "Tuesday", "Thursday": PRINT"It is Tuesday or Thursday" WHEN "Friday": PRINT"It is Friday" WHEN "Wednesday": PRINT"It it the middle of the week" OTHERWISE PRINT"It is the weekend" ENDCASE As general expressions can be used after the WHEN, CASE statements are very flexible. Here one is being used in place of a series of IF statements: CASE TRUE OF WHEN abc%<10: state%=1 WHEN abc%=10: state%=2 WHEN abc%>20 AND abc%<20: state%=3 OTHERWISE: state%=99 ENDCASE CHAIN Syntax: CHAIN CHAIN loads and runs the program named by the string . The programs currently in memory is replaced by this one and the values of all variables lost, with the exception of the static integer variables. Extension: The interpreter searches for the program to load in the directories given by the pseudo-variable FILEPATH$. CIRCLE Syntax: a) CIRCLE ,, b) CIRCLE FILL ,, a) This draws a circle outline centred at (, ) and with a radius in the current graphics foreground colour. b) This version plots a filled circle centred at (, ) and with a radius using the current graphics foreground colour. CLG Syntax: CLG This statement clears the graphics window (normally the whole screen) to the current graphics background colour. CLEAR Syntax: CLEAR CLEAR discards all of the variables and arrays created so far in the program. It also clears the chain of called procedures and functions so it should not be used in a procedure or function. Example: IF silly% THEN CLEAR CLOSE Syntax: CLOSE# The CLOSE statement closes one or more open files. is a numeric value that gives the handle of the file to close. If is zero then *all* files that have been opened by the Basic program are closed. Example: CLOSE#outfile% CLS Syntax: CLS CLS clears the screen (or the current text window if one is being used). It also sends the cursor to the top left-hand corner of the screen. Example: IF full% THEN CLS COLOUR Syntax: a) COLOUR b) COLOUR TINT c) COLOUR , , d) COLOUR , e) COLOUR , , , f) COLOUR OF ON g) COLOUR OF , , ON , , The COLOUR statement is used to change the colour being used when writing text on the screen. It is also used to change the physical colour corresponding to the given logical colour. a) This sets the colour to be used when writing text on the screen. is a numeric value. It is reduced modulo the number of colours available in the current screen mode. The colour changed is the logical colour. If the original value of is less than 128, the colour changed is the text foreground colour; otherwise the background colour is altered. 128 is subtracted from the vale of to get the colour number. b) This version of the statement is used in 256 colour modes to set the colour used for writing text on the screen. sets the logical colour and sets the 'tint' value. If the value of is less than 128 then the foreground colour is changed otherwise the background one is altered. Whether or not is less than 128 affects whether the foreground tint value or background tint value is the one changed by . The colour value is reduced modulo 64 to obtain the colour. The tint value has set values: 0, 64, 128 and 192. The increasing tint value has an effect on the brightness of the colour. See the section '256 Colour Modes' below for an explanation of how the colour and tint work together. c) This sets the current text foreground colour to the colour with components , , . The values of the colour components are reduced modulo 256. The colour is mapped to the nearest equivalent colour in the current screen mode. d) This version of the COLOUR statement changes the mapping between the logical colour number and the colour displayed on the screen in screen modes which have less than 256 colours. is the logical colour number whose mapping is to be changed. The value is reduced modulo the number of colours in the current screen mode. is the colour number of the physical colour to be used. The colour numbers are given in the section '2, 4 and 16 Colour Modes' below. e) This version of the statement is related to c) above in that it alters the colour displayed for a given logical colour number in screen modes with more than sixteen colours available. is the number of the colour to change and , and are the red, green and blue components of the new colour. These are reduced modulo 256. The colour number is also reduced modulo 256. f) This version of the statement has two parts, the 'OF' part and the 'ON' part. The 'OF' part gives the foreground colour and the 'ON' part the background colour. Either of these parts can be omitted but not both of them. The value is the colour number to use. g) This version has two parts, the 'OF' part and the 'ON' part where the 'OF' part is used to give the foreground colour and the 'ON' part the background colour. The three expressions after each keyword, , and , give the red, green and blue components of the colour to use. The colour that will actually be used is the closest match to this colour in the current screen mode. Either the 'OF' or the 'ON' part can be left out but not both. Examples: COLOUR 5 COLOUR 23 TINT &C0 COLOUR 2, 128, 128, 128 COLOUR OF 0, 0, 255 ON 0, 0, 0 COLOUR ON 191, 191, 191 COLOUR ON COLOUR(191, 191, 191) The 'COLOUR OF' statement (along with 'GCOL OF') represent a new way of selecting colours to use on screen. Along with the 'COLOUR()' function they provide a means of specifying colours independently of the screen mode, for example: pink = COLOUR(255, 127, 255) blue = COLOUR(0, 0, 255) COLOUR OF pink ON blue This avoids use of the 'TINT' keyword. DATA Syntax: DATA The DATA statement provides the data to be read by a READ statement. It must be the first keyword on a line after the line number. is one or more items of data separated by commas. DEF 'DEF' marks the start of a procedure or function definition. It must be the first non-blank item on a line after the line number. Refer to the section 'Procedures and Functions' above for more information. Examples: DEF PROCfirst DEF FNsecond(X%) DIM Syntax: DIM The DIM statement is used to declare arrays. contains one or more arrays to be declared separated by commas. There are two types of array declation. The format of a normal array declaration is: ( , ... , ) where is the name of the array and to are the array's dimensions. Arrays can have up to ten dimensions and their size is limited only by the available memory. Array indexes start at zero with the size given in the array declaration as the highest index of each dimension. Note that the '(' is considered part of the array name. Examples: DIM abc%(100), def(10,10), ghi$(size%+10) The second form is used to allocated blocks of memory. There are two versions of this: LOCAL where is the name of a variable and is the size of the block to allocate in bytes. The address of the block is stored in . The first form can be used anywhere but the second can only be used in a procedure or function. In the second case the block is allocated on the Basic stack and is automatically returned when the procedure or function containing the DIM statement ends. In the first case memory is obtained from the Basic heap and it cannot be returned to the heap for reuse later. To be more accurate, the second form allocates a byte array with a low index of zero and a high index of . For this reason the size of the block allocated is actually +1 bytes. Examples: DIM heap% 100000, block% 100 DIM abc%(10), block% 1000 DIM xyz% LOCAL 1000 LOCAL ptr%: DIM ptr% LOCAL 100 One trick is to declare an array in this way with a size of -1 bytes. This stores the address of the current top of the Basic heap in the variable, for example: DIM heaptop% -1 The same effect can be obtained using the function 'END'. Local Arrays ------------ The interpreter allows local arrays to be created in procedures and functions. The memory for these is reclaimed when the procedure or function call ends. The way in which local arrays are defined is as follows: LOCAL DIM In other words, the array is declared local first and then its dimensions are defined, for example: LOCAL abc$() DIM abc$(10,10) DRAW and DRAW BY Syntax: a) DRAW , b) DRAW BY , The DRAW statement draws a line in the current graphics foreground colour from the current graphics cursor position to the one given by , . a) and are absolute coordinates. b) and are the offsets from the current graphics cursor position of the end point of the line. Examples: DRAW 500,100: DRAW 500,500: DRAW 100,100 DRAW BY 400,0: DRAW BY 0,400: DRAW BY -400,-400 ELLIPSE Syntax: a) ELLIPSE , , , , b) ELLIPSE FILL , , , , The ELLIPSE statement draws an ellipse. The coordinates of the centre are (, ). and are the lengths of the semi-major and semi-minor axes respectively. is the angle between the semi-major axis and the x axis in radians. Note that values other than zero for the angle only work in the RISC OS version of the program in the current version of the interpreter. a) This draws an ellipse outline. b) This draws a filled ellipse. Example: ELLIPSE 500, 500, 400, 200, 0.5 ELSE Syntax: ELSE The ELSE statement is part of an IF statement. Refer to the section on the IF statement for more information. END Syntax: END As a statement, END stops the program. Example: IF alldone THEN END ENDCASE Syntax: ENDCASE Part of a 'CASE' statement. It marks the end of the statement. Refer to the section on the 'CASE' statement above for more details. ENDIF Syntax: ENDIF Part of a block 'IF' statement. It marks the end of the statement. Refer to the section on the 'IF' statement below for more information. ENDPROC Syntax: ENDPROC The ENDPROC statement is used to return from a procedure to the calling routine. Variables corresponding to RETURN parameters are set to the their returned values, all local variables declared in the procedure are restored to their original values and local arrays destroyed. The effects of any LOCAL DATA or LOCAL ERROR statements are undone. Control then passes back to the statement after the procedure call. Example: IF count%=0 THEN ENDPROC ENDWHILE Syntax: ENDWHILE ENDWHILE marks the end of a WHILE loop. Refer to the section below on the WHILE statement for more information. Example: ENDWHILE ENVELOPE Syntax: ENVELOPE , ... , This is an unsupported statement. It was used as part of the sound system on the BBC Micro but it is completely redundant in Basic V. ERROR Syntax: ERROR , The ERROR statement is used to generate a user-defined error. is the number of the error and is the error message. Errors raised this way can be trapped just like any other using ON ERROR and ON ERROR LOCAL. Example: ERROR 25, "Bad error" FALSE Syntax: FALSE FALSE returns the value corresponding to 'false' in the interpreter, zero. Example: flag = FALSE FILL and FILL BY Syntax: a) FILL , b) FILL BY , The FILL statement is used to flood-fill areas with the current graphics foreground colour. a) and give the coordinates of the point at which to start the flood fill. b) and give the offsets from the current graphics cursor position at which to start the flood fill. Example: FILL 500,100 FOR Syntax: FOR = TO [ STEP ] The FOR statement marks the start of a FOR loop. and are numeric values that give the start and end values for the loop index, . is optional and gives the amount by which the loop index is incremented or decremented on each iteration. If omitted, it defaults to one. Execution continues from the statement after the FOR statement to the first NEXT statement encountered. At this point the loop index is incremented (or decremented if the step value is negative) and compared against the end expression. If it exceeds that value (or is less than it if the step is negative) the loop is terminated, otherwise program execution continues back at the statement after the FOR. The body of the loop will be executed at least once. and are evaluated only once, at the start of the loop. As with all the loop constructs, exiting the loop will automatically undo the effect of any LOCAL DATA or LOCAL ERROR statements that were used in the loop. Loops badly nested within the FOR loop body will also be silently ignored. Examples: FOR N% = 1 TO 10: NEXT FOR N% = 10 TO 1 STEP -1: NEXT FOR abc = FNstart TO FNfinish STEP 10: NEXT FOR array%(5) = 1 TO 10: NEXT array%(5) The last example shows that the loop index does not have to be a simple variable. GCOL Syntax: a) GCOL b) GCOL TINT c) GCOL , d) GCOL , TINT e) GCOL , , f) GCOL OF ON g) GCOL OF , ON , h) GCOL OF , , ON , , i) GCOL OF , , , ON , , , GCOL is used to set the graphics foreground or background colour. The various combinations are as follows: a) Set the graphics colour to logical colour number . This value is reduced modulo the number of colours available in the current screen mode in 2, 4 and 16 colour modes and modulo 64 in 256 colour modes. If the value is less than 128 then the foreground colour is altered. If it is 128 or more, 128 is subtracted from the colour number and the background colour changed. b) Set the graphics colour to logical colour number and the 'tint' value to . This version is used in 256 colour modes. The colour number is reduced modulo 64. The tint value should be set to 0, 64, 128 or 192. c) This form changes the graphics colour to logical colour number and sets the graphics plot action to . The RISC OS version of the interpreter supports the full range of plot actions but others are restricted to just plot action zero, where each point plotted overwrites the one already there. d) This is a combination of cases b) and c) and is used in 256 colour modes. The graphics colour is set to colour number with tint value . The graphics plot action is set to . e) The current graphics foreground colour is set to the colour with colour components , and . The colour used will be the closest match to the specified colour in the current screen mode. f) and g) are very similar. There are two parts to the statement, the 'OF' part and the 'ON' part. The 'OF' part gives the colour to use for the graphics foreground colour and the 'ON' part the background colour. In case f), only the colour is given but in g) both the colour and the graphics plotting action are supplied. It is possible to leave out either of the 'OF' or the 'ON' parts but not both. h) and i) are similar. There are two parts to the statement, the 'OF' part and the 'ON' part. The 'OF' part gives the components of the colour to use for the graphics foreground colour and the 'ON' part the components of the background colour. The actual colour used will be the closest match to the specified colour in the current screen mode. In case h), only the colour is given but in i) both the colour and the graphics plotting action are supplied. It is possible to leave out either of the 'OF' or the 'ON' parts but not both. Examples: GCOL OF 192,192,192 GCOL OF 0, 0, 0 ON 255,255,255 GCOL OF 1, 15 GCOL OF COLOUR(0, 0, 255) The 'CCOL OF' statement (along with 'COLOUR OF') represent a new way of selecting colours to use on screen. Along with the 'COLOUR()' function they provide a means of specifying colours independently of the screen mode, for example: pink = GCOL(255, 127, 255) blue = GCOL(0, 0, 255) GCOL OF pink ON blue This avoids the use of the 'TINT' keyword, which is really only of use in old-style RISC OS 256 colour modes. GOSUB Syntax: a) GOSUB b) GOSUB ( ) The GOSUB statement calls a subroutine. Control passes back to the statement after the GOSUB by means of a RETURN statement. a) The subroutine to be called starts at line . b) The line number of the subroutine to be called is found given by the numeric expression . Note that the RENUMBER command will update the line numbers in the first form of GOSUB above but it cannot handle the second form. Example: GOSUB 1000 GOTO Syntax: a) GOTO b) GOTO ( ) Program execution continues at the line specified on the GOTO statement. a) The number of the line is given explicitly and so the interpreter can go to that line immediately. b) The line number is given by the numeric expression . Note that the RENUMBER command will update the line numbers in the first form of GOTO above but it cannot handle the second form. IF Syntax: a) IF [ [ THEN ] ] [ ELSE ] b) IF THEN [ ELSE ] c) IF THEN [ ELSE ] ENDIF a) The first form of IF statement is the single line IF. The numeric expression is evaluated. If the result is not zero ('true') the statements after the THEN keyword are executed otherwise the ones after the ELSE keywords are executed. There can be any number of statements after the THEN or ELSE separated by colons. The only limit is the length of the line. Those statements can include further IF statements and some confusion can arise as to which IF statement an ELSE clause applies. If the interpreter has to look for an ELSE as the result of the IF expression is zero, it stops at the first one it finds after the current IF. It is possible to omit the THEN clause or the ELSE clause. It is also possible to leave out the THEN. If the item after the IF expression is neither a THEN nor a ELSE keyword, the THEN keyword is assumed. Examples: IF abc$="xyz" THEN PROCabc: PROCdef IF def<2.0 ELSE PRINT"def is too large" IF X% PROCpqr IF abc$="abc" THEN PRINT"abc": abc$="def" ELSE abc$="abc" b) This is a variation on the single line IF. Either or both of the THEN and ELSE keywords can be followed by a line number instead of one or more statements. Program execution continues at that line iIf the interpreter finds a line number after a THEN or ELSE keyword. Examples: IF abc%=1 THEN 100 IF def<2.0 THEN PROCabc ELSE 200 IF ghi$="abc" ELSE 300 c) The second form of the IF statement is the block IF. If there is nothing else on the line after a THEN keyword or just a REM statement then the IF statement is a block IF. The ELSE part is optional but if it is included the ELSE keyword must be the first item on the line after the line number and any leading blanks. The statements for the ELSE part can start on the same line as the ELSE. The ENDIF must be the first item on the line after the line number and any preceding blanks. Block IF statements can be nested to any depth. Examples: IF X%=1 THEN PROCabc ENDIF IF X%=2 THEN PROCabc ELSE PROCdef ENDIF IF X%=2 THEN IF Y%=1 THEN STOP ELSE PROCabc PROCdef ENDIF IF X=2 THEN REM X is set to 2 PROCabc ELSE PROCdef ENDIF Note in this last example that there is a REM statement after the THEN but the statement is still seen as a block IF. INPUT Syntax: a) INPUT b) INPUT# , c) INPUT LINE d) LINE INPUT The INPUT statement is used to read data from the terminal of from a file. a) This form of INPUT statement reads from the terminal. The format is more accurately specified as: INPUT [ [,]] [ [,]] ] ... is a prompt displayed before the input is read. It can be made up of any number of the following: a string, the function TAB() and "'". TAB() is used to display the prompt at a specific position on the screen. "'" causes a skip to the next line. Examples: INPUT TAB(10, 10) "Value: " INPUT "Size" INPUT TAB(0, 10) "Enter coordinates:" ' "X: " TAB() takes two parameters, the column number and the row number to which to move the text cursor, that is, the point at which the next character will be written. If the prompt is followed by a comma, a '?' is printed after the prompt. If the prompt is left out, a '?' will be displayed as the prompt. is the list of variables to receive the values read. There can be any number of these. The variable names can be separated with blanks, commas or semicolons. Examples: INPUT X%,Y% INPUT abc(1), abc(2), abc(3) INPUT xyz$, ghi% Values typed in are separated by commas. Leading blanks are ignored when they are read. When reading a string, trailing blanks as far as the next comma or the end of the are considered to be part of the string. Strings can be enclosed in double quotes. Numeric values can be entered in hexadecimal or binary as well as decimal. Hexadecimal values are preceded with a '&' and binary ones with a '%'. (Note that this is an extension in this interpreter.) If insufficient values are supplied or an error found, the interpreter prompts again for a value to be entered. Multiple Prompts ---------------- It is possible to repeat as many prompt and variable list sequences as desired. When 'return' is pressed the next prompt is displayed and the next set of values read. Any values not used from the previous read are discarded. Example: INPUT "Name: " name$ "Address: " address$ b) The second form of INPUT statement is used to read data from a file. is the handle of the file from which input is to be taken and gives the variables to received those values. Note that the data is assumed to be formatted binary data produced using PRINT#. INPUT# cannot be used to read text from a file. Example: INPUT# file% , abc(1), abc(2), xyz$ c) and d) These are a variation on format a). The difference is that each value read is taken from a new line. Example: LINE INPUT "Coordinates: " X% Y% LET Syntax: LET = is evaluated and the result assigned to the variable . Only the '=' assignment operator is allowed here. Pseudo-variables, for example, PTR#, cannot be used after LET. LIBRARY Syntax: a) LIBRARY , , ... , b) LIBRARY LOCAL This statement has two purposes. In case a), it is used to read libraries of Basic procedures and functions into memory. to are strings that give the names of the libraries. There can be any number of these. The libraries are held in memory until the Basic program is run again or edited or the statements NEW or CLEAR used. When a procedure or function is called, the interpreter checks to see if it is one already encountered. If not it searches the Basic program for it. If it cannot be found the interpreter then searches the loaded libraries and it if still cannot locate it, the libraries loaded via the INSTALL command. Libraries are searched in the reverse order to which they were loaded, for example, given: LIBRARY "aaaaa" LIBRARY "bbbbb" LIBRARY "ccccc" 'ccccc' will be searched first, then 'bbbbb' and lastly 'aaaaa'. Libraries can be seen as an extension of the program in memory rather than separate entities. They can have their own private variables (declared using LIBRARY LOCAL) but any other variables created in procedures and functions in the library will be added to those the program creates. LIBRARY LOCAL is used to define variables and arrays that will be private to a library. Only the library will be able to reference these variables and arrays. The syntax of the statement is as follows: LIBRARY LOCAL where is a list of variable and array names separated by commas, for example: LIBRARY LOCAL abc%, def%, ghi$, jkl(), mno(), pqr$() In the case of arrays, this merely defines that the array is local to the library. The dimensions of the array have to be declared using a DIM statement in the normal way, for example: LIBRARY LOCAL jkl(), pqr$() DIM jkl(100), pqr$(table_size%) There can be as many LIBRARY LOCAL and DIM statements as necessary but they have to be before the first DEF PROC or DEF FN statement in the library. They also have to be the first item on the line. The variables can only be referenced in the library. They are not visible outside it. This is different to the way in which local variables are dealt with in a procedure or function, where local varables can be accessed by any procedure of function called by the procedure in which they were declared. They can duplicate the names of variables in the Basic program or other libraries. When looking for a variable in a library, the interpreter first searches for it amongst the library's private variables and then in the Basic program's. The variables and arrays are created the first time the library is referenced. In practice this means that they are set up when the interpreter has to search the library for a procedure or function. Private variables in a library can further be used as local variables in a procedure or function. Note that they can only be accessed in the library, for example: LIBRARY LOCAL abc%, def, ghi$, jkl(), mno$() DIM jkl(100) DEF PROCaaa(abc%) LOCAL def, ghi$ ENDPROC DEF PROCbbb(def, jkl()) LOCAL mno$() DIM mno$(100) ENDPROC DEF PROCccc(xyz, abc%) ENDPROC Here, abc%, def, ghi$, jkl() and mno$() are all declared to be private to the library. The dimensions of jkl() are also defined. In PROCaaa, abc% is used as a formal parameter (effectively a local variable) and def and ghi$ declared to be local to the procedure. Any procedure or function *in the library* that PROCaaa calls that use def and ghi$ will use PROCaaa's local versions. Any procedure or function that PROCaaa calls that are *outside* the library *will not* see these variables. In PROCbbb, def and jkl() are used as formal parameters and mno$() is defined as a local array and its dimensions given. Note that this is the first place where the dimensions have been defined. In PROCccc, two variables are used as formal parameters, xyz and abc%. This case is more complex in that abc% is one of the library's private variables whereas xyz is not. xyz is one of the Basic program's variables. abc% can only be referenced in the library but xyz is visible anywhere. The rules for the scope of private library variables may sound complex but they are quite simple. The point to remember is that a private variable in *only* accessible in the library in which it was declared. If a variable is not declared on a LIBRARY LOCAL statement then it is visible anywhere. LINE Syntax: a) LINE , , , b) LINE INPUT a) This form of the statement draws a line on the screen in the current graphics foreground colour from coordinates ( , ) to ( , ). Example: LINE 100, 100, 400, 500 b) This is a version of the INPUT statement. It is described in the section on INPUT above. LOCAL Syntax: a) LOCAL b) LOCAL DATA c) LOCAL ERROR a) This version of the LOCAL statement is used in a procedure or function to declare local variables. The keyword LOCAL is followed by any number of variable names separated by commas, for example: LOCAL abc%, def, ghi$, jkl Arrays can also be declared to be local, but the definition of a local array is slightly more complicated in that the new array dimensions have to be given on a DIM statement, for example: LOCAL xyz() DIM xyz(100,10) LOCAL statements can only appear in procedure or function. The term 'local variables' is somewhat misleading in this context in that the variables are accessible not just in the procedure or function in which they are declared but anywhere in the program. What actually happens is that if the variable already exists, its old value is saved and then it is reset to zero (or the empty string in the case of string variables). When the procedure or function in which the variable was declared local is exited from, the old value is restored. Variables that do not exist are created by the LOCAL statement but they are not destroyed when the procedure or function is left. Anything that can appear on the left-hand side of an assignment can in fact be declared as a local variable, so that, for example, individual elements can be declared local if need be! Example: LOCAL abc(25), abc(30) This would declare two elements of array abc(), elements 25 and 30, to be local. The array abc() has to exist already for this to work. Another example: LOCAL block%!4, block%?20, $text% This would preserve the integer value at address block%!4, the byte at block%?20 and the string at $text%. b) 'LOCAL DATA' saves the current value of the DATA statement pointer. It can be reset to its original value by 'RESTORE DATA'. Example: LOCAL DATA RESTORE 100 READ abc% RESTORE DATA Uses of LOCAL DATA can be nested without any problems. Note that there are times when the DATA pointer will be set back to its old value automatically: 1) If LOCAL DATA is used in a procedure or function the old value will be restored when the function or procedure is exited from. 2) If it is used inside a WHILE, REPEAT or FOR loop, the value will again be restored when the loop ends. It is possible to leave out the RESTORE DATA but it is probably best to include it. c) The 'LOCAL ERROR' statement is used to save the details of the current 'ON ERROR' error handler so that it can be changed and restored later. 'RESTORE ERROR' is used to reset it. Example: LOCAL ERROR ON ERROR LOCAL PROClocal_error: ENDPROC X=X/0 RESTORE ERROR There is no limit on the number of times LOCAL ERROR can be used (other than the memory available). It is possible to nest LOCAL ERROR statements, that is, LOCAL ERROR can be used in a procedure, say, and then it can be used again in the procedures that that procedure calls without any problems. As with LOCAL DATA, there are times when the old error handler details will be restored automatically. They are: 1) If LOCAL ERROR is used in a procedure or function the old handler will be restored when the function or procedure is exited from. 2) If it is used inside a WHILE, REPEAT or FOR loop, the handler will again be restored when the loop ends. So RESTORE ERROR can be omitted but it is probably best to include it. MODE Syntax: a) MODE b) MODE , , , a) The MODE statement is used to change the screen mode. is the new screen mode. It can be either a number or a string. If the mode is numeric, it has to be in the range 0 to 127. This gives the RISC OS screen mode number. The range of modes defined corresponds to those available under RISC OS 3.1 (modes 0 to 46) but whether or not all of these are available depends on the machine on which the program is being run. Mode numbers greater than 46 are undefined and mode 0 is used instead. There is one special mode, mode 127. This corresponds to the screen or window size of the environment in which the interpreter is being run, for example, if the program is being run in an xterm under NetBSD with a window size of 96 characters by 50 lines, mode 0 (80 by 32) will use only part of this but mode 127 will switch to the entire window. The details of the screen mode can also be given as a string. This can be the RISC OS screen mode number as a string or a more precise specification of the resolution and the number of colours to be used. A mode string has the format: X Y [ C ] [ G ] where and give the screen size in pixels, gives the number of colours for a colour screen mode and the number of levels for grey-scale. Example: MODE "X800 Y600 C256" The number of colours or grey scale levels is optional. The parts of the mode string can be separated by any number of commas or blanks. As with numeric screen modes, whether or not the screen mode is available depends on the machine on which the interpreter is being used. b) In this version of the statement, and give the desired size of the screen in graphics units. is a value that gives the number of colours and the frame rate. The last parameter, can be left out, in which case the highest frame rate available will be used. The program will attempt to match the details of the requested mode with those available and will only switch to that mode if it finds a match. The possible values for are as follows: 1 2 colours 2 4 colours 4 16 colours 6 256 colours, old-style RISC OS mode 8 256 colours, new-style RISC OS mode 16 32K colours 32 16M colours The values possible depend on the version of the program being used. In general, depths of 16 and 32 are only available in the version of the program that runs under RISC OS. Under RISC OS, a depth of 6 specifies an old-style Archimedes type 256 colour screen mode in which the extent to which colours can be changed is limited. A depth of 8 indicates that a newer type (RISC OS 3.5 and later) screen mode is to be used where all of the colours can be changed. Examples: MODE 1024, 768, 8 MODE 640, 512, 2, 75 MOUSE Syntax: a) MOUSE ON b) MOUSE OFF c) MOUSE , ,