| author | |
| committer | |
| log | 22e6bfca9602fdb79f669b494fa7f1c58094706c |
| tree | 560c8a37e895e914afaa1386a1b3a48d839d5e95 |
| parent | 9ae426a06b2e380e688fa0b4d4ad1587bebefa64 |
closes #2557 files changed, 95 insertions(+), 69 deletions(-)
doc/langref.md+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | ``` |
| 6 | 6 | Root = many(TopLevelItem) "EOF" |
| 7 | 7 | |
| 8 | TopLevelItem = ErrorValueDecl | Block | TopLevelDecl | TestDecl | |
| 8 | TopLevelItem = ErrorValueDecl | CompTimeExpression | TopLevelDecl | TestDecl | |
| 9 | 9 | |
| 10 | 10 | TestDecl = "test" String Block |
| 11 | 11 |
src/all_types.hpp+5-4| ... | ... | @@ -242,6 +242,7 @@ enum TldId { |
| 242 | 242 | TldIdFn, |
| 243 | 243 | TldIdContainer, |
| 244 | 244 | TldIdTypeDef, |
| 245 | TldIdCompTime, | |
| 245 | 246 | }; |
| 246 | 247 | |
| 247 | 248 | enum TldResolution { |
| ... | ... | @@ -293,6 +294,10 @@ struct TldTypeDef { |
| 293 | 294 | TypeTableEntry *type_entry; |
| 294 | 295 | }; |
| 295 | 296 | |
| 297 | struct TldCompTime { | |
| 298 | Tld base; | |
| 299 | }; | |
| 300 | ||
| 296 | 301 | struct TypeEnumField { |
| 297 | 302 | Buf *name; |
| 298 | 303 | TypeTableEntry *type_entry; |
| ... | ... | @@ -430,16 +435,12 @@ struct AstNodeTypeDecl { |
| 430 | 435 | }; |
| 431 | 436 | |
| 432 | 437 | struct AstNodeErrorValueDecl { |
| 433 | // always invalid if it's not VisibModPrivate but can be parsed that way | |
| 434 | VisibMod visib_mod; | |
| 435 | 438 | Buf *name; |
| 436 | 439 | |
| 437 | 440 | ErrorTableEntry *err; |
| 438 | 441 | }; |
| 439 | 442 | |
| 440 | 443 | struct AstNodeTestDecl { |
| 441 | // always invalid if it's not VisibModPrivate but can be parsed that way | |
| 442 | VisibMod visib_mod; | |
| 443 | 444 | Buf *name; |
| 444 | 445 | |
| 445 | 446 | AstNode *body; |
src/analyze.cpp+24-9| ... | ... | @@ -1924,6 +1924,12 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1924 | 1924 | } |
| 1925 | 1925 | } |
| 1926 | 1926 | |
| 1927 | static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) { | |
| 1928 | assert(tld_comptime->base.source_node->type == NodeTypeCompTime); | |
| 1929 | AstNode *expr_node = tld_comptime->base.source_node->data.comptime_expr.expr; | |
| 1930 | analyze_const_value(g, tld_comptime->base.parent_scope, expr_node, g->builtin_types.entry_void, nullptr); | |
| 1931 | } | |
| 1932 | ||
| 1927 | 1933 | static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 1928 | 1934 | if (tld->visib_mod == VisibModExport || |
| 1929 | 1935 | (buf_eql_str(tld->name, "panic") && |
| ... | ... | @@ -1955,10 +1961,6 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 1955 | 1961 | static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { |
| 1956 | 1962 | assert(node->type == NodeTypeTestDecl); |
| 1957 | 1963 | |
| 1958 | if (node->data.test_decl.visib_mod != VisibModPrivate) { | |
| 1959 | add_node_error(g, node, buf_sprintf("tests require no visibility modifier")); | |
| 1960 | } | |
| 1961 | ||
| 1962 | 1964 | if (!g->is_test_build) |
| 1963 | 1965 | return; |
| 1964 | 1966 | |
| ... | ... | @@ -1976,10 +1978,6 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope |
| 1976 | 1978 | static void preview_error_value_decl(CodeGen *g, AstNode *node) { |
| 1977 | 1979 | assert(node->type == NodeTypeErrorValueDecl); |
| 1978 | 1980 | |
| 1979 | if (node->data.error_value_decl.visib_mod != VisibModPrivate) { | |
| 1980 | add_node_error(g, node, buf_sprintf("error values require no visibility modifier")); | |
| 1981 | } | |
| 1982 | ||
| 1983 | 1981 | ErrorTableEntry *err = allocate<ErrorTableEntry>(1); |
| 1984 | 1982 | |
| 1985 | 1983 | err->decl_node = node; |
| ... | ... | @@ -2000,6 +1998,15 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) { |
| 2000 | 1998 | node->data.error_value_decl.err = err; |
| 2001 | 1999 | } |
| 2002 | 2000 | |
| 2001 | static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { | |
| 2002 | assert(node->type == NodeTypeCompTime); | |
| 2003 | ||
| 2004 | TldCompTime *tld_comptime = allocate<TldCompTime>(1); | |
| 2005 | init_tld(&tld_comptime->base, TldIdCompTime, nullptr, VisibModPrivate, node, &decls_scope->base); | |
| 2006 | g->resolve_queue.append(&tld_comptime->base); | |
| 2007 | } | |
| 2008 | ||
| 2009 | ||
| 2003 | 2010 | void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, |
| 2004 | 2011 | Scope *parent_scope) |
| 2005 | 2012 | { |
| ... | ... | @@ -2069,6 +2076,9 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2069 | 2076 | case NodeTypeTestDecl: |
| 2070 | 2077 | preview_test_decl(g, node, decls_scope); |
| 2071 | 2078 | break; |
| 2079 | case NodeTypeCompTime: | |
| 2080 | preview_comptime_decl(g, node, decls_scope); | |
| 2081 | break; | |
| 2072 | 2082 | case NodeTypeContainerDecl: |
| 2073 | 2083 | case NodeTypeParamDecl: |
| 2074 | 2084 | case NodeTypeFnDecl: |
| ... | ... | @@ -2098,7 +2108,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2098 | 2108 | case NodeTypeSwitchRange: |
| 2099 | 2109 | case NodeTypeLabel: |
| 2100 | 2110 | case NodeTypeGoto: |
| 2101 | case NodeTypeCompTime: | |
| 2102 | 2111 | case NodeTypeBreak: |
| 2103 | 2112 | case NodeTypeContinue: |
| 2104 | 2113 | case NodeTypeAsmExpr: |
| ... | ... | @@ -2357,6 +2366,12 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) { |
| 2357 | 2366 | resolve_decl_typedef(g, tld_typedef); |
| 2358 | 2367 | break; |
| 2359 | 2368 | } |
| 2369 | case TldIdCompTime: | |
| 2370 | { | |
| 2371 | TldCompTime *tld_comptime = (TldCompTime *)tld; | |
| 2372 | resolve_decl_comptime(g, tld_comptime); | |
| 2373 | break; | |
| 2374 | } | |
| 2360 | 2375 | } |
| 2361 | 2376 | |
| 2362 | 2377 | tld->resolution = TldResolutionOk; |
src/ast_render.cpp+4-1| ... | ... | @@ -1055,7 +1055,7 @@ void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) { |
| 1055 | 1055 | |
| 1056 | 1056 | Tld *tld = entry->value; |
| 1057 | 1057 | |
| 1058 | if (!buf_eql_buf(entry->key, tld->name)) { | |
| 1058 | if (tld->name != nullptr && !buf_eql_buf(entry->key, tld->name)) { | |
| 1059 | 1059 | fprintf(ar.f, "pub const "); |
| 1060 | 1060 | print_symbol(&ar, entry->key); |
| 1061 | 1061 | fprintf(ar.f, " = %s;\n", buf_ptr(tld->name)); |
| ... | ... | @@ -1075,6 +1075,9 @@ void ast_render_decls(FILE *f, int indent_size, ImportTableEntry *import) { |
| 1075 | 1075 | case TldIdTypeDef: |
| 1076 | 1076 | ast_render_tld_typedef(&ar, entry->key, (TldTypeDef *)tld); |
| 1077 | 1077 | break; |
| 1078 | case TldIdCompTime: | |
| 1079 | fprintf(stdout, "comptime\n"); | |
| 1080 | break; | |
| 1078 | 1081 | } |
| 1079 | 1082 | } |
| 1080 | 1083 | } |
src/ir.cpp+2| ... | ... | @@ -9114,6 +9114,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 9114 | 9114 | |
| 9115 | 9115 | switch (tld->id) { |
| 9116 | 9116 | case TldIdContainer: |
| 9117 | case TldIdCompTime: | |
| 9117 | 9118 | zig_unreachable(); |
| 9118 | 9119 | case TldIdVar: |
| 9119 | 9120 | { |
| ... | ... | @@ -12122,6 +12123,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 12122 | 12123 | |
| 12123 | 12124 | switch (tld->id) { |
| 12124 | 12125 | case TldIdContainer: |
| 12126 | case TldIdCompTime: | |
| 12125 | 12127 | zig_unreachable(); |
| 12126 | 12128 | case TldIdVar: |
| 12127 | 12129 | { |
src/parser.cpp+21-17| ... | ... | @@ -2399,7 +2399,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2399 | 2399 | /* |
| 2400 | 2400 | ErrorValueDecl : "error" "Symbol" ";" |
| 2401 | 2401 | */ |
| 2402 | static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { | |
| 2402 | static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index) { | |
| 2403 | 2403 | Token *first_token = &pc->tokens->at(*token_index); |
| 2404 | 2404 | |
| 2405 | 2405 | if (first_token->id != TokenIdKeywordError) { |
| ... | ... | @@ -2411,7 +2411,6 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index |
| 2411 | 2411 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2412 | 2412 | |
| 2413 | 2413 | AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token); |
| 2414 | node->data.error_value_decl.visib_mod = visib_mod; | |
| 2415 | 2414 | node->data.error_value_decl.name = token_buf(name_tok); |
| 2416 | 2415 | |
| 2417 | 2416 | return node; |
| ... | ... | @@ -2420,7 +2419,7 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index |
| 2420 | 2419 | /* |
| 2421 | 2420 | TestDecl = "test" String Block |
| 2422 | 2421 | */ |
| 2423 | static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { | |
| 2422 | static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index) { | |
| 2424 | 2423 | Token *first_token = &pc->tokens->at(*token_index); |
| 2425 | 2424 | |
| 2426 | 2425 | if (first_token->id != TokenIdKeywordTest) { |
| ... | ... | @@ -2431,7 +2430,6 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index, |
| 2431 | 2430 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdStringLiteral); |
| 2432 | 2431 | |
| 2433 | 2432 | AstNode *node = ast_create_node(pc, NodeTypeTestDecl, first_token); |
| 2434 | node->data.test_decl.visib_mod = visib_mod; | |
| 2435 | 2433 | node->data.test_decl.name = token_buf(name_tok); |
| 2436 | 2434 | node->data.test_decl.body = ast_parse_block(pc, token_index, true); |
| 2437 | 2435 | |
| ... | ... | @@ -2464,11 +2462,29 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, Visib |
| 2464 | 2462 | } |
| 2465 | 2463 | |
| 2466 | 2464 | /* |
| 2467 | TopLevelItem = ErrorValueDecl | Block | TopLevelDecl | TestDecl | |
| 2465 | TopLevelItem = ErrorValueDecl | CompTimeExpression | TopLevelDecl | TestDecl | |
| 2468 | 2466 | TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl) |
| 2469 | 2467 | */ |
| 2470 | 2468 | static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) { |
| 2471 | 2469 | for (;;) { |
| 2470 | AstNode *comptime_expr_node = ast_parse_comptime_expr(pc, token_index, false); | |
| 2471 | if (comptime_expr_node) { | |
| 2472 | top_level_decls->append(comptime_expr_node); | |
| 2473 | continue; | |
| 2474 | } | |
| 2475 | ||
| 2476 | AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index); | |
| 2477 | if (error_value_node) { | |
| 2478 | top_level_decls->append(error_value_node); | |
| 2479 | continue; | |
| 2480 | } | |
| 2481 | ||
| 2482 | AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index); | |
| 2483 | if (test_decl_node) { | |
| 2484 | top_level_decls->append(test_decl_node); | |
| 2485 | continue; | |
| 2486 | } | |
| 2487 | ||
| 2472 | 2488 | Token *visib_tok = &pc->tokens->at(*token_index); |
| 2473 | 2489 | VisibMod visib_mod; |
| 2474 | 2490 | if (visib_tok->id == TokenIdKeywordPub) { |
| ... | ... | @@ -2506,18 +2522,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig |
| 2506 | 2522 | continue; |
| 2507 | 2523 | } |
| 2508 | 2524 | |
| 2509 | AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, visib_mod); | |
| 2510 | if (error_value_node) { | |
| 2511 | top_level_decls->append(error_value_node); | |
| 2512 | continue; | |
| 2513 | } | |
| 2514 | ||
| 2515 | AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index, visib_mod); | |
| 2516 | if (test_decl_node) { | |
| 2517 | top_level_decls->append(test_decl_node); | |
| 2518 | continue; | |
| 2519 | } | |
| 2520 | ||
| 2521 | 2525 | AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, visib_mod); |
| 2522 | 2526 | if (type_decl_node) { |
| 2523 | 2527 | top_level_decls->append(type_decl_node); |
test/self_hosted.zig+38-37| ... | ... | @@ -1,37 +1,38 @@ |
| 1 | // TODO '_' identifier for unused variable bindings | |
| 2 | const test_array = @import("cases/array.zig"); | |
| 3 | const test_atomics = @import("cases/atomics.zig"); | |
| 4 | const test_bool = @import("cases/bool.zig"); | |
| 5 | const test_cast = @import("cases/cast.zig"); | |
| 6 | const test_const_slice_child = @import("cases/const_slice_child.zig"); | |
| 7 | const test_defer = @import("cases/defer.zig"); | |
| 8 | const test_enum = @import("cases/enum.zig"); | |
| 9 | const test_enum_with_members = @import("cases/enum_with_members.zig"); | |
| 10 | const test_error = @import("cases/error.zig"); | |
| 11 | const test_eval = @import("cases/eval.zig"); | |
| 12 | const test_fn = @import("cases/fn.zig"); | |
| 13 | const test_for = @import("cases/for.zig"); | |
| 14 | const test_generics = @import("cases/generics.zig"); | |
| 15 | const test_goto = @import("cases/goto.zig"); | |
| 16 | const test_if = @import("cases/if.zig"); | |
| 17 | const test_import = @import("cases/import.zig"); | |
| 18 | const test_incomplete_struct_param_tld = @import("cases/incomplete_struct_param_tld.zig"); | |
| 19 | const test_ir_block_deps = @import("cases/ir_block_deps.zig"); | |
| 20 | const test_math = @import("cases/math.zig"); | |
| 21 | const test_misc = @import("cases/misc.zig"); | |
| 22 | const test_namespace_depends_on_compile_var = @import("cases/namespace_depends_on_compile_var/index.zig"); | |
| 23 | const test_null = @import("cases/null.zig"); | |
| 24 | const test_pub_enum = @import("cases/pub_enum/index.zig"); | |
| 25 | const test_sizeof_and_typeof = @import("cases/sizeof_and_typeof.zig"); | |
| 26 | const test_struct = @import("cases/struct.zig"); | |
| 27 | const test_struct_contains_slice_of_itself = @import("cases/struct_contains_slice_of_itself.zig"); | |
| 28 | const test_switch = @import("cases/switch.zig"); | |
| 29 | const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig"); | |
| 30 | const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig"); | |
| 31 | const test_this = @import("cases/this.zig"); | |
| 32 | const test_try = @import("cases/try.zig"); | |
| 33 | const test_typedef = @import("cases/typedef.zig"); | |
| 34 | const test_undefined = @import("cases/undefined.zig"); | |
| 35 | const test_var_args = @import("cases/var_args.zig"); | |
| 36 | const test_void = @import("cases/void.zig"); | |
| 37 | const test_while = @import("cases/while.zig"); | |
| 1 | comptime { | |
| 2 | _ = @import("cases/array.zig"); | |
| 3 | _ = @import("cases/atomics.zig"); | |
| 4 | _ = @import("cases/bool.zig"); | |
| 5 | _ = @import("cases/cast.zig"); | |
| 6 | _ = @import("cases/const_slice_child.zig"); | |
| 7 | _ = @import("cases/defer.zig"); | |
| 8 | _ = @import("cases/enum.zig"); | |
| 9 | _ = @import("cases/enum_with_members.zig"); | |
| 10 | _ = @import("cases/error.zig"); | |
| 11 | _ = @import("cases/eval.zig"); | |
| 12 | _ = @import("cases/fn.zig"); | |
| 13 | _ = @import("cases/for.zig"); | |
| 14 | _ = @import("cases/generics.zig"); | |
| 15 | _ = @import("cases/goto.zig"); | |
| 16 | _ = @import("cases/if.zig"); | |
| 17 | _ = @import("cases/import.zig"); | |
| 18 | _ = @import("cases/incomplete_struct_param_tld.zig"); | |
| 19 | _ = @import("cases/ir_block_deps.zig"); | |
| 20 | _ = @import("cases/math.zig"); | |
| 21 | _ = @import("cases/misc.zig"); | |
| 22 | _ = @import("cases/namespace_depends_on_compile_var/index.zig"); | |
| 23 | _ = @import("cases/null.zig"); | |
| 24 | _ = @import("cases/pub_enum/index.zig"); | |
| 25 | _ = @import("cases/sizeof_and_typeof.zig"); | |
| 26 | _ = @import("cases/struct.zig"); | |
| 27 | _ = @import("cases/struct_contains_slice_of_itself.zig"); | |
| 28 | _ = @import("cases/switch.zig"); | |
| 29 | _ = @import("cases/switch_prong_err_enum.zig"); | |
| 30 | _ = @import("cases/switch_prong_implicit_cast.zig"); | |
| 31 | _ = @import("cases/this.zig"); | |
| 32 | _ = @import("cases/try.zig"); | |
| 33 | _ = @import("cases/typedef.zig"); | |
| 34 | _ = @import("cases/undefined.zig"); | |
| 35 | _ = @import("cases/var_args.zig"); | |
| 36 | _ = @import("cases/void.zig"); | |
| 37 | _ = @import("cases/while.zig"); | |
| 38 | } |