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
20 * Jürg Billeter <j@bitron.ch>
26 * Represents a type or namespace field.
28 public class Vala
.Field
: Variable
, Lockable
{
30 * Specifies whether this field may only be accessed with an instance of
33 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
36 * Specifies whether the field is volatile. Volatile fields are
37 * necessary to allow multi-threaded access.
39 public bool is_volatile
{ get; set; }
41 private bool lock_used
= false;
44 * Creates a new field.
46 * @param name field name
47 * @param variable_type field type
48 * @param initializer initializer expression
49 * @param source_reference reference to source code
50 * @return newly created field
52 public Field (string name
, DataType variable_type
, Expression? initializer
, SourceReference? source_reference
= null, Comment? comment
= null) {
53 base (variable_type
, name
, initializer
, source_reference
, comment
);
56 public override void accept (CodeVisitor visitor
) {
57 visitor
.visit_field (this
);
60 public override void accept_children (CodeVisitor visitor
) {
61 variable_type
.accept (visitor
);
63 if (initializer
!= null) {
64 initializer
.accept (visitor
);
68 public bool get_lock_used () {
72 public void set_lock_used (bool used
) {
76 public override void replace_expression (Expression old_node
, Expression new_node
) {
77 if (initializer
== old_node
) {
78 initializer
= new_node
;
82 public override void replace_type (DataType old_type
, DataType new_type
) {
83 if (variable_type
== old_type
) {
84 variable_type
= new_type
;
88 public override bool check (CodeContext context
) {
95 var old_source_file
= context
.analyzer
.current_source_file
;
96 var old_symbol
= context
.analyzer
.current_symbol
;
98 if (source_reference
!= null) {
99 context
.analyzer
.current_source_file
= source_reference
.file
;
101 context
.analyzer
.current_symbol
= this
;
103 if (variable_type is VoidType
) {
105 Report
.error (source_reference
, "'void' not supported as field type");
109 variable_type
.check (context
);
111 // check whether field type is at least as accessible as the field
112 if (!context
.analyzer
.is_type_accessible (this
, variable_type
)) {
114 Report
.error (source_reference
, "field type `%s` is less accessible than field `%s`".printf (variable_type
.to_string (), get_full_name ()));
118 if (initializer
!= null) {
119 initializer
.target_type
= variable_type
;
121 if (!initializer
.check (context
)) {
126 if (initializer
.value_type
== null) {
128 Report
.error (source_reference
, "expression type not allowed as initializer");
132 if (!initializer
.value_type
.compatible (variable_type
)) {
134 Report
.error (source_reference
, "Cannot convert from `%s' to `%s'".printf (initializer
.value_type
.to_string (), variable_type
.to_string ()));
138 if (initializer
.value_type
.is_disposable ()) {
139 /* rhs transfers ownership of the expression */
140 if (!(variable_type is PointerType
) && !variable_type
.value_owned
) {
141 /* lhs doesn't own the value */
143 Report
.error (source_reference
, "Invalid assignment from owned expression to unowned variable");
148 if (parent_symbol is Namespace
&& !initializer
.is_constant ()) {
150 Report
.error (source_reference
, "Non-constant field initializers not supported in this context");
154 if (parent_symbol is Namespace
&& initializer
.is_constant () && initializer
.is_non_null ()) {
155 if (variable_type
.is_disposable () && variable_type
.value_owned
) {
157 Report
.error (source_reference
, "Owned namespace fields can only be initialized in a function or method");
162 if (binding
== MemberBinding
.STATIC
&& parent_symbol is Class
&& ((Class
)parent_symbol
).is_compact
&& !initializer
.is_constant ()) {
164 Report
.error (source_reference
, "Static fields in compact classes cannot have non-constant initializers");
170 Report
.error (source_reference
, "External fields cannot use initializers");
174 if (binding
== MemberBinding
.INSTANCE
&& parent_symbol is Interface
) {
176 Report
.error (source_reference
, "Interfaces may not have instance fields");
180 bool field_in_header
= !is_internal_symbol ();
181 if (parent_symbol is Class
) {
182 var cl
= (Class
) parent_symbol
;
183 if (cl
.is_compact
&& !cl
.is_internal_symbol ()) {
184 // compact classes don't have priv structs
185 field_in_header
= true;
189 if (!external_package
&& !hides
&& get_hidden_member () != null) {
190 Report
.warning (source_reference
, "%s hides inherited field `%s'. Use the `new' keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
193 context
.analyzer
.current_source_file
= old_source_file
;
194 context
.analyzer
.current_symbol
= old_symbol
;