| author | |
| committer | |
| log | 37b13bf1512d8eed7308a2194c1935d91a33796c |
| tree | 42b6d1d4b6ddd16c7f69c4bdd15677a720609cf3 |
| parent | e50ced44a2cf6268c19df901ad56b367d8d802fe |
10 files changed, 57 insertions(+), 34 deletions(-)
doc/langref.md+1-1| ... | @@ -151,7 +151,7 @@ GroupedExpression = "(" Expression ")" | ... | @@ -151,7 +151,7 @@ GroupedExpression = "(" Expression ")" |
| 151 | 151 | ||
| 152 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" | 152 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" |
| 153 | 153 | ||
| 154 | ContainerDecl = ("struct" | "enum" | "union") "{" many(StructMember) "}" | 154 | ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}" |
| 155 | 155 | ||
| 156 | ``` | 156 | ``` |
| 157 | 157 |
src/all_types.hpp+4| ... | @@ -598,6 +598,7 @@ struct AstNodeContainerDecl { | ... | @@ -598,6 +598,7 @@ struct AstNodeContainerDecl { |
| 598 | ContainerKind kind; | 598 | ContainerKind kind; |
| 599 | ZigList<AstNode *> fields; | 599 | ZigList<AstNode *> fields; |
| 600 | ZigList<AstNode *> decls; | 600 | ZigList<AstNode *> decls; |
| 601 | bool is_extern; | ||
| 601 | }; | 602 | }; |
| 602 | 603 | ||
| 603 | struct AstNodeStructField { | 604 | struct AstNodeStructField { |
| ... | @@ -801,6 +802,7 @@ struct TypeStructField { | ... | @@ -801,6 +802,7 @@ struct TypeStructField { |
| 801 | }; | 802 | }; |
| 802 | struct TypeTableEntryStruct { | 803 | struct TypeTableEntryStruct { |
| 803 | AstNode *decl_node; | 804 | AstNode *decl_node; |
| 805 | bool is_extern; | ||
| 804 | bool is_packed; | 806 | bool is_packed; |
| 805 | uint32_t src_field_count; | 807 | uint32_t src_field_count; |
| 806 | uint32_t gen_field_count; | 808 | uint32_t gen_field_count; |
| ... | @@ -827,6 +829,7 @@ struct TypeTableEntryError { | ... | @@ -827,6 +829,7 @@ struct TypeTableEntryError { |
| 827 | 829 | ||
| 828 | struct TypeTableEntryEnum { | 830 | struct TypeTableEntryEnum { |
| 829 | AstNode *decl_node; | 831 | AstNode *decl_node; |
| 832 | bool is_extern; | ||
| 830 | uint32_t src_field_count; | 833 | uint32_t src_field_count; |
| 831 | uint32_t gen_field_count; | 834 | uint32_t gen_field_count; |
| 832 | TypeEnumField *fields; | 835 | TypeEnumField *fields; |
| ... | @@ -845,6 +848,7 @@ struct TypeTableEntryEnum { | ... | @@ -845,6 +848,7 @@ struct TypeTableEntryEnum { |
| 845 | 848 | ||
| 846 | struct TypeTableEntryUnion { | 849 | struct TypeTableEntryUnion { |
| 847 | AstNode *decl_node; | 850 | AstNode *decl_node; |
| 851 | bool is_extern; | ||
| 848 | uint32_t src_field_count; | 852 | uint32_t src_field_count; |
| 849 | uint32_t gen_field_count; | 853 | uint32_t gen_field_count; |
| 850 | TypeStructField *fields; | 854 | TypeStructField *fields; |
src/analyze.cpp+3| ... | @@ -838,12 +838,15 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi | ... | @@ -838,12 +838,15 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKi |
| 838 | switch (kind) { | 838 | switch (kind) { |
| 839 | case ContainerKindStruct: | 839 | case ContainerKindStruct: |
| 840 | entry->data.structure.decl_node = decl_node; | 840 | entry->data.structure.decl_node = decl_node; |
| 841 | entry->data.structure.is_extern = decl_node->data.container_decl.is_extern; | ||
| 841 | break; | 842 | break; |
| 842 | case ContainerKindEnum: | 843 | case ContainerKindEnum: |
| 843 | entry->data.enumeration.decl_node = decl_node; | 844 | entry->data.enumeration.decl_node = decl_node; |
| 845 | entry->data.enumeration.is_extern = decl_node->data.container_decl.is_extern; | ||
| 844 | break; | 846 | break; |
| 845 | case ContainerKindUnion: | 847 | case ContainerKindUnion: |
| 846 | entry->data.unionation.decl_node = decl_node; | 848 | entry->data.unionation.decl_node = decl_node; |
| 849 | entry->data.unionation.is_extern = decl_node->data.container_decl.is_extern; | ||
| 847 | break; | 850 | break; |
| 848 | } | 851 | } |
| 849 | 852 |
src/ir.cpp+3| ... | @@ -8007,6 +8007,9 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru | ... | @@ -8007,6 +8007,9 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru |
| 8007 | TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, | 8007 | TypeTableEntry *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields, |
| 8008 | bool depends_on_compile_var) | 8008 | bool depends_on_compile_var) |
| 8009 | { | 8009 | { |
| 8010 | if (!type_is_complete(container_type)) | ||
| 8011 | resolve_container_type(ira->codegen, container_type); | ||
| 8012 | |||
| 8010 | size_t actual_field_count = container_type->data.structure.src_field_count; | 8013 | size_t actual_field_count = container_type->data.structure.src_field_count; |
| 8011 | 8014 | ||
| 8012 | IrInstruction *first_non_const_instruction = nullptr; | 8015 | IrInstruction *first_non_const_instruction = nullptr; |
src/parser.cpp+24-11| ... | @@ -684,11 +684,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -684,11 +684,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 684 | AstNode *node = ast_create_node(pc, NodeTypeErrorType, token); | 684 | AstNode *node = ast_create_node(pc, NodeTypeErrorType, token); |
| 685 | *token_index += 1; | 685 | *token_index += 1; |
| 686 | return node; | 686 | return node; |
| 687 | } else if (token->id == TokenIdKeywordExtern) { | ||
| 688 | *token_index += 1; | ||
| 689 | AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate); | ||
| 690 | node->data.fn_proto.is_extern = true; | ||
| 691 | return node; | ||
| 692 | } else if (token->id == TokenIdAtSign) { | 687 | } else if (token->id == TokenIdAtSign) { |
| 693 | *token_index += 1; | 688 | *token_index += 1; |
| 694 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); | 689 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); |
| ... | @@ -742,6 +737,13 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -742,6 +737,13 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 742 | if (container_decl) | 737 | if (container_decl) |
| 743 | return container_decl; | 738 | return container_decl; |
| 744 | 739 | ||
| 740 | if (token->id == TokenIdKeywordExtern) { | ||
| 741 | *token_index += 1; | ||
| 742 | AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate); | ||
| 743 | node->data.fn_proto.is_extern = true; | ||
| 744 | return node; | ||
| 745 | } | ||
| 746 | |||
| 745 | if (!mandatory) | 747 | if (!mandatory) |
| 746 | return nullptr; | 748 | return nullptr; |
| 747 | 749 | ||
| ... | @@ -2224,28 +2226,39 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi | ... | @@ -2224,28 +2226,39 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi |
| 2224 | } | 2226 | } |
| 2225 | 2227 | ||
| 2226 | /* | 2228 | /* |
| 2227 | ContainerDecl = ("struct" | "enum" | "union") "{" many(StructMember) "}" | 2229 | ContainerDecl = option("extern") ("struct" | "enum" | "union") "{" many(StructMember) "}" |
| 2228 | StructMember = (StructField | FnDef | GlobalVarDecl) | 2230 | StructMember = (StructField | FnDef | GlobalVarDecl) |
| 2229 | StructField = Symbol option(":" Expression) ",") | 2231 | StructField = Symbol option(":" Expression) ",") |
| 2230 | */ | 2232 | */ |
| 2231 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { | 2233 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2232 | Token *first_token = &pc->tokens->at(*token_index); | 2234 | Token *first_token = &pc->tokens->at(*token_index); |
| 2235 | Token *container_kind_token; | ||
| 2236 | |||
| 2237 | bool is_extern; | ||
| 2238 | if (first_token->id == TokenIdKeywordExtern) { | ||
| 2239 | container_kind_token = &pc->tokens->at(*token_index + 1); | ||
| 2240 | is_extern = true; | ||
| 2241 | } else { | ||
| 2242 | container_kind_token = first_token; | ||
| 2243 | is_extern = false; | ||
| 2244 | } | ||
| 2233 | 2245 | ||
| 2234 | ContainerKind kind; | 2246 | ContainerKind kind; |
| 2235 | if (first_token->id == TokenIdKeywordStruct) { | 2247 | if (container_kind_token->id == TokenIdKeywordStruct) { |
| 2236 | kind = ContainerKindStruct; | 2248 | kind = ContainerKindStruct; |
| 2237 | } else if (first_token->id == TokenIdKeywordEnum) { | 2249 | } else if (container_kind_token->id == TokenIdKeywordEnum) { |
| 2238 | kind = ContainerKindEnum; | 2250 | kind = ContainerKindEnum; |
| 2239 | } else if (first_token->id == TokenIdKeywordUnion) { | 2251 | } else if (container_kind_token->id == TokenIdKeywordUnion) { |
| 2240 | kind = ContainerKindUnion; | 2252 | kind = ContainerKindUnion; |
| 2241 | } else if (mandatory) { | 2253 | } else if (mandatory) { |
| 2242 | ast_invalid_token_error(pc, first_token); | 2254 | ast_invalid_token_error(pc, container_kind_token); |
| 2243 | } else { | 2255 | } else { |
| 2244 | return nullptr; | 2256 | return nullptr; |
| 2245 | } | 2257 | } |
| 2246 | *token_index += 1; | 2258 | *token_index += is_extern ? 2 : 1; |
| 2247 | 2259 | ||
| 2248 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token); | 2260 | AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token); |
| 2261 | node->data.container_decl.is_extern = is_extern; | ||
| 2249 | node->data.container_decl.kind = kind; | 2262 | node->data.container_decl.kind = kind; |
| 2250 | 2263 | ||
| 2251 | ast_eat_token(pc, token_index, TokenIdLBrace); | 2264 | ast_eat_token(pc, token_index, TokenIdLBrace); |
std/cstr.zig+2-2| ... | @@ -34,7 +34,7 @@ pub fn toSlice(str: &u8) -> []u8 { | ... | @@ -34,7 +34,7 @@ pub fn toSlice(str: &u8) -> []u8 { |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | /// A buffer that allocates memory and maintains a null byte at the end. | 36 | /// A buffer that allocates memory and maintains a null byte at the end. |
| 37 | pub struct CBuf { | 37 | pub const CBuf = struct { |
| 38 | list: List(u8), | 38 | list: List(u8), |
| 39 | 39 | ||
| 40 | /// Must deinitialize with deinit. | 40 | /// Must deinitialize with deinit. |
| ... | @@ -124,7 +124,7 @@ pub struct CBuf { | ... | @@ -124,7 +124,7 @@ pub struct CBuf { |
| 124 | pub fn startsWithCStr(self: &const CBuf, s: &const u8) -> bool { | 124 | pub fn startsWithCStr(self: &const CBuf, s: &const u8) -> bool { |
| 125 | self.startsWithMem(s[0...strlen(s)]) | 125 | self.startsWithMem(s[0...strlen(s)]) |
| 126 | } | 126 | } |
| 127 | } | 127 | }; |
| 128 | 128 | ||
| 129 | fn testSimpleCBuf() { | 129 | fn testSimpleCBuf() { |
| 130 | @setFnTest(this, true); | 130 | @setFnTest(this, true); |
std/io.zig+4-4| ... | @@ -69,7 +69,7 @@ pub const OpenWrite = 0b0010; | ... | @@ -69,7 +69,7 @@ pub const OpenWrite = 0b0010; |
| 69 | pub const OpenCreate = 0b0100; | 69 | pub const OpenCreate = 0b0100; |
| 70 | pub const OpenTruncate = 0b1000; | 70 | pub const OpenTruncate = 0b1000; |
| 71 | 71 | ||
| 72 | pub struct OutStream { | 72 | pub const OutStream = struct { |
| 73 | fd: i32, | 73 | fd: i32, |
| 74 | buffer: [buffer_size]u8, | 74 | buffer: [buffer_size]u8, |
| 75 | index: usize, | 75 | index: usize, |
| ... | @@ -153,11 +153,11 @@ pub struct OutStream { | ... | @@ -153,11 +153,11 @@ pub struct OutStream { |
| 153 | return; | 153 | return; |
| 154 | } | 154 | } |
| 155 | } | 155 | } |
| 156 | } | 156 | }; |
| 157 | 157 | ||
| 158 | // TODO created a BufferedInStream struct and move some of this code there | 158 | // TODO created a BufferedInStream struct and move some of this code there |
| 159 | // BufferedInStream API goes on top of minimal InStream API. | 159 | // BufferedInStream API goes on top of minimal InStream API. |
| 160 | pub struct InStream { | 160 | pub const InStream = struct { |
| 161 | fd: i32, | 161 | fd: i32, |
| 162 | 162 | ||
| 163 | /// Call close to clean up. | 163 | /// Call close to clean up. |
| ... | @@ -360,7 +360,7 @@ pub struct InStream { | ... | @@ -360,7 +360,7 @@ pub struct InStream { |
| 360 | 360 | ||
| 361 | return usize(stat.size); | 361 | return usize(stat.size); |
| 362 | } | 362 | } |
| 363 | } | 363 | }; |
| 364 | 364 | ||
| 365 | pub fn parseUnsigned(inline T: type, buf: []u8, radix: u8) -> %T { | 365 | pub fn parseUnsigned(inline T: type, buf: []u8, radix: u8) -> %T { |
| 366 | var x: T = 0; | 366 | var x: T = 0; |
std/linux.zig+8-8| ... | @@ -342,31 +342,31 @@ pub const socklen_t = u32; | ... | @@ -342,31 +342,31 @@ pub const socklen_t = u32; |
| 342 | pub const in_addr = u32; | 342 | pub const in_addr = u32; |
| 343 | pub const in6_addr = [16]u8; | 343 | pub const in6_addr = [16]u8; |
| 344 | 344 | ||
| 345 | export struct sockaddr { | 345 | pub const sockaddr = extern struct { |
| 346 | family: sa_family_t, | 346 | family: sa_family_t, |
| 347 | port: u16, | 347 | port: u16, |
| 348 | data: [12]u8, | 348 | data: [12]u8, |
| 349 | } | 349 | }; |
| 350 | 350 | ||
| 351 | export struct sockaddr_in { | 351 | pub const sockaddr_in = extern struct { |
| 352 | family: sa_family_t, | 352 | family: sa_family_t, |
| 353 | port: u16, | 353 | port: u16, |
| 354 | addr: in_addr, | 354 | addr: in_addr, |
| 355 | zero: [8]u8, | 355 | zero: [8]u8, |
| 356 | } | 356 | }; |
| 357 | 357 | ||
| 358 | export struct sockaddr_in6 { | 358 | pub const sockaddr_in6 = extern struct { |
| 359 | family: sa_family_t, | 359 | family: sa_family_t, |
| 360 | port: u16, | 360 | port: u16, |
| 361 | flowinfo: u32, | 361 | flowinfo: u32, |
| 362 | addr: in6_addr, | 362 | addr: in6_addr, |
| 363 | scope_id: u32, | 363 | scope_id: u32, |
| 364 | } | 364 | }; |
| 365 | 365 | ||
| 366 | export struct iovec { | 366 | pub const iovec = extern struct { |
| 367 | iov_base: &u8, | 367 | iov_base: &u8, |
| 368 | iov_len: usize, | 368 | iov_len: usize, |
| 369 | } | 369 | }; |
| 370 | 370 | ||
| 371 | // | 371 | // |
| 372 | //const IF_NAMESIZE = 16; | 372 | //const IF_NAMESIZE = 16; |
std/linux_x86_64.zig+6-6| ... | @@ -442,7 +442,7 @@ pub inline fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg | ... | @@ -442,7 +442,7 @@ pub inline fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg |
| 442 | : "rcx", "r11") | 442 | : "rcx", "r11") |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | export struct msghdr { | 445 | pub const msghdr = extern struct { |
| 446 | msg_name: &u8, | 446 | msg_name: &u8, |
| 447 | msg_namelen: socklen_t, | 447 | msg_namelen: socklen_t, |
| 448 | msg_iov: &iovec, | 448 | msg_iov: &iovec, |
| ... | @@ -452,9 +452,9 @@ export struct msghdr { | ... | @@ -452,9 +452,9 @@ export struct msghdr { |
| 452 | msg_controllen: socklen_t, | 452 | msg_controllen: socklen_t, |
| 453 | __pad2: socklen_t, | 453 | __pad2: socklen_t, |
| 454 | msg_flags: i32, | 454 | msg_flags: i32, |
| 455 | } | 455 | }; |
| 456 | 456 | ||
| 457 | export struct stat { | 457 | pub const stat = extern struct { |
| 458 | dev: u64, | 458 | dev: u64, |
| 459 | ino: u64, | 459 | ino: u64, |
| 460 | nlink: usize, | 460 | nlink: usize, |
| ... | @@ -472,9 +472,9 @@ export struct stat { | ... | @@ -472,9 +472,9 @@ export struct stat { |
| 472 | mtim: timespec, | 472 | mtim: timespec, |
| 473 | ctim: timespec, | 473 | ctim: timespec, |
| 474 | __unused: [3]isize, | 474 | __unused: [3]isize, |
| 475 | } | 475 | }; |
| 476 | 476 | ||
| 477 | export struct timespec { | 477 | pub const timespec = extern struct { |
| 478 | tv_sec: isize, | 478 | tv_sec: isize, |
| 479 | tv_nsec: isize, | 479 | tv_nsec: isize, |
| 480 | } | 480 | }; |
std/math.zig+2-2| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | pub enum Cmp { | 1 | pub const Cmp = enum { |
| 2 | Equal, | 2 | Equal, |
| 3 | Greater, | 3 | Greater, |
| 4 | Less, | 4 | Less, |
| 5 | } | 5 | }; |
| 6 | 6 | ||
| 7 | pub fn min(x: var, y: var) -> @typeOf(x + y) { | 7 | pub fn min(x: var, y: var) -> @typeOf(x + y) { |
| 8 | if (x < y) x else y | 8 | if (x < y) x else y |