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 }