1/* valatypecheck.vala 2 * 3 * Copyright (C) 2006-2010 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 23using GLib; 24 25/** 26 * Represents a type check (`is`) expression in the source code. 27 */ 28public class Vala.TypeCheck : Expression { 29 /** 30 * The expression to be checked. 31 */ 32 public Expression expression { 33 get { return _expression; } 34 set { 35 _expression = value; 36 _expression.parent_node = this; 37 } 38 } 39 40 /** 41 * The type to be matched against. 42 */ 43 public DataType type_reference { 44 get { return _data_type; } 45 set { 46 _data_type = value; 47 _data_type.parent_node = this; 48 } 49 } 50 51 Expression _expression; 52 private DataType _data_type; 53 54 /** 55 * Creates a new type check expression. 56 * 57 * @param expr an expression 58 * @param type a data type 59 * @param source reference to source code 60 * @return newly created type check expression 61 */ 62 public TypeCheck (Expression expr, DataType type, SourceReference? source = null) { 63 expression = expr; 64 type_reference = type; 65 source_reference = source; 66 } 67 68 public override void accept (CodeVisitor visitor) { 69 visitor.visit_type_check (this); 70 71 visitor.visit_expression (this); 72 } 73 74 public override void accept_children (CodeVisitor visitor) { 75 expression.accept (visitor); 76 77 type_reference.accept (visitor); 78 } 79 80 public override bool is_pure () { 81 return expression.is_pure (); 82 } 83 84 public override void replace_type (DataType old_type, DataType new_type) { 85 if (type_reference == old_type) { 86 type_reference = new_type; 87 } 88 } 89 90 public override void replace_expression (Expression old_node, Expression new_node) { 91 if (expression == old_node) { 92 expression = new_node; 93 } 94 } 95 96 public override bool check (CodeContext context) { 97 if (checked) { 98 return !error; 99 } 100 101 checked = true; 102 103 expression.check (context); 104 105 type_reference.check (context); 106 107 if (expression.value_type == null) { 108 Report.error (expression.source_reference, "invalid left operand"); 109 error = true; 110 return false; 111 } 112 113 if (type_reference.type_symbol == null) { 114 /* if type resolving didn't succeed, skip this check */ 115 error = true; 116 return false; 117 } 118 119 if (type_reference is ErrorType && !(expression.value_type is ErrorType)) { 120 Report.error (expression.source_reference, "`%s' must be an error".printf (expression.to_string ())); 121 error = true; 122 return false; 123 } 124 125 if (context.profile == Profile.GOBJECT && type_reference.has_type_arguments ()) { 126 Report.warning (_data_type.source_reference, "Type argument list has no effect"); 127 } 128 129 value_type = context.analyzer.bool_type; 130 131 return !error; 132 } 133 134 public override void emit (CodeGenerator codegen) { 135 expression.emit (codegen); 136 137 codegen.visit_type_check (this); 138 139 codegen.visit_expression (this); 140 } 141 142 public override string to_string () { 143 return "(%s is %s)".printf (expression.to_string (), type_reference.to_string ()); 144 } 145} 146