girparser: Provide default constructor for classes.
[vala-lang.git] / vala / valalocalvariable.vala
blob4fd8daf9f4a75f75a8f874e0052222b056b8445b
1 /* valalocalvariable.vala
3 * Copyright (C) 2006-2010 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 : Variable {
29 public bool is_result { get; set; }
31 /**
32 * Floating variables may only be accessed exactly once.
34 public bool floating { get; set; }
36 public bool captured { get; set; }
38 public bool no_init { get; set; }
40 /**
41 * Creates a new local variable.
43 * @param name name of the variable
44 * @param init optional initializer expression
45 * @param source reference to source code
46 * @return newly created variable declarator
48 public LocalVariable (DataType? variable_type, string name, Expression? initializer = null, SourceReference? source_reference = null) {
49 base (variable_type, name, initializer, source_reference);
52 public override void accept (CodeVisitor visitor) {
53 visitor.visit_local_variable (this);
56 public override void accept_children (CodeVisitor visitor) {
57 if (initializer != null) {
58 initializer.accept (visitor);
60 visitor.visit_end_full_expression (initializer);
63 if (variable_type != null) {
64 variable_type.accept (visitor);
68 public override void replace_expression (Expression old_node, Expression new_node) {
69 if (initializer == old_node) {
70 initializer = new_node;
74 public override void replace_type (DataType old_type, DataType new_type) {
75 if (variable_type == old_type) {
76 variable_type = new_type;
80 public override bool check (CodeContext context) {
81 if (checked) {
82 return !error;
85 checked = true;
87 if (variable_type != null) {
88 if (variable_type is VoidType) {
89 error = true;
90 Report.error (source_reference, "'void' not supported as variable type");
91 return false;
93 variable_type.check (context);
96 if (initializer != null) {
97 initializer.target_type = variable_type;
99 initializer.check (context);
102 if (variable_type == null) {
103 /* var type */
105 if (initializer == null) {
106 error = true;
107 Report.error (source_reference, "var declaration not allowed without initializer");
108 return false;
110 if (initializer.value_type == null) {
111 error = true;
112 Report.error (source_reference, "var declaration not allowed with non-typed initializer");
113 return false;
115 if (initializer.value_type is FieldPrototype) {
116 error = true;
117 Report.error (initializer.source_reference, "Access to instance member `%s' denied".printf (initializer.symbol_reference.get_full_name ()));
118 return false;
121 variable_type = initializer.value_type.copy ();
122 variable_type.value_owned = true;
123 variable_type.floating_reference = false;
125 initializer.target_type = variable_type;
128 if (initializer != null && !initializer.error) {
129 if (initializer.value_type == null) {
130 if (!(initializer is MemberAccess) && !(initializer is LambdaExpression)) {
131 error = true;
132 Report.error (source_reference, "expression type not allowed as initializer");
133 return false;
136 if (initializer.symbol_reference is Method &&
137 variable_type is DelegateType) {
138 var m = (Method) initializer.symbol_reference;
139 var dt = (DelegateType) variable_type;
140 var cb = dt.delegate_symbol;
142 /* check whether method matches callback type */
143 if (!cb.matches_method (m, dt)) {
144 error = true;
145 Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
146 return false;
149 initializer.value_type = variable_type;
150 } else {
151 error = true;
152 Report.error (source_reference, "expression type not allowed as initializer");
153 return false;
157 if (!initializer.value_type.compatible (variable_type)) {
158 error = true;
159 Report.error (source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (initializer.value_type.to_string (), variable_type.to_string ()));
160 return false;
163 if (initializer.value_type.is_disposable ()) {
164 /* rhs transfers ownership of the expression */
165 if (!(variable_type is PointerType) && !variable_type.value_owned) {
166 /* lhs doesn't own the value */
167 error = true;
168 Report.error (source_reference, "Invalid assignment from owned expression to unowned variable");
169 return false;
174 context.analyzer.current_symbol.scope.add (name, this);
176 // current_symbol is a Method if this is the `result'
177 // variable used for postconditions
178 var block = context.analyzer.current_symbol as Block;
179 if (block != null) {
180 block.add_local_variable (this);
183 active = true;
185 return !error;