authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-31 16:04:13-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-31 16:04:13-07:00
logb3ac5c16ecc8dd9da661dcb9d15a6c36a8e4167b
tree4539ac7b88906ef03540639f19e2f37ce0bf319f
parent7ba99e9715c1fa3cd00fe6d9ac74b9a15eeac706

block expressions require parens

closes #39

7 files changed, 141 insertions(+), 73 deletions(-)

doc/langref.md+7-7
...@@ -60,10 +60,12 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen)...@@ -60,10 +60,12 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen)
6060
61ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis)61ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis)
6262
63Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType63Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType
6464
65PointerType : token(Ampersand) option(token(Const)) Type65PointerType : token(Ampersand) option(token(Const)) Type
6666
67MaybeType : token(Question) Type
68
67ArrayType : token(LBracket) Type token(Semicolon) Expression token(RBracket)69ArrayType : token(LBracket) Type token(Semicolon) Expression token(RBracket)
6870
69Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)71Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
...@@ -96,7 +98,7 @@ AssignmentOperator : token(Eq) | token(TimesEq) | token(DivEq) | token(ModEq) |...@@ -96,7 +98,7 @@ AssignmentOperator : token(Eq) | token(TimesEq) | token(DivEq) | token(ModEq) |
9698
97BlockExpression : IfExpression | Block | WhileExpression99BlockExpression : IfExpression | Block | WhileExpression
98100
99WhileExpression : token(While) Expression Block101WhileExpression : token(While) token(LParen) Expression token(RParen) Expression
100102
101BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression103BoolOrExpression : BoolAndExpression token(BoolOr) BoolOrExpression | BoolAndExpression
102104
...@@ -104,13 +106,11 @@ ReturnExpression : token(Return) option(Expression)...@@ -104,13 +106,11 @@ ReturnExpression : token(Return) option(Expression)
104106
105IfExpression : IfVarExpression | IfBoolExpression107IfExpression : IfVarExpression | IfBoolExpression
106108
107IfBoolExpression : token(If) option((token) Expression Block option(Else | ElseIf)109IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)
108
109IfVarExpression : token(If) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(MaybeAssign) Expression Block Option(Else | ElseIf)
110110
111ElseIf : token(Else) IfExpression111IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)
112112
113Else : token(Else) Block113Else : token(Else) Expression
114114
115BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression115BoolAndExpression : ComparisonExpression token(BoolAnd) BoolAndExpression | ComparisonExpression
116116
example/maybe_type/main.zig created+19
...@@ -0,0 +1,19 @@
1export executable "maybe_type";
2
3use "std.zig";
4
5fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
6 const x : ?bool = true;
7
8 if (const y ?= x) {
9 if (y) {
10 print_str("x is true\n");
11 } else {
12 print_str("x is false\n");
13 }
14 } else {
15 print_str("x is none\n");
16 }
17
18 return 0;
19}
src/analyze.cpp+34
...@@ -132,6 +132,26 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -132,6 +132,26 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
132 }132 }
133}133}
134134
135static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
136 if (child_type->maybe_parent) {
137 return child_type->maybe_parent;
138 } else {
139 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMaybe);
140 // TODO entry->type_ref
141 buf_resize(&entry->name, 0);
142 buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
143 // TODO entry->size_in_bits
144 // TODO entry->align_in_bits
145 assert(child_type->di_type);
146 // TODO entry->di_type
147 entry->data.maybe.child_type = child_type;
148
149 g->type_table.put(&entry->name, entry);
150 child_type->maybe_parent = entry;
151 return entry;
152 }
153}
154
135static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) {155static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size) {
136 auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);156 auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);
137 if (existing_entry) {157 if (existing_entry) {
...@@ -208,6 +228,20 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {...@@ -208,6 +228,20 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
208 }228 }
209 return type_node->entry;229 return type_node->entry;
210 }230 }
231 case AstNodeTypeTypeMaybe:
232 {
233 resolve_type(g, node->data.type.child_type);
234 TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry;
235 assert(child_type);
236 if (child_type->id == TypeTableEntryIdUnreachable) {
237 add_node_error(g, node,
238 buf_create_from_str("maybe unreachable type not allowed"));
239 } else if (child_type->id == TypeTableEntryIdInvalid) {
240 return child_type;
241 }
242 type_node->entry = get_maybe_type(g, child_type);
243 return type_node->entry;
244 }
211 }245 }
212 zig_unreachable();246 zig_unreachable();
213}247}
src/analyze.hpp+1
...@@ -96,6 +96,7 @@ struct TypeTableEntry {...@@ -96,6 +96,7 @@ struct TypeTableEntry {
96 TypeTableEntry *pointer_const_parent;96 TypeTableEntry *pointer_const_parent;
97 TypeTableEntry *pointer_mut_parent;97 TypeTableEntry *pointer_mut_parent;
98 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;98 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
99 TypeTableEntry *maybe_parent;
99100
100};101};
101102
src/parser.cpp+30-17
...@@ -225,6 +225,12 @@ void ast_print(AstNode *node, int indent) {...@@ -225,6 +225,12 @@ void ast_print(AstNode *node, int indent) {
225 ast_print(node->data.type.array_size, indent + 2);225 ast_print(node->data.type.array_size, indent + 2);
226 break;226 break;
227 }227 }
228 case AstNodeTypeTypeMaybe:
229 {
230 fprintf(stderr, "MaybeType\n");
231 ast_print(node->data.type.child_type, indent + 2);
232 break;
233 }
228 }234 }
229 break;235 break;
230 case NodeTypeReturnExpr:236 case NodeTypeReturnExpr:
...@@ -920,7 +926,7 @@ static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNod...@@ -920,7 +926,7 @@ static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNod
920}926}
921927
922/*928/*
923Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType929Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType
924PointerType : token(Ampersand) option(token(Const)) Type930PointerType : token(Ampersand) option(token(Const)) Type
925ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket)931ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket)
926*/932*/
...@@ -941,6 +947,9 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) {...@@ -941,6 +947,9 @@ static AstNode *ast_parse_type(ParseContext *pc, int *token_index) {
941 ast_buf_from_token(pc, token, &node->data.type.primitive_name);947 ast_buf_from_token(pc, token, &node->data.type.primitive_name);
942 } else if (token->id == TokenIdAmpersand) {948 } else if (token->id == TokenIdAmpersand) {
943 ast_parse_type_assume_amp(pc, token_index, node);949 ast_parse_type_assume_amp(pc, token_index, node);
950 } else if (token->id == TokenIdMaybe) {
951 node->data.type.type = AstNodeTypeTypeMaybe;
952 node->data.type.child_type = ast_parse_type(pc, token_index);
944 } else if (token->id == TokenIdBoolAnd) {953 } else if (token->id == TokenIdBoolAnd) {
945 // Pretend that we got 2 ampersand tokens954 // Pretend that we got 2 ampersand tokens
946 node->data.type.type = AstNodeTypeTypePointer;955 node->data.type.type = AstNodeTypeTypePointer;
...@@ -1636,10 +1645,9 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, int *token_index, bool...@@ -1636,10 +1645,9 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, int *token_index, bool
1636}1645}
16371646
1638/*1647/*
1639ElseIf : token(Else) IfExpression1648Else : token(Else) Expression
1640Else : token(Else) Block
1641*/1649*/
1642static AstNode *ast_parse_else_or_else_if(ParseContext *pc, int *token_index, bool mandatory) {1650static AstNode *ast_parse_else(ParseContext *pc, int *token_index, bool mandatory) {
1643 Token *else_token = &pc->tokens->at(*token_index);1651 Token *else_token = &pc->tokens->at(*token_index);
16441652
1645 if (else_token->id != TokenIdKeywordElse) {1653 if (else_token->id != TokenIdKeywordElse) {
...@@ -1651,17 +1659,13 @@ static AstNode *ast_parse_else_or_else_if(ParseContext *pc, int *token_index, bo...@@ -1651,17 +1659,13 @@ static AstNode *ast_parse_else_or_else_if(ParseContext *pc, int *token_index, bo
1651 }1659 }
1652 *token_index += 1;1660 *token_index += 1;
16531661
1654 AstNode *if_expr = ast_parse_if_expr(pc, token_index, false);1662 return ast_parse_expression(pc, token_index, true);
1655 if (if_expr)
1656 return if_expr;
1657
1658 return ast_parse_block(pc, token_index, true);
1659}1663}
16601664
1661/*1665/*
1662IfExpression : IfVarExpression | IfBoolExpression1666IfExpression : IfVarExpression | IfBoolExpression
1663IfBoolExpression : token(If) option((token) Expression Block option(Else | ElseIf)1667IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)
1664IfVarExpression : token(If) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(Eq) Expression Block Option(Else | ElseIf)1668IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)
1665*/1669*/
1666static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory) {1670static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory) {
1667 Token *if_tok = &pc->tokens->at(*token_index);1671 Token *if_tok = &pc->tokens->at(*token_index);
...@@ -1674,6 +1678,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda...@@ -1674,6 +1678,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
1674 }1678 }
1675 *token_index += 1;1679 *token_index += 1;
16761680
1681 ast_eat_token(pc, token_index, TokenIdLParen);
1682
1677 Token *token = &pc->tokens->at(*token_index);1683 Token *token = &pc->tokens->at(*token_index);
1678 if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) {1684 if (token->id == TokenIdKeywordConst || token->id == TokenIdKeywordVar) {
1679 AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_tok);1685 AstNode *node = ast_create_node(pc, NodeTypeIfVarExpr, if_tok);
...@@ -1695,14 +1701,16 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda...@@ -1695,14 +1701,16 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
1695 } else {1701 } else {
1696 ast_invalid_token_error(pc, eq_or_colon);1702 ast_invalid_token_error(pc, eq_or_colon);
1697 }1703 }
1698 node->data.if_var_expr.then_block = ast_parse_block(pc, token_index, true);1704 ast_eat_token(pc, token_index, TokenIdRParen);
1699 node->data.if_var_expr.else_node = ast_parse_else_or_else_if(pc, token_index, false);1705 node->data.if_var_expr.then_block = ast_parse_expression(pc, token_index, true);
1706 node->data.if_var_expr.else_node = ast_parse_else(pc, token_index, false);
1700 return node;1707 return node;
1701 } else {1708 } else {
1702 AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_tok);1709 AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_tok);
1703 node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);1710 node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true);
1704 node->data.if_bool_expr.then_block = ast_parse_block(pc, token_index, true);1711 ast_eat_token(pc, token_index, TokenIdRParen);
1705 node->data.if_bool_expr.else_node = ast_parse_else_or_else_if(pc, token_index, false);1712 node->data.if_bool_expr.then_block = ast_parse_expression(pc, token_index, true);
1713 node->data.if_bool_expr.else_node = ast_parse_else(pc, token_index, false);
1706 return node;1714 return node;
1707 }1715 }
1708}1716}
...@@ -1795,7 +1803,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool...@@ -1795,7 +1803,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, int *token_index, bool
1795}1803}
17961804
1797/*1805/*
1798WhileExpression : token(While) Expression Block1806WhileExpression : token(While) token(LParen) Expression token(RParen) Expression
1799*/1807*/
1800static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool mandatory) {1808static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool mandatory) {
1801 Token *token = &pc->tokens->at(*token_index);1809 Token *token = &pc->tokens->at(*token_index);
...@@ -1811,8 +1819,13 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool ma...@@ -1811,8 +1819,13 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool ma
18111819
1812 AstNode *node = ast_create_node(pc, NodeTypeWhileExpr, token);1820 AstNode *node = ast_create_node(pc, NodeTypeWhileExpr, token);
18131821
1822 ast_eat_token(pc, token_index, TokenIdLParen);
1814 node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);1823 node->data.while_expr.condition = ast_parse_expression(pc, token_index, true);
1815 node->data.while_expr.body = ast_parse_block(pc, token_index, true);1824 ast_eat_token(pc, token_index, TokenIdRParen);
1825
1826 node->data.while_expr.body = ast_parse_expression(pc, token_index, true);
1827
1828
18161829
1817 return node;1830 return node;
1818}1831}
src/parser.hpp+1
...@@ -95,6 +95,7 @@ enum AstNodeTypeType {...@@ -95,6 +95,7 @@ enum AstNodeTypeType {
95 AstNodeTypeTypePrimitive,95 AstNodeTypeTypePrimitive,
96 AstNodeTypeTypePointer,96 AstNodeTypeTypePointer,
97 AstNodeTypeTypeArray,97 AstNodeTypeTypeArray,
98 AstNodeTypeTypeMaybe,
98};99};
99100
100struct AstNodeType {101struct AstNodeType {
test/run_tests.cpp+49-49
...@@ -184,17 +184,17 @@ static void add_compiling_test_cases(void) {...@@ -184,17 +184,17 @@ static void add_compiling_test_cases(void) {
184 use "std.zig";184 use "std.zig";
185185
186 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {186 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
187 if 1 != 0 {187 if (1 != 0) {
188 print_str("1 is true\n");188 print_str("1 is true\n");
189 } else {189 } else {
190 print_str("1 is false\n");190 print_str("1 is false\n");
191 }191 }
192 if 0 != 0 {192 if (0 != 0) {
193 print_str("0 is true\n");193 print_str("0 is true\n");
194 } else if 1 - 1 != 0 {194 } else if (1 - 1 != 0) {
195 print_str("1 - 1 is true\n");195 print_str("1 - 1 is true\n");
196 }196 }
197 if !(0 != 0) {197 if (!(0 != 0)) {
198 print_str("!0 is true\n");198 print_str("!0 is true\n");
199 }199 }
200 return 0;200 return 0;
...@@ -209,7 +209,7 @@ static void add_compiling_test_cases(void) {...@@ -209,7 +209,7 @@ static void add_compiling_test_cases(void) {
209 }209 }
210210
211 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {211 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
212 if add(22, 11) == 33 {212 if (add(22, 11) == 33) {
213 print_str("pass\n");213 print_str("pass\n");
214 }214 }
215 return 0;215 return 0;
...@@ -220,7 +220,7 @@ static void add_compiling_test_cases(void) {...@@ -220,7 +220,7 @@ static void add_compiling_test_cases(void) {
220 use "std.zig";220 use "std.zig";
221221
222 fn loop(a : i32) {222 fn loop(a : i32) {
223 if a == 0 {223 if (a == 0) {
224 goto done;224 goto done;
225 }225 }
226 print_str("loop\n");226 print_str("loop\n");
...@@ -304,7 +304,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -304,7 +304,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
304304
305 var i = 0 as i32;305 var i = 0 as i32;
306loop_start:306loop_start:
307 if i == 3 {307 if (i == 3) {
308 goto done;308 goto done;
309 }309 }
310 print_str("loop\n");310 print_str("loop\n");
...@@ -323,7 +323,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -323,7 +323,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
323323
324 var i : i32 = 0;324 var i : i32 = 0;
325loop_start:325loop_start:
326 if i == 5 {326 if (i == 5) {
327 goto loop_end;327 goto loop_end;
328 }328 }
329 array[i] = i + 1;329 array[i] = i + 1;
...@@ -335,7 +335,7 @@ loop_end:...@@ -335,7 +335,7 @@ loop_end:
335 i = 0;335 i = 0;
336 var accumulator = 0 as i32;336 var accumulator = 0 as i32;
337loop_2_start:337loop_2_start:
338 if i == 5 {338 if (i == 5) {
339 goto loop_2_end;339 goto loop_2_end;
340 }340 }
341341
...@@ -345,7 +345,7 @@ loop_2_start:...@@ -345,7 +345,7 @@ loop_2_start:
345 goto loop_2_start;345 goto loop_2_start;
346loop_2_end:346loop_2_end:
347347
348 if accumulator == 15 {348 if (accumulator == 15) {
349 print_str("OK\n");349 print_str("OK\n");
350 }350 }
351351
...@@ -368,18 +368,18 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -368,18 +368,18 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
368use "std.zig";368use "std.zig";
369369
370export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {370export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
371 if false || false || false { print_str("BAD 1\n"); }371 if (false || false || false) { print_str("BAD 1\n"); }
372 if true && true && false { print_str("BAD 2\n"); }372 if (true && true && false) { print_str("BAD 2\n"); }
373 if 1 | 2 | 4 != 7 { print_str("BAD 3\n"); }373 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }
374 if 3 ^ 6 ^ 8 != 13 { print_str("BAD 4\n"); }374 if (3 ^ 6 ^ 8 != 13) { print_str("BAD 4\n"); }
375 if 7 & 14 & 28 != 4 { print_str("BAD 5\n"); }375 if (7 & 14 & 28 != 4) { print_str("BAD 5\n"); }
376 if 9 << 1 << 2 != 9 << 3 { print_str("BAD 6\n"); }376 if (9 << 1 << 2 != 9 << 3) { print_str("BAD 6\n"); }
377 if 90 >> 1 >> 2 != 90 >> 3 { print_str("BAD 7\n"); }377 if (90 >> 1 >> 2 != 90 >> 3) { print_str("BAD 7\n"); }
378 if 100 - 1 + 1000 != 1099 { print_str("BAD 8\n"); }378 if (100 - 1 + 1000 != 1099) { print_str("BAD 8\n"); }
379 if 5 * 4 / 2 % 3 != 1 { print_str("BAD 9\n"); }379 if (5 * 4 / 2 % 3 != 1) { print_str("BAD 9\n"); }
380 if 5 as i32 as i32 != 5 { print_str("BAD 10\n"); }380 if (5 as i32 as i32 != 5) { print_str("BAD 10\n"); }
381 if !!false { print_str("BAD 11\n"); }381 if (!!false) { print_str("BAD 11\n"); }
382 if 7 != --7 { print_str("BAD 12\n"); }382 if (7 != --7) { print_str("BAD 12\n"); }
383383
384 print_str("OK\n");384 print_str("OK\n");
385 return 0;385 return 0;
...@@ -390,17 +390,17 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -390,17 +390,17 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
390use "std.zig";390use "std.zig";
391391
392export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {392export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
393 if true || { print_str("BAD 1\n"); false } {393 if (true || { print_str("BAD 1\n"); false }) {
394 print_str("OK 1\n");394 print_str("OK 1\n");
395 }395 }
396 if false || { print_str("OK 2\n"); false } {396 if (false || { print_str("OK 2\n"); false }) {
397 print_str("BAD 2\n");397 print_str("BAD 2\n");
398 }398 }
399399
400 if true && { print_str("OK 3\n"); false } {400 if (true && { print_str("OK 3\n"); false }) {
401 print_str("BAD 3\n");401 print_str("BAD 3\n");
402 }402 }
403 if false && { print_str("BAD 4\n"); false } {403 if (false && { print_str("BAD 4\n"); false }) {
404 } else {404 } else {
405 print_str("OK 4\n");405 print_str("OK 4\n");
406 }406 }
...@@ -414,18 +414,18 @@ use "std.zig";...@@ -414,18 +414,18 @@ use "std.zig";
414414
415export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {415export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
416 var i : i32 = 0;416 var i : i32 = 0;
417 i += 5; if i != 5 { print_str("BAD +=\n"); }417 i += 5; if (i != 5) { print_str("BAD +=\n"); }
418 i -= 2; if i != 3 { print_str("BAD -=\n"); }418 i -= 2; if (i != 3) { print_str("BAD -=\n"); }
419 i *= 20; if i != 60 { print_str("BAD *=\n"); }419 i *= 20; if (i != 60) { print_str("BAD *=\n"); }
420 i /= 3; if i != 20 { print_str("BAD /=\n"); }420 i /= 3; if (i != 20) { print_str("BAD /=\n"); }
421 i %= 11; if i != 9 { print_str("BAD %=\n"); }421 i %= 11; if (i != 9) { print_str("BAD %=\n"); }
422 i <<= 1; if i != 18 { print_str("BAD <<=\n"); }422 i <<= 1; if (i != 18) { print_str("BAD <<=\n"); }
423 i >>= 2; if i != 4 { print_str("BAD >>=\n"); }423 i >>= 2; if (i != 4) { print_str("BAD >>=\n"); }
424 i = 6;424 i = 6;
425 i &= 5; if i != 4 { print_str("BAD &=\n"); }425 i &= 5; if (i != 4) { print_str("BAD &=\n"); }
426 i ^= 6; if i != 2 { print_str("BAD ^=\n"); }426 i ^= 6; if (i != 2) { print_str("BAD ^=\n"); }
427 i = 6;427 i = 6;
428 i |= 3; if i != 7 { print_str("BAD |=\n"); }428 i |= 3; if (i != 7) { print_str("BAD |=\n"); }
429429
430 print_str("OK\n");430 print_str("OK\n");
431 return 0;431 return 0;
...@@ -570,7 +570,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -570,7 +570,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
570 foo.b = foo.a == 1;570 foo.b = foo.a == 1;
571 test_foo(foo);571 test_foo(foo);
572 test_mutation(&foo);572 test_mutation(&foo);
573 if foo.c != 100 {573 if (foo.c != 100) {
574 print_str("BAD\n");574 print_str("BAD\n");
575 }575 }
576 test_point_to_self();576 test_point_to_self();
...@@ -585,7 +585,7 @@ struct Foo {...@@ -585,7 +585,7 @@ struct Foo {
585 c : f32,585 c : f32,
586}586}
587fn test_foo(foo : Foo) {587fn test_foo(foo : Foo) {
588 if !foo.b {588 if (!foo.b) {
589 print_str("BAD\n");589 print_str("BAD\n");
590 }590 }
591}591}
...@@ -610,7 +610,7 @@ fn test_point_to_self() {...@@ -610,7 +610,7 @@ fn test_point_to_self() {
610610
611 root.next = &node;611 root.next = &node;
612612
613 if node.next.next.next.val.x != 1 {613 if (node.next.next.next.val.x != 1) {
614 print_str("BAD\n");614 print_str("BAD\n");
615 }615 }
616}616}
...@@ -620,15 +620,15 @@ fn test_byval_assign() {...@@ -620,15 +620,15 @@ fn test_byval_assign() {
620620
621 foo1.a = 1234;621 foo1.a = 1234;
622622
623 if foo2.a != 0 { print_str("BAD\n"); }623 if (foo2.a != 0) { print_str("BAD\n"); }
624624
625 foo2 = foo1;625 foo2 = foo1;
626626
627 if foo2.a != 1234 { print_str("BAD - byval assignment failed\n"); }627 if (foo2.a != 1234) { print_str("BAD - byval assignment failed\n"); }
628}628}
629fn test_initializer() {629fn test_initializer() {
630 const val = Val { .x = 42 };630 const val = Val { .x = 42 };
631 if val.x != 42 { print_str("BAD\n"); }631 if (val.x != 42) { print_str("BAD\n"); }
632}632}
633 )SOURCE", "OK\n");633 )SOURCE", "OK\n");
634634
...@@ -639,9 +639,9 @@ const g1 : i32 = 1233 + 1;...@@ -639,9 +639,9 @@ const g1 : i32 = 1233 + 1;
639var g2 : i32;639var g2 : i32;
640640
641export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {641export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
642 if g2 != 0 { print_str("BAD\n"); }642 if (g2 != 0) { print_str("BAD\n"); }
643 g2 = g1;643 g2 = g1;
644 if g2 != 1234 { print_str("BAD\n"); }644 if (g2 != 1234) { print_str("BAD\n"); }
645 print_str("OK\n");645 print_str("OK\n");
646 return 0;646 return 0;
647}647}
...@@ -651,7 +651,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -651,7 +651,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
651use "std.zig";651use "std.zig";
652export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {652export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
653 var i : i32 = 0;653 var i : i32 = 0;
654 while i < 4 {654 while (i < 4) {
655 print_str("loop\n");655 print_str("loop\n");
656 i += 1;656 i += 1;
657 }657 }
...@@ -663,10 +663,10 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -663,10 +663,10 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
663use "std.zig";663use "std.zig";
664export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {664export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
665 var i : i32 = 0;665 var i : i32 = 0;
666 while true {666 while (true) {
667 print_str("loop\n");667 print_str("loop\n");
668 i += 1;668 i += 1;
669 if i < 4 {669 if (i < 4) {
670 continue;670 continue;
671 }671 }
672 break;672 break;
...@@ -871,8 +871,8 @@ fn f() {...@@ -871,8 +871,8 @@ fn f() {
871871
872 add_compile_fail_case("missing else clause", R"SOURCE(872 add_compile_fail_case("missing else clause", R"SOURCE(
873fn f() {873fn f() {
874 const x : i32 = if true { 1 };874 const x : i32 = if (true) { 1 };
875 const y = if true { 1 as i32 };875 const y = if (true) { 1 as i32 };
876}876}
877 )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'",877 )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'",
878 ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");878 ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'");