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 type or namespace field.
28 public class Vala
.Field
: Member
, Lockable
{
30 * The data type of this field.
32 public DataType field_type
{
33 get { return _data_type
; }
36 _data_type
.parent_node
= this
;
41 * Specifies the expression to be used to initialize this field.
43 public Expression? initializer
{
44 get { return _initializer
; }
47 if (_initializer
!= null) {
48 _initializer
.parent_node
= this
;
54 * Specifies whether this field may only be accessed with an instance of
57 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
60 * Specifies whether the field is volatile. Volatile fields are
61 * necessary to allow multi-threaded access.
63 public bool is_volatile
{ get; set; }
66 * Specifies whether an array length field should implicitly be created
67 * if the field type is an array.
69 public bool no_array_length
{ get; set; }
72 * Specifies whether a delegate target field should implicitly be created
73 * if the field type is a delegate.
75 public bool no_delegate_target
{ get; set; }
78 * Specifies whether the array is null terminated.
80 public bool array_null_terminated
{ get; set; }
83 * Specifies whether the array length field uses a custom name in C.
85 public bool has_array_length_cname
{
86 get { return (array_length_cname
!= null); }
90 * Specifies whether the array uses a custom C expression as length.
92 public bool has_array_length_cexpr
{
93 get { return (array_length_cexpr
!= null); }
96 private string? array_length_cname
;
98 private string? array_length_cexpr
;
100 private string cname
;
102 private bool lock_used
= false;
104 private Expression _initializer
;
106 private DataType _data_type
;
109 * Creates a new field.
111 * @param name field name
112 * @param type field type
113 * @param init initializer expression
114 * @param source reference to source code
115 * @return newly created field
117 public Field (string name
, DataType field_type
, Expression? initializer
, SourceReference? source_reference
= null, Comment? comment
= null) {
118 base (name
, source_reference
, comment
);
119 this
.field_type
= field_type
;
120 this
.initializer
= initializer
;
123 public override void accept (CodeVisitor visitor
) {
124 visitor
.visit_member (this
);
126 visitor
.visit_field (this
);
129 public override void accept_children (CodeVisitor visitor
) {
130 field_type
.accept (visitor
);
132 if (initializer
!= null) {
133 initializer
.accept (visitor
);
138 * Returns the name of this field as it is used in C code.
140 * @return the name to be used in C code
142 public string get_cname () {
144 cname
= get_default_cname ();
150 * Sets the name of this field as it is used in C code.
152 * @param cname the name to be used in C code
154 public void set_cname (string cname
) {
159 * Returns the default name of this field as it is used in C code.
161 * @return the name to be used in C code by default
163 public string get_default_cname () {
164 if (binding
== MemberBinding
.STATIC
) {
165 return parent_symbol
.get_lower_case_cprefix () + name
;
172 * Returns the name of the array length field as it is used in C code
174 * @return the name of the array length field to be used in C code
176 public string?
get_array_length_cname () {
177 return this
.array_length_cname
;
181 * Sets the name of the array length field as it is used in C code
183 * @param array_length_cname the name of the array length field to be
186 public void set_array_length_cname (string? array_length_cname
) {
187 this
.array_length_cname
= array_length_cname
;
191 * Returns the array length expression as it is used in C code
193 * @return the array length expression to be used in C code
195 public string?
get_array_length_cexpr () {
196 return this
.array_length_cexpr
;
201 * Sets the array length expression as it is used in C code
203 * @param array_length_cexpr the array length expression to be used in C
206 public void set_array_length_cexpr (string? array_length_cexpr
) {
207 this
.array_length_cexpr
= array_length_cexpr
;
210 private void process_ccode_attribute (Attribute a
) {
211 if (a
.has_argument ("cname")) {
212 set_cname (a
.get_string ("cname"));
214 if (a
.has_argument ("cheader_filename")) {
215 var val
= a
.get_string ("cheader_filename");
216 foreach (string filename
in val
.split (",")) {
217 add_cheader_filename (filename
);
220 if (a
.has_argument ("array_length")) {
221 no_array_length
= !a
.get_bool ("array_length");
223 if (a
.has_argument ("array_null_terminated")) {
224 array_null_terminated
= a
.get_bool ("array_null_terminated");
226 if (a
.has_argument ("array_length_cname")) {
227 set_array_length_cname (a
.get_string ("array_length_cname"));
229 if (a
.has_argument ("array_length_cexpr")) {
230 set_array_length_cexpr (a
.get_string ("array_length_cexpr"));
232 if (a
.has_argument ("delegate_target")) {
233 no_delegate_target
= !a
.get_bool ("delegate_target");
238 * Process all associated attributes.
240 public void process_attributes () {
241 foreach (Attribute a
in attributes
) {
242 if (a
.name
== "CCode") {
243 process_ccode_attribute (a
);
248 public bool get_lock_used () {
252 public void set_lock_used (bool used
) {
256 public override void replace_expression (Expression old_node
, Expression new_node
) {
257 if (initializer
== old_node
) {
258 initializer
= new_node
;
262 public override void replace_type (DataType old_type
, DataType new_type
) {
263 if (field_type
== old_type
) {
264 field_type
= new_type
;
268 public string?
get_ctype () {
269 var attr
= get_attribute ("CCode");
273 return attr
.get_string ("type");
276 public void set_ctype (string ctype
) {
277 var attr
= get_attribute ("CCode");
279 attr
= new
Attribute ("CCode");
280 attributes
.append (attr
);
282 attr
.add_argument ("type", new
StringLiteral ("\"%s\"".printf (ctype
)));
285 public override bool check (SemanticAnalyzer analyzer
) {
292 var old_source_file
= analyzer
.current_source_file
;
293 var old_symbol
= analyzer
.current_symbol
;
295 if (source_reference
!= null) {
296 analyzer
.current_source_file
= source_reference
.file
;
298 analyzer
.current_symbol
= this
;
300 field_type
.check (analyzer
);
302 // check whether field type is at least as accessible as the field
303 if (!analyzer
.is_type_accessible (this
, field_type
)) {
305 Report
.error (source_reference
, "field type `%s` is less accessible than field `%s`".printf (field_type
.to_string (), get_full_name ()));
309 process_attributes ();
311 if (initializer
!= null) {
312 initializer
.target_type
= field_type
;
314 initializer
.check (analyzer
);
316 if (!initializer
.value_type
.compatible (field_type
)) {
318 Report
.error (source_reference
, "Cannot convert from `%s' to `%s'".printf (initializer
.value_type
.to_string (), field_type
.to_string ()));
324 Report
.error (source_reference
, "External fields cannot use initializers");
328 if (binding
== MemberBinding
.INSTANCE
&& parent_symbol is Interface
) {
330 Report
.error (source_reference
, "Interfaces may not have instance fields");
334 bool field_in_header
= !is_internal_symbol ();
335 if (parent_symbol is Class
) {
336 var cl
= (Class
) parent_symbol
;
337 if (cl
.is_compact
&& !cl
.is_internal_symbol ()) {
338 // compact classes don't have priv structs
339 field_in_header
= true;
343 if (!external_package
&& !hides
&& get_hidden_member () != null) {
344 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 ()));
347 analyzer
.current_source_file
= old_source_file
;
348 analyzer
.current_symbol
= old_symbol
;