lib/chant/src/parse/assert.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const expression = @import("expression.zig");
 3 const state = @import("state/root.zig");
 4 
 5 const cursor = state.cursor;
 6 const diagnostic = state.diagnostic;
 7 const Error = @import("error.zig").Error;
 8 const Parser = state.Parser;
 9 
10 pub fn consume(parser: *Parser) Error!bool {
11     if (!cursor.consume(parser, .kw_static_assert)) return false;
12     _ = try cursor.expect(parser, .lparen);
13     const condition = try expression.parseExpression(parser);
14     const value = expression.evaluateIntegerConstant(parser, condition) orelse
15         return diagnostic.fail(parser, error.UnsupportedConstruct, "static_assert condition is not an integer constant");
16     if (cursor.consume(parser, .comma)) {
17         _ = try cursor.expect(parser, .string);
18     }
19     _ = try cursor.expect(parser, .rparen);
20     _ = try cursor.expect(parser, .semicolon);
21     if (value == 0) {
22         return diagnostic.fail(parser, error.StaticAssertionFailed, "static assertion failed");
23     }
24     return true;
25 }
26 
27 test "static assertions accept nonzero integer constants" {
28     const lexer = @import("../lexer/root.zig");
29     var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);
30     defer arena_state.deinit();
31     const arena = arena_state.allocator();
32 
33     const source = "static_assert(alignof(double) == 8, \"lp64\");";
34     const token_survey = try lexer.survey(source, "assert.c");
35     const capacity = try lexer.Capacity.derive(token_survey.limits);
36     const bytes = try arena.alignedAlloc(
37         u8,
38         .fromByteUnits(lexer.Storage.storage_alignment),
39         capacity.storage_bytes,
40     );
41     var storage = try lexer.Storage.init(bytes, token_survey.limits);
42     storage.activate();
43     defer _ = storage.deinit();
44     const tokens = try storage.fill(token_survey, source, "assert.c");
45     var parser = try @import("state/test.zig").initParser(arena, tokens);
46     try std.testing.expect(try consume(&parser));
47 }
48 
49 test "static assertions reject zero" {
50     const lexer = @import("../lexer/root.zig");
51     var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);
52     defer arena_state.deinit();
53     const arena = arena_state.allocator();
54 
55     const source = "static_assert(false);";
56     const token_survey = try lexer.survey(source, "assert.c");
57     const capacity = try lexer.Capacity.derive(token_survey.limits);
58     const bytes = try arena.alignedAlloc(
59         u8,
60         .fromByteUnits(lexer.Storage.storage_alignment),
61         capacity.storage_bytes,
62     );
63     var storage = try lexer.Storage.init(bytes, token_survey.limits);
64     storage.activate();
65     defer _ = storage.deinit();
66     const tokens = try storage.fill(token_survey, source, "assert.c");
67     var parser = try @import("state/test.zig").initParser(arena, tokens);
68     try std.testing.expectError(error.StaticAssertionFailed, consume(&parser));
69 }