diff options
Diffstat (limited to 'examples/snippets/syntax-tour.zig')
| -rw-r--r-- | examples/snippets/syntax-tour.zig | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/examples/snippets/syntax-tour.zig b/examples/snippets/syntax-tour.zig new file mode 100644 index 0000000..4c29588 --- /dev/null +++ b/examples/snippets/syntax-tour.zig @@ -0,0 +1,283 @@ +//! 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); +} |
