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,
714714 }
715715}
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
717761static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
718762 TypeTableEntry *expected_type, AstNode *node)
719763{
......@@ -842,6 +886,18 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
842886 {
843887 switch (node->data.bin_op_expr.bin_op) {
844888 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:
845901 {
846902 AstNode *lhs_node = node->data.bin_op_expr.op1;
847903 TypeTableEntry *expected_rhs_type = nullptr;
......@@ -853,7 +909,12 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
853909 add_node_error(g, lhs_node,
854910 buf_sprintf("cannot assign to constant variable"));
855911 } 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 }
857918 }
858919 } else {
859920 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) {
409409 case BinOpTypeCmpGreaterOrEq:
410410 case BinOpTypeInvalid:
411411 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:
412424 zig_unreachable();
413425 }
414426 zig_unreachable();
......@@ -543,6 +555,11 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
543555
544556 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
546563 if (lhs_node->type == NodeTypeSymbol) {
547564 LocalVariableTableEntry *var = find_local_variable(node->codegen_node->expr_node.block_context,
548565 &lhs_node->data.symbol);
......@@ -577,15 +594,26 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
577594 } else {
578595 zig_panic("bad assign target");
579596 }
580
581597}
582598
583599static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
584600 switch (node->data.bin_op_expr.bin_op) {
585 case BinOpTypeAssign:
586 return gen_assign_expr(g, node);
587601 case BinOpTypeInvalid:
588602 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);
589617 case BinOpTypeBoolOr:
590618 return gen_bool_or_expr(g, node);
591619 case BinOpTypeBoolAnd:
src/parser.cpp+74-26
......@@ -14,26 +14,38 @@
1414
1515static const char *bin_op_str(BinOpType bin_op) {
1616 switch (bin_op) {
17 case BinOpTypeInvalid: return "(invalid)";
18 case BinOpTypeBoolOr: return "||";
19 case BinOpTypeBoolAnd: return "&&";
20 case BinOpTypeCmpEq: return "==";
21 case BinOpTypeCmpNotEq: return "!=";
22 case BinOpTypeCmpLessThan: return "<";
23 case BinOpTypeCmpGreaterThan: return ">";
24 case BinOpTypeCmpLessOrEq: return "<=";
25 case BinOpTypeCmpGreaterOrEq: return ">=";
26 case BinOpTypeBinOr: return "|";
27 case BinOpTypeBinXor: return "^";
28 case BinOpTypeBinAnd: return "&";
29 case BinOpTypeBitShiftLeft: return "<<";
30 case BinOpTypeBitShiftRight: return ">>";
31 case BinOpTypeAdd: return "+";
32 case BinOpTypeSub: return "-";
33 case BinOpTypeMult: return "*";
34 case BinOpTypeDiv: return "/";
35 case BinOpTypeMod: return "%";
36 case BinOpTypeAssign: return "=";
17 case BinOpTypeInvalid: return "(invalid)";
18 case BinOpTypeBoolOr: return "||";
19 case BinOpTypeBoolAnd: return "&&";
20 case BinOpTypeCmpEq: return "==";
21 case BinOpTypeCmpNotEq: return "!=";
22 case BinOpTypeCmpLessThan: return "<";
23 case BinOpTypeCmpGreaterThan: return ">";
24 case BinOpTypeCmpLessOrEq: return "<=";
25 case BinOpTypeCmpGreaterOrEq: return ">=";
26 case BinOpTypeBinOr: return "|";
27 case BinOpTypeBinXor: return "^";
28 case BinOpTypeBinAnd: return "&";
29 case BinOpTypeBitShiftLeft: return "<<";
30 case BinOpTypeBitShiftRight: return ">>";
31 case BinOpTypeAdd: return "+";
32 case BinOpTypeSub: return "-";
33 case BinOpTypeMult: return "*";
34 case BinOpTypeDiv: return "/";
35 case BinOpTypeMod: 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 "||=";
3749 }
3850 zig_unreachable();
3951}
......@@ -103,7 +115,7 @@ const char *node_type_str(NodeType node_type) {
103115 case NodeTypeLabel:
104116 return "Label";
105117 case NodeTypeGoto:
106 return "Label";
118 return "Goto";
107119 case NodeTypeAsmExpr:
108120 return "AsmExpr";
109121 case NodeTypeFieldAccessExpr:
......@@ -1448,24 +1460,60 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
14481460 return nullptr;
14491461}
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
14511482/*
1452AssignmentExpression : BoolOrExpression token(Equal) BoolOrExpression | BoolOrExpression
1483AssignmentOperator : 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
14531501*/
14541502static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mandatory) {
14551503 AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);
14561504 if (!lhs)
1457 return lhs;
1505 return nullptr;
14581506
14591507 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)
14611510 return lhs;
1462 *token_index += 1;
14631511
14641512 AstNode *rhs = ast_parse_bool_or_expr(pc, token_index, true);
14651513
14661514 AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token);
14671515 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;
14691517 node->data.bin_op_expr.op2 = rhs;
14701518
14711519 return node;
src/parser.hpp+12
......@@ -119,6 +119,18 @@ struct AstNodeVariableDeclaration {
119119enum BinOpType {
120120 BinOpTypeInvalid,
121121 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,
122134 BinOpTypeBoolOr,
123135 BinOpTypeBoolAnd,
124136 BinOpTypeCmpEq,