vala: Allow read-only properties
[vala-gnome.git] / vala / valaconstant.vala
blob0a9266cf178f701560096bb003f6abc93b2fa0d3
1 /* valaconstant.vala
3 * Copyright (C) 2006-2011 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 type member with a constant value.
28 public class Vala.Constant : Symbol {
29 /**
30 * The data type of this constant.
32 public DataType type_reference {
33 get { return _data_type; }
34 set {
35 _data_type = value;
36 _data_type.parent_node = this;
40 /**
41 * The value of this constant.
43 public Expression? value {
44 get { return _value; }
45 set {
46 _value = value;
47 if (_value != null) {
48 _value.parent_node = this;
53 private DataType _data_type;
55 private Expression _value;
57 /**
58 * Creates a new constant.
60 * @param name constant name
61 * @param type_reference constant type
62 * @param value constant value
63 * @param source_reference reference to source code
64 * @return newly created constant
66 public Constant (string name, DataType? type_reference, Expression? value, SourceReference? source_reference, Comment? comment = null) {
67 base (name, source_reference, comment);
68 if (type_reference != null) {
69 this.type_reference = type_reference;
71 this.value = value;
74 public override void accept (CodeVisitor visitor) {
75 visitor.visit_constant (this);
78 public override void accept_children (CodeVisitor visitor) {
79 type_reference.accept (visitor);
81 if (value != null) {
82 value.accept (visitor);
86 public override void replace_expression (Expression old_node, Expression new_node) {
87 if (value == old_node) {
88 value = new_node;
92 public override void replace_type (DataType old_type, DataType new_type) {
93 if (type_reference == old_type) {
94 type_reference = new_type;
98 public override bool check (CodeContext context) {
99 if (checked) {
100 return !error;
103 checked = true;
105 var old_source_file = context.analyzer.current_source_file;
106 var old_symbol = context.analyzer.current_symbol;
108 if (source_reference != null) {
109 context.analyzer.current_source_file = source_reference.file;
111 if (!(parent_symbol is Block)) {
112 // non-local constant
113 context.analyzer.current_symbol = this;
116 type_reference.check (context);
118 if (!check_const_type (type_reference, context)) {
119 error = true;
120 Report.error (source_reference, "`%s' not supported as type for constants".printf (type_reference.to_string ()));
121 return false;
124 if (!external) {
125 if (value == null) {
126 error = true;
127 Report.error (source_reference, "A const field requires a value to be provided");
128 } else {
129 value.target_type = type_reference;
131 if (!value.check (context)) {
132 error = true;
133 return false;
136 if (!value.value_type.compatible (type_reference)) {
137 error = true;
138 Report.error (source_reference, "Cannot convert from `%s' to `%s'".printf (value.value_type.to_string (), type_reference.to_string ()));
139 return false;
142 // support translated string constants for efficiency / convenience
143 // even though the expression is not a compile-time constant
144 var call = value as MethodCall;
145 if (call != null) {
146 var method_type = call.call.value_type as MethodType;
147 if (method_type != null && method_type.method_symbol.get_full_name () == "GLib._") {
148 // first argument is string
149 var literal = call.get_argument_list ().get (0) as StringLiteral;
150 if (literal != null) {
151 value = literal;
152 literal.translate = true;
157 if (!value.is_constant ()) {
158 error = true;
159 Report.error (value.source_reference, "Value must be constant");
160 return false;
163 } else {
164 if (value != null) {
165 error = true;
166 Report.error (source_reference, "External constants cannot use values");
170 if (!external_package && !hides && get_hidden_member () != null) {
171 Report.warning (source_reference, "%s hides inherited constant `%s'. Use the `new' keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
174 context.analyzer.current_source_file = old_source_file;
175 context.analyzer.current_symbol = old_symbol;
177 active = true;
179 return !error;
182 bool check_const_type (DataType type, CodeContext context) {
183 if (type is ValueType) {
184 return true;
185 } else if (type is ArrayType) {
186 var array_type = type as ArrayType;
187 return check_const_type (array_type.element_type, context);
188 } else if (type.data_type.is_subtype_of (context.analyzer.string_type.data_type)) {
189 return true;
190 } else {
191 return false;