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 }