authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-02 03:39:36-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-02 03:39:36-07:00
log303823b6b8b250580d644bacce5285efda76b731
tree9ba13c51bf8e0bcbe00b7309076f3e9283006e51
parent34f8d80eac87a5e3bdf495163d8bc0fbd80ae83f

building part of the hello world AST


4 files changed, 414 insertions(+), 25 deletions(-)

README.md+5
...@@ -29,4 +29,9 @@ readable, safe, optimal, and concise code to solve any computing problem....@@ -29,4 +29,9 @@ readable, safe, optimal, and concise code to solve any computing problem.
29## Roadmap29## Roadmap
3030
31 * Hello, world.31 * Hello, world.
32 - Build AST
33 - Code Gen
34 * C style comments.
35 * Unit tests.
36 * Simple .so library
32 * How should the Widget use case be solved? In Genesis I'm using C++ and inheritance.37 * How should the Widget use case be solved? In Genesis I'm using C++ and inheritance.
src/buffer.hpp+8-4
...@@ -49,16 +49,20 @@ static inline void buf_deinit(Buf *buf) {...@@ -49,16 +49,20 @@ static inline void buf_deinit(Buf *buf) {
49 buf->list.deinit();49 buf->list.deinit();
50}50}
5151
52static inline Buf *buf_from_mem(char *ptr, int len) {52static inline void buf_init_from_mem(Buf *buf, char *ptr, int len) {
53 Buf *buf = allocate<Buf>(1);
54 buf->list.resize(len + 1);53 buf->list.resize(len + 1);
55 memcpy(buf_ptr(buf), ptr, len);54 memcpy(buf_ptr(buf), ptr, len);
56 buf->list.at(buf_len(buf)) = 0;55 buf->list.at(buf_len(buf)) = 0;
56}
57
58static inline Buf *buf_create_from_mem(char *ptr, int len) {
59 Buf *buf = allocate<Buf>(1);
60 buf_init_from_mem(buf, ptr, len);
57 return buf;61 return buf;
58}62}
5963
60static inline Buf *buf_from_str(char *str) {64static inline Buf *buf_create_from_str(char *str) {
61 return buf_from_mem(str, strlen(str));65 return buf_create_from_mem(str, strlen(str));
62}66}
6367
64static inline Buf *buf_slice(Buf *in_buf, int start, int end) {68static inline Buf *buf_slice(Buf *in_buf, int start, int end) {
src/main.cpp+400-20
...@@ -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}
5050
51static 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) {
130138
131enum TokenId {139enum 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) {
208static void end_token(Tokenize *t) {220static 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}
213239
...@@ -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
357static const char * token_name(Token *token) {383static 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}
385415
416struct AstNode;
417
386enum NodeType {418enum NodeType {
387 NodeTypeRoot,419 NodeTypeRoot,
420 NodeTypeFnDecl,
421 NodeTypeParam,
422 NodeTypeType,
423 NodeTypeBlock,
388};424};
389425
390struct AstNode {426struct 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
433struct AstNodeRoot {
434 ZigList<AstNode *> fn_decls;
435};
436
437enum AstNodeTypeType {
438 AstNodeTypeTypePrimitive,
439 AstNodeTypeTypePointer,
440};
441
442enum 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
459struct AstNodeType {
460 AstNodeTypeType type;
461 AstPrimitiveType primitive_type;
462 AstNode *pointer_type;
463 bool is_const;
464};
465
466struct AstNodeParam {
467 Buf name;
468 AstNode *type;
393};469};
394470
395enum AstState {471enum 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
486struct 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};
398497
399struct BuildAst {498struct 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};
406506
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}
420520
421static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {521static 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
529static void ast_make_node_current(BuildAst *b, AstNode *node) {
530 b->cur_node = node;
531}
532
533static 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
540static 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
551static 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}
427596
597static void ast_end_fn_param_list(BuildAst *b) {
598 b->state = AstStateFnDeclArrow;
599}
428600
429static AstNode *build_ast(Buf *buf, ZigList<Token> *tokens) {601static 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;
434608
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}
458842
459static void print_ast(AstNode *node) {
460 zig_panic("TODO");
461}
462
463char cur_dir[1024];843char cur_dir[1024];
464844
465int main(int argc, char **argv) {845int 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 }
512892
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);
524904
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);
527907
528908
529 return EXIT_SUCCESS;909 return EXIT_SUCCESS;
test/hello.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
11
22
3fn main(argc: int, argv: *mut char) -> int {3fn main(argc: isize, argv: *mut u8) -> isize {
4 puts("Hello, world!\n");4 puts("Hello, world!\n");
5 return 0;5 return 0;
6}6}