A modern language with familiar syntax

ObjoBasic is a statically typed, object-oriented language that reads like English. Everything is an object, types are checked at compile time, and there is no boilerplate to wade through. If you have ever written any BASIC, you will feel right at home.

Clean, Readable Syntax

No semicolons, no curly braces. ObjoBasic reads naturally - declare variables, branch, loop and call methods with plain English keywords. The IDE handles class and method scaffolding for you, so all you write is the logic.

objo
Var greeting As String = "Hello, " + player.Name
Var lives As Integer = 3

If lives > 0 Then
    StatusLabel.Text = greeting
    StartGame()
Else
    StatusLabel.Text = "Game Over"
End If

For i As Integer = 1 To 10
    SpawnEnemy(i * 50, 100)
Next i

Everything Is an Object

Integers, doubles, strings, booleans - every value in ObjoBasic is a full object. Call methods directly on literals, chain operations naturally, and never worry about the distinction between primitives and objects.

objo
# Method calls on literals.
Var upper As String = "hello world".Uppercase()
Var hex As String = 255.ToHex()
Var abs As Integer = (-42).Abs()

# Chaining.
Var result As String = "  hello  ".Trim().Uppercase()
# result = "HELLO"

# Even numbers have useful methods.
Print(7.IsOdd())         # True
Print(100.Clamp(0, 50))  # 50
Print(2.Pow(10))         # 1024

Static Typing Without the Pain

ObjoBasic catches type errors at compile time, not at runtime. Value types like Integer and String can never be Nothing, eliminating an entire category of null-related bugs.

objo
# Explicit types catch errors early.
Var name As String = "Alice"
Var age As Integer = 30
Var scores() As Double = [98.5, 87.3, 92.0]

# Value types are never Nothing.
Var count As Integer   # Defaults to 0, not Nothing
Var label As String    # Defaults to "", not Nothing

# Type checking at runtime.
If animal IsA Dog Then
    Var dog As Dog = Dog(animal)
    Print(dog.Breed)
End If

Powerful Collections

Arrays and dictionaries are first-class citizens with literal syntax. Create them inline, access elements by index or key, and iterate with For Each. Dictionaries support any hashable key type.

objo
# Array literals.
Var names() As String = ["Alice", "Bob", "Charlie"]
names.Append("Diana")
names.Sort()

# Dictionary literals.
Var ages As Dictionary(Of String, Integer) = { _
    "Alice": 30, "Bob": 25, "Charlie": 35}

# Iterate with For Each.
For Each name As String In names
    If ages.HasKey(name) Then
        Print(name + " is " + ages.Value(name).ToString())
    End If
Next name

Functional Collections

Arrays ship with useful methods like Map(), Where() and Reduce(). Pass inline functions to transform and filter collections in a single expression. Closures capture their surrounding scope automatically.

objo
Var numbers() As Integer = [1, 2, 3, 4, 5]

# Filter.
Var evens() As Integer = numbers.Where(Function(n) n Mod 2 = 0)
# evens = [2, 4]

# Transform.
Var doubled() As Integer = numbers.Map(Function(n) n * 2)
# doubled = [2, 4, 6, 8, 10]

# Accumulate.
Var sum As Integer = numbers.Reduce(0, Function(acc, n) acc + n)
# sum = 15

# Check conditions.
Print(numbers.All(Function(n) n > 0))  # True
Print(numbers.Any(Function(n) n > 4))  # True

Rich String Handling

Strings are immutable, Unicode-aware objects packed with useful methods. String interpolation lets you embed expressions directly.

objo
Var name As String = "Garry"
Var age As Integer = 40

# String interpolation.
Var bio As String = $"My name is {name}, age {age}."

# Useful built-in methods.
Print("hello world".Capitalise())       # "Hello world"
Print("foo:bar:baz".Split(":").Count)    # 3
Print("  padded  ".Trim())               # "padded"
Print("abcdef".Substring(2, 3))          # "cde"
Print("banana".Replace("na", "🎉"))

# Case-insensitive by default.
Print("Hello" = "hello")                 # True

Structured Error Handling

Catch errors precisely with Try/Catch/Finally. Match on specific exception types or catch broadly - your choice. The Finally block always runs, making cleanup reliable.

objo
Try
    Var data As String = LoadFile(path)
    Process(data)
Catch e As FileNotFoundException
    Print("Missing: " + e.Message)
Catch e As Exception
    Print("Error: " + e.Message)
    Throw e  # Re-throw if needed.
Finally
    Cleanup()
End Try

Events Made Simple

Subscribe to events on any control or object with AddHandler. The IDE creates event stubs for you - just fill in the logic. Multiple handlers can respond to the same event, and you can add or remove them at any time.

objo
# Wire up a button press.
AddHandler btn.Pressed, AddressOf HandlePress
AddHandler btn.Pressed, AddressOf LogPress

# Respond to value changes.
AddHandler slider.ValueChanged, AddressOf OnSliderChanged

# Remove a handler when done.
RemoveHandler btn.Pressed, AddressOf LogPress

# Raise custom events.
RaiseEvent DataLoaded(records.Count)

Async/Await

Write asynchronous code that reads like synchronous code. Await long-running operations and the language handles the rest. Errors propagate naturally through Await, so Try/Catch works exactly as expected.

objo
# Fetch data without blocking the UI.
Var response As HTTPResponse = Await conn.SendAsync( _
    "GET", "/api/users")
Var users As String = response.Content
UserList.DataSource = ParseJSON(users)

# Run multiple requests concurrently.
Var tasks() As Task(Of String)
For Each url As String In urls
    tasks.Add(conn.FetchAsync(url))
Next url

Var results() As String = Await Task.WhenAll(tasks)

Expressive Control Flow

For/Next with Step, For Each over any collection, While/Wend, Do/Loop with Until or While, and Select Case with multi-value and range matching. Exit and Continue work in every loop type.

objo
# Select Case with multiple matches.
Select Case httpStatus
Case 200
    HandleSuccess(response)
Case 301, 302
    FollowRedirect(response)
Case Is >= 400
    ShowError(response)
End Select

# Loop with early exit.
For Each file As String In files
    If file.EndsWith(".tmp") Then Continue
    If file.IsBlank() Then Exit
    ProcessFile(file)
Next file

Explore the full language reference

Everything you need to know about ObjoBasic — types, classes, generics, error handling, the standard library and more.

Read the full language reference