Welcome to SmallBASIC

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.

Constants and Variables

  • All user variables (include arrays) are ‘Variant’. That means the data-type is invisible to user.
  • Arrays are always dynamic, even if you had declared their size, with dynamic size and type of elements.

However, SmallBASIC uses, internally, 4 data-types

  • Integer (32bit)
  • Real (64bit)
  • String (<32KB on 16bit / 2GB on 32bit)
  • Array (~2970 elements on 16bit / ~50M elements on 32bit)

Conversions between those types are performed internally. In any case there are functions for the user to do it manually.

Variable names

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 a ‘$’.

About the dollar-symbol

The symbol ‘$’ is supported for compatibility. Since in SmallBASIC there are no data-types its use is meaningless.

The dollar in function names will be ignored.

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 allowed.

The dollar in system variables names will be ignore it (that means COMMAND and COMMAND$ is the same)

Example of variable names:

abc, a_c, _bc, ab2c, abc$ -> valid names
1cd, a$b, $abc            -> invalid names


This is the default data type. You can declare integers in decimal, hexadecimal, octal and binary form.

x = 256   '
x = 0x100 ' Hexadecimal form 1
x = &h100 ' Hexadecimal form 2
x = 0o400 ' Octal form 1
x = &o400 ' Octal form 2
x = 0b111 ' Binary form 1
x = &b111 ' Binary form 2


Any number which out-bounds the limits or an ‘integer’ or had decimal digits will be converted automatically to real.

x = .25
x = 1.2

Reals can be also written by using scientific notation. 1E+2 or 1E-+2, 5E—2, 2.6E-0.25, etc


Strings may be appended to one another using the + operator.

b = "Hello, " + "world!"


Constant variables can be declared by using the keyword CONST.

CONST my_pi = 3.14

System Variables

System variables, are constant variables for the programmer. Those variables get values or modified at run-time by the SB’s subsystem.

  • OSNAME Operating System name
  • OSVER Operating System Version (0xAABBCC (A=major, B=minor, C=patch))
  • SBVER SmallBASIC Version (0xAABBCC)
  • PI 3.14..
  • XMAX Graphics display, maximum x (width-1)
  • YMAX Graphics display, maximum y (height-1) value
  • BPP Graphics display: bits per pixel (color resolution)
  • VIDADR Video RAM address (only on specific drivers)
  • CWD Current Working Directory
  • HOME User’s home directory
  • COMMAND Command-line parameters
  • TRUE The value 1
  • FALSE The value 0


Sorted by priority

( ) 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
= Equal
<> or != Not Equal
>, < Less Than, Greater Than
=>, =< Less or Equal, Greater or Equal
>=, <= Less or Equal, Greater or Equal
IN belongs to … (see “The IN operator”)
LIKE Regular expression match (see “The LIKE operator”)
AND or && Logical AND
OR or Logical OR
BAND or & bitwise AND
BOR or bitwise OR
EQV bitwise EQV
IMP bitwise IMP
XOR bitwise XOR
NAND bitwise NAND
NOR bitwise NOR
XNOR bitwise XNOR

Special Characters

&h or 0x Prefix for hexadecimal constant (0×1F, &h3C)
&o or 0o Prefix for octal constant (0o33, &o33)
&b or 0b Prefix for binary constant (0b1010, &b1110)
[,;] Array definition (function ARRAY) ($1)
<< Appends to an array (command APPEND) ($1)
++ Increase a value by 1 (x = x + 1) ($1)
Decrease a value by 1 (x = x – 1) ($1)
p= Another LET macro (x = x p …). Where p any character of -+/\*^%&
: Separates commands typed on the same line
& Join code lines (if its the last character of the line). The result line its must not exceed the max. line size.
# Meta-command (if its the first character of the line) or prefix for file handle
@ The ‘at’ symbol can by used instead of BYREF ($1)

Pseudo operators. These operators are replaced by compiler with a command or an expression.

Statement OPTION keyword parameters

This special command is used to pass parameters to the SB-environment. There are two styles for that, the run-time (like BASE) which can change the value at run-time, and the compile-time (like PREDEF) which used only in compile-time and the value cannot be changed on run-time.


Statement OPTION BASE lower-bound

The OPTION BASE statement sets the lowest allowable subscript of arrays to lower-bound. The default is zero. The OPTION BASE statement can be used in any place in the source code but that is the wrong use of this except if we have a good reason. In most cases the OPTION BASE must declared at first lines of the program before any DIM declaration.


Sets as default matching algorithm to (P)erl-(C)ompatible ®egular (E)xpressions library or back to simple one. Matching-algorithm is used in LIKE and FILES.

PRCE works only in systems with this library and it must be linked with. Also, there is no extra code on compiler which means that SB compiles the pattern every time it is used.


Statement OPTION PREDEF parameter

Sets parameters of the compiler. Where parameter

  • QUIET Sets the quiet flag (-q option)
  • COMMAND cmdstr Sets the COMMAND$ string to var (useful for debug reasons)
  • GRMODE [widthxheight[xbpp]] Sets the graphics mode flag (-g option) or sets the preferred screen resolution. Example: (Clie HiRes)
  • TEXTMODE Sets the text mode flag (g option)
  • CSTR Sets as default string style the C-style special character encoding (’\’)


Used by Unix to make source runs as a script executable

#sec: section-name
Used internally to store the section name. Sections names are used at limited OSes like PalmOS for multiple 32kB source code sections.

#inc: file
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 Unix must separated by ‘:’, and on DOS/Windows by ‘;’


MyLibProc "Hi"

*Arrays and Matrices*

Define a 3x2 matrix
A = [11, 12; 21, 22; 31, 32]

That creates the array

| 11  12|
| 21  22| = A
| 31  32|

The comma used to separate column items; the semi-colon used to separate rows. Values between columns can be omitted.

A = [ ; ; 1, 2 ; 3, 4, 5]

This creates the array

| 0  0  0|
| 1  2  0| = A
| 3  4  5|

Supported operators:


B = [1, 2; 3, 4]: C = [5, 6; 7, 8]

A = B + C
C = A – B




A2 = -A


A = [1, 2; 3, 4]: B = [5 ; 6]
C = A * B
D = 0.8 * A


A = [ 1, -1, 1; 2, -1, 2; 3, 2, -1]


? "Solve this:"
? "  5x - 2y + 3z = -2"
? " -2x + 7y + 5z =  7"
? "  3x + 5y + 6z =  9"
A = [ 5, -2, 3; -2, 7, 5; 3, 5, 6]
B = [ -2; 7; 9]
C = LinEqn(A, B)
? "[x;y;z] = "; C

There is a problem with 1 dimension arrays, because 1-dim arrays does not specify how SmallBASIC must see them.

DIM A(3)

| 1 2 3| = A


| 1|
| 2| = A
| 3|

And because this is not the same thing. (ex. for multiplication) So the default is columns

DIM A(3) ' or A(1,3)

| 1 2 3| = A

For vertical arrays you must declare it as 2-dim arrays Nx1

DIM A(3,1)

| 1|
| 2| = A
| 3|

Nested arrays are allowed

A = [[1,2] , [3,4]]
B = [1, 2, 3]
C = [4, 5]
B(2) = C
print B

This will be printed

[1, 2, [4, 5], 3]

You can access them by using a second (or third, etc) pair of parenthesis.

B(2)(1) = 16
print B(2)(1)

Result: 16

The operator IN

IN operator is used to compare if the left-value belongs to

' Using it with arrays
print 1 in [2,3]        :REM FALSE
print 1 in [1,2]        :REM TRUE
print "b" in ["a", "b", "c"] :REM TRUE
' Using it with strings
print "na" in "abcde"   :REM FALSE
print "cd" in "abcde"   :REM TRUE
' Using it with number (true only if left = right)
print 11 in 21          :REM FALSE
print 11 in 11          :REM TRUE
' special case
' auto-convert integers/reals
print 12 in "234567"    :REM FALSE
print 12 in "341256"    :REM TRUE

The operator LIKE

LIKE is a regular-expression operator. It is compares the left part of the expression with the pattern (right part). Since the original regular expression code is too big (for handhelds), I use only a subset of it, based on an excellent old stuff by J. Kercheval (match.c, public-domain, 1991). But there is an option to use PCRE (Perl-Compatible Regular Expression library) on systems that is supported (Linux); (see OPTION).

The same code is used for filenames (FILES, DIRWALK) too. In the pattern string:

* matches any sequence of characters (zero or more)
? matches any character
[SET] matches any character in the specified set,
[!SET] or [^SET] matches any character not in the specified set.

A set is composed of characters or ranges; a range looks like character hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of characters allowed in the [..] pattern construct.

To suppress the special syntactic significance of any of `[]*?!^-\’, and match the character exactly, precede it with a `\’.

? "Hello" LIKE "*[oO]" : REM TRUE
? "Hello" LIKE "He??o" : REM TRUE
? "Hello" LIKE "hello" : REM FALSE
? "Hello" LIKE "[Hh]*" : REM TRUE

The pseudo-operator <<

This operator can be used to append elements to an array.

A << 1
A << 2
A << 3

? A(1)

Syntax of procedure (SUB) statements

SUB name [([BYREF] par1 [, ...[BYREF] parN)]]
  [LOCAL var[, var[, ...]]]

Syntax of function (FUNC) statements

FUNC name[([BYREF] par1 [, ...[BYREF] parN)]]
  [LOCAL var[, var[, ...]]]

On functions you must use the function’s name to return the value. That is, the function-name acts like a variable and it is the function’s returned value.

The parameters are ‘by value’ by default. Passing parameters by value means the executor makes a copy of the parameter to stack. The value in caller’s code will not be changed.

Use BYREF keyword for passing parameters ‘by reference’. Passing parameters by reference means the executor push the pointer of variable into the stack. The value in caller’s code will be the changed.

' Passing 'x' by value
SUB F(x)
F x
? x:REM displays 2
' Passing 'x' by reference
F x
? x:REM displays 1

You can use the symbol instead of BYREF@. There is no difference between and BYREF@.

SUB F(@@x)

On a multi-section (PalmOS) applications sub/funcs needs declaration on the main section.

declare func f(x)

#sec:another section
func f(x)

Use the LOCAL keyword for local variables. LOCAL creates variables (dynamic) at routine’s code.

  ? N:REM displays 2

? N:REM displays 1

You can send arrays as parameters.

When using arrays as parameters its better to use them as BYREF; otherwise their data will be duplicated in memory space.

  ? FRE(0)

SUB FBV(tbl)
  ? FRE(0)

DIM dt(128)
? FRE(0)
FBR dt
? FRE(0)
FBV dt
? FRE(0)

Passing & returning arrays, using local arrays.

func fill(a)
  local b, i

  dim b(16)
  for i=0 to 16

DIM v()

Single-line Functions

There is also an alternative FUNC/DEF syntax (single-line functions). This is actually a macro for compatibility with the BASIC’s DEF FN command, but quite useful.

FUNC name[(par1[,...])] = expression
DEF name[(par1[,...])] = expression

DEF MySin(x) = SIN(x)
? MySin(pi/2)

Nested procedures and functions

One nice feature, are the nested procedures/functions. The nested procedures/functions are visible only inside the “parent” procedure/function.

There is no way to access a global procedure with the same name of a local.

FUNC f(x)
    Rem Function: F/F1()
    FUNC f1(x)
        Rem Function: F/F1/F2()
        FUNC f2(x)
        f1 = f2(x)/4
    Rem Function: F/F3()
    FUNC f3
? f1(pi) : REM OK
? f2(pi) : REM ERROR
f = x + f1(pi) + f3 : REM OK


Units are a set of procedures, functions and/or variables that can be used by another SB program or SB unit. The main section of the unit (commands out of procedure or function bodies) is the initialization code.

A unit declared by the use of UNIT keyword.


The functions, procedure or variables which we want to be visible to another programs must be declared with the EXPORT keyword.


Keep file-name and unit-name the same. That helps the SB to automatically recompile the required units when it is needed. To link a program with a unit we use the IMPORT keyword.


To access a member of a unit we must use the unit-name, a point and the name of the member.

PRINT MyUnit.MyF(1/1.6)

Full example:

file my_unit.bas:



REM a shared function
    F = x*x

REM a non-shared function
    I = x+x

REM Initialization code
V="I am a shared variable"
L="I am invisible to the application"
PRINT "Unit 'MyUnit' initialized :)"

file my_app.bas:

PRINT MyUnit.F(2)

The pseudo-operators ++/—/p=

The ++ and — operators are used to increase or decrease the value of a
variable by 1.

x = 4
x ++ : REM x <- x + 1 = 5
x -- : REM x <- x - 1 = 4

The generic p= operators are used as in C Where p any character of -+/\*^%&|

x += 4 : REM x <- x + 4
x *= 4 : REM x <- x * 4

All these pseudo-operators are not allowed inside of expressions

y = x ++ ' ERROR
z = (y+=4)+5 ' ALSO ERROR

The USE keyword

This keyword is used on specific commands to passing a user-defined expression.

SPLIT s," ",v USE TRIM(x)

In that 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

The DO keyword

This keyword is used to declare single-line commands. It can be used with WHILE and FOR-family commands.

FOR f IN files("*.txt") DO PRINT f
WHILE i < 4 DO i ++

Also, it can be used by IF command (instead of THEN), but is not suggested.

Using LOCAL variables

When a variable is not declared it is by default a global variable. A usual problem is that name may be used again in a function or procedure.

  FOR i=1 TO 6

FOR i=1 TO 10
  PRINT F(i)

In this example, the result is a real mess, because the var{i of the main loop will always (except the first time) have the value 6!

This problem can be solved if we use the LOCAL keyword to declare the var in the function body.


  FOR i=1 TO 6

FOR i=1 TO 10
  PRINT F(i)

It is good to declare all local variables on the top of the function. For compatibility reasons, the func./proc. variables are not declared as ‘local’ by default. That it is WRONG but as I said … compatibility.

Loops and variables

When we write loops it is much better to initialize the counters on the top of the loop instead of the top of the program or nowhere.

i = 0
  i = i + 1
UNTIL i > 10

Initializing variables at the top of the loop can make code more readable.

Loops and expressions

FOR-like (loops) commands evaluate both the “destination” and the exit-expression every time.

FOR i=0 TO LEN(FILES("*.txt"))-1
    PRINT i

In that example the ‘destination’ is the LEN)-1 For each value of i the destination will be evaluated. That is WRONG but it is supported by BASIC and many other languages.

So, it is much better to be rewritten as

FOR i=0 TO idest
    PRINT i

Of course, it is much faster too.


"FOR-like commands are evaluate the ‘destination’ every time. Also, loops are evaluate the exit-expression every time too."

should change to something like this"
FOR-like (loops)commands evaluate both the ‘destination’ and the exit-expression every time.

I like this page. A good summary

I can't seem to make the below command work. Can I get an example?

NUM [initial-line [, increment]] [Command]
The NUM command sets the values for the autonumbering. If the ’initial-line’ and
’increment’ are not specified, the line numbers start at 10 and increase in increments
of 10.

Hi, I have downloaded small basic onto my laptop, however every time I try to run the program I stops working and shuts down on me.

Can anyone help? Has this happened to you ?

I confess when I was new to this version of BASIC, I was very disconcerted to find my very simply classic one liner program, Print "Hello World" not working as I was expecting. I am embarrassed to say how long it took for me to find the Output tab, "Oh! there is the results of my program! but wait where did my file get saved? And help what happened to that?" I had just come from playing with nuBasic version of Basic which is more Windows 7 familiar. But this version (SB 11.5) of BASIC is sweet, no data typing!, dynamic arrays! Everything is under tabbed screens or forms or windows whatever you call them, and did I mention no data typing? Thanks to them you can load a number of programs at once and its all there at your next session. By the way, Hello World will hang in there for you to see it with second line: Input "press enter", K

I confess when I was new to this version of BASIC, I was very disconcerted to find my very simply classic one liner program, Print "Hello World" not working as I was expecting. I am embarrassed to say how long it took for me to find the Output tab, "Oh! there is the results of my program! but wait where did my file get saved? And help what happened to that?" I had just come from playing with nuBasic version of Basic which is more Windows 7 familiar. But this version (SB 11.5) of BASIC is sweet, no data typing!, dynamic arrays! Everything is under tabbed screens or forms or windows whatever you call them. Thanks to them you can load a number of programs at once and its all there at your next session. By the way, Hello World will hang in there for you to see it with second line: Input "press enter", K

Hi, I have downloaded small basic onto my laptop, however every time I try to run the program I stops working and shuts down on me.

Can anyone help? Has this happened to you ?

The first time I've used SmallBASIC v0.12.2 I've
tested the next program on two laptops:
' Obviously instead of '/' I had to put ':' char,
' but I just wanted to see what will happen

print "myName" / print "myName"

On ASUS 32-bit + LinuxMint xfce 17.3 the interpreter just stopped and indicated where the syntax error is (that's OK).

On ASUS 64-bit + LinuxMint Cinnamon 17.3 the laptop freezes and it sounded like the hard-disk is stuck in a loop. It took me 5 minutes to enter tty1 and reboot the laptop from the console. If I would just turned off the laptop then the file system would be damaged... I don't know why.

conclusion: use SmallBASIC on another PC/OS, or reinstall/clean your system, or check for some unusual bug/code in your program.
(I'm new to SmallBASIC but I know that no programming language is perfect, especially when new technologies are popping up every day).

"Freeze" with syntax error during a run is standard procedure with current SmallBASIC. You just need to hit escape key to return to editor even though you are already are looking at the editor! The same happens when you consult help, you need to escape from it to return to editor/editing.

You might want PAUSE '(wait for keypress) or DELAY 1000 '(1 sec) so that the output screen will not return immediately back to editor after a run.
You can always see results of last run with right click, click show output screen.

SmallBASIC is pretty unique with built in editor available from right click menu, it has its quirks.

PS (hour later) I tried to duplicate this error (on Windows 10 laptop) and discovered:
1. Enter key will also work to break out of freeze, or being stuck in upper right message area
2. PAUSE (or DELAY) weren't needed to keep the output screen showing ???

Then I tried to duplicate error on Android NOOK, it does things different like only flashing an error message (over the pop up keyboard) for too short a time, one might not even notice a message given if looking somewhere else.

So it might be an OS problem too...

BTW, Welcome shian!

Thank you,

In the first case it was truly system failure. the tty1 console confirmed it by displaying repeatedly a message about loop, while the entire system is frozen (mouse, keyboard, screen).

But the good news is that, today, after I reboot the laptop and tried to run this program again - everything was just fine: a syntax error message appeared as it should.

second conclusion: rebooting the computer, in many cases, is a simple solution for incredibly complicated problems.

(I will update this comment if/when I find more. I'm using Linux versions)

System Variables:
TRUE The value 1 --> TRUE = -1

* and in practice: True is any value other then 0, for expression result (because it's not always -1 or 1).

* There are more system variables, such as those used by CHART: LINECHART and BARCHART which are reserved to SmallBASIC.

Statement OPTION PREDEF parameter
OPTION PREDEF CSTR is unrecognised by the interpreter.

#inc: file --> Now it's: INCLUDE "file"
#unit-path: path --> Now it's: UNITPATH "path"

* it's important to add that the "file" or "path" are converted to lower case by SmallBASIC, since in Linux pathname is case sensitive.


? true

output: -1 (Windows 10 (64 bit) system)

Yikes! Thanks for the point shian and your other points are very valuable too.

This subject has come up on another forum. It is true BASIC will evaluate any non zero as true say in an IF/THEN = evaluation.

But when BASIC has to output one value for true, that is when it it important to know will it be -1 or will it be...

? 10>1

Output: 1 (Windows 10 (64 bit) system)

It has been discovered that C based programmers of new BASIC dialects prefer 1 over -1. I do remember -1 from DOS Basics.

But I wonder, if some old function might still return -1 for true just by habit or for compatibility to old Basics. It is something to be mindful of when an odd bug flys in.

Many parts of QuickBasic or QBASIC are written in assembly; other parts in C.

This is the reason that OPTION BASE 0 is the default; and that TRUE = -1.

Assembly is more efficient then C. And in assembly bitwise calculation is very fast.

Any sequence of bits or bytes or disk/memory address starts natively at 0; so using OPTION BASE 0 for arrays is more efficient then OPTION BASE 1.

And bitwise NOT(0) is equal -1, so it is more efficient then 1.

20 years ago speed and efficiency were critical, so it was really stupid to use 1 as TRUE and OPTION BASE 1 as default.

But for the user it's easy to think about the first element of a sequence as 1, second as 2, etc, (as well as to use positive number instead of negative).

This way or another: CONSISTENCY is a key point which makes your code work.