diff --git a/doc/langref.md b/doc/langref.md index 37ce3cee52..439ef6a500 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -92,7 +92,7 @@ AssignmentExpression : BoolOrExpression token(Equal) BoolOrExpression | BoolOrEx BlockExpression : IfExpression | Block -BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndExpression +BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression ReturnExpression : token(Return) option(Expression) @@ -102,33 +102,33 @@ ElseIf : token(Else) IfExpression Else : token(Else) Block -BoolAndExpression : ComparisonExpression token(BoolAnd) ComparisonExpression | ComparisonExpression +BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression ComparisonExpression : BinaryOrExpression ComparisonOperator BinaryOrExpression | BinaryOrExpression ComparisonOperator : token(BoolEq) | token(BoolNotEq) | token(BoolLessThan) | token(BoolGreaterThan) | token(BoolLessEqual) | token(BoolGreaterEqual) -BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryXorExpression | BinaryXorExpression +BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryOrExpression | BinaryXorExpression -BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryAndExpression | BinaryAndExpression +BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryXorExpression | BinaryAndExpression -BinaryAndExpression : BitShiftExpression token(BinAnd) BitShiftExpression | BitShiftExpression +BinaryAndExpression : BitShiftExpression token(BinAnd) BinaryAndExpression | BitShiftExpression -BitShiftExpression : AdditionExpression BitShiftOperator AdditionExpression | AdditionExpression +BitShiftExpression : AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression -BitShiftOperator : token(BitShiftLeft | token(BitShiftRight) +BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight) -AdditionExpression : MultiplyExpression AdditionOperator MultiplyExpression | MultiplyExpression +AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression AdditionOperator : token(Plus) | token(Minus) -MultiplyExpression : CastExpression MultiplyOperator CastExpression | CastExpression +MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression MultiplyOperator : token(Star) | token(Slash) | token(Percent) -CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression +CastExpression : CastExpression token(as) Type | PrefixOpExpression -PrefixOpExpression : PrefixOp SuffixOpExpression | SuffixOpExpression +PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression) diff --git a/src/analyze.cpp b/src/analyze.cpp index 89e5e109b8..b7a4bd388f 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -894,20 +894,24 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, return_type = g->builtin_types.entry_bool; break; case BinOpTypeBinOr: - zig_panic("TODO bin or type"); - break; case BinOpTypeBinXor: - zig_panic("TODO bin xor type"); - break; case BinOpTypeBinAnd: - zig_panic("TODO bin and type"); - break; + { + // TODO: don't require i32 + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1); + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2); + return_type = g->builtin_types.entry_i32; + break; + } case BinOpTypeBitShiftLeft: - zig_panic("TODO bit shift left type"); - break; case BinOpTypeBitShiftRight: - zig_panic("TODO bit shift right type"); - break; + { + // TODO: don't require i32 + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1); + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2); + return_type = g->builtin_types.entry_i32; + break; + } case BinOpTypeAdd: case BinOpTypeSub: // TODO think how should type checking for these work? @@ -918,14 +922,15 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, return_type = g->builtin_types.entry_i32; break; case BinOpTypeMult: - zig_panic("TODO mult type"); - break; case BinOpTypeDiv: - zig_panic("TODO div type"); - break; case BinOpTypeMod: - zig_panic("TODO modulus type"); - break; + { + // TODO: don't require i32 + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op1); + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.bin_op_expr.op2); + return_type = g->builtin_types.entry_i32; + break; + } case BinOpTypeInvalid: zig_unreachable(); } @@ -1081,11 +1086,19 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, return_type = g->builtin_types.entry_bool; break; case PrefixOpBinNot: - zig_panic("TODO type check bin not"); - break; + { + // TODO: don't require i32 + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.prefix_op_expr.primary_expr); + return_type = g->builtin_types.entry_i32; + break; + } case PrefixOpNegation: - zig_panic("TODO type check negation"); - break; + { + // TODO: don't require i32 + analyze_expression(g, import, context, g->builtin_types.entry_i32, node->data.prefix_op_expr.primary_expr); + return_type = g->builtin_types.entry_i32; + break; + } case PrefixOpInvalid: zig_unreachable(); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 7329f53d91..e5f938a52c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -485,22 +485,18 @@ static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { // block for when val1 == false (don't even evaluate the second part) LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse"); - LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(val1)); add_debug_source_node(g, node); - LLVMValueRef val1_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, zero, ""); - LLVMBuildCondBr(g->builder, val1_i1, false_block, true_block); + LLVMBuildCondBr(g->builder, val1, true_block, false_block); LLVMPositionBuilderAtEnd(g->builder, true_block); LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2); add_debug_source_node(g, node); - LLVMValueRef val2_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, ""); LLVMBuildBr(g->builder, false_block); LLVMPositionBuilderAtEnd(g->builder, false_block); add_debug_source_node(g, node); LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); - LLVMValueRef one_i1 = LLVMConstAllOnes(LLVMInt1Type()); - LLVMValueRef incoming_values[2] = {one_i1, val2_i1}; + LLVMValueRef incoming_values[2] = {val1, val2}; LLVMBasicBlockRef incoming_blocks[2] = {orig_block, true_block}; LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); @@ -519,22 +515,18 @@ static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { // block for when val1 == true (don't even evaluate the second part) LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue"); - LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(val1)); add_debug_source_node(g, expr_node); - LLVMValueRef val1_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, zero, ""); - LLVMBuildCondBr(g->builder, val1_i1, false_block, true_block); + LLVMBuildCondBr(g->builder, val1, true_block, false_block); LLVMPositionBuilderAtEnd(g->builder, false_block); LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2); add_debug_source_node(g, expr_node); - LLVMValueRef val2_i1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, ""); LLVMBuildBr(g->builder, true_block); LLVMPositionBuilderAtEnd(g->builder, true_block); add_debug_source_node(g, expr_node); LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); - LLVMValueRef one_i1 = LLVMConstAllOnes(LLVMInt1Type()); - LLVMValueRef incoming_values[2] = {one_i1, val2_i1}; + LLVMValueRef incoming_values[2] = {val1, val2}; LLVMBasicBlockRef incoming_blocks[2] = {orig_block, false_block}; LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); diff --git a/src/parser.cpp b/src/parser.cpp index 9497224fbb..7b20bd7811 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -944,7 +944,7 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man } /* -PrefixOpExpression : PrefixOp SuffixOpExpression | SuffixOpExpression +PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression */ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -952,7 +952,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo if (prefix_op == PrefixOpInvalid) return ast_parse_suffix_op_expr(pc, token_index, mandatory); - AstNode *prefix_op_expr = ast_parse_suffix_op_expr(pc, token_index, true); + AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true); AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); node->data.prefix_op_expr.primary_expr = prefix_op_expr; node->data.prefix_op_expr.prefix_op = prefix_op; @@ -962,24 +962,26 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo /* -CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression +CastExpression : CastExpression token(as) Type | PrefixOpExpression */ static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) { - AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, mandatory); - if (!prefix_op_expr) + AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory); + if (!operand_1) return nullptr; - Token *as_kw = &pc->tokens->at(*token_index); - if (as_kw->id != TokenIdKeywordAs) - return prefix_op_expr; - *token_index += 1; + while (true) { + Token *as_kw = &pc->tokens->at(*token_index); + if (as_kw->id != TokenIdKeywordAs) + return operand_1; + *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw); - node->data.cast_expr.expr = prefix_op_expr; + AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw); + node->data.cast_expr.expr = operand_1; - node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index); + node->data.cast_expr.type = ast_parse_type(pc, *token_index, token_index); - return node; + operand_1 = node; + } } static BinOpType tok_to_mult_op(Token *token) { @@ -1009,26 +1011,28 @@ static BinOpType ast_parse_mult_op(ParseContext *pc, int *token_index, bool mand } /* -MultiplyExpression : CastExpression MultiplyOperator CastExpression | CastExpression +MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastExpression */ static AstNode *ast_parse_mult_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_cast_expression(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - BinOpType mult_op = ast_parse_mult_op(pc, token_index, false); - if (mult_op == BinOpTypeInvalid) - return operand_1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + BinOpType mult_op = ast_parse_mult_op(pc, token_index, false); + if (mult_op == BinOpTypeInvalid) + return operand_1; - AstNode *operand_2 = ast_parse_cast_expression(pc, token_index, true); + AstNode *operand_2 = ast_parse_cast_expression(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = mult_op; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = mult_op; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } static BinOpType tok_to_add_op(Token *token) { @@ -1057,26 +1061,28 @@ static BinOpType ast_parse_add_op(ParseContext *pc, int *token_index, bool manda } /* -AdditionExpression : MultiplyExpression AdditionOperator MultiplyExpression | MultiplyExpression +AdditionExpression : MultiplyExpression AdditionOperator AdditionExpression | MultiplyExpression */ static AstNode *ast_parse_add_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_mult_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - BinOpType add_op = ast_parse_add_op(pc, token_index, false); - if (add_op == BinOpTypeInvalid) - return operand_1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + BinOpType add_op = ast_parse_add_op(pc, token_index, false); + if (add_op == BinOpTypeInvalid) + return operand_1; - AstNode *operand_2 = ast_parse_mult_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_mult_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = add_op; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = add_op; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } static BinOpType tok_to_bit_shift_op(Token *token) { @@ -1088,7 +1094,7 @@ static BinOpType tok_to_bit_shift_op(Token *token) { } /* -BitShiftOperator : token(BitShiftLeft | token(BitShiftRight) +BitShiftOperator : token(BitShiftLeft) | token(BitShiftRight) */ static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -1105,96 +1111,104 @@ static BinOpType ast_parse_bit_shift_op(ParseContext *pc, int *token_index, bool } /* -BitShiftExpression : AdditionExpression BitShiftOperator AdditionExpression | AdditionExpression +BitShiftExpression : AdditionExpression BitShiftOperator BitShiftExpression | AdditionExpression */ static AstNode *ast_parse_bit_shift_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_add_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - BinOpType bit_shift_op = ast_parse_bit_shift_op(pc, token_index, false); - if (bit_shift_op == BinOpTypeInvalid) - return operand_1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + BinOpType bit_shift_op = ast_parse_bit_shift_op(pc, token_index, false); + if (bit_shift_op == BinOpTypeInvalid) + return operand_1; - AstNode *operand_2 = ast_parse_add_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_add_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = bit_shift_op; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = bit_shift_op; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } /* -BinaryAndExpression : BitShiftExpression token(BinAnd) BitShiftExpression | BitShiftExpression +BinaryAndExpression : BitShiftExpression token(BinAnd) BinaryAndExpression | BitShiftExpression */ static AstNode *ast_parse_bin_and_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_bit_shift_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - if (token->id != TokenIdBinAnd) - return operand_1; - *token_index += 1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + if (token->id != TokenIdBinAnd) + return operand_1; + *token_index += 1; - AstNode *operand_2 = ast_parse_bit_shift_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_bit_shift_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = BinOpTypeBinAnd; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = BinOpTypeBinAnd; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } /* -BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryAndExpression | BinaryAndExpression +BinaryXorExpression : BinaryAndExpression token(BinXor) BinaryXorExpression | BinaryAndExpression */ static AstNode *ast_parse_bin_xor_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_bin_and_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - if (token->id != TokenIdBinXor) - return operand_1; - *token_index += 1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + if (token->id != TokenIdBinXor) + return operand_1; + *token_index += 1; - AstNode *operand_2 = ast_parse_bin_and_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_bin_and_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = BinOpTypeBinXor; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = BinOpTypeBinXor; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } /* -BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryXorExpression | BinaryXorExpression +BinaryOrExpression : BinaryXorExpression token(BinOr) BinaryOrExpression | BinaryXorExpression */ static AstNode *ast_parse_bin_or_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_bin_xor_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - if (token->id != TokenIdBinOr) - return operand_1; - *token_index += 1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + if (token->id != TokenIdBinOr) + return operand_1; + *token_index += 1; - AstNode *operand_2 = ast_parse_bin_xor_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_bin_xor_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = BinOpTypeBinOr; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = BinOpTypeBinOr; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } static BinOpType tok_to_cmp_op(Token *token) { @@ -1247,26 +1261,28 @@ static AstNode *ast_parse_comparison_expr(ParseContext *pc, int *token_index, bo } /* -BoolAndExpression : ComparisonExpression token(BoolAnd) ComparisonExpression | ComparisonExpression +BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression */ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_comparison_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - if (token->id != TokenIdBoolAnd) - return operand_1; - *token_index += 1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + if (token->id != TokenIdBoolAnd) + return operand_1; + *token_index += 1; - AstNode *operand_2 = ast_parse_comparison_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_comparison_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = BinOpTypeBoolAnd; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = BinOpTypeBoolAnd; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } /* @@ -1382,26 +1398,28 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token } /* -BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndExpression +BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression */ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool mandatory) { AstNode *operand_1 = ast_parse_bool_and_expr(pc, token_index, mandatory); if (!operand_1) return nullptr; - Token *token = &pc->tokens->at(*token_index); - if (token->id != TokenIdBoolOr) - return operand_1; - *token_index += 1; + while (true) { + Token *token = &pc->tokens->at(*token_index); + if (token->id != TokenIdBoolOr) + return operand_1; + *token_index += 1; - AstNode *operand_2 = ast_parse_bool_and_expr(pc, token_index, true); + AstNode *operand_2 = ast_parse_bool_and_expr(pc, token_index, true); - AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); - node->data.bin_op_expr.op1 = operand_1; - node->data.bin_op_expr.bin_op = BinOpTypeBoolOr; - node->data.bin_op_expr.op2 = operand_2; + AstNode *node = ast_create_node(pc, NodeTypeBinOpExpr, token); + node->data.bin_op_expr.op1 = operand_1; + node->data.bin_op_expr.bin_op = BinOpTypeBoolOr; + node->data.bin_op_expr.op2 = operand_2; - return node; + operand_1 = node; + } } /* diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index d1e672d2f1..fd976637d7 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -478,9 +478,10 @@ void tokenize(Buf *buf, Tokenization *out) { t.multi_line_comment_count = 1; break; default: + t.pos -= 1; end_token(&t); t.state = TokenizeStateStart; - break; + continue; } break; case TokenizeStateLineComment: @@ -592,9 +593,10 @@ void tokenize(Buf *buf, Tokenization *out) { t.state = TokenizeStateStart; break; default: + t.pos -= 1; end_token(&t); t.state = TokenizeStateStart; - break; + continue; } break; } diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 8adbe0b6d7..a737298ef8 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -409,6 +409,27 @@ export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 { )SOURCE", "Hello, world!\n"); + add_simple_case("a + b + c", R"SOURCE( +use "std.zig"; + +export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 { + if false || false || false { print_str("BAD 1\n" as string); } + if true && true && false { print_str("BAD 2\n" as string); } + if 1 | 2 | 4 != 7 { print_str("BAD 3\n" as string); } + if 3 ^ 6 ^ 8 != 13 { print_str("BAD 4\n" as string); } + if 7 & 14 & 28 != 4 { print_str("BAD 5\n" as string); } + if 9 << 1 << 2 != 9 << 3 { print_str("BAD 6\n" as string); } + if 90 >> 1 >> 2 != 90 >> 3 { print_str("BAD 7\n" as string); } + if 100 - 1 + 1000 != 1099 { print_str("BAD 8\n" as string); } + if 5 * 4 / 2 % 3 != 1 { print_str("BAD 9\n" as string); } + if 5 as i32 as i32 != 5 { print_str("BAD 10\n" as string); } + if !!false { print_str("BAD 11\n" as string); } + if 7 != --7 { print_str("BAD 12\n" as string); } + + print_str("OK\n" as string); + return 0; +} + )SOURCE", "OK\n"); }