authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-28 16:04:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-28 16:04:44-07:00
log46b0b84b90119a1eb70a30f78baa8239cafb2524
tree8dc295fa3eb52dc966444b381724206eb4e445ff
parenta299de2265ae1fc2da31214725ea5bf399848319

ability to specify body of an extern function

closes #101

4 files changed, 32 insertions(+), 13 deletions(-)

doc/langref.md+1-1
......@@ -31,7 +31,7 @@ Directive = "#" "Symbol" "(" Expression ")"
3131
3232VisibleMod = "pub" | "export"
3333
34FnDef = option("inline") FnProto Block
34FnDef = option("inline" | "extern") FnProto Block
3535
3636ParamDeclList = "(" list(ParamDecl, ",") ")"
3737
src/analyze.cpp+8-8
......@@ -994,9 +994,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
994994 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
995995 }
996996 } else if (buf_eql_str(name, "debug_safety")) {
997 if (fn_table_entry->is_extern) {
997 if (!fn_table_entry->fn_def_node) {
998998 add_node_error(g, directive_node,
999 buf_sprintf("#debug_safety invalid on extern functions"));
999 buf_sprintf("#debug_safety valid only on function definitions"));
10001000 } else {
10011001 bool enable;
10021002 bool ok = resolve_const_expr_bool(g, import, import->block_context,
......@@ -1018,9 +1018,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
10181018 buf_sprintf("#condition valid only on exported symbols"));
10191019 }
10201020 } else if (buf_eql_str(name, "static_eval_enable")) {
1021 if (fn_table_entry->is_extern) {
1021 if (!fn_table_entry->fn_def_node) {
10221022 add_node_error(g, directive_node,
1023 buf_sprintf("#static_val_enable invalid on extern functions"));
1023 buf_sprintf("#static_val_enable valid only on function definitions"));
10241024 } else {
10251025 bool enable;
10261026 bool ok = resolve_const_expr_bool(g, import, import->block_context,
......@@ -1470,9 +1470,9 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
14701470
14711471 assert(!is_extern || !is_generic_instance);
14721472
1473 if (!is_extern && proto_node->data.fn_proto.is_var_args) {
1473 if (fn_def_node && proto_node->data.fn_proto.is_var_args) {
14741474 add_node_error(g, proto_node,
1475 buf_sprintf("variadic arguments only allowed in extern functions"));
1475 buf_sprintf("variadic arguments only allowed in extern function declarations"));
14761476 }
14771477
14781478 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
......@@ -1480,13 +1480,13 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
14801480 fn_table_entry->proto_node = proto_node;
14811481 fn_table_entry->fn_def_node = fn_def_node;
14821482 fn_table_entry->is_extern = is_extern;
1483 fn_table_entry->is_pure = !is_extern;
1483 fn_table_entry->is_pure = fn_def_node != nullptr;
14841484
14851485 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, proto_node, '_');
14861486
14871487 g->fn_protos.append(fn_table_entry);
14881488
1489 if (!is_extern) {
1489 if (fn_def_node) {
14901490 g->fn_defs.append(fn_table_entry);
14911491 }
14921492
src/parser.cpp+22-3
......@@ -2414,27 +2414,46 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
24142414}
24152415
24162416/*
2417FnDef = option("inline") FnProto Block
2417FnDef = option("inline" | "extern") FnProto Block
24182418*/
24192419static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory,
24202420 ZigList<AstNode*> *directives, VisibMod visib_mod)
24212421{
24222422 Token *first_token = &pc->tokens->at(*token_index);
24232423 bool is_inline;
2424 bool is_extern;
24242425 if (first_token->id == TokenIdKeywordInline) {
24252426 *token_index += 1;
24262427 is_inline = true;
2428 is_extern = false;
2429 } else if (first_token->id == TokenIdKeywordExtern) {
2430 *token_index += 1;
2431 is_extern = true;
2432 is_inline = false;
24272433 } else {
24282434 is_inline = false;
2435 is_extern = false;
24292436 }
24302437
24312438 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod);
2432 if (!fn_proto)
2439 if (!fn_proto) {
2440 if (is_inline || is_extern) {
2441 *token_index -= 1;
2442 }
24332443 return nullptr;
2434 AstNode *node = ast_create_node(pc, NodeTypeFnDef, first_token);
2444 }
24352445
24362446 fn_proto->data.fn_proto.is_inline = is_inline;
2447 fn_proto->data.fn_proto.is_extern = is_extern;
24372448
2449 Token *semi_token = &pc->tokens->at(*token_index);
2450 if (semi_token->id == TokenIdSemicolon) {
2451 *token_index += 1;
2452 normalize_parent_ptrs(fn_proto);
2453 return fn_proto;
2454 }
2455
2456 AstNode *node = ast_create_node(pc, NodeTypeFnDef, first_token);
24382457 node->data.fn_def.fn_proto = fn_proto;
24392458 node->data.fn_def.body = ast_parse_block(pc, token_index, true);
24402459 normalize_parent_ptrs(node);
test/run_tests.cpp+1-1
......@@ -819,7 +819,7 @@ fn f() {
819819
820820 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
821821fn f(...) {}
822 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
822 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern function declarations");
823823
824824 add_compile_fail_case("write to const global variable", R"SOURCE(
825825const x : i32 = 99;