Commit 8a0f8cc2 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

don't require developer to explicitly write static in namespace field

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

svn path=/trunk/; revision=84
parent 6ba9479f
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
......
......@@ -1511,6 +1511,10 @@ namespace_member_declaration
{
/* 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);
}
......@@ -1560,13 +1564,19 @@ class_declaration
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
......@@ -2207,7 +2217,7 @@ struct_member_declaration
;
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;
......@@ -2228,6 +2238,15 @@ interface_declaration
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
{
......@@ -2390,7 +2409,7 @@ flags_member_declaration
;
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;
......@@ -2410,22 +2429,28 @@ callback_declaration
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);
}
;
......
......@@ -38,6 +38,8 @@ public class Vala.Callback : DataType {
*/
public bool instance { get; set; }
private List<TypeParameter> type_parameters;
private List<FormalParameter> parameters;
private string cname;
......@@ -52,6 +54,16 @@ public class Vala.Callback : DataType {
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.
......@@ -109,6 +121,10 @@ public class Vala.Callback : DataType {
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_callback (this);
foreach (TypeParameter p in type_parameters) {
p.accept (visitor);
}
return_type.accept (visitor);
......
......@@ -52,15 +52,15 @@ public class Vala.Class : DataType {
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.
......@@ -346,4 +346,15 @@ public class Vala.Class : DataType {
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;
}
}
......@@ -1776,10 +1776,14 @@ public class Vala.CodeGenerator : CodeVisitor {
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 ();
......
......@@ -46,6 +46,9 @@ public abstract class Vala.DataType : CodeNode {
*/
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.
*
......@@ -192,11 +195,10 @@ public abstract class Vala.DataType : CodeNode {
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) {
......@@ -213,4 +215,15 @@ public abstract class Vala.DataType : CodeNode {
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;
}
}
......@@ -26,12 +26,13 @@ using GLib;
* 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.
......@@ -199,4 +200,15 @@ public class Vala.Interface : DataType {
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;
}
}
......@@ -131,10 +131,14 @@ public class Vala.MemoryManager : CodeVisitor {
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 ();
}
......
......@@ -381,12 +381,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
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;
}
......@@ -655,21 +657,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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) {
......@@ -703,6 +691,16 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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 ();
......@@ -753,6 +751,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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;
......
......@@ -93,6 +93,22 @@ public class Vala.SymbolResolver : CodeVisitor {
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 &&
......
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