authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-11-29 14:52:49-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-11-29 14:52:49-07:00
log30442ed893c4477851d37c865eb978c4bf27c814
tree406d86f58bcda7ab68affb8c37c6787854338884
parent9a014b52ccc22d7ec24804f90993cfe08e3d20c4
parentc1d77f2a231461d88ad493c92079cc571e565f87

merge conflicts


7 files changed, 228 insertions(+), 108 deletions(-)

README.md+12-6
...@@ -88,6 +88,8 @@ ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnDecl) token(RBr...@@ -88,6 +88,8 @@ ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnDecl) token(RBr
8888
89FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type)89FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type)
9090
91Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)
92
91FnVisibleMod : token(Pub) | token(Export)93FnVisibleMod : token(Pub) | token(Export)
9294
93FnDecl : FnProto token(Semicolon)95FnDecl : FnProto token(Semicolon)
...@@ -138,20 +140,24 @@ MultiplyExpression : CastExpression MultiplyOperator CastExpression | CastExpres...@@ -138,20 +140,24 @@ MultiplyExpression : CastExpression MultiplyOperator CastExpression | CastExpres
138140
139MultiplyOperator : token(Star) | token(Slash) | token(Percent)141MultiplyOperator : token(Star) | token(Slash) | token(Percent)
140142
141CastExpression : PrimaryExpression token(as) Type | PrimaryExpression143CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression
142144
143PrimaryExpression : token(Number) | token(String) | token(Unreachable) | FnCall | GroupedExpression | Block145PrefixOpExpression : PrefixOp FnCallExpression | FnCallExpression
144146
145GroupedExpression : token(LParen) Expression token(RParen)147FnCallExpression : PrimaryExpression token(LParen) list(Expression, token(Comma)) token(RParen) | PrimaryExpression
146148
147FnCall : token(Symbol) token(LParen) list(Expression, token(Comma)) token(RParen)149PrefixOp : token(Not) | token(Dash) | token(Tilde)
148150
149Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)151PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | Block | token(Symbol)
152
153GroupedExpression : token(LParen) Expression token(RParen)
150```154```
151155
152### Binary Operator Precedence156### Operator Precedence
153157
154```158```
159x()
160!x -x ~x
155as161as
156* / %162* / %
157+ -163+ -
example/math.zig-1
...@@ -3,4 +3,3 @@ export library "math";...@@ -3,4 +3,3 @@ export library "math";
3export fn add(a: i32, b: i32) -> i32 {3export fn add(a: i32, b: i32) -> i32 {
4 return a + b;4 return a + b;
5}5}
6
src/codegen.cpp+83-42
...@@ -306,9 +306,10 @@ static void find_declarations(CodeGen *g, AstNode *node) {...@@ -306,9 +306,10 @@ static void find_declarations(CodeGen *g, AstNode *node) {
306 case NodeTypeRoot:306 case NodeTypeRoot:
307 case NodeTypeBlock:307 case NodeTypeBlock:
308 case NodeTypeBinOpExpr:308 case NodeTypeBinOpExpr:
309 case NodeTypeFnCall:309 case NodeTypeFnCallExpr:
310 case NodeTypeRootExportDecl:310 case NodeTypeRootExportDecl:
311 case NodeTypeCastExpr:311 case NodeTypeCastExpr:
312 case NodeTypePrefixOpExpr:
312 case NodeTypePrimaryExpr:313 case NodeTypePrimaryExpr:
313 case NodeTypeGroupedExpr:314 case NodeTypeGroupedExpr:
314 zig_unreachable();315 zig_unreachable();
...@@ -369,6 +370,14 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {...@@ -369,6 +370,14 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
369 }370 }
370}371}
371372
373static Buf *hack_get_fn_call_name(CodeGen *g, AstNode *node) {
374 // Assume that the expression evaluates to a simple name and return the buf
375 // TODO after type checking works we should be able to remove this hack
376 assert(node->type == NodeTypePrimaryExpr);
377 assert(node->data.primary_expr.type == PrimaryExprTypeSymbol);
378 return &node->data.primary_expr.data.symbol;
379}
380
372static void analyze_node(CodeGen *g, AstNode *node) {381static void analyze_node(CodeGen *g, AstNode *node) {
373 switch (node->type) {382 switch (node->type) {
374 case NodeTypeRoot:383 case NodeTypeRoot:
...@@ -477,9 +486,9 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -477,9 +486,9 @@ static void analyze_node(CodeGen *g, AstNode *node) {
477 analyze_node(g, node->data.bin_op_expr.op1);486 analyze_node(g, node->data.bin_op_expr.op1);
478 analyze_node(g, node->data.bin_op_expr.op2);487 analyze_node(g, node->data.bin_op_expr.op2);
479 break;488 break;
480 case NodeTypeFnCall:489 case NodeTypeFnCallExpr:
481 {490 {
482 Buf *name = &node->data.fn_call.name;491 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
483492
484 auto entry = g->fn_table.maybe_get(name);493 auto entry = g->fn_table.maybe_get(name);
485 if (!entry) {494 if (!entry) {
...@@ -489,7 +498,7 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -489,7 +498,7 @@ static void analyze_node(CodeGen *g, AstNode *node) {
489 FnTableEntry *fn_table_entry = entry->value;498 FnTableEntry *fn_table_entry = entry->value;
490 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);499 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
491 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;500 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;
492 int actual_param_count = node->data.fn_call.params.length;501 int actual_param_count = node->data.fn_call_expr.params.length;
493 if (expected_param_count != actual_param_count) {502 if (expected_param_count != actual_param_count) {
494 add_node_error(g, node,503 add_node_error(g, node,
495 buf_sprintf("wrong number of arguments. Expected %d, got %d.",504 buf_sprintf("wrong number of arguments. Expected %d, got %d.",
...@@ -497,8 +506,8 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -497,8 +506,8 @@ static void analyze_node(CodeGen *g, AstNode *node) {
497 }506 }
498 }507 }
499508
500 for (int i = 0; i < node->data.fn_call.params.length; i += 1) {509 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
501 AstNode *child = node->data.fn_call.params.at(i);510 AstNode *child = node->data.fn_call_expr.params.at(i);
502 analyze_node(g, child);511 analyze_node(g, child);
503 }512 }
504 break;513 break;
...@@ -509,16 +518,17 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -509,16 +518,17 @@ static void analyze_node(CodeGen *g, AstNode *node) {
509 case NodeTypeCastExpr:518 case NodeTypeCastExpr:
510 zig_panic("TODO");519 zig_panic("TODO");
511 break;520 break;
521 case NodeTypePrefixOpExpr:
522 zig_panic("TODO");
523 break;
512 case NodeTypePrimaryExpr:524 case NodeTypePrimaryExpr:
513 switch (node->data.primary_expr.type) {525 switch (node->data.primary_expr.type) {
514 case PrimaryExprTypeNumber:526 case PrimaryExprTypeNumber:
515 case PrimaryExprTypeString:527 case PrimaryExprTypeString:
516 case PrimaryExprTypeUnreachable:528 case PrimaryExprTypeUnreachable:
529 case PrimaryExprTypeSymbol:
517 // nothing to do530 // nothing to do
518 break;531 break;
519 case PrimaryExprTypeFnCall:
520 analyze_node(g, node->data.primary_expr.data.fn_call);
521 break;
522 case PrimaryExprTypeGroupedExpr:532 case PrimaryExprTypeGroupedExpr:
523 analyze_node(g, node->data.primary_expr.data.grouped_expr);533 analyze_node(g, node->data.primary_expr.data.grouped_expr);
524 break;534 break;
...@@ -625,33 +635,6 @@ static void add_debug_source_node(CodeGen *g, AstNode *node) {...@@ -625,33 +635,6 @@ static void add_debug_source_node(CodeGen *g, AstNode *node) {
625 g->block_scopes.last()));635 g->block_scopes.last()));
626}636}
627637
628static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) {
629 assert(fn_call_node->type == NodeTypeFnCall);
630
631 Buf *name = &fn_call_node->data.fn_call.name;
632 FnTableEntry *fn_table_entry = g->fn_table.get(name);
633 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
634 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;
635 int actual_param_count = fn_call_node->data.fn_call.params.length;
636 assert(expected_param_count == actual_param_count);
637
638 LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count);
639 for (int i = 0; i < actual_param_count; i += 1) {
640 AstNode *expr_node = fn_call_node->data.fn_call.params.at(i);
641 param_values[i] = gen_expr(g, expr_node);
642 }
643
644 add_debug_source_node(g, fn_call_node);
645 LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value,
646 param_values, actual_param_count, fn_table_entry->calling_convention, "");
647
648 if (type_is_unreachable(fn_table_entry->proto_node->data.fn_proto.return_type)) {
649 return LLVMBuildUnreachable(g->builder);
650 } else {
651 return result;
652 }
653}
654
655static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {638static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {
656 auto entry = g->str_table.maybe_get(str);639 auto entry = g->str_table.maybe_get(str);
657 if (entry) {640 if (entry) {
...@@ -696,21 +679,76 @@ static LLVMValueRef gen_primary_expr(CodeGen *g, AstNode *node) {...@@ -696,21 +679,76 @@ static LLVMValueRef gen_primary_expr(CodeGen *g, AstNode *node) {
696 case PrimaryExprTypeUnreachable:679 case PrimaryExprTypeUnreachable:
697 add_debug_source_node(g, node);680 add_debug_source_node(g, node);
698 return LLVMBuildUnreachable(g->builder);681 return LLVMBuildUnreachable(g->builder);
699 case PrimaryExprTypeFnCall:
700 return gen_fn_call(g, prim_expr->data.fn_call);
701 case PrimaryExprTypeGroupedExpr:682 case PrimaryExprTypeGroupedExpr:
702 return gen_expr(g, prim_expr->data.grouped_expr);683 return gen_expr(g, prim_expr->data.grouped_expr);
703 case PrimaryExprTypeBlock:684 case PrimaryExprTypeBlock:
685 zig_panic("TODO block in expression");
704 break;686 break;
687 case PrimaryExprTypeSymbol:
688 zig_panic("TODO variable reference");
689 break;
690 }
691
692 zig_unreachable();
693}
694
695static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
696 assert(node->type == NodeTypeFnCallExpr);
697
698 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
699
700 FnTableEntry *fn_table_entry = g->fn_table.get(name);
701 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
702 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;
703 int actual_param_count = node->data.fn_call_expr.params.length;
704 assert(expected_param_count == actual_param_count);
705
706 LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count);
707 for (int i = 0; i < actual_param_count; i += 1) {
708 AstNode *expr_node = node->data.fn_call_expr.params.at(i);
709 param_values[i] = gen_expr(g, expr_node);
705 }710 }
706711
712 add_debug_source_node(g, node);
713 LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value,
714 param_values, actual_param_count, fn_table_entry->calling_convention, "");
715
716 if (type_is_unreachable(fn_table_entry->proto_node->data.fn_proto.return_type)) {
717 return LLVMBuildUnreachable(g->builder);
718 } else {
719 return result;
720 }
721}
722
723static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
724 assert(node->type == NodeTypePrefixOpExpr);
725 assert(node->data.prefix_op_expr.primary_expr);
726
727 LLVMValueRef expr = gen_expr(g, node->data.prefix_op_expr.primary_expr);
728
729 switch (node->data.prefix_op_expr.prefix_op) {
730 case PrefixOpNegation:
731 add_debug_source_node(g, node);
732 return LLVMBuildNeg(g->builder, expr, "");
733 case PrefixOpBoolNot:
734 {
735 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
736 add_debug_source_node(g, node);
737 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
738 }
739 case PrefixOpBinNot:
740 add_debug_source_node(g, node);
741 return LLVMBuildNot(g->builder, expr, "");
742 case PrefixOpInvalid:
743 zig_unreachable();
744 }
707 zig_unreachable();745 zig_unreachable();
708}746}
709747
710static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {748static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
711 assert(node->type == NodeTypeCastExpr);749 assert(node->type == NodeTypeCastExpr);
712750
713 LLVMValueRef expr = gen_primary_expr(g, node->data.cast_expr.primary_expr);751 LLVMValueRef expr = gen_expr(g, node->data.cast_expr.prefix_op_expr);
714752
715 if (!node->data.cast_expr.type)753 if (!node->data.cast_expr.type)
716 return expr;754 return expr;
...@@ -968,6 +1006,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -968,6 +1006,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
968 return gen_return_expr(g, node);1006 return gen_return_expr(g, node);
969 case NodeTypeCastExpr:1007 case NodeTypeCastExpr:
970 return gen_cast_expr(g, node);1008 return gen_cast_expr(g, node);
1009 case NodeTypePrefixOpExpr:
1010 return gen_prefix_op_expr(g, node);
1011 case NodeTypeFnCallExpr:
1012 return gen_fn_call_expr(g, node);
1013 case NodeTypePrimaryExpr:
1014 return gen_primary_expr(g, node);
971 case NodeTypeRoot:1015 case NodeTypeRoot:
972 case NodeTypeRootExportDecl:1016 case NodeTypeRootExportDecl:
973 case NodeTypeFnProto:1017 case NodeTypeFnProto:
...@@ -976,11 +1020,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -976,11 +1020,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
976 case NodeTypeParamDecl:1020 case NodeTypeParamDecl:
977 case NodeTypeType:1021 case NodeTypeType:
978 case NodeTypeBlock:1022 case NodeTypeBlock:
979 case NodeTypeFnCall:
980 case NodeTypeExternBlock:1023 case NodeTypeExternBlock:
981 case NodeTypeDirective:1024 case NodeTypeDirective:
982 case NodeTypePrimaryExpr:
983 return gen_primary_expr(g, node);
984 case NodeTypeGroupedExpr:1025 case NodeTypeGroupedExpr:
985 zig_unreachable();1026 zig_unreachable();
986 }1027 }
src/parser.cpp+103-49
...@@ -35,6 +35,16 @@ static const char *bin_op_str(BinOpType bin_op) {...@@ -35,6 +35,16 @@ static const char *bin_op_str(BinOpType bin_op) {
35 zig_unreachable();35 zig_unreachable();
36}36}
3737
38static const char *prefix_op_str(PrefixOp prefix_op) {
39 switch (prefix_op) {
40 case PrefixOpInvalid: return "(invalid)";
41 case PrefixOpNegation: return "-";
42 case PrefixOpBoolNot: return "!";
43 case PrefixOpBinNot: return "~";
44 }
45 zig_unreachable();
46}
47
38__attribute__ ((format (printf, 2, 3)))48__attribute__ ((format (printf, 2, 3)))
39__attribute__ ((noreturn))49__attribute__ ((noreturn))
40static void ast_error(Token *token, const char *format, ...) {50static void ast_error(Token *token, const char *format, ...) {
...@@ -70,8 +80,8 @@ const char *node_type_str(NodeType node_type) {...@@ -70,8 +80,8 @@ const char *node_type_str(NodeType node_type) {
70 return "Block";80 return "Block";
71 case NodeTypeBinOpExpr:81 case NodeTypeBinOpExpr:
72 return "BinOpExpr";82 return "BinOpExpr";
73 case NodeTypeFnCall:83 case NodeTypeFnCallExpr:
74 return "FnCall";84 return "FnCallExpr";
75 case NodeTypeExternBlock:85 case NodeTypeExternBlock:
76 return "ExternBlock";86 return "ExternBlock";
77 case NodeTypeDirective:87 case NodeTypeDirective:
...@@ -84,6 +94,8 @@ const char *node_type_str(NodeType node_type) {...@@ -84,6 +94,8 @@ const char *node_type_str(NodeType node_type) {
84 return "PrimaryExpr";94 return "PrimaryExpr";
85 case NodeTypeGroupedExpr:95 case NodeTypeGroupedExpr:
86 return "GroupedExpr";96 return "GroupedExpr";
97 case NodeTypePrefixOpExpr:
98 return "PrefixOpExpr";
87 }99 }
88 zig_unreachable();100 zig_unreachable();
89}101}
...@@ -188,10 +200,11 @@ void ast_print(AstNode *node, int indent) {...@@ -188,10 +200,11 @@ void ast_print(AstNode *node, int indent) {
188 ast_print(node->data.bin_op_expr.op1, indent + 2);200 ast_print(node->data.bin_op_expr.op1, indent + 2);
189 ast_print(node->data.bin_op_expr.op2, indent + 2);201 ast_print(node->data.bin_op_expr.op2, indent + 2);
190 break;202 break;
191 case NodeTypeFnCall:203 case NodeTypeFnCallExpr:
192 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.fn_call.name));204 fprintf(stderr, "%s\n", node_type_str(node->type));
193 for (int i = 0; i < node->data.fn_call.params.length; i += 1) {205 ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2);
194 AstNode *child = node->data.fn_call.params.at(i);206 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
207 AstNode *child = node->data.fn_call_expr.params.at(i);
195 ast_print(child, indent + 2);208 ast_print(child, indent + 2);
196 }209 }
197 break;210 break;
...@@ -200,10 +213,15 @@ void ast_print(AstNode *node, int indent) {...@@ -200,10 +213,15 @@ void ast_print(AstNode *node, int indent) {
200 break;213 break;
201 case NodeTypeCastExpr:214 case NodeTypeCastExpr:
202 fprintf(stderr, "%s\n", node_type_str(node->type));215 fprintf(stderr, "%s\n", node_type_str(node->type));
203 ast_print(node->data.cast_expr.primary_expr, indent + 2);216 ast_print(node->data.cast_expr.prefix_op_expr, indent + 2);
204 if (node->data.cast_expr.type)217 if (node->data.cast_expr.type)
205 ast_print(node->data.cast_expr.type, indent + 2);218 ast_print(node->data.cast_expr.type, indent + 2);
206 break;219 break;
220 case NodeTypePrefixOpExpr:
221 fprintf(stderr, "%s %s\n", node_type_str(node->type),
222 prefix_op_str(node->data.prefix_op_expr.prefix_op));
223 ast_print(node->data.prefix_op_expr.primary_expr, indent + 2);
224 break;
207 case NodeTypePrimaryExpr:225 case NodeTypePrimaryExpr:
208 switch (node->data.primary_expr.type) {226 switch (node->data.primary_expr.type) {
209 case PrimaryExprTypeNumber:227 case PrimaryExprTypeNumber:
...@@ -217,10 +235,6 @@ void ast_print(AstNode *node, int indent) {...@@ -217,10 +235,6 @@ void ast_print(AstNode *node, int indent) {
217 case PrimaryExprTypeUnreachable:235 case PrimaryExprTypeUnreachable:
218 fprintf(stderr, "PrimaryExpr Unreachable\n");236 fprintf(stderr, "PrimaryExpr Unreachable\n");
219 break;237 break;
220 case PrimaryExprTypeFnCall:
221 fprintf(stderr, "PrimaryExpr FnCall\n");
222 ast_print(node->data.primary_expr.data.fn_call, indent + 2);
223 break;
224 case PrimaryExprTypeGroupedExpr:238 case PrimaryExprTypeGroupedExpr:
225 fprintf(stderr, "PrimaryExpr GroupedExpr\n");239 fprintf(stderr, "PrimaryExpr GroupedExpr\n");
226 ast_print(node->data.primary_expr.data.grouped_expr, indent + 2);240 ast_print(node->data.primary_expr.data.grouped_expr, indent + 2);
...@@ -229,6 +243,10 @@ void ast_print(AstNode *node, int indent) {...@@ -229,6 +243,10 @@ void ast_print(AstNode *node, int indent) {
229 fprintf(stderr, "PrimaryExpr Block\n");243 fprintf(stderr, "PrimaryExpr Block\n");
230 ast_print(node->data.primary_expr.data.block, indent + 2);244 ast_print(node->data.primary_expr.data.block, indent + 2);
231 break;245 break;
246 case PrimaryExprTypeSymbol:
247 fprintf(stderr, "PrimaryExpr Symbol %s\n",
248 buf_ptr(&node->data.primary_expr.data.symbol));
249 break;
232 }250 }
233 break;251 break;
234 case NodeTypeGroupedExpr:252 case NodeTypeGroupedExpr:
...@@ -525,32 +543,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool...@@ -525,32 +543,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool
525}543}
526544
527/*545/*
528FnCall : token(Symbol) token(LParen) list(Expression, token(Comma)) token(RParen) ;546PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | Block | token(Symbol)
529*/
530static AstNode *ast_parse_fn_call(ParseContext *pc, int *token_index, bool mandatory) {
531 Token *fn_name = &pc->tokens->at(*token_index);
532 if (fn_name->id != TokenIdSymbol) {
533 if (mandatory) {
534 ast_invalid_token_error(pc, fn_name);
535 } else {
536 return nullptr;
537 }
538 }
539
540 *token_index += 1;
541
542 AstNode *node = ast_create_node(NodeTypeFnCall, fn_name);
543
544
545 ast_buf_from_token(pc, fn_name, &node->data.fn_call.name);
546
547 ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call.params);
548
549 return node;
550}
551
552/*
553PrimaryExpression : token(Number) | token(String) | token(Unreachable) | FnCall | GroupedExpression | Block
554*/547*/
555static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {548static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
556 Token *token = &pc->tokens->at(*token_index);549 Token *token = &pc->tokens->at(*token_index);
...@@ -572,6 +565,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -572,6 +565,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
572 node->data.primary_expr.type = PrimaryExprTypeUnreachable;565 node->data.primary_expr.type = PrimaryExprTypeUnreachable;
573 *token_index += 1;566 *token_index += 1;
574 return node;567 return node;
568 } else if (token->id == TokenIdSymbol) {
569 AstNode *node = ast_create_node(NodeTypePrimaryExpr, token);
570 node->data.primary_expr.type = PrimaryExprTypeSymbol;
571 ast_buf_from_token(pc, token, &node->data.primary_expr.data.symbol);
572 *token_index += 1;
573 return node;
575 }574 }
576575
577 AstNode *block_node = ast_parse_block(pc, token_index, false);576 AstNode *block_node = ast_parse_block(pc, token_index, false);
...@@ -590,14 +589,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -590,14 +589,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
590 return node;589 return node;
591 }590 }
592591
593 AstNode *fn_call_node = ast_parse_fn_call(pc, token_index, false);
594 if (fn_call_node) {
595 AstNode *node = ast_create_node(NodeTypePrimaryExpr, token);
596 node->data.primary_expr.type = PrimaryExprTypeFnCall;
597 node->data.primary_expr.data.fn_call = fn_call_node;
598 return node;
599 }
600
601 if (!mandatory)592 if (!mandatory)
602 return nullptr;593 return nullptr;
603594
...@@ -605,20 +596,83 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -605,20 +596,83 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
605}596}
606597
607/*598/*
608CastExpression : PrimaryExpression token(As) Type | PrimaryExpression599FnCallExpression : PrimaryExpression token(LParen) list(Expression, token(Comma)) token(RParen) | PrimaryExpression
609*/600*/
610static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {601static AstNode *ast_parse_fn_call_expr(ParseContext *pc, int *token_index, bool mandatory) {
611 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);602 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
612 if (!primary_expr)603 if (!primary_expr)
613 return nullptr;604 return nullptr;
614605
606 Token *l_paren = &pc->tokens->at(*token_index);
607 if (l_paren->id != TokenIdLParen)
608 return primary_expr;
609
610 AstNode *node = ast_create_node_with_node(NodeTypeFnCallExpr, primary_expr);
611 node->data.fn_call_expr.fn_ref_expr = primary_expr;
612 ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call_expr.params);
613
614 return node;
615}
616
617static PrefixOp tok_to_prefix_op(Token *token) {
618 switch (token->id) {
619 case TokenIdBang: return PrefixOpBoolNot;
620 case TokenIdDash: return PrefixOpNegation;
621 case TokenIdTilde: return PrefixOpBinNot;
622 default: return PrefixOpInvalid;
623 }
624}
625
626/*
627PrefixOp : token(Not) | token(Dash) | token(Tilde)
628*/
629static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {
630 Token *token = &pc->tokens->at(*token_index);
631 PrefixOp result = tok_to_prefix_op(token);
632 if (result == PrefixOpInvalid) {
633 if (mandatory) {
634 ast_invalid_token_error(pc, token);
635 } else {
636 return PrefixOpInvalid;
637 }
638 }
639 *token_index += 1;
640 return result;
641}
642
643/*
644PrefixOpExpression : PrefixOp FnCallExpression | FnCallExpression
645*/
646static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
647 Token *token = &pc->tokens->at(*token_index);
648 PrefixOp prefix_op = ast_parse_prefix_op(pc, token_index, false);
649 if (prefix_op == PrefixOpInvalid)
650 return ast_parse_fn_call_expr(pc, token_index, mandatory);
651
652 AstNode *primary_expr = ast_parse_fn_call_expr(pc, token_index, true);
653 AstNode *node = ast_create_node(NodeTypePrefixOpExpr, token);
654 node->data.prefix_op_expr.primary_expr = primary_expr;
655 node->data.prefix_op_expr.prefix_op = prefix_op;
656
657 return node;
658}
659
660
661/*
662CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression
663*/
664static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {
665 AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory);
666 if (!prefix_op_expr)
667 return nullptr;
668
615 Token *as_kw = &pc->tokens->at(*token_index);669 Token *as_kw = &pc->tokens->at(*token_index);
616 if (as_kw->id != TokenIdKeywordAs)670 if (as_kw->id != TokenIdKeywordAs)
617 return primary_expr;671 return prefix_op_expr;
618 *token_index += 1;672 *token_index += 1;
619673
620 AstNode *node = ast_create_node(NodeTypeCastExpr, as_kw);674 AstNode *node = ast_create_node(NodeTypeCastExpr, as_kw);
621 node->data.cast_expr.primary_expr = primary_expr;675 node->data.cast_expr.prefix_op_expr = prefix_op_expr;
622676
623 node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index);677 node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index);
624678
src/parser.hpp+21-7
...@@ -24,7 +24,6 @@ enum NodeType {...@@ -24,7 +24,6 @@ enum NodeType {
24 NodeTypeParamDecl,24 NodeTypeParamDecl,
25 NodeTypeType,25 NodeTypeType,
26 NodeTypeBlock,26 NodeTypeBlock,
27 NodeTypeFnCall,
28 NodeTypeExternBlock,27 NodeTypeExternBlock,
29 NodeTypeDirective,28 NodeTypeDirective,
30 NodeTypeReturnExpr,29 NodeTypeReturnExpr,
...@@ -32,6 +31,8 @@ enum NodeType {...@@ -32,6 +31,8 @@ enum NodeType {
32 NodeTypeCastExpr,31 NodeTypeCastExpr,
33 NodeTypePrimaryExpr,32 NodeTypePrimaryExpr,
34 NodeTypeGroupedExpr,33 NodeTypeGroupedExpr,
34 NodeTypePrefixOpExpr,
35 NodeTypeFnCallExpr,
35};36};
3637
37struct AstNodeRoot {38struct AstNodeRoot {
...@@ -117,8 +118,8 @@ struct AstNodeBinOpExpr {...@@ -117,8 +118,8 @@ struct AstNodeBinOpExpr {
117 AstNode *op2;118 AstNode *op2;
118};119};
119120
120struct AstNodeFnCall {121struct AstNodeFnCallExpr {
121 Buf name;122 AstNode *fn_ref_expr;
122 ZigList<AstNode *> params;123 ZigList<AstNode *> params;
123};124};
124125
...@@ -138,7 +139,7 @@ struct AstNodeRootExportDecl {...@@ -138,7 +139,7 @@ struct AstNodeRootExportDecl {
138};139};
139140
140struct AstNodeCastExpr {141struct AstNodeCastExpr {
141 AstNode *primary_expr;142 AstNode *prefix_op_expr;
142 // if type is non-null, do cast, otherwise nothing143 // if type is non-null, do cast, otherwise nothing
143 AstNode *type;144 AstNode *type;
144};145};
...@@ -147,9 +148,9 @@ enum PrimaryExprType {...@@ -147,9 +148,9 @@ enum PrimaryExprType {
147 PrimaryExprTypeNumber,148 PrimaryExprTypeNumber,
148 PrimaryExprTypeString,149 PrimaryExprTypeString,
149 PrimaryExprTypeUnreachable,150 PrimaryExprTypeUnreachable,
150 PrimaryExprTypeFnCall,
151 PrimaryExprTypeGroupedExpr,151 PrimaryExprTypeGroupedExpr,
152 PrimaryExprTypeBlock,152 PrimaryExprTypeBlock,
153 PrimaryExprTypeSymbol,
153};154};
154155
155struct AstNodePrimaryExpr {156struct AstNodePrimaryExpr {
...@@ -157,7 +158,7 @@ struct AstNodePrimaryExpr {...@@ -157,7 +158,7 @@ struct AstNodePrimaryExpr {
157 union {158 union {
158 Buf number;159 Buf number;
159 Buf string;160 Buf string;
160 AstNode *fn_call;161 Buf symbol;
161 AstNode *grouped_expr;162 AstNode *grouped_expr;
162 AstNode *block;163 AstNode *block;
163 } data;164 } data;
...@@ -167,6 +168,18 @@ struct AstNodeGroupedExpr {...@@ -167,6 +168,18 @@ struct AstNodeGroupedExpr {
167 AstNode *expr;168 AstNode *expr;
168};169};
169170
171enum PrefixOp {
172 PrefixOpInvalid,
173 PrefixOpBoolNot,
174 PrefixOpBinNot,
175 PrefixOpNegation,
176};
177
178struct AstNodePrefixOpExpr {
179 PrefixOp prefix_op;
180 AstNode *primary_expr;
181};
182
170struct AstNode {183struct AstNode {
171 enum NodeType type;184 enum NodeType type;
172 AstNode *parent;185 AstNode *parent;
...@@ -184,12 +197,13 @@ struct AstNode {...@@ -184,12 +197,13 @@ struct AstNode {
184 AstNodeBlock block;197 AstNodeBlock block;
185 AstNodeReturnExpr return_expr;198 AstNodeReturnExpr return_expr;
186 AstNodeBinOpExpr bin_op_expr;199 AstNodeBinOpExpr bin_op_expr;
187 AstNodeFnCall fn_call;
188 AstNodeExternBlock extern_block;200 AstNodeExternBlock extern_block;
189 AstNodeDirective directive;201 AstNodeDirective directive;
190 AstNodeCastExpr cast_expr;202 AstNodeCastExpr cast_expr;
191 AstNodePrimaryExpr primary_expr;203 AstNodePrimaryExpr primary_expr;
192 AstNodeGroupedExpr grouped_expr;204 AstNodeGroupedExpr grouped_expr;
205 AstNodePrefixOpExpr prefix_op_expr;
206 AstNodeFnCallExpr fn_call_expr;
193 } data;207 } data;
194};208};
195209
src/tokenizer.cpp+7-2
...@@ -249,6 +249,10 @@ ZigList<Token> *tokenize(Buf *buf) {...@@ -249,6 +249,10 @@ ZigList<Token> *tokenize(Buf *buf) {
249 begin_token(&t, TokenIdPlus);249 begin_token(&t, TokenIdPlus);
250 end_token(&t);250 end_token(&t);
251 break;251 break;
252 case '~':
253 begin_token(&t, TokenIdTilde);
254 end_token(&t);
255 break;
252 case '-':256 case '-':
253 begin_token(&t, TokenIdDash);257 begin_token(&t, TokenIdDash);
254 t.state = TokenizeStateSawDash;258 t.state = TokenizeStateSawDash;
...@@ -278,7 +282,7 @@ ZigList<Token> *tokenize(Buf *buf) {...@@ -278,7 +282,7 @@ ZigList<Token> *tokenize(Buf *buf) {
278 t.state = TokenizeStateEq;282 t.state = TokenizeStateEq;
279 break;283 break;
280 case '!':284 case '!':
281 begin_token(&t, TokenIdNot);285 begin_token(&t, TokenIdBang);
282 t.state = TokenizeStateBang;286 t.state = TokenizeStateBang;
283 break;287 break;
284 case '<':288 case '<':
...@@ -578,7 +582,8 @@ static const char * token_name(Token *token) {...@@ -578,7 +582,8 @@ static const char * token_name(Token *token) {
578 case TokenIdBoolOr: return "BoolOr";582 case TokenIdBoolOr: return "BoolOr";
579 case TokenIdBoolAnd: return "BoolAnd";583 case TokenIdBoolAnd: return "BoolAnd";
580 case TokenIdEq: return "Eq";584 case TokenIdEq: return "Eq";
581 case TokenIdNot: return "Not";585 case TokenIdBang: return "Bang";
586 case TokenIdTilde: return "Tilde";
582 case TokenIdCmpEq: return "CmpEq";587 case TokenIdCmpEq: return "CmpEq";
583 case TokenIdCmpNotEq: return "CmpNotEq";588 case TokenIdCmpNotEq: return "CmpNotEq";
584 case TokenIdCmpLessThan: return "CmpLessThan";589 case TokenIdCmpLessThan: return "CmpLessThan";
src/tokenizer.hpp+2-1
...@@ -43,7 +43,8 @@ enum TokenId {...@@ -43,7 +43,8 @@ enum TokenId {
43 TokenIdBinXor,43 TokenIdBinXor,
44 TokenIdEq,44 TokenIdEq,
45 TokenIdCmpEq,45 TokenIdCmpEq,
46 TokenIdNot,46 TokenIdBang,
47 TokenIdTilde,
47 TokenIdCmpNotEq,48 TokenIdCmpNotEq,
48 TokenIdCmpLessThan,49 TokenIdCmpLessThan,
49 TokenIdCmpGreaterThan,50 TokenIdCmpGreaterThan,