1 /// Copyright: Copyright (c) 2017-2020 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 module vox.fe.ast.decl.static_assert;
5 
6 import vox.all;
7 
8 
9 @(AstType.decl_static_assert)
10 struct StaticAssertDeclNode
11 {
12 	mixin AstNodeData!(AstType.decl_static_assert, 0, AstNodeState.name_register_self_done);
13 	AstIndex condition;
14 	AstIndex message; // for now only single string is allowed, nullable
15 }
16 
17 void print_static_assert(StaticAssertDeclNode* node, ref AstPrintState state)
18 {
19 	state.print("#ASSERT");
20 	print_ast(node.condition, state);
21 	if (node.message) print_ast(node.message, state);
22 }
23 
24 void post_clone_static_assert(StaticAssertDeclNode* node, ref CloneState state)
25 {
26 	state.fixAstIndex(node.condition);
27 	state.fixAstIndex(node.message);
28 }
29 
30 void name_register_nested_static_assert(StaticAssertDeclNode* node, ref NameRegisterState state)
31 {
32 	node.state = AstNodeState.name_register_nested;
33 	require_name_register(node.condition, state);
34 	if (node.message) require_name_register(node.message, state);
35 	node.state = AstNodeState.name_register_nested_done;
36 }
37 
38 void name_resolve_static_assert(StaticAssertDeclNode* node, ref NameResolveState state)
39 {
40 	node.state = AstNodeState.name_resolve;
41 	require_name_resolve(node.condition, state);
42 	if (node.message) require_name_resolve(node.message, state);
43 	node.state = AstNodeState.name_resolve_done;
44 }
45 
46 void type_check_static_assert(StaticAssertDeclNode* node, ref TypeCheckState state)
47 {
48 	CompilationContext* c = state.context;
49 
50 	node.state = AstNodeState.type_check;
51 	scope(exit) node.state = AstNodeState.type_check_done;
52 
53 	require_type_check(node.condition, state);
54 	if (node.message) {
55 		require_type_check(node.message, state);
56 
57 		if (node.message.astType(c) != AstType.literal_string) {
58 			c.error(node.loc, "#assert only supports string literal as a message");
59 			return;
60 		}
61 	}
62 
63 	IrIndex val = eval_static_expr(node.condition, c);
64 	if (!c.constants.get(val).i64)
65 	{
66 		if (node.message)
67 			c.error(node.loc, "#assert: \"%s\"", node.message.get!StringLiteralExprNode(c).value);
68 		else
69 			c.error(node.loc, "#assert");
70 	}
71 }