Commit c390970c authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter
Browse files

support classes without base class

2007-08-30  Juerg Billeter  <j@bitron.ch>

	* vala/valaclass.vala, vala/valasemanticanalyzer.vala,
	  gobject/valacodegenerator.vala, gobject/valacodegeneratorclass.vala,
	  gobject/valacodegeneratormethod.vala, vapi/glib-2.0.vala: support
	  classes without base class

svn path=/trunk/; revision=537
parent 475ca45f
2007-08-30 Jürg Billeter <j@bitron.ch>
* vala/valaclass.vala, vala/valasemanticanalyzer.vala,
gobject/valacodegenerator.vala, gobject/valacodegeneratorclass.vala,
gobject/valacodegeneratormethod.vala, vapi/glib-2.0.vala: support
classes without base class
2007-08-30 Jürg Billeter <j@bitron.ch>
* vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala,
......
......@@ -1005,7 +1005,7 @@ public class Vala.CodeGenerator : CodeVisitor {
var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL"));
if (type.data_type == null) {
if (!(current_type_symbol is Class)) {
if (!(current_type_symbol is Class) || !current_class.is_subtype_of (gobject_type)) {
return new CCodeConstant ("NULL");
}
......@@ -2375,7 +2375,7 @@ public class Vala.CodeGenerator : CodeVisitor {
var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
if (expr.type_reference.data_type is Class) {
if (expr.type_reference.data_type is Class && expr.type_reference.data_type.is_subtype_of (gobject_type)) {
foreach (TypeReference type_arg in expr.type_reference.get_type_arguments ()) {
if (type_arg.takes_ownership) {
ccall.add_argument (get_dup_func_expression (type_arg));
......
......@@ -38,6 +38,8 @@ public class Vala.CodeGenerator {
current_symbol = cl;
current_type_symbol = cl;
current_class = cl;
bool is_gobject = cl.is_subtype_of (gobject_type);
if (cl.get_cname().len () < 3) {
cl.error = true;
......@@ -67,35 +69,40 @@ public class Vala.CodeGenerator {
decl_frag = source_type_member_declaration;
def_frag = source_type_member_declaration;
}
decl_frag.append (new CCodeNewline ());
var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null));
decl_frag.append (new CCodeMacroReplacement (cl.get_upper_case_cname ("TYPE_"), macro));
if (is_gobject) {
decl_frag.append (new CCodeNewline ());
decl_frag.append (new CCodeMacroReplacement (cl.get_upper_case_cname ("TYPE_"), macro));
macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro));
macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro));
macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));
macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));
macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_"));
decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname ("IS_")), macro));
macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_"));
decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname ("IS_")), macro));
macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_"));
decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), macro));
macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_"));
decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), macro));
macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
decl_frag.append (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
decl_frag.append (new CCodeNewline ());
macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
decl_frag.append (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
decl_frag.append (new CCodeNewline ());
}
if (cl.source_reference.file.cycle == null) {
decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ())));
decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
}
decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
if (cl.is_subtype_of (gobject_type)) {
if (is_gobject) {
if (cl.source_reference.file.cycle == null) {
decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
}
decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
instance_struct.add_field (cl.base_class.get_cname (), "parent");
instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent");
......@@ -105,18 +112,21 @@ public class Vala.CodeGenerator {
def_frag.append (new CCodeComment (cl.source_reference.comment));
}
def_frag.append (instance_struct);
def_frag.append (type_struct);
/* only add the *Private struct if it is not empty, i.e. we actually have private data */
if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
source_type_member_declaration.append (instance_priv_struct);
macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
if (is_gobject) {
def_frag.append (type_struct);
/* only add the *Private struct if it is not empty, i.e. we actually have private data */
if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
source_type_member_declaration.append (instance_priv_struct);
macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
}
source_type_member_declaration.append (prop_enum);
}
source_type_member_declaration.append (prop_enum);
cl.accept_children (this);
if (cl.is_subtype_of (gobject_type)) {
if (is_gobject) {
if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
add_get_property_function (cl);
}
......@@ -151,6 +161,28 @@ public class Vala.CodeGenerator {
register_call.add_argument (new CCodeIdentifier (module_init_param_name));
module_init_fragment.append (new CCodeExpressionStatement (register_call));
}
} else if (cl.default_construction_method != null) {
var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
if (cl.access == MemberAccessibility.PRIVATE) {
function.modifiers = CCodeModifiers.STATIC;
}
function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
decl_frag.append (function.copy ());
var cblock = new CCodeBlock ();
cblock.add_statement (instance_dispose_fragment);
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
ccall.add_argument (new CCodeIdentifier ("self"));
cblock.add_statement (new CCodeExpressionStatement (ccall));
function.block = cblock;
def_frag.append (function);
}
current_type_symbol = old_type_symbol;
......
......@@ -41,7 +41,7 @@ public class Vala.CodeGenerator {
m.accept_children (this);
if (m is CreationMethod) {
if (current_type_symbol is Class && m.body != null) {
if (current_type_symbol is Class && current_class.is_subtype_of (gobject_type) && m.body != null) {
var cblock = new CCodeBlock ();
foreach (CodeNode stmt in m.body.get_statements ()) {
......@@ -127,7 +127,7 @@ public class Vala.CodeGenerator {
}
}
if (m is CreationMethod && current_type_symbol is Class) {
if (m is CreationMethod && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {
// memory management for generic types
foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
function.add_parameter (new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc"));
......@@ -258,7 +258,7 @@ public class Vala.CodeGenerator {
source_type_member_definition.append (function);
if (m is CreationMethod) {
if (current_type_symbol is Class) {
if (current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {
int n_params = ((CreationMethod) m).n_construction_params;
if (n_params > 0) {
......@@ -292,6 +292,13 @@ public class Vala.CodeGenerator {
cassign = new CCodeAssignment (cmember, new CCodeIdentifier (func_name));
function.block.add_statement (new CCodeExpressionStatement (cassign));
}
} else if (current_type_symbol is Class) {
var cl = (Class) m.parent_symbol;
var cdecl = new CCodeDeclaration (cl.get_cname () + "*");
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
cinit.append (cdecl);
} else {
var st = (Struct) m.parent_symbol;
var cdecl = new CCodeDeclaration (st.get_cname () + "*");
......@@ -520,6 +527,21 @@ public class Vala.CodeGenerator {
}
public override void visit_creation_method (CreationMethod! m) {
if (m.body != null && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {
int n_params = 0;
foreach (Statement stmt in m.body.get_statements ()) {
if (!(stmt is ExpressionStatement) || ((ExpressionStatement) stmt).assigned_property () == null) {
m.error = true;
Report.error (stmt.source_reference, "class creation methods only allow property assignment statements");
return;
}
if (((ExpressionStatement) stmt).assigned_property ().set_accessor.construction) {
n_params++;
}
}
m.n_construction_params = n_params;
}
visit_method (m);
}
......
......@@ -397,32 +397,33 @@ public class Vala.Class : DataType {
if (a.has_argument ("ctype")) {
if (a.get_string ("ctype") != "gobject") {
is_gobject = false;
if (a.has_argument ("ref_function")) {
set_ref_function (a.get_string ("ref_function"));
}
if (a.has_argument ("unref_function")) {
set_unref_function (a.get_string ("unref_function"));
}
if (a.has_argument ("copy_function")) {
set_dup_function (a.get_string ("copy_function"));
}
if (a.has_argument ("free_function")) {
set_free_function (a.get_string ("free_function"));
}
if (a.has_argument ("type_id")) {
type_id = a.get_string ("type_id");
}
if (a.has_argument ("marshaller_type_name")) {
marshaller_type_name = a.get_string ("marshaller_type_name");
}
if (a.has_argument ("get_value_function")) {
get_value_function = a.get_string ("get_value_function");
}
if (a.has_argument ("set_value_function")) {
set_value_function = a.get_string ("set_value_function");
}
}
}
if (a.has_argument ("ref_function")) {
set_ref_function (a.get_string ("ref_function"));
}
if (a.has_argument ("unref_function")) {
set_unref_function (a.get_string ("unref_function"));
}
if (a.has_argument ("copy_function")) {
set_dup_function (a.get_string ("copy_function"));
}
if (a.has_argument ("free_function")) {
set_free_function (a.get_string ("free_function"));
}
if (a.has_argument ("type_id")) {
type_id = a.get_string ("type_id");
}
if (a.has_argument ("marshaller_type_name")) {
marshaller_type_name = a.get_string ("marshaller_type_name");
}
if (a.has_argument ("get_value_function")) {
get_value_function = a.get_string ("get_value_function");
}
if (a.has_argument ("set_value_function")) {
set_value_function = a.get_string ("set_value_function");
}
if (a.has_argument ("cname")) {
set_cname (a.get_string ("cname"));
}
......@@ -499,12 +500,12 @@ public class Vala.Class : DataType {
}
public override bool is_reference_counting () {
return is_gobject || (ref_function != null && unref_function != null);
return get_ref_function () != null;
}
public override string get_ref_function () {
if (is_gobject) {
return "g_object_ref";
if (ref_function == null && base_class != null) {
return base_class.get_ref_function ();
} else {
return ref_function;
}
......@@ -515,8 +516,8 @@ public class Vala.Class : DataType {
}
public override string get_unref_function () {
if (is_gobject) {
return "g_object_unref";
if (unref_function == null && base_class != null) {
return base_class.get_unref_function ();
} else {
return unref_function;
}
......
......@@ -466,21 +466,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
Report.error (m.source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ()));
return;
}
if (m.body != null && current_class != null) {
int n_params = 0;
foreach (Statement stmt in m.body.get_statements ()) {
if (!(stmt is ExpressionStatement) || ((ExpressionStatement) stmt).assigned_property () == null) {
m.error = true;
Report.error (stmt.source_reference, "class creation methods only allow property assignment statements");
return;
}
if (((ExpressionStatement) stmt).assigned_property ().set_accessor.construction) {
n_params++;
}
}
m.n_construction_params = n_params;
}
}
public override void visit_formal_parameter (FormalParameter! p) {
......
......@@ -627,7 +627,7 @@ namespace GLib {
public static delegate void ObjectGetPropertyFunc (Object object, uint property_id, Value value, ParamSpec pspec);
public static delegate void ObjectSetPropertyFunc (Object object, uint property_id, Value value, ParamSpec pspec);
[CCode (cheader_filename = "glib-object.h")]
[CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", cheader_filename = "glib-object.h")]
public class Object {
[CCode (cname = "G_TYPE_FROM_INSTANCE")]
public Type get_type ();
......
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