-
Notifications
You must be signed in to change notification settings - Fork 5
Language Reference
← Getting Started | Next: Graphics and Multimedia
- Variables and Types
- Operators
- Control Flow
- Subroutines and Functions
- Classes and Objects
- main() Entry Point
- Namespaced Modules
- Structures
- Arrays
- Hash Tables
- File I/O
- DATA, READ, RESTORE
- String Handling
- Native Library Calls
Variables in nuBASIC can be declared explicitly with Dim or created implicitly on first
assignment. The type suffix appended to the variable name determines its storage type.
| Suffix | Type | Range / Notes | Example |
|---|---|---|---|
% |
Integer | 32-bit signed, −2 147 483 648 .. +2 147 483 647 | count% = 10 |
& |
Long64 | 64-bit signed integer | big& = 10000000000 |
# |
Boolean |
True or False
|
flag# = True |
$ |
String | Variable-length UTF-8 text | name$ = "nuBASIC" |
@ |
Byte | 0..255; used in byte arrays | buf@(255) |
| (none) | Double | 64-bit IEEE 754 floating-point | pi = 3.14159 |
The Any type is inferred automatically from the assigned value and is useful in hash tables
and generic functions.
Explicit declaration with optional type annotation:
Dim counter As Integer
Dim name As String
Dim ratio As Double
Dim items(99) As Integer ' array of 100 integers (indices 0..99)
Dim flag As BooleanConstants are declared with Const and cannot be reassigned:
Const MAX_SIZE As Integer = 100
Const APP_NAME$ = "nuBASIC Demo"
Const PI_APPROX = 3.14159265a = 10 + 3 ' 13 — addition
a = 10 - 3 ' 7 — subtraction
a = 10 * 3 ' 30 — multiplication
a = 10 / 3 ' 3.333… — floating-point division
a = 10 \ 3 ' 3 — integer division (truncates)
a = 10 Div 3 ' 3 — same as backslash
a = 10 Mod 3 ' 1 — remainder
a = 2 ^ 8 ' 256 — exponentiationIncrement and decrement prefixes:
++counter% ' equivalent to: counter% = counter% + 1
--counter% ' equivalent to: counter% = counter% - 1If a = b Then ... ' equal to
If a <> b Then ... ' not equal to
If a < b Then ... ' less than
If a > b Then ... ' greater than
If a <= b Then ... ' less than or equal to
If a >= b Then ... ' greater than or equal toIf x > 0 And y > 0 Then Print "both positive"
If x = 0 Or y = 0 Then Print "at least one zero"
If Not(flag#) Then Print "flag is false"
result# = (a > b) Xor (c > d)result = a bAnd b ' bitwise AND
result = a bOr b ' bitwise OR
result = a bXor b ' bitwise XOR
result = bNot(a) ' bitwise NOT
result = a bShl 2 ' shift left 2 positions
result = a bShr 2 ' shift right 2 positionsHexadecimal literals use the BASIC &h / &H prefix. 0x / 0X is also accepted as a
convenience for C-style constants:
mask% = &hFF000000
red% = &h0000FF
white% = &hFFFFFF
same% = 0xFFFFFFSingle-line form:
If score% > 100 Then Print "High score!" Else Print "Keep trying"Multi-line form:
If score% >= 90 Then
Print "Excellent"
grade$ = "A"
ElIf score% >= 75 Then
Print "Good"
grade$ = "B"
ElIf score% >= 60 Then
Print "Passed"
grade$ = "C"
Else
Print "Failed"
grade$ = "F"
End IfElseIf is accepted as an alias for ElIf.
' Count from 1 to 10
For i% = 1 To 10
Print i%
Next i%
' Custom step
For x = 0.0 To 1.0 Step 0.25
Print x
Next x
' Count down
For i% = 10 To 1 Step -1
Print i%
Next i%
' Exit early
For i% = 1 To 1000
If i% Mod 7 = 0 And i% Mod 11 = 0 Then
Print "First multiple of both 7 and 11: "; i%
Exit For
End If
Next i%While Not(EOF(filenum%))
Input# filenum%, line$
Print line$
Wend
While 1
key$ = InKey$()
If key$ = "q" Or key$ = "Q" Then Exit While
MDelay 10
Wend' Wait for any key press — body runs at least once
Do
key$ = InKey$()
Loop While Len(key$) = 0
' Retry up to 10 times
Do
++attempts%
result% = TryOperation()
If result% = 0 Then Exit Do
Loop While attempts% < 10GoTo gameLoop
init:
score% = 0
lives% = 3
gameLoop:
If lives% = 0 Then GoTo gameOver
GoTo gameLoop
gameOver:
Print "Game over! Score: "; score%
EndGoSub calls a subroutine; Return jumps back to the statement after the GoSub call:
GoSub DrawScreen
GoTo mainLoop
DrawScreen:
Cls
FillRect 0, 0, 640, 480, &h000000
ReturnOn game_mode% GoTo beginner, intermediate, expert
beginner:
mines% = 10 : GoTo setup_done
intermediate:
mines% = 20 : GoTo setup_done
expert:
mines% = 40
setup_done:Select Case dispatches on a scalar expression. Each Case arm is tested in order; the first match wins and execution continues after End Select. Case Else (optional) matches when no earlier arm does.
Select Case score%
Case Is >= 90
grade$ = "A"
Case Is >= 75
grade$ = "B"
Case Is >= 60
grade$ = "C"
Case Else
grade$ = "F"
End SelectSupported arm forms:
| Form | Example | Matches when… |
|---|---|---|
| Single value | Case 1 |
expression = 1 |
| Value list | Case 1, 3, 5 |
expression is any listed value |
| Range | Case 1 To 10 |
1 ≤ expression ≤ 10 |
| Comparison | Case Is > 100 |
expression > 100 |
| Fallback | Case Else |
no previous arm matched |
Works with integers, doubles, and strings. Select Case blocks may be nested.
' String matching
Select Case cmd$
Case "quit", "exit", "q"
Print "Goodbye"
End
Case "help", "?"
Print "Type a command"
Case Else
Print "Unknown: "; cmd$
End SelectSub ClearArea(x1%, y1%, x2%, y2%)
FillRect x1%, y1%, x2%, y2%, &h000000
Rect x1%, y1%, x2%, y2%, &h404040
End Sub
Sub PrintCentered(msg$, row%, color%)
col% = (80 - Len(msg$)) \ 2
Locate row%, col%
Print msg$
End Sub
ClearArea 0, 0, 640, 480
PrintCentered "Welcome to nuBASIC", 12, &hffffffFunction Factorial%(n%)
If n% <= 1 Then
Factorial% = 1
Else
Factorial% = n% * Factorial%(n% - 1)
End If
End Function
Function Clamp(value, minVal, maxVal)
If value < minVal Then
Clamp = minVal
ElIf value > maxVal Then
Clamp = maxVal
Else
Clamp = value
End If
End Function
Function Greeting$(name$)
Greeting$ = "Hello, " + name$ + "! Welcome to nuBASIC."
End Function
Print Factorial%(12)
Print Clamp(1.5, 0.0, 1.0)
Print Greeting$("World")Parameters are by value (ByVal) by default — the procedure receives a copy and changes
do not affect the caller. Prefix a parameter with ByRef to pass by reference: mutations
inside the procedure propagate back to the caller's variable.
Sub Swap(ByRef a% As Integer, ByRef b% As Integer)
Dim tmp% As Integer
tmp% = a% : a% = b% : b% = tmp%
End Sub
Dim x% As Integer, y% As Integer
x% = 7 : y% = 42
Call Swap(x%, y%)
Print x%, y% ' 42 7Struct variables can also be passed ByRef:
Sub Translate(ByRef p As Point, dx As Double, dy As Double)
p.x = p.x + dx
p.y = p.y + dy
End SubCall is an optional keyword before any Sub/Function invocation. When used, arguments must
be enclosed in parentheses:
Call ClearArea(0, 0, 640, 480) ' same as: ClearArea 0, 0, 640, 480A Sub or Function may declare a parameter with empty parentheses (param() As Type) to
accept an array of any size. This lets you write generic procedures without fixing the
dimension in the signature:
Sub PrintAll(items() As String)
Dim i% As Integer
For i% = 0 To SizeOf(items) - 1
Print items(i%)
Next i%
End Sub
Dim names$(2)
names$(0) = "Alice" : names$(1) = "Bob" : names$(2) = "Carol"
Call PrintAll(names$())Include "filename.bas" (also #Include) loads and executes another source file at the
point of the directive — useful for splitting programs across multiple files:
Include "utils.bas"
Call DrawBorder(0, 0, 639, 479)Object-oriented programming is new in nuBASIC 2.0 — earlier versions had only Struct
value types. Classes are available in Modern syntax mode only: a program that defines a
Class must begin with Syntax Modern, otherwise the parser reports
'Class' requires Syntax Modern.
Classes group related data (fields) and behaviour (methods) into a single type. Declare a
class with Class/End Class; create instances with Dim:
Syntax Modern
Class Counter
Public count As Integer
Sub Reset()
Me.count = 0
End Sub
Sub Increment()
Me.count = Me.count + 1
End Sub
Function Value() As Integer
Value = Me.count
End Function
End Class
Dim c As Counter ' default-constructed instance
Call c.Reset()
Call c.Increment()
Call c.Increment()
Print c.Value() ' 2Me refers to the current instance inside an instance method.
A Sub New(...) member is the constructor — it runs when an instance is created. Pass
constructor arguments either with the Dim … As New declaration form or with a New
expression:
Syntax Modern
Class Point
Public x As Double
Public y As Double
Sub New(px As Double, py As Double)
Me.x = px
Me.y = py
End Sub
Function Length() As Double
Length = Sqr(Me.x * Me.x + Me.y * Me.y)
End Function
End Class
Dim p As New Point(3.0, 4.0) ' construct with arguments
Print p.Length() ' 5
' New is also a first-class expression: it can be assigned, passed as an
' argument, returned from a function, or used inline.
Dim q As Point
q = New Point(1.0, 2.0)
Print New Point(6.0, 8.0).Length() ' 10A class without a Sub New is default-constructed (Dim c As Counter above). A class may
also define Sub Delete() — see Destructors.
Class instances are reference types, unlike Struct values (which are copied).
Assigning one object variable to another makes both refer to the same instance, so a
mutation through one is visible through the other:
Syntax Modern
Dim a As New Counter
Dim b As Counter
b = a ' a and b now reference the same object
Call a.Increment()
Print b.Value() ' 1 — same instance
If b = a Then Print "same object" ' reference comparison
Dim empty As Counter
empty = Nothing ' a null object reference
If empty = Nothing Then Print "no object"Calling a method on a Nothing reference raises a null-reference runtime error.
Static Function and Static Sub inside a Class body define class-level procedures.
They do not receive an implicit instance and cannot access Me. Call them with
ClassName.Method(args) — no instance required:
Class MathHelper
Static Function Add(a As Integer, b As Integer) As Integer
Add = a + b
End Function
Static Sub PrintSum(a As Integer, b As Integer)
Print "Sum ="; a + b
End Sub
End Class
Dim result% As Integer
result% = MathHelper.Add(3, 7) ' 10
MathHelper.PrintSum 2, 3 ' Sum = 5Static and instance methods may coexist in the same class.
A class may define Sub Delete() as a destructor. nuBASIC calls it
automatically on owned local class instances when the procedure scope
exits, in reverse declaration order; in a derived class the derived
destructor runs before the base destructor.
Class Resource
Public name$ As String
Sub New(n$ As String)
Me.name$ = n$
End Sub
Sub Delete()
Print "closing "; Me.name$
End Sub
End Class| Modifier | Where the member is reachable |
|---|---|
Public |
Everywhere (default) |
Protected |
Inside the declaring class and any derived class |
Private |
Only inside the declaring class |
Visibility is enforced at compile time.
Class Shape
Overridable Function Describe$() As String
Describe$ = "a shape"
End Function
End Class
Class Circle
Inherits Shape
Public radius As Double
Overrides Function Describe$() As String
Describe$ = MyBase.Describe$() + " (radius " + Str$(Me.radius) + ")"
End Function
End ClassA call through a base-class reference dispatches dynamically to the most-derived
Overrides implementation (virtual dispatch); MyBase.Member(...) is the way to reach the
base version explicitly.
Rules: Overrides must match the base Overridable method's full
signature (Sub vs Function, return type, parameter count, parameter
types, ByRef/ByVal); MyBase.Member(...) is allowed only inside an
instance method and dispatches explicitly to the immediate base class.
If a Function named main is defined in the program, the interpreter calls it as the
entry point instead of executing from the first statement. The function must return an
Integer (used as the process exit code). Three signatures are supported:
' No arguments
Function main() As Integer
Print "Hello from main"
main = 0
End Function
' Argument count only
Function main(argc As Integer) As Integer
Print "argc ="; argc
main = 0
End Function
' Full argc / argv
Function main(argc As Integer, argv() As String) As Integer
Dim i% As Integer
Print "Script: "; argv(0)
For i% = 1 To argc - 1
Print " arg "; i%; " = "; argv(i%)
Next i%
main = 0
End Functionargc equals 1 plus the number of extra command-line arguments. argv(0) is the script
filename; argv(1) through argv(argc-1) are the additional arguments supplied on the
command line after the script name:
nubasic -t -e myprog.bas hello world
' → argc = 3, argv(0)="myprog.bas", argv(1)="hello", argv(2)="world"When main is defined inside an Included file, the entry-point behaviour is suppressed
in that file — only the top-level program's main is used.
In Modern syntax mode (Syntax Modern), built-in functions are organised into named
modules and can be called with a qualified name (module::function). Legacy programs
continue to work with Syntax Legacy (the default).
Syntax Modern
' Qualified calls
Dim s As Double
s = math::sin(0.0)
Dim h$ As String
h$ = string::left$("Hello", 2) ' "He"
Dim n% As Integer
n% = runtime::sizeof(myArray)Using ModuleName imports all names from a module into the current scope so they can be
called without qualification:
Syntax Modern
Using math
Using string
Dim v As Double
v = Sin(0.785398) ' math::sin without prefix
Dim s$ As String
s$ = Left$("World", 3) ' string::left$ without prefixSyntax Legacy restores the classic single-namespace mode. The directive can appear
anywhere in a file; each Included file honours the mode active at its include site.
Syntax Legacy
' All classic global names work as before
Print Len("abc") ' 3
Print Sin(0) ' 0Struct Vector2D
x As Double
y As Double
End Struct
Struct Sprite
pos As Vector2D
width% As Integer
height% As Integer
name$ As String
End Struct
Dim hero As Sprite
hero.pos.x = 100.0
hero.pos.y = 200.0
hero.width% = 32
hero.height% = 48
hero.name$ = "Hero"
Print "Sprite "; hero.name$; " at ("; hero.pos.x; ", "; hero.pos.y; ")"Arrays of structures:
Dim enemies(10) As Sprite
enemies(0).name$ = "Goblin"
enemies(0).pos.x = 50The interpreter pre-registers two struct types that are available without any Struct
definition in your program:
DateTime — returned by GetDateTime(), holds all date/time fields:
| Field | Type | Description |
|---|---|---|
year |
Integer | Full year (e.g. 2026) |
month |
Integer | Month 1–12 |
day |
Integer | Day of month 1–31 |
hour |
Integer | Hour 0–23 |
minute |
Integer | Minute 0–59 |
second |
Integer | Second 0–59 |
wday |
Integer | Day of week: 0=Sunday … 6=Saturday |
yday |
Integer | Day of year 0–365 |
Dim dt As DateTime
dt = GetDateTime()
Print dt.year; "/"; dt.month; "/"; dt.day; " "; dt.hour; ":"; dt.minuteMouse — returned by GetMouse(), holds all pointer state (full build only):
| Field | Type | Description |
|---|---|---|
x |
Integer | Cursor X in pixels from left edge |
y |
Integer | Cursor Y in pixels from top edge |
btn |
Integer | Button mask: 0=none, 1=left, 2=middle, 4=right |
Dim m As Mouse
m = GetMouse()
If m.btn = 1 Then Print "Left click at "; m.x; ", "; m.yDim scores%(9) ' 10 integers, indices 0..9
Dim names$(4) ' 5 strings, indices 0..4
Dim data(99) ' 100 doubles, indices 0..99Access and assignment:
scores%(0) = 95
scores%(1) = 87
total% = 0
For i% = 0 To 9
total% = total% + scores%(i%)
Next i%
Print "Average: "; total% / 10ReDim resizes an existing array (clears content):
size% = 100
ReDim scores%(size% - 1)Byte arrays for binary data:
Dim buf@(1023)
buf@(0) = 65
Print Chr$(buf@(0)) ' AMulti-dimensional data (manual row-major indexing):
Const W% = 10
Dim grid%(W% * W% - 1)
grid%(2 * W% + 3) = 42 ' element at row=2, col=3' Insert or update entries
HSet "config", "width", 800
HSet "config", "height", 600
HSet "config", "title$", "My Game"
HSet "config", "fullscreen#", False
' Retrieve values
w% = HGet%("config", "width")
t$ = HGet$("config", "title$")
Print t$; " — "; w%
' Check whether a key exists
If HChk("config", "fullscreen#") Then
fs# = HGet#("config", "fullscreen#")
End If
' Count entries
Print "Config entries: "; HCnt("config")
' Delete a single key
HDel "config", "fullscreen#"
' Delete the entire table
HDel "config"' Write
Open "notes.txt" For Output As #1
Print# 1, "First line"
Print# 1, "Second line"
Close #1
' Read line by line
Open "notes.txt" For Input As #2
While Not(EOF(2))
Input# 2, line$
Print line$
Wend
Close #2
' Append
Open "notes.txt" For Append As #1
Print# 1, "New entry at " + SysTime$()
Close #1' Write raw bytes
FOpen "data.bin", "wb", 1
Dim buf@(3)
buf@(0) = &hDE : buf@(1) = &hAD : buf@(2) = &hBE : buf@(3) = &hEF
Print# 1, buf@
Close #1
' Seek and read
FOpen "data.bin", "rb", 2
Seek 2, 2, 2
Read# 2, b@, 1
Print "Byte at offset 2: "; Hex$(b@)
Close #2Diagnostic functions:
pos% = FTell(1) ' current byte offset
size% = FSize(1) ' total file size in bytes
err% = FError(1) ' non-zero if error occurred
at_end% = EOF(1) ' 1 if at end of fileMkDir("saves")
RmDir("saves/old")
Erase("temp.txt")
Print Pwd$()
ChDir ".."' Embed a color palette
Data "red", &hFF0000
Data "green", &h00FF00
Data "blue", &h0000FF
Data "yellow", &hFFFF00
Data "white", &hFFFFFF
' Read sequentially
For i% = 0 To 4
Read name$, color%
FillRect i%*60, 10, i%*60+50, 60, color%
TextOut i%*60+5, 70, name$, &hFFFFFF
Next i%
' Rewind to start
Restore
Read first_name$, first_color%
' Jump to specific position (0-based)
Restore 2
Read name$, color%
' Clear the data store
Restore -1s$ = "Hello, World!"
Print Len(s$) ' 13
Print Left$(s$, 5) ' "Hello"
Print Right$(s$, 6) ' "World!"
Print Mid$(s$, 8, 5) ' "World" (1-based)
Print SubStr$(s$, 7, 5) ' "World" (0-based)Print InStr("Hello World", "world") ' 7 (case-insensitive)
Print InStr("Hello World", "xyz") ' -1 (not found)
Print InStrCS("Hello World", "World") ' 7 (case-sensitive)
Print InStrCS("Hello World", "world") ' -1board$ = ".........."
board$ = PStr$(board$, 3, "*") ' "..*......."
board$ = PStr$(board$, 7, "F") ' "..*.....F."Print UCase$("hello") ' "HELLO"
Print LCase$("WORLD") ' "world"
Print Asc("A") ' 65
Print Chr$(65) ' "A"
Print Spc(4) ' " "n% = Val%("42")
x = Val("3.14")
Print Str$(3.14) ' "3.14"
Print Hex$(255) ' "FF"
Print StrP$(3.14159, 4) ' "3.142"Standard escape sequences:
Print "Column1\tColumn2\tColumn3"
Print "Line 1\nLine 2"Unicode characters with $u prefix:
Print $u, "Caf\u00e9 — \u00e0 \u00e8 \u00ec" ' Café — à è ì
Print $u, "\u03b1 \u03b2 \u03b3" ' α β γ (Greek)
Print $u, "\u4e2d\u6587" ' 中文x = 5
expr$ = "x * x + 2 * x + 1"
Print Eval(expr$) ' 36On Windows, Linux, and macOS nuBASIC can declare and call exported
functions from native shared libraries. Loading uses LoadLibraryW on
Windows and dlopen(RTLD_LAZY|RTLD_LOCAL) on Linux/macOS; invocation is
backed by libffi on every platform.
Syntax Modern
' Windows
Declare Function GetCurrentProcessId Lib "kernel32.dll" () As DWORD
Print GetCurrentProcessId()Syntax Modern
' Linux (glibc)
Declare Function strlen Lib "libc.so.6" (text As String) As Integer
Print strlen("hello") ' prints 5Syntax Modern
' macOS
Declare Function strlen Lib "libSystem.B.dylib" (text As String) As Integer
Print strlen("hello") ' prints 5The declaration form is:
Declare Function name Lib "library" _
[Alias "export"] _
[CallConv "default" | "cdecl" | "stdcall"] _
(param As NativeType, ...) As NativeTypeSupported native types: Integer, DWORD, Long64, ULong64, Double,
Bool, Pointer, String, and Void. String maps to a narrow
const char*; use Pointer for mutable buffers and manually laid-out
structures, together with the runtime module helpers (NativeAlloc,
NativeFree, NativePoke*, NativePeekStr$).
Native calls are enabled by default on trusted local hosts and can be
disabled with --disable-native-calls. See the full guide in
docs/native-dll-calls.md
and the worked example
examples/native_open_file_dialog.bas.
← Getting Started | Next: Graphics and Multimedia