From: Luca Bruno Date: Wed, 4 Jan 2012 22:59:34 +0000 (+0100) Subject: Move BinaryExpression transformation to the code transformer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b314d62308e1fe628e245e3c69cbf9711996277f;p=thirdparty%2Fvala.git Move BinaryExpression transformation to the code transformer --- diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala index ff7d29d8d..6b2eac01b 100644 --- a/codegen/valaccodetransformer.vala +++ b/codegen/valaccodetransformer.vala @@ -441,4 +441,50 @@ public class Vala.CCodeTransformer : CodeTransformer { expr.parent_node.replace_expression (expr, ma); check (ma); } + + public override void visit_binary_expression (BinaryExpression expr) { + Expression replacement = null; + var old_parent_node = expr.parent_node; + var target_type = expr.target_type != null ? expr.target_type.copy () : null; + push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference)); + + if (context.analyzer.get_current_non_local_symbol (expr) is Block + && (expr.operator == BinaryOperator.AND || expr.operator == BinaryOperator.OR)) { + var is_and = expr.operator == BinaryOperator.AND; + var result = b.add_temp_declaration (data_type ("bool")); + b.open_if (expr.left); + if (is_and) { + b.add_assignment (expression (result), expr.right); + } else { + b.add_expression (expression (@"$result = true")); + } + b.add_else (); + if (is_and) { + b.add_expression (expression (@"$result = false")); + } else { + b.add_assignment (expression (result), expr.right); + } + b.close (); + replacement = expression (result); + } else if (expr.operator == BinaryOperator.COALESCE) { + replacement = new ConditionalExpression (new BinaryExpression (BinaryOperator.EQUALITY, expr.left, new NullLiteral (expr.source_reference), expr.source_reference), expr.right, expr.left, expr.source_reference); + } else if (expr.operator == BinaryOperator.IN && !(expr.left.value_type.compatible (context.analyzer.int_type) && expr.right.value_type.compatible (context.analyzer.int_type)) && !(expr.right.value_type is ArrayType)) { + // neither enums nor array, it's contains() + var call = new MethodCall (new MemberAccess (expr.right, "contains", expr.source_reference), expr.source_reference); + call.add_argument (expr.left); + replacement = call; + } + + if (replacement != null) { + replacement.target_type = target_type; + context.analyzer.replaced_nodes.add (expr); + old_parent_node.replace_expression (expr, replacement); + b.check (this); + pop_builder (); + check (replacement); + } else { + pop_builder (); + base.visit_binary_expression (expr); + } + } } diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala index 037ace33a..e8eef326b 100644 --- a/codegen/valagvarianttransformer.vala +++ b/codegen/valagvarianttransformer.vala @@ -533,6 +533,10 @@ public class Vala.GVariantTransformer : CCodeTransformer { } public override void visit_expression (Expression expr) { + if (expr in context.analyzer.replaced_nodes) { + return; + } + if (!(context.profile == Profile.GOBJECT && expr.target_type != null && is_gvariant_type (expr.target_type) && !(expr.value_type is NullType) && !is_gvariant_type (expr.value_type))) { // no implicit gvariant boxing base.visit_expression (expr); diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala index 9075a6cbd..229c44861 100644 --- a/vala/valabinaryexpression.vala +++ b/vala/valabinaryexpression.vala @@ -140,138 +140,6 @@ public class Vala.BinaryExpression : Expression { checked = true; - var insert_block = context.analyzer.get_current_block (this); - - // some expressions are not in a block, - // for example, expressions in method contracts - if (context.analyzer.get_current_non_local_symbol (this) is Block - && (operator == BinaryOperator.AND || operator == BinaryOperator.OR)) { - // convert conditional expression into if statement - // required for flow analysis and exception handling - - var local = new LocalVariable (context.analyzer.bool_type.copy (), get_temp_name (), null, source_reference); - var decl = new DeclarationStatement (local, source_reference); - - var right_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, right.source_reference), right, AssignmentOperator.SIMPLE, right.source_reference), right.source_reference); - - var stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, left.source_reference), new BooleanLiteral ((operator == BinaryOperator.OR), left.source_reference), AssignmentOperator.SIMPLE, left.source_reference), left.source_reference); - - var true_block = new Block (source_reference); - var false_block = new Block (source_reference); - - if (operator == BinaryOperator.AND) { - true_block.add_statement (right_stmt); - false_block.add_statement (stmt); - } else { - true_block.add_statement (stmt); - false_block.add_statement (right_stmt); - } - - var if_stmt = new IfStatement (left, true_block, false_block, source_reference); - - insert_statement (insert_block, decl); - insert_statement (insert_block, if_stmt); - - decl.check (context); - - if (!if_stmt.check (context)) { - error = true; - return false; - } - - var ma = new MemberAccess.simple (local.name, source_reference); - ma.target_type = target_type; - ma.formal_target_type = formal_target_type; - - parent_node.replace_expression (this, ma); - - ma.check (context); - - return true; - } - - if (operator == BinaryOperator.COALESCE) { - if (!left.check (context)) { - error = true; - return false; - } - - if (!right.check (context)) { - error = true; - return false; - } - - DataType local_type = null; - bool cast_non_null = false; - if (left.value_type is NullType && right.value_type != null) { - Report.warning (left.source_reference, "left operand is always null"); - local_type = right.value_type.copy (); - local_type.nullable = true; - if (!right.value_type.nullable) { - cast_non_null = true; - } - } else if (left.value_type != null) { - local_type = left.value_type.copy (); - if (right.value_type != null && right.value_type.value_owned) { - // value owned if either left or right is owned - local_type.value_owned = true; - } - if (context.experimental_non_null) { - if (!local_type.nullable) { - Report.warning (left.source_reference, "left operand is never null"); - if (right.value_type != null && right.value_type.nullable) { - local_type.nullable = true; - cast_non_null = true; - } - } else if (right.value_type != null && !right.value_type.nullable) { - cast_non_null = true; - } - } - } else if (right.value_type != null) { - local_type = right.value_type.copy (); - } - - var local = new LocalVariable (local_type, get_temp_name (), left, source_reference); - var decl = new DeclarationStatement (local, source_reference); - - var right_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, right.source_reference), right, AssignmentOperator.SIMPLE, right.source_reference), right.source_reference); - - var true_block = new Block (source_reference); - - true_block.add_statement (right_stmt); - - var cond = new BinaryExpression (BinaryOperator.EQUALITY, new MemberAccess.simple (local.name, left.source_reference), new NullLiteral (source_reference), source_reference); - - var if_stmt = new IfStatement (cond, true_block, null, source_reference); - - insert_statement (insert_block, decl); - insert_statement (insert_block, if_stmt); - - if (!decl.check (context)) { - error = true; - return false; - } - - if (!if_stmt.check (context)) { - error = true; - return false; - } - - var replace_expr = SemanticAnalyzer.create_temp_access (local, target_type); - if (cast_non_null && replace_expr.target_type != null) { - var cast = new CastExpression.non_null (replace_expr, source_reference); - cast.target_type = replace_expr.target_type.copy (); - cast.target_type.nullable = false; - replace_expr = cast; - } - - parent_node.replace_expression (this, replace_expr); - - replace_expr.check (context); - - return true; - } - // enum-type inference if (target_type != null && target_type.data_type is Enum && (operator == BinaryOperator.BITWISE_AND || operator == BinaryOperator.BITWISE_OR)) { @@ -324,7 +192,11 @@ public class Vala.BinaryExpression : Expression { right.target_type = right.value_type.copy (); right.target_type.value_owned = false; - if (left.value_type.data_type == context.analyzer.string_type.data_type + if (operator == BinaryOperator.COALESCE) { + left.target_type.nullable = true; + right.target_type = left.target_type.copy (); + value_type = left.target_type.copy (); + } else if (left.value_type.data_type == context.analyzer.string_type.data_type && operator == BinaryOperator.PLUS) { // string concatenation @@ -517,15 +389,9 @@ public class Vala.BinaryExpression : Expression { error = true; return false; } - - var contains_call = new MethodCall (new MemberAccess (right, "contains", source_reference), source_reference); - contains_call.add_argument (left); - parent_node.replace_expression (this, contains_call); - return contains_call.check (context); } value_type = context.analyzer.bool_type; - } else { assert_not_reached (); } diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala index acade94b2..f8b3e6cc5 100644 --- a/vala/valaforeachstatement.vala +++ b/vala/valaforeachstatement.vala @@ -158,7 +158,7 @@ public class Vala.ForeachStatement : CodeNode, Statement { array_type.inline_allocated = false; foreach_iteration = ForeachIteration.ARRAY; - error = !analyze_element_type (array_type.element_type); + error = !analyze_element_type (array_type.element_type, false); } else if (context.profile == Profile.GOBJECT && collection_type.compatible (context.analyzer.glist_type) || collection_type.compatible (context.analyzer.gslist_type)) { if (collection_type.get_type_arguments ().size != 1) { error = true; @@ -167,10 +167,10 @@ public class Vala.ForeachStatement : CodeNode, Statement { } foreach_iteration = ForeachIteration.GLIST; - error = !analyze_element_type (collection_type.get_type_arguments ().get (0)); + error = !analyze_element_type (collection_type.get_type_arguments ().get (0), false); } else if (context.profile == Profile.GOBJECT && collection_type.compatible (context.analyzer.gvaluearray_type)) { foreach_iteration = ForeachIteration.GVALUE_ARRAY; - error = !analyze_element_type (context.analyzer.gvalue_type); + error = !analyze_element_type (context.analyzer.gvalue_type, false); } else { error = !check_with_iterator (context, collection_type); } @@ -202,7 +202,7 @@ public class Vala.ForeachStatement : CodeNode, Statement { return false; } - if (!analyze_element_type (element_type)) { + if (!analyze_element_type (element_type, element_type.value_owned)) { return false; } @@ -253,7 +253,7 @@ public class Vala.ForeachStatement : CodeNode, Statement { return false; } - if (!analyze_element_type (element_type)) { + if (!analyze_element_type (element_type, element_type.value_owned)) { return false; } @@ -287,7 +287,7 @@ public class Vala.ForeachStatement : CodeNode, Statement { return false; } - if (!analyze_element_type (element_type)) { + if (!analyze_element_type (element_type, element_type.value_owned)) { return false; } @@ -297,7 +297,7 @@ public class Vala.ForeachStatement : CodeNode, Statement { return true; } - bool analyze_element_type (DataType element_type) { + bool analyze_element_type (DataType element_type, bool get_owned) { // analyze element type if (type_reference == null) { // var type @@ -306,7 +306,7 @@ public class Vala.ForeachStatement : CodeNode, Statement { error = true; Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_type.to_string (), type_reference.to_string ())); return false; - } else if (element_type.is_disposable () && element_type.value_owned && !type_reference.value_owned) { + } else if (get_owned && element_type.is_disposable () && element_type.value_owned && !type_reference.value_owned) { error = true; Report.error (source_reference, "Foreach: Invalid assignment from owned expression to unowned variable"); return false;