Insert "%s" argument in printf calls with non-literal format string
[vala-lang.git] / vala / valalocalvariable.vala
blob917e4b76bc669d6ea6e8d39a332fc2ab49664522
1 /* valalocalvariable.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
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.
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.
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents a local variable declaration in the source code.
28 public class Vala.LocalVariable : Symbol {
29 /**
30 * The optional initializer expression.
32 public Expression? initializer {
33 get {
34 return _initializer;
36 set {
37 _initializer = value;
38 if (_initializer != null) {
39 _initializer.parent_node = this;
44 /**
45 * The variable type.
47 public DataType? variable_type {
48 get { return _variable_type; }
49 set {
50 _variable_type = value;
51 if (_variable_type != null) {
52 _variable_type.parent_node = this;
57 public bool is_result { get; set; }
59 /**
60 * Floating variables may only be accessed exactly once.
62 public bool floating { get; set; }
64 public bool captured { get; set; }
66 public bool no_init { get; set; }
68 private Expression? _initializer;
69 private DataType? _variable_type;
71 /**
72 * Creates a new local variable.
74 * @param name name of the variable
75 * @param init optional initializer expression
76 * @param source reference to source code
77 * @return newly created variable declarator
79 public LocalVariable (DataType? variable_type, string name, Expression? initializer = null, SourceReference? source_reference = null) {
80 base (name, source_reference);
81 this.variable_type = variable_type;
82 this.initializer = initializer;
85 public override void accept (CodeVisitor visitor) {
86 visitor.visit_local_variable (this);
89 public override void accept_children (CodeVisitor visitor) {
90 if (initializer != null) {
91 initializer.accept (visitor);
93 visitor.visit_end_full_expression (initializer);
96 if (variable_type != null) {
97 variable_type.accept (visitor);
101 public override void replace_expression (Expression old_node, Expression new_node) {
102 if (initializer == old_node) {
103 initializer = new_node;
107 public override void replace_type (DataType old_type, DataType new_type) {
108 if (variable_type == old_type) {
109 variable_type = new_type;
113 public override bool check (SemanticAnalyzer analyzer) {
114 if (checked) {
115 return !error;
118 checked = true;
120 if (variable_type != null) {
121 variable_type.check (analyzer);
124 if (initializer != null) {
125 initializer.target_type = variable_type;
127 initializer.check (analyzer);
130 if (variable_type == null) {
131 /* var type */
133 if (initializer == null) {
134 error = true;
135 Report.error (source_reference, "var declaration not allowed without initializer");
136 return false;
138 if (initializer.value_type == null) {
139 error = true;
140 Report.error (source_reference, "var declaration not allowed with non-typed initializer");
141 return false;
144 variable_type = initializer.value_type.copy ();
145 variable_type.value_owned = true;
146 variable_type.floating_reference = false;
148 initializer.target_type = variable_type;
151 if (initializer != null) {
152 if (initializer.value_type == null) {
153 if (!(initializer is MemberAccess) && !(initializer is LambdaExpression)) {
154 error = true;
155 Report.error (source_reference, "expression type not allowed as initializer");
156 return false;
159 if (initializer.symbol_reference is Method &&
160 variable_type is DelegateType) {
161 var m = (Method) initializer.symbol_reference;
162 var dt = (DelegateType) variable_type;
163 var cb = dt.delegate_symbol;
165 /* check whether method matches callback type */
166 if (!cb.matches_method (m)) {
167 error = true;
168 Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
169 return false;
172 initializer.value_type = variable_type;
173 } else {
174 error = true;
175 Report.error (source_reference, "expression type not allowed as initializer");
176 return false;
180 if (!initializer.value_type.compatible (variable_type)) {
181 error = true;
182 Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (initializer.value_type.to_string (), variable_type.to_string ()));
183 return false;
186 if (initializer.value_type.is_disposable ()) {
187 /* rhs transfers ownership of the expression */
188 if (!(variable_type is PointerType) && !variable_type.value_owned) {
189 /* lhs doesn't own the value */
190 error = true;
191 Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
192 return false;
197 analyzer.current_symbol.scope.add (name, this);
199 // current_symbol is a Method if this is the `result'
200 // variable used for postconditions
201 var block = analyzer.current_symbol as Block;
202 if (block != null) {
203 block.add_local_variable (this);
206 active = true;
208 return !error;