[vala/wip/transform: 39/99] Move BinaryExpression transformation to the code transformer



commit e06a42ce8417857f1bbdc25ef5d41aa2d56bf4e9
Author: Luca Bruno <lucabru src gnome org>
Date:   Wed Jan 4 23:59:34 2012 +0100

    Move BinaryExpression transformation to the code transformer

 codegen/valaccodetransformer.vala    |   48 +++++++++++++-
 codegen/valagvarianttransformer.vala |    4 +
 vala/valabinaryexpression.vala       |  118 ++--------------------------------
 vala/valaforeachstatement.vala       |   16 ++--
 4 files changed, 64 insertions(+), 122 deletions(-)
---
diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala
index f9ef7ff..51c3540 100644
--- a/codegen/valaccodetransformer.vala
+++ b/codegen/valaccodetransformer.vala
@@ -297,7 +297,7 @@ public class Vala.CCodeTransformer : CodeTransformer {
                        break;
                case ForeachIteration.INDEX:
                        // get()+size
-                       var size = b.add_temp_declaration (null, expression ("$collection.size"));
+                       var size = b.add_temp_declaration (null, expression (@"$collection.size"));
                        var i = b.add_temp_declaration (null, expression ("0"));
                        b.open_for (null, expression (@"$i < $size"), expression (@"$i++"));
                        stmt.element_variable.initializer = expression (@"$collection.get ($i)");
@@ -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_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 26a521a..ef3c2c2 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 70721b8..8a81e6c 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -148,112 +148,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_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;
-
-                       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;
-                       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;
-                               }
-                       } 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 temp_access = SemanticAnalyzer.create_temp_access (local, target_type);
-
-                       parent_node.replace_expression (this, temp_access);
-
-                       temp_access.check (context);
-
-                       return true;
-               }
-
                if (!left.check (context) || !right.check (context)) {
                        /* if there were any errors in inner expressions, skip type check */
                        error = true;
@@ -288,7 +182,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
 
@@ -481,15 +379,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 bbdcb45..08844fa 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -157,7 +157,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 (collection_type.compatible (context.analyzer.glist_type) || 
collection_type.compatible (context.analyzer.gslist_type)) {
                        if (collection_type.get_type_arguments ().size != 1) {
                                error = true;
@@ -166,10 +166,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 (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);
                }
@@ -201,7 +201,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;
                }
 
@@ -252,7 +252,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;
                        }
 
@@ -286,7 +286,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;
                        }
 
@@ -296,7 +296,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
@@ -305,7 +305,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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]