FESBasic/basic.doc CONTENTS ======== 1. Overview 2. Expressions 3. Control Constructs 4. Statements 5. Final Points ************************************************************************ ======================================================================== 1 Overview ======================================================================== ************************************************************************ 1.1 Preamble ============ This file contains a description of the FESBasic Programming language. I have tried to be as complete as possible in my description of the language as I could in this file so I must apologize if in some places I appear to be stating the obvious, and in others going into excessive technicalities. I suggest that this file be browsed rather than read. Anyone with a moderate knowledge of BASIC should probably skip to section 5 then look at the example files and use the on-line help facilities, then refer to this file only when absolutely necessary. Persons with little or no previous knowledge of computer programming will probably find this document too "technical" to be of much use. The best advice I can give is too find a friend who knows about BASIC, then play around with this program, contacting your friend when ever you are stuck. By the way the HelpFile can be browsed through by just double-clicking its icon. It consists of a list of all the commands and functions in FESBasic along with descriptions of each one's usage. 1.2 The Language ================ FESBasic is a modern version of the BASIC Language. Like most modern BASICs there are no line numbers, so commands like GOTO are rarely used. Without line numbers control constructs like FOR...NEXT and DO...LOOP take a much higher importance. As do Procedures and user defined functions. FES BASIC offers rich choice of these to the programmer, allowing the creation of well structured programs. In addition the editor automatically formats your programs to give them that 'structured' indented look. It must be pointed out at this stage that work is still continuing on the Language. See the "Register.doc" file for more information about getting hold of the latest version of the language. Probably the best way to start this file is with an example:- 'FES BASIC EXAMPLE PROGRAM 'Doesn't do much, but what do you expect? FOR k=1 to 10 COLOR k 'Comments can be placed on any line PROC Put_Text "Line %d",k NEXT STOP DEFPROC Put_Text text$,number LOCAL a$ a$=FORMAT$(text$,number) PRINT a$ ENDPROC <<>> That should give me enough to talk about for a few paragraphs. Comments can be placed on any line. A comment is signalled by a ' and continues until the end of the line. The editor automatically indents your code for you. Your programs automatically get their own screen for their output. ************************************************************************* ========================================================================= 2 EXPRESSIONS ========================================================================= ************************************************************************* An expression can be used almost anywhere a value is required in FESBasic. An expression can consist of: Constants eg 1 -4 "hello" Variables eg a hello& MyString$ Operators eg + - * / = < <= AND OR Functions eg RND VAL STR$ INC AND Brackets ( ) UserFuncs eg FNxyz FNabc$ Lets consider each of these in turn. 2.1 Constants ============= There are three types of constant: int , long and string. An int constant consists of an optional minus sign followed by up to 5 digits (0123456789). An int constant must be in the range -32768 to 32767. A long constant is like an int but it is followed by a & (eg 65538& ), unlike int constants a long can be any size between -4294967296 and 4294967295. If you type a number too big for an int then the editor will automatically add the & to make a long. Arithmetic involving longs is slower than that involving only ints. A string constant is started by a " and is terminated by the same. 2.2 Variables ============= Like constants a variable can be any of three types, int long or string. Int variables consist of a letter followed by 0 to 18 alphanumeric symbols, the underscore _ and the 'at' symbol @ are considered to be letters for this definition. So valid names are x abc Hello Hi_There @ But invalid names include: 3_blind_mice as it starts with a digit a_very_long_name_that never_seems_to_end as it's >19 characters a+b it contains a + Int variables store only whole numbers in the range -32768 to 32767. Long variables have similar names to ints but they must end with a &. This is included in the 18 alphanumeric symbols, again the total name cannot be more than 19 characters. A long can store whole values in the range -4294967296 to 4294967295. As you have probably guessed by now a string variable name consists of the same restrictions as an int but must end in a $ A string variable can store up to 100000 characters of text. A value is placed in a variable by an assignment. This takes the form variable_name = expression on a line of its own. 'expression' must be of the same type as variable_name (ie both ints or both strings), but some flexibility is allowed with ints and longs, if a conversion is possible then one will be made, so it is acceptable to write a&=5 despite a& being a long variable and 5 being an int constant. 2.3 Operators ============= Operators combine the value of two sub-expressions (called operands) relational and boolean. There are also similar operators for strings. 2.3.1 Arithmetic Operators -------------------------- Arithmetic operators combine two numbers together to form a third. The returned value will be a long unless both operands are ints when the return value will be an int. There are 4 Arithmetic Operators + Performs Addition of the two operands - Performs Subtraction * Multiplication / Integer Division ( fractions are ignored) When an expression contains both multiplication/division and addition/subtraction then the Multiply/Divides are done before the add/subs. so 3+5*6 is 33 not 48 and 5+3/4 is 5 NOTE in Integer division 3/4 is zero. To perform additions first use brackets eg (3+5)*6 2.3.2 Relational Operators -------------------------- A relational operator compares the values of its two operands and returns a the int 'one' if some relationship is true, or zero if the relationship is false. The available relational Operators are < Less Than > Greater Than = Equal <> Not Equal <= Less than or equal >= Greater than or equal Relational operations are performed after arithmetic ones , so 5+8<7*3 gives a value 1 and b*a<>b*b gives 1 unless 'a' and 'b' are equal. 2.3.3 Boolean Operators ----------------------- A boolean operator tests its two operators for "truth" (true being defined as any value except zero) and gives a value based on the "truths" of both. The three Boolean Operators are AND Gives '1' if and only if BOTH are true, else gives '0' OR Gives '1' if either or both are true , else 0 XOR Gives '1' if one but not both are true, else 0 Boolean operators are evaluated after relational ones. NOTE: Unlike some other BASICs FESBasic's operators are 'logical' not 'bitwise'. ie 5 AND 4 is 1 not 4. 2.3.4 String Operators ---------------------- There are less operators that can be applied to strings than to numbers. For 'Arithmetic' operators the only one available is 'concatenation' + This operator joins two strings together, ie "egg and "+"chips" gives "egg and chips" All the relational operators can be applied. For comparison a one string is less than another if its first letter's ASCII code is less than the second strings first letter. If the first letters are the same then the comparison is made on the second letter, then the end of one string is reached. So the following relationships are all true:- "chips" < "egg" c comes before e "Egg" < "chips" Capitals come before lower-case "2Chips" < "egg" Numbers come before letters " Egg" < "chips" Spaces come before letters. "chips"<>"CHIPS" The case's are different so not equal "chips" = "chips" Identical. Most basics do not allow Boolean operations on strings. FESBasic contains an extension to the language to allow:- string AND number gives string if number is 'true' "" if number is 'false' string1 OR string2 gives string1 if string1<>"" string2 if string1="" These can be occasionally useful: OTHER BASIC: c$=a$ IF a$="" then c$=b$ FES BASIC: c$=a$ OR b$ OTHER BASIC: PRINT "There are ";n;" cat"; IF n<>1 THEN PRINT "s"; PRINT " on the roof" FES BASIC: PRINT "There are ";n;"s" AND n<>1;" on the roof" 2.4 Functions ============= A function takes zero or more values (called parameters) and produces a single value as a result (known as the return value). If a function takes two or more parameters then the function name must be followed by a '(' and each of the parameters must be separated by commas so for example BTST(a,3). For a function with just one parameter the brackets are optional, so it is acceptable to write ABS(x) or ABS x For functions with no parameters there must not be brackets, eg TIMER Each individual function specifies how many parameters it takes and of what type each must be. It is an error to provide the wrong number or types, and the computer will give an error message, either when the program is executed or as the line is entered. Functions are evaluated BEFORE operators so ABS a+b means (ABS a)+b not ABS(a+b). For a complete list of the functions available in FESBasic refer to the "FESBasic_HelpFile", where they are all listed alphabetically with descriptions. I will now briefly describe the more interesting/useful functions:- 2.4.1 String Manipulation ------------------------- If we have a string ( for example h$ or "hello") we may need to split it up into smaller pieces. All BASICs provide functions to do this. The most general one is MID$. This takes as parameters the string to be sliced, a position to start and a length. It then returns a string made up of a part of the initial string. so MID$("Hello",2,3) gives "ell" e being the 2nd letter and continuing for 3 characters. If the second number is left out then the string continues to the end of the first string, ie MID$("Hi There",4) is "There" FESBasic also allows the second number to be specified as a position, so you can write MID$("Egg and Chips",5 TO 7) to get "and". Other available functions are LEFT$(a$,n) which gives the first 'n' characters of a$, and RIGHT$(a$,n) which gives the last 'n' characters. To convert the case of a string you can use UCASE$(a$) which converts all small letters in string to capitals, and LCASE$ which is the opposite. Finally the function TRIM$ removes any spaces from the beginning and end of a string, so TRIM$(" hello ") gives "hello" 2.4.2 Bit Manipulation ---------------------- These functions are only needed by more experienced programmers. You may have noticed that the AND,OR and XOR operators in FESBasic are 'logical' not bitwise. The bitwise operations are available but as functions. So to mask out bits except 0 and 1 of 'a' use a=AND(a,3) Also direct bit manipulation functions are available: BSET(a,n) sets bit n of a BCLR(a,n) clears bit n of a BCHG(a,n) toggles bit n of a BTST(a,n) tests bit n of a Note these are functions not statements, so write a=BCLR(a,0) instead of BCLR a,0 Also note that NOT is a logical function. To do a bitwise negation use something like XOR(n,-1) 2.4.3 Arithmetic ---------------- Various mathematical operations are available:- ABS n the "absolute value" of n, ie n made positive MOD(a,b) the remainder when 'a' is divided by 'b' - negation INC n n+1 DEC n n-1 MULT(a,b) a*b DIV(a,b) a/b The top three of these are standard BASIC, the last 4 are new to FES. MULT and DIV are subtly different to the * and / operators. All work is performed in 16 bits, with no error checking performed. Division by zero gives int machine infinity, (ie 32767). Multiplication results are modulo 65536, sign adjusted. If this does not mean much to you then you will probably never need to use these functions. INC and DEC can be useful in avoiding brackets sometimes, 3*INC a instead of 3*(a+1). It is a matter of personal choice really. There is little performance difference between either form. 2.4.4 Input/Output Functions ---------------------------- A range of functions are available to perform input and output operations:- INKEY Key Press as ASCII code INKEY$ Key Press as string SHIFTKEY Which Qualifier keys are pressed INPUT$(a) Read 'a' characters from keyboard INPUT$(#n,a) Read 'a' characters from a file. MOUSEB Which Mouse Buttons are pressed MOUSEX Mouse X position MOUSEY Mouse Y position STICKB(n) Joystick 'n's Fire Button STICKX(n) Joystick 'n's Left/Right Position STICKY(n) Joystick 'n's Up/Down Position 2.4.5 Format Conversion Functions --------------------------------- It is often required to convert data from one format to another. To convert an int or a long to a string of digits use STR$. To perform the reverse operation, a string of digits to a long, use VAL. To convert an int/long to an ASCII string use CHR$, the reverse can be done with ASC. Ints and Longs can be converted to 2 or 4 character strings respectively by using MKI$ or MKL$. These are different from STR$ in that STR$ produces a string that makes sense to a human, eg STR$(84) is "84". MKI$(84) is "_T". To convert back from the MK?$ format use CVI or CVL. CVI and CVL can also be used to convert ints to longs or vice versa. Although this is normally done automatically it is sometimes necessary to do it explicitly. For example PRINT 3000*9000 gives an overflow error, as it multiplies two ints to give an int, but the answer is too big for an int to cope with, but PRINT 3000*CVL 9000 does work, as 9000 is now a long, so the result of the multiplication is a long, which can cope with the value 27000000. Note if, as in this case, you are working with constants, you could use PRINT 3000*9000& which is more succinct. {When CVI or CVL are used like this it is jargon to refer to them as "cast" operators. That's a good one to impress your friends with your knowledge of computing} 2.5 User Defined Functions ========================== FESBasic allows you to build up functions of your own. All User Defined Functions must begin with the letters 'FN' followed by a name, the rules for FN names are the same as for variable names, so valid names are FNadd FNSwap$ FNlong_var_name& When it is used a user defined function must be followed by brackets. Even if there are no augments the brackets must still be specified. Functions are defined using DEF. The end of the function definition is marked by a ENDDEF statement followed by an expression. This expression gives the value returned by the function. FES Basic does allow recursion. That is a function can be defined in terms of itself. So the standard example; the Factorial:- 'Factorial Program 'Asks for a number then calculates its factorial '{ So if the user gives the number 5 the answer is 1x2x3x4x5 } INPUT "Give me a number ",a PRINT "Factorial of ";a;" is ";FNFactorial&(a) STOP DEF FNFactorial& n 'use & as numbers can be quite big ' Factorial calculated recursively. ' Factorial 1 =1; ' Factorial n = n* Factorial (n-1) IF n=1 THEN RETURN 1 'RETURN can be used to return value ENDDEF n*FNFactorial&(n-1) 'call FNFactorial again, and again... Notice the slightly weird syntax for DEF. There are no brackets around the list of augments. (It is the same for DEFPROC later). I'm not quite sure why I programmed it that way, but that's the way things happened! Function definitions can contain LOCAL variables, just like PROCedures. ************************************************************************** ========================================================================== 3 CONTROL CONSTRUCTS ========================================================================== ************************************************************************** Probably the most important parts of computer programs are the statements which control the flow of the programs. Performing calculations is fine but if that is all that is required then the end-user is probably better off with a pocket calculator. The main advantage of a computer is its ability to perform operations many times, this looping constructs. There are several Constructs that can be used in FES Basic to perform branching and looping. Labels:...GOTO IF...[THEN] FOR...NEXT REPEAT...UNTIL WHILE...WEND DO...LOOP SELECT...CASE PROC There is also the EXIT command which can be used to make an early exit from a FOR...NEXT, DO...LOOP ,WHILE...WEND or REPEAT...UNTIL. 3.1 Labels:...GOTO ================== These are the least preferred way to perform operations. This method is very much frowned upon in professional programming circles, however it possibly the one that beginners may find themselves most familiar with. A Label is a method of marking a point in a program. In FESBasic this is done by placing an Alphanumeric word at the beginning of a line followed by a :. The computer can be made to jump to a label at any point by the use of the GOTO command. The word GOTO is followed by the label of the point to jump to. There must not be a : after the label at the GOTO. For example, the standard program that everyone writes:- Label: PRINT "FOZZ is ace!" GOTO Label Care must be taken with GOTO's not to jump into or out of other control constructs. If you do the behaviour is not defined. There may be an error message, the program may work correctly on some computers but not on others, etc. Sod's law states that in this last case then the only computer in the cosmos that the program works on will be the programmers own when no-one else is in the room. Although the GOTO command is available it should only be used where absolutely necessary. It is much preferred to use other constructs:- DO PRINT "FOZZ is ace!" LOOP 3.2 IF...[THEN] =============== This is the main decision making construct. It can take two forms:- IF condition THEN statement or IF condition statement statement : : ENDIF The first form is quicker to type, requires less lines, but can only cope with one statement. The second form can cope with any number of statements, even with more IF statements. What forms a "condition"? It can in fact be any expression that gives a numeric result. If the result is not zero then it is regarded as "true",if zero then "false". So we can say:- IF a",action SELECT action CASE 1 INPUT "Load which File? ",FName$ PROC LoadFile FName$ CASE 2 INPUT "Save which file? ",FName$ PROC SaveFile FName$ CASE 3 STOP CASE REMAINDER PRINT "Invalid Option" END SELECT 3.9 PROCedures ============== Procedures are the recommended way of splitting a program up into manageable chunks. They allow blocks of program to be named, each block can have its own 'local' variables separate from all other blocks, and generally makes your programs far better structured. Unfortunately the syntax for PROCedures in FES Basic is highly non-standard. I'm not sure how the syntax came about, but I'm stuck with it now. Its not to bad once you get used to it. Lets start of by looking at how to define a procedure. First comes the statement DEFPROC then the procedure name (alpha numeric just like a variable) then a space then any parameters it takes, all separated by commas. eg DEFPROC myproc a&,b,c$ Note that the variables used in a DEFPROC line are independent of any variables that may have the same name in the rest of the program. After the DEFPROC comes the program lines that make up the procedure, and the whole thing is finished of with an ENDPROC. So a full example: DEFPROC stars n_spaces,n_stars LOCAL k 'the variable 'k' is independent of any other 'k's FOR k=1 to n_spaces PRINT " "; NEXT FOR k=1 to n PRINT "*"; NEXT PRINT ENDPROC To run the procedure use the command PROC, followed by the name then the values to give each parameter. So to display 5 spaces then 3 stars in the above example use PROC stars 5,3 Either value could have been a variable or a complete expression. See the example file "procs.fes" for a complete example. **************************************************************************** ============================================================================ 4. STATEMENTS ============================================================================ **************************************************************************** A 'statement' is the word at the beginning of each line which describes what that line is going to do. So PRINT,GOTO,IF,LINE,CLS,COLOR are all statements. FESBasic currently contains about 65 statements (There is some confusion about lines containing a comment only, or about assignment lines, but this is all besides the point!). For a full list of all the statements please refer to the FESBasic_HelpFile. It consists off all the statements with descriptions. In this section I will describe very briefly some of these statements by subjects... 4.1 PROGRAM FLOW ================ There are quite a few statements which control the flow of execution around a program. These are explained in more detail in section 3: Control Constructs GOTO label The most blatant. Causes a jump to a specified point. GOSUB label Causes a jump to the label. When a RETURN statement is RETURN encountered the program jumps back to the line after the GOSUB. PROC This causes a jump to be made to a given location, like GOSUB DEFPROC however PROC allows passing of parameters, and provides ENDPROC clearly defined limits to blocks of program. FOR This is used to repeat a number of lines a set number of NEXT times. Use this construct when you can determine the number of times round the loop before you start. REPEAT This is used to repeat a block of program several times until UNTIL a given condition is met. The block will always be executed at least once. WHILE Similar to REPEAT...UNTIL but the condition is at the start WEND of the block. This means that if the condition fails on the first time round then no code will be executed. DO Repeats a block of code indefinatly until an EXIT statement LOOP EXIT Leave a looping construct IF Allows decision making, a block of code can be executed only ELSEIF if certain conditions are met. ELSE ENDIF SELECT A more compact form of IF...ELSEIF...ELSEIF...ENDIF when the CASE conditions are all very similar. ENDSELECT 4.2 INPUT AND OUTPUT ==================== PRINT Displays the values of zero or more expressions on the screen. Expressions can be separated by semi-colons in which case they will be displayed side by side on the screen, by commas when they will be displayed in separate columns or by bars '|' when they will appear on separate lines. INPUT Displays a prompt then accepts information from the user and places it in a variable. OPEN Opens a channel to a (disk) file. Information can be sent to the channel using PRINT # or WRITE #. Information can be read using INPUT #, INPUT$(#n) or READ #. CLOSE Closes a channel opened by OPEN. PRINT #n, Similar to PRINT but writes the output to channel 'n' WRITE #n, Writes values to channel 'n' in a computer readable format. This format is understood by READ # INPUT #n, Similar to INPUT but reads from a file not the keyboard. READ #n, Retrieves information from a file written to by WRITE #n. BWRITE Writes a block of memory to a channel opened with OPEN. BREAD Reads a block of memory from a channel. 4.3 GRAPHICS ============ SCREEN 1,w,h,n Determines the screen mode that Basic will use. Note the slightly strange syntax with a 1, at the beginning! COLOR f,b,m Chooses the colour to draw in. PALETTE Changes the selection of colours available LINE Draws straight lines on the screen. BOX Draws hollow or filled boxes. CIRCLE Draws filled/hollow circles/ellipses. AREA Fills an arbitrary shape with up to 20 vertices. AREAFILL FLOOD Fills a shape already drawn on screen. PSET Sets a pixel on the screen. GET Copy a section of screen to a buffer PUT Copy a buffer onto the screen. SCROLL Move a part of the screen around. *************************************************************************** =========================================================================== 5. FINAL POINTS =========================================================================== *************************************************************************** This chapter is intended mainly for persons already familiar with other versions of BASIC. In it I list the peculiarities of my language in comparison with others. 5.1 Integers Only ================= The freely distributable version of FESBasic is limited to working only with Integer Numbers (ie numbers with no decimal points). To obtain a version that supports real-numbers you need to register (see the accompanying file Register.doc) This limitation means that for example 5/3 is, as far as the computer is concerned, equal to 1, as 1 is the largest number of times that 3 can go into 5. 5.2 Syntax for PROCs and DEF FNs ================================ Procedures are defined by using the command DEFPROC followed by the proc name and then any augments, without brackets around the list of augments. Variables local to a procedure are declared by using the statement 'LOCAL' on the line immediately after the DEFPROC. To call a procedure the word PROC must be used, and again there are no brackets around the augment list. So for example PROC Stars n . . . DEFPROC Stars number LOCAL k . . . ENDPROC To define a function the syntax is exactly the same as for a procedure except use the word DEF not DEFPROC. Again there are no brackets around the augment list. User defined function names must begin with the letters FN followed by at least one alphanumeric character. The return type of a function is placed at the end of the name, so FNx returns an integer, but FNy$ returns a string. When calling a user defined function however the brackets are essential, even if there are no parameters. The return value expression is placed after the ENDDEF that finishes the definition. Early exit from a function is possible using RETURN value but note that it is illegal to exit from within a loop. The function below will have undefined effects:- DEF FNFindValue value FOR k=1 to 10 IF a(k)=value THEN RETURN k NEXT ENDDEF 0 Some other BASICs do allow this sort of early exiting from definitions, but FES does not. Using this type of construct can get the computer VERY confused! You may use the RETURN statement within block IF and SELECT constructs however, but not if the IF/SELECT is within a FOR/DO/WHILE/WEND etc. eg 'This is OK DEF FNFindValue Value SELECT Value CASE 1,2,3 RETURN 1 CASE 4,5,6 IF RND(3)>2 RETURN 2 ELSE RETURN 4 ENDIF CASE REMAINDER RETURN 0 ENDSELECT ENDDEF 5.3 LOGICAL AND BITWIZE OPERATIONS ================================== The operators AND OR and XOR in FESBasic are logical operators. That is they give the value '1' if the answer is true and '0' for false based on the whole number input, not on each individual bit input. This means that a=5 AND 4 gives a=1 not 4 as some BASICs might. The Bitwize operations are available as functions though:- So you would write a=AND(5,4) to get a=4. Also the operators AND and OR can be used on Strings:- a$ AND a gives a$ if a<>0 "" if a=0 a$ OR b$ gives a$ if a$<>"" b$ if a$="" These functions are not often used but can be quite useful, for example to set a default value on a string: other BASIC INPUT "Enter your name ",name$ IF name$="" then name$="Anon" : : FES BASIC Input "Enter your name ",name$ name$=name$ OR "Anon" or to handle plurals other Basic PRINT n;" apple"; IF n<>1 THEN PRINT "s"; FESBasic PRINT n;" apple";"s" AND (n<>1); 5.4 PRINT USING and FORMAT$ =========================== FESBasic does NOT support the PRINT USING syntax found on many other versions of BASIC. Instead the C-Style function FORMAT$ is used. FORMAT$ can be used in any context unlike USING which could only be used in conjunction with PRINT. eg 'print a persons name and age PRINT FROMAT$("Name: %15s Age %2d",name$,age) would give something like:- Name: Simon Forey Age 20 5.5 STAND ALONE PROGRAMS ======================== If you have written a program using FESBasic it is not neccary to load it into the editor every time you want to run it. If you create a program with an Icon then the program can be run by double-clicking its icon. Just make sure that the program "basic" is on your disk in the same place as the "Tool Type" of the Icon says it is. Running programs from the CLI is equally easy. Just make sure that "basic" is in your command path ( eg put it in the 'c' directory of your disk) then type basic file_name.fes NOTE: For a program to be executable like this it must have been saved using SAVE or SAVE PROT from the editor. Programs saved using SAVE ASCII cannot be run without loading them back into the editor. So suppose you have written a game called "game.fes" and you want to make a bootable disk that will boot to the game. You need the following disk structure c basic «any other commands used» s startup-sequence libs reqtools.library OR } only if you use the FILEREQ$ function asl.library } game.fes the startup-sequence would look something like «any commands you want to run before game» basic game.fes «any commands for after game»