3 * Copyright (C) 2006-2008 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>
27 * Represents a type or namespace field.
29 public class Vala
.Field
: Member
, Lockable
{
31 * The data type of this field.
33 public DataType field_type
{
34 get { return _data_type
; }
37 _data_type
.parent_node
= this
;
42 * Specifies the expression to be used to initialize this field.
44 public Expression? initializer
{
45 get { return _initializer
; }
48 if (_initializer
!= null) {
49 _initializer
.parent_node
= this
;
55 * Specifies whether this field may only be accessed with an instance of
58 public MemberBinding binding
{ get; set; default = MemberBinding
.INSTANCE
; }
61 * Specifies whether the field is volatile. Volatile fields are
62 * necessary to allow multi-threaded access.
64 public bool is_volatile
{ get; set; }
67 * Specifies whether an array length field should implicitly be created
68 * if the field type is an array.
70 public bool no_array_length
{ get; set; }
74 private bool lock_used
= false;
76 private Expression _initializer
;
78 private DataType _data_type
;
81 * Creates a new field.
83 * @param name field name
84 * @param type field type
85 * @param init initializer expression
86 * @param source reference to source code
87 * @return newly created field
89 public Field (string name
, DataType field_type
, Expression? initializer
, SourceReference? source_reference
= null) {
90 base (name
, source_reference
);
91 this
.field_type
= field_type
;
92 this
.initializer
= initializer
;
95 public override void accept (CodeVisitor visitor
) {
96 visitor
.visit_member (this
);
98 visitor
.visit_field (this
);
101 public override void accept_children (CodeVisitor visitor
) {
102 field_type
.accept (visitor
);
104 if (initializer
!= null) {
105 initializer
.accept (visitor
);
110 * Returns the name of this field as it is used in C code.
112 * @return the name to be used in C code
114 public string get_cname () {
116 cname
= get_default_cname ();
122 * Sets the name of this field as it is used in C code.
124 * @param cname the name to be used in C code
126 public void set_cname (string cname
) {
131 * Returns the default name of this field as it is used in C code.
133 * @return the name to be used in C code by default
135 public string get_default_cname () {
136 if (binding
== MemberBinding
.STATIC
) {
137 return parent_symbol
.get_lower_case_cprefix () + name
;
143 private void process_ccode_attribute (Attribute a
) {
144 if (a
.has_argument ("cname")) {
145 set_cname (a
.get_string ("cname"));
147 if (a
.has_argument ("cheader_filename")) {
148 var val
= a
.get_string ("cheader_filename");
149 foreach (string filename
in val
.split (",")) {
150 add_cheader_filename (filename
);
156 * Process all associated attributes.
158 public void process_attributes () {
159 foreach (Attribute a
in attributes
) {
160 if (a
.name
== "CCode") {
161 process_ccode_attribute (a
);
162 } else if (a
.name
== "NoArrayLength") {
163 no_array_length
= true;
168 public bool get_lock_used () {
172 public void set_lock_used (bool used
) {
176 public override void replace_type (DataType old_type
, DataType new_type
) {
177 if (field_type
== old_type
) {
178 field_type
= new_type
;
182 public string?
get_ctype () {
183 var attr
= get_attribute ("CCode");
187 return attr
.get_string ("type");
190 public void set_ctype (string ctype
) {
191 var attr
= get_attribute ("CCode");
193 attr
= new
Attribute ("CCode");
194 attributes
.append (attr
);
196 attr
.add_argument ("type", new
StringLiteral ("\"%s\"".printf (ctype
)));
199 public override bool check (SemanticAnalyzer analyzer
) {
206 var old_source_file
= analyzer
.current_source_file
;
208 if (source_reference
!= null) {
209 analyzer
.current_source_file
= source_reference
.file
;
212 field_type
.check (analyzer
);
214 process_attributes ();
216 if (initializer
!= null) {
217 initializer
.target_type
= field_type
;
220 field_type
.check (analyzer
);
222 if (initializer
!= null) {
223 initializer
.check (analyzer
);
226 if (binding
== MemberBinding
.INSTANCE
&& parent_symbol is Interface
) {
228 Report
.error (source_reference
, "Interfaces may not have instance fields");
232 bool field_in_header
= !is_internal_symbol ();
233 if (parent_symbol is Class
) {
234 var cl
= (Class
) parent_symbol
;
235 if (cl
.is_compact
&& !cl
.is_internal_symbol ()) {
236 // compact classes don't have priv structs
237 field_in_header
= true;
241 if (field_in_header
) {
242 if (field_type is ValueType
) {
243 analyzer
.current_source_file
.add_type_dependency (field_type
, SourceFileDependencyType
.HEADER_FULL
);
245 analyzer
.current_source_file
.add_type_dependency (field_type
, SourceFileDependencyType
.HEADER_SHALLOW
);
248 if (parent_symbol is Namespace
) {
250 Report
.error (source_reference
, "Namespaces may not have private members");
254 analyzer
.current_source_file
.add_type_dependency (field_type
, SourceFileDependencyType
.SOURCE
);
257 analyzer
.current_source_file
= old_source_file
;