lib/chant/src/parse/constant.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const ast = @import("../ast/root.zig");
 2 const expression = @import("expression.zig");
 3 const state = @import("state/root.zig");
 4 const Error = @import("error.zig").Error;
 5 
 6 const object = state.object;
 7 const Parser = state.Parser;
 8 
 9 pub fn isScalar(parser: *Parser, expr: *ast.Expr) Error!bool {
10     if (expression.evaluateIntegerConstant(parser, expr) != null) return true;
11     const expression_type = try expression.inferType(parser, expr);
12     if (expression_type) |c_type| {
13         if (ast.types.isInteger(c_type)) return false;
14     }
15     return hasScalarConstantShape(parser, expr);
16 }
17 
18 pub fn isInitializer(parser: *Parser, expr: *ast.Expr) Error!bool {
19     switch (expr.*) {
20         .string_literal => return true,
21         .initializer_list => |list| {
22             for (list.items) |item| {
23                 if (!try isInitializer(parser, item.value)) return false;
24             }
25             return true;
26         },
27         else => return isScalar(parser, expr),
28     }
29 }
30 
31 fn hasScalarConstantShape(parser: *const Parser, expr: *ast.Expr) bool {
32     switch (expr.*) {
33         .integer_literal, .float_literal => return true,
34         .identifier => |identifier| return object.constantValue(parser, identifier.name) != null,
35         .string_literal, .call, .index, .initializer_list, .assign => return false,
36         .unary => |unary| {
37             return switch (unary.op) {
38                 .negate, .logical_not, .bit_not => hasScalarConstantShape(parser, unary.operand),
39                 .address_of, .deref => false,
40             };
41         },
42         .binary => |binary| {
43             return hasScalarConstantShape(parser, binary.lhs) and hasScalarConstantShape(parser, binary.rhs);
44         },
45         .conditional => |conditional| {
46             const condition = expression.evaluateIntegerConstant(parser, conditional.condition) orelse return false;
47             return hasScalarConstantShape(parser, if (condition != 0) conditional.then_value else conditional.else_value);
48         },
49         .cast => |cast| return hasScalarConstantShape(parser, cast.operand),
50     }
51 }