authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-26 13:08:21-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-26 13:08:21-07:00
log5afe473a86c2fe32b6d7c472b71f88e70ac671c6
treef96903b0859c702fa7391d40024056cb1d2563d1
parentbc896149966afb3740a02cd34939f0543b769be7

different extern syntax and simplify parsing top level decls


8 files changed, 174 insertions(+), 353 deletions(-)

doc/langref.md+14-12
......@@ -5,31 +5,33 @@
55```
66Root : many(TopLevelDecl) "EOF"
77
8TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl
8TopLevelDecl : many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl)
99
10ErrorValueDecl : option(FnVisibleMod) "error" "Symbol"
10CImportDecl : "c_import" Block
1111
12VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression
12ErrorValueDecl : "error" "Symbol" ";"
1313
14ContainerDecl : many(Directive) option(FnVisibleMod) ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
14GlobalVarDecl : VariableDeclaration ";"
1515
16StructMember: StructField | FnDecl
16VariableDeclaration : ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression
17
18ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
19
20StructMember: many(Directive) option(VisibleMod) (StructField | FnDef)
1721
1822StructField : "Symbol" option(":" Expression) ",")
1923
20Import : many(Directive) "import" "String" ";"
24Import : "import" "String" ";"
2125
22RootExportDecl : many(Directive) "export" "Symbol" "String" ";"
26RootExportDecl : "export" "Symbol" "String" ";"
2327
24ExternBlock : many(Directive) "extern" "{" many(FnDecl) "}"
28ExternDecl : "extern" FnProto ";"
2529
26FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
30FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
2731
2832Directive : "#" "Symbol" "(" "String" ")"
2933
30FnVisibleMod : "pub" | "export"
31
32FnDecl : FnProto ";"
34VisibleMod : "pub" | "export"
3335
3436FnDef : FnProto Block
3537
doc/vim/syntax/zig.vim+1-1
......@@ -14,7 +14,7 @@ syn keyword zigConditional if else switch
1414syn keyword zigRepeat while for
1515
1616syn keyword zigConstant null undefined
17syn keyword zigKeyword fn import
17syn keyword zigKeyword fn import c_import
1818syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 void unreachable type error
1919syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong
2020
example/hello_world/hello_libc.zig+2-4
......@@ -1,9 +1,7 @@
1#link("c")
12export executable "hello";
23
3#link("c")
4extern {
5 fn printf(__format: &const u8, ...) -> c_int;
6}
4extern fn printf(__format: &const u8, ...) -> c_int;
75
86export fn main(argc: c_int, argv: &&u8) -> c_int {
97 printf(c"Hello, world!\n");
src/all_types.hpp+6-10
......@@ -121,7 +121,6 @@ enum NodeType {
121121 NodeTypeFnDecl,
122122 NodeTypeParamDecl,
123123 NodeTypeBlock,
124 NodeTypeExternBlock,
125124 NodeTypeDirective,
126125 NodeTypeReturnExpr,
127126 NodeTypeVariableDeclaration,
......@@ -178,11 +177,10 @@ struct AstNodeFnProto {
178177 ZigList<AstNode *> params;
179178 AstNode *return_type;
180179 bool is_var_args;
180 bool is_extern;
181181
182182 // populated by semantic analyzer:
183183
184 // the extern block this fn proto is inside. can be null.
185 AstNode *extern_node;
186184 // the struct decl node this fn proto is inside. can be null.
187185 AstNode *struct_node;
188186 // the function definition this fn proto is inside. can be null.
......@@ -247,6 +245,7 @@ struct AstNodeVariableDeclaration {
247245 // one or both of type and expr will be non null
248246 AstNode *type;
249247 AstNode *expr;
248 ZigList<AstNode *> *directives;
250249
251250 // populated by semantic analyzer
252251 TopLevelDecl top_level_decl;
......@@ -255,8 +254,9 @@ struct AstNodeVariableDeclaration {
255254};
256255
257256struct AstNodeErrorValueDecl {
258 VisibMod visib_mod;
259257 Buf name;
258 VisibMod visib_mod;
259 ZigList<AstNode *> *directives;
260260
261261 // populated by semantic analyzer
262262 TopLevelDecl top_level_decl;
......@@ -378,11 +378,6 @@ struct AstNodeFieldAccessExpr {
378378 StructValExprCodeGen resolved_struct_val_expr; // for enum values
379379};
380380
381struct AstNodeExternBlock {
382 ZigList<AstNode *> *directives;
383 ZigList<AstNode *> fn_decls;
384};
385
386381struct AstNodeDirective {
387382 Buf name;
388383 Buf param;
......@@ -418,6 +413,7 @@ struct AstNodePrefixOpExpr {
418413struct AstNodeUse {
419414 Buf path;
420415 ZigList<AstNode *> *directives;
416 VisibMod visib_mod;
421417
422418 // populated by semantic analyzer
423419 ImportTableEntry *import;
......@@ -559,6 +555,7 @@ struct AstNodeStructField {
559555 Buf name;
560556 AstNode *type;
561557 ZigList<AstNode *> *directives;
558 VisibMod visib_mod;
562559};
563560
564561struct AstNodeStringLiteral {
......@@ -697,7 +694,6 @@ struct AstNode {
697694 AstNodeErrorValueDecl error_value_decl;
698695 AstNodeBinOpExpr bin_op_expr;
699696 AstNodeUnwrapErrorExpr unwrap_err_expr;
700 AstNodeExternBlock extern_block;
701697 AstNodeDirective directive;
702698 AstNodePrefixOpExpr prefix_op_expr;
703699 AstNodeFnCallExpr fn_call_expr;
src/analyze.cpp+6-35
......@@ -45,7 +45,6 @@ static AstNode *first_executing_node(AstNode *node) {
4545 case NodeTypeFnDecl:
4646 case NodeTypeParamDecl:
4747 case NodeTypeBlock:
48 case NodeTypeExternBlock:
4948 case NodeTypeDirective:
5049 case NodeTypeReturnExpr:
5150 case NodeTypeVariableDeclaration:
......@@ -897,8 +896,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
897896 AstNode *proto_node)
898897{
899898 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
900 AstNode *extern_node = proto_node->data.fn_proto.extern_node;
901899 AstNode *struct_node = proto_node->data.fn_proto.struct_node;
900 bool is_extern = proto_node->data.fn_proto.is_extern;
902901 TypeTableEntry *struct_type;
903902 if (struct_node) {
904903 assert(struct_node->type == NodeTypeStructDecl);
......@@ -914,7 +913,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
914913 auto entry = fn_table->maybe_get(proto_name);
915914 bool skip = false;
916915 bool is_internal = (proto_node->data.fn_proto.visib_mod != VisibModExport);
917 bool is_c_compat = !is_internal || extern_node;
916 bool is_c_compat = !is_internal || is_extern;
918917 bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate);
919918 if (entry) {
920919 add_node_error(g, proto_node,
......@@ -922,7 +921,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
922921 proto_node->data.fn_proto.skip = true;
923922 skip = true;
924923 }
925 if (!extern_node && proto_node->data.fn_proto.is_var_args) {
924 if (!is_extern && proto_node->data.fn_proto.is_var_args) {
926925 add_node_error(g, proto_node,
927926 buf_sprintf("variadic arguments only allowed in extern functions"));
928927 }
......@@ -935,7 +934,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
935934 fn_table_entry->proto_node = proto_node;
936935 fn_table_entry->fn_def_node = fn_def_node;
937936 fn_table_entry->internal_linkage = !is_c_compat;
938 fn_table_entry->is_extern = extern_node;
937 fn_table_entry->is_extern = is_extern;
939938 fn_table_entry->label_table.init(8);
940939 fn_table_entry->member_of_struct = struct_type;
941940
......@@ -950,7 +949,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
950949
951950 g->fn_protos.append(fn_table_entry);
952951
953 if (!extern_node) {
952 if (!is_extern) {
954953 g->fn_defs.append(fn_table_entry);
955954 }
956955
......@@ -1021,19 +1020,6 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo
10211020
10221021static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
10231022 switch (node->type) {
1024 case NodeTypeExternBlock:
1025 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {
1026 AstNode *directive_node = node->data.extern_block.directives->at(i);
1027 Buf *name = &directive_node->data.directive.name;
1028 Buf *param = &directive_node->data.directive.param;
1029 if (buf_eql_str(name, "link")) {
1030 g->link_table.put(param, true);
1031 } else {
1032 add_node_error(g, directive_node,
1033 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
1034 }
1035 }
1036 break;
10371023 case NodeTypeFnProto:
10381024 preview_fn_proto(g, import, node);
10391025 break;
......@@ -4051,7 +4037,6 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
40514037 case NodeTypeParamDecl:
40524038 case NodeTypeRoot:
40534039 case NodeTypeRootExportDecl:
4054 case NodeTypeExternBlock:
40554040 case NodeTypeFnDef:
40564041 case NodeTypeUse:
40574042 case NodeTypeLabel:
......@@ -4155,15 +4140,14 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
41554140 break;
41564141 }
41574142 case NodeTypeRootExportDecl:
4158 case NodeTypeExternBlock:
41594143 case NodeTypeUse:
41604144 case NodeTypeVariableDeclaration:
41614145 case NodeTypeErrorValueDecl:
4146 case NodeTypeFnProto:
41624147 // already took care of these
41634148 break;
41644149 case NodeTypeDirective:
41654150 case NodeTypeParamDecl:
4166 case NodeTypeFnProto:
41674151 case NodeTypeFnDecl:
41684152 case NodeTypeReturnExpr:
41694153 case NodeTypeRoot:
......@@ -4350,7 +4334,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
43504334 break;
43514335 case NodeTypeVariableDeclaration:
43524336 case NodeTypeFnProto:
4353 case NodeTypeExternBlock:
43544337 case NodeTypeRootExportDecl:
43554338 case NodeTypeFnDef:
43564339 case NodeTypeRoot:
......@@ -4453,16 +4436,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
44534436
44544437 break;
44554438 }
4456 case NodeTypeExternBlock:
4457 for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) {
4458 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
4459 assert(fn_decl->type == NodeTypeFnDecl);
4460 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
4461 fn_proto->data.fn_proto.extern_node = node;
4462 detect_top_level_decl_deps(g, import, fn_proto);
4463 }
4464 resolve_top_level_decl(g, import, node);
4465 break;
44664439 case NodeTypeFnDef:
44674440 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;
44684441 detect_top_level_decl_deps(g, import, node->data.fn_def.fn_proto);
......@@ -4786,7 +4759,6 @@ Expr *get_resolved_expr(AstNode *node) {
47864759 case NodeTypeFnDef:
47874760 case NodeTypeFnDecl:
47884761 case NodeTypeParamDecl:
4789 case NodeTypeExternBlock:
47904762 case NodeTypeDirective:
47914763 case NodeTypeUse:
47924764 case NodeTypeStructDecl:
......@@ -4832,7 +4804,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
48324804 case NodeTypeFnDecl:
48334805 case NodeTypeParamDecl:
48344806 case NodeTypeBlock:
4835 case NodeTypeExternBlock:
48364807 case NodeTypeDirective:
48374808 case NodeTypeStringLiteral:
48384809 case NodeTypeCharLiteral:
src/codegen.cpp+5-15
......@@ -2249,7 +2249,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
22492249 case NodeTypeFnDef:
22502250 case NodeTypeFnDecl:
22512251 case NodeTypeParamDecl:
2252 case NodeTypeExternBlock:
22532252 case NodeTypeDirective:
22542253 case NodeTypeUse:
22552254 case NodeTypeStructDecl:
......@@ -3001,18 +3000,6 @@ static void init(CodeGen *g, Buf *source_path) {
30013000
30023001}
30033002
3004static bool directives_contains_link_libc(ZigList<AstNode*> *directives) {
3005 for (int i = 0; i < directives->length; i += 1) {
3006 AstNode *directive_node = directives->at(i);
3007 if (buf_eql_str(&directive_node->data.directive.name, "link") &&
3008 buf_eql_str(&directive_node->data.directive.param, "c"))
3009 {
3010 return true;
3011 }
3012 }
3013 return false;
3014}
3015
30163003static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
30173004 char *dot1 = strstr(buf_ptr(buf), ".");
30183005 if (!dot1)
......@@ -3114,6 +3101,11 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
31143101 Buf *param = &directive_node->data.directive.param;
31153102 if (buf_eql_str(name, "version")) {
31163103 set_root_export_version(g, param, directive_node);
3104 } else if (buf_eql_str(name, "link")) {
3105 g->link_table.put(param, true);
3106 if (buf_eql_str(param, "c")) {
3107 g->link_libc = true;
3108 }
31173109 } else {
31183110 add_node_error(g, directive_node,
31193111 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
......@@ -3204,8 +3196,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
32043196 if (buf_eql_str(proto_name, "main") && !is_private) {
32053197 g->have_exported_main = true;
32063198 }
3207 } else if (top_level_decl->type == NodeTypeExternBlock) {
3208 g->link_libc = directives_contains_link_libc(top_level_decl->data.extern_block.directives);
32093199 }
32103200 }
32113201
src/parser.cpp+132-261
......@@ -105,8 +105,6 @@ const char *node_type_str(NodeType node_type) {
105105 return "ArrayAccessExpr";
106106 case NodeTypeSliceExpr:
107107 return "SliceExpr";
108 case NodeTypeExternBlock:
109 return "ExternBlock";
110108 case NodeTypeDirective:
111109 return "Directive";
112110 case NodeTypeReturnExpr:
......@@ -258,15 +256,6 @@ void ast_print(AstNode *node, int indent) {
258256 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
259257 break;
260258 }
261 case NodeTypeExternBlock:
262 {
263 fprintf(stderr, "%s\n", node_type_str(node->type));
264 for (int i = 0; i < node->data.extern_block.fn_decls.length; i += 1) {
265 AstNode *child = node->data.extern_block.fn_decls.at(i);
266 ast_print(child, indent + 2);
267 }
268 break;
269 }
270259 case NodeTypeFnDecl:
271260 fprintf(stderr, "%s\n", node_type_str(node->type));
272261 ast_print(node->data.fn_decl.fn_proto, indent + 2);
......@@ -482,9 +471,9 @@ struct ParseContext {
482471 Buf *buf;
483472 AstNode *root;
484473 ZigList<Token> *tokens;
485 ZigList<AstNode *> *directive_list;
486474 ImportTableEntry *owner;
487475 ErrColor err_color;
476 bool parsed_root_export;
488477 uint32_t *next_node_index;
489478};
490479
......@@ -2146,56 +2135,32 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
21462135}
21472136
21482137/*
2149VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))
2138VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))
21502139*/
2151static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {
2140static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory,
2141 ZigList<AstNode*> *directives, VisibMod visib_mod)
2142{
21522143 Token *first_token = &pc->tokens->at(*token_index);
21532144
2154 VisibMod visib_mod;
21552145 bool is_const;
21562146
2157 if (first_token->id == TokenIdKeywordPub) {
2158 Token *next_token = &pc->tokens->at(*token_index + 1);
2159 if (next_token->id == TokenIdKeywordVar ||
2160 next_token->id == TokenIdKeywordConst)
2161 {
2162 visib_mod = VisibModPub;
2163 is_const = (next_token->id == TokenIdKeywordConst);
2164 *token_index += 2;
2165 } else if (mandatory) {
2166 ast_invalid_token_error(pc, next_token);
2167 } else {
2168 return nullptr;
2169 }
2170 } else if (first_token->id == TokenIdKeywordExport) {
2171 Token *next_token = &pc->tokens->at(*token_index + 1);
2172 if (next_token->id == TokenIdKeywordVar ||
2173 next_token->id == TokenIdKeywordConst)
2174 {
2175 visib_mod = VisibModExport;
2176 is_const = (next_token->id == TokenIdKeywordConst);
2177 *token_index += 2;
2178 } else if (mandatory) {
2179 ast_invalid_token_error(pc, next_token);
2180 } else {
2181 return nullptr;
2182 }
2183 } else if (first_token->id == TokenIdKeywordVar ||
2184 first_token->id == TokenIdKeywordConst)
2185 {
2186 visib_mod = VisibModPrivate;
2187 is_const = (first_token->id == TokenIdKeywordConst);
2188 *token_index += 1;
2147 if (first_token->id == TokenIdKeywordVar) {
2148 is_const = false;
2149 } else if (first_token->id == TokenIdKeywordConst) {
2150 is_const = true;
21892151 } else if (mandatory) {
21902152 ast_invalid_token_error(pc, first_token);
21912153 } else {
21922154 return nullptr;
21932155 }
21942156
2157 *token_index += 1;
2158
21952159 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);
21962160
21972161 node->data.variable_declaration.is_const = is_const;
21982162 node->data.variable_declaration.visib_mod = visib_mod;
2163 node->data.variable_declaration.directives = directives;
21992164
22002165 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
22012166 ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);
......@@ -2643,7 +2608,8 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
26432608 if (statement_node) {
26442609 semicolon_expected = false;
26452610 } else {
2646 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false);
2611 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,
2612 nullptr, VisibModPrivate);
26472613 if (statement_node) {
26482614 semicolon_expected = true;
26492615 } else {
......@@ -2677,47 +2643,25 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
26772643}
26782644
26792645/*
2680FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
2646FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
26812647*/
2682static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) {
2648static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
2649 ZigList<AstNode*> *directives, VisibMod visib_mod)
2650{
26832651 Token *first_token = &pc->tokens->at(*token_index);
26842652
2685 VisibMod visib_mod;
2686
2687 if (first_token->id == TokenIdKeywordPub) {
2688 Token *next_token = &pc->tokens->at(*token_index + 1);
2689 if (next_token->id == TokenIdKeywordFn) {
2690 visib_mod = VisibModPub;
2691 *token_index += 2;
2692 } else if (mandatory) {
2693 ast_invalid_token_error(pc, first_token);
2694 } else {
2695 return nullptr;
2696 }
2697 } else if (first_token->id == TokenIdKeywordExport) {
2698 Token *next_token = &pc->tokens->at(*token_index + 1);
2699 if (next_token->id == TokenIdKeywordFn) {
2700 visib_mod = VisibModExport;
2701 *token_index += 2;
2702 } else if (mandatory) {
2703 ast_invalid_token_error(pc, first_token);
2653 if (first_token->id != TokenIdKeywordFn) {
2654 if (mandatory) {
2655 ast_expect_token(pc, first_token, TokenIdKeywordFn);
27042656 } else {
27052657 return nullptr;
27062658 }
2707 } else if (first_token->id == TokenIdKeywordFn) {
2708 visib_mod = VisibModPrivate;
2709 *token_index += 1;
2710 } else if (mandatory) {
2711 ast_invalid_token_error(pc, first_token);
2712 } else {
2713 return nullptr;
27142659 }
2660 *token_index += 1;
27152661
27162662 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);
27172663 node->data.fn_proto.visib_mod = visib_mod;
2718 node->data.fn_proto.directives = pc->directive_list;
2719 pc->directive_list = nullptr;
2720
2664 node->data.fn_proto.directives = directives;
27212665
27222666 Token *fn_name = &pc->tokens->at(*token_index);
27232667 *token_index += 1;
......@@ -2743,107 +2687,59 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
27432687/*
27442688FnDef : FnProto Block
27452689*/
2746static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) {
2747 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory);
2690static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory,
2691 ZigList<AstNode*> *directives, VisibMod visib_mod)
2692{
2693 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod);
27482694 if (!fn_proto)
27492695 return nullptr;
27502696 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);
27512697
27522698 node->data.fn_def.fn_proto = fn_proto;
27532699 node->data.fn_def.body = ast_parse_block(pc, token_index, true);
2754
2755 normalize_parent_ptrs(node);
2756 return node;
2757}
2758
2759/*
2760FnDecl : FnProto token(Semicolon)
2761*/
2762static AstNode *ast_parse_fn_decl(ParseContext *pc, int *token_index) {
2763 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, true);
2764 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDecl, fn_proto);
2765
2766 node->data.fn_decl.fn_proto = fn_proto;
2767
2768 Token *semicolon = &pc->tokens->at(*token_index);
2769 *token_index += 1;
2770 ast_expect_token(pc, semicolon, TokenIdSemicolon);
2771
27722700 normalize_parent_ptrs(node);
27732701 return node;
27742702}
27752703
27762704/*
2777Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)
2778*/
2779/*
2780ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnProtoDecl) token(RBrace)
2705ExternDecl : "extern" FnProto ";"
27812706*/
2782static AstNode *ast_parse_extern_block(ParseContext *pc, int *token_index, bool mandatory) {
2707static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool mandatory,
2708 ZigList<AstNode *> *directives, VisibMod visib_mod)
2709{
27832710 Token *extern_kw = &pc->tokens->at(*token_index);
27842711 if (extern_kw->id != TokenIdKeywordExtern) {
2785 if (mandatory)
2712 if (mandatory) {
27862713 ast_invalid_token_error(pc, extern_kw);
2787 else
2714 } else {
27882715 return nullptr;
2716 }
27892717 }
27902718 *token_index += 1;
27912719
2792 AstNode *node = ast_create_node(pc, NodeTypeExternBlock, extern_kw);
2793
2794 node->data.extern_block.directives = pc->directive_list;
2795 pc->directive_list = nullptr;
2796
2797 Token *l_brace = &pc->tokens->at(*token_index);
2798 *token_index += 1;
2799 ast_expect_token(pc, l_brace, TokenIdLBrace);
2800
2801 for (;;) {
2802 Token *directive_token = &pc->tokens->at(*token_index);
2803 assert(!pc->directive_list);
2804 pc->directive_list = allocate<ZigList<AstNode*>>(1);
2805 ast_parse_directives(pc, token_index, pc->directive_list);
2806
2807 Token *token = &pc->tokens->at(*token_index);
2808 if (token->id == TokenIdRBrace) {
2809 if (pc->directive_list->length > 0) {
2810 ast_error(pc, directive_token, "invalid directive");
2811 }
2812 pc->directive_list = nullptr;
2813
2814 *token_index += 1;
2815
2816 normalize_parent_ptrs(node);
2817 return node;
2818 } else {
2819 AstNode *child = ast_parse_fn_decl(pc, token_index);
2820 node->data.extern_block.fn_decls.append(child);
2821 }
2822 }
2720 AstNode *node = ast_parse_fn_proto(pc, token_index, true, directives, visib_mod);
28232721
2722 ast_eat_token(pc, token_index, TokenIdSemicolon);
28242723
2825 zig_unreachable();
2724 node->data.fn_proto.is_extern = true;
2725 normalize_parent_ptrs(node);
2726 return node;
28262727}
28272728
28282729/*
2829RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon)
2730RootExportDecl : "export" "Symbol" "String" ";"
28302731*/
2831static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, bool mandatory) {
2832 assert(mandatory == false);
2833
2834 Token *export_kw = &pc->tokens->at(*token_index);
2835 if (export_kw->id != TokenIdKeywordExport)
2836 return nullptr;
2837
2838 Token *export_type = &pc->tokens->at(*token_index + 1);
2732static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index,
2733 ZigList<AstNode*> *directives)
2734{
2735 Token *export_type = &pc->tokens->at(*token_index);
28392736 if (export_type->id != TokenIdSymbol)
28402737 return nullptr;
28412738
2842 *token_index += 2;
2739 *token_index += 1;
28432740
2844 AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_kw);
2845 node->data.root_export_decl.directives = pc->directive_list;
2846 pc->directive_list = nullptr;
2741 AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_type);
2742 node->data.root_export_decl.directives = directives;
28472743
28482744 ast_buf_from_token(pc, export_type, &node->data.root_export_decl.type);
28492745
......@@ -2862,11 +2758,13 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
28622758}
28632759
28642760/*
2865Use : many(Directive) token(Use) token(String) token(Semicolon)
2761Import : "import" "String" ";"
28662762*/
2867static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {
2868 Token *use_kw = &pc->tokens->at(*token_index);
2869 if (use_kw->id != TokenIdKeywordImport)
2763static AstNode *ast_parse_import(ParseContext *pc, int *token_index,
2764 ZigList<AstNode*> *directives, VisibMod visib_mod)
2765{
2766 Token *import_kw = &pc->tokens->at(*token_index);
2767 if (import_kw->id != TokenIdKeywordImport)
28702768 return nullptr;
28712769 *token_index += 1;
28722770
......@@ -2878,59 +2776,35 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {
28782776 *token_index += 1;
28792777 ast_expect_token(pc, semicolon, TokenIdSemicolon);
28802778
2881 AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);
2779 AstNode *node = ast_create_node(pc, NodeTypeUse, import_kw);
2780 node->data.use.visib_mod = visib_mod;
2781 node->data.use.directives = directives;
28822782
28832783 parse_string_literal(pc, use_name, &node->data.use.path, nullptr, nullptr);
2884
2885 node->data.use.directives = pc->directive_list;
2886 pc->directive_list = nullptr;
2887
28882784 normalize_parent_ptrs(node);
28892785 return node;
28902786}
28912787
28922788/*
2893ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
2894StructMember: StructField | FnDecl
2895StructField : token(Symbol) option(token(Colon) Expression) token(Comma))
2789ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
2790StructMember: many(Directive) option(VisibleMod) (StructField | FnDef)
2791StructField : "Symbol" option(":" Expression) ",")
28962792*/
2897static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2793static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
2794 ZigList<AstNode*> *directives, VisibMod visib_mod)
2795{
28982796 Token *first_token = &pc->tokens->at(*token_index);
28992797
2900 VisibMod visib_mod;
29012798 ContainerKind kind;
29022799
2903 if (first_token->id == TokenIdKeywordPub) {
2904 Token *next_token = &pc->tokens->at(*token_index + 1);
2905 if (next_token->id == TokenIdKeywordStruct ||
2906 next_token->id == TokenIdKeywordEnum)
2907 {
2908 visib_mod = VisibModPub;
2909 kind = (next_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum;
2910 *token_index += 2;
2911 } else {
2912 return nullptr;
2913 }
2914 } else if (first_token->id == TokenIdKeywordExport) {
2915 Token *next_token = &pc->tokens->at(*token_index + 1);
2916 if (next_token->id == TokenIdKeywordStruct ||
2917 next_token->id == TokenIdKeywordEnum)
2918 {
2919 visib_mod = VisibModExport;
2920 kind = (next_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum;
2921 *token_index += 2;
2922 } else {
2923 return nullptr;
2924 }
2925 } else if (first_token->id == TokenIdKeywordStruct ||
2926 first_token->id == TokenIdKeywordEnum)
2927 {
2928 visib_mod = VisibModPrivate;
2929 kind = (first_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum;
2930 *token_index += 1;
2800 if (first_token->id == TokenIdKeywordStruct) {
2801 kind = ContainerKindStruct;
2802 } else if (first_token->id == TokenIdKeywordEnum) {
2803 kind = ContainerKindEnum;
29312804 } else {
29322805 return nullptr;
29332806 }
2807 *token_index += 1;
29342808
29352809 Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol);
29362810
......@@ -2938,19 +2812,28 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
29382812 node->data.struct_decl.kind = kind;
29392813 ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);
29402814 node->data.struct_decl.visib_mod = visib_mod;
2815 node->data.struct_decl.directives = directives;
29412816
29422817 ast_eat_token(pc, token_index, TokenIdLBrace);
29432818
2944 node->data.struct_decl.directives = pc->directive_list;
2945 pc->directive_list = nullptr;
2946
29472819 for (;;) {
2948 assert(!pc->directive_list);
2949 pc->directive_list = allocate<ZigList<AstNode*>>(1);
29502820 Token *directive_token = &pc->tokens->at(*token_index);
2951 ast_parse_directives(pc, token_index, pc->directive_list);
2821 ZigList<AstNode *> *directive_list = allocate<ZigList<AstNode*>>(1);
2822 ast_parse_directives(pc, token_index, directive_list);
2823
2824 Token *visib_tok = &pc->tokens->at(*token_index);
2825 VisibMod visib_mod;
2826 if (visib_tok->id == TokenIdKeywordPub) {
2827 *token_index += 1;
2828 visib_mod = VisibModPub;
2829 } else if (visib_tok->id == TokenIdKeywordExport) {
2830 *token_index += 1;
2831 visib_mod = VisibModExport;
2832 } else {
2833 visib_mod = VisibModPrivate;
2834 }
29522835
2953 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false);
2836 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directive_list, visib_mod);
29542837 if (fn_def_node) {
29552838 node->data.struct_decl.fns.append(fn_def_node);
29562839 continue;
......@@ -2959,10 +2842,9 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
29592842 Token *token = &pc->tokens->at(*token_index);
29602843
29612844 if (token->id == TokenIdRBrace) {
2962 if (pc->directive_list->length > 0) {
2845 if (directive_list->length > 0) {
29632846 ast_error(pc, directive_token, "invalid directive");
29642847 }
2965 pc->directive_list = nullptr;
29662848
29672849 *token_index += 1;
29682850 break;
......@@ -2970,8 +2852,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
29702852 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
29712853 *token_index += 1;
29722854
2973 field_node->data.struct_field.directives = pc->directive_list;
2974 pc->directive_list = nullptr;
2855 field_node->data.struct_field.visib_mod = visib_mod;
2856 field_node->data.struct_field.directives = directive_list;
29752857
29762858 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);
29772859
......@@ -2997,47 +2879,24 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
29972879}
29982880
29992881/*
3000ErrorValueDecl : option(FnVisibleMod) "error" "Symbol"
2882ErrorValueDecl : "error" "Symbol" ";"
30012883*/
3002static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, bool mandatory) {
2884static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,
2885 ZigList<AstNode*> *directives, VisibMod visib_mod)
2886{
30032887 Token *first_token = &pc->tokens->at(*token_index);
30042888
3005 VisibMod visib_mod;
3006
3007 if (first_token->id == TokenIdKeywordPub) {
3008 Token *next_token = &pc->tokens->at(*token_index + 1);
3009 if (next_token->id == TokenIdKeywordError) {
3010 visib_mod = VisibModPub;
3011 *token_index += 2;
3012 } else if (mandatory) {
3013 ast_invalid_token_error(pc, next_token);
3014 } else {
3015 return nullptr;
3016 }
3017 } else if (first_token->id == TokenIdKeywordExport) {
3018 Token *next_token = &pc->tokens->at(*token_index + 1);
3019 if (next_token->id == TokenIdKeywordError) {
3020 visib_mod = VisibModExport;
3021 *token_index += 2;
3022 } else if (mandatory) {
3023 ast_invalid_token_error(pc, next_token);
3024 } else {
3025 return nullptr;
3026 }
3027 } else if (first_token->id == TokenIdKeywordError) {
3028 visib_mod = VisibModPrivate;
3029 *token_index += 1;
3030 } else if (mandatory) {
3031 ast_invalid_token_error(pc, first_token);
3032 } else {
2889 if (first_token->id != TokenIdKeywordError) {
30332890 return nullptr;
30342891 }
2892 *token_index += 1;
30352893
30362894 Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
30372895 ast_eat_token(pc, token_index, TokenIdSemicolon);
30382896
30392897 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
30402898 node->data.error_value_decl.visib_mod = visib_mod;
2899 node->data.error_value_decl.directives = directives;
30412900 ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name);
30422901
30432902 normalize_parent_ptrs(node);
......@@ -3045,63 +2904,79 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b
30452904}
30462905
30472906/*
3048TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl
2907TopLevelDecl : many(Directive) option(FnVisibleMod) (FnDef | ExternFnProto | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl | CImportDecl)
30492908*/
30502909static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
30512910 for (;;) {
30522911 Token *directive_token = &pc->tokens->at(*token_index);
3053 assert(!pc->directive_list);
3054 pc->directive_list = allocate<ZigList<AstNode*>>(1);
3055 ast_parse_directives(pc, token_index, pc->directive_list);
2912 ZigList<AstNode *> *directives = allocate<ZigList<AstNode*>>(1);
2913 ast_parse_directives(pc, token_index, directives);
30562914
3057 AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, false);
3058 if (root_export_decl_node) {
3059 top_level_decls->append(root_export_decl_node);
3060 continue;
2915 Token *visib_tok = &pc->tokens->at(*token_index);
2916 VisibMod visib_mod;
2917 if (visib_tok->id == TokenIdKeywordPub) {
2918 *token_index += 1;
2919 visib_mod = VisibModPub;
2920 } else if (visib_tok->id == TokenIdKeywordExport) {
2921 *token_index += 1;
2922 visib_mod = VisibModExport;
2923 } else {
2924 visib_mod = VisibModPrivate;
30612925 }
30622926
3063 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false);
2927 bool try_to_parse_root_export = (visib_mod == VisibModExport && !pc->parsed_root_export);
2928 pc->parsed_root_export = true;
2929
2930 if (try_to_parse_root_export) {
2931 AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, directives);
2932 if (root_export_decl_node) {
2933 top_level_decls->append(root_export_decl_node);
2934 continue;
2935 }
2936 }
2937
2938 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);
30642939 if (fn_def_node) {
30652940 top_level_decls->append(fn_def_node);
30662941 continue;
30672942 }
30682943
3069 AstNode *extern_node = ast_parse_extern_block(pc, token_index, false);
3070 if (extern_node) {
3071 top_level_decls->append(extern_node);
2944 AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, directives, visib_mod);
2945 if (fn_proto_node) {
2946 top_level_decls->append(fn_proto_node);
30722947 continue;
30732948 }
30742949
3075 AstNode *use_node = ast_parse_use(pc, token_index);
3076 if (use_node) {
3077 top_level_decls->append(use_node);
2950 AstNode *import_node = ast_parse_import(pc, token_index, directives, visib_mod);
2951 if (import_node) {
2952 top_level_decls->append(import_node);
30782953 continue;
30792954 }
30802955
3081 AstNode *struct_node = ast_parse_struct_decl(pc, token_index);
2956 AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod);
30822957 if (struct_node) {
30832958 top_level_decls->append(struct_node);
30842959 continue;
30852960 }
30862961
3087 if (pc->directive_list->length > 0) {
3088 ast_error(pc, directive_token, "invalid directive");
3089 }
3090 pc->directive_list = nullptr;
3091
3092 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false);
2962 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false,
2963 directives, visib_mod);
30932964 if (var_decl_node) {
30942965 ast_eat_token(pc, token_index, TokenIdSemicolon);
30952966 top_level_decls->append(var_decl_node);
30962967 continue;
30972968 }
30982969
3099 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, false);
2970 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, directives, visib_mod);
31002971 if (error_value_node) {
31012972 top_level_decls->append(error_value_node);
31022973 continue;
31032974 }
31042975
2976 if (directives->length > 0) {
2977 ast_error(pc, directive_token, "invalid directive");
2978 }
2979
31052980 return;
31062981 }
31072982 zig_unreachable();
......@@ -3175,10 +3050,6 @@ void normalize_parent_ptrs(AstNode *node) {
31753050 case NodeTypeBlock:
31763051 set_list_fields(&node->data.block.statements);
31773052 break;
3178 case NodeTypeExternBlock:
3179 set_list_fields(node->data.extern_block.directives);
3180 set_list_fields(&node->data.extern_block.fn_decls);
3181 break;
31823053 case NodeTypeDirective:
31833054 // none
31843055 break;
test/run_tests.cpp+8-15
......@@ -97,10 +97,8 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
9797static void add_compiling_test_cases(void) {
9898 add_simple_case("hello world with libc", R"SOURCE(
9999#link("c")
100extern {
101 fn puts(s: &const u8) -> c_int;
102}
103
100export executable "test";
101extern fn puts(s: &const u8) -> c_int;
104102export fn main(argc: c_int, argv: &&u8) -> c_int {
105103 puts(c"Hello, world!");
106104 return 0;
......@@ -482,9 +480,8 @@ pub fn main(args: [][]u8) -> %void {
482480
483481 add_simple_case("number literals", R"SOURCE(
484482#link("c")
485extern {
486 fn printf(__format: &const u8, ...) -> c_int;
487}
483export executable "test";
484extern fn printf(__format: &const u8, ...) -> c_int;
488485
489486export fn main(argc: c_int, argv: &&u8) -> c_int {
490487 printf(c"\n");
......@@ -1321,13 +1318,11 @@ fn a() {}
13211318
13221319 add_compile_fail_case("bad directive", R"SOURCE(
13231320#bogus1("")
1324extern {
1325 fn b();
1326}
1321extern fn b();
13271322#bogus2("")
13281323fn a() {}
13291324 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
1330 ".tmp_source.zig:6:1: error: invalid directive: 'bogus2'");
1325 ".tmp_source.zig:4:1: error: invalid directive: 'bogus2'");
13311326
13321327 add_compile_fail_case("unreachable with return", R"SOURCE(
13331328fn a() -> unreachable {return;}
......@@ -1668,11 +1663,9 @@ fn f() {
16681663 )SOURCE", 1, ".tmp_source.zig:6:9: error: multiple else prongs in switch expression");
16691664
16701665 add_compile_fail_case("global variable initializer must be constant expression", R"SOURCE(
1671extern {
1672 fn foo() -> i32;
1673}
1666extern fn foo() -> i32;
16741667const x = foo();
1675 )SOURCE", 1, ".tmp_source.zig:5:11: error: global variable initializer requires constant expression");
1668 )SOURCE", 1, ".tmp_source.zig:3:11: error: global variable initializer requires constant expression");
16761669
16771670 add_compile_fail_case("non compile time string concatenation", R"SOURCE(
16781671fn f(s: []u8) -> []u8 {