| ... | ... | @@ -48,6 +48,14 @@ static Buf *fetch_file(FILE *f) { |
| 48 | 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 | 59 | #define WHITESPACE \ |
| 52 | 60 | ' ': \ |
| 53 | 61 | case '\t': \ |
| ... | ... | @@ -130,6 +138,10 @@ static Buf *fetch_file(FILE *f) { |
| 130 | 138 | |
| 131 | 139 | enum TokenId { |
| 132 | 140 | TokenIdSymbol, |
| 141 | TokenIdKeywordFn, |
| 142 | TokenIdKeywordReturn, |
| 143 | TokenIdKeywordMut, |
| 144 | TokenIdKeywordConst, |
| 133 | 145 | TokenIdLParen, |
| 134 | 146 | TokenIdRParen, |
| 135 | 147 | TokenIdComma, |
| ... | ... | @@ -208,6 +220,20 @@ static void begin_token(Tokenize *t, TokenId id) { |
| 208 | 220 | static void end_token(Tokenize *t) { |
| 209 | 221 | assert(t->cur_tok); |
| 210 | 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 | 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 | 383 | static const char * token_name(Token *token) { |
| 358 | 384 | switch (token->id) { |
| 359 | 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 | 390 | case TokenIdLParen: return "LParen"; |
| 361 | 391 | case TokenIdRParen: return "RParen"; |
| 362 | 392 | case TokenIdComma: return "Comma"; |
| ... | ... | @@ -383,17 +413,86 @@ static void print_tokens(Buf *buf, ZigList<Token> *tokens) { |
| 383 | 413 | } |
| 384 | 414 | } |
| 385 | 415 | |
| 416 | struct AstNode; |
| 417 | |
| 386 | 418 | enum NodeType { |
| 387 | 419 | NodeTypeRoot, |
| 420 | NodeTypeFnDecl, |
| 421 | NodeTypeParam, |
| 422 | NodeTypeType, |
| 423 | NodeTypeBlock, |
| 388 | 424 | }; |
| 389 | 425 | |
| 390 | | struct AstNode { |
| 391 | | enum NodeType type; |
| 392 | | ZigList<AstNode *> children; |
| 426 | struct AstNodeFnDecl { |
| 427 | Buf name; |
| 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 | 471 | enum AstState { |
| 396 | 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 | 498 | struct BuildAst { |
| ... | ... | @@ -402,6 +501,7 @@ struct BuildAst { |
| 402 | 501 | AstState state; |
| 403 | 502 | int line; |
| 404 | 503 | int column; |
| 504 | AstNode *cur_node; |
| 405 | 505 | }; |
| 406 | 506 | |
| 407 | 507 | __attribute__ ((format (printf, 2, 3))) |
| ... | ... | @@ -418,36 +518,320 @@ static void ast_error(BuildAst *b, const char *format, ...) { |
| 418 | 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) { |
| 422 | | size_t str_len = strlen(str); |
| 423 | | if (str_len != mem_len) |
| 424 | | return false; |
| 425 | | return memcmp(mem, str, mem_len) == 0; |
| 521 | static AstNode *ast_create_node(BuildAst *b, NodeType type) { |
| 522 | AstNode *child = allocate<AstNode>(1); |
| 523 | child->prev_state = b->state; |
| 524 | child->parent = b->cur_node; |
| 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 | 601 | static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) { |
| 430 | 602 | BuildAst b = {0}; |
| 603 | b.state = AstStateStart; |
| 431 | 604 | b.buf = buf; |
| 432 | 605 | b.root = allocate<AstNode>(1); |
| 433 | 606 | b.root->type = NodeTypeRoot; |
| 607 | b.cur_node = b.root; |
| 434 | 608 | |
| 435 | 609 | for (int i = 0; i < tokens->length; i += 1) { |
| 436 | 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 | 612 | int token_len = token->end_pos - token->start_pos; |
| 439 | 613 | b.line = token->start_line; |
| 440 | 614 | b.column = token->start_column; |
| 441 | 615 | switch (b.state) { |
| 442 | 616 | case AstStateStart: |
| 443 | | if (mem_eql_str(token_str, token_len, "fn")) { |
| 444 | | zig_panic("TODO fn"); |
| 617 | assert(b.cur_node->type == NodeTypeRoot); |
| 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 | 623 | } else { |
| 446 | 624 | Buf msg = {0}; |
| 447 | | buf_append_str(&msg, "unexpected symbol: '"); |
| 448 | | buf_append_mem(&msg, token_str, token_len); |
| 625 | buf_appendf(&msg, "unexpected %s: '", token_name(token)); |
| 626 | buf_append_mem(&msg, token_mem, token_len); |
| 449 | 627 | buf_append_str(&msg, "'"); |
| 450 | 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 | 836 | break; |
| 453 | 837 | } |
| ... | ... | @@ -456,10 +840,6 @@ static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) { |
| 456 | 840 | return b.root; |
| 457 | 841 | } |
| 458 | 842 | |
| 459 | | static void print_ast(AstNode *node) { |
| 460 | | zig_panic("TODO"); |
| 461 | | } |
| 462 | | |
| 463 | 843 | char cur_dir[1024]; |
| 464 | 844 | |
| 465 | 845 | int main(int argc, char **argv) { |
| ... | ... | @@ -502,12 +882,12 @@ int main(int argc, char **argv) { |
| 502 | 882 | char *result = getcwd(cur_dir, sizeof(cur_dir)); |
| 503 | 883 | if (!result) |
| 504 | 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 | 886 | } else { |
| 507 | 887 | in_f = fopen(in_file, "rb"); |
| 508 | 888 | if (!in_f) |
| 509 | 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 | 893 | Buf *in_data = fetch_file(in_f); |
| ... | ... | @@ -523,7 +903,7 @@ int main(int argc, char **argv) { |
| 523 | 903 | print_tokens(in_data, tokens); |
| 524 | 904 | |
| 525 | 905 | AstNode *root = build_ast(in_data, tokens); |
| 526 | | print_ast(root); |
| 906 | print_ast(root, 0); |
| 527 | 907 | |
| 528 | 908 | |
| 529 | 909 | return EXIT_SUCCESS; |