lib/chant/src/ast/expr.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const types = @import("type/root.zig");
3
4 pub const BinaryOp = enum {
5 add,
6 sub,
7 mul,
8 div,
9 rem,
10 lt,
11 gt,
12 le,
13 ge,
14 eq,
15 ne,
16 logical_and,
17 logical_or,
18 bit_and,
19 bit_or,
20 bit_xor,
21 shl,
22 shr,
23 };
24
25 pub const UnaryOp = enum {
26 negate,
27 logical_not,
28 bit_not,
29 address_of,
30 deref,
31 };
32
33 pub const IntegerLiteral = struct {
34 value: u64,
35 type: *const types.Type,
36 };
37
38 pub const FloatLiteral = struct {
39 value: f64,
40 type: *const types.Type,
41 };
42
43 pub const StringLiteral = struct {
44 text: []const u8,
45 };
46
47 pub const Identifier = struct {
48 name: []const u8,
49 };
50
51 pub const Binary = struct {
52 op: BinaryOp,
53 lhs: *Expr,
54 rhs: *Expr,
55 };
56
57 pub const Unary = struct {
58 op: UnaryOp,
59 operand: *Expr,
60 };
61
62 pub const Assign = struct {
63 op: ?BinaryOp,
64 target: *Expr,
65 value: *Expr,
66 };
67
68 pub const Conditional = struct {
69 condition: *Expr,
70 then_value: *Expr,
71 else_value: *Expr,
72 };
73
74 pub const Call = struct {
75 callee: []const u8,
76 arguments: []*Expr,
77 };
78
79 pub const Index = struct {
80 base: *Expr,
81 subscript: *Expr,
82 };
83
84 pub const Cast = struct {
85 target: *const types.Type,
86 operand: *Expr,
87 };
88
89 pub const InitializerItem = struct {
90 designator: []const u64 = &.{},
91 value: *Expr,
92 };
93
94 pub const InitializerList = struct {
95 type: *const types.Type,
96 items: []InitializerItem,
97 };
98
99 pub const Expr = union(enum) {
100 integer_literal: IntegerLiteral,
101 float_literal: FloatLiteral,
102 string_literal: StringLiteral,
103 identifier: Identifier,
104 binary: Binary,
105 unary: Unary,
106 assign: Assign,
107 conditional: Conditional,
108 call: Call,
109 index: Index,
110 cast: Cast,
111 initializer_list: InitializerList,
112 };
113
114 test "expressions compose as arena nodes" {
115 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
116 defer arena.deinit();
117 const allocator = arena.allocator();
118
119 const lhs = try allocator.create(Expr);
120 lhs.* = .{ .identifier = .{ .name = "i" } };
121 const rhs = try allocator.create(Expr);
122 rhs.* = .{ .integer_literal = .{ .value = 1, .type = &types.int_type } };
123 const sum = try allocator.create(Expr);
124 sum.* = .{ .binary = .{ .op = .add, .lhs = lhs, .rhs = rhs } };
125
126 try std.testing.expectEqual(BinaryOp.add, sum.binary.op);
127 try std.testing.expectEqualStrings("i", sum.binary.lhs.identifier.name);
128 }