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; }
43 private bool lock_used
= false;
46 * Creates a new field.
48 * @param name field name
49 * @param type field type
50 * @param init initializer expression
51 * @param source reference to source code
52 * @return newly created field
54 public Field (string name
, DataType variable_type
, Expression? initializer
, SourceReference? source_reference
= null, Comment? comment
= null) {
55 base (variable_type
, name
, initializer
, source_reference
, comment
);
58 public override void accept (CodeVisitor visitor
) {
59 visitor
.visit_field (this
);
62 public override void accept_children (CodeVisitor visitor
) {
63 variable_type
.accept (visitor
);
65 if (initializer
!= null) {
66 initializer
.accept (visitor
);
71 * Returns the name of this field as it is used in C code.
73 * @return the name to be used in C code
75 public string get_cname () {
77 cname
= get_default_cname ();
83 * Sets the name of this field as it is used in C code.
85 * @param cname the name to be used in C code
87 public void set_cname (string cname
) {
92 * Returns the default name of this field as it is used in C code.
94 * @return the name to be used in C code by default
96 public string get_default_cname () {
97 if (binding
== MemberBinding
.STATIC
) {
98 return parent_symbol
.get_lower_case_cprefix () + name
;
104 private void process_ccode_attribute (Attribute a
) {
105 if (a
.has_argument ("cname")) {
106 set_cname (a
.get_string ("cname"));
108 if (a
.has_argument ("cheader_filename")) {
109 var val
= a
.get_string ("cheader_filename");
110 foreach (string filename
in val
.split (",")) {
111 add_cheader_filename (filename
);
114 if (a
.has_argument ("array_length")) {
115 no_array_length
= !a
.get_bool ("array_length");
117 if (a
.has_argument ("array_null_terminated")) {
118 array_null_terminated
= a
.get_bool ("array_null_terminated");
120 if (a
.has_argument ("array_length_cname")) {
121 set_array_length_cname (a
.get_string ("array_length_cname"));
123 if (a
.has_argument ("array_length_cexpr")) {
124 set_array_length_cexpr (a
.get_string ("array_length_cexpr"));
126 if (a
.has_argument ("array_length_type")) {
127 array_length_type
= a
.get_string ("array_length_type");
129 if (a
.has_argument ("delegate_target")) {
130 no_delegate_target
= !a
.get_bool ("delegate_target");
135 * Process all associated attributes.
137 public override void process_attributes () {
138 base.process_attributes ();
140 foreach (Attribute a
in attributes
) {
141 if (a
.name
== "CCode") {
142 process_ccode_attribute (a
);
143 } else if (a
.name
== "Deprecated") {
144 process_deprecated_attribute (a
);
149 public bool get_lock_used () {
153 public void set_lock_used (bool used
) {
157 public override void replace_expression (Expression old_node
, Expression new_node
) {
158 if (initializer
== old_node
) {
159 initializer
= new_node
;
163 public override void replace_type (DataType old_type
, DataType new_type
) {
164 if (variable_type
== old_type
) {
165 variable_type
= new_type
;
169 public string?
get_ctype () {
170 var attr
= get_attribute ("CCode");
174 return attr
.get_string ("type");
177 public void set_ctype (string ctype
) {
178 var attr
= get_attribute ("CCode");
180 attr
= new
Attribute ("CCode");
181 attributes
.append (attr
);
183 attr
.add_argument ("type", "\"%s\"".printf (ctype
));
186 public override bool check (CodeContext context
) {
193 var old_source_file
= context
.analyzer
.current_source_file
;
194 var old_symbol
= context
.analyzer
.current_symbol
;
196 if (source_reference
!= null) {
197 context
.analyzer
.current_source_file
= source_reference
.file
;
199 context
.analyzer
.current_symbol
= this
;
201 if (variable_type is VoidType
) {
203 Report
.error (source_reference
, "'void' not supported as field type");
207 variable_type
.check (context
);
209 // check whether field type is at least as accessible as the field
210 if (!context
.analyzer
.is_type_accessible (this
, variable_type
)) {
212 Report
.error (source_reference
, "field type `%s` is less accessible than field `%s`".printf (variable_type
.to_string (), get_full_name ()));
216 process_attributes ();
218 if (initializer
!= null) {
219 initializer
.target_type
= variable_type
;
221 if (!initializer
.check (context
)) {
226 if (initializer
.value_type
== null) {
228 Report
.error (source_reference
, "expression type not allowed as initializer");
232 if (!initializer
.value_type
.compatible (variable_type
)) {
234 Report
.error (source_reference
, "Cannot convert from `%s' to `%s'".printf (initializer
.value_type
.to_string (), variable_type
.to_string ()));
240 Report
.error (source_reference
, "External fields cannot use initializers");
244 if (binding
== MemberBinding
.INSTANCE
&& parent_symbol is Interface
) {
246 Report
.error (source_reference
, "Interfaces may not have instance fields");
250 bool field_in_header
= !is_internal_symbol ();
251 if (parent_symbol is Class
) {
252 var cl
= (Class
) parent_symbol
;
253 if (cl
.is_compact
&& !cl
.is_internal_symbol ()) {
254 // compact classes don't have priv structs
255 field_in_header
= true;
259 if (!external_package
&& !hides
&& get_hidden_member () != null) {
260 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 ()));
263 context
.analyzer
.current_source_file
= old_source_file
;
264 context
.analyzer
.current_symbol
= old_symbol
;