Repository navigation
Feature Index
Paul Squires edited this page Nov 9, 2026
·
30 revisions
Every language feature and library that ships with tiko, one row each, with the page that documents it. Compatibility lists the known compatibility differences.
| Feature | What it is |
|---|---|
| Properties |
Auto-properties, Declare Property Age As Long = 18 Get, Private Set: a hidden field and both accessors written by the compiler, with Get, Init for a value only the constructor sets. Property blocks hold Get and Set in one definition, with value as the value crossing the boundary. Any number of indices, Static properties, properties in a namespace, += and Swap on a property, and a property passed ByRef is written back through its setter. |
| Generics |
type Box( of T ) and function Max( of T )( … ). One concrete type per distinct type-argument list, type-checked like any other type. Not a macro, not a separate template language. |
| Interfaces |
interface IShape … end interface, class Circle with implements IShape lines. A contract any type or class can take on, as many as it needs, with each method mapped explicitly; an interface value is a 16-byte reference, and a plain type needs no vtable to implement one. Generic interfaces, and constraints: function Largest( of T as IComparable( of T ) ). |
| Iterator Protocol | A structural contract: a type is iterable if it has GetIterator( ) returning something with IsValid( ), Value( ) and MoveNext( ). No base class, no interface, no registration, nothing to inherit. |
| For Each | Walks arrays (any lbound), var-len STRING, and any type satisfying the protocol. |
| Tuples |
as (int32, ustring) — an anonymous aggregate identified structurally, so (int32, ustring) is one type in every module. Gives tiko multiple return: function MinMax( ) as (min as int32, max as int32), then var (lo, hi) = MinMax( ). |
| Array Results |
function foo( ) as integer( ) returns a classic dynamic array, not a container: return { 10, 20, 30 }, a local array (moved out) or another call, then var i = foo( ) and i( 1 ). The caller owns it; nothing is copied or leaked. |
| Collection Initializers |
dim b as containers.Array( of integer ) = { 10, 20, 30 }: a brace list on a type that needs construction calls its Add, PushBack or Push once per element, after the constructor. { {"a", 1}, {"b", 2} } fills a Map. Works for any type with one of those methods, not only the containers. |
| Defer |
defer <statement> runs on the way out of the enclosing scope, in reverse order, on every path — fallthrough, exit, return, goto out of nested scopes — and every iteration of a loop body. A contextual keyword: existing code using defer as a name keeps working. |
| Lambdas |
function( byval x as int32 ) as int32 … end function in expression position. Non-capturing ones are plain procedure pointers, so every existing callback API — including C ones like qsort — works unchanged. Capturing ones build a stack closure; every capture states byval or byref explicitly. |
| Block Strings |
""" ending its line opens a multi-line string literal; the closing line's indentation is removed from every line, so the text indents with the code around it. " needs no escaping, line breaks are always LF, and !""" reads escapes. |
| Partial Types |
partial type and partial class write one type in several blocks, usually two files of one module, so a tool's generated half and a person's half never edit each other's text. |
| String Slices |
s[lo to hi] names part of a string without copying it: uslice, slice and wslice view a ustring, a string or a wstring in place, print and compare like text, and become an owned string only when assigned to one. The compiler tracks where each slice came from: a slice cannot outlive its text, be stored where it could, or be read after its string grew — and -exx checks what crosses a procedure. std/strings adds Find, TrimSpace and SplitSlices over slices. |
| Embed |
#embed NAME "file" puts a file's bytes inside the program at compile time, as a read-only ubyte array with a NUL after the last byte. The path is searched like an #include; the file is a build dependency; public #embed exports it from a module. |
| Typed Variadics |
sub Log( items() as const ustring ... ) takes any number of arguments, each converted to the element type -- through its constructors too -- and packed into an array the procedure reads like any array parameter. A whole array of that type passes as the list, with no copy. A call that matches without packing always wins, so adding one never changes an existing call. |
| UString | A dynamic Unicode string that is UTF-16 on every target, unlike WSTRING (2 bytes on Windows, 4 on Linux and macOS, 1 on DOS). A true intrinsic type in the compiler, not a library — LEN is O(1) and every string intrinsic works. const G as ustring = "hé" declares a ustring constant, read as a ustring everywhere: len( G ) is 2. |
| Fixed-Width Types |
int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32 and float64: names that say their width, for byte through double. Typedefs, not new types, and not keywords — a program's own declaration of one of the names wins. |
| Nullptr |
nullptr, a null pointer that is a pointer: an any ptr constant, so an overload, var and a generic see a pointer where 0 gives them an integer. A predeclared constant, not a keyword — a program's own nullptr wins — and 0 still works. |
| Goroutines and Channels |
spawn Worker( a, b ) runs a procedure concurrently with its arguments copied at the spawn point. Channel( of T ) is a typed queue — rendezvous or buffered, with a close protocol and for each v in ch. select channel waits on several at once; WaitGroup joins a fan-out; Context cancels one. Start with the tutorial. |
| Library | What it is |
|---|---|
| Array |
Array( of T ) — one implementation, fully type-checked per instantiation. Push is amortised O(1); capacity doubles instead of reallocating on every append. |
| Map / Set / LinkedList | Hash map, hash set and a doubly-linked list in the std/containers module, written in ordinary tiko-lang with zero compiler support. |
| OrderedMap and OrderedSet |
OrderedMap and OrderedSet are red-black trees: O(log n), always in ascending key order, with TryFirst/TryLast/TryFloor/TryCeiling. They need only < on the key — no hash and no =. Iterators survive insertion. |
| Sorting |
Sort( a ) is an introsort — O(n log n) worst case, in place. StableSort( a ) is a bottom-up merge sort. SortList( l ) relinks nodes and moves no element. Every move is a SWAP, so sorting an Array( of string ) performs zero string copies. |
| Searching |
BinarySearch, LowerBound, UpperBound and PartitionPoint on a sorted array; PartialSort, NthElement, NextPermutation, RotateArray, ReverseArray and Dedup in place. Each has a ...By form taking a comparer. |
| PriorityQueue / Deque / BitSet | A binary-heap priority queue (smallest first, or any order with a comparer), a ring-buffer double-ended queue with O(1) indexing, and a growable set of bit indices with set algebra. |
| Optional / Result |
Optional( of T ) for a value that might not be there, Result( of T, E ) for a value or the reason there isn't one. Zero is a value; a default-constructed Result is a failure, so a forgotten assignment cannot read as success. |
| SharedPtr and WeakPtr | Shared ownership by reference count, destroyed exactly once when the last handle goes. WeakPtr observes without keeping alive. Counts are atomic under -mt. Derived→base is the explicit SpCast, and the base needs a virtual destructor. |
| String Library | 37 algorithms — Replace, Split, Join, Between, the pad family, the character-set family — in the std/strings module, working on all four string types from one call. Nothing becomes a keyword.
|
| Format |
strings.Format( "{:>8} {:.2f}", name, price ): C++20 std::format's format strings and spec language -- fill, alignment, width, sign, precision, binary/octal/hex, every float form, the shortest round-trip double. A literal format string is checked at compile time against the values' types, with the caret on the character at fault. TryFormat for templates that are data; your own types by a text cast or Formattable. |
| Chrono Date and Time |
DateTime, LocalDate, LocalTime, Instant, TimeSpan, WallClock, Stopwatch, CpuClock, TimeZoneInfo — immutable value types over int64 ticks of 100 ns. ISO 8601 / RFC 3339, OS-native offsets and DST, a monotonic clock. Arithmetic never wraps. Ships alongside datetime.bi. |
| Codec | Base64 (standard and URL-safe), base32, hex and percent-encoding, with strict decoding that reports the position of the first bad character; fixed-width numbers in either byte order and LEB128 varints in a byte buffer. |
| Hash | CRC-32, CRC-32C, Adler-32, FNV-1a, xxHash64, MD5, SHA-1 and the SHA-2 family behind one Hasher interface: one call, or streaming in pieces; DigestFile; Hmac( of H ) over any cryptographic hasher; ConstantTimeEquals for comparing MACs. |
| OS |
os.Args( ) in Unicode, GetEnv that tells unset from empty, SetEnv/UnsetEnv/Environment/ExpandEnv, host facts (CpuCount honours affinity and containers), ExitWith/Abort, and Ctrl-C / SIGTERM as a flag you poll or wait on -- plus tasks.InterruptContext( ), a Context cancelled by the first interrupt. |
| Process |
process.Command( "git" ).Arg( "status" ) -- an argument vector, never a shell unless you ask for Shell. Run, Capture (stdout and stderr read together, so 1 MiB on both cannot deadlock), or a Child whose stdin/stdout/stderr are fs.Stream pipes; Wait, WaitTimeout, TryWait, Kill, Terminate. PATH lookup never in the current directory, .bat/.cmd arguments cmd.exe would expand are refused, and only the three stdio handles reach the child. |
| Net |
net.ParseIp, net.Resolve, TcpStream (an fs.Stream: Connect/ConnectHost with timeouts, then WriteUtf8, ReadExact), TcpListener (Bind, Accept with a timeout), UdpSocket (SendTo/ReceiveFrom, truncation reported). ParseUrl (RFC 3986), Url.Resolve for relative links, QueryValues. Strict address parsing: a leading zero in an IPv4 part is refused. Blocking calls with timeouts on both systems. |
| HTTP and TLS |
http.Fetch, http.Post, Client (Fetch/Head/Post/Send, connection reuse, redirects, TimeoutMs, MaxBodyBytes), Request (SetBody, SetBasicAuth), Response (StatusCode, Header, Text( )), Client.Open for a body read as a stream. std/tls: TlsStream (ConnectHost, Connect, Accept) over any connected stream, TlsConfig (extra roots, InsecureSkipVerify, a server identity from PEM). The system's TLS on Windows, OpenSSL 3 loaded at run time on Linux and macOS. |
| Config |
config.ParseToml / LoadToml into a TomlValue tree that keeps key order -- TOML 1.1 read, valid 1.0 written back with ToTomlText, every table rule enforced, errors with line and column -- and IniFile for INI: sections, key = value or key: value, case-insensitive names, duplicates replaced or refused. CSV writing (JoinCsvRow, CsvWriter) is in std/strings. |
| UUID |
uuids.NewV4( ) (random) and uuids.NewV7( ) (time-ordered, strictly increasing within a program); parse every common spelling; usable as a Map key and sortable. |
| Filesystem Library | Path algebra, FileInfo, a reentrant directory iterator that works with FOR EACH, a recursive walk, whole-file I/O, mkdir -p / rm -rf / tree copy, glob, atomic replace, temp files, symlinks, volumes, file watching, memory mapping and locking. Every fallible call returns Result( of T, FsError ). Ships alongside Dir/Kill. |
| Math Library | The std/numeric module: constants, rounding and classification, integer arithmetic and bits, parsing that can fail and formatting that round-trips, seeded random streams, statistics, Vec/Mat/Quat/Complex, and floating-point environment control. |
| Finance | Money, and what you do with it. The two money types first, because a DOUBLE is the wrong place to keep an amount and 0.1 + 0.2 <> 0.3 says so: Currency is a LONGINT scaled by 10,000 -- eight bytes, four places, exact, the VB6 / COM CY / SQL Server money shape -- and Decimal is the .NET System.Decimal, a 96-bit mantissa with a per-value scale of 0..28. Both round half-to-even and report overflow as an infectious Invalid. Then the finance functions: interest and rate conventions with day count, the time value of money, loans and amortization schedules, cash-flow appraisal, depreciation, and portfolio returns and risk. Compounding frequency and payment frequency are separate parameters, so one code path serves both the US and Canadian mortgage conventions; growth over an integer number of periods is exact, solvers take a float64 kernel and say so; and an amortization schedule's final balance lands on exactly zero. |
| Logging | A structured logger: levels spaced by ten, typed fields, a zero-allocation disabled path, and an event that lives on the caller's stack so it is thread-safe without thread-local storage. |
Libraries the toolchain ships in vendor/, each reached with one #import and nothing on the command line. Vendor Packages explains link static and link dynamic and what is inside a package.
| Package | What it is |
|---|---|
| sqlite3 | SQLite, the embedded SQL database: #import "vendor/sqlite3", linked statically or dynamically. |
| SDL3 | SDL 3 for windows, input, audio and 2D rendering, with vendor/SDL3/image, vendor/SDL3/ttf and vendor/SDL3/mixer for images, fonts and mixing. |
| raylib6 | raylib, for games and graphics programs, with vendor/raylib6/raymath and vendor/raylib6/rlgl. |
| cJSON | cJSON, a small JSON parser and writer, with vendor/cJSON/utils for JSON Pointer, Patch and Merge Patch. |
| PsControls | Owner-drawn Win32 controls written in tiko and shipped as source, one module per control: text, numeric and date entry, buttons and switches, a list/tree, menus, toolbars, tabs, splitters, scroll bars, a message box, a colour picker, tooltips, a progress bar and a chart. Nothing underneath is a system control, so every colour is settable. PsApp runs a program of them in a dozen lines: forms with message callbacks, the message loop, a shared light/dark theme, background-thread hand-off and per-monitor DPI. Start with the tutorial. |
| tkControls | Owner-drawn controls on SDL3 for Windows, Linux and macOS, written in tiko and shipped as source: the PsControls set under tk names, plus a code editor, a file dialog and a font list. The fonts ship with them, so a program looks the same on every system. tkApp runs a program of them: forms with event callbacks, the event loop, a shared light/dark theme, background-thread hand-off and per-monitor scale. Start with the tutorial. |
| Feature | What it is |
|---|---|
| C Header Import | tiko implements it through libclang, on every target, with -cimport/-cimport-out. #cinclude once "sqlite3.h" uses a C library's own header in place of a hand-written binding: the header goes to Clang, and what comes back becomes FreeBASIC declarations for the target being built — structs, unions, enums, typedefs, variadics, function pointers with their real signatures, globals and object-like macros. It emits text and lets the compiler compute the layout itself, so the two answers can be compared; a disagreement is a compile-time error naming the record and the first differing member. libclang is loaded on first use via DyLibLoad, never linked. Pairs with #foreignlib — declarations and linkage — to ship a binding entirely inside your own tree. -cimport/-cimport-out generate a deterministic binding file you can check in and diff across an SDK upgrade. Start with the tutorial. |
| Foreign Library Linking |
#foreignlib SQLITE dynamic "vendor/sqlite3" binds a name to a library shipped inside your source tree, resolved relative to the declaring file rather than the working directory, with the target variant picked by filename convention (sqlite3_windows_x86_64.dll.a, sqlite3_linux_x86_64.so). static/dynamic is mandatory — a file of the other kind is an error listing every path tried, never a silent substitution. Declarations then say lib SQLITE instead of a string literal, so a cross-platform binding stops duplicating every Declare inside #ifdef. #inclib and #libpath are unchanged. Start with the tutorial. |
| Vendor Packages |
#import "vendor/sqlite3" link dynamic reaches a C library the toolchain ships, with nothing on the command line: its header -- translated once by tiko c2t -- comes across whole and unqualified, its library is linked statically or dynamically as the import asks, and a dynamic library is copied beside the program, with a $ORIGIN run path on Linux and an @loader_path one on macOS. vendor/ is the toolchain's alone, like std/. |
| LLVM Backend | tiko's only backend. It emits LLVM IR and runs clang -c, with its own ABI pass for Win64, SysV AMD64 and Apple's AAPCS64, and clang drives the link. It covers windows-x86_64, linux-x86_64 and macos-arm64, and there is no -gen switch. Needs clang 18 or newer: it is not bundled, and tiko takes TIKO_CLANG if set, then LLVM's usual install location, then PATH. Inline ASM is refused with TKO0407 rather than miscompiled. |
| tiko build |
tiko build, run, check, clean and metadata build a project from its tiko.toml: targets (exe, dll, lib), profiles (debug, release, your own) and paths relative to the manifest. Every main file is cached beside the modules, misses compile in parallel (-j), and a link with nothing new is skipped. --message-format json is a line-per-event stream and tiko metadata the resolved project, both versioned contracts for editors; task recipes for VS Code, Zed and Sublime. |
| TIKO_COMPILER | tiko's identity define, always 1. #ifdef __TIKO_COMPILER__ is how a source tree asks "is this tiko?". __TIKO_VERSION__ gives the version. |
These are the limits of the language and library today, each one measured. The headline ones:
-
Constraints name interfaces only.
of T as IComparable( of T )can be required; an operator such as=cannot. A member needing=onTmakes the whole type unusable for aTwithout one — which is whyIndexOf/Containsand everything instd/containers'sort.tikoare free procedures rather thanArraymembers. -
Generic procedures cannot be overloaded. One name, one generic procedure — which is why the sort library spells its variants
SortBy,StableSortandSortList. -
A capturing lambda cannot name the enclosing generic's
Tin its own parameter list. Non-capturing lambdas are unaffected, and so is a capturing lambda whose own parameters are concrete. -
typeof( T )does not see through a type parameter, so a generic body cannot branch on whatTis bound to. This is why the hash contract is an overloadedHashOf. - Tuple variables of different element types do not convert, and there are no ordering operators on tuples.
- No IANA tzdb in the date/time library — zones are OS-native only.
-
The filesystem library does not auto-prefix
\\?\, so on Windows a path over roughlyMAX_PATHis refused withFS_NAME_TOO_LONGrather than silently truncated.
The full list, with the reasoning and the measurements behind each one, is on the individual feature pages — start with Generics.
tiko-lang · Home · Feature Index · Keyword Index · License
FreeBASIC manual pages reproduced under the GNU FDL 1.3.
- Generics
- Interfaces
- For Each
- Iterators
- Tuples
- Array Results
- Defer
- Lambdas
- Block Strings
- Partial Types
- String Slices
- Embed
- Typed Variadics
- C Header Import
- Foreign Library Linking
- UString
- Fixed-Width Types
- Nullptr
- String Library
- Format
- Array
- Map
- Set
- LinkedList
- OrderedMap
- OrderedSet
- Sorting
- Optional
- Result
- Smart Pointers
- Date and Time (Chrono)
- Filesystem
- File Streams
- Config (INI and TOML)
- Codec
- Hash
- UUID
- OS
- Process
- Net
- HTTP and TLS
- Math Library
- Finance
- Logging
- Terminal TUI Library
- PsControls
- tkControls
- sys/win
- Goroutines and Channels
- LLVM Backend
- tiko build
- TIKO_COMPILER
- Variable Declarations
- Standard Data Types
- User Defined Types
- Procedures
- Operators
- Control Flow Statements
- Converting Data Types
- Array Functions
- String Functions
- Mathematical Functions
- Bit Manipulation
- Date and Time Functions
- File I/O Functions
- Console Functions
- User Input (Runtime Library)
- User Input Functions (Graphics Library)
- Screen Functions
- 2D Drawing Functions
- Graphics Library Reference
- Graphics Keyword List
- Memory Functions
- Threading Support Functions
- Error Handling Functions
- Operating System Functions
- Preprocessor
- Intrinsic Defines
- Miscellaneous Keywords
- Modularizing