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
;
57 public bool is_result
{ get; set; }
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
;
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
) {
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) {
133 if (initializer
== null) {
135 Report
.error (source_reference
, "var declaration not allowed without initializer");
138 if (initializer
.value_type
== null) {
140 Report
.error (source_reference
, "var declaration not allowed with non-typed initializer");
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
)) {
155 Report
.error (source_reference
, "expression type not allowed as initializer");
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
)) {
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 ()));
172 initializer
.value_type
= variable_type
;
175 Report
.error (source_reference
, "expression type not allowed as initializer");
180 if (!initializer
.value_type
.compatible (variable_type
)) {
182 Report
.error (source_reference
, "Assignment: Cannot convert from `%s' to `%s'".printf (initializer
.value_type
.to_string (), variable_type
.to_string ()));
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 */
191 Report
.error (source_reference
, "Invalid assignment from owned expression to unowned variable");
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
;
203 block
.add_local_variable (this
);