varyk GitHub

Roadmap

Milestones are ordered; items within a milestone are not. Nothing here is a release commitment or a date. The live roadmap in the compiler repository tracks progress item by item.

Milestone 1: compiler skeleton and the borrow-by-default proof

Complete, released as 0.0.1. A minimum viable compiler that validates the central idea with six small programs: the examples. Lexer and parser, resolver, type checker and borrow analysis, the println! intrinsic, mod resolving to .vr or .rs files, import of top-level pub fn signatures from Rust modules, a Rust backend writing a Cargo project under target/varyk/, diagnostics with codes and fix-its, --message-format=json, and the varyk check, build, and run commands.

Milestone 2: enums, matching, methods, and collections

Complete, released as 0.0.2. The language core a small program needs: enums with unit and tuple variants, match on enums, Option, and Result, with a forgotten variant caught by Varyk before cargo runs, for over ranges and Vec, impl blocks with self and mut self methods, Option, Result, and Vec with a small table of methods and indexing, usize, ?, format! and vec!, s.clone() as the one explicit string copy, and the rule that a name taken from part of a value cannot outlive a change to the whole. Six more example programs.

Milestone 3: packages and interop

Complete, released as 0.1.0. Varyk code never names a crate; a dependency is used from a .rs facade in the same package. Cargo.toml as the package manifest, with src/main.vr or src/lib.vr as the root, edition 2024, and [package.metadata.varyk] reserved; Cargo dependencies reached from .rs facades, with Cargo.lock shared with cargo; nested modules and mod.vr directories, pub mod, and use for paths inside the package; field-level pub; import of Rust structs, their inherent methods, and enums from .rs modules; errors rustc finds in the generated Rust mapped to Varyk source as V0900, the user's own .rs errors and warnings shown at their file, and item-level lint allows on generated code; varyk init with a build.rs so plain cargo build works, and varyk emit, both removed in milestone 5b2; varyk publish, which publishes binaries and libraries as plain Rust crates with the generated .rs and the .vr sources included; and three example packages. This site's pitch, install page, and language reference are part of it. Its release is 0.1.0, because private fields are a breaking change.

Milestone 4: closures, iterators, and patterns

Complete, released as 0.2.0. The language only; the former milestone-4 tooling and interop items moved to milestones 5 and 6. Closures as the arguments of built-in calls, with untyped parameters and shared captures, never a value of their own; iterator chains on stored values, from iter, split, keys, and values through map and filter to collect, count, sum, any, all, and find, or as the head of a for; borrowed return values inferred from the body, with a lifetime in the generated Rust only where elision would not name it; if let and while let; enum variants with named fields, nested, literal, and ..= range patterns, match on numbers, bool, and strings, with exhaustiveness and reachability checked by Varyk; ? on Option; the Option and Result methods and new Vec and string calls, parse included; HashMap; as between number types; Clone and PartialEq derived where every field allows, so .clone() and == work on structs and enums; import of Rust signatures returning &str or &S where lifetime elision names the parameter; a test asserting the language reference mentions every keyword, built-in type, table call, and diagnostic code; and six new example programs.

Milestone 5: batteries for services

Milestone 5 is six milestones. The bar for the whole of it is one golden path: a users API on a database is varyk init, varyk add http sql, one file, and varyk run away, within fifteen minutes of cargo install varyk, and varyk build --release leaves an ordinary native executable. It is met when 5b4 and 5c are done, and promotion waits for it.

Milestone 5a: data, configuration, logging, and tests

Complete, released as 0.3.0. The varyk-std crate, and the varyk-std dependency in every package, whose version and lock varyk check reads; Error, one built-in error type with a message, and parse returning a Result; the attributes #[rename], #[default], #[skip], and #[test]; serde derivation for the types a json or env call reaches; JSON through json::parse and json::stringify; configuration from the environment and .env through env::parse; logging via tracing, with log::debug, info, warn, and error; varyk test, with assert and assert_eq; varyk add, a pass-through to cargo add; and the examples json, config, and logging and the users package. Its release is 0.3.0, because parse returning a Result is a breaking change.

Milestone 5b1: async

Complete, released as 0.4.0. async fn and .await on a built-in multi-threaded tokio runtime, with Send, Sync, and Pin kept out of the surface syntax; started calls, where a call to an async function without .await starts it at once and gives a Task<T>; tasks cancelled when dropped, detach to let one run on its own, Task::all and Task::all_settled to wait on many; Shared<T> for a read-only struct held by many tasks; time::sleep; pub async fn imported from .rs modules; and the examples tasks, fanout, and shared. Both questions it was gated on are answered: the runtime is multi-threaded, and ownership transfer needs no syntax, because the arguments of a started call are the one place a value is handed over. Its release is 0.4.0, because Task, Shared, and time become reserved names.

Milestone 5b2: packages

Complete, released as 0.5.0. A Varyk package named from Varyk code by its Cargo.toml key, with - read as _, to any depth: units::length::add(a, b) calls into the package units, and packages may use packages. Varyk packages compiled by varyk from their .vr sources, each as a crate of its own, never from Rust a publisher shipped or a build script; a Varyk package reached any other way, through [dev-dependencies], as an optional dependency, or through a Rust crate, refused. Packages built only by varyk: Cargo.toml names the .vr root as cargo's target, varyk init writes no build.rs or stub, and varyk emit is removed. The examples' Rust stops calling expect, and the examples route and trip. It also redraws milestone 5: HTTP and the database move to packages in 5b3 and 5b4, because varyk-std stays the small runtime every program has, and anything heavy is a package the writer adds. Official packages are named varyk-* and community packages *-varyk. Its release is 0.5.0, because a package's Cargo.toml must now name its .vr root and varyk emit is gone.

Milestone 5b3: facades and varyk-sql

Complete, released as 0.6.0, with varyk-sql released as 0.1.0. What a .rs facade can say: a function or method with one type parameter standing for any Varyk data type, chosen from where the result goes; a last parameter that takes any number of scalar values (varyk_std::Value); a &'static str parameter that takes only text written in the program; and varyk_std::Error as the error type of a function's result. pub use in a .vr file, and varyk add sql. Then varyk-sql, in its own repository, on sqlx, with SQLite, Postgres, and MySQL each a cargo feature: connect and connect_with, migrate, begin and commit, and on a pool or a transaction one, first, all, and run, each taking the query and its values; rows read into structs by column name; each database's own placeholders, passed through (since varyk-sql 0.4.0, released after milestone 5, $1, $2, and so on work on every database, and ? still works on SQLite and MySQL); the query text a literal, so a query built from input is a compile error; and no secret in an error message. The Serialize half of the type parameter, for sending a Varyk value out, moves to 5b4, where the HTTP client needs it.

Milestone 5b4: varyk-http and the golden path

Complete, released as 0.7.0, with varyk-http released as 0.1.0. The compiler: a route table, the App of the varyk-http package known to the compiler by its crate name; get, post, put, patch, and delete routes with {name} segments; a handler's parameters bound by name to the path and the query string, and by type to the JSON body, to the state (a Shared<T>), and to the package's own types; the return value as the response, None as 404, and http::Response for a custom status and headers; every route checked against its handler by varyk check; before, before_on, and after hooks, and app.request for tests; Error carrying an optional status, set by Error::with_status and the http:: constructors written over it, where an error without one is a 500 whose message is logged and not sent; a .rs function with a type parameter &T: Serialize in a parameter (moved from 5b3), and a .rs function returning varyk_std::Error; and varyk add http sql, several official packages in one call. Then varyk-http, in its own repository: the server on axum and tower-http, with tracing, a body limit, a timeout, panic containment, and graceful shutdown on by default, and CORS, compression, metrics, the address (127.0.0.1 unless set), the limits, and a maximum of requests in flight by one call; cookies with secure defaults and Response::file; the client on reqwest with rustls; WebSockets, server-sent events, and multipart uploads, text and files until a bytes type exists; and the users API on varyk-sql as its demo, with the fifteen-minute path in its README. varyk-sql 0.2.0 ships with it, on the same varyk-std. Still to come, as its own work in its own repository: an agent evaluation, the examples written by a model from the language reference alone with pass rates published, before any page claims that agents write Varyk well. After 5b4 come the next packages.

Milestone 5c: time, ids, and bytes

Complete, released as 0.8.0, with varyk-sql released as 0.3.0 and varyk-http as 0.2.0. What a production API needs that the language lacked, so that the users API does not ship created_at as a string. The compiler: three built-in types, reserved names as Error is. Time, one point in time in UTC to the microsecond: now, from_iso, from_unix, from_unix_micros, to_iso, to_unix, to_unix_micros, add_seconds, seconds_since, parse, comparison, and RFC 3339 in JSON and env. Uuid: new, a time-ordered version 7, v7, v4, the random one by name, parse, a map key, and the hyphenated form in JSON and env. Bytes, immutable: from_text, from_base64, to_text, to_base64, len, is_empty, and base64 in JSON. The three in trailing values, route parameters (Time and Uuid), and facade signatures; varyk-std 0.8; and the example records. Then the packages, each in its own repository: varyk-sql 0.3 drops sqlx's Any driver for concrete pools, and stores the three types as native columns, timestamptz, uuid, and bytea on Postgres; varyk-http 0.2 reads Time and Uuid path and query parameters, and adds bytes bodies, uploads, and binary WebSocket messages, and bytes for its client, with created_at: Time in its users demo. With both, 5b4 and 5c are done, and milestone 5's bar is met. A calendar date, a duration, and time zones are not in it; each waits for a program that needs it.

The next packages

Not a milestone: packages that came after milestone 5, each in its own repository and released on its own.

varyk-redis is next.

Milestone 6: tooling and beyond

In progress, and not scheduled.

Still planned: varyk fmt, a deterministic formatter on varyk-syntax; the rest of the language server, hover, go-to-definition, and completion, which need error recovery in the parser; nested modules in .rs files; import of Rust tuple and unit structs; Debug on imported Rust structs, with a {:?} placeholder; and a decision on a native backend. Direct import of a published Varyk library from Varyk, once listed here, arrived in milestone 5b2.

Unscheduled

Declaring generics, traits, and attributes of your own in Varyk code, and using a Rust crate directly from Varyk code, with no facade .rs module in between. Each waits on an open question in the specification; the four attributes milestone 5a added are the compiler's own, and only the compiler defines attributes. Using a crate directly is an experiment for after traits exist, because most crate APIs are generic; the facade rule stands until that experiment says otherwise. TOML is unscheduled too, beside the rest of the cuts the language reference lists under "Not in milestone 5c": nothing on the golden path needs it, and the same machinery adds it later. Also unscheduled: Box, until a program needs a recursive type that Vec or HashMap cannot hold, and the rest of the milestone-4 cut list, a character type, closures as values, tuples, HashSet, and the remaining iterator adapters. .rs signatures naming Varyk-declared types moved here from milestone 5b2, because the type parameter of milestone 5b3 makes them unnecessary for what a facade needs. JWT verification and password hashing are facades over jsonwebtoken and argon2 in the service that needs them, to become packages if people keep writing the same facade. A document literal in the language, with values written inline, for MongoDB and JSON, is unscheduled too: varyk-mongo builds its documents from structs until then, and the literal's shape is an open question. So is {name} capture in println! and format!, the Rust 1.58 form, inside the {} syntax the language has.