Support constructor chain up to GObject using Object (...)
[vala-lang.git] / vala / valapropertyaccessor.vala
blobf9eaa79e9cf5eb82b1862de82c2a305bd6a4b4c5
1 /* valapropertyaccessor.vala
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents a get or set accessor of a property in the source code.
28 public class Vala.PropertyAccessor : Symbol {
29 /**
30 * The corresponding property.
32 public Property prop {
33 get { return parent_symbol as Property; }
36 /**
37 * The property type.
39 public DataType? value_type {
40 get { return _value_type; }
41 set {
42 _value_type = value;
43 if (value != null) {
44 _value_type.parent_node = this;
49 /**
50 * Specifies whether this accessor may be used to get the property.
52 public bool readable { get; set; }
54 /**
55 * Specifies whether this accessor may be used to set the property.
57 public bool writable { get; set; }
59 /**
60 * Specifies whether this accessor may be used to construct the
61 * property.
63 public bool construction { get; set; }
65 /**
66 * The accessor body.
68 public Block? body {
69 get { return _body; }
70 set {
71 _body = value;
72 if (_body != null) {
73 _body.owner = scope;
78 public BasicBlock entry_block { get; set; }
80 public BasicBlock exit_block { get; set; }
82 /**
83 * True if the body was automatically generated
85 public bool automatic_body { get; set; }
87 /**
88 * Represents the generated value parameter in a set accessor.
90 public FormalParameter value_parameter { get; set; }
92 /**
93 * The publicly accessible name of the function that performs the
94 * access in C code.
96 public string get_cname () {
97 if (_cname != null) {
98 return _cname;
101 var t = (TypeSymbol) prop.parent_symbol;
103 if (readable) {
104 return "%sget_%s".printf (t.get_lower_case_cprefix (), prop.name);
105 } else {
106 return "%sset_%s".printf (t.get_lower_case_cprefix (), prop.name);
110 private DataType _value_type;
111 private string? _cname;
112 private Block _body;
115 * Creates a new property accessor.
117 * @param readable true if get accessor, false otherwise
118 * @param writable true if set accessor, false otherwise
119 * @param construction true if construct accessor, false otherwise
120 * @param body accessor body
121 * @param source reference to source code
122 * @return newly created property accessor
124 public PropertyAccessor (bool readable, bool writable, bool construction, DataType? value_type, Block? body, SourceReference? source_reference) {
125 base (null, source_reference);
126 this.readable = readable;
127 this.writable = writable;
128 this.construction = construction;
129 this.value_type = value_type;
130 this.body = body;
133 public override void accept (CodeVisitor visitor) {
134 visitor.visit_property_accessor (this);
137 public override void accept_children (CodeVisitor visitor) {
138 value_type.accept (visitor);
140 if (body != null) {
141 body.accept (visitor);
146 * Process all associated attributes.
148 public void process_attributes () {
149 foreach (Attribute a in attributes) {
150 if (a.name == "CCode") {
151 if (a.has_argument ("cname")) {
152 _cname = a.get_string ("cname");
158 public override bool check (SemanticAnalyzer analyzer) {
159 if (checked) {
160 return !error;
163 checked = true;
165 process_attributes ();
167 if (!value_type.check (analyzer)) {
168 error = true;
169 return false;
172 var old_symbol = analyzer.current_symbol;
174 analyzer.current_symbol = this;
176 if (!prop.external_package) {
177 if (body == null && !prop.interface_only && !prop.is_abstract) {
178 /* no accessor body specified, insert default body */
180 if (prop.parent_symbol is Interface) {
181 error = true;
182 Report.error (source_reference, "Automatic properties can't be used in interfaces");
183 return false;
185 automatic_body = true;
186 body = new Block (source_reference);
187 var ma = new MemberAccess.simple ("_%s".printf (prop.name), source_reference);
188 if (readable) {
189 body.add_statement (new ReturnStatement (ma, source_reference));
190 } else {
191 var assignment = new Assignment (ma, new MemberAccess.simple ("value", source_reference), AssignmentOperator.SIMPLE, source_reference);
192 body.add_statement (new ExpressionStatement (assignment));
197 if (body != null) {
198 if (writable || construction) {
199 value_parameter = new FormalParameter ("value", value_type, source_reference);
200 body.scope.add (value_parameter.name, value_parameter);
203 body.check (analyzer);
205 foreach (DataType body_error_type in body.get_error_types ()) {
206 if (!((ErrorType) body_error_type).dynamic_error) {
207 Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
212 analyzer.current_symbol = old_symbol;
214 return !error;
217 public override void replace_type (DataType old_type, DataType new_type) {
218 if (value_type == old_type) {
219 value_type = new_type;
223 public override List<string> get_cheader_filenames () {
224 return parent_symbol.get_cheader_filenames ();