authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-12 19:07:29-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-12 19:07:29-07:00
log5cb5f5dbf625f5995a2e34b96985dca181222cea
treef8214648a6ce5e59e09f55e85786cd403f637be0
parenteb1542c1027481546d0efdf6a5faac2593b9e8e8

parsing assignment operators


4 files changed, 179 insertions(+), 30 deletions(-)

src/analyze.cpp+62-1
...@@ -714,6 +714,50 @@ static TypeTableEntry *analyze_variable_name(CodeGen *g, BlockContext *context,...@@ -714,6 +714,50 @@ static TypeTableEntry *analyze_variable_name(CodeGen *g, BlockContext *context,
714 }714 }
715}715}
716716
717static bool is_op_allowed(TypeTableEntry *type, BinOpType op) {
718 switch (op) {
719 case BinOpTypeAssign:
720 return true;
721 case BinOpTypeAssignTimes:
722 case BinOpTypeAssignDiv:
723 case BinOpTypeAssignMod:
724 case BinOpTypeAssignPlus:
725 case BinOpTypeAssignMinus:
726 return type->id == TypeTableEntryIdInt || type->id == TypeTableEntryIdFloat;
727 case BinOpTypeAssignBitShiftLeft:
728 case BinOpTypeAssignBitShiftRight:
729 case BinOpTypeAssignBitAnd:
730 case BinOpTypeAssignBitXor:
731 case BinOpTypeAssignBitOr:
732 return type->id == TypeTableEntryIdInt;
733 case BinOpTypeAssignBoolAnd:
734 case BinOpTypeAssignBoolOr:
735 return type->id == TypeTableEntryIdBool;
736
737 case BinOpTypeInvalid:
738 case BinOpTypeBoolOr:
739 case BinOpTypeBoolAnd:
740 case BinOpTypeCmpEq:
741 case BinOpTypeCmpNotEq:
742 case BinOpTypeCmpLessThan:
743 case BinOpTypeCmpGreaterThan:
744 case BinOpTypeCmpLessOrEq:
745 case BinOpTypeCmpGreaterOrEq:
746 case BinOpTypeBinOr:
747 case BinOpTypeBinXor:
748 case BinOpTypeBinAnd:
749 case BinOpTypeBitShiftLeft:
750 case BinOpTypeBitShiftRight:
751 case BinOpTypeAdd:
752 case BinOpTypeSub:
753 case BinOpTypeMult:
754 case BinOpTypeDiv:
755 case BinOpTypeMod:
756 zig_unreachable();
757 }
758 zig_unreachable();
759}
760
717static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,761static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
718 TypeTableEntry *expected_type, AstNode *node)762 TypeTableEntry *expected_type, AstNode *node)
719{763{
...@@ -842,6 +886,18 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -842,6 +886,18 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
842 {886 {
843 switch (node->data.bin_op_expr.bin_op) {887 switch (node->data.bin_op_expr.bin_op) {
844 case BinOpTypeAssign:888 case BinOpTypeAssign:
889 case BinOpTypeAssignTimes:
890 case BinOpTypeAssignDiv:
891 case BinOpTypeAssignMod:
892 case BinOpTypeAssignPlus:
893 case BinOpTypeAssignMinus:
894 case BinOpTypeAssignBitShiftLeft:
895 case BinOpTypeAssignBitShiftRight:
896 case BinOpTypeAssignBitAnd:
897 case BinOpTypeAssignBitXor:
898 case BinOpTypeAssignBitOr:
899 case BinOpTypeAssignBoolAnd:
900 case BinOpTypeAssignBoolOr:
845 {901 {
846 AstNode *lhs_node = node->data.bin_op_expr.op1;902 AstNode *lhs_node = node->data.bin_op_expr.op1;
847 TypeTableEntry *expected_rhs_type = nullptr;903 TypeTableEntry *expected_rhs_type = nullptr;
...@@ -853,7 +909,12 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -853,7 +909,12 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
853 add_node_error(g, lhs_node,909 add_node_error(g, lhs_node,
854 buf_sprintf("cannot assign to constant variable"));910 buf_sprintf("cannot assign to constant variable"));
855 } else {911 } else {
856 expected_rhs_type = var->type;912 if (!is_op_allowed(var->type, node->data.bin_op_expr.bin_op)) {
913 add_node_error(g, lhs_node,
914 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&var->type->name)));
915 } else {
916 expected_rhs_type = var->type;
917 }
857 }918 }
858 } else {919 } else {
859 add_node_error(g, lhs_node,920 add_node_error(g, lhs_node,
src/codegen.cpp+31-3
...@@ -409,6 +409,18 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {...@@ -409,6 +409,18 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {
409 case BinOpTypeCmpGreaterOrEq:409 case BinOpTypeCmpGreaterOrEq:
410 case BinOpTypeInvalid:410 case BinOpTypeInvalid:
411 case BinOpTypeAssign:411 case BinOpTypeAssign:
412 case BinOpTypeAssignTimes:
413 case BinOpTypeAssignDiv:
414 case BinOpTypeAssignMod:
415 case BinOpTypeAssignPlus:
416 case BinOpTypeAssignMinus:
417 case BinOpTypeAssignBitShiftLeft:
418 case BinOpTypeAssignBitShiftRight:
419 case BinOpTypeAssignBitAnd:
420 case BinOpTypeAssignBitXor:
421 case BinOpTypeAssignBitOr:
422 case BinOpTypeAssignBoolAnd:
423 case BinOpTypeAssignBoolOr:
412 zig_unreachable();424 zig_unreachable();
413 }425 }
414 zig_unreachable();426 zig_unreachable();
...@@ -543,6 +555,11 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {...@@ -543,6 +555,11 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
543555
544 AstNode *lhs_node = node->data.bin_op_expr.op1;556 AstNode *lhs_node = node->data.bin_op_expr.op1;
545557
558 bool is_read_first = node->data.bin_op_expr.bin_op != BinOpTypeAssign;
559 if (is_read_first) {
560 zig_panic("TODO: implement modify assignment ops");
561 }
562
546 if (lhs_node->type == NodeTypeSymbol) {563 if (lhs_node->type == NodeTypeSymbol) {
547 LocalVariableTableEntry *var = find_local_variable(node->codegen_node->expr_node.block_context,564 LocalVariableTableEntry *var = find_local_variable(node->codegen_node->expr_node.block_context,
548 &lhs_node->data.symbol);565 &lhs_node->data.symbol);
...@@ -577,15 +594,26 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {...@@ -577,15 +594,26 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
577 } else {594 } else {
578 zig_panic("bad assign target");595 zig_panic("bad assign target");
579 }596 }
580
581}597}
582598
583static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {599static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
584 switch (node->data.bin_op_expr.bin_op) {600 switch (node->data.bin_op_expr.bin_op) {
585 case BinOpTypeAssign:
586 return gen_assign_expr(g, node);
587 case BinOpTypeInvalid:601 case BinOpTypeInvalid:
588 zig_unreachable();602 zig_unreachable();
603 case BinOpTypeAssign:
604 case BinOpTypeAssignTimes:
605 case BinOpTypeAssignDiv:
606 case BinOpTypeAssignMod:
607 case BinOpTypeAssignPlus:
608 case BinOpTypeAssignMinus:
609 case BinOpTypeAssignBitShiftLeft:
610 case BinOpTypeAssignBitShiftRight:
611 case BinOpTypeAssignBitAnd:
612 case BinOpTypeAssignBitXor:
613 case BinOpTypeAssignBitOr:
614 case BinOpTypeAssignBoolAnd:
615 case BinOpTypeAssignBoolOr:
616 return gen_assign_expr(g, node);
589 case BinOpTypeBoolOr:617 case BinOpTypeBoolOr:
590 return gen_bool_or_expr(g, node);618 return gen_bool_or_expr(g, node);
591 case BinOpTypeBoolAnd:619 case BinOpTypeBoolAnd:
src/parser.cpp+74-26
...@@ -14,26 +14,38 @@...@@ -14,26 +14,38 @@
1414
15static const char *bin_op_str(BinOpType bin_op) {15static const char *bin_op_str(BinOpType bin_op) {
16 switch (bin_op) {16 switch (bin_op) {
17 case BinOpTypeInvalid: return "(invalid)";17 case BinOpTypeInvalid: return "(invalid)";
18 case BinOpTypeBoolOr: return "||";18 case BinOpTypeBoolOr: return "||";
19 case BinOpTypeBoolAnd: return "&&";19 case BinOpTypeBoolAnd: return "&&";
20 case BinOpTypeCmpEq: return "==";20 case BinOpTypeCmpEq: return "==";
21 case BinOpTypeCmpNotEq: return "!=";21 case BinOpTypeCmpNotEq: return "!=";
22 case BinOpTypeCmpLessThan: return "<";22 case BinOpTypeCmpLessThan: return "<";
23 case BinOpTypeCmpGreaterThan: return ">";23 case BinOpTypeCmpGreaterThan: return ">";
24 case BinOpTypeCmpLessOrEq: return "<=";24 case BinOpTypeCmpLessOrEq: return "<=";
25 case BinOpTypeCmpGreaterOrEq: return ">=";25 case BinOpTypeCmpGreaterOrEq: return ">=";
26 case BinOpTypeBinOr: return "|";26 case BinOpTypeBinOr: return "|";
27 case BinOpTypeBinXor: return "^";27 case BinOpTypeBinXor: return "^";
28 case BinOpTypeBinAnd: return "&";28 case BinOpTypeBinAnd: return "&";
29 case BinOpTypeBitShiftLeft: return "<<";29 case BinOpTypeBitShiftLeft: return "<<";
30 case BinOpTypeBitShiftRight: return ">>";30 case BinOpTypeBitShiftRight: return ">>";
31 case BinOpTypeAdd: return "+";31 case BinOpTypeAdd: return "+";
32 case BinOpTypeSub: return "-";32 case BinOpTypeSub: return "-";
33 case BinOpTypeMult: return "*";33 case BinOpTypeMult: return "*";
34 case BinOpTypeDiv: return "/";34 case BinOpTypeDiv: return "/";
35 case BinOpTypeMod: return "%";35 case BinOpTypeMod: return "%";
36 case BinOpTypeAssign: return "=";36 case BinOpTypeAssign: return "=";
37 case BinOpTypeAssignTimes: return "*=";
38 case BinOpTypeAssignDiv: return "/=";
39 case BinOpTypeAssignMod: return "%=";
40 case BinOpTypeAssignPlus: return "+=";
41 case BinOpTypeAssignMinus: return "-=";
42 case BinOpTypeAssignBitShiftLeft: return "<<=";
43 case BinOpTypeAssignBitShiftRight: return ">>=";
44 case BinOpTypeAssignBitAnd: return "&=";
45 case BinOpTypeAssignBitXor: return "^=";
46 case BinOpTypeAssignBitOr: return "|=";
47 case BinOpTypeAssignBoolAnd: return "&&=";
48 case BinOpTypeAssignBoolOr: return "||=";
37 }49 }
38 zig_unreachable();50 zig_unreachable();
39}51}
...@@ -103,7 +115,7 @@ const char *node_type_str(NodeType node_type) {...@@ -103,7 +115,7 @@ const char *node_type_str(NodeType node_type) {
103 case NodeTypeLabel:115 case NodeTypeLabel:
104 return "Label";116 return "Label";
105 case NodeTypeGoto:117 case NodeTypeGoto:
106 return "Label";118 return "Goto";
107 case NodeTypeAsmExpr:119 case NodeTypeAsmExpr:
108 return "AsmExpr";120 return "AsmExpr";
109 case NodeTypeFieldAccessExpr:121 case NodeTypeFieldAccessExpr:
...@@ -1448,24 +1460,60 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma...@@ -1448,24 +1460,60 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
1448 return nullptr;1460 return nullptr;
1449}1461}
14501462
1463static BinOpType tok_to_ass_op(Token *token) {
1464 switch (token->id) {
1465 case TokenIdEq: return BinOpTypeAssign;
1466 case TokenIdTimesEq: return BinOpTypeAssignTimes;
1467 case TokenIdDivEq: return BinOpTypeAssignDiv;
1468 case TokenIdModEq: return BinOpTypeAssignMod;
1469 case TokenIdPlusEq: return BinOpTypeAssignPlus;
1470 case TokenIdMinusEq: return BinOpTypeAssignMinus;
1471 case TokenIdBitShiftLeftEq: return BinOpTypeAssignBitShiftLeft;
1472 case TokenIdBitShiftRightEq: return BinOpTypeAssignBitShiftRight;
1473 case TokenIdBitAndEq: return BinOpTypeAssignBitAnd;
1474 case TokenIdBitXorEq: return BinOpTypeAssignBitXor;
1475 case TokenIdBitOrEq: return BinOpTypeAssignBitOr;
1476 case TokenIdBoolAndEq: return BinOpTypeAssignBoolAnd;
1477 case TokenIdBoolOrEq: return BinOpTypeAssignBoolOr;
1478 default: return BinOpTypeInvalid;
1479 }
1480}
1481
1451/*1482/*
1452AssignmentExpression : BoolOrExpression token(Equal) BoolOrExpression | BoolOrExpression1483AssignmentOperator : token(Eq) | token(TimesEq) | token(DivEq) | token(ModEq) | token(PlusEq) | token(MinusEq) | token(BitShiftLeftEq) | token(BitShiftRightEq) | token(BitAndEq) | token(BitXorEq) | token(BitOrEq) | token(BoolAndEq) | token(BoolOrEq)
1484*/
1485static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool mandatory) {
1486 Token *token = &pc->tokens->at(*token_index);
1487 BinOpType result = tok_to_ass_op(token);
1488 if (result == BinOpTypeInvalid) {
1489 if (mandatory) {
1490 ast_invalid_token_error(pc, token);
1491 } else {
1492 return BinOpTypeInvalid;
1493 }
1494 }
1495 *token_index += 1;
1496 return result;
1497}
1498
1499/*
1500AssignmentExpression : BoolOrExpression AssignmentOperator BoolOrExpression | BoolOrExpression
1453*/1501*/
1454static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mandatory) {1502static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mandatory) {
1455 AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);1503 AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);
1456 if (!lhs)1504 if (!lhs)
1457 return lhs;1505 return nullptr;
14581506
1459 Token *token = &pc->tokens->at(*token_index);1507 Token *token = &pc->tokens->at(*token_index);
1460 if (token->id != TokenIdEq)1508 BinOpType ass_op = ast_parse_ass_op(pc, token_index, false);
1509 if (ass_op == BinOpTypeInvalid)
1461 return lhs;1510 return lhs;
1462 *token_index += 1;
14631511
1464 AstNode *rhs = ast_parse_bool_or_expr(pc, token_index, true);1512 AstNode *rhs = ast_parse_bool_or_expr(pc, token_index, true);
14651513
1466 AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);1514 AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
1467 node->data.bin_op_expr.op1 = lhs;1515 node->data.bin_op_expr.op1 = lhs;
1468 node->data.bin_op_expr.bin_op = BinOpTypeAssign;1516 node->data.bin_op_expr.bin_op = ass_op;
1469 node->data.bin_op_expr.op2 = rhs;1517 node->data.bin_op_expr.op2 = rhs;
14701518
1471 return node;1519 return node;
src/parser.hpp+12
...@@ -119,6 +119,18 @@ struct AstNodeVariableDeclaration {...@@ -119,6 +119,18 @@ struct AstNodeVariableDeclaration {
119enum BinOpType {119enum BinOpType {
120 BinOpTypeInvalid,120 BinOpTypeInvalid,
121 BinOpTypeAssign,121 BinOpTypeAssign,
122 BinOpTypeAssignTimes,
123 BinOpTypeAssignDiv,
124 BinOpTypeAssignMod,
125 BinOpTypeAssignPlus,
126 BinOpTypeAssignMinus,
127 BinOpTypeAssignBitShiftLeft,
128 BinOpTypeAssignBitShiftRight,
129 BinOpTypeAssignBitAnd,
130 BinOpTypeAssignBitXor,
131 BinOpTypeAssignBitOr,
132 BinOpTypeAssignBoolAnd,
133 BinOpTypeAssignBoolOr,
122 BinOpTypeBoolOr,134 BinOpTypeBoolOr,
123 BinOpTypeBoolAnd,135 BinOpTypeBoolAnd,
124 BinOpTypeCmpEq,136 BinOpTypeCmpEq,