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
20 * Jürg Billeter <j@bitron.ch>
26 * Represents a local variable declaration in the source code.
28 public class Vala
.LocalVariable
: Symbol
{
30 * The optional initializer expression.
32 public Expression? initializer
{
38 if (_initializer
!= null) {
39 _initializer
.parent_node
= this
;
47 public DataType? variable_type
{
48 get { return _variable_type
; }
50 _variable_type
= value
;
51 if (_variable_type
!= null) {
52 _variable_type
.parent_node
= this
;
58 * Floating variables may only be accessed exactly once.
60 public bool floating
{ get; set; }
62 private Expression? _initializer
;
63 private DataType? _variable_type
;
66 * Creates a new local variable.
68 * @param name name of the variable
69 * @param init optional initializer expression
70 * @param source reference to source code
71 * @return newly created variable declarator
73 public LocalVariable (DataType? variable_type
, string name
, Expression? initializer
= null, SourceReference? source_reference
= null) {
74 base (name
, source_reference
);
75 this
.variable_type
= variable_type
;
76 this
.initializer
= initializer
;
79 public override void accept (CodeVisitor visitor
) {
80 visitor
.visit_local_variable (this
);
83 public override void accept_children (CodeVisitor visitor
) {
84 if (initializer
!= null) {
85 initializer
.accept (visitor
);
87 visitor
.visit_end_full_expression (initializer
);
90 if (variable_type
!= null) {
91 variable_type
.accept (visitor
);
95 public override void replace_expression (Expression old_node
, Expression new_node
) {
96 if (initializer
== old_node
) {
97 initializer
= new_node
;
101 public override void replace_type (DataType old_type
, DataType new_type
) {
102 if (variable_type
== old_type
) {
103 variable_type
= new_type
;
107 public override bool check (SemanticAnalyzer analyzer
) {
114 if (variable_type
!= null) {
115 variable_type
.check (analyzer
);
118 if (initializer
!= null) {
119 initializer
.target_type
= variable_type
;
121 initializer
.check (analyzer
);
124 if (variable_type
== null) {
127 if (initializer
== null) {
129 Report
.error (source_reference
, "var declaration not allowed without initializer");
132 if (initializer
.value_type
== null) {
134 Report
.error (source_reference
, "var declaration not allowed with non-typed initializer");
138 variable_type
= initializer
.value_type
.copy ();
139 variable_type
.value_owned
= true;
140 variable_type
.floating_reference
= false;
142 initializer
.target_type
= variable_type
;
145 if (name
== "result") {
146 // warn if type of `result' variable is incompatible with return type
147 // as an implicit `result' variable might be introduced to be used
148 // by Vala postconditions and implicit checks generated by the code generated
149 if (analyzer
.current_return_type
== null
150 || !variable_type
.compatible (analyzer
.current_return_type
)) {
151 Report
.warning (source_reference
, "result variable type incompatible with return type");
155 if (initializer
!= null) {
156 if (initializer
.value_type
== null) {
157 if (!(initializer is MemberAccess
) && !(initializer is LambdaExpression
)) {
159 Report
.error (source_reference
, "expression type not allowed as initializer");
163 if (initializer
.symbol_reference is Method
&&
164 variable_type is DelegateType
) {
165 var m
= (Method
) initializer
.symbol_reference
;
166 var dt
= (DelegateType
) variable_type
;
167 var cb
= dt
.delegate_symbol
;
169 /* check whether method matches callback type */
170 if (!cb
.matches_method (m
)) {
172 Report
.error (source_reference
, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m
.get_full_name (), cb
.get_full_name ()));
176 initializer
.value_type
= variable_type
;
179 Report
.error (source_reference
, "expression type not allowed as initializer");
184 if (!initializer
.value_type
.compatible (variable_type
)) {
186 Report
.error (source_reference
, "Assignment: Cannot convert from `%s' to `%s'".printf (initializer
.value_type
.to_string (), variable_type
.to_string ()));
190 if (initializer
.value_type
.is_disposable ()) {
191 /* rhs transfers ownership of the expression */
192 if (!(variable_type is PointerType
) && !variable_type
.value_owned
) {
193 /* lhs doesn't own the value */
195 Report
.error (source_reference
, "Invalid assignment from owned expression to unowned variable");
201 analyzer
.current_source_file
.add_type_dependency (variable_type
, SourceFileDependencyType
.SOURCE
);
203 analyzer
.current_symbol
.scope
.add (name
, this
);
205 // current_symbol is a Method if this is the `result'
206 // variable used for postconditions
207 var block
= analyzer
.current_symbol as Block
;
209 block
.add_local_variable (this
);