| author | |
| committer | |
| log | 257cf09472ce5f4a51bf39808e119717fa0e4280 |
| tree | 722cbc737134b1aa03fafac400f680f20007308a |
| parent | 31cf43de54c012c3b6f4fa7a516e2aac0ae18b56 |
16 files changed, 240 insertions(+), 113 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -31,6 +31,7 @@ set(ZIG_SOURCES |
| 31 | 31 | "${CMAKE_SOURCE_DIR}/src/main.cpp" |
| 32 | 32 | "${CMAKE_SOURCE_DIR}/src/os.cpp" |
| 33 | 33 | "${CMAKE_SOURCE_DIR}/src/util.cpp" |
| 34 | "${CMAKE_SOURCE_DIR}/src/errmsg.cpp" | |
| 34 | 35 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" |
| 35 | 36 | ) |
| 36 | 37 |
src/analyze.cpp+11-7| ... | ... | @@ -12,13 +12,17 @@ |
| 12 | 12 | #include "os.hpp" |
| 13 | 13 | |
| 14 | 14 | static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 15 | g->errors.add_one(); | |
| 16 | ErrorMsg *last_msg = &g->errors.last(); | |
| 17 | last_msg->line_start = node->line; | |
| 18 | last_msg->column_start = node->column; | |
| 19 | last_msg->line_end = -1; | |
| 20 | last_msg->column_end = -1; | |
| 21 | last_msg->msg = msg; | |
| 15 | ErrorMsg *err = allocate<ErrorMsg>(1); | |
| 16 | err->line_start = node->line; | |
| 17 | err->column_start = node->column; | |
| 18 | err->line_end = -1; | |
| 19 | err->column_end = -1; | |
| 20 | err->msg = msg; | |
| 21 | err->path = node->owner->path; | |
| 22 | err->source = node->owner->source_code; | |
| 23 | err->line_offsets = node->owner->line_offsets; | |
| 24 | ||
| 25 | g->errors.append(err); | |
| 22 | 26 | } |
| 23 | 27 | |
| 24 | 28 | static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) { |
src/buffer.cpp+10-4| ... | ... | @@ -3,9 +3,8 @@ |
| 3 | 3 | #include <stdlib.h> |
| 4 | 4 | #include <stdio.h> |
| 5 | 5 | |
| 6 | Buf *buf_sprintf(const char *format, ...) { | |
| 7 | va_list ap, ap2; | |
| 8 | va_start(ap, format); | |
| 6 | Buf *buf_vprintf(const char *format, va_list ap) { | |
| 7 | va_list ap2; | |
| 9 | 8 | va_copy(ap2, ap); |
| 10 | 9 | |
| 11 | 10 | int len1 = vsnprintf(nullptr, 0, format, ap); |
| ... | ... | @@ -19,11 +18,18 @@ Buf *buf_sprintf(const char *format, ...) { |
| 19 | 18 | assert(len2 == len1); |
| 20 | 19 | |
| 21 | 20 | va_end(ap2); |
| 22 | va_end(ap); | |
| 23 | 21 | |
| 24 | 22 | return buf; |
| 25 | 23 | } |
| 26 | 24 | |
| 25 | Buf *buf_sprintf(const char *format, ...) { | |
| 26 | va_list ap; | |
| 27 | va_start(ap, format); | |
| 28 | Buf *result = buf_vprintf(format, ap); | |
| 29 | va_end(ap); | |
| 30 | return result; | |
| 31 | } | |
| 32 | ||
| 27 | 33 | void buf_appendf(Buf *buf, const char *format, ...) { |
| 28 | 34 | assert(buf->list.length); |
| 29 | 35 | va_list ap, ap2; |
src/buffer.hpp+2| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | #include <assert.h> |
| 14 | 14 | #include <stdint.h> |
| 15 | 15 | #include <ctype.h> |
| 16 | #include <stdarg.h> | |
| 16 | 17 | |
| 17 | 18 | #define BUF_INIT {{0}} |
| 18 | 19 | |
| ... | ... | @@ -24,6 +25,7 @@ struct Buf { |
| 24 | 25 | |
| 25 | 26 | Buf *buf_sprintf(const char *format, ...) |
| 26 | 27 | __attribute__ ((format (printf, 1, 2))); |
| 28 | Buf *buf_vprintf(const char *format, va_list ap); | |
| 27 | 29 | |
| 28 | 30 | static inline int buf_len(Buf *buf) { |
| 29 | 31 | assert(buf->list.length); |
src/codegen.cpp+25-8| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | #include "error.hpp" |
| 14 | 14 | #include "semantic_info.hpp" |
| 15 | 15 | #include "analyze.hpp" |
| 16 | #include "errmsg.hpp" | |
| 16 | 17 | |
| 17 | 18 | #include <stdio.h> |
| 18 | 19 | #include <errno.h> |
| ... | ... | @@ -678,24 +679,42 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou |
| 678 | 679 | fprintf(stderr, "---------\n"); |
| 679 | 680 | } |
| 680 | 681 | |
| 681 | ZigList<Token> *tokens = tokenize(source_code); | |
| 682 | Tokenization tokenization = {0}; | |
| 683 | tokenize(source_code, &tokenization); | |
| 684 | ||
| 685 | if (tokenization.err) { | |
| 686 | ErrorMsg *err = allocate<ErrorMsg>(1); | |
| 687 | err->line_start = tokenization.err_line; | |
| 688 | err->column_start = tokenization.err_column; | |
| 689 | err->line_end = -1; | |
| 690 | err->column_end = -1; | |
| 691 | err->msg = tokenization.err; | |
| 692 | err->path = source_path; | |
| 693 | err->source = source_code; | |
| 694 | err->line_offsets = tokenization.line_offsets; | |
| 695 | ||
| 696 | print_err_msg(err); | |
| 697 | exit(1); | |
| 698 | } | |
| 682 | 699 | |
| 683 | 700 | if (g->verbose) { |
| 684 | print_tokens(source_code, tokens); | |
| 701 | print_tokens(source_code, tokenization.tokens); | |
| 685 | 702 | |
| 686 | 703 | fprintf(stderr, "\nAST:\n"); |
| 687 | 704 | fprintf(stderr, "------\n"); |
| 688 | 705 | } |
| 689 | 706 | |
| 690 | 707 | ImportTableEntry *import_entry = allocate<ImportTableEntry>(1); |
| 708 | import_entry->source_code = source_code; | |
| 709 | import_entry->line_offsets = tokenization.line_offsets; | |
| 710 | import_entry->path = source_path; | |
| 691 | 711 | import_entry->fn_table.init(32); |
| 692 | import_entry->root = ast_parse(source_code, tokens); | |
| 712 | import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry); | |
| 693 | 713 | assert(import_entry->root); |
| 694 | 714 | if (g->verbose) { |
| 695 | 715 | ast_print(import_entry->root, 0); |
| 696 | 716 | } |
| 697 | 717 | |
| 698 | import_entry->path = source_path; | |
| 699 | 718 | import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname)); |
| 700 | 719 | g->import_table.put(source_path, import_entry); |
| 701 | 720 | |
| ... | ... | @@ -736,10 +755,8 @@ void codegen_add_root_code(CodeGen *g, Buf *source_path, Buf *source_code) { |
| 736 | 755 | } |
| 737 | 756 | } else { |
| 738 | 757 | for (int i = 0; i < g->errors.length; i += 1) { |
| 739 | ErrorMsg *err = &g->errors.at(i); | |
| 740 | fprintf(stderr, "Error: Line %d, column %d: %s\n", | |
| 741 | err->line_start + 1, err->column_start + 1, | |
| 742 | buf_ptr(err->msg)); | |
| 758 | ErrorMsg *err = g->errors.at(i); | |
| 759 | print_err_msg(err); | |
| 743 | 760 | } |
| 744 | 761 | exit(1); |
| 745 | 762 | } |
src/codegen.hpp-9| ... | ... | @@ -20,15 +20,6 @@ enum OutType { |
| 20 | 20 | }; |
| 21 | 21 | |
| 22 | 22 | |
| 23 | struct ErrorMsg { | |
| 24 | int line_start; | |
| 25 | int column_start; | |
| 26 | int line_end; | |
| 27 | int column_end; | |
| 28 | Buf *msg; | |
| 29 | }; | |
| 30 | ||
| 31 | ||
| 32 | 23 | CodeGen *codegen_create(Buf *root_source_dir); |
| 33 | 24 | |
| 34 | 25 | enum CodeGenBuildType { |
src/errmsg.cpp created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | #include "errmsg.hpp" | |
| 2 | #include "os.hpp" | |
| 3 | ||
| 4 | #include <stdio.h> | |
| 5 | ||
| 6 | #define RED "\x1b[31;1m" | |
| 7 | #define WHITE "\x1b[37;1m" | |
| 8 | #define GREEN "\x1b[32;1m" | |
| 9 | #define RESET "\x1b[0m" | |
| 10 | ||
| 11 | void print_err_msg(ErrorMsg *err) { | |
| 12 | if (os_stderr_tty()) { | |
| 13 | fprintf(stderr, WHITE "%s:%d:%d: " RED "error:" WHITE " %s" RESET "\n", | |
| 14 | buf_ptr(err->path), | |
| 15 | err->line_start + 1, err->column_start + 1, | |
| 16 | buf_ptr(err->msg)); | |
| 17 | ||
| 18 | assert(err->source); | |
| 19 | assert(err->line_offsets); | |
| 20 | ||
| 21 | int line_start_offset = err->line_offsets->at(err->line_start); | |
| 22 | int line_end_offset = err->line_offsets->at(err->line_start + 1); | |
| 23 | ||
| 24 | fwrite(buf_ptr(err->source) + line_start_offset, 1, line_end_offset - line_start_offset - 1, stderr); | |
| 25 | fprintf(stderr, "\n"); | |
| 26 | for (int i = 0; i < err->column_start; i += 1) { | |
| 27 | fprintf(stderr, " "); | |
| 28 | } | |
| 29 | fprintf(stderr, GREEN "^" RESET "\n"); | |
| 30 | ||
| 31 | } else { | |
| 32 | fprintf(stderr, "%s:%d:%d: error: %s\n", | |
| 33 | buf_ptr(err->path), | |
| 34 | err->line_start + 1, err->column_start + 1, | |
| 35 | buf_ptr(err->msg)); | |
| 36 | } | |
| 37 | } | |
| 38 |
src/errmsg.hpp created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | /* | |
| 2 | * Copyright (c) 2015 Andrew Kelley | |
| 3 | * | |
| 4 | * This file is part of zig, which is MIT licensed. | |
| 5 | * See http://opensource.org/licenses/MIT | |
| 6 | */ | |
| 7 | ||
| 8 | #ifndef ZIG_ERRMSG_HPP | |
| 9 | #define ZIG_ERRMSG_HPP | |
| 10 | ||
| 11 | #include "buffer.hpp" | |
| 12 | #include "list.hpp" | |
| 13 | ||
| 14 | struct ErrorMsg { | |
| 15 | int line_start; | |
| 16 | int column_start; | |
| 17 | int line_end; | |
| 18 | int column_end; | |
| 19 | Buf *msg; | |
| 20 | Buf *path; | |
| 21 | Buf *source; | |
| 22 | ZigList<int> *line_offsets; | |
| 23 | }; | |
| 24 | ||
| 25 | void print_err_msg(ErrorMsg *msg); | |
| 26 | ||
| 27 | #endif |
src/os.cpp+4| ... | ... | @@ -180,3 +180,7 @@ int os_get_cwd(Buf *out_cwd) { |
| 180 | 180 | |
| 181 | 181 | return 0; |
| 182 | 182 | } |
| 183 | ||
| 184 | bool os_stderr_tty(void) { | |
| 185 | return isatty(STDERR_FILENO); | |
| 186 | } |
src/os.hpp+2| ... | ... | @@ -29,4 +29,6 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents); |
| 29 | 29 | int os_get_cwd(Buf *out_cwd); |
| 30 | 30 | |
| 31 | 31 | |
| 32 | bool os_stderr_tty(void); | |
| 33 | ||
| 32 | 34 | #endif |
src/parser.cpp+65-53| ... | ... | @@ -6,6 +6,8 @@ |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | #include "parser.hpp" |
| 9 | #include "errmsg.hpp" | |
| 10 | #include "semantic_info.hpp" | |
| 9 | 11 | |
| 10 | 12 | #include <stdarg.h> |
| 11 | 13 | #include <stdio.h> |
| ... | ... | @@ -45,21 +47,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) { |
| 45 | 47 | zig_unreachable(); |
| 46 | 48 | } |
| 47 | 49 | |
| 48 | __attribute__ ((format (printf, 2, 3))) | |
| 49 | __attribute__ ((noreturn)) | |
| 50 | static void ast_error(Token *token, const char *format, ...) { | |
| 51 | int line = token->start_line + 1; | |
| 52 | int column = token->start_column + 1; | |
| 53 | ||
| 54 | va_list ap; | |
| 55 | va_start(ap, format); | |
| 56 | fprintf(stderr, "Error: Line %d, column %d: ", line, column); | |
| 57 | vfprintf(stderr, format, ap); | |
| 58 | fprintf(stderr, "\n"); | |
| 59 | va_end(ap); | |
| 60 | exit(EXIT_FAILURE); | |
| 61 | } | |
| 62 | ||
| 63 | 50 | const char *node_type_str(NodeType node_type) { |
| 64 | 51 | switch (node_type) { |
| 65 | 52 | case NodeTypeRoot: |
| ... | ... | @@ -254,11 +241,35 @@ struct ParseContext { |
| 254 | 241 | AstNode *root; |
| 255 | 242 | ZigList<Token> *tokens; |
| 256 | 243 | ZigList<AstNode *> *directive_list; |
| 244 | ImportTableEntry *owner; | |
| 257 | 245 | }; |
| 258 | 246 | |
| 259 | static AstNode *ast_create_node_no_line_info(NodeType type) { | |
| 247 | __attribute__ ((format (printf, 3, 4))) | |
| 248 | __attribute__ ((noreturn)) | |
| 249 | static void ast_error(ParseContext *pc, Token *token, const char *format, ...) { | |
| 250 | ErrorMsg *err = allocate<ErrorMsg>(1); | |
| 251 | err->line_start = token->start_line; | |
| 252 | err->column_start = token->start_column; | |
| 253 | err->line_end = -1; | |
| 254 | err->column_end = -1; | |
| 255 | ||
| 256 | va_list ap; | |
| 257 | va_start(ap, format); | |
| 258 | err->msg = buf_vprintf(format, ap); | |
| 259 | va_end(ap); | |
| 260 | ||
| 261 | err->path = pc->owner->path; | |
| 262 | err->source = pc->owner->source_code; | |
| 263 | err->line_offsets = pc->owner->line_offsets; | |
| 264 | ||
| 265 | print_err_msg(err); | |
| 266 | exit(EXIT_FAILURE); | |
| 267 | } | |
| 268 | ||
| 269 | static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) { | |
| 260 | 270 | AstNode *node = allocate<AstNode>(1); |
| 261 | 271 | node->type = type; |
| 272 | node->owner = pc->owner; | |
| 262 | 273 | return node; |
| 263 | 274 | } |
| 264 | 275 | |
| ... | ... | @@ -267,21 +278,21 @@ static void ast_update_node_line_info(AstNode *node, Token *first_token) { |
| 267 | 278 | node->column = first_token->start_column; |
| 268 | 279 | } |
| 269 | 280 | |
| 270 | static AstNode *ast_create_node(NodeType type, Token *first_token) { | |
| 271 | AstNode *node = ast_create_node_no_line_info(type); | |
| 281 | static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_token) { | |
| 282 | AstNode *node = ast_create_node_no_line_info(pc, type); | |
| 272 | 283 | ast_update_node_line_info(node, first_token); |
| 273 | 284 | return node; |
| 274 | 285 | } |
| 275 | 286 | |
| 276 | static AstNode *ast_create_node_with_node(NodeType type, AstNode *other_node) { | |
| 277 | AstNode *node = ast_create_node_no_line_info(type); | |
| 287 | static AstNode *ast_create_node_with_node(ParseContext *pc, NodeType type, AstNode *other_node) { | |
| 288 | AstNode *node = ast_create_node_no_line_info(pc, type); | |
| 278 | 289 | node->line = other_node->line; |
| 279 | 290 | node->column = other_node->column; |
| 280 | 291 | return node; |
| 281 | 292 | } |
| 282 | 293 | |
| 283 | 294 | static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) { |
| 284 | AstNode *node = ast_create_node(NodeTypeType, token); | |
| 295 | AstNode *node = ast_create_node(pc, NodeTypeType, token); | |
| 285 | 296 | node->data.type.type = AstNodeTypeTypePrimitive; |
| 286 | 297 | buf_init_from_str(&node->data.type.primitive_name, "void"); |
| 287 | 298 | return node; |
| ... | ... | @@ -331,7 +342,7 @@ __attribute__ ((noreturn)) |
| 331 | 342 | static void ast_invalid_token_error(ParseContext *pc, Token *token) { |
| 332 | 343 | Buf token_value = BUF_INIT; |
| 333 | 344 | ast_buf_from_token(pc, token, &token_value); |
| 334 | ast_error(token, "invalid token: '%s'", buf_ptr(&token_value)); | |
| 345 | ast_error(pc, token, "invalid token: '%s'", buf_ptr(&token_value)); | |
| 335 | 346 | } |
| 336 | 347 | |
| 337 | 348 | static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool mandatory); |
| ... | ... | @@ -349,7 +360,7 @@ static AstNode *ast_parse_directive(ParseContext *pc, int token_index, int *new_ |
| 349 | 360 | token_index += 1; |
| 350 | 361 | ast_expect_token(pc, number_sign, TokenIdNumberSign); |
| 351 | 362 | |
| 352 | AstNode *node = ast_create_node(NodeTypeDirective, number_sign); | |
| 363 | AstNode *node = ast_create_node(pc, NodeTypeDirective, number_sign); | |
| 353 | 364 | |
| 354 | 365 | Token *name_symbol = &pc->tokens->at(token_index); |
| 355 | 366 | token_index += 1; |
| ... | ... | @@ -399,7 +410,7 @@ static AstNode *ast_parse_type(ParseContext *pc, int token_index, int *new_token |
| 399 | 410 | Token *token = &pc->tokens->at(token_index); |
| 400 | 411 | token_index += 1; |
| 401 | 412 | |
| 402 | AstNode *node = ast_create_node(NodeTypeType, token); | |
| 413 | AstNode *node = ast_create_node(pc, NodeTypeType, token); | |
| 403 | 414 | |
| 404 | 415 | if (token->id == TokenIdKeywordUnreachable) { |
| 405 | 416 | node->data.type.type = AstNodeTypeTypePrimitive; |
| ... | ... | @@ -437,7 +448,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, int token_index, int *new |
| 437 | 448 | token_index += 1; |
| 438 | 449 | ast_expect_token(pc, param_name, TokenIdSymbol); |
| 439 | 450 | |
| 440 | AstNode *node = ast_create_node(NodeTypeParamDecl, param_name); | |
| 451 | AstNode *node = ast_create_node(pc, NodeTypeParamDecl, param_name); | |
| 441 | 452 | |
| 442 | 453 | |
| 443 | 454 | ast_buf_from_token(pc, param_name, &node->data.param_decl.name); |
| ... | ... | @@ -544,21 +555,21 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 544 | 555 | Token *token = &pc->tokens->at(*token_index); |
| 545 | 556 | |
| 546 | 557 | if (token->id == TokenIdNumberLiteral) { |
| 547 | AstNode *node = ast_create_node(NodeTypeNumberLiteral, token); | |
| 558 | AstNode *node = ast_create_node(pc, NodeTypeNumberLiteral, token); | |
| 548 | 559 | ast_buf_from_token(pc, token, &node->data.number); |
| 549 | 560 | *token_index += 1; |
| 550 | 561 | return node; |
| 551 | 562 | } else if (token->id == TokenIdStringLiteral) { |
| 552 | AstNode *node = ast_create_node(NodeTypeStringLiteral, token); | |
| 563 | AstNode *node = ast_create_node(pc, NodeTypeStringLiteral, token); | |
| 553 | 564 | parse_string_literal(pc, token, &node->data.string); |
| 554 | 565 | *token_index += 1; |
| 555 | 566 | return node; |
| 556 | 567 | } else if (token->id == TokenIdKeywordUnreachable) { |
| 557 | AstNode *node = ast_create_node(NodeTypeUnreachable, token); | |
| 568 | AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token); | |
| 558 | 569 | *token_index += 1; |
| 559 | 570 | return node; |
| 560 | 571 | } else if (token->id == TokenIdSymbol) { |
| 561 | AstNode *node = ast_create_node(NodeTypeSymbol, token); | |
| 572 | AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); | |
| 562 | 573 | ast_buf_from_token(pc, token, &node->data.symbol); |
| 563 | 574 | *token_index += 1; |
| 564 | 575 | return node; |
| ... | ... | @@ -592,7 +603,7 @@ static AstNode *ast_parse_fn_call_expr(ParseContext *pc, int *token_index, bool |
| 592 | 603 | if (l_paren->id != TokenIdLParen) |
| 593 | 604 | return primary_expr; |
| 594 | 605 | |
| 595 | AstNode *node = ast_create_node_with_node(NodeTypeFnCallExpr, primary_expr); | |
| 606 | AstNode *node = ast_create_node_with_node(pc, NodeTypeFnCallExpr, primary_expr); | |
| 596 | 607 | node->data.fn_call_expr.fn_ref_expr = primary_expr; |
| 597 | 608 | ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call_expr.params); |
| 598 | 609 | |
| ... | ... | @@ -635,7 +646,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo |
| 635 | 646 | return ast_parse_fn_call_expr(pc, token_index, mandatory); |
| 636 | 647 | |
| 637 | 648 | AstNode *primary_expr = ast_parse_fn_call_expr(pc, token_index, true); |
| 638 | AstNode *node = ast_create_node(NodeTypePrefixOpExpr, token); | |
| 649 | AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); | |
| 639 | 650 | node->data.prefix_op_expr.primary_expr = primary_expr; |
| 640 | 651 | node->data.prefix_op_expr.prefix_op = prefix_op; |
| 641 | 652 | |
| ... | ... | @@ -656,7 +667,7 @@ static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bo |
| 656 | 667 | return prefix_op_expr; |
| 657 | 668 | *token_index += 1; |
| 658 | 669 | |
| 659 | AstNode *node = ast_create_node(NodeTypeCastExpr, as_kw); | |
| 670 | AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw); | |
| 660 | 671 | node->data.cast_expr.prefix_op_expr = prefix_op_expr; |
| 661 | 672 | |
| 662 | 673 | node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index); |
| ... | ... | @@ -705,7 +716,7 @@ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool man |
| 705 | 716 | |
| 706 | 717 | AstNode *operand_2 = ast_parse_cast_expression(pc, token_index, true); |
| 707 | 718 | |
| 708 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 719 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 709 | 720 | node->data.bin_op_expr.op1 = operand_1; |
| 710 | 721 | node->data.bin_op_expr.bin_op = mult_op; |
| 711 | 722 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -753,7 +764,7 @@ static AstNode *ast_parse_add_expr(ParseContext *pc, int *token_index, bool mand |
| 753 | 764 | |
| 754 | 765 | AstNode *operand_2 = ast_parse_mult_expr(pc, token_index, true); |
| 755 | 766 | |
| 756 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 767 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 757 | 768 | node->data.bin_op_expr.op1 = operand_1; |
| 758 | 769 | node->data.bin_op_expr.bin_op = add_op; |
| 759 | 770 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -801,7 +812,7 @@ static AstNode *ast_parse_bit_shift_expr(ParseContext *pc, int *token_index, boo |
| 801 | 812 | |
| 802 | 813 | AstNode *operand_2 = ast_parse_add_expr(pc, token_index, true); |
| 803 | 814 | |
| 804 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 815 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 805 | 816 | node->data.bin_op_expr.op1 = operand_1; |
| 806 | 817 | node->data.bin_op_expr.bin_op = bit_shift_op; |
| 807 | 818 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -825,7 +836,7 @@ static AstNode *ast_parse_bin_and_expr(ParseContext *pc, int *token_index, bool |
| 825 | 836 | |
| 826 | 837 | AstNode *operand_2 = ast_parse_bit_shift_expr(pc, token_index, true); |
| 827 | 838 | |
| 828 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 839 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 829 | 840 | node->data.bin_op_expr.op1 = operand_1; |
| 830 | 841 | node->data.bin_op_expr.bin_op = BinOpTypeBinAnd; |
| 831 | 842 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -848,7 +859,7 @@ static AstNode *ast_parse_bin_xor_expr(ParseContext *pc, int *token_index, bool |
| 848 | 859 | |
| 849 | 860 | AstNode *operand_2 = ast_parse_bin_and_expr(pc, token_index, true); |
| 850 | 861 | |
| 851 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 862 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 852 | 863 | node->data.bin_op_expr.op1 = operand_1; |
| 853 | 864 | node->data.bin_op_expr.bin_op = BinOpTypeBinXor; |
| 854 | 865 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -871,7 +882,7 @@ static AstNode *ast_parse_bin_or_expr(ParseContext *pc, int *token_index, bool m |
| 871 | 882 | |
| 872 | 883 | AstNode *operand_2 = ast_parse_bin_xor_expr(pc, token_index, true); |
| 873 | 884 | |
| 874 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 885 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 875 | 886 | node->data.bin_op_expr.op1 = operand_1; |
| 876 | 887 | node->data.bin_op_expr.bin_op = BinOpTypeBinOr; |
| 877 | 888 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -920,7 +931,7 @@ static AstNode *ast_parse_comparison_expr(ParseContext *pc, int *token_index, bo |
| 920 | 931 | |
| 921 | 932 | AstNode *operand_2 = ast_parse_bin_or_expr(pc, token_index, true); |
| 922 | 933 | |
| 923 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 934 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 924 | 935 | node->data.bin_op_expr.op1 = operand_1; |
| 925 | 936 | node->data.bin_op_expr.bin_op = cmp_op; |
| 926 | 937 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -943,7 +954,7 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, int *token_index, bool |
| 943 | 954 | |
| 944 | 955 | AstNode *operand_2 = ast_parse_comparison_expr(pc, token_index, true); |
| 945 | 956 | |
| 946 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 957 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 947 | 958 | node->data.bin_op_expr.op1 = operand_1; |
| 948 | 959 | node->data.bin_op_expr.bin_op = BinOpTypeBoolAnd; |
| 949 | 960 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -958,7 +969,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m |
| 958 | 969 | Token *return_tok = &pc->tokens->at(*token_index); |
| 959 | 970 | if (return_tok->id == TokenIdKeywordReturn) { |
| 960 | 971 | *token_index += 1; |
| 961 | AstNode *node = ast_create_node(NodeTypeReturnExpr, return_tok); | |
| 972 | AstNode *node = ast_create_node(pc, NodeTypeReturnExpr, return_tok); | |
| 962 | 973 | node->data.return_expr.expr = ast_parse_expression(pc, token_index, false); |
| 963 | 974 | return node; |
| 964 | 975 | } else if (mandatory) { |
| ... | ... | @@ -983,7 +994,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool |
| 983 | 994 | |
| 984 | 995 | AstNode *operand_2 = ast_parse_bool_and_expr(pc, token_index, true); |
| 985 | 996 | |
| 986 | AstNode *node = ast_create_node(NodeTypeBinOpExpr, token); | |
| 997 | AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); | |
| 987 | 998 | node->data.bin_op_expr.op1 = operand_1; |
| 988 | 999 | node->data.bin_op_expr.bin_op = BinOpTypeBoolOr; |
| 989 | 1000 | node->data.bin_op_expr.op2 = operand_2; |
| ... | ... | @@ -1046,7 +1057,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato |
| 1046 | 1057 | } |
| 1047 | 1058 | *token_index += 1; |
| 1048 | 1059 | |
| 1049 | AstNode *node = ast_create_node(NodeTypeBlock, l_brace); | |
| 1060 | AstNode *node = ast_create_node(pc, NodeTypeBlock, l_brace); | |
| 1050 | 1061 | |
| 1051 | 1062 | for (;;) { |
| 1052 | 1063 | Token *token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -1092,7 +1103,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand |
| 1092 | 1103 | return nullptr; |
| 1093 | 1104 | } |
| 1094 | 1105 | |
| 1095 | AstNode *node = ast_create_node(NodeTypeFnProto, token); | |
| 1106 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, token); | |
| 1096 | 1107 | node->data.fn_proto.visib_mod = visib_mod; |
| 1097 | 1108 | node->data.fn_proto.directives = pc->directive_list; |
| 1098 | 1109 | pc->directive_list = nullptr; |
| ... | ... | @@ -1125,7 +1136,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandat |
| 1125 | 1136 | AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory); |
| 1126 | 1137 | if (!fn_proto) |
| 1127 | 1138 | return nullptr; |
| 1128 | AstNode *node = ast_create_node_with_node(NodeTypeFnDef, fn_proto); | |
| 1139 | AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto); | |
| 1129 | 1140 | |
| 1130 | 1141 | node->data.fn_def.fn_proto = fn_proto; |
| 1131 | 1142 | node->data.fn_def.body = ast_parse_block(pc, token_index, true); |
| ... | ... | @@ -1138,7 +1149,7 @@ FnDecl : FnProto token(Semicolon) |
| 1138 | 1149 | */ |
| 1139 | 1150 | static AstNode *ast_parse_fn_decl(ParseContext *pc, int token_index, int *new_token_index) { |
| 1140 | 1151 | AstNode *fn_proto = ast_parse_fn_proto(pc, &token_index, true); |
| 1141 | AstNode *node = ast_create_node_with_node(NodeTypeFnDecl, fn_proto); | |
| 1152 | AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDecl, fn_proto); | |
| 1142 | 1153 | |
| 1143 | 1154 | node->data.fn_decl.fn_proto = fn_proto; |
| 1144 | 1155 | |
| ... | ... | @@ -1166,7 +1177,7 @@ static AstNode *ast_parse_extern_block(ParseContext *pc, int *token_index, bool |
| 1166 | 1177 | } |
| 1167 | 1178 | *token_index += 1; |
| 1168 | 1179 | |
| 1169 | AstNode *node = ast_create_node(NodeTypeExternBlock, extern_kw); | |
| 1180 | AstNode *node = ast_create_node(pc, NodeTypeExternBlock, extern_kw); | |
| 1170 | 1181 | |
| 1171 | 1182 | node->data.extern_block.directives = pc->directive_list; |
| 1172 | 1183 | pc->directive_list = nullptr; |
| ... | ... | @@ -1184,7 +1195,7 @@ static AstNode *ast_parse_extern_block(ParseContext *pc, int *token_index, bool |
| 1184 | 1195 | Token *token = &pc->tokens->at(*token_index); |
| 1185 | 1196 | if (token->id == TokenIdRBrace) { |
| 1186 | 1197 | if (pc->directive_list->length > 0) { |
| 1187 | ast_error(directive_token, "invalid directive"); | |
| 1198 | ast_error(pc, directive_token, "invalid directive"); | |
| 1188 | 1199 | } |
| 1189 | 1200 | pc->directive_list = nullptr; |
| 1190 | 1201 | |
| ... | ... | @@ -1216,7 +1227,7 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b |
| 1216 | 1227 | |
| 1217 | 1228 | *token_index += 2; |
| 1218 | 1229 | |
| 1219 | AstNode *node = ast_create_node(NodeTypeRootExportDecl, export_kw); | |
| 1230 | AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_kw); | |
| 1220 | 1231 | node->data.root_export_decl.directives = pc->directive_list; |
| 1221 | 1232 | pc->directive_list = nullptr; |
| 1222 | 1233 | |
| ... | ... | @@ -1254,7 +1265,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index, bool mandatory |
| 1254 | 1265 | *token_index += 1; |
| 1255 | 1266 | ast_expect_token(pc, semicolon, TokenIdSemicolon); |
| 1256 | 1267 | |
| 1257 | AstNode *node = ast_create_node(NodeTypeUse, use_kw); | |
| 1268 | AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw); | |
| 1258 | 1269 | |
| 1259 | 1270 | parse_string_literal(pc, use_name, &node->data.use.path); |
| 1260 | 1271 | |
| ... | ... | @@ -1299,7 +1310,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 1299 | 1310 | } |
| 1300 | 1311 | |
| 1301 | 1312 | if (pc->directive_list->length > 0) { |
| 1302 | ast_error(directive_token, "invalid directive"); | |
| 1313 | ast_error(pc, directive_token, "invalid directive"); | |
| 1303 | 1314 | } |
| 1304 | 1315 | pc->directive_list = nullptr; |
| 1305 | 1316 | |
| ... | ... | @@ -1312,7 +1323,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 1312 | 1323 | Root : many(TopLevelDecl) token(EOF) |
| 1313 | 1324 | */ |
| 1314 | 1325 | static AstNode *ast_parse_root(ParseContext *pc, int *token_index) { |
| 1315 | AstNode *node = ast_create_node(NodeTypeRoot, &pc->tokens->at(*token_index)); | |
| 1326 | AstNode *node = ast_create_node(pc, NodeTypeRoot, &pc->tokens->at(*token_index)); | |
| 1316 | 1327 | |
| 1317 | 1328 | ast_parse_top_level_decls(pc, token_index, &node->data.root.top_level_decls); |
| 1318 | 1329 | |
| ... | ... | @@ -1323,8 +1334,9 @@ static AstNode *ast_parse_root(ParseContext *pc, int *token_index) { |
| 1323 | 1334 | return node; |
| 1324 | 1335 | } |
| 1325 | 1336 | |
| 1326 | AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens) { | |
| 1337 | AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner) { | |
| 1327 | 1338 | ParseContext pc = {0}; |
| 1339 | pc.owner = owner; | |
| 1328 | 1340 | pc.buf = buf; |
| 1329 | 1341 | pc.tokens = tokens; |
| 1330 | 1342 | int token_index = 0; |
src/parser.hpp+3-2| ... | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | |
| 15 | 15 | struct AstNode; |
| 16 | 16 | struct CodeGenNode; |
| 17 | struct ImportTableEntry; | |
| 17 | 18 | |
| 18 | 19 | enum NodeType { |
| 19 | 20 | NodeTypeRoot, |
| ... | ... | @@ -166,10 +167,10 @@ struct AstNodeUse { |
| 166 | 167 | |
| 167 | 168 | struct AstNode { |
| 168 | 169 | enum NodeType type; |
| 169 | AstNode *parent; | |
| 170 | 170 | int line; |
| 171 | 171 | int column; |
| 172 | 172 | CodeGenNode *codegen_node; |
| 173 | ImportTableEntry *owner; | |
| 173 | 174 | union { |
| 174 | 175 | AstNodeRoot root; |
| 175 | 176 | AstNodeRootExportDecl root_export_decl; |
| ... | ... | @@ -198,7 +199,7 @@ void ast_token_error(Token *token, const char *format, ...); |
| 198 | 199 | |
| 199 | 200 | |
| 200 | 201 | // This function is provided by generated code, generated by parsergen.cpp |
| 201 | AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens); | |
| 202 | AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner); | |
| 202 | 203 | |
| 203 | 204 | const char *node_type_str(NodeType node_type); |
| 204 | 205 |
src/semantic_info.hpp+4-1| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #include "codegen.hpp" |
| 12 | 12 | #include "hash_map.hpp" |
| 13 | 13 | #include "zig_llvm.hpp" |
| 14 | #include "errmsg.hpp" | |
| 14 | 15 | |
| 15 | 16 | struct FnTableEntry; |
| 16 | 17 | |
| ... | ... | @@ -30,6 +31,8 @@ struct ImportTableEntry { |
| 30 | 31 | AstNode *root; |
| 31 | 32 | Buf *path; // relative to root_source_dir |
| 32 | 33 | LLVMZigDIFile *di_file; |
| 34 | Buf *source_code; | |
| 35 | ZigList<int> *line_offsets; | |
| 33 | 36 | |
| 34 | 37 | // reminder: hash tables must be initialized before use |
| 35 | 38 | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table; |
| ... | ... | @@ -47,7 +50,7 @@ struct FnTableEntry { |
| 47 | 50 | |
| 48 | 51 | struct CodeGen { |
| 49 | 52 | LLVMModuleRef module; |
| 50 | ZigList<ErrorMsg> errors; | |
| 53 | ZigList<ErrorMsg*> errors; | |
| 51 | 54 | LLVMBuilderRef builder; |
| 52 | 55 | LLVMZigDIBuilder *dbuilder; |
| 53 | 56 | LLVMZigDICompileUnit *compile_unit; |
src/tokenizer.cpp+26-17| ... | ... | @@ -104,6 +104,7 @@ enum TokenizeState { |
| 104 | 104 | TokenizeStateBang, |
| 105 | 105 | TokenizeStateLessThan, |
| 106 | 106 | TokenizeStateGreaterThan, |
| 107 | TokenizeStateError, | |
| 107 | 108 | }; |
| 108 | 109 | |
| 109 | 110 | |
| ... | ... | @@ -116,27 +117,25 @@ struct Tokenize { |
| 116 | 117 | int column; |
| 117 | 118 | Token *cur_tok; |
| 118 | 119 | int multi_line_comment_count; |
| 120 | Tokenization *out; | |
| 119 | 121 | }; |
| 120 | 122 | |
| 121 | 123 | __attribute__ ((format (printf, 2, 3))) |
| 122 | 124 | static void tokenize_error(Tokenize *t, const char *format, ...) { |
| 123 | int line; | |
| 124 | int column; | |
| 125 | t->state = TokenizeStateError; | |
| 126 | ||
| 125 | 127 | if (t->cur_tok) { |
| 126 | line = t->cur_tok->start_line + 1; | |
| 127 | column = t->cur_tok->start_column + 1; | |
| 128 | t->out->err_line = t->cur_tok->start_line; | |
| 129 | t->out->err_column = t->cur_tok->start_column; | |
| 128 | 130 | } else { |
| 129 | line = t->line + 1; | |
| 130 | column = t->column + 1; | |
| 131 | t->out->err_line = t->line; | |
| 132 | t->out->err_column = t->column; | |
| 131 | 133 | } |
| 132 | 134 | |
| 133 | 135 | va_list ap; |
| 134 | 136 | va_start(ap, format); |
| 135 | fprintf(stderr, "Error: Line %d, column %d: ", line, column); | |
| 136 | vfprintf(stderr, format, ap); | |
| 137 | fprintf(stderr, "\n"); | |
| 137 | t->out->err = buf_vprintf(format, ap); | |
| 138 | 138 | va_end(ap); |
| 139 | exit(EXIT_FAILURE); | |
| 140 | 139 | } |
| 141 | 140 | |
| 142 | 141 | static void begin_token(Tokenize *t, TokenId id) { |
| ... | ... | @@ -187,13 +186,20 @@ static void end_token(Tokenize *t) { |
| 187 | 186 | t->cur_tok = nullptr; |
| 188 | 187 | } |
| 189 | 188 | |
| 190 | ZigList<Token> *tokenize(Buf *buf) { | |
| 189 | void tokenize(Buf *buf, Tokenization *out) { | |
| 191 | 190 | Tokenize t = {0}; |
| 192 | t.tokens = allocate<ZigList<Token>>(1); | |
| 191 | t.out = out; | |
| 192 | t.tokens = out->tokens = allocate<ZigList<Token>>(1); | |
| 193 | 193 | t.buf = buf; |
| 194 | ||
| 195 | out->line_offsets = allocate<ZigList<int>>(1); | |
| 196 | ||
| 197 | out->line_offsets->append(0); | |
| 194 | 198 | for (t.pos = 0; t.pos < buf_len(t.buf); t.pos += 1) { |
| 195 | 199 | uint8_t c = buf_ptr(t.buf)[t.pos]; |
| 196 | 200 | switch (t.state) { |
| 201 | case TokenizeStateError: | |
| 202 | break; | |
| 197 | 203 | case TokenizeStateStart: |
| 198 | 204 | switch (c) { |
| 199 | 205 | case WHITESPACE: |
| ... | ... | @@ -509,6 +515,7 @@ ZigList<Token> *tokenize(Buf *buf) { |
| 509 | 515 | break; |
| 510 | 516 | } |
| 511 | 517 | if (c == '\n') { |
| 518 | out->line_offsets->append(t.pos + 1); | |
| 512 | 519 | t.line += 1; |
| 513 | 520 | t.column = 0; |
| 514 | 521 | } else { |
| ... | ... | @@ -518,6 +525,7 @@ ZigList<Token> *tokenize(Buf *buf) { |
| 518 | 525 | // EOF |
| 519 | 526 | switch (t.state) { |
| 520 | 527 | case TokenizeStateStart: |
| 528 | case TokenizeStateError: | |
| 521 | 529 | break; |
| 522 | 530 | case TokenizeStateString: |
| 523 | 531 | tokenize_error(&t, "unterminated string"); |
| ... | ... | @@ -544,11 +552,12 @@ ZigList<Token> *tokenize(Buf *buf) { |
| 544 | 552 | tokenize_error(&t, "unterminated multi-line comment"); |
| 545 | 553 | break; |
| 546 | 554 | } |
| 547 | t.pos = -1; | |
| 548 | begin_token(&t, TokenIdEof); | |
| 549 | end_token(&t); | |
| 550 | assert(!t.cur_tok); | |
| 551 | return t.tokens; | |
| 555 | if (t.state != TokenizeStateError) { | |
| 556 | t.pos = -1; | |
| 557 | begin_token(&t, TokenIdEof); | |
| 558 | end_token(&t); | |
| 559 | assert(!t.cur_tok); | |
| 560 | } | |
| 552 | 561 | } |
| 553 | 562 | |
| 554 | 563 | static const char * token_name(Token *token) { |
src/tokenizer.hpp+11-1| ... | ... | @@ -65,7 +65,17 @@ struct Token { |
| 65 | 65 | int start_column; |
| 66 | 66 | }; |
| 67 | 67 | |
| 68 | ZigList<Token> *tokenize(Buf *buf); | |
| 68 | struct Tokenization { | |
| 69 | ZigList<Token> *tokens; | |
| 70 | ZigList<int> *line_offsets; | |
| 71 | ||
| 72 | // if an error occurred | |
| 73 | Buf *err; | |
| 74 | int err_line; | |
| 75 | int err_column; | |
| 76 | }; | |
| 77 | ||
| 78 | void tokenize(Buf *buf, Tokenization *out_tokenization); | |
| 69 | 79 | |
| 70 | 80 | void print_tokens(Buf *buf, ZigList<Token> *tokens); |
| 71 | 81 |
test/run_tests.cpp+11-11| ... | ... | @@ -139,7 +139,7 @@ static void add_compile_failure_test_cases(void) { |
| 139 | 139 | add_compile_fail_case("multiple function definitions", R"SOURCE( |
| 140 | 140 | fn a() {} |
| 141 | 141 | fn a() {} |
| 142 | )SOURCE", 1, "Line 3, column 1: redefinition of 'a'"); | |
| 142 | )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'"); | |
| 143 | 143 | |
| 144 | 144 | add_compile_fail_case("bad directive", R"SOURCE( |
| 145 | 145 | #bogus1("") |
| ... | ... | @@ -148,37 +148,37 @@ extern { |
| 148 | 148 | } |
| 149 | 149 | #bogus2("") |
| 150 | 150 | fn a() {} |
| 151 | )SOURCE", 2, "Line 2, column 1: invalid directive: 'bogus1'", | |
| 152 | "Line 6, column 1: invalid directive: 'bogus2'"); | |
| 151 | )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'", | |
| 152 | ".tmp_source.zig:6:1: error: invalid directive: 'bogus2'"); | |
| 153 | 153 | |
| 154 | 154 | add_compile_fail_case("unreachable with return", R"SOURCE( |
| 155 | 155 | fn a() -> unreachable {return;} |
| 156 | )SOURCE", 1, "Line 2, column 24: return statement in function with unreachable return type"); | |
| 156 | )SOURCE", 1, ".tmp_source.zig:2:24: error: return statement in function with unreachable return type"); | |
| 157 | 157 | |
| 158 | 158 | add_compile_fail_case("control reaches end of non-void function", R"SOURCE( |
| 159 | 159 | fn a() -> i32 {} |
| 160 | )SOURCE", 1, "Line 2, column 1: control reaches end of non-void function"); | |
| 160 | )SOURCE", 1, ".tmp_source.zig:2:1: error: control reaches end of non-void function"); | |
| 161 | 161 | |
| 162 | 162 | add_compile_fail_case("undefined function call", R"SOURCE( |
| 163 | 163 | fn a() { |
| 164 | 164 | b(); |
| 165 | 165 | } |
| 166 | )SOURCE", 1, "Line 3, column 5: undefined function: 'b'"); | |
| 166 | )SOURCE", 1, ".tmp_source.zig:3:5: error: undefined function: 'b'"); | |
| 167 | 167 | |
| 168 | 168 | add_compile_fail_case("wrong number of arguments", R"SOURCE( |
| 169 | 169 | fn a() { |
| 170 | 170 | b(1); |
| 171 | 171 | } |
| 172 | 172 | fn b(a: i32, b: i32, c: i32) { } |
| 173 | )SOURCE", 1, "Line 3, column 5: wrong number of arguments. Expected 3, got 1."); | |
| 173 | )SOURCE", 1, ".tmp_source.zig:3:5: error: wrong number of arguments. Expected 3, got 1."); | |
| 174 | 174 | |
| 175 | 175 | add_compile_fail_case("invalid type", R"SOURCE( |
| 176 | 176 | fn a() -> bogus {} |
| 177 | )SOURCE", 1, "Line 2, column 11: invalid type name: 'bogus'"); | |
| 177 | )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid type name: 'bogus'"); | |
| 178 | 178 | |
| 179 | 179 | add_compile_fail_case("pointer to unreachable", R"SOURCE( |
| 180 | 180 | fn a() -> *mut unreachable {} |
| 181 | )SOURCE", 1, "Line 2, column 11: pointer to unreachable not allowed"); | |
| 181 | )SOURCE", 1, ".tmp_source.zig:2:11: error: pointer to unreachable not allowed"); | |
| 182 | 182 | |
| 183 | 183 | add_compile_fail_case("unreachable code", R"SOURCE( |
| 184 | 184 | fn a() { |
| ... | ... | @@ -187,12 +187,12 @@ fn a() { |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | 189 | fn b() {} |
| 190 | )SOURCE", 1, "Line 4, column 5: unreachable code"); | |
| 190 | )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code"); | |
| 191 | 191 | |
| 192 | 192 | add_compile_fail_case("bad version string", R"SOURCE( |
| 193 | 193 | #version("aoeu") |
| 194 | 194 | export executable "test"; |
| 195 | )SOURCE", 1, "Line 2, column 1: invalid version string"); | |
| 195 | )SOURCE", 1, ".tmp_source.zig:2:1: error: invalid version string"); | |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | 198 | static void print_compiler_invokation(TestCase *test_case, Buf *zig_stderr) { |