authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-19 01:19:49-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-19 01:19:49-05:00
logc627f9ea18b5f194860c6bf3730f3f0407c224f2
tree63b2d0386cd6302707a63220f3ded913a0383542
parent1fdebc1dc4881a00766f7c2b4b2d8ee6ad6e79b6

wip bring back export keyword


7 files changed, 112 insertions(+), 60 deletions(-)

doc/langref.html.in+8-6
...@@ -5819,9 +5819,11 @@ TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl)...@@ -5819,9 +5819,11 @@ TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
58195819
5820ErrorValueDecl = "error" Symbol ";"5820ErrorValueDecl = "error" Symbol ";"
58215821
5822GlobalVarDecl = VariableDeclaration ";"5822GlobalVarDecl = option("export") VariableDeclaration ";"
58235823
5824VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression5824LocalVarDecl = option("comptime") VariableDeclaration
5825
5826VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression
58255827
5826ContainerMember = (ContainerField | FnDef | GlobalVarDecl)5828ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
58275829
...@@ -5831,9 +5833,9 @@ UseDecl = "use" Expression ";"...@@ -5831,9 +5833,9 @@ UseDecl = "use" Expression ";"
58315833
5832ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"5834ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
58335835
5834FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr)5836FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr)
58355837
5836FnDef = option("inline" | "extern") FnProto Block5838FnDef = option("inline" | "export") FnProto Block
58375839
5838ParamDeclList = "(" list(ParamDecl, ",") ")"5840ParamDeclList = "(" list(ParamDecl, ",") ")"
58395841
...@@ -5841,7 +5843,7 @@ ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...")...@@ -5841,7 +5843,7 @@ ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...")
58415843
5842Block = "{" many(Statement) option(Expression) "}"5844Block = "{" many(Statement) option(Expression) "}"
58435845
5844Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";"5846Statement = Label | LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";"
58455847
5846Label = Symbol ":"5848Label = Symbol ":"
58475849
...@@ -5947,7 +5949,7 @@ StructLiteralField = "." Symbol "=" Expression...@@ -5947,7 +5949,7 @@ StructLiteralField = "." Symbol "=" Expression
59475949
5948PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"5950PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%"
59495951
5950PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl5952PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl
59515953
5952ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr5954ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr
59535955
src/all_types.hpp+3-7
...@@ -315,12 +315,6 @@ struct TldVar {...@@ -315,12 +315,6 @@ struct TldVar {
315 VariableTableEntry *var;315 VariableTableEntry *var;
316 Buf *extern_lib_name;316 Buf *extern_lib_name;
317 Buf *section_name;317 Buf *section_name;
318
319 size_t export_count;
320 union {
321 TldExport *tld; // if export_count == 1
322 TldExport **tld_list; // if export_count > 1
323 } export_data;
324};318};
325319
326struct TldFn {320struct TldFn {
...@@ -428,6 +422,7 @@ struct AstNodeFnProto {...@@ -428,6 +422,7 @@ struct AstNodeFnProto {
428 AstNode *return_type;422 AstNode *return_type;
429 bool is_var_args;423 bool is_var_args;
430 bool is_extern;424 bool is_extern;
425 bool is_export;
431 bool is_inline;426 bool is_inline;
432 CallingConvention cc;427 CallingConvention cc;
433 AstNode *fn_def_node;428 AstNode *fn_def_node;
...@@ -485,7 +480,8 @@ struct AstNodeVariableDeclaration {...@@ -485,7 +480,8 @@ struct AstNodeVariableDeclaration {
485 VisibMod visib_mod;480 VisibMod visib_mod;
486 Buf *symbol;481 Buf *symbol;
487 bool is_const;482 bool is_const;
488 bool is_inline;483 bool is_comptime;
484 bool is_export;
489 bool is_extern;485 bool is_extern;
490 // one or both of type and expr will be non null486 // one or both of type and expr will be non null
491 AstNode *type;487 AstNode *type;
src/analyze.cpp+27-2
...@@ -1062,7 +1062,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou...@@ -1062,7 +1062,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
1062 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;1062 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
10631063
1064 if (fn_proto->cc == CallingConventionUnspecified) {1064 if (fn_proto->cc == CallingConventionUnspecified) {
1065 bool extern_abi = fn_proto->is_extern;1065 bool extern_abi = fn_proto->is_extern || fn_proto->is_export;
1066 fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified;1066 fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified;
1067 } else {1067 } else {
1068 fn_type_id->cc = fn_proto->cc;1068 fn_type_id->cc = fn_proto->cc;
...@@ -2675,6 +2675,26 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {...@@ -2675,6 +2675,26 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
2675}2675}
26762676
2677static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {2677static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
2678 bool is_export = false;
2679 if (tld->id == TldIdVar) {
2680 assert(tld->source_node->type == NodeTypeVariableDeclaration);
2681 is_export = tld->source_node->data.variable_declaration.is_export;
2682 } else if (tld->id == TldIdFn) {
2683 assert(tld->source_node->type == NodeTypeFnProto);
2684 is_export = tld->source_node->data.fn_proto.is_export;
2685 }
2686 if (is_export) {
2687 g->resolve_queue.append(tld);
2688
2689 auto entry = g->exported_symbol_names.put_unique(tld->name, tld->source_node);
2690 if (entry) {
2691 AstNode *other_source_node = entry->value;
2692 ErrorMsg *msg = add_node_error(g, tld->source_node,
2693 buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name)));
2694 add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here"));
2695 }
2696 }
2697
2678 {2698 {
2679 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);2699 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);
2680 if (entry) {2700 if (entry) {
...@@ -3006,6 +3026,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3006,6 +3026,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
30063026
3007 bool is_const = var_decl->is_const;3027 bool is_const = var_decl->is_const;
3008 bool is_extern = var_decl->is_extern;3028 bool is_extern = var_decl->is_extern;
3029 bool is_export = var_decl->is_export;
30093030
3010 TypeTableEntry *explicit_type = nullptr;3031 TypeTableEntry *explicit_type = nullptr;
3011 if (var_decl->type) {3032 if (var_decl->type) {
...@@ -3013,8 +3034,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3013,8 +3034,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3013 explicit_type = validate_var_type(g, var_decl->type, proposed_type);3034 explicit_type = validate_var_type(g, var_decl->type, proposed_type);
3014 }3035 }
30153036
3037 assert(!is_export || !is_extern);
3038
3016 VarLinkage linkage;3039 VarLinkage linkage;
3017 if (is_extern) {3040 if (is_export) {
3041 linkage = VarLinkageExport;
3042 } else if (is_extern) {
3018 linkage = VarLinkageExternal;3043 linkage = VarLinkageExternal;
3019 } else {3044 } else {
3020 linkage = VarLinkageInternal;3045 linkage = VarLinkageInternal;
src/ir.cpp+1-1
...@@ -5066,7 +5066,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5066,7 +5066,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5066 bool is_const = variable_declaration->is_const;5066 bool is_const = variable_declaration->is_const;
5067 bool is_extern = variable_declaration->is_extern;5067 bool is_extern = variable_declaration->is_extern;
5068 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,5068 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node,
5069 ir_should_inline(irb->exec, scope) || variable_declaration->is_inline);5069 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
5070 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,5070 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
5071 is_const, is_const, is_shadowable, is_comptime);5071 is_const, is_const, is_shadowable, is_comptime);
5072 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node5072 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
src/parser.cpp+70-44
...@@ -676,7 +676,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b...@@ -676,7 +676,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
676}676}
677677
678/*678/*
679PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl679PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl
680KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"680KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
681*/681*/
682static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {682static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
...@@ -791,13 +791,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo...@@ -791,13 +791,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
791 if (container_decl)791 if (container_decl)
792 return container_decl;792 return container_decl;
793793
794 if (token->id == TokenIdKeywordExtern) {
795 *token_index += 1;
796 AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate);
797 node->data.fn_proto.is_extern = true;
798 return node;
799 }
800
801 if (!mandatory)794 if (!mandatory)
802 return nullptr;795 return nullptr;
803796
...@@ -1534,38 +1527,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {...@@ -1534,38 +1527,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
1534}1527}
15351528
1536/*1529/*
1537VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression1530VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression
1538*/1531*/
1539static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,1532static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory,
1540 VisibMod visib_mod)1533 VisibMod visib_mod, bool is_comptime, bool is_export)
1541{1534{
1542 Token *first_token = &pc->tokens->at(*token_index);1535 Token *first_token = &pc->tokens->at(*token_index);
1543 Token *var_token;1536 Token *var_token;
15441537
1545 bool is_const;1538 bool is_const;
1546 bool is_comptime;1539 if (first_token->id == TokenIdKeywordVar) {
1547 if (first_token->id == TokenIdKeywordCompTime) {
1548 is_comptime = true;
1549 var_token = &pc->tokens->at(*token_index + 1);
1550
1551 if (var_token->id == TokenIdKeywordVar) {
1552 is_const = false;
1553 } else if (var_token->id == TokenIdKeywordConst) {
1554 is_const = true;
1555 } else if (mandatory) {
1556 ast_invalid_token_error(pc, var_token);
1557 } else {
1558 return nullptr;
1559 }
1560
1561 *token_index += 2;
1562 } else if (first_token->id == TokenIdKeywordVar) {
1563 is_comptime = false;
1564 is_const = false;1540 is_const = false;
1565 var_token = first_token;1541 var_token = first_token;
1566 *token_index += 1;1542 *token_index += 1;
1567 } else if (first_token->id == TokenIdKeywordConst) {1543 } else if (first_token->id == TokenIdKeywordConst) {
1568 is_comptime = false;
1569 is_const = true;1544 is_const = true;
1570 var_token = first_token;1545 var_token = first_token;
1571 *token_index += 1;1546 *token_index += 1;
...@@ -1577,7 +1552,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to...@@ -1577,7 +1552,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
15771552
1578 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token);1553 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token);
15791554
1580 node->data.variable_declaration.is_inline = is_comptime;1555 node->data.variable_declaration.is_comptime = is_comptime;
1581 node->data.variable_declaration.is_const = is_const;1556 node->data.variable_declaration.is_const = is_const;
1582 node->data.variable_declaration.visib_mod = visib_mod;1557 node->data.variable_declaration.visib_mod = visib_mod;
15831558
...@@ -1620,6 +1595,50 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to...@@ -1620,6 +1595,50 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
1620 return node;1595 return node;
1621}1596}
16221597
1598/*
1599GlobalVarDecl = option("export") VariableDeclaration ";"
1600*/
1601static AstNode *ast_parse_global_var_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) {
1602 Token *first_token = &pc->tokens->at(*token_index);
1603
1604 bool is_export = false;;
1605 if (first_token->id == TokenIdKeywordExport) {
1606 *token_index += 1;
1607 is_export = true;
1608 }
1609
1610 AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, is_export);
1611 if (node == nullptr) {
1612 if (is_export) {
1613 *token_index -= 1;
1614 }
1615 return nullptr;
1616 }
1617 return node;
1618}
1619
1620/*
1621LocalVarDecl = option("comptime") VariableDeclaration
1622*/
1623static AstNode *ast_parse_local_var_decl(ParseContext *pc, size_t *token_index) {
1624 Token *first_token = &pc->tokens->at(*token_index);
1625
1626 bool is_comptime = false;;
1627 if (first_token->id == TokenIdKeywordCompTime) {
1628 *token_index += 1;
1629 is_comptime = true;
1630 }
1631
1632 AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate, is_comptime, false);
1633 if (node == nullptr) {
1634 if (is_comptime) {
1635 *token_index -= 1;
1636 }
1637 return nullptr;
1638 }
1639 return node;
1640}
1641
1623/*1642/*
1624BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression1643BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
1625*/1644*/
...@@ -2171,7 +2190,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -2171,7 +2190,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
2171 for (;;) {2190 for (;;) {
2172 AstNode *statement_node = ast_parse_label(pc, token_index, false);2191 AstNode *statement_node = ast_parse_label(pc, token_index, false);
2173 if (!statement_node)2192 if (!statement_node)
2174 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate);2193 statement_node = ast_parse_local_var_decl(pc, token_index);
2175 if (!statement_node)2194 if (!statement_node)
2176 statement_node = ast_parse_defer_expr(pc, token_index);2195 statement_node = ast_parse_defer_expr(pc, token_index);
2177 if (!statement_node)2196 if (!statement_node)
...@@ -2213,13 +2232,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -2213,13 +2232,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
2213}2232}
22142233
2215/*2234/*
2216FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr)2235FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr)
2217*/2236*/
2218static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {2237static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
2219 Token *first_token = &pc->tokens->at(*token_index);2238 Token *first_token = &pc->tokens->at(*token_index);
2220 Token *fn_token;2239 Token *fn_token;
22212240
2222 CallingConvention cc;2241 CallingConvention cc;
2242 bool is_extern = false;
2223 if (first_token->id == TokenIdKeywordColdCC) {2243 if (first_token->id == TokenIdKeywordColdCC) {
2224 *token_index += 1;2244 *token_index += 1;
2225 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);2245 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
...@@ -2232,8 +2252,13 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m...@@ -2232,8 +2252,13 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
2232 *token_index += 1;2252 *token_index += 1;
2233 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);2253 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2234 cc = CallingConventionStdcall;2254 cc = CallingConventionStdcall;
2255 } else if (first_token->id == TokenIdKeywordExtern) {
2256 *token_index += 1;
2257 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2258 cc = CallingConventionC;
2235 } else if (first_token->id == TokenIdKeywordFn) {2259 } else if (first_token->id == TokenIdKeywordFn) {
2236 fn_token = first_token;2260 fn_token = first_token;
2261 is_extern = true;
2237 *token_index += 1;2262 *token_index += 1;
2238 cc = CallingConventionUnspecified;2263 cc = CallingConventionUnspecified;
2239 } else if (mandatory) {2264 } else if (mandatory) {
...@@ -2246,6 +2271,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m...@@ -2246,6 +2271,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
2246 AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token);2271 AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token);
2247 node->data.fn_proto.visib_mod = visib_mod;2272 node->data.fn_proto.visib_mod = visib_mod;
2248 node->data.fn_proto.cc = cc;2273 node->data.fn_proto.cc = cc;
2274 node->data.fn_proto.is_extern = is_extern;
22492275
2250 Token *fn_name = &pc->tokens->at(*token_index);2276 Token *fn_name = &pc->tokens->at(*token_index);
22512277
...@@ -2286,35 +2312,35 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m...@@ -2286,35 +2312,35 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
2286}2312}
22872313
2288/*2314/*
2289FnDef = option("inline" | "extern") FnProto Block2315FnDef = option("inline" | "export") FnProto Block
2290*/2316*/
2291static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {2317static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
2292 Token *first_token = &pc->tokens->at(*token_index);2318 Token *first_token = &pc->tokens->at(*token_index);
2293 bool is_inline;2319 bool is_inline;
2294 bool is_extern;2320 bool is_export;
2295 if (first_token->id == TokenIdKeywordInline) {2321 if (first_token->id == TokenIdKeywordInline) {
2296 *token_index += 1;2322 *token_index += 1;
2297 is_inline = true;2323 is_inline = true;
2298 is_extern = false;2324 is_export = false;
2299 } else if (first_token->id == TokenIdKeywordExtern) {2325 } else if (first_token->id == TokenIdKeywordExport) {
2300 *token_index += 1;2326 *token_index += 1;
2301 is_extern = true;2327 is_export = true;
2302 is_inline = false;2328 is_inline = false;
2303 } else {2329 } else {
2304 is_inline = false;2330 is_inline = false;
2305 is_extern = false;2331 is_export = false;
2306 }2332 }
23072333
2308 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod);2334 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod);
2309 if (!fn_proto) {2335 if (!fn_proto) {
2310 if (is_inline || is_extern) {2336 if (is_inline || is_export) {
2311 *token_index -= 1;2337 *token_index -= 1;
2312 }2338 }
2313 return nullptr;2339 return nullptr;
2314 }2340 }
23152341
2316 fn_proto->data.fn_proto.is_inline = is_inline;2342 fn_proto->data.fn_proto.is_inline = is_inline;
2317 fn_proto->data.fn_proto.is_extern = is_extern;2343 fn_proto->data.fn_proto.is_export = is_export;
23182344
2319 Token *semi_token = &pc->tokens->at(*token_index);2345 Token *semi_token = &pc->tokens->at(*token_index);
2320 if (semi_token->id == TokenIdSemicolon) {2346 if (semi_token->id == TokenIdSemicolon) {
...@@ -2360,7 +2386,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo...@@ -2360,7 +2386,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
2360 return fn_proto_node;2386 return fn_proto_node;
2361 }2387 }
23622388
2363 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);2389 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, false);
2364 if (var_decl_node) {2390 if (var_decl_node) {
2365 ast_eat_token(pc, token_index, TokenIdSemicolon);2391 ast_eat_token(pc, token_index, TokenIdSemicolon);
23662392
...@@ -2473,7 +2499,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2473,7 +2499,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2473 continue;2499 continue;
2474 }2500 }
24752501
2476 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);2502 AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod);
2477 if (var_decl_node) {2503 if (var_decl_node) {
2478 ast_eat_token(pc, token_index, TokenIdSemicolon);2504 ast_eat_token(pc, token_index, TokenIdSemicolon);
2479 node->data.container_decl.decls.append(var_decl_node);2505 node->data.container_decl.decls.append(var_decl_node);
...@@ -2566,7 +2592,7 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index)...@@ -2566,7 +2592,7 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index)
25662592
2567/*2593/*
2568TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl2594TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
2569TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl)2595TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
2570*/2596*/
2571static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {2597static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
2572 for (;;) {2598 for (;;) {
...@@ -2615,7 +2641,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig...@@ -2615,7 +2641,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
2615 continue;2641 continue;
2616 }2642 }
26172643
2618 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);2644 AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod);
2619 if (var_decl_node) {2645 if (var_decl_node) {
2620 ast_eat_token(pc, token_index, TokenIdSemicolon);2646 ast_eat_token(pc, token_index, TokenIdSemicolon);
2621 top_level_decls->append(var_decl_node);2647 top_level_decls->append(var_decl_node);
src/tokenizer.cpp+2
...@@ -119,6 +119,7 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -119,6 +119,7 @@ static const struct ZigKeyword zig_keywords[] = {
119 {"else", TokenIdKeywordElse},119 {"else", TokenIdKeywordElse},
120 {"enum", TokenIdKeywordEnum},120 {"enum", TokenIdKeywordEnum},
121 {"error", TokenIdKeywordError},121 {"error", TokenIdKeywordError},
122 {"export", TokenIdKeywordExport},
122 {"extern", TokenIdKeywordExtern},123 {"extern", TokenIdKeywordExtern},
123 {"false", TokenIdKeywordFalse},124 {"false", TokenIdKeywordFalse},
124 {"fn", TokenIdKeywordFn},125 {"fn", TokenIdKeywordFn},
...@@ -1518,6 +1519,7 @@ const char * token_name(TokenId id) {...@@ -1518,6 +1519,7 @@ const char * token_name(TokenId id) {
1518 case TokenIdKeywordElse: return "else";1519 case TokenIdKeywordElse: return "else";
1519 case TokenIdKeywordEnum: return "enum";1520 case TokenIdKeywordEnum: return "enum";
1520 case TokenIdKeywordError: return "error";1521 case TokenIdKeywordError: return "error";
1522 case TokenIdKeywordExport: return "export";
1521 case TokenIdKeywordExtern: return "extern";1523 case TokenIdKeywordExtern: return "extern";
1522 case TokenIdKeywordFalse: return "false";1524 case TokenIdKeywordFalse: return "false";
1523 case TokenIdKeywordFn: return "fn";1525 case TokenIdKeywordFn: return "fn";
src/tokenizer.hpp+1
...@@ -59,6 +59,7 @@ enum TokenId {...@@ -59,6 +59,7 @@ enum TokenId {
59 TokenIdKeywordElse,59 TokenIdKeywordElse,
60 TokenIdKeywordEnum,60 TokenIdKeywordEnum,
61 TokenIdKeywordError,61 TokenIdKeywordError,
62 TokenIdKeywordExport,
62 TokenIdKeywordExtern,63 TokenIdKeywordExtern,
63 TokenIdKeywordFalse,64 TokenIdKeywordFalse,
64 TokenIdKeywordFn,65 TokenIdKeywordFn,