<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Violet Programming Language</title><link>/</link><description>Recent content on Violet Programming Language</description><generator>Hugo</generator><language>en-GB</language><lastBuildDate>Tue, 14 Jul 2026 18:30:10 +0200</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml"/><item><title>Quickstart</title><link>/docs/quickstart/</link><pubDate>Wed, 03 May 2023 22:37:22 +0100</pubDate><guid>/docs/quickstart/</guid><description>&lt;p&gt;Violet is a systems programming language that combines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zig&amp;rsquo;s&lt;/strong&gt; manual allocation philosophy, comptime metaprogramming, fast compile times, and simplicity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rust&amp;rsquo;s&lt;/strong&gt; interfaces (traits), generics, affine type system, and operator overloading&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pascal&amp;rsquo;s&lt;/strong&gt; readability, keyword conventions, and syntactic clarity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Violet targets embedded systems, operating systems, games, servers, and any domain where control over memory and performance is essential. It provides memory safety without a borrow checker through a combination of linear types, scope-tagged pointers, and explicit allocator discipline.&lt;/p&gt;</description></item><item><title>Full Language Specification</title><link>/docs/full-reference/</link><pubDate>Wed, 03 May 2023 22:37:22 +0100</pubDate><guid>/docs/full-reference/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Design phase. Bootstrap compiler in progress (Zig).
Items marked &lt;strong&gt;[TBD]&lt;/strong&gt; are accepted in principle but not yet formally specified or implemented.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction &lt;a href="#introduction" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Violet is a systems programming language that combines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zig&amp;rsquo;s&lt;/strong&gt; manual allocation philosophy, comptime metaprogramming, fast compile times, and simplicity&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rust&amp;rsquo;s&lt;/strong&gt; interfaces (traits), generics, affine type system, and operator overloading&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pascal&amp;rsquo;s&lt;/strong&gt; readability, keyword conventions, and syntactic clarity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Violet targets embedded systems, operating systems, games, servers, and any domain where control over memory and performance is essential. It provides memory safety without a borrow checker through a combination of linear types, scope-tagged pointers, and explicit allocator discipline.&lt;/p&gt;</description></item><item><title>Chapter 1: Hello Violet</title><link>/docs/reference/hello-violet/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/hello-violet/</guid><description>&lt;p&gt;Every Violet program starts with a &lt;code&gt;main&lt;/code&gt; function. The simplest possible program:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3cd06ce" class="language- "&gt;
 &lt;code&gt;fn main(): void {
 debug.print(&amp;#34;Hello, Violet!\n&amp;#34;);
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;With access to process context — arguments, environment, allocator, scheduler:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="c823310" class="language- "&gt;
 &lt;code&gt;const process = import(&amp;#34;std/process&amp;#34;);
const debug = import(&amp;#34;std/debug&amp;#34;);

fn main(ctx: process.Context): !void {
 debug.print(&amp;#34;Hello, {}!\n&amp;#34;, .{ctx.args[0]});
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;code&gt;!void&lt;/code&gt; means this function can fail. The &lt;code&gt;!&lt;/code&gt; prefix is Violet&amp;rsquo;s error union syntax — more on this in Chapter 7.&lt;/p&gt;</description></item><item><title>Chapter 2: Variables and Bindings</title><link>/docs/reference/variables-and-bindings/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/variables-and-bindings/</guid><description>&lt;h3 id="mutable-and-immutable"&gt;Mutable and Immutable &lt;a href="#mutable-and-immutable" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d991770" class="language- "&gt;
 &lt;code&gt;const pi: f64 = 3.14159; -- immutable, must be initialized
var count: i32 = 0; -- mutable

count := count &amp;#43; 1; -- reassignment uses :=
count &amp;#43;= 1; -- compound assignment&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;:=&lt;/code&gt; for reassignment, &lt;code&gt;=&lt;/code&gt; for initialization and equality comparison.&lt;/strong&gt; This comes from Pascal. &lt;code&gt;=&lt;/code&gt; in expression position is always equality — there is no &lt;code&gt;==&lt;/code&gt; in Violet.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="0d5fd02" class="language- "&gt;
 &lt;code&gt;if count = 5 { -- = means equality here
 debug.print(&amp;#34;five!\n&amp;#34;);
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="type-inference"&gt;Type Inference &lt;a href="#type-inference" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="1b3c643" class="language- "&gt;
 &lt;code&gt;var x = 42; -- inferred as i32
var s = &amp;#34;hello&amp;#34;; -- inferred as []const u8
var f = 3.14; -- inferred as f64&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="constants"&gt;Constants &lt;a href="#constants" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Constants are compile-time values. They can be used anywhere a comptime value is expected:&lt;/p&gt;</description></item><item><title>Chapter 3: Primitive Types</title><link>/docs/reference/primitive-types/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/primitive-types/</guid><description>&lt;h3 id="integers"&gt;Integers &lt;a href="#integers" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="f346a20" class="language- "&gt;
 &lt;code&gt;var a: i8 = -128;
var b: u8 = 255;
var c: i32 = -2_147_483_648; -- underscores for readability
var d: u64 = 18_446_744_073_709_551_615;
var e: isize = -1; -- pointer-sized signed
var f: usize = 0; -- pointer-sized unsigned&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Integer overflow always panics&lt;/strong&gt; with plain arithmetic. Use explicit operators for other behavior:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3d394b3" class="language- "&gt;
 &lt;code&gt;var x: u8 = 255;
var wrapped = x &amp;#43;% 1; -- wrapping: 0
var saturated = x &amp;#43;| 1; -- saturating: 255
-- x &amp;#43; 1 would panic&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="floats"&gt;Floats &lt;a href="#floats" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5afda7d" class="language- "&gt;
 &lt;code&gt;var a: f32 = 3.14;
var b: f64 = 2.718281828;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="booleans"&gt;Booleans &lt;a href="#booleans" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="486e4c9" class="language- "&gt;
 &lt;code&gt;var t: bool = true;
var f: bool = false;

if t and not f {
 debug.print(&amp;#34;yes\n&amp;#34;);
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Logical operators are words: &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;, &lt;code&gt;xor&lt;/code&gt;. Bitwise operators are symbols: &lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;~&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Chapter 4: Functions</title><link>/docs/reference/functions/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/functions/</guid><description>&lt;h3 id="basic-functions"&gt;Basic Functions &lt;a href="#basic-functions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="f165f4f" class="language- "&gt;
 &lt;code&gt;fn add(a: i32, b: i32): i32 {
 return a &amp;#43; b;
}

fn greet(name: []const u8) { -- no return type = void
 debug.print(&amp;#34;hello, {}\n&amp;#34;, .{name});
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="multiple-return-values"&gt;Multiple Return Values &lt;a href="#multiple-return-values" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Violet uses anonymous structs for multiple returns:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7b40e8c" class="language- "&gt;
 &lt;code&gt;fn minMax(items: []const i32): struct { min: i32, max: i32 } {
 var min = items[0];
 var max = items[0];
 for item in items[1..] {
 if item.* &amp;lt; min { min := item.*; }
 if item.* &amp;gt; max { max := item.*; }
 }
 return .{ .min = min, .max = max };
}

var result = minMax(&amp;amp;.{3, 1, 4, 1, 5, 9});
debug.print(&amp;#34;min={} max={}\n&amp;#34;, .{result.min, result.max});&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Destructure at the call site:&lt;/p&gt;</description></item><item><title>Chapter 5: Control Flow</title><link>/docs/reference/control-flow/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/control-flow/</guid><description>&lt;h3 id="loops"&gt;Loops &lt;a href="#loops" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="461b5ee" class="language- "&gt;
 &lt;code&gt;-- for: iterate a collection
for item in items {
 process(item);
}

-- for with index
for item, i in items {
 debug.print(&amp;#34;[{}] {}\n&amp;#34;, .{i, item});
}

-- for over a range
for i in 0..10 { -- exclusive: 0, 1, ..., 9
 debug.print(&amp;#34;{}\n&amp;#34;, .{i});
}

for i in 0..=10 { -- inclusive: 0, 1, ..., 10
 debug.print(&amp;#34;{}\n&amp;#34;, .{i});
}

-- while: condition-based
var n: i32 = 1;
while n &amp;lt; 100 {
 n *= 2;
}

-- loop: infinite, exit with break
var count: i32 = 0;
loop {
 count &amp;#43;= 1;
 if count = 10 { break; }
}

-- loop with a value
var found = loop {
 var candidate = try nextCandidate();
 if candidate.valid { break candidate; }
};

-- repeat...until: post-condition (runs at least once)
var input: []const u8 = &amp;#34;&amp;#34;;
repeat {
 input = try readLine();
} until input != &amp;#34;&amp;#34;;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="multi-sequence-for"&gt;Multi-sequence For &lt;a href="#multi-sequence-for" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="8a7e258" class="language- "&gt;
 &lt;code&gt;for x, y in xs, ys {
 debug.print(&amp;#34;{} {}\n&amp;#34;, .{x, y});
}

-- with shared index
for x, y, i in xs, ys {
 debug.print(&amp;#34;[{}] {} {}\n&amp;#34;, .{i, x, y});
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="break-and-continue"&gt;Break and Continue &lt;a href="#break-and-continue" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="e8c3237" class="language- "&gt;
 &lt;code&gt;outer: for i in 0..10 {
 for j in 0..10 {
 if i &amp;#43; j = 15 { break outer; }
 }
}

for item in items {
 if item.* = 0 { continue; }
 process(item);
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;</description></item><item><title>Chapter 6: Structs</title><link>/docs/reference/structs/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/structs/</guid><description>&lt;h3 id="defining-and-using-structs"&gt;Defining and Using Structs &lt;a href="#defining-and-using-structs" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="3598138" class="language- "&gt;
 &lt;code&gt;type Point = struct {
 x: f32,
 y: f32,
};

var p = Point { .x = 1.0, .y = 2.0 };
var p: Point = .{ .x = 1.0, .y = 2.0 }; -- type inferred from context

debug.print(&amp;#34;({}, {})\n&amp;#34;, .{p.x, p.y});&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="field-defaults"&gt;Field Defaults &lt;a href="#field-defaults" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="032f0b8" class="language- "&gt;
 &lt;code&gt;type Config = struct {
 host: []const u8 = &amp;#34;localhost&amp;#34;,
 port: u16 = 8080,
 timeout: u32 = 30,
 debug: bool = false,
};

var cfg = Config { .host = &amp;#34;example.com&amp;#34; };
-- port, timeout, debug use their defaults&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="methods"&gt;Methods &lt;a href="#methods" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Methods go in &lt;code&gt;impl&lt;/code&gt; blocks. Receivers use &lt;code&gt;*self&lt;/code&gt; (mutable), &lt;code&gt;*const self&lt;/code&gt; (immutable), or &lt;code&gt;self&lt;/code&gt; (consuming):&lt;/p&gt;</description></item><item><title>Chapter 7: Enums and Unions</title><link>/docs/reference/enums-and-unions/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/enums-and-unions/</guid><description>&lt;h3 id="enums--fieldless-variants"&gt;Enums — Fieldless Variants &lt;a href="#enums--fieldless-variants" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="beb562c" class="language- "&gt;
 &lt;code&gt;type Direction = enum {
 North,
 South,
 East,
 West,
};

var d = Direction.North;

-- enums are always Copy
case d {
 .North =&amp;gt; debug.print(&amp;#34;going north\n&amp;#34;),
 .South =&amp;gt; debug.print(&amp;#34;going south\n&amp;#34;),
 .East =&amp;gt; debug.print(&amp;#34;going east\n&amp;#34;),
 .West =&amp;gt; debug.print(&amp;#34;going west\n&amp;#34;),
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="unions--tagged-variants-with-data"&gt;Unions — Tagged Variants With Data &lt;a href="#unions--tagged-variants-with-data" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7027bcc" class="language- "&gt;
 &lt;code&gt;type Shape = union {
 Circle { radius: f32 },
 Rectangle { width: f32, height: f32 },
 Triangle { base: f32, height: f32 },
 Point, -- unit variant, no data
};

fn area(shape: Shape): f32 {
 return case shape {
 .Circle { radius } =&amp;gt; 3.14159 * radius * radius,
 .Rectangle { width, height } =&amp;gt; width * height,
 .Triangle { base, height } =&amp;gt; 0.5 * base * height,
 .Point =&amp;gt; 0.0,
 };
}

var s = Shape.Circle { .radius = 5.0 };
debug.print(&amp;#34;area: {}\n&amp;#34;, .{area(s)});&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="optionals--t"&gt;Optionals — &lt;code&gt;?T&lt;/code&gt; &lt;a href="#optionals--t" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;An optional is either a value or nothing:&lt;/p&gt;</description></item><item><title>Chapter 8: Error Handling</title><link>/docs/reference/error-handling/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/error-handling/</guid><description>&lt;h3 id="defining-error-types"&gt;Defining Error Types &lt;a href="#defining-error-types" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="1ac9d2b" class="language- "&gt;
 &lt;code&gt;type ParseError = error {
 InvalidChar { ch: u8, pos: usize },
 UnexpectedEof,
 Overflow { value: i64 },
};&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="returning-errors"&gt;Returning Errors &lt;a href="#returning-errors" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="dcdb531" class="language- "&gt;
 &lt;code&gt;fn parseU8(s: []const u8): ParseError!u8 {
 if s.len = 0 {
 return error.UnexpectedEof;
 }

 var result: u8 = 0;
 for byte, i in s.bytes() {
 if byte &amp;lt; &amp;#39;0&amp;#39; or byte &amp;gt; &amp;#39;9&amp;#39; {
 return error.InvalidChar { .ch = byte, .pos = i };
 }
 result = result *% 10 &amp;#43;% (byte - &amp;#39;0&amp;#39;);
 }
 return result;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="handling-errors"&gt;Handling Errors &lt;a href="#handling-errors" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7f01fe2" class="language- "&gt;
 &lt;code&gt;-- try: propagate if same error type
var n = try parseU8(input);

-- catch: handle inline
var n = parseU8(input) catch |e| {
 case e {
 .InvalidChar { ch, pos } =&amp;gt; {
 debug.print(&amp;#34;bad char &amp;#39;{}&amp;#39; at {}\n&amp;#34;, .{ch, pos});
 return error.InvalidChar { .ch = ch, .pos = pos };
 },
 .UnexpectedEof =&amp;gt; return error.UnexpectedEof,
 .Overflow { value } =&amp;gt; {
 debug.print(&amp;#34;overflow: {}\n&amp;#34;, .{value});
 return 255;
 },
 }
};

-- orelse: provide default on error
var n = parseU8(input) catch 0;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="wrapping-errors--wrap"&gt;Wrapping Errors — &lt;code&gt;wrap&lt;/code&gt; &lt;a href="#wrapping-errors--wrap" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;When your function has a different error type:&lt;/p&gt;</description></item><item><title>Chapter 9: Memory and Ownership</title><link>/docs/reference/memory-and-ownership/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/memory-and-ownership/</guid><description>&lt;h3 id="allocators"&gt;Allocators &lt;a href="#allocators" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Every allocation in Violet is explicit. You choose the allocator:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="f5417ed" class="language- "&gt;
 &lt;code&gt;const alloc_mod = import(&amp;#34;std/alloc&amp;#34;);

fn main(ctx: process.Context): !void {
 -- general purpose allocator
 var gpa = alloc_mod.GPA::new();
 defer gpa.deinit();
 var alloc = gpa.allocator();

 -- allocate memory
 var buf = try alloc.alloc(u8, 1024);
 defer alloc.free(buf);

 -- allocate a single value
 var ptr = try alloc.create(i32);
 defer alloc.destroy(ptr);
 ptr.* := 42;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="using--implicit-allocator-threading"&gt;&lt;code&gt;using&lt;/code&gt; — Implicit Allocator Threading &lt;a href="#using--implicit-allocator-threading" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;When a function uses the same allocator everywhere, &lt;code&gt;using&lt;/code&gt; reduces noise:&lt;/p&gt;</description></item><item><title>Chapter 10: Interfaces</title><link>/docs/reference/interfaces/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/interfaces/</guid><description>&lt;h3 id="defining-an-interface"&gt;Defining an Interface &lt;a href="#defining-an-interface" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="f3303de" class="language- "&gt;
 &lt;code&gt;interface Animal {
 fn name(*const self): []const u8;
 fn sound(*const self): []const u8;
 fn legs(*const self): u32;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="implementing-an-interface"&gt;Implementing an Interface &lt;a href="#implementing-an-interface" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="83e6459" class="language- "&gt;
 &lt;code&gt;type Dog = struct {
 name_: []const u8,
};

type Cat = struct {
 name_: []const u8,
};

provide Animal for Dog {
 fn name(*const self): []const u8 { return self.name_; }
 fn sound(*const self): []const u8 { return &amp;#34;woof&amp;#34;; }
 fn legs(*const self): u32 { return 4; }
}

provide Animal for Cat {
 fn name(*const self): []const u8 { return self.name_; }
 fn sound(*const self): []const u8 { return &amp;#34;meow&amp;#34;; }
 fn legs(*const self): u32 { return 4; }
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="static-dispatch--generics"&gt;Static Dispatch — Generics &lt;a href="#static-dispatch--generics" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5afd310" class="language- "&gt;
 &lt;code&gt;fn describe[A: Animal](animal: *const A) {
 debug.print(&amp;#34;{} says {} and has {} legs\n&amp;#34;,
 .{animal.name(), animal.sound(), animal.legs()});
}

var dog = Dog { .name_ = &amp;#34;Rex&amp;#34; };
var cat = Cat { .name_ = &amp;#34;Whiskers&amp;#34; };

describe(&amp;amp;dog); -- monomorphized for Dog
describe(&amp;amp;cat); -- monomorphized for Cat&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="dynamic-dispatch--dyn"&gt;Dynamic Dispatch — &lt;code&gt;dyn&lt;/code&gt; &lt;a href="#dynamic-dispatch--dyn" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;When you need a collection of different types:&lt;/p&gt;</description></item><item><title>Chapter 11: Generics and Comptime</title><link>/docs/reference/generics-and-comptime/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/generics-and-comptime/</guid><description>&lt;h3 id="generic-functions"&gt;Generic Functions &lt;a href="#generic-functions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7ef2613" class="language- "&gt;
 &lt;code&gt;fn largest[T: Eq](items: []const T): ?*const T {
 if items.len = 0 { return .None; }
 var best = &amp;amp;items[0];
 for item in items[1..] {
 if item.* &amp;gt; best.* { best := item; }
 }
 return best;
}

var numbers = [_]i32{ 3, 1, 4, 1, 5, 9, 2, 6 };
if largest(&amp;amp;numbers) |n| {
 debug.print(&amp;#34;largest: {}\n&amp;#34;, .{n.*});
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="generic-types"&gt;Generic Types &lt;a href="#generic-types" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="a27da64" class="language- "&gt;
 &lt;code&gt;type Stack[T] = struct {
 items: List[T],
};

impl[T] Stack[T] {
 static fn new(): Self {
 return .{ .items = List[T]::new() };
 }

 fn push(*self, alloc: Allocator, val: T): !void {
 try self.items.push(alloc, val);
 }

 fn pop(*self): ?T {
 return self.items.pop();
 }

 fn peek(*const self): ?*const T {
 if self.items.len() = 0 { return .None; }
 return self.items.get(self.items.len() - 1);
 }

 fn isEmpty(*const self): bool {
 return self.items.isEmpty();
 }
}

provide Destroy for Stack[T] {
 type Args = Allocator;
 fn deinit(*self, alloc: Allocator) {
 self.items.deinit(alloc);
 }
}

var stack = Stack[i32]::new();
defer stack.deinit(alloc);

try stack.push(alloc, 1);
try stack.push(alloc, 2);
try stack.push(alloc, 3);

while stack.pop() -&amp;gt; val {
 debug.print(&amp;#34;{}\n&amp;#34;, .{val});
}
-- prints: 3, 2, 1&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="comptime-functions"&gt;Comptime Functions &lt;a href="#comptime-functions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;When you need to inspect type structure:&lt;/p&gt;</description></item><item><title>Chapter 12: Closures</title><link>/docs/reference/closures/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/closures/</guid><description>&lt;h3 id="basic-closures"&gt;Basic Closures &lt;a href="#basic-closures" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d53ab29" class="language- "&gt;
 &lt;code&gt;-- [capture_list](params): ReturnType { body }
var add = [](x: i32, y: i32): i32 { return x &amp;#43; y; };
debug.print(&amp;#34;{}\n&amp;#34;, .{add(3, 4)}); -- 7

-- capturing from outer scope
var offset: i32 = 10;
var addOffset = [offset](x: i32): i32 { return x &amp;#43; offset; };
debug.print(&amp;#34;{}\n&amp;#34;, .{addOffset(5)}); -- 15&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="moving-into-closures"&gt;Moving Into Closures &lt;a href="#moving-into-closures" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Non-&lt;code&gt;Copy&lt;/code&gt; values must be moved:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="c58324d" class="language- "&gt;
 &lt;code&gt;var name = try String::from(alloc, &amp;#34;World&amp;#34;);
var greet = [move name](): void {
 debug.print(&amp;#34;Hello, {}!\n&amp;#34;, .{name});
};
-- name is gone from this scope
greet();&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="closures-as-parameters"&gt;Closures as Parameters &lt;a href="#closures-as-parameters" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="c333d49" class="language- "&gt;
 &lt;code&gt;fn applyTwice[T](f: fn(*mut T): void, val: *mut T) {
 f(val);
 f(val);
}

var x: i32 = 0;
applyTwice([&amp;amp;x](_: *mut i32) { x &amp;#43;= 1; }, &amp;amp;x);
debug.print(&amp;#34;{}\n&amp;#34;, .{x}); -- 2&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="closures-with-collections"&gt;Closures With Collections &lt;a href="#closures-with-collections" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="343ffbc" class="language- "&gt;
 &lt;code&gt;fn filter[T](items: []T, pred: fn(*const T): bool, alloc: Allocator): ![]T {
 var result = List[T]::new();
 errdefer result.deinit(alloc);

 for item in items {
 if pred(item) {
 try result.push(alloc, item.*);
 }
 }
 return result.intoSlice();
}

var numbers = [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 };
var evens = try filter(&amp;amp;numbers, [](n: *const i32): bool {
 return n.* % 2 = 0;
}, alloc);
defer alloc.free(evens);
-- evens: { 2, 4, 6, 8 }&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;</description></item><item><title>Chapter 13: Concurrency</title><link>/docs/reference/concurrency/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/concurrency/</guid><description>&lt;h3 id="the-io-scheduler"&gt;The &lt;code&gt;Io&lt;/code&gt; Scheduler &lt;a href="#the-io-scheduler" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Functions that may suspend take an explicit &lt;code&gt;*Io&lt;/code&gt; parameter. This makes suspension visible at every call site — critical for lock safety:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="e045ba5" class="language- "&gt;
 &lt;code&gt;const io_mod = import(&amp;#34;std/async&amp;#34;);
const net = import(&amp;#34;std/net&amp;#34;);

-- provably synchronous: no *Io parameter
fn computeHash(data: []const u8): u64 {
 return fnv1a(data);
}

-- may suspend: takes *Io
fn fetchData(io: *Io, url: []const u8, alloc: Allocator): ![]u8 {
 var conn = try net.TcpStream::connect(io, url);
 defer conn.deinit();
 return try conn.readAll(io, alloc);
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="structured-concurrency"&gt;Structured Concurrency &lt;a href="#structured-concurrency" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The safest way to run concurrent tasks — all tasks are joined when the scope exits:&lt;/p&gt;</description></item><item><title>Chapter 14: C FFI (Foreign Function Interface)</title><link>/docs/reference/c-ffi/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/c-ffi/</guid><description>&lt;h3 id="calling-c-functions"&gt;Calling C Functions &lt;a href="#calling-c-functions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5748612" class="language- "&gt;
 &lt;code&gt;const c = #cImport({
 #cInclude(&amp;#34;stdio.h&amp;#34;);
 #cInclude(&amp;#34;string.h&amp;#34;);
});

fn countOccurrences(haystack: []const u8, needle: u8): usize {
 var count: usize = 0;
 for b in haystack {
 if b.* = needle { count &amp;#43;= 1; }
 }
 return count;
}

fn main(): void {
 -- calling C functions requires unsafe
 unsafe {
 _ = c.printf(&amp;#34;Hello from C!\n&amp;#34;);
 }
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="exporting-violet-functions-to-c"&gt;Exporting Violet Functions to C &lt;a href="#exporting-violet-functions-to-c" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="9687cfb" class="language- "&gt;
 &lt;code&gt;-- Violet function callable from C
export fn violetAdd(a: i32, b: i32): i32 {
 return a &amp;#43; b;
}

-- with custom C name
export(&amp;#34;violet_compute&amp;#34;) fn compute(data: [*c]const u8, len: usize): u64 {
 unsafe {
 return hashBytes(data[0..len]);
 }
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Generate a C header: &lt;code&gt;violet build --emit-header mylib.h&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Chapter 15: Complete Example Program</title><link>/docs/reference/complete-example/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/complete-example/</guid><description>&lt;p&gt;Putting it all together: a simple in-memory key-value store with a TCP interface.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5ea54fe" class="language- "&gt;
 &lt;code&gt;const process = import(&amp;#34;std/process&amp;#34;);
const io_mod = import(&amp;#34;std/async&amp;#34;);
const net = import(&amp;#34;std/net&amp;#34;);
const sync = import(&amp;#34;std/sync&amp;#34;);
const collections = import(&amp;#34;std/collections&amp;#34;);
const fmt = import(&amp;#34;std/fmt&amp;#34;);

-- the store: a thread-safe HashMap
type Store = struct {
 data: sync.Mutex[collections.HashMap[String, String]],
};

impl Store {
 static fn new(alloc: Allocator): !Self {
 return .{
 .data = sync.Mutex[collections.HashMap[String, String]]::new(
 collections.HashMap[String, String]::new()
 ),
 };
 }

 fn get(*const self, key: []const u8): ?String {
 var guard = self.data.lock();
 return case guard.*.get(key) {
 .Some { val } =&amp;gt; .Some { .value = val.clone() },
 .None =&amp;gt; .None,
 };
 }

 fn set(*self, alloc: Allocator, key: String, val: String): !void {
 var guard = self.data.lock();
 try guard.*.set(alloc, key, val);
 }

 fn delete(*self, key: []const u8): bool {
 var guard = self.data.lock();
 return guard.*.remove(key) != .None;
 }
}

-- parse and handle one command
fn handleCommand(
 io: *Io,
 store: *Store,
 alloc: Allocator,
 line: []const u8,
 conn: *net.TcpStream,
): !void {
 var parts = splitLine(line);

 case parts[0] {
 &amp;#34;GET&amp;#34; if parts.len = 2 =&amp;gt; {
 if store.get(parts[1]) -&amp;gt; val {
 defer val.deinit(alloc);
 try conn.write(io, val.asSlice());
 try conn.write(io, &amp;#34;\n&amp;#34;);
 } else {
 try conn.write(io, &amp;#34;NOT_FOUND\n&amp;#34;);
 }
 },
 &amp;#34;SET&amp;#34; if parts.len = 3 =&amp;gt; {
 var key = try String::from(alloc, parts[1]);
 errdefer key.deinit(alloc);
 var val = try String::from(alloc, parts[2]);
 errdefer val.deinit(alloc);

 try store.set(alloc, key, val);
 try conn.write(io, &amp;#34;OK\n&amp;#34;);
 },
 &amp;#34;DEL&amp;#34; if parts.len = 2 =&amp;gt; {
 if store.delete(parts[1]) {
 try conn.write(io, &amp;#34;DELETED\n&amp;#34;);
 } else {
 try conn.write(io, &amp;#34;NOT_FOUND\n&amp;#34;);
 }
 },
 _ =&amp;gt; {
 try conn.write(io, &amp;#34;ERR unknown command\n&amp;#34;);
 },
 }
}

-- handle one connection
fn handleConn(
 io: *Io,
 store: *Store,
 alloc: Allocator,
 conn: net.TcpStream,
): !void {
 defer conn.deinit();

 var buf: [4096]u8 = #undefined;

 loop {
 var n = try conn.read(io, &amp;amp;buf);
 if n = 0 { break; } -- connection closed

 var line = trim(buf[0..n]);
 handleCommand(io, store, alloc, line, &amp;amp;conn) catch |e| {
 var msg = try fmt.format(alloc, &amp;#34;ERR {}\n&amp;#34;, .{e});
 defer alloc.free(msg);
 conn.write(io, msg) catch {};
 };
 }
}

fn main(ctx: process.Context): !void {
 using ctx.alloc;

 var io = try io_mod.IoUringScheduler::new(ctx.alloc, 1024);
 defer io.deinit(ctx.alloc);

 -- shared store, Arc for thread safety
 var store = Arc[Store]::new(ctx.alloc, try Store::new(ctx.alloc));
 defer store.deinit(ctx.alloc);

 var listener = try net.TcpListener::bind(&amp;amp;io, &amp;#34;0.0.0.0:6379&amp;#34;);
 defer listener.deinit();

 debug.print(&amp;#34;Listening on :6379\n&amp;#34;);

 -- structured concurrency: all connections joined on exit
 try io.scope([](s: *IoScope) {
 while true {
 var conn = try listener.accept(&amp;amp;io);
 var s_clone = store.clone(ctx.alloc);

 try s.spawn([move conn, move s_clone](_: *IoScope) {
 handleConn(&amp;amp;io, s_clone.*, ctx.alloc, conn) catch |e| {
 debug.print(&amp;#34;connection error: {}\n&amp;#34;, .{e});
 };
 s_clone.deinit(ctx.alloc);
 });
 }
 });
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;</description></item><item><title>Chapter 16: Quick Reference</title><link>/docs/reference/quick-reference/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/reference/quick-reference/</guid><description>&lt;h3 id="operators"&gt;Operators &lt;a href="#operators" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="82ffea7" class="language- "&gt;
 &lt;code&gt;-- arithmetic
&amp;#43; - * / % -- checked (panic on overflow)
&amp;#43;% -% *% -- wrapping
&amp;#43;| -| *| -- saturating

-- logical (word)
and or not xor

-- bitwise (symbol)
&amp;amp; | ~ ^ &amp;lt;&amp;lt; &amp;gt;&amp;gt;

-- comparison
= != &amp;lt; &amp;gt; &amp;lt;= &amp;gt;= -- = is equality (not ==)

-- assignment
:= -- reassignment
&amp;#43;= -= *= /= etc. -- compound

-- type operators
is as as? -- type check, cast, safe cast

-- error/optional
try -- propagate error
? -- propagate None
orelse -- provide default
catch -- handle error

-- pointer
.* -- dereference
&amp;amp; -- address-of&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="common-patterns"&gt;Common Patterns &lt;a href="#common-patterns" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="c8e8deb" class="language- "&gt;
 &lt;code&gt;-- defer cleanup
var x = try acquire();
defer x.release();

-- errdefer (error path only)
var buf = try alloc.alloc(u8, n);
errdefer alloc.free(buf);

-- optional unwrap
if maybe -&amp;gt; val { use(val); }
var n = maybe orelse 0;

-- error propagation
var n = try riskyOp();
var n = riskyOp() catch 0;
var n = riskyOp() catch wrap;

-- comptime type check
inline if #implements(T, Clone) { ... }
inline for field in #typeInfo(T).fields { ... }&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h3 id="import-paths"&gt;Import Paths &lt;a href="#import-paths" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="f385590" class="language- "&gt;
 &lt;code&gt;-- files are namespaces, . is field access
const std = import(&amp;#34;std&amp;#34;);
const List = std.collections.List;
const Io = import(&amp;#34;std/io&amp;#34;).Io;

-- re-export from your module
pub const HashMap = import(&amp;#34;std/collections/hashmap&amp;#34;).HashMap;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;</description></item><item><title>Packaging System</title><link>/docs/build-system/packages/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/build-system/packages/</guid><description>&lt;h2 id="terminology"&gt;Terminology &lt;a href="#terminology" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&amp;ldquo;Palette&amp;rdquo; — Violet&amp;rsquo;s name for a package. A palette is a collection of colors; your dependencies are the colors in your project&amp;rsquo;s palette.&lt;/p&gt;
&lt;h2 id="manifest"&gt;Manifest &lt;a href="#manifest" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Every package has a manifest file, called &lt;code&gt;palette.kdl&lt;/code&gt;. This file declares the package information and dependencies.&lt;/p&gt;
&lt;p&gt;For a full KDL reference, refer to &lt;a href="https://kdl.dev/" rel="external" target="_blank"&gt;https://kdl.dev/&lt;svg width="16" height="16" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"&gt;&lt;path fill="currentColor" d="M14 5c-.552 0-1-.448-1-1s.448-1 1-1h6c.552 0 1 .448 1 1v6c0 .552-.448 1-1 1s-1-.448-1-1v-3.586l-7.293 7.293c-.391.39-1.024.39-1.414 0-.391-.391-.391-1.024 0-1.414l7.293-7.293h-3.586zm-9 2c-.552 0-1 .448-1 1v11c0 .552.448 1 1 1h11c.552 0 1-.448 1-1v-4.563c0-.552.448-1 1-1s1 .448 1 1v4.563c0 1.657-1.343 3-3 3h-11c-1.657 0-3-1.343-3-3v-11c0-1.657 1.343-3 3-3h4.563c.552 0 1 .448 1 1s-.448 1-1 1h-4.563z"/&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Allocator</title><link>/docs/standard-library/core/allocator/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/standard-library/core/allocator/</guid><description>&lt;p&gt;Module: &lt;code&gt;std/allocator&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The allocator module provides the &lt;code&gt;Allocator&lt;/code&gt; interface, which describes the functionality
of allocators used in Violet.&lt;/p&gt;
&lt;h2 id="definition"&gt;Definition &lt;a href="#definition" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This is the public allocator interface, which users derive an allocator from directly.&lt;/p&gt;
&lt;p&gt;Allocators can implement this interface and be used for all forms of memory allocation.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="e561d1e" class="language- "&gt;
 &lt;code&gt;interface Allocator {
 -- Create a new pointer of type
 fn create[T](self: *Self): !*T;

 -- Create a new buffer of type with n elements
 fn alloc(self: *Self, n: usize): []T;

 -- Destroy an allocated type
 fn destroy[T](self: *Self, value: *T);

 -- Destroy an allocated buffer
 fn free[T](self: *Self, value: []T);

 -- Resize an existing allocation
 fn resize[T](self: *Self, value: T, new_size: usize): bool;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;</description></item><item><title>Build Script</title><link>/docs/build-system/build-script/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/build-system/build-script/</guid><description>&lt;p&gt;Calling &lt;code&gt;violet build&lt;/code&gt; starts the compilation process. The &lt;code&gt;build.vi&lt;/code&gt; file is
read, which provides build instructions.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5c3a24e" class="language- "&gt;
 &lt;code&gt;const build = import(&amp;#34;std/build&amp;#34;);

fn main(b: *build.Builder) {
 var opts = b.options();
 var mode = opts.enum(&amp;#34;mode&amp;#34;, build.BuildMode, .Debug);

 var exe = b.addExecutable(.{
 .name = &amp;#34;myapp&amp;#34;,
 .root = &amp;#34;src/main.vi&amp;#34;,
 .mode = mode,
 });

 exe.linkSystemLib(&amp;#34;z&amp;#34;);
 exe.libc(.musl);
 exe.addIncludePath(&amp;#34;vendor/mylib/include&amp;#34;);

 b.install(exe);
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;</description></item><item><title>Async I/O</title><link>/docs/standard-library/core/io/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/standard-library/core/io/</guid><description>&lt;p&gt;Module: &lt;code&gt;core/io&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Violet&amp;rsquo;s async model uses an explicit &lt;code&gt;*Io&lt;/code&gt; parameter rather than &lt;code&gt;async/await&lt;/code&gt; keywords. Functions that take &lt;code&gt;*Io&lt;/code&gt; may suspend; functions without it are provably synchronous.&lt;/p&gt;
&lt;h2 id="definitions"&gt;Definitions &lt;a href="#definitions" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="44a7af6" class="language- "&gt;
 &lt;code&gt;interface Io {
 fn waitFd(*self, fd: Fd, event: IoEvent): !void;
 fn sleep(*self, dur: Duration): !void;
 fn yield_(*self): void;
 fn spawnBlocking(*self, alloc: Allocator, work: BoxedBlockingTask): !void;
 fn scope(*self, alloc: Allocator, body: BoxedScopeTask): !void;
 fn spawn(*self, alloc: Allocator, task: BoxedTask): !TaskHandle;
 fn spawnDetached(*self, alloc: Allocator, task: BoxedTask): !void;
 fn waker(*self): Waker;
 fn handle(*self, alloc: Allocator): IoHandle;
 fn run(*self): !void;
 fn shutdown(*self): void;
}

interface IoScope: Io {
 fn spawn(*self, alloc: Allocator, task: BoxedTask): !void;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="usage"&gt;Usage &lt;a href="#usage" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3 id="structured-concurrency-recommended"&gt;Structured Concurrency (Recommended) &lt;a href="#structured-concurrency-recommended" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;


 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="c7a134e" class="language- "&gt;
 &lt;code&gt;fn serveRequests(io: *Io, alloc: Allocator): !void {
 using alloc;

 try io.scope([](s: *IoScope) {
 while true {
 var conn = try acceptConnection(io);
 try s.spawn([move conn](_: *IoScope) {
 try handleConnection(io, conn);
 });
 }
 });
 -- all connection tasks joined before returning
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Inside &lt;code&gt;io.scope&lt;/code&gt;, use &lt;code&gt;s&lt;/code&gt; for everything:&lt;/strong&gt; &lt;code&gt;IoScope&lt;/code&gt; extends &lt;code&gt;Io&lt;/code&gt;, so &lt;code&gt;s.waitFd&lt;/code&gt;, &lt;code&gt;s.sleep&lt;/code&gt;, &lt;code&gt;s.spawn&lt;/code&gt; all work through the scope.&lt;/p&gt;</description></item><item><title>Pascal</title><link>/docs/design-decisions/pascal/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/design-decisions/pascal/</guid><description>&lt;h3 id="word-operators-and-or-not-xor"&gt;Word Operators: &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;, &lt;code&gt;xor&lt;/code&gt; &lt;a href="#word-operators-and-or-not-xor" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; Logical operators are English words. Bitwise operators are symbols.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reason:&lt;/strong&gt; The single most common C mistake is writing &lt;code&gt;&amp;amp;&lt;/code&gt; when you meant &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, or &lt;code&gt;|&lt;/code&gt; when you meant &lt;code&gt;||&lt;/code&gt;. They look nearly identical and silently produce wrong results. Word operators for logic, symbol operators for bitwise — makes the distinction impossible to miss.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="f457279" class="language- "&gt;
 &lt;code&gt;-- logical: words
if x &amp;gt; 0 and y &amp;gt; 0 {
 proceed();
}

if not valid or count = 0 {
 return error.Invalid;
}

if flagA xor flagB { -- exactly one is true
 handleExclusive();
}

-- bitwise: symbols (distinct, cannot be confused)
var flags = a &amp;amp; b; -- AND
var mask = a | b; -- OR
var inv = ~a; -- NOT
var mixed = a ^ b; -- XOR
var shifted = a &amp;lt;&amp;lt; 3;&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;hr&gt;
&lt;h3 id="-for-reassignment--for-equality"&gt;&lt;code&gt;:=&lt;/code&gt; For Reassignment, &lt;code&gt;=&lt;/code&gt; For Equality &lt;a href="#-for-reassignment--for-equality" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; &lt;code&gt;:=&lt;/code&gt; is the only reassignment operator. &lt;code&gt;=&lt;/code&gt; in expression position is always equality comparison. &lt;code&gt;=&lt;/code&gt; in declaration position is initialization.&lt;/p&gt;</description></item><item><title>Rust</title><link>/docs/design-decisions/rust/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/design-decisions/rust/</guid><description>&lt;h3 id="interfaces-traits"&gt;Interfaces (Traits) &lt;a href="#interfaces-traits" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; Interfaces are nominal — a type satisfies an interface only when explicitly stated, either through structural satisfaction (having the right methods) or an explicit &lt;code&gt;provide&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reason:&lt;/strong&gt; Structural typing (Go&amp;rsquo;s model) causes accidental interface satisfaction. If any type with a &lt;code&gt;.close()&lt;/code&gt; method satisfies &lt;code&gt;io.Closer&lt;/code&gt;, a &lt;code&gt;DatabaseConnection&lt;/code&gt; might accidentally satisfy &lt;code&gt;NetworkCloser&lt;/code&gt;. Nominal interfaces prevent this class of bug and make intent explicit.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d73acd3" class="language- "&gt;
 &lt;code&gt;interface Serialize {
 fn serialize(*const self, writer: *Writer): !void;
}

interface Deserialize {
 static fn deserialize(reader: *Reader): !Self;
}

type Point = struct { x: f32, y: f32 };

provide Serialize for Point {
 fn serialize(*const self, writer: *Writer): !void {
 try writer.writeF32(self.x);
 try writer.writeF32(self.y);
 }
}

provide Deserialize for Point {
 static fn deserialize(reader: *Reader): !Self {
 return .{
 .x = try reader.readF32(),
 .y = try reader.readF32(),
 };
 }
}

-- generic over any serializable type
fn writeAll[T: Serialize](items: []const T, writer: *Writer): !void {
 for item in items {
 try item.serialize(writer);
 }
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;hr&gt;
&lt;h3 id="generics-with-bounds"&gt;Generics With Bounds &lt;a href="#generics-with-bounds" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; Generic parameters use square brackets with explicit interface bounds: &lt;code&gt;[T: Bound]&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Zig</title><link>/docs/design-decisions/zig/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/design-decisions/zig/</guid><description>&lt;h3 id="explicit-allocators"&gt;Explicit Allocators &lt;a href="#explicit-allocators" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; Every allocation takes an explicit &lt;code&gt;Allocator&lt;/code&gt; parameter. No hidden heap usage anywhere in the language or standard library.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reason:&lt;/strong&gt; Hidden allocation is one of the primary sources of unexpected latency, OOM errors in unexpected places, and difficulty reasoning about memory usage. When allocation is explicit, the programmer always knows where memory comes from, which allocator strategy is being used, and can substitute a different allocator (arena, pool, stack) for testing or performance.&lt;/p&gt;</description></item><item><title>Violet</title><link>/docs/design-decisions/violet/</link><pubDate>Tue, 14 Jul 2026 14:30:13 +0200</pubDate><guid>/docs/design-decisions/violet/</guid><description>&lt;h3 id="explicit-io-parameter--no-async-fn"&gt;Explicit &lt;code&gt;*Io&lt;/code&gt; Parameter — No &lt;code&gt;async fn&lt;/code&gt; &lt;a href="#explicit-io-parameter--no-async-fn" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Decision:&lt;/strong&gt; Functions that may suspend take an explicit &lt;code&gt;*Io&lt;/code&gt; scheduler parameter. There is no &lt;code&gt;async fn&lt;/code&gt; keyword. Suspension is visible at every call site.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reason:&lt;/strong&gt; Rust&amp;rsquo;s &lt;code&gt;async fn&lt;/code&gt; colors the call graph — you cannot call an async function from a sync context without wrapping in an executor. Go&amp;rsquo;s goroutines hide suspension entirely. Both create versions of the &amp;ldquo;what color is your function&amp;rdquo; problem. Violet&amp;rsquo;s explicit &lt;code&gt;*Io&lt;/code&gt; parameter makes suspension visible at the call site — critical for reasoning about lock safety and task scheduling.&lt;/p&gt;</description></item></channel></rss>