1/* valabaseaccess.vala
2 *
3 * Copyright (C) 2006-2010  Jürg Billeter
4 *
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.
9
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.
14
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
18 *
19 * Author:
20 * 	Jürg Billeter <j@bitron.ch>
21 */
22
23
24/**
25 * Represents an access to base type member in the source code.
26 */
27public class Vala.BaseAccess : Expression {
28	/**
29	 * Creates a new base access expression.
30	 *
31	 * @param source reference to source code
32	 * @return       newly created base access expression
33	 */
34	public BaseAccess (SourceReference? source = null) {
35		source_reference = source;
36	}
37
38	public override void accept (CodeVisitor visitor) {
39		visitor.visit_base_access (this);
40
41		visitor.visit_expression (this);
42	}
43
44	public override string to_string () {
45		return "base";
46	}
47
48	public override bool is_pure () {
49		return true;
50	}
51
52	public override bool check (CodeContext context) {
53		if (checked) {
54			return !error;
55		}
56
57		checked = true;
58
59		if (!context.analyzer.is_in_instance_method ()) {
60			error = true;
61			Report.error (source_reference, "Base access invalid outside of instance methods");
62			return false;
63		}
64
65		if (context.analyzer.current_class == null) {
66			if (context.analyzer.current_struct == null) {
67				error = true;
68				Report.error (source_reference, "Base access invalid outside of class and struct");
69				return false;
70			} else if (context.analyzer.current_struct.base_type == null) {
71				error = true;
72				Report.error (source_reference, "Base access invalid without base type");
73				return false;
74			}
75			value_type = context.analyzer.current_struct.base_type;
76		} else if (context.analyzer.current_class.base_class == null) {
77			error = true;
78			Report.error (source_reference, "Base access invalid without base class");
79			return false;
80		} else if (context.analyzer.current_class.is_compact && context.analyzer.current_method != null
81		    && !(context.analyzer.current_method is CreationMethod)
82		    && (context.analyzer.current_method.overrides || context.analyzer.current_method.is_virtual)) {
83			error = true;
84			Report.error (source_reference, "Base access invalid in virtual overridden method of compact class");
85			return false;
86		} else if (context.analyzer.current_class.is_compact && context.analyzer.current_property_accessor != null
87		    && (context.analyzer.current_property_accessor.prop.overrides || context.analyzer.current_property_accessor.prop.is_virtual)) {
88			error = true;
89			Report.error (source_reference, "Base access invalid in virtual overridden property of compact class");
90			return false;
91		} else {
92			foreach (var base_type in context.analyzer.current_class.get_base_types ()) {
93				if (base_type.type_symbol is Class) {
94					value_type = base_type.copy ();
95					value_type.value_owned = false;
96				}
97			}
98		}
99
100		symbol_reference = value_type.type_symbol;
101
102		return !error;
103	}
104
105	public override void emit (CodeGenerator codegen) {
106		codegen.visit_base_access (this);
107
108		codegen.visit_expression (this);
109	}
110}
111