authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-03-06 11:57:51+01:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-03-06 11:57:51+01:00
logbf47cf418af785550f298a519b0dbfa2efcdd3cb
tree0f26e833e7e4a3418c1b73a76cba77d07bd19b81
parent61ecc486717944ad652cd9442fe35a4cfb9ae1ec

expr to bool is now it's own function.

* Now while and for loops work on ints and floats, like if statements * This fixes the loop problem in #813

2 files changed, 122 insertions(+), 70 deletions(-)

src/translate_c.cpp+66-61
......@@ -2204,43 +2204,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
22042204 return ErrorNone;
22052205}
22062206
2207static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
2208 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
2209
2210 while_scope->node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2211 if (while_scope->node->data.while_expr.condition == nullptr)
2212 return nullptr;
2213
2214 TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),
2215 &while_scope->node->data.while_expr.body);
2216 if (body_scope == nullptr)
2217 return nullptr;
2218
2219 return while_scope->node;
2220}
2221
2222static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
2223 // if (c) t
2224 // if (c) t else e
2225 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
2226
2227 TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
2228 if (then_scope == nullptr)
2229 return nullptr;
2230
2231 if (stmt->getElse() != nullptr) {
2232 TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node);
2233 if (else_scope == nullptr)
2234 return nullptr;
2235 }
2236
2237 AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2238 if (condition_node == nullptr)
2239 return nullptr;
2240
2241 switch (condition_node->type) {
2207static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) {
2208 switch (expr->type) {
22422209 case NodeTypeBinOpExpr:
2243 switch (condition_node->data.bin_op_expr.bin_op) {
2210 switch (expr->data.bin_op_expr.bin_op) {
22442211 case BinOpTypeBoolOr:
22452212 case BinOpTypeBoolAnd:
22462213 case BinOpTypeCmpEq:
......@@ -2249,43 +2216,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
22492216 case BinOpTypeCmpGreaterThan:
22502217 case BinOpTypeCmpLessOrEq:
22512218 case BinOpTypeCmpGreaterOrEq:
2252 if_node->data.if_bool_expr.condition = condition_node;
2253 return if_node;
2219 return expr;
22542220 default:
22552221 goto convert_to_bitcast;
22562222 }
22572223
22582224 case NodeTypePrefixOpExpr:
2259 switch (condition_node->data.prefix_op_expr.prefix_op) {
2225 switch (expr->data.prefix_op_expr.prefix_op) {
22602226 case PrefixOpBoolNot:
2261 if_node->data.if_bool_expr.condition = condition_node;
2262 return if_node;
2227 return expr;
22632228 default:
22642229 goto convert_to_bitcast;
22652230 }
22662231
22672232 case NodeTypeBoolLiteral:
2268 if_node->data.if_bool_expr.condition = condition_node;
2269 return if_node;
2233 return expr;
22702234
22712235 default: {
2272 // In Zig, float, int and pointer does not work in if statements.
2273 // To make it work, we bitcast any value we get to an int of the right size
2274 // and comp it to 0
2275 // TODO: This doesn't work for pointers, as they become nullable on
2276 // translate
2277 // c: if (cond) { }
2278 // zig: {
2279 // zig: const _tmp = cond;
2280 // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }
2281 // zig: }
2282 convert_to_bitcast:
2236 // In Zig, float, int and pointer does not implicitly cast to bool.
2237 // To make it work, we bitcast any value we get to an int of the right size
2238 // and comp it to 0
2239 // TODO: This doesn't work for pointers, as they become nullable on
2240 // translate
2241 // c: expr
2242 // zig: __to_bool_expr: {
2243 // zig: const _tmp = cond;
2244 // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
2245 // zig: }
2246 convert_to_bitcast:
22832247 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
2248 Buf *label_name = buf_create_from_str("__to_bool_expr");
2249 child_scope->node->data.block.name = label_name;
22842250
22852251 // const _tmp = cond;
22862252 // TODO: avoid name collisions with generated variable names
2287 Buf* tmp_var_name = buf_create_from_str("_tmp");
2288 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node);
2253 Buf *tmp_var_name = buf_create_from_str("_tmp");
2254 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr);
22892255 child_scope->node->data.block.statements.append(tmp_var_decl);
22902256
22912257 // @sizeOf(@typeOf(_tmp)) * 8
......@@ -2294,8 +2260,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
22942260 AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
22952261 sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
22962262 AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
2297 c, sizeof_tmp, BinOpTypeMult,
2298 trans_create_node_unsigned_negative(c, 8, false));
2263 c, sizeof_tmp, BinOpTypeMult,
2264 trans_create_node_unsigned_negative(c, 8, false));
22992265
23002266 // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
23012267 AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");
......@@ -2307,16 +2273,53 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
23072273 bit_cast->data.fn_call_expr.params.append(int_type);
23082274 bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
23092275
2310 // if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }
2276 // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0
23112277 AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2312 if_node->data.if_bool_expr.condition = not_eql_zero;
2313 child_scope->node->data.block.statements.append(if_node);
2278 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero));
23142279
23152280 return child_scope->node;
23162281 }
23172282 }
23182283}
23192284
2285static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
2286 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
2287
2288 while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, scope, trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue));
2289 if (while_scope->node->data.while_expr.condition == nullptr)
2290 return nullptr;
2291
2292 TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),
2293 &while_scope->node->data.while_expr.body);
2294 if (body_scope == nullptr)
2295 return nullptr;
2296
2297 return while_scope->node;
2298}
2299
2300static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
2301 // if (c) t
2302 // if (c) t else e
2303 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
2304
2305 TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
2306 if (then_scope == nullptr)
2307 return nullptr;
2308
2309 if (stmt->getElse() != nullptr) {
2310 TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node);
2311 if (else_scope == nullptr)
2312 return nullptr;
2313 }
2314
2315 AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2316 if (condition_node == nullptr)
2317 return nullptr;
2318
2319 if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node);
2320 return if_node;
2321}
2322
23202323static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
23212324 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
23222325
......@@ -2503,6 +2506,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
25032506 &while_scope->node->data.while_expr.condition);
25042507 if (end_cond_scope == nullptr)
25052508 return nullptr;
2509
2510 while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, cond_scope, while_scope->node->data.while_expr.condition);
25062511 }
25072512
25082513 const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig+56-9
......@@ -1124,15 +1124,62 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
11241124 \\ }
11251125 \\}
11261126 ,
1127 \\pub fn if_int(i: c_int) c_int {
1128 \\ {
1129 \\ const _tmp = i;
1130 \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) {
1131 \\ return 0;
1132 \\ } else {
1133 \\ return 1;
1134 \\ };
1135 \\ };
1127 \\pub fn if_int(i: c_int) c_int {
1128 \\ if (__to_bool_expr: {
1129 \\ const _tmp = i;
1130 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1131 \\ }) {
1132 \\ return 0;
1133 \\ } else {
1134 \\ return 1;
1135 \\ };
1136 \\}
1137 );
1138
1139 cases.add("while on int",
1140 \\int while_int(int i) {
1141 \\ while (i) {
1142 \\ return 0;
1143 \\ }
1144 \\}
1145 ,
1146 \\pub fn while_int(i: c_int) c_int {
1147 \\ while (__to_bool_expr: {
1148 \\ const _tmp = i;
1149 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1150 \\ }) {
1151 \\ return 0;
1152 \\ };
1153 \\}
1154 );
1155
1156 cases.add("for on int",
1157 \\int for_int(int i) {
1158 \\ for (;i;) {
1159 \\ return 0;
1160 \\ }
1161 \\
1162 \\ for (int j = 4;j;j--) {
1163 \\ return 0;
1164 \\ }
11361165 \\}
1166 ,
1167 \\pub fn for_int(i: c_int) c_int {
1168 \\ while (__to_bool_expr: {
1169 \\ const _tmp = i;
1170 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1171 \\ }) {
1172 \\ return 0;
1173 \\ };
1174 \\ {
1175 \\ var j: c_int = 4;
1176 \\ while (__to_bool_expr: {
1177 \\ const _tmp = j;
1178 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1179 \\ }) : (j -= 1) {
1180 \\ return 0;
1181 \\ };
1182 \\ };
1183 \\}
11371184 );
11381185}