Tinox
A compiled, object-oriented programming language with Java-like syntax, LLVM backend, integrated HTTP server, and complete IDE tooling – designed for high-performance backend services.
What is Tinox?
Tinox is an independently developed, statically typed programming language that compiles directly to native machine instructions. The language combines a Java-like, annotation-driven syntax with the performance advantages of an LLVM-based compiler and a runtime system written in C.
The main focus is on the simple development of high-performance
HTTP REST services: a controller handler requires only a few lines of code,
and the built-in HTTP server is based on epoll and
SO_REUSEPORT – technologies also used in production-ready
web servers such as Nginx.
import tinox.core.http_server;
import tinox.core.json;
class SortController
{
@POST
@Path("/sort")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
fn sort(ctx: HttpContext) -> Nothing
{
let root: JsonValue = Json.parse(ctx.request.body);
let numbers: List<Int64> = Json.intArrayFromJson(root.getField("numbers"));
ctx.response.body = Json.intArrayWrap("sorted", numbers.sort());
}
}
This code represents a fully functional REST endpoint – no framework configuration overhead, no XML files, no boilerplate.
Technical Fundamentals
LLVM as Compiler Backend
The Tinox compiler does not generate native machine instructions directly, but rather LLVM Intermediate Representation (LLVM IR) – a platform-independent, typed assembly language. The LLVM toolchain then handles the optimization and translation to machine code.
LLVM is also used by Clang (C/C++), Rust, Swift, Julia, and Kotlin Native – it is one of the most mature compiler backends in the industry.
Rust as Implementation Language
The entire compiler – lexer, parser, type checker, code generator, and LSP server – is implemented in Rust. This brings the following advantages:
- Safety No undefined behavior, no memory errors in the compiler itself
- Performance Fast compile times of the compiler (no GC pauses)
- Concurrency Thread-safe data structures (DashMap) for the LSP server
C as Runtime System
The runtime system (runtime.c) is written in C and provides all
operating system-level functions: memory management, strings, arrays,
maps, file I/O, networking, and the HTTP server. C functions are called directly from
LLVM IR – no ABI overhead through wrapper layers.
Key Concepts
Static Typing
All types are checked at compile time. No runtime type errors possible.
AOT Compilation
Ahead-of-Time: the source code is fully compiled to a native binary before execution. No interpreter, no JIT.
Boehm GC
Tinox uses the Boehm Garbage Collector – a conservative, thread-safe GC. Memory is freed automatically; the developer does not need to manage anything manually.
1:1 Threading
Every spawn call creates a real OS thread (pthread).
Full parallelism on multiple CPU cores.
Components Overview
Tinox consists of several Rust crates (libraries) that together form the compiler and tooling, plus the C runtime system and the standard library written in Tinox itself.
| Component | Language | Purpose | Size |
|---|---|---|---|
tinox-common | Rust | Shared data types (Span, Error, AST nodes) | ~250 lines |
tinox-lexer | Rust | Tokenization (Lexer) | ~800 lines |
tinox-parser | Rust | AST construction + code formatter | ~2,500 lines |
tinox-typecheck | Rust | Type checking + annotation processing | ~2,000 lines |
tinox-codegen | Rust | AST → LLVM IR | ~6,000 lines |
tinox (CLI) | Rust | Compiler control, REPL, project manager | ~1,700 lines |
tinox-lsp | Rust | Language Server Protocol Server | ~1,000 lines |
tinox-eclipse | Java | Eclipse IDE Plugin | ~400 lines |
runtime.c | C | Runtime system: I/O, HTTP, memory, strings | ~1,700 lines |
tinox-core | Tinox | Standard library (55+ modules) | ~200 KB |
Compiler Pipeline
The Tinox compiler transforms a .tnx source file in several
steps into an executable native binary:
Lexer (tinox-lexer)
Reads the UTF-8 source text and breaks it into tokens (smallest
meaningful units): keywords, identifiers, literals,
operators, brackets. Each token carries precise position information
(line, column, byte offset) for later error messages.
Supports string interpolation ("Hello ${name}!").
Parser (tinox-parser)
Converts the token sequence into an Abstract Syntax Tree (AST) – a tree structure representing the syntactic structure of the program. Recursive descent parser: every grammar rule corresponds to a function. Recognizes classes, methods, expressions, loops, match expressions, etc.
Import Resolution (tinox CLI)
import declarations are resolved recursively: the imported
.tnx files (from the standard library or the project directory)
are loaded, parsed, and embedded into the AST. The result is a
single, consolidated AST with all required declarations.
Type Checker (tinox-typecheck)
Two-pass approach: first all declarations (classes, methods, functions) are registered, then expressions and statements are checked for type correctness. Also validates annotations (@GET, @POST, @Produces etc.), extracts REST routes, and recognizes DI components.
Code Generator (tinox-codegen)
Traverses the AST directly and generates LLVM IR as text. Generates vtable structures for interface dispatch, monomorphizes generic functions/classes, allocates closure environments, generates HTTP route handlers. No intermediate step – directly AST → IR.
llc (LLVM Compiler)
The external LLVM tool llc translates LLVM IR into
assembler. In release mode with -O3, extensive
optimizations (inlining, loop optimizations, vectorization) are performed.
Clang (C Compiler / Linker)
clang compiles runtime.c into an object file
and links it with the generated assembler into a finished
native binary. This also links -lm (math library).
Runtime (C Runtime System)
The core of the Tinox runtime system is runtime/runtime.c
(~1,700 lines of C code). It provides all primitives that the generated
LLVM IR accesses directly.
Memory Management
Tinox uses the Boehm Garbage Collector (libgc) for automatic
memory management. The GC is conservative: it scans the stack and registers for
pointers and frees objects that are no longer reachable – without the developer
having to call free() explicitly. With GC_THREADS it is
fully thread-safe and works correctly with the epoll-based
HTTP server thread pool.
For frequent operations (sort, JSON parsing), thread-local static buffers that are allocated once and then reused – this completely eliminates malloc overhead in the request-critical path.
Collections
| Type | Implementation | Special Feature |
|---|---|---|
| Array | Dynamic C array | Length stored at offset -1; grows on push |
| Map | Open-addressing hash table | FNV-1a hash, load factor 0.75, tombstones for delete |
| String | C string (char*) | Immutable; operations create new object |
Async & Concurrency
The concurrency model is based on POSIX threads (pthreads).
spawn creates a real OS thread. Channels internally use
a linked-list queue with mutex and condition variable.
HTTP Server (Low Level)
The HTTP server in the runtime uses:
- SO_REUSEPORT Multiple threads bind the same port – the kernel distributes connections
- epoll Event multiplexing: one thread manages up to 4,096 simultaneous connections
- TCP_NODELAY Nagle algorithm disabled – immediate sending of small packets
- Keep-Alive HTTP/1.1 keep-alive, idle timeout 500ms
Type System
Primitive Types
| Tinox Type | Bit | LLVM-IR | Description |
|---|---|---|---|
Int8 / Int16 / Int32 / Int64 | 8–64 | i8–i64 | Signed integers |
UInt8 / UInt16 / UInt32 / UInt64 | 8–64 | i8–i64 | Unsigned integers |
Float32 / Float64 | 32/64 | float/double | IEEE 754 floating-point numbers |
Bool | 1 | i1 | Boolean value |
Char | 32 | i32 | Unicode code point |
String | – | i8* | UTF-8 string (C string) |
Nothing | – | void | No return value (equivalent to void) |
Never | – | void | Function never returns (throw, exit) |
Composite Types
let numbers: List<Int64> = [1, 2, 3]; // Array
let ages: Map<String, Int32> = @{"Alice" => 30}; // Map/Dictionary
let pair: (Int32, String) = (42, "hello"); // Tuple
let name: String? = null; // Nullable
let fn add: fn(Int32, Int32) -> Int32 = |a, b| a + b; // Function type
Generics
Tinox supports parametric polymorphism via monomorphization: a separate function is generated for each concrete type – like C++ templates or Rust. There is no runtime overhead from type erasure (as in Java).
fn max<T>(a: T, b: T) -> T
{
if a > b { return a; }
return b;
}
class Box<T>
{
var value: T;
}
Object Orientation
Tinox is a hybrid language – object-oriented with classes, inheritance, and interfaces, but procedural free functions and functional concepts (lambdas, higher-order functions) are also possible.
Classes
class Animal
{
var name: String;
var age: Int32;
fn speak() -> String // instance method
{
return "...";
}
fnc create(name: String) -> Animal // static method (fnc)
{
return Animal { name: name, age: 0 };
}
}
class Dog extends Animal // inheritance
{
fn speak() -> String
{
return "Woof!";
}
}
Interfaces & Polymorphism
interface Serializable
{
fn serialize() -> String;
}
class User implements Serializable
{
var name: String;
fn serialize() -> String
{
return "User:" + this.name;
}
}
Interface dispatch is implemented via vtables – identical to C++ virtual functions. Every object that implements an interface receives a pointer to a table of function pointers.
Keyword Overview
| Keyword | Meaning |
|---|---|
fn | Instance method (has implicit this) |
fnc | Static method (no this, called via class name) |
let | Immutable local variable |
var | Mutable local variable or field |
class | Class declaration |
interface | Interface declaration (like Java interface) |
enum | Enumeration type |
extends | Single inheritance |
implements | Interface implementation |
spawn | Start a new thread |
await | Wait for thread result |
defer | Execute code when leaving the scope |
match | Pattern matching expression |
Annotations
The annotation system is one of the core strengths of Tinox. Annotations control the behavior of the compiler, the HTTP server, and future frameworks – similar to Java/Spring or Quarkus.
HTTP REST Annotations
Every parameter of a @GET/@POST/etc. handler needs
exactly one binding annotation: @PathParam/@QueryParam
bind by the parameter's own name to the same-named :name path
segment or query string key, @PostParam deserializes the whole
JSON request body, @HttpContext gives access to the request/
response. The return type decides the response mode:
HttpContext means manual mode (the method builds
ctx.response itself), any other type gets auto-serialized as JSON.
// Auto-serialize: the return value becomes the JSON response body
@GET
@Path("/users/:id")
@Produces(MediaType.APPLICATION_JSON)
@Auth("bearer")
fn getUser(@PathParam id: Int64) -> User { ... }
// Manual mode: dynamic status code (e.g. 404), @HttpContext + -> HttpContext
@GET
@Path("/users/:id")
fn getUserOrNotFound(@PathParam id: Int64, @HttpContext ctx: HttpContext) -> HttpContext
{
// ... ctx.response.status(404).json(...) or ctx.response.json(...)
return ctx;
}
Migrating from the old REST API
Before this version, every handler implicitly got exactly one unannotated
ctx: HttpContext parameter, return type Nothing, and
had to read path/query parameters and the request body manually via
ctx.request.getParam(...)/ctx.request.getQuery(...)/
Json::deserialize<T>(ctx.request.body). That shape no longer
compiles — there is no backward compatibility, every parameter now needs one
of the four binding annotations explicitly.
| Before | After |
|---|---|
fn getUser(ctx: HttpContext) -> Nothing |
fn getUser(@PathParam id: Int64) -> User |
fn createUser(ctx: HttpContext) -> Nothing |
fn createUser(@PostParam u: User) -> User |
A dynamic status code (e.g. the same route answering 200
sometimes and 404 other times) can't be expressed with a fixed return
type — manual mode stays available for that: @HttpContext ctx:
HttpContext as a parameter, -> HttpContext as the
return type, ending in return ctx;. |
|
Serialization
@JsonSerializable
class User
{
var id: Int64;
@JsonField("first_name") // Overrides the JSON key
var firstName: String;
@Sensitive // Output as "***" in logs
var password: String;
@DoNotSerialize // Excluded from JSON
var internalToken: String;
}
All Built-in Annotations
| Annotation | Target | Description |
|---|---|---|
@GET @POST @PUT @PATCH @DELETE | Method | HTTP verb for REST route |
@Path("...") | Class / Method | URL path (supports :param) |
@Produces(MediaType.*) | Method | Response content type |
@Consumes(MediaType.*) | Method | Request content type |
@StatusCode(200) | Method | Default HTTP status code |
@PathParam | Parameter | Binds a :name path segment (same name as the parameter) — String/Int64/Int32/Bool/Float64/Float32 |
@QueryParam | Parameter | Binds a query string key (same name as the parameter) — same types as @PathParam |
@PostParam | Parameter | Binds the deserialized JSON request body — type must be @JsonSerializable |
@HttpContext | Parameter | Binds the request/response handle — type must be HttpContext; return type HttpContext switches on manual response mode |
@Auth("bearer") | Class / Method | Authentication required |
@JsonSerializable | Class | Generates toJson()/fromJson() |
@JsonField("name") | Field | Alternative JSON key |
@Sensitive | Field | Completely masked in logs |
@Masked | Field | Partially masked in logs |
@DoNotSerialize | Field | Exclude field from JSON |
@Log | Class | Automatically inject log field |
@Inject | Field | Dependency injection field |
@Config("key") | Field | Value from application.properties |
@ApplicationComponent | Class | Singleton scope for DI |
@HttpRequestScoped | Class | New object per HTTP request |
@Test("desc") | Method | Unit test (tinox test) |
@inline | Function / Method | Forced LLVM inlining |
@deprecated("msg") | All | Deprecation warning |
@Command("name") | Class | CLI command |
@annotation | Class | Define custom annotation |
@WebsocketEndpoint("/path"[, port]) | Class | WebSocket: generates an accept/message loop, spawned alongside class Main (multiple classes allowed, each its own port) |
@OnOpen | Method | WebSocket: called on new connection, signature fn(conn: Int64) -> Nothing |
@OnMessage | Method | WebSocket: called per text message, signature fn(conn: Int64, msg: String) -> Nothing. AMQP-1.0: called per received message, signature fn(msg: Amqp10Message) -> Nothing. AMQP-0-9-1: called per received message, signature fn(msg: AmqpMessage091) -> Nothing |
@OnClose | Method | WebSocket: called when the connection ends, signature fn(conn: Int64) -> Nothing |
@Amqp10Consumer(host, port, user, pass, address) | Class | AMQP-1.0: generates a connect/attach/receive loop, spawned alongside class Main (multiple consumer classes allowed, even against the same broker/port with different queues) |
@Amqp091Consumer(host, port, vhost, user, pass, queue) | Class | AMQP-0-9-1: generates a connect/open/qos/consume/receive loop, spawned alongside class Main (multiple consumer classes allowed); prefetch is fixed at 1 in v1 |
@TinoxUIApp(httpPort, wsPort) | Class | Tinox-UI: generates the HTTP shell/client-JS server on httpPort and a WebSocket accept loop on wsPort that calls the @View method and re-renders the component tree diff-based (only patches are sent, no full resend); at most one @TinoxUIApp class per program, with exactly one @View method |
@View | Method | Tinox-UI: marks the method that builds/rebuilds the @TinoxUIApp's component tree, signature fn() -> Component; also serves as the fallback/404 view when @Route is used and the current route matches no pattern |
@Route("/path/:param") | Method | Tinox-UI: registers a fn() -> Component method inside a @TinoxUIApp class as that path's builder (Vaadin-style route dispatch). Requires a var currentRoute: String field; matched :name path segments are auto-assigned into a same-named field on the class, if one exists |
Standard Library (tinox-core)
The standard library consists of over 55 modules written in Tinox itself.
Import: import tinox.core.<module>;
HTTP & Web
http_server, rest, rest_framework,
http, websocket – complete HTTP/1.1 server with
routing, middleware, and content negotiation, plus a WebSocket server per
RFC 6455.
Messaging
amqp091 – AMQP-0-9-1 client (no broker) for
message-queue brokers like RabbitMQ: connect, channel, publish/consume.
amqp10 – standalone AMQP-1.0 client with a
connection/session/link hierarchy and credit-based flow control.
Data Formats
json, xml, csv, toml,
ini, base64, hex – serialization and
deserialization of common formats.
Mathematics
math, mathf, decimal,
complex – trigonometric functions, high-precision arithmetic,
complex numbers.
Collections
array, sort, set, queue,
stack, heap, graph, trie
– algorithms and data structures.
Strings & Regex
string, regex, fmt, tpl
– string manipulation, regular expressions, formatting, templating.
I/O & System
io, fs, env, process,
socket – file system, environment variables, processes,
low-level networking.
Concurrency
cron, events, pool,
semaphore, ratelimit, cache
– scheduling, event bus, thread pool, synchronization.
Cryptography
crypto, jwt, bcrypt
– hashing, JSON Web Tokens, password hashing.
LSP – Basics
The Language Server Protocol (LSP) is an open protocol developed by Microsoft in 2016 that standardizes the communication between a language server (which understands the programming language) and an editor (which shows the user interface).
The Problem Before LSP
Previously, every IDE had to implement its own plugins for every language: Eclipse plugin for Java, VS Code plugin for Java, IntelliJ plugin for Java – all separate implementations of the same logic. With n languages and m editors, n × m integrations were created.
LSP Solution: n + m Instead of n × m
With LSP you write one language server, and every LSP-compatible editor uses it automatically. The language server communicates via JSON-RPC over stdio with the editor.
Editor (Eclipse, VS Code, Neovim …)
│
│ JSON-RPC via stdin/stdout
▼
Language Server (tinox-lsp Binary)
│
│ Analyzes .tnx files
▼
Lex → Parse → Typecheck → Responses to editor
Important LSP Methods
| LSP Method | What the editor sends | What the server responds |
|---|---|---|
textDocument/hover | Cursor position | Markdown with type information |
textDocument/completion | Cursor position after . | List of completion suggestions |
textDocument/definition | Cursor on identifier | File + line of the definition |
textDocument/documentSymbol | Document URI | Hierarchical symbol list (Outline) |
textDocument/publishDiagnostics | – (server push) | Error positions + messages |
textDocument/didChange | New file content | Triggers re-analysis |
Tinox LSP Server
tinox-lsp is a complete LSP server implemented with
tower-lsp 0.20 (Rust) and Tokio as asynchronous
runtime.
Embedded Standard Library
All 26+ standard library modules are embedded directly into the LSP binary
using include_str!(). The server requires no installation
or configuration of file paths – it works immediately after copying
the binary.
Import Resolution for Diagnostics
When a .tnx file is opened, the LSP server automatically
resolves import declarations and loads the corresponding stdlib ASTs as
prelude. This way Json.parse() or HttpContext
are not marked as "undefined".
Dot Completion for Classes
When the user types Json.:
- The editor sends
textDocument/completionwith the offset after the dot - The LSP extracts the dot chain (
["Json"]) - It checks whether
Jsonis a variable (instance) or a class name - If class name: directly load the methods of
Jsonfrom the registry - Static methods (
fnc) are displayed with the hintfnc parse(...)
Technical Details
| Property | Value |
|---|---|
| Protocol | Language Server Protocol 3.17 (JSON-RPC via stdio) |
| Async Runtime | Tokio 1.x (multi-threaded) |
| Document Storage | DashMap (lock-free concurrent HashMap) |
| Stdlib embedded | Yes, via include_str!() at compile time |
| Diagnostics Mode | Full re-parse + typecheck on every save/change |
| Supported Editors | Eclipse (LSP4E), VS Code, Neovim, Emacs, … |
Eclipse Plugin
The Eclipse plugin tinox-eclipse connects the Eclipse IDE with the
tinox-lsp language server via the LSP4E framework –
the LSP client for Eclipse.
Features
Real-Time Error Highlighting
Syntax errors and type errors are underlined directly in the editor as soon as the file is saved.
Hover Information
Mouse over a function or variable: type signature and documentation appear in the tooltip.
Go to Definition
Ctrl+click or F3 jumps to the definition of a class, method, or function.
Code Completion
Ctrl+Space or after typing a dot, method and field suggestions appear.
Outline View
The Eclipse Outline View shows all classes, methods, and fields of the current file hierarchically.
Run (Ctrl+F11)
Direct compilation and execution of the current .tnx file
from within Eclipse.
Architecture
The plugin is an OSGi bundle that registers the
.tnx file extension via plugin.xml and instructs LSP4E to start the tinox-lsp process when
.tnx files are opened. Communication runs over stdin/stdout in JSON-RPC.
CLI Tools
The tinox binary is the central tool for all
development tasks:
| Command | Description |
|---|---|
tinox new <name> | Scaffold new project (folder structure, tinox.toml, main.tnx) |
tinox build <file> | Compile to native binary (release: -O3 + LTO) |
tinox run <file> | Compile and run immediately |
tinox dev <file> | Hot-reload mode: automatically recompile on file change |
tinox check <file> | Type check only, no binary generated |
tinox test <file> | Run all @Test-annotated methods |
tinox fmt <file> | Format source code (AST → formatted text) |
tinox doc | Generate HTML documentation from docstrings |
tinox graph [file] | Generate a Mermaid call-graph diagram from REST/WebSocket/AMQP/CLI entry points |
tinox repl | Interactive REPL session |
tinox add … | Add package dependency |
tinox install | Download and install dependencies |
HTTP Server & Performance
The integrated HTTP server is optimized for maximum throughput at minimal latency. It uses technologies also employed in production-ready systems such as Nginx and Envoy.
epoll – Event Multiplexing
Instead of blocking a thread for each connection, the server registers all
active connections in an epoll file descriptor. One
epoll_wait() call delivers all connections that have readable data
– in a single system call.
// Concept (simplified):
epoll_fd = epoll_create1(0);
// Register all active connections...
while (true)
{
events = epoll_wait(epoll_fd, max_events, 50); // 50ms Timeout
for event in events
{
if event.fd == server_socket { accept(); }
else { handle_request(event.fd); }
}
}
SO_REUSEPORT – Kernel Load Balancing
With SO_REUSEPORT, multiple threads (or processes) can listen
on the same port simultaneously. The Linux kernel automatically distributes incoming connections
to available listeners – without locks, without bottlenecks.
Thread-Local Buffers
Each HTTP worker thread has its own static buffer for request data, response data, and JSON parsing. These buffers are never freed and are reused – this completely eliminates malloc/free in the critical request path.
Benchmark: Tinox vs. Quarkus
A sort REST endpoint was measured under identical conditions against Quarkus (Java, native image):
| Metric | Tinox | Quarkus | Difference |
|---|---|---|---|
| Throughput | 26,700–27,000 req/s | 24,867–25,541 req/s | +5–7% |
| Latency (mean) | 0.44–0.45 ms | 0.52–0.55 ms | ~17–20% better |
| Error rate | 0 % | 0 % | – |
Test conditions: 5,000 requests, concurrency 20, list with 20 numbers per request, Linux x86_64.
Pros & Cons
✓ Advantages
- Very low latency and high throughput thanks to LLVM + epoll
- Boehm GC – automatic memory management without borrow-checker complexity
- Low startup time (<1ms) – ideal for serverless/Lambda
- Java-like syntax – low entry barrier for backend developers
- Annotation-driven REST: minimal boilerplate
- Complete tooling: LSP, Eclipse plugin, REPL, formatter
- Standard library written in the language itself
- Small binary footprint – no framework as runtime dependency
- Embedded stdlib in the LSP – no configuration required
- Cross-platform via LLVM (Linux, macOS, Windows possible)
✗ Disadvantages
- Conservative GC (Boehm) – can be somewhat slower than manual management for pointer-intensive workloads
- Small ecosystem – no mature third-party libraries
- No standardized specification – language changes quickly
- Compiler errors not yet as helpful as in Rust or Go
- No complete module system with real separation between projects
- No borrow-checker safety – use-after-free theoretically possible (but GC prevents leaks)
- Long compile times due to LLVM (for large projects)
- No Windows support (epoll is Linux-specific)
- No stable releases yet – pre-1.0
- Thin community and documentation so far
Comparison: Memory Safety
Tinox gives the developer full control over memory – like C –, but does not offer static guarantees like Rust's borrow checker. This means:
| Language | Memory Model | Safety | Performance |
|---|---|---|---|
| Java / Kotlin | GC | High (no UAF) | GC pauses |
| Rust | Ownership + Borrow-Checker | Very high (compile-time) | Maximum |
| Go | GC (concurrent) | High | Good |
| Tinox | Boehm GC (conservative) | GC prevents leaks | Very high |
| C/C++ | Manual | Developer responsibility | Maximum |
Use Cases
High-Performance REST APIs
Microservices with very low latency requirements (trading, real-time systems). Annotation-driven routing, no framework overhead.
Serverless / Edge Computing
Cold start <1ms thanks to native binary without JVM or Node.js. Ideal for AWS Lambda, Cloudflare Workers (native mode), edge functions.
System Tools & CLIs
With @Command/@Option/@Argument
CLI tools can be developed with minimal effort. Native binary without
runtime dependencies.
Data Processing Pipelines
Batch processing of large data volumes with automatic GC – no manual memory management required, yet high performance.
Security-Critical Services
Deterministic runtime behavior through conservative GC with predictable behavior. Annotations for sensitivity and masking built in.
Teaching & Research
Small, readable compiler codebase. Ideal for learning compiler construction, LLVM IR, and LSP development.
Less Suitable For…
- Frontend development (no browser target, no WASM focus)
- Data science / ML (no NumPy equivalent, no notebook integration)
- Mobile apps (no iOS/Android framework)
- Projects that require a huge package ecosystem (npm, Maven)
Comparison with Other Languages
| Feature | Tinox | Java / Quarkus | Go | Rust | C |
|---|---|---|---|---|---|
| Compilation | AOT → native | JVM / AOT (native image) | AOT → native | AOT → native | AOT → native |
| Garbage Collector | Yes (Boehm GC) | Yes (G1GC, ZGC) | Yes (concurrent) | No (Ownership) | No |
| Memory Safety | GC-protected (no leaks) | GC-protected | GC-protected | Compile-time | Manual |
| Syntax Style | Java-like | Java | C-like | C-like | C |
| REST Annotations | Built-in | JAX-RS / Quarkus | No standard | No standard | None |
| Startup Time | <1ms | JVM: 1–3s; Native: ~10ms | ~5ms | <1ms | <1ms |
| IDE Tooling | LSP + Eclipse | Very mature | Good (gopls) | Very good (rust-analyzer) | Medium (clangd) |
| Ecosystem | Small (growing) | Huge (Maven) | Good | Good (crates.io) | Large (mature) |
| Concurrency | Threads + Channels | Virtual Threads (Java 21) | Goroutines | async/await + Threads | pthreads |
| Backend LLVM | Yes | No (JVM / Graal) | No (custom) | Yes | Optional (clang) |
http_server
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/http_server/1-0-3/docs.html
Request body size cap: 4 MiB (TINOX_MAX_BODY in runtime.c). A request whose Content-Length exceeds this is rejected up front with 413 Payload Too Large and the connection is closed — the handler is never invoked, and the body is never silently truncated and processed as if it were complete (issue #174).
http2_server
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/http2_server/1-0-2/docs.html
http3_server
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/http3_server/1-0-2/docs.html
websocket
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/websocket/1-0-3/docs.html
sse
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/sse/1-0-1/docs.html
amqp091
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/amqp091/1-0-3/docs.html
amqp10
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/amqp10/1-0-2/docs.html
smtp
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/smtp/1-0-1/docs.html
redis
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/redis/1-0-1/docs.html
hpack
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/hpack/1-0-1/docs.html
http
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/http/1-0-3/docs.html
rest.client & rest.server
rest is published as a single package covering both the client and the server API. Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/rest/1-0-2/docs.html
socket
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/socket/1-0-0/docs.html
kubernetes
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/kubernetes/1-0-3/docs.html
ui
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/ui/1-0-7/docs.html
jwt
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/jwt/1-0-2/docs.html
oauth2
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/oauth2/1-0-2/docs.html
oidc
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/oidc/1-0-2/docs.html
json
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/json/1-0-0/docs.html
msgpack
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/msgpack/1-0-1/docs.html
xml
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/xml/1-0-1/docs.html
yaml
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/yaml/1-0-2/docs.html
csv
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/csv/1-0-1/docs.html
toml
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/toml/1-0-1/docs.html
ini
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/ini/1-0-1/docs.html
base64
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/base64/1-0-0/docs.html
hex
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/hex/1-0-0/docs.html
encoding
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/encoding/1-0-0/docs.html
array
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/array/1-0-0/docs.html
collections
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/collections/1-0-0/docs.html
heap
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/heap/1-0-0/docs.html
queue
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/queue/1-0-0/docs.html
set
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/set/1-0-0/docs.html
sort
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/sort/1-0-0/docs.html
iter
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/iter/1-0-0/docs.html
graph
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/graph/1-0-0/docs.html
trie
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/trie/1-0-0/docs.html
math
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/math/1-0-0/docs.html
mathf
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/mathf/1-0-0/docs.html
mathx
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/mathx/1-0-0/docs.html
complex
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/complex/1-0-0/docs.html
decimal
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/decimal/1-0-0/docs.html
random
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/random/1-0-0/docs.html
string
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/string/1-0-0/docs.html
fmt
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/fmt/1-0-0/docs.html
format
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/format/1-0-0/docs.html
regex
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/regex/1-0-0/docs.html
uri
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/uri/1-0-0/docs.html
fs
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/fs/1-0-0/docs.html
io
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/io/1-0-0/docs.html
env
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/env/1-0-0/docs.html
process
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/process/1-0-0/docs.html
debug
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/debug/1-0-0/docs.html
zip
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/zip/1-0-2/docs.html
compress
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/compress/1-0-1/docs.html
asm
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/asm/1-0-0/docs.html
bitmap
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/bitmap/1-0-1/docs.html
tpl
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/tpl/1-0-1/docs.html
crypto
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/crypto/1-0-2/docs.html
hash
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/hash/1-0-0/docs.html
validation
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/validation/1-0-0/docs.html
uuid
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/uuid/1-0-0/docs.html
semaphore
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/semaphore/1-0-0/docs.html
pool
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/pool/1-0-0/docs.html
ratelimit
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/ratelimit/1-0-1/docs.html
cron
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/cron/1-0-0/docs.html
events
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/events/1-0-0/docs.html
time
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/time/1-0-0/docs.html
cache
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/cache/1-0-0/docs.html
option
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/option/1-0-0/docs.html
result
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/result/1-0-0/docs.html
logger
Full reference (description, dependencies, examples, classes & methods) is loaded directly from the published tinox-central package documentation, so it does not have to be maintained in two places: docs/tinox-core/logger/1-0-0/docs.html
ORM & Lambda Query DSL
Tinox provides a type-safe ORM inspired by JPA/QueryDSL. Classes are annotated as database tables, and all queries run through a type-safe lambda DSL — no string-based queries.
Annotations
| Annotation | Target | Description |
|---|---|---|
@Entity | Class | Marks the class as a database entity |
@Table("name") | Class | Sets the table name (default: lowercase class name) |
@Id | Field | Primary key |
@Column("col") | Field | Maps field to a DB column (default: field name) |
@GeneratedValue | Field | ID generated by the DB (AUTO_INCREMENT / SERIAL) |
@NotNull | Field | Column is NOT NULL |
Entity Definition
@Entity
@Table("users")
class User {
@Id @GeneratedValue
var id: Int64;
@Column("name")
var name: String;
@Column("age")
var age: Int64;
@Column("active")
var active: Bool;
}tinox.toml – [database] Configuration
# PostgreSQL
[database]
driver = "postgres"
url = "postgres://user:pass@localhost:5432/mydb"
pool = 10
# MySQL / MariaDB
[database]
driver = "mysql"
url = "mysql://user:pass@localhost:3306/mydb"
# SQLite (no DB server required)
[database]
driver = "sqlite"
url = "sqlite:///path/to/database.db"Lambda Query DSL
// All users over 18, sorted alphabetically, max 10 results
let adults: List<User> = DB.of(User)
.filter(u -> u.age > 18)
.orderBy(u -> u.name)
.limit(10)
.list();
// Read a single user
let alice: User = DB.of(User)
.filter(u -> u.name == "Alice")
.first();
// Count active users
let n: Int64 = DB.of(User)
.filter(u -> u.active == true)
.count();Lambda → SQL Translation Table
| Lambda Expression | SQL Fragment |
|---|---|
u.age > 18 | age > $1 |
u.name == "Alice" | name = $1 |
u.name != "Bob" | name != $1 |
u.name.startsWith("A") | name LIKE 'A%' |
u.name.endsWith("z") | name LIKE '%z' |
u.name.contains("oo") | name LIKE '%oo%' |
expr1 && expr2 | (pred1) AND (pred2) |
expr1 || expr2 | (pred1) OR (pred2) |
!expr | NOT (pred) |
Save, Update, Delete
// INSERT (ID assigned by the DB)
let user: User = User {};
user.name = "Alice";
user.age = 30;
let saved: User = DB.of(User).save(user);
// DELETE
DB.of(User).delete(saved);
// Save multiple entities
let list: List<User> = List::new();
list.add(user1);
list.add(user2);
DB.of(User).saveAll(list);Error Handling
Database errors are currently logged to stderr. Integration with try/catch is planned for a future release. Connection errors at startup terminate the program with a descriptive message.