A dynamic, pure object-oriented language focused on simplicity and fluency.

Tick feels like a natural conversation between objects. It combines the pure message passing of Smalltalk-80 with the command-token clarity of Tcl.

Every statement is a receiver, a keyword, or an argument—with zero decorative prepositions and zero punctuation noise. Featuring Ruby-style fluent pipelines (|), comma cascades (,), stackless Protothreads coroutines, and native FFI (@).

Try Tick Live in WebAssembly

Compile and run Tick code directly in your browser with zero installation.

Source Code Language: Tick
Terminal Output
Initializing Tick WebAssembly runtime...

Why Developers will Love Tick

Designed as an embeddable, featherweight scripting language for rapid prototyping.

💎

Pure Object-Oriented Messaging

Everything is an object, from integers and booleans to block closures. Objects communicate strictly via unary, binary, or keyword messages without primitive exceptions.

⚡

Zero-Filler Syntax

No semicolons, no trailing periods, no parenthesis soup. Newlines terminate statements, and inline expressions nest naturally using Tcl-style brackets [...].

🌊

Fluent Pipelines & Cascades

Chain outputs seamlessly with the pipe (|) like modern Ruby or Elixir, and send sequential messages to the same receiver with comma cascades (,).

🧵

Stackless Protothreads

First-class cooperative coroutines with two-way value exchange. Implemented via Adam Dunkels' stackless protothreads in C and Goroutine channels in Go.

🔌

Foreign Function Interface (FFI)

Variables and functions with the @ sigil directly invoke host C functions, system calls, and dynamic DLLs without writing glue code.

🌐

Two Implementations & WASM

Complete, independent reference implementations in C99 and Golang with identical semantics, plus a WebAssembly build for in-browser execution.

Pure Object-Oriented Principles

Rooted in the timeless object messaging philosophy of Alan Kay and Smalltalk-80.

💎

1. Everything is an Object

There are zero unboxed primitive types. Numbers, strings, booleans, code blocks ({ ... }), and classes themselves are first-class objects inheriting from Object. Arithmetic and conditionals are message sends!

🏛️

2. Classes & Dynamic Subclassing

Classes are first-class runtime objects (instances of Metaclass). Create classes and subclasses dynamically using Superclass subclass Name vars { ivar1 ivar2 }.

🔒

3. Encapsulation & Clean Assignment

Instance variables are private to each instance and protected from external access. All state mutation uses the clean keyword set (e.g. set balance [balance + amount]). All external interactions are mediated through messages.

🎭

4. Polymorphism & Dynamic Dispatch

Method resolution is late-bound at runtime. Diverse classes can implement common selectors (e.g. speak, area), and the runtime dispatches to the correct receiver implementation.

🔄

5. Implicit Self & Comma Cascades

Every method implicitly returns self if not terminated by return, enabling natural Smalltalk cascading where multiple messages are chained on one receiver with commas (,).

🧬

6. Open Classes (Metaprogramming)

Any class—including core built-ins like integer, string, or Array—can be reopened and extended with custom methods at runtime.

oop_architecture.tick Smalltalk-80 Semantics
# 1. Base Class with Instance Variables
Object subclass Animal vars { name sound }

Animal method init nameVal sound soundVal {
    set name nameVal
    set sound soundVal
}

Animal method getName { return name }
Animal method speak {
    "$name says: $sound" println
}

# 2. Subclassing & Method Overriding (Inheritance)
Animal subclass Dog vars { breed }

Dog method initDog nameVal breed breedVal {
    set name nameVal
    set sound "Woof!"
    set breed breedVal
}

Dog method speak {
    "$name the $breed barks: $sound" println
}

# 3. Cascading Instantiation & Polymorphism
set dog [Dog new , initDog "Rover" breed "Collie"]
dog speak    # => Rover the Collie barks: Woof!

# 4. Open Classes (Extend built-ins)
integer method square {
    return [self * self]
}
"5 squared = [5 square]" println  # => 25

Smalltalk vs. Tick

Familiar Smalltalk semantics with a streamlined, modern command-token grammar.

Feature Standard Smalltalk Tick
Assignment total := 0. set total 0
Unary Message server start. server start
Keyword Message canvas draw: shape at: origin. canvas draw shape at origin
Sub-expression x := a + (b factorial). set x [a + [b factorial]]
Zero-Arg Block [ self alert ] { self alert }
Parameterized Block [ :x :y | x + y ] { x y | x + y }
Fluent Pipeline ((items select: [:x | x valid]) collect: [:x | x name]) sorted. items select { x | x valid } | collect { x | x name } | sorted
Message Cascade pen up; color: "blue"; down. pen up, color "blue", down
Class Definition Object subclass: #Dog instanceVariableNames: 'breed' Object subclass Dog vars { breed }
Method Definition Dog >> speak [ ^ 'Woof!' ] Dog method speak { return "Woof!" }
Implicit Self Return deposit: amt [ balance := balance + amt. ^self ] Account method deposit amt { set balance [balance + amt] }