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)
58195819
58205820ErrorValueDecl = "error" Symbol ";"
58215821
5822GlobalVarDecl = VariableDeclaration ";"
5822GlobalVarDecl = option("export") VariableDeclaration ";"
58235823
5824VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression
5824LocalVarDecl = option("comptime") VariableDeclaration
5825
5826VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression
58255827
58265828ContainerMember = (ContainerField | FnDef | GlobalVarDecl)
58275829
......@@ -5831,9 +5833,9 @@ UseDecl = "use" Expression ";"
58315833
58325834ExternDecl = "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 Block
5838FnDef = option("inline" | "export") FnProto Block
58375839
58385840ParamDeclList = "(" list(ParamDecl, ",") ")"
58395841
......@@ -5841,7 +5843,7 @@ ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...")
58415843
58425844Block = "{" 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
58465848Label = Symbol ":"
58475849
......@@ -5947,7 +5949,7 @@ StructLiteralField = "." Symbol "=" Expression
59475949
59485950PrefixOp = "!" | "-" | "~" | "*" | ("&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) | ContainerDecl
5952PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl
59515953
59525954ArrayType : "[" 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 {
315315 VariableTableEntry *var;
316316 Buf *extern_lib_name;
317317 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;
324318};
325319
326320struct TldFn {
......@@ -428,6 +422,7 @@ struct AstNodeFnProto {
428422 AstNode *return_type;
429423 bool is_var_args;
430424 bool is_extern;
425 bool is_export;
431426 bool is_inline;
432427 CallingConvention cc;
433428 AstNode *fn_def_node;
......@@ -485,7 +480,8 @@ struct AstNodeVariableDeclaration {
485480 VisibMod visib_mod;
486481 Buf *symbol;
487482 bool is_const;
488 bool is_inline;
483 bool is_comptime;
484 bool is_export;
489485 bool is_extern;
490486 // one or both of type and expr will be non null
491487 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
10621062 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
10631063
10641064 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;
10661066 fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified;
10671067 } else {
10681068 fn_type_id->cc = fn_proto->cc;
......@@ -2675,6 +2675,26 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
26752675}
26762676
26772677static 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
26782698 {
26792699 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);
26802700 if (entry) {
......@@ -3006,6 +3026,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
30063026
30073027 bool is_const = var_decl->is_const;
30083028 bool is_extern = var_decl->is_extern;
3029 bool is_export = var_decl->is_export;
30093030
30103031 TypeTableEntry *explicit_type = nullptr;
30113032 if (var_decl->type) {
......@@ -3013,8 +3034,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
30133034 explicit_type = validate_var_type(g, var_decl->type, proposed_type);
30143035 }
30153036
3037 assert(!is_export || !is_extern);
3038
30163039 VarLinkage linkage;
3017 if (is_extern) {
3040 if (is_export) {
3041 linkage = VarLinkageExport;
3042 } else if (is_extern) {
30183043 linkage = VarLinkageExternal;
30193044 } else {
30203045 linkage = VarLinkageInternal;
src/ir.cpp+1-1
......@@ -5066,7 +5066,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
50665066 bool is_const = variable_declaration->is_const;
50675067 bool is_extern = variable_declaration->is_extern;
50685068 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);
50705070 VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
50715071 is_const, is_const, is_shadowable, is_comptime);
50725072 // 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
676676}
677677
678678/*
679PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
679PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl
680680KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable"
681681*/
682682static 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
791791 if (container_decl)
792792 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
801794 if (!mandatory)
802795 return nullptr;
803796
......@@ -1534,38 +1527,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
15341527}
15351528
15361529/*
1537VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression
1530VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression
15381531*/
15391532static 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)
15411534{
15421535 Token *first_token = &pc->tokens->at(*token_index);
15431536 Token *var_token;
15441537
15451538 bool is_const;
1546 bool is_comptime;
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;
1539 if (first_token->id == TokenIdKeywordVar) {
15641540 is_const = false;
15651541 var_token = first_token;
15661542 *token_index += 1;
15671543 } else if (first_token->id == TokenIdKeywordConst) {
1568 is_comptime = false;
15691544 is_const = true;
15701545 var_token = first_token;
15711546 *token_index += 1;
......@@ -1577,7 +1552,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to
15771552
15781553 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;
15811556 node->data.variable_declaration.is_const = is_const;
15821557 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
16201595 return node;
16211596}
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
16231642/*
16241643BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression
16251644*/
......@@ -2171,7 +2190,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
21712190 for (;;) {
21722191 AstNode *statement_node = ast_parse_label(pc, token_index, false);
21732192 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);
21752194 if (!statement_node)
21762195 statement_node = ast_parse_defer_expr(pc, token_index);
21772196 if (!statement_node)
......@@ -2213,13 +2232,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
22132232}
22142233
22152234/*
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)
22172236*/
22182237static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
22192238 Token *first_token = &pc->tokens->at(*token_index);
22202239 Token *fn_token;
22212240
22222241 CallingConvention cc;
2242 bool is_extern = false;
22232243 if (first_token->id == TokenIdKeywordColdCC) {
22242244 *token_index += 1;
22252245 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
22322252 *token_index += 1;
22332253 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
22342254 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;
22352259 } else if (first_token->id == TokenIdKeywordFn) {
22362260 fn_token = first_token;
2261 is_extern = true;
22372262 *token_index += 1;
22382263 cc = CallingConventionUnspecified;
22392264 } else if (mandatory) {
......@@ -2246,6 +2271,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
22462271 AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token);
22472272 node->data.fn_proto.visib_mod = visib_mod;
22482273 node->data.fn_proto.cc = cc;
2274 node->data.fn_proto.is_extern = is_extern;
22492275
22502276 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
22862312}
22872313
22882314/*
2289FnDef = option("inline" | "extern") FnProto Block
2315FnDef = option("inline" | "export") FnProto Block
22902316*/
22912317static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
22922318 Token *first_token = &pc->tokens->at(*token_index);
22932319 bool is_inline;
2294 bool is_extern;
2320 bool is_export;
22952321 if (first_token->id == TokenIdKeywordInline) {
22962322 *token_index += 1;
22972323 is_inline = true;
2298 is_extern = false;
2299 } else if (first_token->id == TokenIdKeywordExtern) {
2324 is_export = false;
2325 } else if (first_token->id == TokenIdKeywordExport) {
23002326 *token_index += 1;
2301 is_extern = true;
2327 is_export = true;
23022328 is_inline = false;
23032329 } else {
23042330 is_inline = false;
2305 is_extern = false;
2331 is_export = false;
23062332 }
23072333
23082334 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod);
23092335 if (!fn_proto) {
2310 if (is_inline || is_extern) {
2336 if (is_inline || is_export) {
23112337 *token_index -= 1;
23122338 }
23132339 return nullptr;
23142340 }
23152341
23162342 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
23192345 Token *semi_token = &pc->tokens->at(*token_index);
23202346 if (semi_token->id == TokenIdSemicolon) {
......@@ -2360,7 +2386,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
23602386 return fn_proto_node;
23612387 }
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);
23642390 if (var_decl_node) {
23652391 ast_eat_token(pc, token_index, TokenIdSemicolon);
23662392
......@@ -2473,7 +2499,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
24732499 continue;
24742500 }
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);
24772503 if (var_decl_node) {
24782504 ast_eat_token(pc, token_index, TokenIdSemicolon);
24792505 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)
25662592
25672593/*
25682594TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl
2569TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
2595TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl)
25702596*/
25712597static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
25722598 for (;;) {
......@@ -2615,7 +2641,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
26152641 continue;
26162642 }
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);
26192645 if (var_decl_node) {
26202646 ast_eat_token(pc, token_index, TokenIdSemicolon);
26212647 top_level_decls->append(var_decl_node);
src/tokenizer.cpp+2
......@@ -119,6 +119,7 @@ static const struct ZigKeyword zig_keywords[] = {
119119 {"else", TokenIdKeywordElse},
120120 {"enum", TokenIdKeywordEnum},
121121 {"error", TokenIdKeywordError},
122 {"export", TokenIdKeywordExport},
122123 {"extern", TokenIdKeywordExtern},
123124 {"false", TokenIdKeywordFalse},
124125 {"fn", TokenIdKeywordFn},
......@@ -1518,6 +1519,7 @@ const char * token_name(TokenId id) {
15181519 case TokenIdKeywordElse: return "else";
15191520 case TokenIdKeywordEnum: return "enum";
15201521 case TokenIdKeywordError: return "error";
1522 case TokenIdKeywordExport: return "export";
15211523 case TokenIdKeywordExtern: return "extern";
15221524 case TokenIdKeywordFalse: return "false";
15231525 case TokenIdKeywordFn: return "fn";
src/tokenizer.hpp+1
......@@ -59,6 +59,7 @@ enum TokenId {
5959 TokenIdKeywordElse,
6060 TokenIdKeywordEnum,
6161 TokenIdKeywordError,
62 TokenIdKeywordExport,
6263 TokenIdKeywordExtern,
6364 TokenIdKeywordFalse,
6465 TokenIdKeywordFn,