| ... | @@ -48,6 +48,14 @@ static Buf *fetch_file(FILE *f) { | ... | @@ -48,6 +48,14 @@ static Buf *fetch_file(FILE *f) { |
| 48 | return buf; | 48 | return buf; |
| 49 | } | 49 | } |
| 50 | | 50 | |
| | 51 | static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) { |
| | 52 | size_t str_len = strlen(str); |
| | 53 | if (str_len != mem_len) |
| | 54 | return false; |
| | 55 | return memcmp(mem, str, mem_len) == 0; |
| | 56 | } |
| | 57 | |
| | 58 | |
| 51 | #define WHITESPACE \ | 59 | #define WHITESPACE \ |
| 52 | ' ': \ | 60 | ' ': \ |
| 53 | case '\t': \ | 61 | case '\t': \ |
| ... | @@ -130,6 +138,10 @@ static Buf *fetch_file(FILE *f) { | ... | @@ -130,6 +138,10 @@ static Buf *fetch_file(FILE *f) { |
| 130 | | 138 | |
| 131 | enum TokenId { | 139 | enum TokenId { |
| 132 | TokenIdSymbol, | 140 | TokenIdSymbol, |
| | 141 | TokenIdKeywordFn, |
| | 142 | TokenIdKeywordReturn, |
| | 143 | TokenIdKeywordMut, |
| | 144 | TokenIdKeywordConst, |
| 133 | TokenIdLParen, | 145 | TokenIdLParen, |
| 134 | TokenIdRParen, | 146 | TokenIdRParen, |
| 135 | TokenIdComma, | 147 | TokenIdComma, |
| ... | @@ -208,6 +220,20 @@ static void begin_token(Tokenize *t, TokenId id) { | ... | @@ -208,6 +220,20 @@ static void begin_token(Tokenize *t, TokenId id) { |
| 208 | static void end_token(Tokenize *t) { | 220 | static void end_token(Tokenize *t) { |
| 209 | assert(t->cur_tok); | 221 | assert(t->cur_tok); |
| 210 | t->cur_tok->end_pos = t->pos + 1; | 222 | t->cur_tok->end_pos = t->pos + 1; |
| | 223 | |
| | 224 | char *token_mem = buf_ptr(t->buf) + t->cur_tok->start_pos; |
| | 225 | int token_len = t->cur_tok->end_pos - t->cur_tok->start_pos; |
| | 226 | |
| | 227 | if (mem_eql_str(token_mem, token_len, "fn")) { |
| | 228 | t->cur_tok->id = TokenIdKeywordFn; |
| | 229 | } else if (mem_eql_str(token_mem, token_len, "return")) { |
| | 230 | t->cur_tok->id = TokenIdKeywordReturn; |
| | 231 | } else if (mem_eql_str(token_mem, token_len, "mut")) { |
| | 232 | t->cur_tok->id = TokenIdKeywordMut; |
| | 233 | } else if (mem_eql_str(token_mem, token_len, "const")) { |
| | 234 | t->cur_tok->id = TokenIdKeywordConst; |
| | 235 | } |
| | 236 | |
| 211 | t->cur_tok = nullptr; | 237 | t->cur_tok = nullptr; |
| 212 | } | 238 | } |
| 213 | | 239 | |
| ... | @@ -357,6 +383,10 @@ static ZigList<Token> *tokenize(Buf *buf, ZigList<char *> *include_paths, Buf *c | ... | @@ -357,6 +383,10 @@ static ZigList<Token> *tokenize(Buf *buf, ZigList<char *> *include_paths, Buf *c |
| 357 | static const char * token_name(Token *token) { | 383 | static const char * token_name(Token *token) { |
| 358 | switch (token->id) { | 384 | switch (token->id) { |
| 359 | case TokenIdSymbol: return "Symbol"; | 385 | case TokenIdSymbol: return "Symbol"; |
| | 386 | case TokenIdKeywordFn: return "Fn"; |
| | 387 | case TokenIdKeywordConst: return "Const"; |
| | 388 | case TokenIdKeywordMut: return "Mut"; |
| | 389 | case TokenIdKeywordReturn: return "Return"; |
| 360 | case TokenIdLParen: return "LParen"; | 390 | case TokenIdLParen: return "LParen"; |
| 361 | case TokenIdRParen: return "RParen"; | 391 | case TokenIdRParen: return "RParen"; |
| 362 | case TokenIdComma: return "Comma"; | 392 | case TokenIdComma: return "Comma"; |
| ... | @@ -383,17 +413,86 @@ static void print_tokens(Buf *buf, ZigList<Token> *tokens) { | ... | @@ -383,17 +413,86 @@ static void print_tokens(Buf *buf, ZigList<Token> *tokens) { |
| 383 | } | 413 | } |
| 384 | } | 414 | } |
| 385 | | 415 | |
| | 416 | struct AstNode; |
| | 417 | |
| 386 | enum NodeType { | 418 | enum NodeType { |
| 387 | NodeTypeRoot, | 419 | NodeTypeRoot, |
| | 420 | NodeTypeFnDecl, |
| | 421 | NodeTypeParam, |
| | 422 | NodeTypeType, |
| | 423 | NodeTypeBlock, |
| 388 | }; | 424 | }; |
| 389 | | 425 | |
| 390 | struct AstNode { | 426 | struct AstNodeFnDecl { |
| 391 | enum NodeType type; | 427 | Buf name; |
| 392 | ZigList<AstNode *> children; | 428 | ZigList<AstNode *> params; |
| | 429 | AstNode *return_type; |
| | 430 | AstNode *body; |
| | 431 | }; |
| | 432 | |
| | 433 | struct AstNodeRoot { |
| | 434 | ZigList<AstNode *> fn_decls; |
| | 435 | }; |
| | 436 | |
| | 437 | enum AstNodeTypeType { |
| | 438 | AstNodeTypeTypePrimitive, |
| | 439 | AstNodeTypeTypePointer, |
| | 440 | }; |
| | 441 | |
| | 442 | enum AstPrimitiveType { |
| | 443 | AstPrimitiveTypeVoid, |
| | 444 | AstPrimitiveTypeU8, |
| | 445 | AstPrimitiveTypeI8, |
| | 446 | AstPrimitiveTypeU16, |
| | 447 | AstPrimitiveTypeI16, |
| | 448 | AstPrimitiveTypeU32, |
| | 449 | AstPrimitiveTypeI32, |
| | 450 | AstPrimitiveTypeU64, |
| | 451 | AstPrimitiveTypeI64, |
| | 452 | AstPrimitiveTypeUSize, |
| | 453 | AstPrimitiveTypeISize, |
| | 454 | AstPrimitiveTypeF32, |
| | 455 | AstPrimitiveTypeF64, |
| | 456 | }; |
| | 457 | |
| | 458 | |
| | 459 | struct AstNodeType { |
| | 460 | AstNodeTypeType type; |
| | 461 | AstPrimitiveType primitive_type; |
| | 462 | AstNode *pointer_type; |
| | 463 | bool is_const; |
| | 464 | }; |
| | 465 | |
| | 466 | struct AstNodeParam { |
| | 467 | Buf name; |
| | 468 | AstNode *type; |
| 393 | }; | 469 | }; |
| 394 | | 470 | |
| 395 | enum AstState { | 471 | enum AstState { |
| 396 | AstStateStart, | 472 | AstStateStart, |
| | 473 | AstStateFn, |
| | 474 | AstStateFnLParen, |
| | 475 | AstStateFnParamName, |
| | 476 | AstStateParamColon, |
| | 477 | AstStateType, |
| | 478 | AstStateTypeEnd, |
| | 479 | AstStateFnParamComma, |
| | 480 | AstStateFnDeclArrow, |
| | 481 | AstStateFnDeclBlock, |
| | 482 | AstStatePointerType, |
| | 483 | AstStateBlock, |
| | 484 | }; |
| | 485 | |
| | 486 | struct AstNode { |
| | 487 | enum NodeType type; |
| | 488 | AstNode *parent; |
| | 489 | AstState prev_state; |
| | 490 | union { |
| | 491 | AstNodeRoot root; |
| | 492 | AstNodeFnDecl fn_decl; |
| | 493 | AstNodeType type; |
| | 494 | AstNodeParam param; |
| | 495 | } data; |
| 397 | }; | 496 | }; |
| 398 | | 497 | |
| 399 | struct BuildAst { | 498 | struct BuildAst { |
| ... | @@ -402,6 +501,7 @@ struct BuildAst { | ... | @@ -402,6 +501,7 @@ struct BuildAst { |
| 402 | AstState state; | 501 | AstState state; |
| 403 | int line; | 502 | int line; |
| 404 | int column; | 503 | int column; |
| | 504 | AstNode *cur_node; |
| 405 | }; | 505 | }; |
| 406 | | 506 | |
| 407 | __attribute__ ((format (printf, 2, 3))) | 507 | __attribute__ ((format (printf, 2, 3))) |
| ... | @@ -418,36 +518,320 @@ static void ast_error(BuildAst *b, const char *format, ...) { | ... | @@ -418,36 +518,320 @@ static void ast_error(BuildAst *b, const char *format, ...) { |
| 418 | exit(EXIT_FAILURE); | 518 | exit(EXIT_FAILURE); |
| 419 | } | 519 | } |
| 420 | | 520 | |
| 421 | static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) { | 521 | static AstNode *ast_create_node(BuildAst *b, NodeType type) { |
| 422 | size_t str_len = strlen(str); | 522 | AstNode *child = allocate<AstNode>(1); |
| 423 | if (str_len != mem_len) | 523 | child->prev_state = b->state; |
| 424 | return false; | 524 | child->parent = b->cur_node; |
| 425 | return memcmp(mem, str, mem_len) == 0; | 525 | child->type = type; |
| | 526 | return child; |
| | 527 | } |
| | 528 | |
| | 529 | static void ast_make_node_current(BuildAst *b, AstNode *node) { |
| | 530 | b->cur_node = node; |
| | 531 | } |
| | 532 | |
| | 533 | static void ast_up_stack(BuildAst *b) { |
| | 534 | assert(b->cur_node->parent); |
| | 535 | b->state = b->cur_node->prev_state; |
| | 536 | b->cur_node = b->cur_node->parent; |
| | 537 | } |
| | 538 | |
| | 539 | |
| | 540 | static const char *node_type_str(NodeType node_type) { |
| | 541 | switch (node_type) { |
| | 542 | case NodeTypeRoot: return "Root"; |
| | 543 | case NodeTypeFnDecl: return "FnDecl"; |
| | 544 | case NodeTypeParam: return "Param"; |
| | 545 | case NodeTypeType: return "Type"; |
| | 546 | case NodeTypeBlock: return "Block"; |
| | 547 | } |
| | 548 | zig_panic("unreachable"); |
| | 549 | } |
| | 550 | |
| | 551 | static void print_ast(AstNode *node, int indent) { |
| | 552 | for (int i = 0; i < indent; i += 1) { |
| | 553 | fprintf(stderr, " "); |
| | 554 | } |
| | 555 | |
| | 556 | switch (node->type) { |
| | 557 | case NodeTypeRoot: |
| | 558 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| | 559 | for (int i = 0; i < node->data.root.fn_decls.length; i += 1) { |
| | 560 | AstNode *child = node->data.root.fn_decls.at(i); |
| | 561 | print_ast(child, indent + 2); |
| | 562 | } |
| | 563 | break; |
| | 564 | case NodeTypeFnDecl: |
| | 565 | { |
| | 566 | Buf *name_buf = &node->data.fn_decl.name; |
| | 567 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); |
| | 568 | |
| | 569 | for (int i = 0; i < node->data.fn_decl.params.length; i += 1) { |
| | 570 | AstNode *child = node->data.fn_decl.params.at(i); |
| | 571 | print_ast(child, indent + 2); |
| | 572 | } |
| | 573 | |
| | 574 | print_ast(node->data.fn_decl.return_type, indent + 2); |
| | 575 | |
| | 576 | print_ast(node->data.fn_decl.body, indent + 2); |
| | 577 | |
| | 578 | break; |
| | 579 | } |
| | 580 | case NodeTypeParam: |
| | 581 | { |
| | 582 | Buf *name_buf = &node->data.param.name; |
| | 583 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); |
| | 584 | |
| | 585 | print_ast(node->data.param.type, indent + 2); |
| | 586 | break; |
| | 587 | } |
| | 588 | case NodeTypeType: |
| | 589 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| | 590 | break; |
| | 591 | case NodeTypeBlock: |
| | 592 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| | 593 | break; |
| | 594 | } |
| 426 | } | 595 | } |
| 427 | | 596 | |
| | 597 | static void ast_end_fn_param_list(BuildAst *b) { |
| | 598 | b->state = AstStateFnDeclArrow; |
| | 599 | } |
| 428 | | 600 | |
| 429 | static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) { | 601 | static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) { |
| 430 | BuildAst b = {0}; | 602 | BuildAst b = {0}; |
| | 603 | b.state = AstStateStart; |
| 431 | b.buf = buf; | 604 | b.buf = buf; |
| 432 | b.root = allocate<AstNode>(1); | 605 | b.root = allocate<AstNode>(1); |
| 433 | b.root->type = NodeTypeRoot; | 606 | b.root->type = NodeTypeRoot; |
| | 607 | b.cur_node = b.root; |
| 434 | | 608 | |
| 435 | for (int i = 0; i < tokens->length; i += 1) { | 609 | for (int i = 0; i < tokens->length; i += 1) { |
| 436 | Token *token = &tokens->at(i); | 610 | Token *token = &tokens->at(i); |
| 437 | const char *token_str = buf_ptr(buf) + token->start_pos; | 611 | char *token_mem = buf_ptr(buf) + token->start_pos; |
| 438 | int token_len = token->end_pos - token->start_pos; | 612 | int token_len = token->end_pos - token->start_pos; |
| 439 | b.line = token->start_line; | 613 | b.line = token->start_line; |
| 440 | b.column = token->start_column; | 614 | b.column = token->start_column; |
| 441 | switch (b.state) { | 615 | switch (b.state) { |
| 442 | case AstStateStart: | 616 | case AstStateStart: |
| 443 | if (mem_eql_str(token_str, token_len, "fn")) { | 617 | assert(b.cur_node->type == NodeTypeRoot); |
| 444 | zig_panic("TODO fn"); | 618 | if (token->id == TokenIdKeywordFn) { |
| | 619 | AstNode *child = ast_create_node(&b, NodeTypeFnDecl); |
| | 620 | b.cur_node->data.root.fn_decls.append(child); |
| | 621 | ast_make_node_current(&b, child); |
| | 622 | b.state = AstStateFn; |
| 445 | } else { | 623 | } else { |
| 446 | Buf msg = {0}; | 624 | Buf msg = {0}; |
| 447 | buf_append_str(&msg, "unexpected symbol: '"); | 625 | buf_appendf(&msg, "unexpected %s: '", token_name(token)); |
| 448 | buf_append_mem(&msg, token_str, token_len); | 626 | buf_append_mem(&msg, token_mem, token_len); |
| 449 | buf_append_str(&msg, "'"); | 627 | buf_append_str(&msg, "'"); |
| 450 | ast_error(&b, "%s", buf_ptr(&msg)); | 628 | ast_error(&b, "%s", buf_ptr(&msg)); |
| | 629 | break; |
| | 630 | } |
| | 631 | break; |
| | 632 | case AstStateFn: |
| | 633 | if (token->id != TokenIdSymbol) |
| | 634 | ast_error(&b, "expected symbol"); |
| | 635 | buf_init_from_mem(&b.cur_node->data.fn_decl.name, token_mem, token_len); |
| | 636 | b.state = AstStateFnLParen; |
| | 637 | break; |
| | 638 | case AstStateFnLParen: |
| | 639 | if (token->id != TokenIdLParen) |
| | 640 | ast_error(&b, "expected '('"); |
| | 641 | b.state = AstStateFnParamName; |
| | 642 | break; |
| | 643 | case AstStateFnParamName: |
| | 644 | switch (token->id) { |
| | 645 | case TokenIdSymbol: |
| | 646 | { |
| | 647 | b.state = AstStateFnParamComma; |
| | 648 | AstNode *child = ast_create_node(&b, NodeTypeParam); |
| | 649 | buf_init_from_mem(&child->data.param.name, token_mem, token_len); |
| | 650 | b.cur_node->data.fn_decl.params.append(child); |
| | 651 | ast_make_node_current(&b, child); |
| | 652 | b.state = AstStateParamColon; |
| | 653 | break; |
| | 654 | } |
| | 655 | case TokenIdRParen: |
| | 656 | ast_end_fn_param_list(&b); |
| | 657 | break; |
| | 658 | default: |
| | 659 | ast_error(&b, "expected parameter name"); |
| | 660 | break; |
| | 661 | } |
| | 662 | break; |
| | 663 | case AstStateParamColon: |
| | 664 | { |
| | 665 | if (token->id != TokenIdColon) |
| | 666 | ast_error(&b, "expected ':'"); |
| | 667 | assert(b.cur_node->type == NodeTypeParam); |
| | 668 | b.state = AstStateTypeEnd; |
| | 669 | AstNode *child = ast_create_node(&b, NodeTypeType); |
| | 670 | b.cur_node->data.param.type = child; |
| | 671 | ast_make_node_current(&b, child); |
| | 672 | b.state = AstStateType; |
| | 673 | break; |
| | 674 | } |
| | 675 | case AstStateType: |
| | 676 | switch (token->id) { |
| | 677 | case TokenIdSymbol: |
| | 678 | assert(b.cur_node->type == NodeTypeType); |
| | 679 | if (mem_eql_str(token_mem, token_len, "u8")) { |
| | 680 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 681 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeU8; |
| | 682 | ast_up_stack(&b); |
| | 683 | } else if (mem_eql_str(token_mem, token_len, "i8")) { |
| | 684 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 685 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeI8; |
| | 686 | ast_up_stack(&b); |
| | 687 | } else if (mem_eql_str(token_mem, token_len, "u16")) { |
| | 688 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 689 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeU16; |
| | 690 | ast_up_stack(&b); |
| | 691 | } else if (mem_eql_str(token_mem, token_len, "i16")) { |
| | 692 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 693 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeI16; |
| | 694 | ast_up_stack(&b); |
| | 695 | } else if (mem_eql_str(token_mem, token_len, "u32")) { |
| | 696 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 697 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeU32; |
| | 698 | ast_up_stack(&b); |
| | 699 | } else if (mem_eql_str(token_mem, token_len, "i32")) { |
| | 700 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 701 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeI32; |
| | 702 | ast_up_stack(&b); |
| | 703 | } else if (mem_eql_str(token_mem, token_len, "u64")) { |
| | 704 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 705 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeU64; |
| | 706 | ast_up_stack(&b); |
| | 707 | } else if (mem_eql_str(token_mem, token_len, "i64")) { |
| | 708 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 709 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeI64; |
| | 710 | ast_up_stack(&b); |
| | 711 | } else if (mem_eql_str(token_mem, token_len, "usize")) { |
| | 712 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 713 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeUSize; |
| | 714 | ast_up_stack(&b); |
| | 715 | } else if (mem_eql_str(token_mem, token_len, "isize")) { |
| | 716 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 717 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeISize; |
| | 718 | ast_up_stack(&b); |
| | 719 | } else if (mem_eql_str(token_mem, token_len, "f32")) { |
| | 720 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 721 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeF32; |
| | 722 | ast_up_stack(&b); |
| | 723 | } else if (mem_eql_str(token_mem, token_len, "f64")) { |
| | 724 | b.cur_node->data.type.type = AstNodeTypeTypePrimitive; |
| | 725 | b.cur_node->data.type.primitive_type = AstPrimitiveTypeF64; |
| | 726 | ast_up_stack(&b); |
| | 727 | } else { |
| | 728 | Buf msg = {0}; |
| | 729 | buf_append_str(&msg, "invalid primitive type: '"); |
| | 730 | buf_append_mem(&msg, token_mem, token_len); |
| | 731 | buf_append_str(&msg, "'"); |
| | 732 | ast_error(&b, "%s", buf_ptr(&msg)); |
| | 733 | } |
| | 734 | break; |
| | 735 | case TokenIdStar: |
| | 736 | b.cur_node->data.type.type = AstNodeTypeTypePointer; |
| | 737 | b.state = AstStatePointerType; |
| | 738 | break; |
| | 739 | default: |
| | 740 | ast_error(&b, "expected type name"); |
| | 741 | break; |
| | 742 | } |
| | 743 | break; |
| | 744 | case AstStatePointerType: |
| | 745 | { |
| | 746 | if (token->id == TokenIdKeywordMut) { |
| | 747 | b.cur_node->data.type.is_const = false; |
| | 748 | } else if (token->id == TokenIdKeywordConst) { |
| | 749 | b.cur_node->data.type.is_const = true; |
| | 750 | } else { |
| | 751 | ast_error(&b, "expected 'mut' or 'const'"); |
| | 752 | } |
| | 753 | b.state = AstStateTypeEnd; |
| | 754 | AstNode *child = ast_create_node(&b, NodeTypeType); |
| | 755 | b.cur_node->data.type.pointer_type = child; |
| | 756 | ast_make_node_current(&b, child); |
| | 757 | b.state = AstStateType; |
| | 758 | break; |
| | 759 | } |
| | 760 | case AstStateTypeEnd: |
| | 761 | ast_up_stack(&b); |
| | 762 | i -= 1; |
| | 763 | continue; |
| | 764 | case AstStateFnParamComma: |
| | 765 | switch (token->id) { |
| | 766 | case TokenIdComma: |
| | 767 | b.state = AstStateFnParamName; |
| | 768 | break; |
| | 769 | case TokenIdRParen: |
| | 770 | ast_end_fn_param_list(&b); |
| | 771 | break; |
| | 772 | default: |
| | 773 | ast_error(&b, "expected ',' or ')'"); |
| | 774 | break; |
| | 775 | |
| | 776 | } |
| | 777 | break; |
| | 778 | case AstStateFnDeclArrow: |
| | 779 | switch (token->id) { |
| | 780 | case TokenIdArrow: |
| | 781 | { |
| | 782 | assert(b.cur_node->type == NodeTypeFnDecl); |
| | 783 | b.state = AstStateFnDeclBlock; |
| | 784 | AstNode *child = ast_create_node(&b, NodeTypeType); |
| | 785 | b.cur_node->data.fn_decl.return_type = child; |
| | 786 | ast_make_node_current(&b, child); |
| | 787 | b.state = AstStateType; |
| | 788 | break; |
| | 789 | } |
| | 790 | case TokenIdLBrace: |
| | 791 | { |
| | 792 | AstNode *node = ast_create_node(&b, NodeTypeType); |
| | 793 | node->data.type.type = AstNodeTypeTypePrimitive; |
| | 794 | node->data.type.primitive_type = AstPrimitiveTypeVoid; |
| | 795 | b.cur_node->data.fn_decl.return_type = node; |
| | 796 | |
| | 797 | b.state = AstStateTypeEnd; |
| | 798 | AstNode *child = ast_create_node(&b, NodeTypeBlock); |
| | 799 | b.cur_node->data.fn_decl.body = child; |
| | 800 | ast_make_node_current(&b, child); |
| | 801 | b.state = AstStateBlock; |
| | 802 | break; |
| | 803 | } |
| | 804 | default: |
| | 805 | ast_error(&b, "expected '->' or '}'"); |
| | 806 | break; |
| | 807 | } |
| | 808 | break; |
| | 809 | case AstStateFnDeclBlock: |
| | 810 | { |
| | 811 | if (token->id != TokenIdLBrace) |
| | 812 | ast_error(&b, "expected '{'"); |
| | 813 | |
| | 814 | b.state = AstStateTypeEnd; |
| | 815 | AstNode *child = ast_create_node(&b, NodeTypeBlock); |
| | 816 | b.cur_node->data.fn_decl.body = child; |
| | 817 | ast_make_node_current(&b, child); |
| | 818 | b.state = AstStateBlock; |
| | 819 | break; |
| | 820 | } |
| | 821 | case AstStateBlock: |
| | 822 | switch (token->id) { |
| | 823 | case TokenIdSymbol: |
| | 824 | zig_panic("TODO symbol"); |
| | 825 | break; |
| | 826 | default: |
| | 827 | { |
| | 828 | Buf msg = {0}; |
| | 829 | buf_appendf(&msg, "unexpected %s: '", token_name(token)); |
| | 830 | buf_append_mem(&msg, token_mem, token_len); |
| | 831 | buf_append_str(&msg, "'"); |
| | 832 | ast_error(&b, "%s", buf_ptr(&msg)); |
| | 833 | break; |
| | 834 | } |
| 451 | } | 835 | } |
| 452 | break; | 836 | break; |
| 453 | } | 837 | } |
| ... | @@ -456,10 +840,6 @@ static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) { | ... | @@ -456,10 +840,6 @@ static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) { |
| 456 | return b.root; | 840 | return b.root; |
| 457 | } | 841 | } |
| 458 | | 842 | |
| 459 | static void print_ast(AstNode *node) { | | |
| 460 | zig_panic("TODO"); | | |
| 461 | } | | |
| 462 | | | |
| 463 | char cur_dir[1024]; | 843 | char cur_dir[1024]; |
| 464 | | 844 | |
| 465 | int main(int argc, char **argv) { | 845 | int main(int argc, char **argv) { |
| ... | @@ -502,12 +882,12 @@ int main(int argc, char **argv) { | ... | @@ -502,12 +882,12 @@ int main(int argc, char **argv) { |
| 502 | char *result = getcwd(cur_dir, sizeof(cur_dir)); | 882 | char *result = getcwd(cur_dir, sizeof(cur_dir)); |
| 503 | if (!result) | 883 | if (!result) |
| 504 | zig_panic("unable to get current working directory: %s", strerror(errno)); | 884 | zig_panic("unable to get current working directory: %s", strerror(errno)); |
| 505 | cur_dir_path = buf_from_str(result); | 885 | cur_dir_path = buf_create_from_str(result); |
| 506 | } else { | 886 | } else { |
| 507 | in_f = fopen(in_file, "rb"); | 887 | in_f = fopen(in_file, "rb"); |
| 508 | if (!in_f) | 888 | if (!in_f) |
| 509 | zig_panic("unable to open %s for reading: %s\n", in_file, strerror(errno)); | 889 | zig_panic("unable to open %s for reading: %s\n", in_file, strerror(errno)); |
| 510 | cur_dir_path = buf_dirname(buf_from_str(in_file)); | 890 | cur_dir_path = buf_dirname(buf_create_from_str(in_file)); |
| 511 | } | 891 | } |
| 512 | | 892 | |
| 513 | Buf *in_data = fetch_file(in_f); | 893 | Buf *in_data = fetch_file(in_f); |
| ... | @@ -523,7 +903,7 @@ int main(int argc, char **argv) { | ... | @@ -523,7 +903,7 @@ int main(int argc, char **argv) { |
| 523 | print_tokens(in_data, tokens); | 903 | print_tokens(in_data, tokens); |
| 524 | | 904 | |
| 525 | AstNode *root = build_ast(in_data, tokens); | 905 | AstNode *root = build_ast(in_data, tokens); |
| 526 | print_ast(root); | 906 | print_ast(root, 0); |
| 527 | | 907 | |
| 528 | | 908 | |
| 529 | return EXIT_SUCCESS; | 909 | return EXIT_SUCCESS; |