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...@@ -2204,43 +2204,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2204 return ErrorNone;2204 return ErrorNone;
2205}2205}
22062206
2207static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {2207static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) {
2208 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);2208 switch (expr->type) {
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) {
2242 case NodeTypeBinOpExpr:2209 case NodeTypeBinOpExpr:
2243 switch (condition_node->data.bin_op_expr.bin_op) {2210 switch (expr->data.bin_op_expr.bin_op) {
2244 case BinOpTypeBoolOr:2211 case BinOpTypeBoolOr:
2245 case BinOpTypeBoolAnd:2212 case BinOpTypeBoolAnd:
2246 case BinOpTypeCmpEq:2213 case BinOpTypeCmpEq:
...@@ -2249,43 +2216,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *...@@ -2249,43 +2216,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2249 case BinOpTypeCmpGreaterThan:2216 case BinOpTypeCmpGreaterThan:
2250 case BinOpTypeCmpLessOrEq:2217 case BinOpTypeCmpLessOrEq:
2251 case BinOpTypeCmpGreaterOrEq:2218 case BinOpTypeCmpGreaterOrEq:
2252 if_node->data.if_bool_expr.condition = condition_node;2219 return expr;
2253 return if_node;
2254 default:2220 default:
2255 goto convert_to_bitcast;2221 goto convert_to_bitcast;
2256 }2222 }
22572223
2258 case NodeTypePrefixOpExpr:2224 case NodeTypePrefixOpExpr:
2259 switch (condition_node->data.prefix_op_expr.prefix_op) {2225 switch (expr->data.prefix_op_expr.prefix_op) {
2260 case PrefixOpBoolNot:2226 case PrefixOpBoolNot:
2261 if_node->data.if_bool_expr.condition = condition_node;2227 return expr;
2262 return if_node;
2263 default:2228 default:
2264 goto convert_to_bitcast;2229 goto convert_to_bitcast;
2265 }2230 }
22662231
2267 case NodeTypeBoolLiteral:2232 case NodeTypeBoolLiteral:
2268 if_node->data.if_bool_expr.condition = condition_node;2233 return expr;
2269 return if_node;
22702234
2271 default: {2235 default: {
2272 // In Zig, float, int and pointer does not work in if statements.2236 // In Zig, float, int and pointer does not implicitly cast to bool.
2273 // To make it work, we bitcast any value we get to an int of the right size2237 // To make it work, we bitcast any value we get to an int of the right size
2274 // and comp it to 02238 // and comp it to 0
2275 // TODO: This doesn't work for pointers, as they become nullable on2239 // TODO: This doesn't work for pointers, as they become nullable on
2276 // translate2240 // translate
2277 // c: if (cond) { }2241 // c: expr
2278 // zig: {2242 // zig: __to_bool_expr: {
2279 // zig: const _tmp = cond;2243 // zig: const _tmp = cond;
2280 // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }2244 // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
2281 // zig: }2245 // zig: }
2282 convert_to_bitcast:2246 convert_to_bitcast:
2283 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);2247 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
2285 // const _tmp = cond;2251 // const _tmp = cond;
2286 // TODO: avoid name collisions with generated variable names2252 // TODO: avoid name collisions with generated variable names
2287 Buf* tmp_var_name = buf_create_from_str("_tmp");2253 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);2254 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr);
2289 child_scope->node->data.block.statements.append(tmp_var_decl);2255 child_scope->node->data.block.statements.append(tmp_var_decl);
22902256
2291 // @sizeOf(@typeOf(_tmp)) * 82257 // @sizeOf(@typeOf(_tmp)) * 8
...@@ -2294,8 +2260,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *...@@ -2294,8 +2260,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2294 AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");2260 AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
2295 sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);2261 sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
2296 AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(2262 AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
2297 c, sizeof_tmp, BinOpTypeMult,2263 c, sizeof_tmp, BinOpTypeMult,
2298 trans_create_node_unsigned_negative(c, 8, false));2264 trans_create_node_unsigned_negative(c, 8, false));
22992265
2300 // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)2266 // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
2301 AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");2267 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 *...@@ -2307,16 +2273,53 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2307 bit_cast->data.fn_call_expr.params.append(int_type);2273 bit_cast->data.fn_call_expr.params.append(int_type);
2308 bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));2274 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
2311 AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));2277 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;2278 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero));
2313 child_scope->node->data.block.statements.append(if_node);
23142279
2315 return child_scope->node;2280 return child_scope->node;
2316 }2281 }
2317 }2282 }
2318}2283}
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
2320static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {2323static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
2321 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);2324 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
23222325
...@@ -2503,6 +2506,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt...@@ -2503,6 +2506,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2503 &while_scope->node->data.while_expr.condition);2506 &while_scope->node->data.while_expr.condition);
2504 if (end_cond_scope == nullptr)2507 if (end_cond_scope == nullptr)
2505 return nullptr;2508 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);
2506 }2511 }
25072512
2508 const Stmt *inc_stmt = stmt->getInc();2513 const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig+56-9
...@@ -1124,15 +1124,62 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -1124,15 +1124,62 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
1124 \\ }1124 \\ }
1125 \\}1125 \\}
1126 ,1126 ,
1127 \\pub fn if_int(i: c_int) c_int {1127 \\pub fn if_int(i: c_int) c_int {
1128 \\ {1128 \\ if (__to_bool_expr: {
1129 \\ const _tmp = i;1129 \\ const _tmp = i;
1130 \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) {1130 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1131 \\ return 0;1131 \\ }) {
1132 \\ } else {1132 \\ return 0;
1133 \\ return 1;1133 \\ } else {
1134 \\ };1134 \\ return 1;
1135 \\ };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 \\ }
1136 \\}1165 \\}
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 \\}
1137 );1184 );
1138}1185}