Commit 85981bf8 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

rename base_types of interfaces to prerequisites to follow GObject

2007-03-04  Jürg Billeter  <j@bitron.ch>

	* vala/parser.y, vala/valainterface.vala,
	  vala/valasemanticanalyzer.vala: rename base_types of interfaces to
	  prerequisites to follow GObject terminology
	* vala/valamethod.vala, vala/valasemanticanalyzer.vala,
	  vala/valacodegenerator.vala: move interface usage part from
	  base_method to base_interface_method property
	* vala/valasemanticanalyzer.vala: don't require interface
	  implementations to specify override
	* vala/valacodegenerator.vala: support base access in interface
	  implementations
	* tests/test-017.vala: remove override in method declaration

svn path=/trunk/; revision=218
parent b90b3037
2007-03-04 Jürg Billeter <j@bitron.ch>
* vala/parser.y, vala/valainterface.vala,
vala/valasemanticanalyzer.vala: rename base_types of interfaces to
prerequisites to follow GObject terminology
* vala/valamethod.vala, vala/valasemanticanalyzer.vala,
vala/valacodegenerator.vala: move interface usage part from
base_method to base_interface_method property
* vala/valasemanticanalyzer.vala: don't require interface
implementations to specify override
* vala/valacodegenerator.vala: support base access in interface
implementations
* tests/test-017.vala: remove override in method declaration
2007-03-04 Jürg Billeter <j@bitron.ch>
* vala/valasemanticanalyzer.vala: support lambda expressions in
......
......@@ -5,7 +5,7 @@ interface Maman.Ibaz {
}
class Maman.Baz : Ibaz {
public override void do_action () {
public void do_action () {
stdout.printf (" 2");
}
......
......@@ -2672,7 +2672,7 @@ interface_declaration
if ($8 != NULL) {
GList *l;
for (l = $8; l != NULL; l = l->next) {
vala_interface_add_base_type (current_interface, l->data);
vala_interface_add_prerequisite (current_interface, l->data);
g_object_unref (l->data);
}
g_list_free ($8);
......
......@@ -484,14 +484,10 @@ public class Vala.CodeGenerator : CodeVisitor {
/* connect overridden methods */
var methods = cl.get_methods ();
foreach (Method m in methods) {
if (!m.is_virtual && !m.overrides) {
if (m.base_method == null) {
continue;
}
var base_type = m.base_method.symbol.parent_symbol.node;
if (base_type is Interface) {
continue;
}
var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
ccast.add_argument (new CCodeIdentifier ("klass"));
......@@ -618,13 +614,26 @@ public class Vala.CodeGenerator : CodeVisitor {
ref CCodeFunctionCall ccall;
/* save pointer to parent vtable */
string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null));
var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*");
var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
parent_var_decl.initializer = new CCodeConstant ("NULL");
parent_decl.add_declarator (parent_var_decl);
parent_decl.modifiers = CCodeModifiers.STATIC;
source_type_member_declaration.append (parent_decl);
ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
ccall.add_argument (new CCodeIdentifier ("iface"));
var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall);
init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
var methods = cl.get_methods ();
foreach (Method m in methods) {
if (!m.overrides) {
if (m.base_interface_method == null) {
continue;
}
var base_type = m.base_method.symbol.parent_symbol.node;
var base_type = m.base_interface_method.symbol.parent_symbol.node;
if (base_type != iface) {
continue;
}
......@@ -1150,16 +1159,20 @@ public class Vala.CodeGenerator : CodeVisitor {
if (m.instance) {
var this_type = new TypeReference ();
this_type.data_type = find_parent_type (m);
if (!m.overrides) {
if (m.base_interface_method != null) {
var base_type = new TypeReference ();
base_type.data_type = (DataType) m.base_interface_method.symbol.parent_symbol.node;
instance_param = new CCodeFormalParameter ("base", base_type.get_cname ());
} else if (m.overrides) {
var base_type = new TypeReference ();
base_type.data_type = (DataType) m.base_method.symbol.parent_symbol.node;
instance_param = new CCodeFormalParameter ("base", base_type.get_cname ());
} else {
if (m.instance_by_reference) {
instance_param = new CCodeFormalParameter ("*self", this_type.get_cname ());
} else {
instance_param = new CCodeFormalParameter ("self", this_type.get_cname ());
}
} else {
var base_type = new TypeReference ();
base_type.data_type = (DataType) m.base_method.symbol.parent_symbol.node;
instance_param = new CCodeFormalParameter ("base", base_type.get_cname ());
}
if (!m.instance_last) {
function.add_parameter (instance_param);
......@@ -1207,7 +1220,7 @@ public class Vala.CodeGenerator : CodeVisitor {
/* real function declaration and definition not needed
* for abstract methods */
if (!m.is_abstract) {
if (m.access != MemberAccessibility.PRIVATE && !(m.is_virtual || m.overrides)) {
if (m.access != MemberAccessibility.PRIVATE && m.base_method == null && m.base_interface_method == null) {
/* public methods need function declaration in
* header file except virtual/overridden methods */
header_type_member_declaration.append (function.copy ());
......@@ -1228,7 +1241,7 @@ public class Vala.CodeGenerator : CodeVisitor {
if (m.symbol.parent_symbol.node is Class) {
var cl = (Class) m.symbol.parent_symbol.node;
if (m.overrides) {
if (m.overrides || m.base_interface_method != null) {
var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccall.add_argument (new CCodeIdentifier ("base"));
......@@ -2562,19 +2575,29 @@ public class Vala.CodeGenerator : CodeVisitor {
if (expr.symbol_reference.node is Method) {
var m = (Method) expr.symbol_reference.node;
if (expr.inner is BaseAccess && (m.is_virtual || m.overrides)) {
var base_class = (Class) m.base_method.symbol.parent_symbol.node;
var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
return;
if (expr.inner is BaseAccess) {
if (m.base_interface_method != null) {
var base_iface = (Interface) m.base_interface_method.symbol.parent_symbol.node;
string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
expr.ccodenode = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), m.name);
return;
} else if (m.base_method != null) {
var base_class = (Class) m.base_method.symbol.parent_symbol.node;
var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
return;
}
}
if (!m.overrides) {
expr.ccodenode = new CCodeIdentifier (m.get_cname ());
} else {
if (m.base_interface_method != null) {
expr.ccodenode = new CCodeIdentifier (m.base_interface_method.get_cname ());
} else if (m.base_method != null) {
expr.ccodenode = new CCodeIdentifier (m.base_method.get_cname ());
} else {
expr.ccodenode = new CCodeIdentifier (m.get_cname ());
}
} else if (expr.symbol_reference.node is ArrayLengthField) {
expr.ccodenode = get_array_length_cexpression (expr.inner, 1);
......@@ -2889,7 +2912,9 @@ public class Vala.CodeGenerator : CodeVisitor {
ref CCodeExpression instance;
if (m != null && m.instance) {
var base_method = m;
if (m.overrides) {
if (m.base_interface_method != null) {
base_method = m.base_interface_method;
} else if (m.base_method != null) {
base_method = m.base_method;
}
......@@ -2897,7 +2922,7 @@ public class Vala.CodeGenerator : CodeVisitor {
if (ma.inner == null) {
instance = new CCodeIdentifier ("self");
/* require casts for overriden and inherited methods */
req_cast = m.overrides || (m.symbol.parent_symbol != current_type_symbol);
req_cast = m.overrides || m.base_interface_method != null || (m.symbol.parent_symbol != current_type_symbol);
} else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* reqiure casts if the type of the used instance is
......
......@@ -28,7 +28,7 @@ using GLib;
public class Vala.Interface : DataType {
private List<TypeParameter> type_parameters;
private List<TypeReference> base_types;
private List<TypeReference> prerequisites;
private List<Method> methods;
private List<Property> properties;
......@@ -62,13 +62,13 @@ public class Vala.Interface : DataType {
}
/**
* Adds the specified interface to the list of prerequisites of this
* interface.
* Adds the specified interface or class to the list of prerequisites of
* this interface.
*
* @param type an interface reference
* @param type an interface or class reference
*/
public void add_base_type (TypeReference! type) {
base_types.append (type);
public void add_prerequisite (TypeReference! type) {
prerequisites.append (type);
}
/**
......@@ -76,8 +76,8 @@ public class Vala.Interface : DataType {
*
* @return list of base types
*/
public ref List<weak TypeReference> get_base_types () {
return base_types.copy ();
public ref List<weak TypeReference> get_prerequisites () {
return prerequisites.copy ();
}
/**
......@@ -182,7 +182,7 @@ public class Vala.Interface : DataType {
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_interface (this);
foreach (TypeReference type in base_types) {
foreach (TypeReference type in prerequisites) {
type.accept (visitor);
}
......@@ -222,9 +222,9 @@ public class Vala.Interface : DataType {
}
public override bool is_subtype_of (DataType! t) {
foreach (TypeReference base_type in base_types) {
if (base_type.data_type == t ||
base_type.data_type.is_subtype_of (t)) {
foreach (TypeReference prerequisite in prerequisites) {
if (prerequisite.data_type == t ||
prerequisite.data_type.is_subtype_of (t)) {
return true;
}
}
......
......@@ -105,6 +105,11 @@ public class Vala.Method : Member, Invokable {
*/
public weak Method base_method { get; set; }
/**
* Specifies the abstract interface method this method implements.
*/
public Method base_interface_method { get; set; }
/**
* Specifies the generated `this' parameter for instance methods.
*/
......@@ -219,7 +224,7 @@ public class Vala.Method : Member, Invokable {
* @return the name to be used in C code
*/
public ref string! get_real_cname () {
if (is_virtual || overrides) {
if (base_method != null || base_interface_method != null) {
var parent = (Class) symbol.parent_symbol.node;
return "%s_real_%s".printf (parent.get_lower_case_cname (null), name);
} else {
......
......@@ -136,8 +136,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public override void visit_begin_interface (Interface! iface) {
current_symbol = iface.symbol;
foreach (TypeReference base_type_reference in iface.get_base_types ()) {
current_source_file.add_symbol_dependency (base_type_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL);
foreach (TypeReference prerequisite_reference in iface.get_prerequisites ()) {
current_source_file.add_symbol_dependency (prerequisite_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL);
}
}
......@@ -178,8 +178,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
private void find_base_method (Method! m, DataType! datatype) {
var sym = datatype.symbol.lookup (m.name);
private void find_base_class_method (Method! m, Class! cl) {
var sym = cl.symbol.lookup (m.name);
if (sym != null && sym.node is Method) {
var base_method = (Method) sym.node;
if (base_method.is_abstract || base_method.is_virtual) {
......@@ -194,21 +194,28 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
if (cl.base_class != null) {
find_base_class_method (m, cl.base_class);
}
}
private void find_base_interface_method (Method! m, Class! cl) {
// FIXME report error if multiple possible base methods are found
if (datatype is Class) {
var cl = (Class) datatype;
foreach (TypeReference type in cl.get_base_types ()) {
find_base_method (m, type.data_type);
if (m.base_method != null) {
return;
}
}
} else {
var iface = (Interface) datatype;
foreach (TypeReference type in iface.get_base_types ()) {
find_base_method (m, type.data_type);
if (m.base_method != null) {
return;
foreach (TypeReference type in cl.get_base_types ()) {
if (type.data_type is Interface) {
var sym = type.data_type.symbol.lookup (m.name);
if (sym != null && sym.node is Method) {
var base_method = (Method) sym.node;
if (base_method.is_abstract) {
if (!m.equals (base_method)) {
m.error = true;
Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.symbol.get_full_name (), base_method.symbol.get_full_name ()));
return;
}
m.base_interface_method = base_method;
return;
}
}
}
}
......@@ -225,13 +232,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
current_return_type = up_method.return_type;
}
if (m.is_virtual || m.overrides) {
if (current_symbol.node is Class) {
find_base_method (m, (Class) current_symbol.node);
if (m.base_method == null) {
Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ()));
if (current_symbol.node is Class) {
if (!(m is CreationMethod)) {
find_base_interface_method (m, (Class) current_symbol.node);
if (m.is_virtual || m.overrides) {
find_base_class_method (m, (Class) current_symbol.node);
if (m.base_method == null) {
// FIXME remove check after interface override transition
if (m.base_interface_method == null) {
Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ()));
}
}
}
} else if (current_symbol.node is Struct) {
}
} else if (current_symbol.node is Struct) {
if (m.is_abstract || m.is_virtual || m.overrides) {
Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.symbol.get_full_name ()));
return;
}
......@@ -785,8 +800,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
} else if (sym.node is Interface) {
var iface = (Interface) sym.node;
foreach (TypeReference base_type in iface.get_base_types ()) {
result = symbol_lookup_inherited (base_type.data_type.symbol, name);
foreach (TypeReference prerequisite in iface.get_prerequisites ()) {
result = symbol_lookup_inherited (prerequisite.data_type.symbol, name);
if (result != null) {
return result;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment