| ... | @@ -1955,6 +1955,8 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt | ... | @@ -1955,6 +1955,8 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt |
| 1955 | if (init_node == nullptr) | 1955 | if (init_node == nullptr) |
| 1956 | return ErrorUnexpected; | 1956 | return ErrorUnexpected; |
| 1957 | | 1957 | |
| | 1958 | } else { |
| | 1959 | init_node = trans_create_node(c, NodeTypeUndefinedLiteral); |
| 1958 | } | 1960 | } |
| 1959 | AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart()); | 1961 | AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart()); |
| 1960 | if (type_node == nullptr) | 1962 | if (type_node == nullptr) |
| ... | @@ -2215,12 +2217,6 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2215,12 +2217,6 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2215 | // if (c) t else e | 2217 | // if (c) t else e |
| 2216 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); | 2218 | AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr); |
| 2217 | | 2219 | |
| 2218 | // TODO: condition != 0 | | |
| 2219 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); | | |
| 2220 | if (condition_node == nullptr) | | |
| 2221 | return nullptr; | | |
| 2222 | if_node->data.if_bool_expr.condition = condition_node; | | |
| 2223 | | | |
| 2224 | TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block); | 2220 | TransScope *then_scope = trans_stmt(c, scope, stmt->getThen(), &if_node->data.if_bool_expr.then_block); |
| 2225 | if (then_scope == nullptr) | 2221 | if (then_scope == nullptr) |
| 2226 | return nullptr; | 2222 | return nullptr; |
| ... | @@ -2231,7 +2227,87 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * | ... | @@ -2231,7 +2227,87 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt * |
| 2231 | return nullptr; | 2227 | return nullptr; |
| 2232 | } | 2228 | } |
| 2233 | | 2229 | |
| 2234 | return if_node; | 2230 | AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue); |
| | 2231 | if (condition_node == nullptr) |
| | 2232 | return nullptr; |
| | 2233 | |
| | 2234 | switch (condition_node->type) { |
| | 2235 | case NodeTypeBinOpExpr: |
| | 2236 | switch (condition_node->data.bin_op_expr.bin_op) { |
| | 2237 | case BinOpTypeBoolOr: |
| | 2238 | case BinOpTypeBoolAnd: |
| | 2239 | case BinOpTypeCmpEq: |
| | 2240 | case BinOpTypeCmpNotEq: |
| | 2241 | case BinOpTypeCmpLessThan: |
| | 2242 | case BinOpTypeCmpGreaterThan: |
| | 2243 | case BinOpTypeCmpLessOrEq: |
| | 2244 | case BinOpTypeCmpGreaterOrEq: |
| | 2245 | if_node->data.if_bool_expr.condition = condition_node; |
| | 2246 | return if_node; |
| | 2247 | default: |
| | 2248 | goto convert_to_bitcast; |
| | 2249 | } |
| | 2250 | |
| | 2251 | case NodeTypePrefixOpExpr: |
| | 2252 | switch (condition_node->data.prefix_op_expr.prefix_op) { |
| | 2253 | case PrefixOpBoolNot: |
| | 2254 | if_node->data.if_bool_expr.condition = condition_node; |
| | 2255 | return if_node; |
| | 2256 | default: |
| | 2257 | goto convert_to_bitcast; |
| | 2258 | } |
| | 2259 | |
| | 2260 | case NodeTypeBoolLiteral: |
| | 2261 | if_node->data.if_bool_expr.condition = condition_node; |
| | 2262 | return if_node; |
| | 2263 | |
| | 2264 | default: { |
| | 2265 | // In Zig, float, int and pointer does not work in if statements. |
| | 2266 | // To make it work, we bitcast any value we get to an int of the right size |
| | 2267 | // and comp it to 0 |
| | 2268 | // TODO: This doesn't work for pointers, as they become nullable on |
| | 2269 | // translate |
| | 2270 | // c: if (cond) { } |
| | 2271 | // zig: { |
| | 2272 | // zig: const _tmp = cond; |
| | 2273 | // zig: if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } |
| | 2274 | // zig: } |
| | 2275 | convert_to_bitcast: |
| | 2276 | TransScopeBlock *child_scope = trans_scope_block_create(c, scope); |
| | 2277 | |
| | 2278 | // const _tmp = cond; |
| | 2279 | // TODO: avoid name collisions with generated variable names |
| | 2280 | Buf* tmp_var_name = buf_create_from_str("_tmp"); |
| | 2281 | AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, condition_node); |
| | 2282 | child_scope->node->data.block.statements.append(tmp_var_decl); |
| | 2283 | |
| | 2284 | // @sizeOf(@typeOf(_tmp)) * 8 |
| | 2285 | AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf"); |
| | 2286 | typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); |
| | 2287 | AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf"); |
| | 2288 | sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp); |
| | 2289 | AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op( |
| | 2290 | c, sizeof_tmp, BinOpTypeMult, |
| | 2291 | trans_create_node_unsigned_negative(c, 8, false)); |
| | 2292 | |
| | 2293 | // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8) |
| | 2294 | AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType"); |
| | 2295 | int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false)); |
| | 2296 | int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits); |
| | 2297 | |
| | 2298 | // @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) |
| | 2299 | AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast"); |
| | 2300 | bit_cast->data.fn_call_expr.params.append(int_type); |
| | 2301 | bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name)); |
| | 2302 | |
| | 2303 | // if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { } |
| | 2304 | AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false)); |
| | 2305 | if_node->data.if_bool_expr.condition = not_eql_zero; |
| | 2306 | child_scope->node->data.block.statements.append(if_node); |
| | 2307 | |
| | 2308 | return child_scope->node; |
| | 2309 | } |
| | 2310 | } |
| 2235 | } | 2311 | } |
| 2236 | | 2312 | |
| 2237 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { | 2313 | static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) { |