SmallBASIC is a fast and easy to learn BASIC language interpreter ideal for everyday calculations, scripts and prototypes. SmallBASIC includes trigonometric, matrices and algebra functions, a built in IDE, a powerful string library, system, sound, and graphic commands along with structured programming syntax.
::: articleRight :: ::: articleRightInner :: Contents :::
- Getting Started
- Source Code Format
- Comments
- Numbers and Srings
- Variables and Constants
- Arrays
- Matrices
- Maps
- Operators
- Expressions
- Subroutines and Functions
- Conditions
- Loops
- Units
- Input and Output
- The USE Keyword
- OPTION
- Meta Commands
- Exception Handling
:::
SmallBASIC is available for various operating systems, including Windows, Linux, and Android. It can be built from source to run on many other POSIX-compliant systems, such as Raspberry Pi OS. With its built-in Integrated Development Environment (IDE), you can write programs on your Android-powered tablet or mobile phone and run them instantly.
SmallBASIC comes in three different flavors for the desktop. The SDL version offers a simple but efficient IDE and is perfect for working with graphics. The FLTK version has a great IDE. The console version doesn’t offer an IDE and is text-only but works perfect with plugins like raylib or nuklear. The Android version is similar to the SDL version and comes with an integrated IDE, too.
Download the latest release of SmallBASIC. The different versions of SmallBASIC are included in the zip-file. Extract the zip-file to a location of your choice. Open the SmallBASIC folder and start one of the following programs:
- sbasicg.exe: SDL
- sbasici.exe: FLTK
- sbasic.exe: Console
Download the latest release of SmallBASIC. The different versions of SmallBASIC are provided as separate AppImages. Download an AppImage and copy it to a directory of your choice. Execute the AppImage. Depending of the Linux version you have to make the AppImage executable: chmod u+x AppImageFile
, where AppImageFile
is the filename of the AppImage.
Download and install SmallBASIC for Android using Google Play. Files are stored in /InternalMemory/SmallBASIC
or in case of an old Android version in /InternalMemory/Android/data/net.sourceforge.smallbasic/files
. For easy file transfer between Android and desktop, please read SmallBASIC file transfer
Using Linux it is quite easy to build SmallBASIC from source. This has the advantage, that you don't need to use AppImages and you can use SmallBASIC on other devices like Raspberry Pi. Please follow the instructions on Github.
Please read the separate articles for the different versions of SmallBASIC:
SmallBASIC files are plain text files in ASCII or UTF-8. A program consists of at least one line of text. Every line is terminated with a CR
or CR/LF
. Each line consist of one or more commands. Multiple commands in a line are separated by a colon :
. If &
is the last character of a line, SmallBASIC will continue with the command in the next line.
Spaces and tabs are ignored as long as the syntax is valid. Inside a string literal spaces and tabs are retained.
A line can start with a line number. Line numbers can be in any order. Multiple lines can have the same line number. Commands like GOTO
will go to the last line with the specified line number.
A comment is a piece of code which is ignored by SmallBASIC but gives the programmer helpful information about the source code. Comments can be created by placing text after a quotation mark '
or after the command REM
. Comments can be placed anywhere in the code but not inside a string. Starting with '
or REM
the rest of the line will be a comment.
When using REM
be aware that REM
is a build in command and multiple commands need to be separated with a colon :
.
' This is a comment REM This is a comment a = 1 ' This is a comment a = 1 : REM This is a comment
Integers are used to store numeric values without any fractional part. Integer is the default data type. You can declare integers in decimal, hexadecimal, octal and binary form. For hexadecimal the number starts with 0x
or &x
, for octal with 0o
or &o
, and for binary with 0b
or &b
.
256 0x100 ' Hexadecimal form 1 &h100 ' Hexadecimal form 2 0o400 ' Octal form 1 &o400 ' Octal form 2 0b111 ' Binary form 1 &b111 ' Binary form 2
Floating point values are used to store numeric data which may have a fractional part. Any number which out-bounds the limits or an integer or has decimal digits will be converted automatically to real. Reals can be written in scientific notation.
1.2 .25 1E2 1.2E-2 2.6E-0.25
Strings are used to store sequences of characters. The characters of a string are enclosed with "
. If a string spans more than one line, enclose the string with """
. The end of each line will be a line break in the string. Strings may be appended to one another using the +
operator.
"This is a string" "Hello, " + "world!" """This is a string over several lines with line breaks"""
Strings can contain escape sequences. Escape sequences always start with the \
character. The following escape sequences are supported:
Code | Action |
---|---|
\a | beep |
\t | tab (20 px) |
\r | return |
\n | next line |
\" | quote " |
\\ | Backslash \ |
\e[K | clear to end of line |
\e[nG | move to column n |
\e[s | save cursor position |
\e[u | restore cursor position |
\e[0m | reset all attributes to their defaults |
\e[1m | set bold on |
\e[3m | set italic on |
\e[4m | set underline on |
\e[7m | reverse video |
\e[21m | set bold off |
\e[23m | set italic off |
\e[24m | set underline off |
\e[27m | set reverse off |
\e[nm | n : foreground color 30 to 37, m : background color 40 to 47 |
Example:
print "String with line\nbreak" print "\e[32m\e[47mGreen text on white background"
In the console version of SmallBASIC (sbasic.exe or sbasic) most of the escape codes, for example ANSI Codes at wikipedia, can be used in version 12.25 or later. Support of escape codes depends on the operating system and the terminal you are using.
SmallBASIC uses, internally, 4 data-types:
- Integer (64bit)
- Real (64bit)
- String (> 2GB)
- Array (> 50M elements)
However, all user variables (include arrays) are 'Variant'. That means the data-type is invisible to users and might change during runtime. Arrays are always dynamic (size and number of elements), even if you had declared their size. Conversions between those types are performed internally. In any case there are functions for the user to do it manually.
Variable names can use any alphanumeric characters, extended characters (ASCII codes 128 - 255 for non-English languages), the symbol _
, and the symbol $
. The first character of the name cannot be a digit nor $
.
The symbol $
is supported for compatibility. The dollar in variable names will be count as part of the name, that means v
and v$
are two different variables. It can be used only as the last character of the name, and only one is allowed.
Variable names are case-insensitive.
abc, a_c, _bc, ab2c, abc$ -> valid names 1cd, a$b, $abc -> invalid names
Variables do not need to be declared. A variable will be initialized with 0
when used for the first time.
Values are assigned to a variable using the =
character. The value at the right of =
will be assigned to the variable on the left side. Additionally the right side of =
can be an expression or a function.
a = 256 b = 0x100 c = 0o400 d = 0b111 e = "This is a string" g = """This is a string over several lines with line breaks""" h = 1 + 1 i = h j = 1 + h k = "Hello, " + "world" l = k + "!" m = j > h n = h == j o = sin(0.5)
For compatibility reasons, SmallBASIC support the assignment of values to a variable using the LET
command.
let x = 20
Constants store values that don't change during the execution of the program. Constant variables can be declared by using the keyword CONST
. Assigning a value to a constant a second time will result in an error.
CONST my_pi = 3.14
SmallBASIC predefines the following constants:
Constant | Value |
---|---|
PI | 3.14.. |
TRUE | 1 |
FALSE | 0 |
NIL | nil (not set) |
Arrays are used to store sequences of elements. Arrays are always dynamic. The allowed data-types of the elements can be integers, reals and strings and maps Data-types can be mixed in an array. Nested arrays are allowed.
Arrays are a subclass of Matrices (see Matrices). They are equivalent to a row vector.
Arrays can be created by assignment using the =
operator, with the command DIM
, or with []
.
By Assignment
To assign an array to a variable, the array elements are enclosed by square brackets [
and ]
. The array elements are separated by a comma ,
. If no value for a element is given, SmallBASIC will set this element to 0
.
A = [1,2,3,4] A = [,2,,4] ' Equal to A = [0,2,0,4] A = [1,"A", 2.2] ' Array with elements of different data-type A = [1,"A", [2,3]] ' Creates an nested array S = [1, "Small", "BASIC"] ' Numbers and strings M = [{x: 1, y: 2}, {x: 4, y: 7}] ' Array of maps
By DIM
Using the command DIM A(n)
or DIM A[n]
, an array A
with n + 1
elements will be created. Every element is set to 0
.
DIM A(3) ' Array A with 4 elements DIM A[3]
When using the command DIM A(lower TO upper)
it is also possible, to set the lower
and upper
element index of an array.
' One dimensional array of 7 elements, starting from 3 ' with elements A(3), A(4), ... , A(9) DIM A(3 TO 9)
Empty Array
The following example will create an empty array variable. If the variable already exist, it will be deleted and reinitialized as an array.
A = []
To access an element of an array, the array name is followed by (i)
or [i]
, where i
is the element index. In SmallBASIC using default configuration, the first element of an array has the index 0
.
Examples:
A = [1,2,3,4] print A(1) ' Output: 2 A[1] = 5 ' A = [1,5,3,4] A(0) = A(3) ' A = [4,5,3,4]
Accessing an element outside the bounds of the array will result in an error.
In a nested array, one or more elements of this array are arrays. Nested arrays can be created by assignment with the =
operator. There is no limit to the depth of nesting.
A = [[1,2] , [3,4]] A = [[1,2] , [3, [4, 5]]] B = [1, 2, 3] C = [4, 5] B(2) = C ' -> B = [1, 2, [4, 5]]
To access an element of a nested array, a second (or third, etc) pair of parenthesis or square brackets can be used.
A = [1, 2, [4, 5]] PRINT A[2][0] ' Output: 4 PRINT A(2)(1) ' Output: 5
SmallBASIC supports basic array operations using the standard operators:
Element-wise Addition and Subtraction
A = [1, 2, 3, 4] B = [5, 6, 7, 8] C = B + A D = A - B
Element-wise Multiplication
A = [1, 2, 3, 4] B = [5, 6, 7, 8] C = A * B D = 0.8 * A
Equality
A = [1, 2, 3, 4] B = [5, 6, 7, 8] e = A==B
Unary
A = [5, 6; 7, 8] B = -A
Append Elements
The pseudo-operator <<
can be used to append elements to an array.
A << 1 A << 2 A << 3 PRINT A(1) ' Output: 2
A 2D matrix can be created by assignment using the =
operator or with the command DIM
.
By Assignment
To assign a matrix to a variable, the matrix elements are enclosed by square brackets [
and ]
. The matrix elements of one row are separated by ,
and rows are separated by a semicolon ;
. If no value for a element is given, SmallBASIC will set this element to 0
.
Examples 1:
M = [11, 12; 21, 22; 31, 32] ' Creates the 3x2 matrix ' 11 12 ' 21 22 ' 31 32
Example 2:
M = [ ; ; 1, 2 ; 3, 4, 5] ' Creates the 3x3 matrix ' 0 0 0 ' 1 2 0 ' 3 4 5
By DIM
Using the command DIM M(n,m)
or DIM M[n,m]
, a matrix M
with n + 1
rows and m + 1
elements per row will be created. Every element is set to 0
.
Example:
DIM M(3,2) ' Creates the 3x4 matrix ' 0 0 0 ' 0 0 0 ' 0 0 0 ' 0 0 0
When using the command DIM A(rlower TO rupper, elower TO eupper)
it is also possible, to set the rlower
and rupper
row index and elower
and eupper
element index of a matrix.
Example:
DIM M(2 to 4, 3 to 7) ' Creates the 5x3 matrix ' 0 0 0 0 0 ' 0 0 0 0 0 ' 0 0 0 0 0 ' With elements M(2,3) to M(2,7), M(3,3) to M(3,7) and M(4,3) to M(4,7)
To access an element of a matrix, the matrix name is followed by (row, column)
or [row, column]
, where column
and row
are the coordinates of the matrix element. In SmallBASIC using default configuration, the first element of a matrix has the index (0, 0)
.
Examples:
M = [1,2;3,4] print M(0,0) ' Output: 1 M[1,0] = 5 ' M = [1,2;5,4] M(0,1) = M(0,0) ' M = [1,1,5,4]
Accessing an element outside the bounds of the matrix will result in an error.
SmallBASIC supports basic matrix operations using the standard operators:
Addition and Subtraction
A = [1, 2; 3, 4] B = [5, 6; 7, 8] C = B + A D = A - B
Multiplication
A = [1, 2; 3, 4] B = [5 ; 6] C = A * B D = 0.8 * A
Equality
A = [1, 2; 3, 4] B = [5, 6; 7, 8] e = A==B
Unary
A = [5, 6; 7, 8] B = -A
Matrices with a dimension higher than two can be created with the command DIM M(n1, n2, ..., ni)
, where n1 + 1
to ni + 1
are the number of elements of each dimension. To access an element, give the coordinates of that element in parenthesis or square brackets.
Example:
DIM M(2,2,3) ' Creates a 3x3x4 3D Matrix M[0,0,2] = 5
Equality is the only valid matrix operating for higher dimensional matrices.
By Assignment
To create a column vector, separate the elements by ;
.
Example:
v = [1;2;3] ' Creates the column vector ' 1 ' 2 ' 3 PRINT v(1,0) ' Prints the value of the element in row 2 -> 2
By DIM
The command DIM A(n)
creates a row vector with n+1
elements. To create a column vector, use DIM A(n, 0)
. The elements of the column vector can be access by A(n,0)
, where n
is the column index of the element.
DIM A(2) ' Creates a row vector ' 0 0 0 DIM B(2, 0) ' Creates a column vector ' 0 ' 0 ' 0 PRINT B(1,0) ' Prints the value of the element in row 2
Maps are complex data structures with key-value pairs. Elements of a map are addressed by keys. Allowed data-types are integers, reals, strings, arrays, maps and references. Elements of different data-types can be mixed in a map.
Maps can be created by assignment using the =
operator, with the command ARRAY
and with {}
.
By Assignment
To assign a map to a variable, key-value pairs are enclosed by curly brackets {
and }
. The key-value pairs are separated by comma ,
. A key-value pair consist of a key and a value. Key and value are separated by a colon :
. The key is a string. It is not necessary to enclose the string with quotes. The value can be any data-type, array, map or reference. The order of key-value pairs is not relevant for maps.
Additionally, a map variable can be created with the assignment name.key = value
, where name
is the name of the map variable, key
is the name of the key and value any datatype supported by SmallBASIC.
Examples of valid map assignments:
A = {x:1, y:2, z:3} B = {"x":1, "y":2, "z":3} C = {1:10, 2:5, Name: "SmallBASIC"} D = {ArrayData:[1,2,3], MapData:{node:1, value:5}} E.x = 1
By ARRAY
Using the command M = ARRAY(JSONString)
will create a map variable from the string JSONString
.
M = ARRAY("{x:1, y:2, z:3}") s = "{1:10, 2:5, Name:\"SmallBASIC\"}" ' The quotation marks of the string SmallBASIC are escaped with \" M = ARRAY(s)
Empty Map
The following example will create an empty map variable. If the variable already exist, it will be deleted and reinitialized as a map.
A = {}
An element of a map variable can be accessed in the following three ways:
name.key
name("key")
orname["key"]
s = "key" : name(s)
ors = "key" : name[s]
where name
is the name of the map variable and key
is the key of the key-value pair. The third option offers the possibility to access an element using a string-variable as the key.
A = {x:1, y:2, z:3} print A.x print A("x") print A["x"] A.y = 3 A("y") = 3 A["y"] = 3
To access elements of an array or a matrix inside a map, use additional parentheses ()
or square brackets[]
.
A = {x:[2,3], y:[1,2;3,4]} print A.x(0) ' Output: 2 print A.x[1] ' Output: 3 print A.y[1,1] ' Output: 4 A.x(0) = 5 A.x[1] = 6 A.y[1,1] = 7 print A ' Output: {"y":[1,2;3,7],"x":[5,6]}
To access a nested map variable, use a further .
or ("key")
. Both notations can be mixed.
A = {x:{a:1, b:{c:2}}} print A.x.a ' Output: 1 print A.x.b.c ' Output: 2 print A("x")("a") ' Output: 1 print A("x")("b")("c") ' Output: 2 print A("x")("b").c ' Output: 2 A.x.a = 3 A.x.b.c = 4 print A ' Output: {"x":{"a":3,"b":{"c":4}}} A("x")("a") = 5 A("x")("b")("c") = 6 A("x")("b").c = 7 print A ' Output: {"x":{"a":5,"b":{"c":7}}}
Reading a non-existing element of a map will return 0
. Writing to a non-existing element will create a new key-value pair.
Use dot-notation or parenthesis-notation with the =
operator to add a new key-value pair to a map variable.
A = {a:1, b:2} A.c = 3 A("d") = 4 A.e = {x:5, y:6}
The value of a key-value pair can be a reference to a function or subroutine.
A = {} A.x = 1 A.Add = @Add A.PrintBold = @PrintBold print A ' Output: {"x":1,"Add":func,"PrintBold":func} ' Execute function and subroutine print A.Add(1, 2) A.PrintBold("Test") ' Define function and subroutine func Add(a,b) return a + b end sub PrintBold(s) print "\e[1m"; s; "\e[21m" end
Maps in combination with references can be used to create a pseudo object similar to object-oriented programming.
A = MyAddClass(3,4) print A.Add() ' Definitions func MyAddClass(x,y) local TempMap ' Properties TempMap.x = x TempMap.y = y ' Methods TempMap.Add = @AddFunction ' Functions and subroutines func AddFunction() return self.x + self.y end return TempMap end
SmallBASIC supports the following operators, sorted by priority:
Operator | Description |
---|---|
( , ) | Parenthesis |
+ , - | Unary |
~ | bitwise NOT |
NOT or ! | Logical NOT (NOT false = true) |
^ | Exponentiation |
* , / , \ | Multiplication, Division, Integer Division |
% or MOD | Reminder (QB compatible: a = int(a), b = int(b), a - b*(a/b) ) |
MDL | Modulus (a % b + b*(sgn(a) <> sgn(b)) ) |
+ , - | Addition/Concatenation, Subtraction |
= or == | Equal |
<> or != | Not Equal |
> , < | Less Than, Greater Than |
=> , =< | Less or Equal, Greater or Equal |
>= , <= | Less or Equal, Greater or Equal |
IN | belongs to |
LIKE | Regular expression match |
AND or && | Logical AND |
OR or ` | |
BAND or & | bitwise AND |
BOR or ` | ` |
EQV | bitwise EQV |
IMP | bitwise IMP |
XOR | bitwise XOR |
NAND | bitwise NAND |
NOR | bitwise NOR |
XNOR | bitwise XNOR |
These operators are replaced by the compiler with a command or an expression.
The ++
and --
operators are used to increase or decrease the value of a variable by 1.
x = 4 x++ ' x = x + 1 -> 5 x-- ' x = x - 1 -> 4
The generic p=
operators are used to perform an operation p
on a variable and store the result in the same variable. p
is any character of -+/\*^%&|
x += 4 ' x = x + 4 x *= 4 ' x = x * 4 x &= 4 ' x = x & 4
All these pseudo-operators are not allowed inside of expressions.
y = x++ ' -> ERROR z = (y+=4) + 5 ' -> ERROR
Expressions are entities that are evaluated to determine their values. They are a combination of one or more constants, variables, functions, and operators. SmallBASIC evaluates an expression and returns a value. Order of evaluation is left-to-right and inside-out according to the priority of the operators used in the expression.
a = 1 + 1 b = 1 + a c = sin(pi) d = sin(x^2) + 2 e = a AND b f = a AND (c OR d)
Subroutines and functions are blocks of code separated from the main program. These routines can be called from the main program or other subroutines and functions. When calling, program execution will jump to the start of the routine and execute the code of it. After finishing the routine, program execution will continue from the position of calling.
Subroutines and functions can be defined at every position in the source code. These routines can be nested. If a routine is nested, it can only be called within the parent routine. Otherwise subroutines and functions have a global scope.
Subroutine and function names can use any alphanumeric characters, extended characters (ASCII codes 128 - 255 for non-English languages), and the symbol _
. The first character of the name cannot be a digit.
Subroutine and function names are case-insensitive.
abc(), a_c(), ab2c(), _abc() -> valid names 1cd(), a$b() -> invalid names
Subroutines and functions can not have the same name as build-in commands.
SUB name ' subroutine code here END SUB name() ' subroutine code here END SUB name par1, ..., parN ' subroutine code here END SUB name (par1, ..., parN) ' subroutine code here END
The definition of a subroutine starts with the keyword SUB
and ends with the keyword END
. It has a name name
, can have parameters par1
to parN
and does not return a value. The parameters are separated with a comma ,
. The parameters can be optionally enclosed by parentheses.
FUNC name ' function code here RETURN value END FUNC name() ' function code here name = value END FUNC name par1, ..., parN ' function code here RETURN value END FUNC name (par1, ..., parN) ' function code here name = value END
The definition of a function starts with the keyword FUNC
and ends with the keyword END
. It has a name name
, can have parameters par1
to parN
and must return a value value
. The parameters are separated with a comma ,
. The parameters can be optionally enclosed by parentheses. To return a value, the keyword RETURN
can be used or the assignment of a value to the function name. If RETURN
is used, execution of the function will immediately stop, even if there are further commands until END
.
FUNC MyFunction() i = 1 Return i i = 2 Return i end print MyFunction() ' Output: 1
FUNC MyFunction() i = 1 MyFunction = i i = 2 MyFunction = i end print MyFunction() ' Output: 2
Using Parameters
To use a parameters inside a function or subroutine, address the parameter by the name given in the routine declaration.
FUNC AddNumbers(a, b) c = a + b RETURN c END
By-Value and By-Reference
Parameters are 'by value' by default. Passing parameters by value means, that the function or subroutine receives a copy of the parameters.
When using the keyword BYREF
or the symbol @
in the routine declaration before the parameter, a reference (pointer) to the parameter will be passed to the routine. 'by-reference' parameters can be used to return values from a subroutine or function, because the variable in the calling subroutine or function will be changed.
Passing array or map parameters as references will not result in creating a copy of the parameters in RAM. Thus, program execution will be faster and RAM will be saved.
' Passing the parameter by value SUB F(a) a = 1 END x = 2 F(x) PRINT x ' Output 2
' Passing the parameter by reference SUB F(BYREF a) a = 1 END x = 2 F(x) PRINT x ' Output 1
Functions can be exited using RETURN expression
, where expression
is an expression to be evaluated. The evaluated value of the expression will be returned by the function. Alternatively the keywords EXIT FUNC
can be used. In this case the return value of the function will be 0
. All commands following RETURN expression
or EXIT FUNC
will not be executed.
Subroutines can be exited using the keywords EXIT SUB
. All commands following EXIT SUB
will not be executed.
FUNC name(par1, ..., parN) = expression DEF name(par1, ..., parN) = expression
FUNC
and DEF
can be used to declare single-line functions. Declaration starts with the keyword FUNC
or DEF
, followed by the name of the routine. The parameter list must be enclosed by parentheses. After the closing parentheses an expression is assigned to the routine using the =
operator.
DEF MyFunc(x) = SIN(x) + COS(x) Print MyFunc(pi/2)
Variable are by default global variables. Global variables are accessible anywhere in the program. A usual problem is that a variable name may be used again in a function or subroutine:
FOR i = 1 TO 10 a = F(i) PRINT i NEXT FUNC F(x) FOR i = 1 TO 6 NEXT RETURN x END
In this example, the result is a real mess, because the variable i
of the main loop will always (except the first time) have the value 7 and the program will run endless! This problem can be solved by using the keyword LOCAL
to declare the variable in the function body.
FOR i = 1 TO 10 a = F(i) PRINT i NEXT FUNC F(x) LOCAL i FOR i = 1 TO 6 NEXT RETURN x END
It is good practice to declare all local variables on the top of the routine. For compatibility reasons, the function and subroutine variables are not declared as 'local' by default.
Nested subroutines and Functions are allowed in SmallBASIC. Nested subroutines and functions are visible only inside the parent routine. There is no way to access a global routine with the same name of a local routine.
FUNC f1(x) ' f1 FUNC f2(x) ' f2 nested in f1 FUNC f3(x) ' f3 nested in f2 f3 = cos(x) END f2 = f3(x)/4 END FUNC f4 ' f4 nested in f1 f4 = f2(pi/2) ' f2 is visible for f4 END PRINT f2(pi) ' Calling f2 inside f1 is valid 'PRINT f3(pi) ' Calling f3 inside f1 is invalid, ' because f3 is only visible to f2 END
On a multi-section (PalmOS) applications subroutines and functions need to be declared in the main section.
sec:Main declare func f(x) #sec:another section func f(x) ' function code end
Loops are used to repeatably execute commands until a stop condition is reached. Inside a loop an unlimited amount of program lines can be placed. Loops can be nested and subroutines, functions and all build-in commands can be used.
A FOR-TO-NEXT-loop will continue until an index variable goes beyond a defined stop value. In the last loop, the index variable is set to the defined stop value. The index variable is updated automatically every cycle. The syntax of a FOR-TO-NEXT-loop is:
FOR Index = StartExpr TO StopExpr STEP StepSize ' some code NEXT
Where Index
is the automatically updates index variable, StartExpr
and StopExpr
are expressions defining the start and stop value, and StepSize
is an expression defining the step size of the FOR-loop. The FOR-loop ends with the Keyword NEXT
.
The expressions Start
, Stop
and StepSize
are evaluated every cycle. It is allowed that these expressions change their value every cycle, i.e. they are changed inside the FOR-loop. To speed up a FOR-loop these expressions should be pre-calculated and assigned to variables, which are used in the loop.
Defining a step size is optional. If STEP
is not used, the step size is set to 1
.
FOR i = 6 to 1 STEP -2 PRINT i NEXT ' Output: 6,4,2
The index variable after the end of the loop has a value larger/smaller than the stop condition, depending on the step size.
Use EXIT
or in case of nested loops EXIT FOR
to end the loop before the stop condition is reached.
A FOR-IN-NEXT loop loops until the last element of an array or map is reached. In every cycle the index variable is updated with the next value of the array or map. The array or map variable can change value and/or number of elements.
a = [12, 6, 23, -4] FOR index IN a PRINT index NEXT ' Output 12 6 23 -4
Use EXIT
or in case of nested loops EXIT FOR
to end the loop before the last element is reached.
A WHILE-WEND loop continues executing as long as the expression Expression
evaluates to true
.
WHILE Expression ' some code WEND
If Expression
evaluates to false
when starting the loop for the first time, the loop will not be entered and the code inside the loop will not be executed.
WHILE index < 10 index++ PRINT index WEND
Use EXIT
or in case of nested loops EXIT LOOP
to exit the loop.
A REPEAT-UNTIL loop continues executing until the expression Expression
evaluates to true
. The code inside the loop will be executed at least one time.
REPEAT ' some code UNTIL Expression
REPEAT index++ PRINT index UNTIL index > 10
Use EXIT
or in case of nested loops EXIT LOOP
to exit the loop.
This keyword is used to declare single-line commands. It can be used with WHILE
and FOR
-family loops.
FOR i = 1 to 10 DO PRINT i FOR f IN files("*.txt") DO PRINT f
WHILE i < 4 DO i++
Conditions can be used to branch the program flow depending on the value of expressions.
IF expression1 THEN ' some code ELSEIF expression2 THEN ' some code ELSE ' some code ENDIF
IF-THEN_ELSEIF-ELSE causes SmallBASIC to make a decision based on the value of an expression. expression1
and expression2
are expressions, which will be evaluated. 0
is equivalent to FALSE
, while all other values are equivalent to TRUE
.
Each expression in the IF/ELSEIF construct is tested in order. As soon as an expression is found to be TRUE
, then its corresponding commands are executed. If none of the expressions are TRUE
, then the commands following the ELSE
keyword are executed. If ELSE
is not specified, then execution continues with the command following ENDIF
. More then one ELSEIF
is allowed.
IF
, ELSE
, ELSEIF
, and ENDIF
must all be the first keywords on their respective lines. THEN
is optional, but if its used it must be the last keyword on its line. If anything other than a comment follows THEN
on the same line, SmallBASIC interprets it as a single-line IF-THEN-ELSE construct. IF blocks may be nested.
Instead of ELSEIF
and ENDIF
, ELIF
and FI
can be used. Instead of THEN
, DO
can be used, but this is not suggested.
IF expression THEN command1 ELSE command2
Single-line IF-THEN-ELSE causes SmallBASIC to make a decision based on the value of an expression expression
. 0
is equivalent to FALSE
, while all other values are equivalent to TRUE
. command1
and comannd2
are any legal commands. Multiple commands can be separated by a colon :
. If instead of a command a number is specified, it is equivalent to a GOTO command with the specified numeric-label.
result = IFF (condition, return_value_true, return_value_false)
The command IFF
will test the condition condition
. If condition
resolves to true
then return_value_true
will be returned otherwise return_value_false
.
x = 4 ans = IFF(x <= 5, 0, 10) PRINT ans ' Output: 0
See function reference IFF for more information.
SELECT CASE expr CASE result1 ' do thinks CASE result2 ' do thinks CASE ELSE ' do thinks END SELECT
SELECT CASE
offers a more concise syntax to writing successive IF tests. SELECT CASE
performs multiple tests on the expression expr
. If the value of expr
is equal to result1
, the case statement result1
will be entered and the commands executed. An unlimited amount of case statements can be used. Once a case statement is fulfilled the select-case structure will be exited and all following case statements will not be tested anymore. If non of the case statements were entered the optional 'CASE ELSE' statements will be entered.
See function reference SELECT CASE for detailed information.
Units are a set of subroutines, functions and/or variables that can be used by another SmallBASIC program or SmallBASIC unit. An unit has its own namespace and therefore is independent of the program code. Every unit is saved in a separate file with the extension .bas
. A unit source file can only contain one unit. Unit name must be identical to the file name, but without the .bas
extension.
An unit is declared by the use of the UNIT
keyword followed by the name of the unit as the first command in the unit source file. The functions, subroutines and/or variables which should be accessible by another programs must be declared with the EXPORT
keyword and defined in the unit source file.
UNIT MyUnitName EXPORT MyFunction FUNC MyFuntion(x) ' some code END
Function, subroutines or variables which are not exported can only be used inside the unit source file.
To import an unit in a program use the IMPORT
keyword followed by the unit name without the .bas
extension. The namespace is identical to the unit name. If a different namespace is required specify the new namespace using IMPORT UnitName AS NameSpace
.
To access a member of a unit use the namespace followed by a point and the name of the member.
IMPORT MyUnit MyUnit.MyFunction(1)
IMPORT MyUnit as u u.MyFunction(1)
The USE
keyword is used on specific commands for passing a user-defined expression.
SPLIT s," ",v USE TRIM(x)
In this example, every element of v
will be trimmed. Use the x
variable to specify the parameter of the expression. If the expression needs more parameter, you can use also the names y
and z
.
Use PRINT
to print text on the screen at the current cursor location. When starting the BASIC program, the cursor is in the top left corner. After printing to the screen the cursor location will be updated. After execution of PRINT
, if not otherwise specified, the cursor will be moved to the beginning of the next line. When printing to the last line of the screen, the screen will scroll up by one line.
Basic usage of PRINT
:
PRINT 1 ' Output: 1 PRINT 1+1 ' Output: 2 PRINT cos(pi) ' Output: -1 PRINT "Text" ' Output: Text
If ;
or ,
are used as last character of a print command, carriage return/line feed (new line) will be suppressed after printing.
Please read the language reference of PRINT for a detailed description. The text cursor can be set using LOCATE.
INPUT
reads text from keyboard and stores it in a variable. INPUT
can print a prompt on screen. After execution of INPUT
the cursor will be moved to the beginning of the next line. INPUT
will block execution of the program until the return-key is pressed.
Basic usage of INPUT
:
INPUT "How old are you?", age PRINT age
For more information see language reference of INPUT. INKEY and DEFINEKEY allow to read from a keyboard without blocking the execution of the program.
The OPTION
command is used to pass parameters to the SB-environment. There are two styles for that, the run-time which can change the value at run-time, and the compile-time which used only in compile-time and the value cannot be changed on run-time.
The OPTION BASE LowerBound
statement sets the lowest allowable subscript of arrays to LowerBound
. The default is zero. The OPTION BASE
statement can be used in any place in the source code but in most cases the OPTION BASE
must be declared in the first lines of the program before any DIM
declaration.
Use OPTION BASE 1
to set the index of the first element of an array to 1
. This option is useful especially for beginners, because it makes counting elements more intuitive.
OPTION BASE 1 A = [1,2,3] PRINT A[1] ' Output 1
OPTION BASE
is a run-time option.
OPTION MATCH [PCRE [CASELESS]|SIMPLE]
sets the default matching algorithm to (P)erl-(C)ompatible (R)egular (E)xpressions library or back to simple. The matching-algorithm is used in LIKE
and FILES
. PRCE works only in systems with this library and SmallBASIC must be linked against it.
OPTION MATCH
is a run-time option.
OPTION PREDEF parameter
sets parameters of the compiler. Where parameter
is
QUIET
: Sets the quiet flag (-q option)COMMAND cmdstr
: Sets theCOMMAND
string tocmdstr
(useful for debug reasons)GRMODE [widthxheight[xbpp]]
: Sets the graphics mode flag (-g option) or sets the preferred screen resolution. Example:OPTION PREDEF GRMODE 320x320x16
TEXTMODE
: Sets the text mode flag (-g- option)CSTR
: Sets as default string style the C-style special character encoding (\
)ANTIALIAS on,off
: Enable/Disable anti-aliasing for drawing commands likeCIRCLE
orLINE
OPTION PREDEF
is a compile-time option.
SmallBASIC uses the following meta commands:
#!...
: Shebang; used by Linux to make source runs as a script executable#sec: SectionName
: Used internally to store the section name. Sections names are used at limited OSes like PalmOS for multiple 32kB source code sections.#inc: FileName
: Used to include a SmallBASIC source file into the current BASIC code.#unit-path: path
: Used to setup additional directories for searching for unit-files This meta does nothing more than to setting up the environment variable SB_UNIT_PATH. Directories on Linux must be separated by:
, and on DOS/Windows by;
#!/usr/local/bin/sbasic #inc:"mylib.bas" #unit-path: C:\sbasic\units;C:\temp
Exception handling is supported for file handling, and accessing serial ports and network sockets. Exception handling is typically used with errors raised when calling a file system command that cannot be completed, for example attempting to open a non-existent file.
TRY ' do something CATCH err print err ' do something END TRY
TRY ' do something CATCH "Error 1" ' do something CATCH "Error 2" ' do something END TRY
The TRY
statement introduces a try/catch block. A try/catch block consist of the following structure:
TRY
The TRY
statement starts a block of commands which might create a run-time error.
CATCH [var | expr]
The CATCH
statement is used to catch a run-time error of one of the commands in the try-block.
The CATCH
statement has two modes. You can supply a variable argument to store the error string. Alternatively you can supply a string expression. When the raised error matches the string expression, the error will be caught. When using the expression mode, you can supply a succession of CATCH statements to handle various error messages separately.
END TRY
The END TRY
statement marks the end of a try/catch block.
For examples see the language reference TRY.