+2007-03-11 Jürg Billeter <j@bitron.ch>
+
+ * vala/valasemanticanalyzer.vala: resolve generic return values
+ * vala/valamemorymanager.vala: fix check for generic method parameters
+ to support derived types
+ * vala/valainterface.vala: implement get_type_parameter_index
+ * vala/valamemberaccess.vala: visit type arguments
+ * vala/valaclassregisterfunction.vala,
+ vala/valainterfaceregisterfunction.vala,
+ vala/valatyperegisterfunction.vala: pass base_init function pointer
+ for interfaces
+ * vala/valacodegenerator.vala: fix initialization check in interface
+ base_init function
+ * vala/valasemanticanalyzer.vala: fix prerequisite check to also accept
+ derived types of prerequisites
+
2007-03-10 Jürg Billeter <j@bitron.ch>
* ccode/valaccodecastexpression.vala: correct bracketing in cast
/* valaclassregisterfunction.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-2007 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
public override ref string! get_type_struct_name () {
return "%sClass".printf (class_reference.get_cname ());
}
-
+
+ public override ref string! get_base_init_func_name () {
+ return "NULL";
+ }
+
public override ref string! get_class_init_func_name () {
return "%s_class_init".printf (class_reference.get_lower_case_cname (null));
}
/* make sure not to run the initialization code twice */
base_init.block = new CCodeBlock ();
var decl = new CCodeDeclaration (bool_type.get_cname ());
+ decl.modifiers |= CCodeModifiers.STATIC;
decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("initialized", new CCodeConstant ("FALSE")));
base_init.block.add_statement (decl);
var cif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("initialized")), init_block);
var params = sig.get_parameters ();
if (prefix == null) {
- if (predefined_marshal_list.lookup (signature) != null) {
+ // FIXME remove equality check with cast in next revision
+ if (predefined_marshal_list.lookup (signature) != (bool) null) {
prefix = "g_cclosure_marshal";
} else {
prefix = "g_cclosure_user_marshal";
/* check whether a signal with the same signature already exists for this source file (or predefined) */
signature = get_signal_signature (sig);
- if (predefined_marshal_list.lookup (signature) != null || user_marshal_list.lookup (signature) != null) {
+ // FIXME remove equality checks with cast in next revision
+ if (predefined_marshal_list.lookup (signature) != (bool) null || user_marshal_list.lookup (signature) != (bool) null) {
return;
}
/* valainterface.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-2007 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
return type_id;
}
+
+ public override int get_type_parameter_index (string! name) {
+ int i = 0;
+ foreach (TypeParameter parameter in type_parameters) {
+ if (parameter.name == name) {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+ }
}
public override ref string! get_type_struct_name () {
return interface_reference.get_type_cname ();
}
-
+
+ public override ref string! get_base_init_func_name () {
+ return "%s_base_init".printf (interface_reference.get_lower_case_cname (null));
+ }
+
public override ref string! get_class_init_func_name () {
return "NULL";
}
/* valainvokable.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-2007 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
/**
* Represents a possibly invokable code object.
*/
-public interface Vala.Invokable {
+public interface Vala.Invokable /* : CodeNode */ {
/**
* Returns whether this code object is invokable.
*
/* valamemberaccess.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-2007 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
if (inner != null) {
inner.accept (visitor);
}
+
+ foreach (TypeReference type_arg in type_argument_list) {
+ type_arg.accept (visitor);
+ }
visitor.visit_member_access (this);
}
|| param.type_reference.type_parameter != null)) {
bool is_ref = param.type_reference.takes_ownership;
if (is_ref && param.type_reference.type_parameter != null) {
+ // TODO move this to semantic analyzer
if (expr.call is MemberAccess) {
- var instance_type = ((MemberAccess) expr.call).inner.static_type;
- var param_index = instance_type.data_type.get_type_parameter_index (param.type_reference.type_parameter.name);
+ var ma = (MemberAccess) expr.call;
+ ref TypeReference instance_type = ma.inner.static_type;
+ // trace type arguments back to the datatype where the method has been declared
+ while (instance_type.data_type != msym.parent_symbol.node) {
+ List<weak TypeReference> base_types = null;
+ if (instance_type.data_type is Class) {
+ var cl = (Class) instance_type.data_type;
+ base_types = cl.get_base_types ();
+ } else if (instance_type.data_type is Interface) {
+ var iface = (Interface) instance_type.data_type;
+ base_types = iface.get_prerequisites ();
+ } else {
+ Report.error (expr.source_reference, "internal error: unsupported generic type");
+ expr.error = true;
+ return;
+ }
+ foreach (TypeReference base_type in base_types) {
+ if (SemanticAnalyzer.symbol_lookup_inherited (base_type.data_type.symbol, msym.name) != null) {
+ // construct a new type reference for the base type with correctly linked type arguments
+ var instance_base_type = new TypeReference ();
+ instance_base_type.data_type = base_type.data_type;
+ foreach (TypeReference type_arg in base_type.get_type_arguments ()) {
+ if (type_arg.type_parameter != null) {
+ // link to type argument of derived type
+ int param_index = instance_type.data_type.get_type_parameter_index (type_arg.type_parameter.name);
+ if (param_index == -1) {
+ Report.error (expr.source_reference, "internal error: unknown type parameter %s".printf (type_arg.type_parameter.name));
+ expr.error = true;
+ return;
+ }
+ type_arg = instance_type.get_type_arguments ().nth_data (param_index);
+ }
+ instance_base_type.add_type_argument (type_arg);
+ }
+ instance_type = instance_base_type;
+ }
+ }
+ }
+ if (instance_type.data_type != msym.parent_symbol.node) {
+ Report.error (expr.source_reference, "internal error: generic type parameter tracing not supported yet");
+ expr.error = true;
+ return;
+ }
+ int param_index = instance_type.data_type.get_type_parameter_index (param.type_reference.type_parameter.name);
if (param_index == -1) {
- Report.error (arg.source_reference, "Internal Error: No actual parameter found for `%s' in `%s'".printf (param.name, instance_type.data_type.symbol.get_full_name ()));
+ Report.error (expr.source_reference, "internal error: unknown type parameter %s".printf (param.type_reference.type_parameter.name));
+ expr.error = true;
+ return;
+ }
+ var param_type = (TypeReference) instance_type.get_type_arguments ().nth_data (param_index);
+ if (param_type == null) {
+ Report.error (expr.source_reference, "internal error: no actual argument found for type parameter %s".printf (param.type_reference.type_parameter.name));
+ expr.error = true;
return;
}
- is_ref = ((TypeReference)instance_type.get_type_arguments ().nth_data (param_index)).takes_ownership;
+ is_ref = param_type.takes_ownership;
}
}
return ret.reverse ();
}
+ private bool class_is_a (Class! cl, DataType! t) {
+ if (cl == t) {
+ return true;
+ }
+
+ foreach (TypeReference base_type in cl.get_base_types ()) {
+ if (base_type.data_type is Class) {
+ if (class_is_a ((Class) base_type.data_type, t)) {
+ return true;
+ }
+ } else if (base_type.data_type == t) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
public override void visit_end_class (Class! cl) {
/* gather all prerequisites */
List<DataType> prerequisites = null;
foreach (TypeReference base_type in cl.get_base_types ()) {
if (base_type.data_type is Interface) {
- prerequisites.concat (get_all_prerequisites ((Interface)base_type.data_type));
+ prerequisites.concat (get_all_prerequisites ((Interface) base_type.data_type));
}
}
/* check whether all prerequisites are met */
List<string> missing_prereqs = null;
foreach (DataType prereq in prerequisites) {
- bool found = false;
- foreach (TypeReference base_type in cl.get_base_types ()) {
- if (base_type.data_type == prereq) {
- found = true;
- break;
- }
- }
- if (!found) {
+ if (!class_is_a (cl, prereq)) {
missing_prereqs.prepend (prereq.symbol.get_full_name ());
}
}
return null;
}
- Symbol symbol_lookup_inherited (Symbol! sym, string! name) {
+ public static Symbol symbol_lookup_inherited (Symbol! sym, string! name) {
var result = sym.lookup (name);
if (result != null) {
return result;
var msym = expr.call.symbol_reference;
- TypeReference ret_type;
+ ref TypeReference ret_type;
List<weak FormalParameter> params;
if (msym.node is Invokable) {
var m = (Invokable) msym.node;
ret_type = m.get_return_type ();
params = m.get_parameters ();
+
+ // resolve generic return values
+ if (ret_type.type_parameter != null) {
+ if (!(expr.call is MemberAccess)) {
+ Report.error (((CodeNode) m).source_reference, "internal error: unsupported generic return value");
+ expr.error = true;
+ return;
+ }
+ var ma = (MemberAccess) expr.call;
+ if (ma.inner == null) {
+ // TODO resolve generic return values within the type hierarchy if possible
+ Report.error (expr.source_reference, "internal error: resolving generic return values within type hierarchy not supported yet");
+ expr.error = true;
+ return;
+ } else {
+ ref TypeReference instance_type = ma.inner.static_type;
+ // trace type arguments back to the datatype where the method has been declared
+ while (instance_type.data_type != msym.parent_symbol.node) {
+ List<weak TypeReference> base_types = null;
+ if (instance_type.data_type is Class) {
+ var cl = (Class) instance_type.data_type;
+ base_types = cl.get_base_types ();
+ } else if (instance_type.data_type is Interface) {
+ var iface = (Interface) instance_type.data_type;
+ base_types = iface.get_prerequisites ();
+ } else {
+ Report.error (expr.source_reference, "internal error: unsupported generic type");
+ expr.error = true;
+ return;
+ }
+ foreach (TypeReference base_type in base_types) {
+ if (symbol_lookup_inherited (base_type.data_type.symbol, msym.name) != null) {
+ // construct a new type reference for the base type with correctly linked type arguments
+ var instance_base_type = new TypeReference ();
+ instance_base_type.data_type = base_type.data_type;
+ foreach (TypeReference type_arg in base_type.get_type_arguments ()) {
+ if (type_arg.type_parameter != null) {
+ // link to type argument of derived type
+ int param_index = instance_type.data_type.get_type_parameter_index (type_arg.type_parameter.name);
+ if (param_index == -1) {
+ Report.error (expr.source_reference, "internal error: unknown type parameter %s".printf (type_arg.type_parameter.name));
+ expr.error = true;
+ return;
+ }
+ type_arg = instance_type.get_type_arguments ().nth_data (param_index);
+ }
+ instance_base_type.add_type_argument (type_arg);
+ }
+ instance_type = instance_base_type;
+ }
+ }
+ }
+ if (instance_type.data_type != msym.parent_symbol.node) {
+ Report.error (expr.source_reference, "internal error: generic type parameter tracing not supported yet");
+ expr.error = true;
+ return;
+ }
+ int param_index = instance_type.data_type.get_type_parameter_index (ret_type.type_parameter.name);
+ if (param_index == -1) {
+ Report.error (expr.source_reference, "internal error: unknown type parameter %s".printf (ret_type.type_parameter.name));
+ expr.error = true;
+ return;
+ }
+ ret_type = (TypeReference) instance_type.get_type_arguments ().nth_data (param_index);
+ if (ret_type == null) {
+ Report.error (expr.source_reference, "internal error: no actual argument found for type parameter %s".printf (ret_type.type_parameter.name));
+ expr.error = true;
+ return;
+ }
+ }
+ }
}
expr.static_type = ret_type;
var constructor = (Method) constructor_node;
if (!(constructor_node is CreationMethod)) {
expr.error = true;
- Report.error (expr.source_reference, "`%s' is not a construction method".printf (constructor.symbol.get_full_name ()));
+ Report.error (expr.source_reference, "`%s' is not a creation method".printf (constructor.symbol.get_full_name ()));
return;
}
/* valatyperegisterfunction.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-2007 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
var type_init = new CCodeBlock ();
var ctypedecl = new CCodeDeclaration ("const GTypeInfo");
ctypedecl.modifiers = CCodeModifiers.STATIC;
- ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s }".printf (get_type_struct_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name ()))));
+ ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name ()))));
type_init.add_statement (ctypedecl);
var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static"));
reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
public abstract ref string! get_type_struct_name ();
/**
+ * Returns the name of the base_init function in C code.
+ *
+ * @return C function name
+ */
+ public abstract ref string! get_base_init_func_name ();
+
+ /**
* Returns the name of the class_init function in C code.
*
* @return C function name