LCOV - code coverage report
Current view: top level - vala - valaconditionalexpression.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 75.4 % 114 86
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valaconditionalexpression.vala
       2              :  *
       3              :  * Copyright (C) 2006-2011  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  */
      22              : 
      23              : using GLib;
      24              : 
      25              : /**
      26              :  * Represents a conditional expression in the source code.
      27              :  */
      28         7826 : public class Vala.ConditionalExpression : Expression {
      29              :         /**
      30              :          * The condition.
      31              :          */
      32              :         public Expression condition {
      33        20399 :                 get {
      34        20399 :                         return _condition;
      35              :                 }
      36         6297 :                 private set {
      37        30571 :                         _condition = value;
      38         6297 :                         _condition.parent_node = this;
      39              :                 }
      40              :         }
      41              : 
      42              :         /**
      43              :          * The expression to be evaluated if the condition holds.
      44              :          */
      45              :         public Expression true_expression {
      46        96316 :                 get {
      47        96316 :                         return _true_expression;
      48              :                 }
      49        12137 :                 private set {
      50        24274 :                         _true_expression = value;
      51        12137 :                         _true_expression.parent_node = this;
      52              :                 }
      53              :         }
      54              : 
      55              :         /**
      56              :          * The expression to be evaluated if the condition doesn't hold.
      57              :          */
      58              :         public Expression false_expression {
      59        90451 :                 get {
      60        90451 :                         return _false_expression;
      61              :                 }
      62        12137 :                 private set {
      63        24274 :                         _false_expression = value;
      64        12137 :                         _false_expression.parent_node = this;
      65              :                 }
      66              :         }
      67              : 
      68         6297 :         Expression _condition;
      69         6297 :         Expression _true_expression;
      70         6297 :         Expression _false_expression;
      71              : 
      72              :         /**
      73              :          * Creates a new conditional expression.
      74              :          *
      75              :          * @param cond       a condition
      76              :          * @param true_expr  expression to be evaluated if condition is true
      77              :          * @param false_expr expression to be evaluated if condition is false
      78              :          * @return           newly created conditional expression
      79              :          */
      80        18891 :         public ConditionalExpression (Expression cond, Expression true_expr, Expression false_expr, SourceReference? source = null) {
      81         6297 :                 condition = cond;
      82         6297 :                 true_expression = true_expr;
      83         6297 :                 false_expression = false_expr;
      84         6297 :                 source_reference = source;
      85              :         }
      86              : 
      87        14559 :         public override void accept (CodeVisitor visitor) {
      88        14559 :                 visitor.visit_conditional_expression (this);
      89              : 
      90        14559 :                 visitor.visit_expression (this);
      91              :         }
      92              : 
      93        14559 :         public override void accept_children (CodeVisitor visitor) {
      94        14559 :                 condition.accept (visitor);
      95        14559 :                 true_expression.accept (visitor);
      96        14559 :                 false_expression.accept (visitor);
      97              :         }
      98              : 
      99            0 :         public override bool is_pure () {
     100            0 :                 return condition.is_pure () && true_expression.is_pure () && false_expression.is_pure ();
     101              :         }
     102              : 
     103            0 :         public override bool is_accessible (Symbol sym) {
     104            0 :                 return condition.is_accessible (sym) && true_expression.is_accessible (sym) && false_expression.is_accessible (sym);
     105              :         }
     106              : 
     107            0 :         public override void get_error_types (Collection<DataType> collection, SourceReference? source_reference = null) {
     108            0 :                 condition.get_error_types (collection, source_reference);
     109            0 :                 true_expression.get_error_types (collection, source_reference);
     110            0 :                 false_expression.get_error_types (collection, source_reference);
     111              :         }
     112              : 
     113            0 :         public override string to_string () {
     114            0 :                 return "(%s ? %s : %s)".printf (condition.to_string (), true_expression.to_string (), false_expression.to_string ());
     115              :         }
     116              : 
     117            0 :         public override void replace_expression (Expression old_node, Expression new_node) {
     118            0 :                 if (condition == old_node) {
     119            0 :                         condition = new_node;
     120              :                 }
     121            0 :                 if (true_expression == old_node) {
     122            0 :                         true_expression = new_node;
     123              :                 }
     124            0 :                 if (false_expression == old_node) {
     125            0 :                         false_expression = new_node;
     126              :                 }
     127              :         }
     128              : 
     129            0 :         public override void get_defined_variables (Collection<Variable> collection) {
     130            0 :                 condition.get_defined_variables (collection);
     131            0 :                 true_expression.get_defined_variables (collection);
     132            0 :                 false_expression.get_defined_variables (collection);
     133              :         }
     134              : 
     135            0 :         public override void get_used_variables (Collection<Variable> collection) {
     136            0 :                 condition.get_used_variables (collection);
     137            0 :                 true_expression.get_used_variables (collection);
     138            0 :                 false_expression.get_used_variables (collection);
     139              :         }
     140              : 
     141         5841 :         public override bool check (CodeContext context) {
     142         5841 :                 if (checked) {
     143            0 :                         return !error;
     144              :                 }
     145              : 
     146         5841 :                 checked = true;
     147              : 
     148         5841 :                 if (!(context.analyzer.current_symbol is Block)) {
     149            1 :                         Report.error (source_reference, "Conditional expressions may only be used in blocks");
     150            1 :                         error = true;
     151            1 :                         return false;
     152              :                 }
     153              : 
     154              :                 // convert ternary expression into if statement
     155              :                 // required for flow analysis and exception handling
     156              : 
     157         5840 :                 string temp_name = get_temp_name ();
     158              : 
     159         5840 :                 true_expression.target_type = target_type;
     160         5840 :                 false_expression.target_type = target_type;
     161              : 
     162         5840 :                 var local = new LocalVariable (null, temp_name, null, source_reference);
     163         5840 :                 var decl = new DeclarationStatement (local, source_reference);
     164              : 
     165         5840 :                 var true_local = new LocalVariable (null, temp_name, true_expression, true_expression.source_reference);
     166         5840 :                 var true_block = new Block (true_expression.source_reference);
     167         5840 :                 var true_decl = new DeclarationStatement (true_local, true_expression.source_reference);
     168         5840 :                 true_block.add_statement (true_decl);
     169              : 
     170         5840 :                 var false_local = new LocalVariable (null, temp_name, false_expression, false_expression.source_reference);
     171         5840 :                 var false_block = new Block (false_expression.source_reference);
     172         5840 :                 var false_decl = new DeclarationStatement (false_local, false_expression.source_reference);
     173         5840 :                 false_block.add_statement (false_decl);
     174              : 
     175         5840 :                 var if_stmt = new IfStatement (condition, true_block, false_block, source_reference);
     176              : 
     177         5840 :                 insert_statement (context.analyzer.insert_block, decl);
     178         5840 :                 insert_statement (context.analyzer.insert_block, if_stmt);
     179              : 
     180         5840 :                 if (!if_stmt.check (context) || true_expression.error || false_expression.error) {
     181            0 :                         error = true;
     182            0 :                         return false;
     183              :                 }
     184              : 
     185         5840 :                 true_expression = true_local.initializer;
     186         5840 :                 false_expression = false_local.initializer;
     187              : 
     188         5840 :                 true_block.remove_local_variable (true_local);
     189         5840 :                 false_block.remove_local_variable (false_local);
     190              : 
     191         5840 :                 if (false_expression.value_type.compatible (true_expression.value_type)) {
     192         5832 :                         value_type = true_expression.value_type.copy ();
     193            8 :                 } else if (true_expression.value_type.compatible (false_expression.value_type)) {
     194            7 :                         value_type = false_expression.value_type.copy ();
     195              :                 } else {
     196            1 :                         error = true;
     197            1 :                         var source_reference = new SourceReference (true_expression.source_reference.file, true_expression.source_reference.begin, false_expression.source_reference.end);
     198            1 :                         Report.error (source_reference, "Cannot resolve target type from `%s' and `%s'", true_expression.value_type.to_prototype_string (), false_expression.value_type.to_prototype_string ());
     199            1 :                         return false;
     200              :                 }
     201              : 
     202         5839 :                 value_type.value_owned = (true_expression.value_type.value_owned || false_expression.value_type.value_owned);
     203         5839 :                 value_type.floating_reference = false;
     204         5839 :                 value_type.check (context);
     205              : 
     206         5839 :                 local.variable_type = value_type;
     207         5839 :                 decl.check (context);
     208              : 
     209         5839 :                 true_expression.target_type = value_type;
     210         5839 :                 false_expression.target_type = value_type;
     211              : 
     212         5839 :                 var true_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, true_expression.source_reference), true_expression, AssignmentOperator.SIMPLE, true_expression.source_reference), true_expression.source_reference);
     213              : 
     214         5839 :                 var false_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, false_expression.source_reference), false_expression, AssignmentOperator.SIMPLE, false_expression.source_reference), false_expression.source_reference);
     215              : 
     216         5839 :                 true_block.replace_statement (true_decl, true_stmt);
     217         5839 :                 false_block.replace_statement (false_decl, false_stmt);
     218         5839 :                 true_stmt.check (context);
     219         5839 :                 false_stmt.check (context);
     220              : 
     221         5839 :                 var ma = new MemberAccess.simple (local.name, source_reference);
     222         5839 :                 ma.formal_target_type = formal_target_type;
     223         5839 :                 ma.target_type = target_type;
     224              : 
     225         5839 :                 parent_node.replace_expression (this, ma);
     226         5839 :                 ma.check (context);
     227              : 
     228         5839 :                 return true;
     229              :         }
     230              : }
        

Generated by: LCOV version 2.0-1