Commit bf47cf418a
Changed files (2)
test
src/translate_c.cpp
@@ -2204,43 +2204,10 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
return ErrorNone;
}
-static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
- TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
-
- while_scope->node->data.while_expr.condition = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
- if (while_scope->node->data.while_expr.condition == nullptr)
- return nullptr;
-
- TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),
- &while_scope->node->data.while_expr.body);
- if (body_scope == nullptr)
- return nullptr;
-
- return while_scope->node;
-}
-
-static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
- // if (c) t
- // if (c) t else e
- AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
-
- TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
- if (then_scope == nullptr)
- return nullptr;
-
- if (stmt->getElse() != nullptr) {
- TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node);
- if (else_scope == nullptr)
- return nullptr;
- }
-
- AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
- if (condition_node == nullptr)
- return nullptr;
-
- switch (condition_node->type) {
+static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) {
+ switch (expr->type) {
case NodeTypeBinOpExpr:
- switch (condition_node->data.bin_op_expr.bin_op) {
+ switch (expr->data.bin_op_expr.bin_op) {
case BinOpTypeBoolOr:
case BinOpTypeBoolAnd:
case BinOpTypeCmpEq:
@@ -2249,43 +2216,42 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
case BinOpTypeCmpGreaterThan:
case BinOpTypeCmpLessOrEq:
case BinOpTypeCmpGreaterOrEq:
- if_node->data.if_bool_expr.condition = condition_node;
- return if_node;
+ return expr;
default:
goto convert_to_bitcast;
}
case NodeTypePrefixOpExpr:
- switch (condition_node->data.prefix_op_expr.prefix_op) {
+ switch (expr->data.prefix_op_expr.prefix_op) {
case PrefixOpBoolNot:
- if_node->data.if_bool_expr.condition = condition_node;
- return if_node;
+ return expr;
default:
goto convert_to_bitcast;
}
case NodeTypeBoolLiteral:
- if_node->data.if_bool_expr.condition = condition_node;
- return if_node;
+ return expr;
default: {
- // In Zig, float, int and pointer does not work in if statements.
- // To make it work, we bitcast any value we get to an int of the right size
- // and comp it to 0
- // TODO: This doesn't work for pointers, as they become nullable on
- // translate
- // c: if (cond) { }
- // zig: {
- // zig: const _tmp = cond;
- // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }
- // zig: }
- convert_to_bitcast:
+ // In Zig, float, int and pointer does not implicitly cast to bool.
+ // To make it work, we bitcast any value we get to an int of the right size
+ // and comp it to 0
+ // TODO: This doesn't work for pointers, as they become nullable on
+ // translate
+ // c: expr
+ // zig: __to_bool_expr: {
+ // zig: const _tmp = cond;
+ // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
+ // zig: }
+ convert_to_bitcast:
TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
+ Buf *label_name = buf_create_from_str("__to_bool_expr");
+ child_scope->node->data.block.name = label_name;
// const _tmp = cond;
// TODO: avoid name collisions with generated variable names
- Buf* tmp_var_name = buf_create_from_str("_tmp");
- AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node);
+ Buf *tmp_var_name = buf_create_from_str("_tmp");
+ AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr);
child_scope->node->data.block.statements.append(tmp_var_decl);
// @sizeOf(@typeOf(_tmp)) * 8
@@ -2294,8 +2260,8 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
- c, sizeof_tmp, BinOpTypeMult,
- trans_create_node_unsigned_negative(c, 8, false));
+ c, sizeof_tmp, BinOpTypeMult,
+ trans_create_node_unsigned_negative(c, 8, false));
// @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
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 *
bit_cast->data.fn_call_expr.params.append(int_type);
bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
- // if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { }
+ // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0
AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
- if_node->data.if_bool_expr.condition = not_eql_zero;
- child_scope->node->data.block.statements.append(if_node);
+ child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero));
return child_scope->node;
}
}
}
+static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
+ TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
+
+ while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, scope, trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue));
+ if (while_scope->node->data.while_expr.condition == nullptr)
+ return nullptr;
+
+ TransScope *body_scope = trans_stmt(c, &while_scope->base, stmt->getBody(),
+ &while_scope->node->data.while_expr.body);
+ if (body_scope == nullptr)
+ return nullptr;
+
+ return while_scope->node;
+}
+
+static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
+ // if (c) t
+ // if (c) t else e
+ AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
+
+ TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block);
+ if (then_scope == nullptr)
+ return nullptr;
+
+ if (stmt->getElse() != nullptr) {
+ TransScope *else_scope = trans_stmt(c, scope, stmt->getElse(), &if_node->data.if_bool_expr.else_node);
+ if (else_scope == nullptr)
+ return nullptr;
+ }
+
+ AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
+ if (condition_node == nullptr)
+ return nullptr;
+
+ if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node);
+ return if_node;
+}
+
static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
@@ -2503,6 +2506,8 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
&while_scope->node->data.while_expr.condition);
if (end_cond_scope == nullptr)
return nullptr;
+
+ while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, cond_scope, while_scope->node->data.while_expr.condition);
}
const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig
@@ -1124,15 +1124,62 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\ }
\\}
,
- \\pub fn if_int(i: c_int) c_int {
- \\ {
- \\ const _tmp = i;
- \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) {
- \\ return 0;
- \\ } else {
- \\ return 1;
- \\ };
- \\ };
+ \\pub fn if_int(i: c_int) c_int {
+ \\ if (__to_bool_expr: {
+ \\ const _tmp = i;
+ \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
+ \\ }) {
+ \\ return 0;
+ \\ } else {
+ \\ return 1;
+ \\ };
+ \\}
+ );
+
+ cases.add("while on int",
+ \\int while_int(int i) {
+ \\ while (i) {
+ \\ return 0;
+ \\ }
+ \\}
+ ,
+ \\pub fn while_int(i: c_int) c_int {
+ \\ while (__to_bool_expr: {
+ \\ const _tmp = i;
+ \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
+ \\ }) {
+ \\ return 0;
+ \\ };
+ \\}
+ );
+
+ cases.add("for on int",
+ \\int for_int(int i) {
+ \\ for (;i;) {
+ \\ return 0;
+ \\ }
+ \\
+ \\ for (int j = 4;j;j--) {
+ \\ return 0;
+ \\ }
\\}
+ ,
+ \\pub fn for_int(i: c_int) c_int {
+ \\ while (__to_bool_expr: {
+ \\ const _tmp = i;
+ \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
+ \\ }) {
+ \\ return 0;
+ \\ };
+ \\ {
+ \\ var j: c_int = 4;
+ \\ while (__to_bool_expr: {
+ \\ const _tmp = j;
+ \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
+ \\ }) : (j -= 1) {
+ \\ return 0;
+ \\ };
+ \\ };
+ \\}
);
}