//! Root-level doc comment (module doc). //! This file exercises every syntax category for highlighting verification. //! Open in Nova and check that all constructs colour correctly. const std = @import("std"); // ── Keywords: pub, const, var, comptime, extern, export, inline, noinline ────── /// Doc comment on a public constant. pub const VERSION: []const u8 = "0.15.0"; pub var mutable_counter: u32 = 0; // ── Enums ────────────────────────────────────────────────────────────────────── pub const Color = enum(u8) { red = 0, green = 1, blue = 2, pub fn toHex(self: Color) u24 { return switch (self) { .red => 0xFF0000, .green => 0x00FF00, .blue => 0x0000FF, }; } }; // ── Structs with default field values ───────────────────────────────────────── pub const Point = struct { x: f64 = 0.0, y: f64 = 0.0, pub fn distanceTo(self: Point, other: Point) f64 { const dx = self.x - other.x; const dy = self.y - other.y; return std.math.sqrt(dx * dx + dy * dy); } /// Generic format method — tests `anytype` keyword. pub fn format(self: Point, comptime fmt: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { _ = fmt; try writer.print("({d:.2}, {d:.2})", .{ self.x, self.y }); } }; // ── Tagged union ─────────────────────────────────────────────────────────────── pub const Number = union(enum) { integer: i64, float: f64, pub fn isZero(self: Number) bool { return switch (self) { .integer => |v| v == 0, .float => |v| v == 0.0, }; } }; // ── Opaque type ─────────────────────────────────────────────────────────────── pub const Handle = opaque {}; // ── Packed struct ───────────────────────────────────────────────────────────── pub const Flags = packed struct { enabled: bool, verbose: bool, debug: bool, _pad: u5 = 0, }; // ── Comptime ────────────────────────────────────────────────────────────────── pub fn typeName(comptime T: type) []const u8 { return @typeName(T); } /// Comptime block with labeled break. pub const BITS_IN_BYTE: comptime_int = blk: { var n: u8 = 255; var count: usize = 0; while (n > 0) : (n >>= 1) count += 1; break :blk count; }; // ── Generics ────────────────────────────────────────────────────────────────── pub fn Stack(comptime T: type) type { return struct { items: std.ArrayList(T) = .empty, pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void { self.items.deinit(allocator); } pub fn push(self: *@This(), allocator: std.mem.Allocator, value: T) !void { try self.items.append(allocator, value); } pub fn pop(self: *@This()) ?T { return self.items.pop(); } }; } // ── Builtin functions ───────────────────────────────────────────────────────── pub fn builtinDemo(value: i32) u32 { const as_u32: u32 = @intCast(value); const as_f32: f32 = @floatFromInt(value); _ = as_f32; _ = @sizeOf(u64); _ = @alignOf(*u8); _ = @typeInfo(Color); return as_u32; } // ── String literal variants ─────────────────────────────────────────────────── pub const PLAIN: []const u8 = "hello, Nova!"; pub const ESCAPE: []const u8 = "tab:\there\nnewline\x00null"; /// Multiline string — each line starts with `\\`. pub const MULTILINE: []const u8 = \\first line \\second line \\third line ; pub const CHAR_LITERAL: u8 = 'Z'; pub const UNICODE_ESCAPE: []const u8 = "\u{2744}"; // ❄ pub const HEX_ESCAPE: u8 = '\xff'; // ── Error sets and error union ───────────────────────────────────────────────── pub const ParseError = error{ UnexpectedToken, EndOfStream, Overflow, }; pub fn parseU8(s: []const u8) ParseError!u8 { if (s.len == 0) return error.EndOfStream; return std.fmt.parseInt(u8, s, 10) catch error.UnexpectedToken; } // ── Optional / orelse / if capture ─────────────────────────────────────────── pub fn firstByte(s: []const u8) ?u8 { return if (s.len == 0) null else s[0]; } pub fn firstByteOr(s: []const u8, fallback: u8) u8 { return firstByte(s) orelse fallback; } // ── Switch with integer ranges ──────────────────────────────────────────────── pub fn classify(n: i32) []const u8 { return switch (n) { std.math.minInt(i32)...-1 => "negative", 0 => "zero", 1...100 => "small positive", else => "large positive", }; } // ── For with index, multi-sequence ──────────────────────────────────────────── pub fn sumSlice(items: []const i32) i64 { var total: i64 = 0; for (items, 0..) |item, idx| { _ = idx; total += item; } return total; } // ── While with continue expression ─────────────────────────────────────────── pub fn countDown(start: u32) u32 { var i = start; var steps: u32 = 0; while (i > 0) : (i -= 1) steps += 1; return steps; } // ── Defer / errdefer ───────────────────────────────────────────────────────── pub fn withDefer(allocator: std.mem.Allocator) ![]u8 { const buf = try allocator.alloc(u8, 16); errdefer allocator.free(buf); @memset(buf, 0); return buf; } // ── Pointer types, alignment ────────────────────────────────────────────────── pub fn ptrDemo(p: *align(8) u64) u64 { return p.*; } // ── inline / noinline ───────────────────────────────────────────────────────── pub inline fn inlineAdd(a: u32, b: u32) u32 { return a + b; } pub noinline fn noinlineAdd(a: u32, b: u32) u32 { return a + b; } // ── threadlocal ─────────────────────────────────────────────────────────────── threadlocal var tl_counter: u32 = 0; pub fn bumpCounter() void { tl_counter += 1; } // ── extern ──────────────────────────────────────────────────────────────────── extern fn c_strlen(ptr: [*:0]const u8) usize; // ── Inline assembly ─────────────────────────────────────────────────────────── pub fn nop() void { asm volatile ("nop"); } // ── Tests ───────────────────────────────────────────────────────────────────── test "syntax-tour: classify" { try std.testing.expectEqualStrings("zero", classify(0)); try std.testing.expectEqualStrings("negative", classify(-5)); try std.testing.expectEqualStrings("small positive", classify(42)); try std.testing.expectEqualStrings("large positive", classify(200)); } test "syntax-tour: sumSlice" { try std.testing.expectEqual(@as(i64, 15), sumSlice(&.{ 1, 2, 3, 4, 5 })); try std.testing.expectEqual(@as(i64, 0), sumSlice(&.{})); } test "syntax-tour: parseU8 errors" { try std.testing.expectError(error.EndOfStream, parseU8("")); try std.testing.expectError(error.UnexpectedToken, parseU8("abc")); } test "syntax-tour: firstByte" { try std.testing.expectEqual(@as(?u8, 'h'), firstByte("hello")); try std.testing.expectEqual(@as(?u8, null), firstByte("")); } test "syntax-tour: Color.toHex" { try std.testing.expectEqual(@as(u24, 0xFF0000), Color.red.toHex()); try std.testing.expectEqual(@as(u24, 0x0000FF), Color.blue.toHex()); } test "syntax-tour: Number.isZero" { try std.testing.expect((Number{ .integer = 0 }).isZero()); try std.testing.expect(!(Number{ .float = 3.14 }).isZero()); } test "syntax-tour: Stack(i32)" { const gpa = std.testing.allocator; var s = Stack(i32){}; defer s.deinit(gpa); try s.push(gpa, 10); try s.push(gpa, 20); try std.testing.expectEqual(@as(?i32, 20), s.pop()); try std.testing.expectEqual(@as(?i32, 10), s.pop()); try std.testing.expectEqual(@as(?i32, null), s.pop()); } test "syntax-tour: BITS_IN_BYTE" { try std.testing.expectEqual(@as(comptime_int, 8), BITS_IN_BYTE); }