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 }