summaryrefslogtreecommitdiff
path: root/vala/valaelementaccess.vala
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2008-11-07 09:07:08 +0000
committerJürg Billeter <juergbi@src.gnome.org>2008-11-07 09:07:08 +0000
commitdb5f3f9062a7dd32a41a37031835e4cecff30656 (patch)
tree8880a12bf9077397cb27c8dec69552565c985bdc /vala/valaelementaccess.vala
parent6f58267f4fecde1c38eacf12340f2f12b311e5ed (diff)
downloadvala-db5f3f9062a7dd32a41a37031835e4cecff30656.tar.gz
Move element access checking to ElementAccess.check
2008-11-07 Jürg Billeter <j@bitron.ch> * vala/valaelementaccess.vala: * vala/valasemanticanalyzer.vala: Move element access checking to ElementAccess.check svn path=/trunk/; revision=1994
Diffstat (limited to 'vala/valaelementaccess.vala')
-rw-r--r--vala/valaelementaccess.vala123
1 files changed, 123 insertions, 0 deletions
diff --git a/vala/valaelementaccess.vala b/vala/valaelementaccess.vala
index 640bd3e31..0734944d4 100644
--- a/vala/valaelementaccess.vala
+++ b/vala/valaelementaccess.vala
@@ -85,4 +85,127 @@ public class Vala.ElementAccess : Expression {
}
return container.is_pure ();
}
+
+ public override bool check (SemanticAnalyzer analyzer) {
+ if (checked) {
+ return !error;
+ }
+
+ checked = true;
+
+ container.accept (analyzer);
+
+ if (container.value_type == null) {
+ /* don't proceed if a child expression failed */
+ error = true;
+ return false;
+ }
+
+ var container_type = container.value_type.data_type;
+
+ if (container is MemberAccess && container.symbol_reference is Signal) {
+ // signal detail access
+ if (get_indices ().size != 1) {
+ error = true;
+ Report.error (source_reference, "Element access with more than one dimension is not supported for signals");
+ return false;
+ }
+ get_indices ().get (0).target_type = analyzer.string_type.copy ();
+ }
+
+ foreach (Expression index in get_indices ()) {
+ index.accept (analyzer);
+ }
+
+ bool index_int_type_check = true;
+
+ var pointer_type = container.value_type as PointerType;
+
+ /* assign a value_type when possible */
+ if (container.value_type is ArrayType) {
+ var array_type = (ArrayType) container.value_type;
+ value_type = array_type.element_type.copy ();
+ if (!lvalue) {
+ value_type.value_owned = false;
+ }
+ } else if (pointer_type != null && !pointer_type.base_type.is_reference_type_or_type_parameter ()) {
+ value_type = pointer_type.base_type.copy ();
+ } else if (container_type == analyzer.string_type.data_type) {
+ if (get_indices ().size != 1) {
+ error = true;
+ Report.error (source_reference, "Element access with more than one dimension is not supported for strings");
+ return false;
+ }
+
+ value_type = analyzer.unichar_type;
+ } else if (container_type != null && analyzer.list_type != null && analyzer.map_type != null &&
+ (container_type.is_subtype_of (analyzer.list_type) || container_type.is_subtype_of (analyzer.map_type))) {
+ Gee.List<Expression> indices = get_indices ();
+ if (indices.size != 1) {
+ error = true;
+ Report.error (source_reference, "Element access with more than one dimension is not supported for the specified type");
+ return false;
+ }
+ Iterator<Expression> indices_it = indices.iterator ();
+ indices_it.next ();
+ var index = indices_it.get ();
+ index_int_type_check = false;
+
+ // lookup symbol in interface instead of class as implemented interface methods are not in VAPI files
+ Symbol get_sym = null;
+ if (container_type.is_subtype_of (analyzer.list_type)) {
+ get_sym = analyzer.list_type.scope.lookup ("get");
+ } else if (container_type.is_subtype_of (analyzer.map_type)) {
+ get_sym = analyzer.map_type.scope.lookup ("get");
+ }
+ var get_method = (Method) get_sym;
+ Gee.List<FormalParameter> get_params = get_method.get_parameters ();
+ Iterator<FormalParameter> get_params_it = get_params.iterator ();
+ get_params_it.next ();
+ var get_param = get_params_it.get ();
+
+ var index_type = get_param.parameter_type;
+ if (index_type.type_parameter != null) {
+ index_type = analyzer.get_actual_type (container.value_type, get_method, get_param.parameter_type, this);
+ }
+
+ if (!index.value_type.compatible (index_type)) {
+ error = true;
+ Report.error (source_reference, "index expression: Cannot convert from `%s' to `%s'".printf (index.value_type.to_string (), index_type.to_string ()));
+ return false;
+ }
+
+ value_type = analyzer.get_actual_type (container.value_type, get_method, get_method.return_type, this).copy ();
+ if (lvalue) {
+ // get () returns owned value, set () accepts unowned value
+ value_type.value_owned = false;
+ }
+ } else if (container is MemberAccess && container.symbol_reference is Signal) {
+ index_int_type_check = false;
+
+ symbol_reference = container.symbol_reference;
+ value_type = container.value_type;
+ } else {
+ error = true;
+ Report.error (source_reference, "The expression `%s' does not denote an Array".printf (container.value_type.to_string ()));
+ }
+
+ if (index_int_type_check) {
+ /* check if the index is of type integer */
+ foreach (Expression e in get_indices ()) {
+ /* don't proceed if a child expression failed */
+ if (e.value_type == null) {
+ return false;
+ }
+
+ /* check if the index is of type integer */
+ if (!(e.value_type.data_type is Struct) || !((Struct) e.value_type.data_type).is_integer_type ()) {
+ error = true;
+ Report.error (e.source_reference, "Expression of integer type expected");
+ }
+ }
+ }
+
+ return !error;
+ }
}