lib/chant/src/parse/declaration.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const ast = @import("../ast/root.zig");
3 const auto_mod = @import("auto.zig");
4 const constexpr = @import("constexpr.zig");
5 const ctype = @import("type/root.zig");
6 const expression = @import("expression.zig");
7 const initializer_mod = @import("initializer.zig");
8 const state = @import("state/root.zig");
9 const thread = @import("thread.zig");
10 const cursor = state.cursor;
11 const diagnostic = state.diagnostic;
12 const object = state.object;
13 const typedef = state.typedef;
14 const Error = @import("error.zig").Error;
15
16 const Parser = state.Parser;
17
18 pub fn parseLocal(parser: *Parser) Error![]ast.Variable {
19 const specifiers = try ctype.parseSpecifiers(parser);
20 var variables = std.ArrayListUnmanaged(ast.Variable).empty;
21 if (cursor.consume(parser, .semicolon)) {
22 return variables.toOwnedSlice(parser.arena);
23 }
24 if (specifiers.requires_standalone_declaration) {
25 return diagnostic.fail(parser, error.UnsupportedConstruct, "fixed enum forward declaration must be standalone");
26 }
27 while (true) {
28 try ctype.skipAttributes(parser);
29 const declarator = try ctype.parseDeclarator(parser, specifiers.type, expression.parseAssignment);
30 try ctype.skipAttributes(parser);
31 const name = declarator.name orelse return diagnostic.fail(parser, error.ExpectedIdentifier, "declaration requires a name");
32 if (specifiers.storage == .typedef_storage) {
33 try thread.validateTypedef(parser, specifiers.is_thread_local);
34 if (specifiers.is_constexpr) {
35 return diagnostic.fail(parser, error.UnsupportedConstruct, "typedef cannot be constexpr");
36 }
37 if (auto_mod.contains(declarator.type)) {
38 return diagnostic.fail(parser, error.ExpectedType, "typedef cannot infer auto");
39 }
40 try typedef.register(parser, name, declarator.type);
41 } else {
42 var initializer: ?*ast.Expr = null;
43 if (cursor.consume(parser, .assign)) {
44 initializer = try initializer_mod.parse(parser, declarator.type);
45 }
46 const completed_type = try initializer_mod.completeType(parser, declarator.type, initializer);
47 const variable_type = try auto_mod.resolve(parser, completed_type, initializer);
48 const constant_value = if (specifiers.is_constexpr)
49 try constexpr.validateObject(parser, variable_type, initializer)
50 else
51 null;
52 try thread.validateObject(parser, .block, specifiers.storage, variable_type, initializer, specifiers.is_thread_local);
53 try variables.append(parser.arena, .{
54 .name = name,
55 .type = variable_type,
56 .storage = specifiers.storage,
57 .alignment = specifiers.alignment,
58 .is_constexpr = specifiers.is_constexpr,
59 .is_thread_local = specifiers.is_thread_local,
60 .initializer = initializer,
61 });
62 if (specifiers.is_constexpr) {
63 try constexpr.registerObject(parser, name, variable_type, constant_value);
64 } else {
65 try object.register(parser, name, variable_type);
66 }
67 }
68 if (cursor.consume(parser, .comma)) continue;
69 _ = try cursor.expect(parser, .semicolon);
70 break;
71 }
72 return variables.toOwnedSlice(parser.arena);
73 }