lib/chant/src/ast/stmt.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const expr = @import("expr.zig");
3 const variable = @import("variable.zig");
4
5 pub const Stmt = union(enum) {
6 expression: *expr.Expr,
7 declaration: []variable.Variable,
8 compound: []*Stmt,
9 if_stmt: If,
10 for_stmt: For,
11 while_stmt: While,
12 do_stmt: While,
13 label: Label,
14 return_stmt: ?*expr.Expr,
15 break_stmt,
16 continue_stmt,
17 empty,
18
19 pub const If = struct {
20 condition: *expr.Expr,
21 then_body: *Stmt,
22 else_body: ?*Stmt,
23 };
24
25 pub const For = struct {
26 init: ?*Stmt,
27 condition: ?*expr.Expr,
28 step: ?*expr.Expr,
29 body: *Stmt,
30 };
31
32 pub const While = struct {
33 condition: *expr.Expr,
34 body: *Stmt,
35 };
36
37 pub const Label = struct {
38 name: []const u8,
39 body: *Stmt,
40 };
41 };
42
43 test "statements nest" {
44 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
45 defer arena.deinit();
46 const allocator = arena.allocator();
47
48 const body = try allocator.create(Stmt);
49 body.* = .empty;
50 const loop = try allocator.create(Stmt);
51 loop.* = .{ .for_stmt = .{ .init = null, .condition = null, .step = null, .body = body } };
52 try std.testing.expect(loop.for_stmt.body.* == .empty);
53
54 const label = try allocator.create(Stmt);
55 label.* = .{ .label = .{ .name = "again", .body = loop } };
56 try std.testing.expectEqualStrings("again", label.label.name);
57 try std.testing.expect(label.label.body.* == .for_stmt);
58 }