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 }