+2006-07-27 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y: don't require developer to explicitly write static in
+ namespace field declarations, support type parameters in interfaces
+ and callbacks
+ * vala/valasymbolresolver.vala: support interfaces and callbacks
+ * vala/valasemanticanalyzer.vala: use is_subtype_of method, support
+ callbacks in fields
+ * vala/valamemorymanager.vala: support callbacks in fields
+ * vala/valacodegenerator.vala: support callbacks in fields
+ * vala/valacallback.vala: support type parameters
+ * vala/valaclass.vala: add is_subtype_of method
+ * vala/valadatatype.vala: add is_subtype_of method
+ * vala/valainterface.vala: add is_subtype_of method
+
2006-07-26 Jürg Billeter <j@bitron.ch>
* vala/scanner.l: support casting arrays
{
/* skip declarations with errors */
if ($1 != NULL) {
+ /* field must be static, don't require developer
+ * to explicitly state it */
+ vala_field_set_instance ($1, FALSE);
+
vala_namespace_add_field (current_namespace, $1);
g_object_unref ($1);
}
if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) {
vala_class_set_is_abstract (current_class, TRUE);
}
- for (l = $8; l != NULL; l = l->next) {
- vala_class_add_type_parameter (current_class, l->data);
- g_object_unref (l->data);
+ if ($8 != NULL) {
+ for (l = $8; l != NULL; l = l->next) {
+ vala_class_add_type_parameter (current_class, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($8);
}
- for (l = $9; l != NULL; l = l->next) {
- vala_class_add_base_type (current_class, l->data);
- g_object_unref (l->data);
+ if ($9 != NULL) {
+ for (l = $9; l != NULL; l = l->next) {
+ vala_class_add_base_type (current_class, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($9);
}
}
class_body
;
interface_declaration
- : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER opt_name_specifier
+ : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER opt_name_specifier opt_type_parameter_list
{
char *name = $5;
current_interface = vala_interface_new (name, src);
g_free (name);
g_object_unref (src);
+
+ if ($7 != NULL) {
+ GList *l;
+ for (l = $7; l != NULL; l = l->next) {
+ vala_interface_add_type_parameter (current_interface, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($7);
+ }
}
interface_body
{
;
callback_declaration
- : comment opt_attributes opt_access_modifier CALLBACK type IDENTIFIER opt_name_specifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON
+ : comment opt_attributes opt_access_modifier CALLBACK type IDENTIFIER opt_name_specifier opt_type_parameter_list OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON
{
GList *l;
char *name = $6;
ValaSourceReference *src = src_com(@6, $1);
$$ = vala_callback_new (name, $5, src);
+ g_free (name);
+ g_object_unref ($5);
g_object_unref (src);
if ($3 != 0) {
VALA_DATA_TYPE($$)->access = $3;
}
VALA_CODE_NODE($$)->attributes = $2;
- for (l = $9; l != NULL; l = l->next) {
- vala_callback_add_parameter ($$, l->data);
- g_object_unref (l->data);
+ if ($8 != NULL) {
+ for (l = $8; l != NULL; l = l->next) {
+ vala_callback_add_type_parameter ($$, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($8);
}
- if ($9 != NULL) {
- g_list_free ($9);
+ if ($10 != NULL) {
+ for (l = $10; l != NULL; l = l->next) {
+ vala_callback_add_parameter ($$, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($10);
}
-
- g_object_unref ($5);
- g_free (name);
}
;
*/
public bool instance { get; set; }
+ private List<TypeParameter> type_parameters;
+
private List<FormalParameter> parameters;
private string cname;
public static ref Callback new (string! name, TypeReference return_type, SourceReference source) {
return (new Callback (name = name, return_type = return_type, source_reference = source));
}
+
+ /**
+ * Appends the specified parameter to the list of type parameters.
+ *
+ * @param p a type parameter
+ */
+ public void add_type_parameter (TypeParameter! p) {
+ type_parameters.append (p);
+ p.type = this;
+ }
/**
* Appends paramater to this callback function.
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_callback (this);
+
+ foreach (TypeParameter p in type_parameters) {
+ p.accept (visitor);
+ }
return_type.accept (visitor);
private bool _has_private_fields;
- List<string> type_parameters;
+ private List<TypeParameter> type_parameters;
private List<TypeReference> base_types;
- List<Constant> constants;
- List<Field> fields;
- List<Method> methods;
- List<Property> properties;
- List<Signal> signals;
+ private List<Constant> constants;
+ private List<Field> fields;
+ private List<Method> methods;
+ private List<Property> properties;
+ private List<Signal> signals;
/**
* Specifies the instance constructor.
public override string get_unref_function () {
return "g_object_unref";
}
+
+ 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)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
var param = (FormalParameter) expr.call.symbol_reference.node;
var cb = (Callback) param.type_reference.data_type;
params = cb.get_parameters ();
+ } else if (expr.call.symbol_reference.node is Field) {
+ var f = (Field) expr.call.symbol_reference.node;
+ var cb = (Callback) f.type_reference.data_type;
+ params = cb.get_parameters ();
} else if (expr.call.symbol_reference.node is Method) {
m = (Method) expr.call.symbol_reference.node;
params = m.get_parameters ();
- } else {
+ } else if (expr.call.symbol_reference.node is Signal) {
var sig = (Signal) expr.call.symbol_reference.node;
params = sig.get_parameters ();
*/
public weak Namespace @namespace;
+ private List<string> cheader_filenames;
+ private Array array_type;
+
/**
* Returns the name of this data type as it is used in C code.
*
cheader_filenames.append (filename);
}
- private List<string> cheader_filenames;
-
- private Array array_type;
/**
- * Retrieves for a given DataType its corresponding Array.
+ * Returns the array type for elements of this data type.
+ *
+ * @return array type for this data type
*/
public Array! get_array () {
if (array_type == null) {
return array_type;
}
+
+ /**
+ * Checks whether this data type is a subtype of the specified data
+ * type.
+ *
+ * @param t a data type
+ * @return true if t is a supertype of this data type, false otherwise
+ */
+ public virtual bool is_subtype_of (DataType! t) {
+ return false;
+ }
}
* Represents a class declaration in the source code.
*/
public class Vala.Interface : DataType {
- List<string> type_parameters;
+ private List<TypeParameter> type_parameters;
+
private List<TypeReference> base_types;
- List<Method> methods;
- List<Property> properties;
- List<Signal> signals;
+ private List<Method> methods;
+ private List<Property> properties;
+ private List<Signal> signals;
/**
* Creates a new interface.
public override string get_unref_function () {
return "g_object_unref";
}
+
+ 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)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
var param = (FormalParameter) msym.node;
var cb = (Callback) param.type_reference.data_type;
params = cb.get_parameters ();
+ } else if (msym.node is Field) {
+ var f = (Field) msym.node;
+ var cb = (Callback) f.type_reference.data_type;
+ params = cb.get_parameters ();
} else if (msym.node is Method) {
var m = (Method) msym.node;
params = m.get_parameters ();
- } else {
+ } else if (msym.node is Signal) {
var sig = (Signal) msym.node;
params = sig.get_parameters ();
}
}
if (stmt.return_expression == null && current_return_type.data_type != null) {
- Report.error (stmt.source_reference, "Return with value in void function");
+ Report.error (stmt.source_reference, "Return without value in non-void function");
return;
}
- if (stmt.return_expression != null && current_return_type.data_type == null) {
- Report.error (stmt.source_reference, "Return without value in non-void function");
+ if (stmt.return_expression != null &&
+ current_return_type.data_type == null &&
+ current_return_type.type_parameter == null) {
+ Report.error (stmt.source_reference, "Return with value in void function");
return;
}
return true;
}
- /* non-class types must match exactly */
- if (!(expression_type.data_type is Class)) {
- return false;
- }
-
- var cl = (Class) expression_type.data_type;
-
- var base_class = cl.base_class;
- for (; base_class != null; base_class = base_class.base_class) {
- if (base_class == expected_type.data_type) {
- return true;
- }
- }
-
- return false;
+ return expression_type.data_type.is_subtype_of (expected_type.data_type);
}
public override void visit_begin_invocation_expression (InvocationExpression! expr) {
Report.error (expr.source_reference, "invocation not supported in this context");
return;
}
+ } else if (msym.node is Field) {
+ var f = (Field) msym.node;
+ if (f.type_reference.data_type is Callback) {
+ var cb = (Callback) f.type_reference.data_type;
+ params = cb.get_parameters ();
+ } else {
+ expr.error = true;
+ Report.error (expr.source_reference, "invocation not supported in this context");
+ return;
+ }
} else if (msym.node is Method) {
var m = (Method) msym.node;
params = m.get_parameters ();
var cb = (Callback) param.type_reference.data_type;
ret_type = cb.return_type;
params = cb.get_parameters ();
+ } else if (msym.node is Field) {
+ var f = (Field) msym.node;
+ var cb = (Callback) f.type_reference.data_type;
+ ret_type = cb.return_type;
+ params = cb.get_parameters ();
} else if (msym.node is Method) {
var m = (Method) msym.node;
ret_type = m.return_type;
current_scope = current_scope.parent_symbol;
}
+ public override void visit_begin_interface (Interface! iface) {
+ current_scope = iface.symbol;
+ }
+
+ public override void visit_end_interface (Interface! iface) {
+ current_scope = current_scope.parent_symbol;
+ }
+
+ public override void visit_begin_callback (Callback! cb) {
+ current_scope = cb.symbol;
+ }
+
+ public override void visit_end_callback (Callback! cb) {
+ current_scope = current_scope.parent_symbol;
+ }
+
public override void visit_formal_parameter (FormalParameter! p) {
if (!p.ellipsis && p.type_reference.is_ref) {
if ((p.type_reference.data_type != null &&