IP Basic Interpreter

August 29, 2014












IP Basic interpreter

Scott A. Franco



1 Introduction 4

2 Beta software warning 4

3 Syntax notation used 4

4 Format of source 5

4.1.1 Line entry 5

4.1.2 File entry 5

4.1.3 Identifiers 5

4.1.4 Numeric constants 6

4.1.5 String constants 6

4.1.6 Comments 7

4.1.7 Internal format 7

5 Variables 7

5.1 Real 7

5.2 Integer 7

5.3 String 7

5.4 Arrays 8

5.4.1 Sparse arrays 8

5.4.2 Function precedence over arrays 8

5.5 Records 8

5.6 Files 9

6 Statements 9

6.1 Input statement 9

6.2 print statement 10

6.3 goto statement 12

6.4 on statement 12

6.5 if statement 12

6.6 rem statement 14

6.7 stop statement 14

6.8 run statement 14

6.9 list statement 14

6.10 new statement 14

6.11 let statement 15

6.12 load statement 15

6.13 save statement 15

6.14 data statement 15

6.15 read statement 15

6.16 restore statement 16

6.17 gosub statement 16

6.18 return statement 16

6.19 For/next statement 16

6.20 while statement 18

6.21 repeat statement 19

6.22 select statement 20

6.23 open statement 21

6.24 close statement 21

6.25 end statement 21

6.26 dim statement 21

6.27 def statement 22

6.28 Function/endfunc statement 22

6.29 procedure statement 23

6.30 Local statement 23

6.31 randomize statement 24

6.32 trace statement 24

6.33 notrace statement 24

6.34 bye statement 24

6.35 clear statement 24

6.36 cont statement 24

6.37 delete statement 24

6.38 kill statement 25

6.39 merge statement 25

6.40 name statement 25

6.41 renum statement 25

6.42 dir statement 26

7 Expressions 26

7.1 Standard functions 27

7.2 Batch mode 28

7.3 Cut and paste 29

8 BNF Grammar Specification 30

8.1 Program Structure 30

8.2 Statements 30

8.3 Expression Hierarchy 31

8.4 Variables and Literals 32

8.4.1 Literals 32

8.5 Grammar Notes 33





1Introduction

This manual covers the IP Basic language interpreter.

The language of the basic interpreter was in common use in the late 1970’s/early 1980’s. When the first microprocessors were used widely to create hobby computers, the Basic language was popular as the programming language. Because the most popular previous implementation was DEC PDP-11 Basic, those Basic implementations often appeared as cut down versions of that Basic interpreter to enable porting of various programs from that machine. This includes implementations such as MBasic-80 by Microsoft, and others.

IP Basic roughly implements MBasic-80, but a subset of that. The test material for it is the “Creative Computing” set of Basic language games that were published in the 1970s. Please see:

http://www.classicbasicgames.org/

Thus IP Basic, for the most part, implements the set of features necessary to implement that set of programs. However, IP Basic implements several features to enable a better programming style than those original Basics, including:

This has been implemented in a manner backwards compatible to the base language. It also retains the ability to run command lines immediately from the console.

2Beta software warning

IP Basic is beta software at this time (version < 1). It should not be considered reliable for production use.

3Syntax notation used

The notation used to introduce language syntax elements is:

[option] An optional item that may or may not exist.

repeated… An item that may be repeated any number of times from 1 to n.

[option]… An item that may be repeated any number of times from 0 to n.

a|b Two alternatives, IE, a or b but not both.

‘literal’ Literally, the characters in single quotes.

“string” A constant string of characters.

keyword A language keyword.

(group) A group of items, usually for purposes of repeating.

(group)… A repeated group, 1 to n times.

4Format of source

A IP basic program consists of a series of text lines. Each line may or may not have a leading number, which is ignored while the program is being executed. Lines can be blank.

10 print “hi”

20

30 end

Case is not significant except within strings.

4.1.1Line entry

When lines are entered on the console, the “line oriented editor” mode is used. The format of a console line is:

[number] program text…

When a line is entered, and it has a leading number, that line is matched to the lines in the current program store. If the line number order is:

If a line number is entered alone, it signifies that any existing line is to be deleted. If a space or spaces exist after the number, then a blank line is assumed.

All leading spaces before the line number are removed. This is the only time the formatting of source lines is changed.

If no line number appears on the entered line, then the line is considered to be immediately executable.

4.1.2File entry

If a source file is read, each line is treated as if it were directly entered on the console. However, if no line number appears, the line is simply appended to the current program. In this manner, it is possible to enter a program without line numbers.

When a source file is written, it is output as is, with out without a leading line number.

Thus directly saving and restoring program files allows free form programming.

4.1.3Identifiers

Identifiers in IP Basic are of the form:

[_,a-z,A-Z][_,a-z,A-Z]…

An identifier starts with any of _, a through z and A through Z, followed by any number of characters in _, a though z, A through Z, or 0 through 9. Note that this also means the legacy basic identifiers are valid labels, thus:

a

a1

a10

MyVariable

Are all valid identifiers.

Note that case is irrelevant in IP Basic. Thus:

MyVar

And

Myvar

Are the same identifier.

4.1.4Numeric constants

Numberic constants can be simple integer, or real:

1

1.2

1.2e5

.5

-0.5

Integer constants can also be input in hex, octal or binary:

$10 Hexadecimal 16

&10 Octal 8

%0101 Binary 5

4.1.5String constants

String constants are characters between double quotes:

“hi there”

If a double quote is wanted within the string, a “quote image” is used, consisting of two back to back quotes:

“and he said “”what is going on”” there?”

4.1.6Comments

IP Pascal features both a comment statement, rem, as well as a comment character, ‘!’. The difference is, besides being shorter, ! is not a statement and can appear anywhere on the line. Like the rem statement, it ignores all further text on the line.

4.1.7Internal format

IP Basic reformats the source language into an internal, tolkenized format that is more efficient, both to store as well as to interpret. It tries hard to maintain the original format of the source. For example, the spacing of the original program is maintained. However, there is one change, and that is of numeric formats. Numbers are simplified, with leading zeros removed, and floating point constants are normalized.

5Variables

IP Basic allows for 7 different kinds of variables

x Real (floating point)

x% Integer

x$ String

x(n[,n]…) Real array

x%(n,[n]…) Integer array

x$(n,[n]…) String array

x.y Record

Each form of variable contains different data. Thus:

x

And

x$

Refer to two completely different variables.

5.1Real

Real valued variables can take any value, with any fraction. They can be used for integer math, but take longer to calculate than integer based variables.

5.2Integer

Integer valued variables always assume integer only values, no fractional part. They are generally faster and more compact than reals.

5.3String

String valued variables take a series of characters and can be any length up to 250 characters.

5.4Arrays

Each of real, integer and string can be expressed as an array, and that array can have any number of dimensions. For example:

x(10, 14, 12, 31, 42)

Is a valid array. Index values range from 0 to n, where n is any number between 0 and 1000.

Arrays are distinct from other variable types, but not from each other. Once an array with a given identifier is used with a given number of dimensions, the number of dimensions used to access it cannot change. Thus:

a(10)

Cannot later be used as:

a(10, 10)

Arrays can be dimensioned by the dim statement, but more typically the size and index characteristics of the array are determined automatically from its first encountered form.

5.4.1Sparse arrays

In IP Basic, arrays are automatically sparse. If the statements appear:

A$(1) = “hi”

A$(10) = “there”

The resulting array is not 10 units long, but 2. IP Basic does not allocate array elements until they are used.

5.4.2Function precedence over arrays

In Basic, array notation a(x) and function notation f(y) are inherently ambiguous with respect to each other. When a name is used to introduce a function, any array definition by that same name is essentially masked by the function definition. The previous contents of the array will not be usable.

Naming functions and arrays the same is to be avoided for this reason.

5.5Records

A record is a collection of named fields, each of which can have a different type:

a.b = 1

a.b$ = “hi there”

a.b(5) = 62

a.c% = 7

There is no limit to the number of fields each record can have. Records can contain records:

a.b.c$ = “hello world”

is a record a, with field b which is a record, which contains field c.

However, in this version of IP Basic, arrays of records are not possible.

There is no special syntax to indicate a record. For each identifier, there exists a different form such as:

a Float

a% Integer

a$ String

a(10) Array of float

a.i Record with field I, which is float.

All of these forms can exist at once.

5.6Files

Separate from variables, IP Basic can operate on a number of text files referenced by number, from 1 to n where n is a maximum of 100. input or print statements can be used with files. Two file numbers, 1 and 2 are reserved:

1 Standard input file.

2 Standard output file.

So the default file for input statements is #1, and the default file for print statements is #2.

Files are text only, and structured into lines. input statements read whole lines from a file. print statements write whole lines to a file.

6Statements

6.1Input statement

input [#file,] [prompt[;|,]] variable[,variable]

The input statement reads some number of variables from either a file or the standard input. The file number can be specified, or the default file #1 used (standard input). If a prompt string is specified, then that will be output to the standard output before the input is performed. This mode is not valid if a file number was specified (even if it is the standard input). The prompt string is a simple constant string. No string expression can be specified.

If no prompt string is not present, then “? “ will be output as the standard prompt (question mark followed by space). The prompt is terminated by either ‘;’ or ‘,’. Which character terminates the prompt determines:

; Specifies to output the standard prompt (“? “) after the prompt string is output.

, Specifies to not output the standard prompt after the prompt string is output.

The input statement reads an entire line from the text file or standard input. If multiple variables appear, then the input line is separated into fields by the ‘,’ character. For example:

input a, b, c

Given an input line “1, 2, 3” would give the results:

a = 1

b = 2

c = 3

String values are also delimited by ‘,’ if more than one variable appears on the input statement. However, if only one string variable appears, the entire input line will be assigned to the given variable without regard to embedded ‘,’ characters.

Note that input from a file is not available if named file handling is not enabled.

6.2print statement

print [#file] ([tab(number)] [using “format”] [expression [,|;] [expression[,|;]])…

Print a series of expressions, of any type, integer, string or real, on one output line. The print statement starts with an optional file number, the a series of “print groups”, containing tab, using, and then expressions, ending with a print format character.

If a file number is specified, then the output is redirected to that file. The default file is #2, the standard output.

Each group must be separated from the next by ‘,’ or ‘;’. The separation of each printed field from the next is determined by the character used to separate the fields. The ‘,’ character causes each field to be placed in 15 character spaces. The ‘;’ character causes each field to be placed separated by 2 spaces. Thus:

print 1,2

1 2

print 1;2

1 2

If the print group starts with a tab expression, it will contain a numeric expression that evaluates to a tab location on the line, from 1 to n, where n is the character location on the line. The print location will be padded with that number of spaces to reach the tab position. Thus:

print tab(20) "hi"

hi

To allow more flexibility in output formatting the using facility is available. Using takes a string expression. The string specifies a series of characters to determine how the expression to be printed is laid out on the line. The following character meanings exist:

& Print a string

$ Print ‘$’ if at the left of the most significant digit in number, otherwise ‘ ‘ (space).

, Divide digits in a number. Prints ‘,’ if within significant digits of the number, otherwise ‘ ‘ (space).

# Print digit in this position or space if not significant.

0 Print digit or zero if not significant.

- Print sign if negative before most significant digit.

+ Print any sign before non-zero digits.

. Place decimal point.

^ Print exponent.

Any other character than what appears above is simply printed in place. The idea of using is to present an “image” of what the number looks like in its field. Each character of the format indicates what happens in that digit position. Thus:

print using "The string is: &" "hi"

The string is: hi

print using "####" 5

5


print using "0000" 5

0005


print using "$$$#" 5

$5


The formatter starts by finding the decimal point in the format. This is either explicitly the ‘.’ decimal point format character or the position to the right of any of the digit format characters. If the number is integer, it is considered to be a whole number with only 0’s as the fraction.

Having found the decimal position, each number format character to the left of the decimal position is matched to a digit in the whole part of the number, and each number format character to the right of the decimal position is matched to a a digit in the fractional part of the number. Thus:

print using "###.###" 5

5.000


print usign "###.###" 5.123

5.123


print using "###,###.###" 5.123

5.123


print using "###,###.###" 1465.123

1,465.123


print using "000,000.###" 1465.123

001,465.123


print using "$$$,$$#.###" 1465.123

$1,465.123


print using "---,--#.###" 1465.123

1,465.123


print using "---,--#.###" -1465.123

-1,465.123



It is an error if there are more than one ‘.’ (decimal) format characters in the using string.

When real numbers are printed, the most space efficient format is used. Generally if the number can be represented without an exponent in 10 characters, it is printed that way. If it takes more than 10 characters, the exponent format is used.

To get the exact format you want, it is recommended that print using be utilized.

6.3goto statement

goto [line number|label]

label:

The goto statement causes program execution to stop and then continue at a new location. If a line number is specified, then that is found and executed. If, instead an identifier appears, then the execution continues after the indicated label. It is an error if the line number or label is not found.

The ability to specify an identifier instead of a line number enables free format code with or without line numbers. To enable this, a label must be present in the code. It must appear first on the line before any statements. The line containing the label may or may not also have a line number on it.

6.4on statement

on expression goto label|lineno [,label|lineno]…

on expression gosub label|lineno [,label|lineno]…

The on statement parses an expression and uses the value to select from a list of line numbers or labels. If the expression is 1, the first in list is matched. If 2, the second, etc. If no item in the list is matched, execution simply continues.

The target line may be a goto or gosub. If goto, the execution simply transfers to the target line (see the goto statement). If gosub, the target statement is executed, and a ensuing return statement will cause it to return to the next statement after the on (see gosub statement).

6.5if statement

if condition then statement [else statement]

if condition goto [line|identifier]

if condition then

[else]

Endif

The if statement controls execution according to a given condition. It comes in several forms, and may either complete on a single line, or span many lines.

The condition must evaluate to 0 or non-zero. If the condition is zero, then the condition is false. If the condition is non-zero, then it is true.

The first form gives a statement to execute if the condition is true, optionally followed by a statement to execute if the condition is false. A side effect is that the rest of the line after the statement is executed along with the last active part of the if statement. Thus:

if 1 then print “hi”: print “how are you”

Prints:

hi

how are you

Because the last part of the if statement is the true clause. If the condition is not true, none of the rest of the line is executed.

If this if is executed:

if 1 then print “hi” else print “lo”: print “how are you”

Prints:

hi

And then terminates the line, because the else or false clause controls the rest of the line. The statement:

if 0 then print “hi” else print “lo”: print “how are you”

Prints:

lo

How are you

Because the else or false clause enables the rest of the line.

The rules for continuation on the same line using if are a bit complex. The recommendation is to only use if for a single statement on the line.

The second form of if gives shorthand for gotos. If the condition is true, then the goto is executed (see the goto statement). The rest of the line is not executed.

In the final form, the if statement spans multiple lines. This form of if is more appropriate for free-form program code. The if statement multiline mode is activated if there is nothing on the line past the then keyword. When this occurs, the if is not terminated until endif is encountered. If an else is encountered and the condition is false, then that is executed. In both true and false cases, the if statement ends after the endif is encountered.



6.6rem statement

rem some text…

The rem statement causes the rest of the line to be ignored, and execution continues with the next line. Thus:

rem this is a comment



Another way to introduce a comment is with the ‘!’ character. This can be placed anywhere on the line, not just where a statement is expected:

print “hi there” ! do my print here

6.7stop statement

stop

Causes the program to halt and enter command mode. In this version of Pascal-P6, it is functionally identical to the end statement (see end statement).

6.8run statement

run [filename]

Runs the current program or a program from a file. The variables, current tabbing, and the random number generator are cleared and reset, and the program runs from the first line in the program. If a filename is specified, then that program file is loaded and the current one completely cleared.

It is an error if a filename is specified and named file I/O is not enabled.

6.9list statement

list [start line[,end line]]

Lists the current program to the console. If no starting or ending line is specified, then the entire program from start to finish is listed. If only a starting line is specified, then that line from the end of the program is listed. If both the start and end are specified, then the program is listed from the starting line to the ending line, inclusive.

To be able to specify starting and ending lines, the source lines indicated must have numbers.

6.10new statement

new

Clears the program store and variables. Used to start editing on a new program.

6.11let statement

[let] variable = expression

Assigns an expression to a variable. The variable assumes the value of the expression. The let keyword is optional. Examples:

Let a = 10.67

A$(10) = “hi”

a.b%(5) = 3

6.12load statement

load filename

Loads a new program. The file by the given filename is loaded into the current program store. Any previous program is erased.

If is an error if named file I/O is not enabled.

6.13save statement

save filename

Saves the current program to the given file by filename. The current program in store is unmodified.

If is an error if named file I/O is not enabled.

6.14data statement

data [value[,value]]

Introduce data into the program. The data statement introduces a series of data values into the program:

data 1, “hi”, 3.1414


Data statements can be placed anywhere in the program, and are simply no-ops when run. The values in the data statement are placed in variables by the read statement (see read statement). All of the data statements in the program are considered a list from start to finish. The read statement will read each in turn until there are no more data statements in the program.

6.15read statement

read variable[,variable]…

Reads from the current data statement (see data statement) into the list of given variables. The data types must match in type, just as if an assignment were being made. Integers can be assigned to real, and vice versa, but strings cannot be read to integer or real, and integer or real cannot be read to a string.

The current data position to read from starts from the first data statement in the program and moves sequentially to the last data item on the last data statement in the program. The position of where data is to be read can be set with the restore statement (see the restore statement).

It is an error if there are no more data values in the program to read to the current variable.

6.16restore statement

restore [linenumber|label]

Restores the data position used by the next read statement (see read statement) to either the beginning of the program, or to a specified line by number or label.

It is not an error to restore the data position if there are no data statements in the program. However, the next read statement will cause an error.

6.17gosub statement

gosub linenumber|label

Transfers control to the line specified by the linenumber or label. The position of the program execution after the gosub is saved, and restored by a later return statement (see return statement). gosubs can be nested to any level.

Example:

10 gosub 30: print “done”

20 end

30 print “hi”: return

hi

done

6.18return statement

return

Returns to the program position just after the last gosub statement was executed (see gosub statement).

It is an error if there is no last gosub executed.

6.19For/next statement

for variable = start expression to end expression [step expression]

for variable = expression [,expression]

next [variable]

Loops a code sequence with a series of values in a variable. The variable is assigned a series of values from the starting expression to the ending expression. The following statements are executed with that variable value until a next statement is encountered (see next statement). Then the loop is repeated with the variable incremented by either the default 1, or by the increment specified in the optional step expression.

The step can be any value, including negative and fractional. The loop will continue as long as the variable value is between the starting and ending expressions. The start and end expressions are evaluated only when the for loop is started.

Examples:

for i = 1 to 10: print i: next

1

2

3

4

5

6

7

8

9

10


for i = 1 to -10 step -0.45: print i: next i

1

.55

.1

-.35

-.8

-1.25

-1.7

-2.15

-2.6

-3.05

-3.5

-3.95

-4.4

-4.85

-5.3

-5.75

-6.2

-6.65

-7.1

-7.55

-8

-8.45

-8.9

-9.35

-9.8


A second form of the for loop can be used called “sequence of values”. Instead of specifying how the variable is to be incremented, a series of values are given:

for i = 1, 3, 5, 2, 0: print i: next

1

3

5

2

0



This form of the for loop also allows string variables to be iterated:

for i$ = "one", "two", "three", "four", "five": print i$: next

one

two

three

four

five


A next statement can be specified with or without a variable. With no variable, it terminates whatever for statement was last executed. The for statement is executed again, and that continues until the values of the for loop are satisfied. Then execution continues after the next statement.

If the next statement has a variable, then only the for statement that matches that variable is reexecuted. If the last for statement does not match, then all previous active for statements that do not match the variable are simply canceled. This allows for special situations:

for y := 1 to 10

for x = 1 to 10

print x, y

if x > 5 goto exit

next x

exit:

next y


Here the inner loop is terminated early. If the next statements were anonymous (no variable specified), then the last next would simply continue the inner loop. Instead, the inner loop is cancelled and the outer loop continues.

for statements can be nested to any level, and be spread over any number of lines.

The rule should be followed that next statements follow the for statements they are matched with. This example of “tricky code”:

10 goto 30

20 next

30 for I = 1 to 10: print i: goto 20


Would function in an interpretive environment, but would not work in a compiler, in case you ever want to generate fast binaries. Thus these kinds of styles should be avoided.

6.20while statement

while expression … wend

The while and wend statements form a loop controlled by the expression of the while statement. Unlike a for statement, the controlling expression is evaluated every time the loop iterates. As long as the expression evaluates to true or non-zero, the statements in the while loop are executed. When the expression value is false or 0, the body of statements in the while loop are skipped and execution continues after the wend statement. Thus a while loop may not execute the contents of the loop at all.

Example:

10 i = 1

20 while i <= 10

30

40 print i

50 i = i+1

60

70 wend


1

2

3

4

5

6

7

8

9

10


while loops can be nested with other while loops and other control structures to any level. The wend statement must be located in the program source after the while statement. This is because if the while condition is false, statements are skipped, not executed, until the wend statement is found.

6.21repeat statement

repeatuntil expression

The repeat and until statements form a loop that is controlled by the until expression. Unlike a for statement, the controlling expression is evaluated every time the loop iterates. As long as the expression evaluates to false or zero, the statements in the repeat loop are executed. When the expression value is true or non-zero, the repeat loop exits and execution continues after the until statement.

Example:

10 i = 1

20 repeat

30

40 print i

50 i = i+1

60

70 until i = 10


1

2

3

4

5

6

7

8

9


repeat loops can be nested with other while loops and other control structures to any level. The until statement should located in the program source after the repeat statement.

6.22select statement

select expression .. case expression: [other:] endsel

A select statement gives a means to execute different alternative program paths depending on the value of an expression. It is like the ongoto statement except that it is a true multiline capable programming structure.

The select expression is evaluated, then each ensuing case statement is examined to see if it contains the matching value by evaluating the case expression and checking for equal with the select expression result. If the case statement is matched, then the statements following the case statement are executed until the next case statement is found. The rest of the case statements are then skipped until endsel is found, and execution continues with the next statement after that.

If an other clause exists, then that will match any select expression result. This allows a single case to handle all other possible select expression values. The other clause behaves just as a case statement.

select and case expressions can be integer, real or string.

Examples:

select 1


case 1: print "one"

case 2: print "two"

case 3: print "three"

other: print "something"


endsel


one


select 1.2


case 1.1: print "point 1"

case 1.2: print "point 2"

case 1.3: print "point 3"


endsel


point 2


select "fork"


case "knife": print "its a knife"

case "spoon": print "its a spoon"

case "fork": print "its a fork"

other: print "don't know what it is"


endsel


its a fork

6.23open statement

open filename for input|output as #number

Opens a text file by filename for either input or output using the given file number as a handle. File numbers can be in the range 3 to 100. The file numbers 1 and 2 are reserved for standard input an standard output.

When a file is open for reading, it is positioned to the start of the file and made ready to read. When a file is open for writing, it is set to zero length and writing starts at the beginning. IP Basic only allows reading or writing to a text file, not both at the same time.

It is an error if the file is opened for reading, but a file by that name does not exist.

If the file by number is already open, it is automatically closed, then reopened under the new name.

6.24close statement

close #number

Closes a text file by filenumber. The file number is then free to be used for other files. It is an error to close either the standard input file (1), or the standard output file (2).

6.25end statement

end

The end statement terminates the program and causes it to stop and enter interactive mode.

It is considered poor form not to have the end statement as the final statement in a program, from a program readability standpoint. If you wish to have the program stop in the middle, the normal practice is to use the stop statement (see stop statement), or goto the final line containing the end statement.

6.26dim statement

dim variable[,variable]

The dim statement defines the exact dimensions of arrays in IP Basic. IP Basic automatically declares variables when they are used. However, the default string length of 250 characters may be excessive, especially in large arrays of strings. Thus it is often useful to set the exact string length used.

For each variable defined as an array, the subscript used with dim is the total size of the array, not an index value:

10 dim a$(100), b.c(10, 10)


Here the size of the string a$ is set at 100 characters, and the size of the matrix c in record b is set to 10x10.

Using a dim statement can also help code size and speed when IP Basic is complied (sometimes dramatically). The dynamic creation of variables in code without dim statements can be a source of considerable runtime overhead.

It is an error to dim variables after their use. It is an error to dim the same variable multiple times.

6.27def statement

def functionname[(parameter[,parameter]…) = expression

Defines a single line function. The function name, which can be any identifier (not “fn…” of older Basics) is registered as a function with optional parameters. Each parameter is a variable declaration for a variable that exists only while the function is being executed.

The expression on the right hand side supplies the definition of the function. Each parameter may appear in the expression and behaves as a variable that was loaded with the data passed by the caller. Thus:

10 def add(a, b) = a+b

20 print add(1, 2)

3

The result returned by the function is the result of the expression that defines it.

The function definition must be executed or appear before it is called. In a compiled environment, it must appear first in source regardless of execution order.

The appearance of a function overrides the function name use as an array. If an array was definined when the function is defined, the contents of the array become unusable. Naming functions and arrays the same is to be avoided.

6.28Function/endfunc statement

function functionname[(parameter[,parameter]…) … endfunc expression

Introduces a multiline function. The function name, which can be any identifier is registered as a function with optional parameters. Each parameter is a variable declaration for a variable that exists only while the function is being executed.

The statements defining the function are terminated by an endfunc statement. Any number of lines can constitute the function. The expression evaluated by the endfunc statement defines the result of the function:

10 function min(a, b)

20

30 if a > b then a = b

40

50 endfunc a


The function definition must be executed or appear before it is called. In a compiled environment, it must appear first in source regardless of execution order.

The appearance of a function overrides the function name use as an array. If an array was definined when the function is defined, the contents of the array become unusable. Naming functions and arrays the same is to be avoided.

Functions can be nested. The definition of a nested function will only be available inside the procedure it is nested within.

6.29procedure statement

procedure procedurename[(parameter[,parameter]…) … endproc

Introduces a multiline procedure. The procedure name, which can be any identifier is registered as a procedure with optional parameters. Each parameter is a variable declaration for a variable that exists only while the procedure is being executed.

The statements defining the procedure are terminated by an endproc statement. Any number of lines can constitute the procedure:

10 procedure printit(a, b)

20

30 print “a”; a; “b”; b

40

50 endproc


The procedure definition must be executed or appear before it is called. In a compiled environment, it must appear first in source regardless of execution order.

The appearance of a procedure overrides the procedure name use as an array. If an array was definined when the procedure is defined, the contents of the array become unusable. Naming procedures and arrays the same is to be avoided.

Procedures can be nested. The definition of a nested procedure will only be available inside the procedure it is nested within.

6.30Local statement

Normally, variables used within a procedure or function are global. The external value of the variable is still present within the procedure or function, and if the variable is set within the function, that value is available outside the procedure or function as well.

The local statement creates a variable definition that is only present during the execution of the procedure or function is is contained in:

10 r = 42

20 procedure doit(a, b)

30

40 local r, t;

50

50 print “r”; r

60

70 endproc


The identifiers contained in the local statement replace any global version of that identifier. Access to the global identifier, if there is one, is prevented or “shadowed” by the local version for the duration of execution of the procedure or function.

Local statements also nest. A local with the same name as an outer nested variable won’t be accessable, and the local will only be available during the execution of the nested procedure or function.

Locals are by identifier. That is, individual a%, a() or other type specifiers cannot be used. The entire identifier is shadowed by the local definition.

6.31randomize statement

randomize

Overrides the reset of the random number generator used in rnd(). The pseudo-random number generator normally gives a series of random numbers that is the same series each time the program is run. This can be overridden by the randomize statement, which causes it to continue with the series instead of restarting.

6.32trace statement

trace

Turns on trace mode. In trace mode, each time a statement is executed, the line the statement comes from is printed. This can help debug programs.

6.33notrace statement

notrace

Turns off trace mode. See the trace statement.

6.34bye statement

bye

Exits the IP Basic interpreter.

6.35clear statement

clear

Resets all variables to their default values (numeric variables to zero, string variables to empty) and closes all user-opened files. The clear statement also invalidates any saved position from a stop statement, so a subsequent cont will not be possible.

6.36cont statement

cont

Continues program execution after a stop statement has halted the program. Execution resumes from the point where the program was stopped. It is an error if no stop statement has been executed, or if a clear, new, or end statement has been executed since the last stop.

6.37delete statement

delete [startline][-endline]

Deletes program lines by line number or range. If a single line number is given, that line is deleted. If a range is given with a - separator, all lines in the range are deleted inclusive. If no start line is given, deletion begins from the first line. If no end line is given after the -, deletion continues to the last line.

Examples:

delete 40

Deletes line 40.

delete 40-100

Deletes lines 40 through 100.

delete -40

Deletes from the first line through line 40.

delete 40-

Deletes from line 40 through the last line.

6.38kill statement

kill filename

Deletes a file from disk. The filename is a string expression. If the file does not have an extension, ".bas" is appended. It is an error if the file does not exist.

It is an error if named file I/O is not enabled.

6.39merge statement

merge filename

Merges a program file into the current program. Lines are read from the file and entered into the program one at a time. If a line in the file has the same number as an existing program line, the existing line is replaced. Lines with new numbers are inserted at the appropriate position. Unlike load, the current program is not cleared first.

The filename is a string expression. If the file does not have an extension, ".bas" is appended. It is an error if the file does not exist.

It is an error if named file I/O is not enabled.

6.40name statement

name oldfilename as newfilename

Renames a file on disk. Both the old and new filenames are string expressions. If either filename does not have an extension, ".bas" is appended. It is an error if the old file does not exist.

It is an error if named file I/O is not enabled.

6.41renum statement

renum [[newstart][,oldstart][,increment]]

Renumbers the lines of the current program. The optional parameters control the renumbering:

newstart: The new starting line number (default 10).

oldstart: The first old line number to renumber from (default: first line).

increment: The increment between new line numbers (default 10).

All line number references in goto, gosub, then, and restore statements are updated to reflect the new line numbers.

It is an error if the resulting line numbers would exceed the maximum line number or overlap with unrenumbered lines.

Examples:

renum

Renumbers all lines starting at 10 with increment 10.

renum 100,,20

Renumbers all lines starting at 100 with increment 20.

6.42dir statement

dir

Lists the files in the current directory in a columnar format. Directory entries are shown with a "/" suffix.

7Expressions

Expressions in IP Basic consist of standard operators, standard functions, and user defined functions. The operators are, in order from lowest to highest precedence, in groups of equal precidence:

a and b Find the bit or logical and of a and b.

a or b Find the bit or logical or of a and b.

xor Find the bit or logical xor of a and b.

a = b Equals. Returns -1 if a = b, otherwise 0.

a <> b Not equals. Returns -1 if a <> b, otherwise 0.

a < b Less than. Returns -1 if a < b, otherwise 0.

a > b Greater than. Returns -1 if a > b, otherwise 0.

a <= b Less than or equal. Returns -1 if a <= b, otherwise 0.

a >= b Greater than or equal. Returns -1 if a >= b, otherwise 0.

a + b Add a and b

a – b Subtract b from a.

a*b Multiply a and b.

a/b Divide a by b.

a mod b Find a modulo b

a div b Divide a by b in integer mode.

a^b Exponential. Find a to the b power.

+a Positivition. Find a.

-a Negation. Find –a.

not a Logical bit not of a.

(a) Subexpression. Find a.

func(a) Find function.

Logical values are always returned as true = -1 and false = 0, because -1 is 2’s complement notation for all bits high in the integer result. This is convienent in conjuction with Boolean math. For example:

1 = 1 and 1 <> 2 is 0, because -1 and 0 are 0.

1 = 1 and 2 = 2 is -1, because -1 and -1 is -1.

1 = 1 and 2 ` is 2 because -1 and any value is the same value.

7.1Standard functions

left$(string, length)

Finds the length number of characters at the left of the string.

right$(string, length)

Finds the length number of characters at the right of the string.

mid$(string, position, length)

Finds length number of characters starting at the position, which is 1 to n.

chr$(value)

Finds the ASCII character corresponding to the character code value.

asc(string)

Finds the ASCII character code corresponding to the first character in the string.

len(string)

Finds the length, in number of characters, of the string.

val(string)

Finds the value of a number in the string (parses and converts the number). The value can be integer or real, and may contain an exponent.

str$(value)

Converts the number value to its equivalent string. Real or integer can be converted. The same comments as print values apply here (see print statement).

rnd(value)

Finds the next random number from the pseudo-random number generator in the range 0 to 1.

int(value)

Finds the integer value of real. The fraction is truncated.

sqr(value)

Finds the square root of the value.

abs(value)

Finds the absolute value.

sgn(value)

Find sign of value, which is 1 if the value is positive, or -1 if the value is negative.

sin(value)

Find the sine of the value.

cos(value)

Finds the cosine of the value.

tan(value)

Finds the tangent of the value.

atn(value)

Finds the arctangent of the value.

log(value)

Finds the log of the value.

exp(value)

Finds the exponential of the value.

lcase(string)

Finds the lower case equivalent of the string.

ucase(string)

Finds the upper case equivalent of the string.

eof(#filenumber)

Finds if the file by filenumber is at the end of that file. Returns -1 if so, otherwise 0.

7.2Batch mode

By completely running IP Basic in batch mode, a fully automated program run can be made. The input is redirected from a file, and the output is redirected to a file (or simply printed to console):

basic < infile > outfile

Thus a sample input file would be:

10 print “hi”

20 end

Run

Then the output file would be:

hi

7.3Cut and paste

A program can also be entered by copying it to the clipboard, then pasting it onto the window running IP Basic. The program will need line numbers to do this, since console line input mode is being used.

Similarly, the program can be saved by using list to print it, then copying the result to the clipboard, then pasting to an editor and saving.

In this way a fully interactive session can be created.



8BNF Grammar Specification

This chapter provides a complete BNF (Backus-Naur Form) grammar specification for the IP BASIC language. The grammar is organized hierarchically, starting with program structure and proceeding through statements, expressions, variables, and lexical elements.

8.1Program Structure

<program> ::= <line>*



<line> ::= [<line-number>] <statement-list> <end-of-line>

| [<line-number>] <end-of-line>

| <label> ":" <statement-list> <end-of-line>



<line-number> ::= <digit>+



<label> ::= <identifier>



<statement-list> ::= <statement> [":" <statement>]*



<end-of-line> ::= <newline> | <eof>

8.2Statements

The complete statement syntax includes:

<statement> ::= <input-stmt>

| <print-stmt>

| <goto-stmt>

| <on-stmt>

| <if-stmt>

| <rem-stmt>

| <stop-stmt>

| <run-stmt>

| <list-stmt>

| <new-stmt>

| <let-stmt>

| <load-stmt>

| <save-stmt>

| <data-stmt>

| <read-stmt>

| <restore-stmt>

| <gosub-stmt>

| <return-stmt>

| <for-stmt>

| <next-stmt>

| <while-stmt>

| <wend-stmt>

| <repeat-stmt>

| <until-stmt>

| <select-stmt>

| <case-stmt>

| <other-stmt>

| <endsel-stmt>

| <open-stmt>

| <close-stmt>

| <end-stmt>

| <dim-stmt>

| <def-stmt>

| <function-stmt>

| <endfunc-stmt>

| <procedure-stmt>

| <endproc-stmt>

| <randomize-stmt>

| <trace-stmt>

| <notrace-stmt>

| <bye-stmt>

| <procedure-call>

8.3Expression Hierarchy

Expressions are parsed according to the following precedence hierarchy (from lowest to highest precedence):



1. Logical operations (and, or, xor)

2. Relational operations (=, <>, <, >, <=, >=)

3. Additive operations (+, -)

4. Multiplicative operations (*, /, mod, div)

5. Exponentiation (^)

6. Unary operations (+, -, not)

7. Primary expressions (literals, variables, functions, parentheses)



<expression> ::= <logical-expr>



<logical-expr> ::= <relational-expr> [<logical-op> <relational-expr>]*



<logical-op> ::= "and" | "or" | "xor"



<relational-expr> ::= <additive-expr> [<relational-op> <additive-expr>]*



<relational-op> ::= "=" | "<>" | "<" | ">" | "<=" | ">="



<additive-expr> ::= <multiplicative-expr> [<additive-op> <multiplicative-expr>]*



<additive-op> ::= "+" | "-"



<multiplicative-expr> ::= <exponential-expr> [<multiplicative-op> <exponential-expr>]*



<multiplicative-op> ::= "*" | "/" | "mod" | "div"



<exponential-expr> ::= <unary-expr> ["^" <unary-expr>]*



<unary-expr> ::= [<unary-op>] <primary-expr>



<unary-op> ::= "+" | "-" | "not"

8.4Variables and Literals

<variable> ::= <simple-variable> | <array-variable> | <record-variable>



<simple-variable> ::= <identifier> [<type-suffix>]



<array-variable> ::= <identifier> [<type-suffix>] "(" <expression> ["," <expression>]* ")"



<record-variable> ::= <identifier> "." <identifier> ["." <identifier>]*



<type-suffix> ::= "%" | "$"

Where % indicates integer type, $ indicates string type, and no suffix indicates real type.

8.4.1Literals

<integer-literal> ::= [<sign>] <digit>+

| "$" <hex-digit>+ (* hexadecimal *)

| "&" <octal-digit>+ (* octal *)

| "%" <binary-digit>+ (* binary *)



<real-literal> ::= [<sign>] <digit>+ "." [<digit>*] [<exponent>]

| [<sign>] [<digit>*] "." <digit>+ [<exponent>]

| [<sign>] <digit>+ <exponent>



<string-literal> ::= '"' <string-char>* '"'



<identifier> ::= <letter> [<letter> | <digit>]*

8.5Grammar Notes

• Case is not significant except within string literals

• Line numbers range from 0 to 9999

• String maximum length is 250 characters

• Maximum 255 variables in a program

• File numbers range from 1 to 100, with 1=stdin and 2=stdout

• Identifiers can be fully alphanumeric with underscores, unlike classic BASIC



For complete syntax details of individual statements, see the corresponding sections in earlier chapters.


0