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.

Compiled LLVM Object-Oriented REST-API LSP High-Performance

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.

Core Idea: The productivity of a framework like Spring Boot or Quarkus – without JVM overhead, garbage collector pauses, or high memory usage.
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
    {
        const root: JsonValue = Json.parse(ctx.request.body)
        const 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.

Advantage: Tinox automatically benefits from all LLVM optimizations (loop unrolling, inlining, dead code elimination, link-time optimization) without needing to implement its own optimization logic.

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:

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.

Statement Termination

A statement ends at the end of its line – there is no statement terminator. A ; that terminates a statement is a hard compile error (“semicolons were removed”), and several statements cannot share a line. The only remaining ; separates the parts of a C-style for (init; cond; update) header.

A statement continues on the next line only if the line ends with a binary operator, a comma or an opening bracket, or if the next line starts with . (method chains). Inside ( ) and [ ] newlines are plain whitespace. A line starting with (, [, - or + directly after a complete expression is a hard error – the compiler never guesses whether it continues the previous line. Enum variants are written one per line.

const total = first +
    second +
    third

const name = user
    .profile()
    .displayName()

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-commonRustShared data types (Span, Error, AST nodes)~250 lines
tinox-lexerRustTokenization (Lexer)~800 lines
tinox-parserRustAST construction + code formatter~2,500 lines
tinox-typecheckRustType checking + annotation processing~2,000 lines
tinox-codegenRustAST → LLVM IR~6,000 lines
tinox (CLI)RustCompiler control, REPL, project manager~1,700 lines
tinox-lspRustLanguage Server Protocol Server~1,000 lines
tinox-eclipseJavaEclipse IDE Plugin~400 lines
runtime.cCRuntime system: I/O, HTTP, memory, strings~1,700 lines
tinox-coreTinoxStandard library (55+ modules)~200 KB

Compiler Pipeline

The Tinox compiler transforms a .tnx source file in several steps into an executable native binary:

1

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}!").

2

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.

3

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.

4

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.

5

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.

6

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.

7

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).

Result: A single, statically linked binary with no external dependencies (except the C standard library). Startup time: <1ms.

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

TypeImplementationSpecial Feature
ArrayDynamic C arrayLength stored at offset -1; grows on push
MapOpen-addressing hash tableFNV-1a hash, load factor 0.75, tombstones for delete
StringC 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.

Task lifetime, deadlines and cancellation

scope { ... } owns its lexical spawns. A plain spawn belongs to its spawning thread's lifetime; that thread joins its remaining children before finishing. On process exit, remaining joinable children are cancelled and joined. Failures are rethrown by await, or at scope exit if unobserved; additional failures are reported on stderr. A body's own error wins. Repeated awaits cache the same result or error while the owner lives. After the owning scope closes, handles expire and further use fails visibly. Keep tasks inside their owner; return the awaited value instead of a task.

try {
    scope {
        taskSetDeadline(250) // Duration from now, in monotonic milliseconds.
        const task: Task<String> = spawn Main::load()
        println(await task)
    }
} catch (e: String) { println(e) }
OperationContract
taskCancel(task: Task<T>)Request cooperative cancellation of a task and its descendants.
taskSetDeadline(ms: Int64)Set the current scope's deadline. Ancestor deadlines still apply; 0 expires immediately. Negative durations fail visibly.
taskCheckCancellation()Checkpoint for CPU loops. Throws Task cancelled, Task deadline exceeded, or Task service shutdown requested.
taskWaitReadable(fd: Int64)Cancellable readiness wait for a real file descriptor; use before a single-reader accept/read.
taskDetach(task: Task<T>)Explicit fire-and-forget. Only the owning thread may detach an unjoined task. It loses inherited scope cancellation/deadlines, cannot be awaited, and any uncaught failure terminates the process visibly.
taskRequestShutdown()Process-wide cooperative stop request for service lifecycle/control code. Bootstrap awaits stop waiting; shutdown joins outstanding joinable tasks and preserves genuine failures.

Cancellation also wakes sleep/sleep_ms, blocked channel recv, and await (check latency about 10 ms, excluding scheduling). Tokens propagate to child tasks and nested scopes. Scope failure cancels unfinished siblings; body errors remain primary. An explicitly cancelled task still reports cancellation unless awaited and caught. Expected cancellation during process shutdown is successful.

Cancellation uses normal exception unwinding: finally and defer run in their usual order; a child's transaction rolls back before its join completes. Transactions are thread-local and never inherited. Put a scope inside a transactional method to join before commit, and put parent resource cleanup outside the scope so children finish first.

No asynchronous thread termination is used. Native blocking I/O, database calls and CPU loops without checkpoints are not automatically interruptible. Use resource-specific stop/close operations or taskWaitReadable; after five seconds of ignored cancellation during scope shutdown, the runtime fails visibly instead of hanging silently. Explicit await of a cancelled task and a service shutdown request have the same five-second watchdog. With @Service, its configured common shutdown deadline replaces the standalone five-second shutdown watchdog; see the service lifecycle below. Detached workers are explicitly outside structured joining.

Legacy Int64 handle storage/await remains temporarily compatible for published packages. New code and task-control operations require Task<T>. Invalid/expired handles and cyclic awaits fail with a diagnostic; integer handles are deprecated.

Coordinated service lifecycle

Add @Service(startupMs, shutdownMs) to class Main to enable coordinated startup, health reporting and graceful shutdown. Both durations are optional positive integer milliseconds (defaults: 30000 and 5000; maximum: 3600000). The coordinator starts before database initialization and eager DI. Existing programs opt into this contract explicitly.

@ApplicationComponent
@Synchronized
class Resources {
    @OnStart
    fn start() -> Nothing { /* Initialize resources before listeners start. */ }
    @Readiness
    fn ready() -> Bool { return true }
    @Liveness
    fn live() -> Bool { return true }
    @OnStop
    fn stop() -> Nothing { /* Dispose resources after callbacks and tasks finish. */ }
}

@Service(30000, 5000)
class Main {
    fnc main() -> Int32 { return 0 }
}

Import the component and annotated controllers/endpoints from the entry file. Hooks are synchronous instance methods without parameters, on non-generic @ApplicationComponent/@Startup classes without inheritance. Start hooks run after injected dependencies' hooks, then by class/method name; stop hooks run in reverse order. Each hook joins its spawned children before the next step. All initialized owners receive stop hooks even after a startup failure; cleanup continues after errors, preserves the first failure and exits nonzero. Protect mutable state shared with health checks and callbacks using @Synchronized.

States are initializing → starting → ready, with unready for failed health contributions, then draining → stopping → stopped (or failed). Readiness requires completed initialization/start hooks, bound required listeners, consumer handshakes and successful readiness/liveness contributions. Returning from Main is not a readiness barrier; with listeners, it leaves the service running. Without listeners, returning requests shutdown.

Generated HTTP and HTTP/3 servers reserve GET /health/live and GET /health/ready: HTTP 200 or 503 with JSON state, readiness, liveness and monotonic startedMs, readyMs, shutdownMs. Started means managed bootstrap entry; ready is the first successful health pass, not process creation or banner timing. Health contributions run periodically on the coordinator and should be quick. Unready startup exceeding its budget fails visibly. A later false health result changes health, without restarting the process.

serviceState(), serviceStatusJson(), serviceIsReady(), serviceIsLive(), serviceIsStopping() and the three timestamp getters serviceStartedMs()/serviceReadyMs()/serviceShutdownMs() expose the same state. serviceAwaitReady(ms) returns Bool; serviceBoundPort(index) reports the actual port of an auto-run task in bootstrap-plan order (-1 before binding or for a broker). tinox explain --bootstrap Main.tnx --json includes deadlines, hook order, tasks and shutdown policy.

SIGTERM, SIGINT, serviceRequestShutdown() and taskRequestShutdown() mark the service unready and stop admission. Accepted HTTP responses and broker acknowledgements finish; WebSockets send close code 1001 and run OnClose. Listeners/workers join before remaining structured children are cancelled/joined, reverse stop hooks run and database pools close. serviceAwaitShutdown() lets Main wait for the stop request. One common shutdown deadline covers every stage; expiry terminates the process with status 1, including blocked native I/O or hooks. No asynchronous thread cancellation is used. Explicitly detached user tasks remain outside structured joining.

Use an exec-form container entrypoint so signals reach tinox. Configure a startup probe and readiness/liveness probes against the health paths, and give the orchestrator a termination grace period longer than the shutdown budget. CLI @Command and @TinoxUIApp entrypoints cannot currently combine with @Service; compilation rejects them visibly.

Shared application state

@ApplicationComponent creates one lazy singleton per component class; @Startup eagerly creates that same kind of singleton before main. Generated providers serialize construction, field defaults, recursive dependency injection and publication. Every concurrent provider caller sees the same fully initialized instance. Providers do not invoke user constructors. This initialization guarantee does not serialize later mutation.

HTTP workers and independently spawned REST, WebSocket and AMQP components can execute concurrently. Put request data in @HttpRequestScoped owners, and inject application services into them. Capturing a request-scoped dependency in a singleton shares that object; refreshing a singleton controller's injected field during dispatch is unsafe for per-request isolation. The compiler warns about captive request state and exposed or unguarded mutable singleton fields.

@ApplicationComponent
@Synchronized
class Counter {
    private var value: Int64 = 0
    fn increment() -> Int64 {
        this.value = this.value + 1
        return this.value
    }
}

@HttpRequestScoped
class Api {
    @Inject var counter: Counter
    @GET @Path("/count")
    fn count() -> Int64 { return this.counter.increment() }
}

@Synchronized on a non-generic application/startup class protects all instance methods; on an instance method it protects only that method. There is one recursive monitor per declaring class, shared by every annotated call and every instance of that class. Nested calls on the same thread are safe. Static methods are excluded from class-level synchronization; explicitly annotating a static method, generic method, unscoped class, interface/trait method or class with inheritance is rejected. This deliberately limited contract prevents silent gaps in generated locking.

The monitor is held across the method's defer/finally cleanup and transactional commit or rollback, and released before returning a result or error. Cancellation while waiting for a monitor throws without executing the body; cancellation inside it unwinds the body and releases the monitor. Existing errors are preserved during cleanup. Dev UI state snapshots use the class monitor when one is present.

Keep state private and protect reads as well as writes. Returned mutable objects, direct field access, static methods and unannotated methods bypass the monitor. Take snapshots inside a protected method instead of returning internal collections. Do not await a child that needs the monitor while holding it, and acquire different class monitors in a consistent order. Reentrancy applies to one thread, not spawned children. For smaller explicit critical sections, use tinox.core.semaphore locks with defer immediately after a successful acquisition; these native blocking locks do not become cancellable. Annotations and diagnostics do not prove universal race freedom.

HTTP Server (Low Level)

The HTTP server in the runtime uses:

Type System

Primitive Types

Tinox TypeBitLLVM-IRDescription
Int8 / Int16 / Int32 / Int648–64i8–i64Signed integers
UInt8 / UInt16 / UInt32 / UInt648–64i8–i64Unsigned integers
Float32 / Float6432/64float/doubleIEEE 754 floating-point numbers
Bool1i1Boolean value
Char32i32Unicode code point
String–i8*UTF-8 string (C string)
Nothing–voidNo return value (equivalent to void)
Never–voidFunction never returns (throw, exit)

s.chars() returns List<String> containing one Unicode scalar value per element. Use for ch in s.chars() to process complete UTF-8 characters. Combining marks and emoji sequences may span several elements: this does not normalize text or segment graphemes. Empty input yields an empty list; malformed UTF-8 aborts with its byte offset. Length, indexing, charAt, and direct string iteration retain their byte semantics. The operation takes O(bytes) time and allocates a list plus one short string per scalar value.

Composite Types

const numbers: List<Int64> = [1, 2, 3]                 // Array
const ages: Map<String, Int32> = @{"Alice" => 30}  // Map/Dictionary
const pair: (Int32, String) = (42, "hello")           // Tuple
const name: String? = null                             // Nullable
const 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.

Absence and recoverable errors

For new library APIs, use Option<T> for absence and Result<T> for expected failures. Import tinox.core.option and tinox.core.result. Some("") means present-empty; None means absent. Check isSome()/isNone() or choose an explicit fallback with unwrapOr(). Do not add a nullable T? alternative for the same lookup.

Result<T> retains its String error. Use isOk()/isErr() and getError(); preserve operation, target and cause without exposing secrets. Do not infer status from message contents. APIs needing stable error categories should use documented domain outcome fields. A generic typed-error Result and allocation changes are deferred.

Exceptions remain appropriate for documented precondition, programming and setup failures. Option.unwrap() on None throws "Option is None"; Result.unwrap() on Err throws the original error. Callback exceptions propagate through combinators. Use finally for cleanup on normal and exceptional exits.

The additive HTTP methods findHeader, findParam, findQuery and QueryString::find return Option<String>. Headers are case-insensitive; path/query names are case-sensitive. Queries keep raw values, the last duplicate, and present-empty bare keys. Existing String getters keep their empty fallback without deprecation warnings. Use a package version that provides the optional methods, or matching workspace sources. See the API inventory and migration guide for examples and legacy I/O limitations.

The current checkout also provides checked filesystem alternatives: Fs::tryReadFile, tryWriteFile, tryAppendFile, tryCopyFile, tryMoveFile and tryDeleteFile. Their IoResult<T> keeps status and payload together; failure() exposes operation, target, OS code and cause. An empty read is success; partial reads and failed flushes are failures. Migration and compatibility contracts.

ByteStream and Http1Stream provide bounded, deadline-aware TCP/TLS streaming with explicit ownership and cleanup. HTTP/1.1 streaming supports one Content-Length exchange; HTTP/2/3 body bridges preserve binary bytes but still buffer whole bodies. Binary and streaming contracts.

Keyword Overview

KeywordMeaning
fnInstance method (has implicit this)
fncStatic method (no this, called via class name)
constImmutable local variable (let is still accepted as a deprecated alias)
varMutable local variable or field
classClass declaration
interfaceInterface declaration (like Java interface)
enumEnumeration type
extendsSingle inheritance
implementsInterface implementation
spawnStart a new thread; the expression has type Task<T> (T = the function's return type)
awaitWait for a Task<T> and yield its T (String, Float64, Bool, classes, ... not just Int64); awaiting the same task again returns the same result. Task is a built-in type name and can no longer be used for your own classes
scope { ... }Structured concurrency: every spawn lexically inside the block belongs to it, and leaving the block (normally, via return/break or throw) joins them all. A child failure nobody awaited is re-thrown at the block's end; if the block itself threw, its error wins and child failures are reported on stderr. A throw inside a spawned function is re-thrown by await. scope is contextual, not a reserved word. A spawn in a closure inside the block is not owned by it
deferExecute code when leaving the scope
matchPattern 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.

BeforeAfter
fn getUser(ctx: HttpContext) -> Nothing
{
  const id: Int64 = ctx.request.getParam("id").toInt();
  ctx.response.json(Json::serialize(user));
}
fn getUser(@PathParam id: Int64) -> User
{
  return user;
}
fn createUser(ctx: HttpContext) -> Nothing
{
  const u: User = Json::deserialize<User>(ctx.request.body);
  ctx.response.json(Json::serialize(u));
}
fn createUser(@PostParam u: User) -> User
{
  return u;
}
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

AnnotationTargetDescription
@GET @POST @PUT @PATCH @DELETEMethodHTTP verb for REST route
@Path("...")Class / MethodURL path (supports :param)
@Produces(MediaType.*)MethodResponse content type
@Consumes(MediaType.*)MethodRequest content type
@StatusCode(200)MethodDefault HTTP status code
@PathParamParameterBinds a :name path segment (same name as the parameter) — String/Int64/Int32/Bool/Float64/Float32
@QueryParamParameterBinds a query string key (same name as the parameter) — same types as @PathParam
@PostParamParameterBinds the deserialized JSON request body — type must be @JsonSerializable
@HttpContextParameterBinds the request/response handle — type must be HttpContext; return type HttpContext switches on manual response mode
@Auth("bearer")Class / MethodAuthentication required
@JsonSerializableClassGenerates toJson()/fromJson()
@JsonField("name")FieldAlternative JSON key
@SensitiveFieldCompletely masked in logs
@MaskedFieldPartially masked in logs
@DoNotSerializeFieldExclude field from JSON
@LogClassAutomatically inject log field
@InjectFieldProvider-owned injection field; source reassignment is rejected
@Provider("name")ClassNames a concrete DI provider with an explicit scope
@Qualifier("name")FieldSelects an @Inject field's provider at compile time
@Required / @OptionalFieldPresence/null contract for JSON request DTOs
@Length(min, max)FieldInclusive Unicode-codepoint or list-element count bounds
@Range(min, max)FieldInclusive numeric request-DTO bounds; @NotNull remains a database annotation
@Config("key")FieldValue from application.properties; values may contain ${ENV} / ${ENV:default} (environment variable, optional default; \${ = literal)
@SynchronizedClass/methodRecursive class monitor for singleton instance methods
@ApplicationComponentClassSingleton scope for DI
@HttpRequestScopedClassOne instance per concrete provider and synchronous REST request context
@Test("desc")MethodUnit test (tinox test)
@inlineFunction / MethodForced LLVM inlining
@deprecated("msg")AllDeprecation warning
@Command("name")ClassCLI command
@annotationClassDefine custom annotation
@GetterClass / FieldGenerates get<Field>() — for every field on a class, or just the annotated field on a field; never overrides an already hand-written method of the same name
@SetterClass / FieldGenerates set<Field>(value) — same rules as @Getter
@WebsocketEndpoint("/path"[, port])ClassWebSocket: generates an accept/message loop, spawned alongside class Main (multiple classes allowed, each its own port)
@OnOpenMethodWebSocket: called on new connection, signature fn(conn: Int64) -> Nothing
@OnMessageMethodWebSocket: 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
@OnCloseMethodWebSocket: called when the connection ends, signature fn(conn: Int64) -> Nothing
@Amqp10Consumer(host, port, user, pass, address)ClassAMQP-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)ClassAMQP-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
@TinoxUIApp(httpPort)
@TinoxUIApp(httpPort, wsPort)
ClassTinox-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. Both ports are optional: with no argument they are 8080/8081, with one argument httpPort and httpPort + 1. Every port a program binds is checked for collisions at compile time — two binders on one port do not fail loudly at runtime (SO_REUSEPORT), they silently split the traffic between them
@ViewMethodTinox-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")MethodTinox-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

Current contracts: DI providers and request contexts, recursive request validation and HTTP-400 details.

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 MethodWhat the editor sendsWhat the server responds
textDocument/hoverCursor positionMarkdown with type information
textDocument/completionCursor position after .List of completion suggestions
textDocument/definitionCursor on identifierFile + line of the definition
textDocument/documentSymbolDocument URIHierarchical symbol list (Outline)
textDocument/publishDiagnostics– (server push)Error positions + messages
textDocument/didChangeNew file contentTriggers re-analysis
Advantage: The tinox-lsp language server works in Eclipse, VS Code, Neovim, Emacs, and every other LSP-capable editor – without language-specific plugin development per editor.

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.:

  1. The editor sends textDocument/completion with the offset after the dot
  2. The LSP extracts the dot chain (["Json"])
  3. It checks whether Json is a variable (instance) or a class name
  4. If class name: directly load the methods of Json from the registry
  5. Static methods (fnc) are displayed with the hint fnc parse(...)

Technical Details

PropertyValue
ProtocolLanguage Server Protocol 3.17 (JSON-RPC via stdio)
Async RuntimeTokio 1.x (multi-threaded)
Document StorageDashMap (lock-free concurrent HashMap)
Stdlib embeddedYes, via include_str!() at compile time
Diagnostics ModeFull re-parse + typecheck on every save/change
Supported EditorsEclipse (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:

CommandDescription
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 docGenerate HTML documentation from docstrings
tinox graph [file]Generate a Mermaid call-graph diagram from REST/WebSocket/AMQP/CLI entry points
tinox replInteractive REPL session
tinox add …Add package dependency
tinox installDownload 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.

Concurrency Budgets & Overload Handling

Worker and connection counts are bounded and container-aware. The effective CPU count is the smaller of the process's CPU affinity (taskset, cpuset) and the cgroup CPU quota (v1 and v2, e.g. docker run --cpus=1.5 gives 2), not the host's core count. Each limit can be overridden with an environment variable; a malformed value aborts startup. The effective values are printed in the startup banner (Limits: ...) and exported on /metrics together with open/peak/rejected counters.

VariableDefaultEffect when exhausted
TINOX_CPUSdetected–
TINOX_HTTP_WORKERSCPUs–
TINOX_MAX_CONNECTIONS4096 (max 4096)HTTP/1: 503 Service Unavailable with Retry-After: 1
TINOX_MAX_TASKS4096spawn returns a task whose await (or enclosing scope) throws a "task budget exhausted" error
TINOX_MAX_WS_CONNECTIONS1024the WebSocket connection is closed immediately
TINOX_QUEUE_WAIT_MS0 (no queueing)how long spawn / a WebSocket accept may wait for a free slot before being rejected

Every setting can also be placed in application.properties as tinox.limits.<name> (e.g. tinox.limits.max_tasks=256); the environment variable wins. The Dev UI API exposes the effective values and live counters at /limits. HTTP/1 rejects immediately (the epoll workers must not block); the HTTP/2, HTTP/3 and TLS accept loops are single-threaded by design, so their backlog is bounded by the kernel listen queue and they never grow threads. AMQP connections use spawn and therefore count against TINOX_MAX_TASKS. A rejected request is never retried automatically. Bind address: by default every listener (HttpServer, @TinoxUIApp, WebSocket, HTTP/2, SSE) binds 0.0.0.0. TINOX_BIND_ADDRESS=127.0.0.1 restricts them to one IPv4 address (e.g. loopback-only for local dashboards); an invalid value aborts startup.

Result: Up to 4,096 simultaneous connections per thread, linear scaling across CPU cores via SO_REUSEPORT.

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.

Note: Quarkus was compiled with native-image – thus also without JVM overhead. The comparison is therefore fair: both systems run as native Linux binaries.

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:

LanguageMemory ModelSafetyPerformance
Java / KotlinGCHigh (no UAF)GC pauses
RustOwnership + Borrow-CheckerVery high (compile-time)Maximum
GoGC (concurrent)HighGood
TinoxBoehm GC (conservative)GC prevents leaksVery high
C/C++ManualDeveloper responsibilityMaximum

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…

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)
Positioning: Tinox fills a niche between Go and C: more productive syntax than C/C++, without the GC overhead of Go or Java, with a built-in REST framework that approaches Spring Boot or Quarkus in terms of developer convenience – but surpasses them in performance.

http_server

Typed JSON responses with dynamic status codes are available as Response<T>. See the typed response and OpenAPI contract guide for checkout-library setup and the annotation-first CRUD example.

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-4/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-3/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-13/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

unicode

A String stays a byte sequence (len(), s[i], substring() count bytes). tinox.core.unicode adds the code point unit explicitly and optionally; grapheme clusters and normalization (NFC/NFD) are not provided. Malformed UTF-8 is never replaced: it raises a catchable error naming the first invalid byte offset.

CallMeaning
Unicode::isValid(s)well-formed UTF-8 (no overlong forms, surrogates, values above U+10FFFF)
Unicode::codePointCount(s)number of code points; "e" + U+0301 is two
Unicode::codePoints(s) / fromCodePoints(list)the scalar values as List<Int64> and back; NUL, surrogates and out-of-range values throw
Unicode::byteOffset(s, index)byte offset of code point index (to cut with substring on code point boundaries)
Unicode::toUpper(s) / toLower(s)full default mapping (ß → SS), no locale; capital sigma always becomes σ (no final-sigma rule)

Costs: every call is O(bytes) and validates first; codePoints allocates 8 bytes per code point, toUpper/toLower up to 3x the input. The tables match Unicode::version() (16.0.0) and are regenerated with scripts/gen-unicode-case.py.

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

Current workspace: Regex methods throw catchable errors for invalid patterns; isValid and WithOptions variants are available. Current Regex contract. The embedded page describes the published package version.

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

Current workspace additions: metadata, atomic rename, and safe directory operations.

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

Request correlation, structured logging and OTLP tracing (development reference)

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

db

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/db/1-0-0/docs.html

Only the query-chain classes (DB, EntityQuery) themselves — @Entity/@Table/@Column/@Id/@GeneratedValue, the connection pool, and @Transactional (since issue #191) are compiler/codegen features, not stdlib classes; see the ORM & Lambda Query DSL guide further down for their full reference.

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

AnnotationTargetDescription
@EntityClassMarks the class as a database entity
@Table("name")ClassSets the table name (default: lowercase class name)
@IdFieldPrimary key
@Column("col")FieldMaps field to a DB column (default: field name)
@GeneratedValueFieldID generated by the DB (AUTO_INCREMENT / SERIAL)
@NotNullFieldColumn 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
const adults: List<User> = DB::of(User)
    .filter(u -> u.age > 18)
    .orderBy(u -> u.name)
    .limit(10)
    .list()

// Read a single user
const alice: User = DB::of(User)
    .filter(u -> u.name == "Alice")
    .first()

// Count active users
const n: Int64 = DB::of(User)
    .filter(u -> u.active == true)
    .count()

Lambda → SQL Translation Table

Lambda ExpressionSQL Fragment
u.age > 18age > $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)
!exprNOT (pred)

Save, Update, Delete

// INSERT (ID assigned by the DB)
const user: User = User {}
user.name = "Alice"
user.age  = 30
const saved: User = DB::of(User).save(user)

// DELETE
DB::of(User).delete(saved)

// Save multiple entities
const 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.