From: Jürg Billeter Date: Sat, 17 Mar 2007 14:29:00 +0000 (+0000) Subject: support creating GTypeModule-based plug-ins with the ModuleInit attribute X-Git-Tag: VALA_0_0_8~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dc6d6847095bef7d393f7bb599ad3ceae88ae752;p=thirdparty%2Fvala.git support creating GTypeModule-based plug-ins with the ModuleInit attribute 2007-03-17 Jürg Billeter * vala/valasemanticanalyzer.vala, vala/valacodegnerator.vala, vala/valaclassregisterfunction.vala, vala/valainterfaceregisterfunction.vala, vala/valatyperegisterfunction.vala, vala/valacodecontext.vala: support creating GTypeModule-based plug-ins with the ModuleInit attribute * vala/parser.y, vala/valacodegenerator.vala, vala/valaclass.vala: support static classes * vapi/glib-2.0.vala: add TypePlugin and TypeModule svn path=/trunk/; revision=242 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index ab7073b76..05cbd49fc 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,14 @@ +2007-03-17 Jürg Billeter + + * vala/valasemanticanalyzer.vala, vala/valacodegnerator.vala, + vala/valaclassregisterfunction.vala, + vala/valainterfaceregisterfunction.vala, + vala/valatyperegisterfunction.vala, vala/valacodecontext.vala: support + creating GTypeModule-based plug-ins with the ModuleInit attribute + * vala/parser.y, vala/valacodegenerator.vala, vala/valaclass.vala: + support static classes + * vapi/glib-2.0.vala: add TypePlugin and TypeModule + 2007-03-17 Jürg Billeter * vala/parser.y: accept attributes without parentheses diff --git a/vala/vala/parser.y b/vala/vala/parser.y index af87d5a56..c4dca5d43 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -2210,6 +2210,9 @@ class_declaration if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { vala_class_set_is_abstract (current_class, TRUE); } + if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { + vala_class_set_is_static (current_class, TRUE); + } if ($8 != NULL) { for (l = $8; l != NULL; l = l->next) { vala_class_add_type_parameter (current_class, l->data); diff --git a/vala/vala/valaclass.vala b/vala/vala/valaclass.vala index ca4a4332d..aacf05e71 100644 --- a/vala/vala/valaclass.vala +++ b/vala/vala/valaclass.vala @@ -36,7 +36,13 @@ public class Vala.Class : DataType { * instantiated. */ public bool is_abstract { get; set; } - + + /** + * Specifies whether this class is static. Static classes may not be + * instantiated and may only contain static members. + */ + public bool is_static { get; set; } + /** * Specifies whether this class has private fields. */ diff --git a/vala/vala/valaclassregisterfunction.vala b/vala/vala/valaclassregisterfunction.vala index c6fc43a85..607a04994 100644 --- a/vala/vala/valaclassregisterfunction.vala +++ b/vala/vala/valaclassregisterfunction.vala @@ -94,7 +94,7 @@ public class Vala.ClassRegisterFunction : TypeRegisterFunction { ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer (iface_info_name, new CCodeConstant ("{ (GInterfaceInitFunc) %s_%s_interface_init, (GInterfaceFinalizeFunc) NULL, NULL}".printf (class_reference.get_lower_case_cname (null), iface.get_lower_case_cname (null))))); frag.append (ctypedecl); var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_interface_static")); - reg_call.add_argument (new CCodeIdentifier ("g_define_type_id")); + reg_call.add_argument (new CCodeIdentifier ("%s_type_id".printf (class_reference.get_lower_case_cname (null)))); reg_call.add_argument (new CCodeIdentifier (iface.get_upper_case_cname ("TYPE_"))); reg_call.add_argument (new CCodeIdentifier ("&%s".printf (iface_info_name))); frag.append (new CCodeExpressionStatement (reg_call)); diff --git a/vala/vala/valacodecontext.vala b/vala/vala/valacodecontext.vala index 374cd8eb9..40d64d85b 100644 --- a/vala/vala/valacodecontext.vala +++ b/vala/vala/valacodecontext.vala @@ -1,6 +1,6 @@ /* valacodecontext.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 @@ -34,6 +34,11 @@ public class Vala.CodeContext { */ public string library { get; set; } + /** + * Specifies the optional module initialization method. + */ + public Method module_init_method { get; set; } + List source_files; private Symbol! root = new Symbol (); diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index ad6be31a0..3908e06cd 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -52,6 +52,7 @@ public class Vala.CodeGenerator : CodeVisitor { CCodeFragment instance_init_fragment; CCodeFragment instance_dispose_fragment; CCodeFragment source_signal_marshaller_definition; + CCodeFragment module_init_fragment; CCodeStruct instance_struct; CCodeStruct type_struct; @@ -89,7 +90,11 @@ public class Vala.CodeGenerator : CodeVisitor { DataType list_type; DataType slist_type; TypeReference mutex_type; - + DataType type_module_type; + + private bool in_plugin = false; + private string module_init_param_name; + public CodeGenerator (bool manage_memory = true) { memory_management = manage_memory; } @@ -177,6 +182,19 @@ public class Vala.CodeGenerator : CodeVisitor { mutex_type = new TypeReference (); mutex_type.data_type = (DataType) glib_ns.lookup ("Mutex").node; + + type_module_type = (DataType) glib_ns.lookup ("TypeModule").node; + + if (context.module_init_method != null) { + module_init_fragment = new CCodeFragment (); + foreach (FormalParameter parameter in context.module_init_method.get_parameters ()) { + if (parameter.type_reference.data_type == type_module_type) { + in_plugin = true; + module_init_param_name = parameter.name; + break; + } + } + } /* we're only interested in non-pkg source files */ var source_files = context.get_source_files (); @@ -354,6 +372,10 @@ public class Vala.CodeGenerator : CodeVisitor { current_type_symbol = cl.symbol; current_class = cl; + if (cl.is_static) { + return; + } + instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ())); @@ -406,25 +428,34 @@ public class Vala.CodeGenerator : CodeVisitor { } public override void visit_end_class (Class! cl) { - add_get_property_function (cl); - add_set_property_function (cl); - add_class_init_function (cl); - - foreach (TypeReference base_type in cl.get_base_types ()) { - if (base_type.data_type is Interface) { - add_interface_init_function (cl, (Interface) base_type.data_type); + if (!cl.is_static) { + add_get_property_function (cl); + add_set_property_function (cl); + add_class_init_function (cl); + + foreach (TypeReference base_type in cl.get_base_types ()) { + if (base_type.data_type is Interface) { + add_interface_init_function (cl, (Interface) base_type.data_type); + } + } + + add_instance_init_function (cl); + if (memory_management && cl.get_fields () != null) { + add_dispose_function (cl); + } + + var type_fun = new ClassRegisterFunction (cl); + type_fun.init_from_type (in_plugin); + header_type_member_declaration.append (type_fun.get_declaration ()); + source_type_member_definition.append (type_fun.get_definition ()); + + if (in_plugin) { + // FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types + var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (cl.get_lower_case_cname (null)))); + register_call.add_argument (new CCodeIdentifier (module_init_param_name)); + module_init_fragment.append (new CCodeExpressionStatement (register_call)); } } - - add_instance_init_function (cl); - if (memory_management && cl.get_fields () != null) { - add_dispose_function (cl); - } - - var type_fun = new ClassRegisterFunction (cl); - type_fun.init_from_type (); - header_type_member_declaration.append (type_fun.get_declaration ()); - source_type_member_definition.append (type_fun); current_type_symbol = null; current_class = null; @@ -841,7 +872,7 @@ public class Vala.CodeGenerator : CodeVisitor { var type_fun = new InterfaceRegisterFunction (iface); type_fun.init_from_type (); header_type_member_declaration.append (type_fun.get_declaration ()); - source_type_member_definition.append (type_fun); + source_type_member_definition.append (type_fun.get_definition ()); current_type_symbol = null; } @@ -1356,6 +1387,11 @@ public class Vala.CodeGenerator : CodeVisitor { cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("__params_it", new CCodeIdentifier ("__params"))); cinit.append (cdecl); } + + if (context.module_init_method == m && in_plugin) { + // GTypeModule-based plug-in, register types + cinit.append (module_init_fragment); + } } } diff --git a/vala/vala/valainterfaceregisterfunction.vala b/vala/vala/valainterfaceregisterfunction.vala index cda7b6b61..7b9a94d07 100644 --- a/vala/vala/valainterfaceregisterfunction.vala +++ b/vala/vala/valainterfaceregisterfunction.vala @@ -72,7 +72,7 @@ public class Vala.InterfaceRegisterFunction : TypeRegisterFunction { var prereq = prereq_ref.data_type; var func = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_add_prerequisite")); - func.add_argument (new CCodeIdentifier ("g_define_type_id")); + func.add_argument (new CCodeIdentifier ("%s_type_id".printf (interface_reference.get_lower_case_cname (null)))); func.add_argument (new CCodeIdentifier (prereq.get_type_id())); frag.append (new CCodeExpressionStatement (func)); diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index de18e12a6..766802c51 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -303,7 +303,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor { public override void visit_begin_method (Method! m) { current_symbol = m.symbol; current_return_type = m.return_type; - + + var init_attr = m.get_attribute ("ModuleInit"); + if (init_attr != null) { + m.source_reference.file.context.module_init_method = m; + } + if (m.return_type.data_type != null) { /* is null if it is void or a reference to a type parameter */ current_source_file.add_symbol_dependency (m.return_type.data_type.symbol, SourceFileDependencyType.HEADER_SHALLOW); diff --git a/vala/vala/valatyperegisterfunction.vala b/vala/vala/valatyperegisterfunction.vala index 95501c628..d8a3044af 100644 --- a/vala/vala/valatyperegisterfunction.vala +++ b/vala/vala/valatyperegisterfunction.vala @@ -25,41 +25,80 @@ using GLib; /** * C function to register a type at runtime. */ -public abstract class Vala.TypeRegisterFunction : CCodeFunction { +public abstract class Vala.TypeRegisterFunction { + private CCodeFragment declaration_fragment = new CCodeFragment (); + + private CCodeFragment definition_fragment = new CCodeFragment (); + /** * Constructs the C function from the specified type. */ - public void init_from_type () { - name = "%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)); - return_type = "GType"; + public void init_from_type (bool plugin = false) { + string type_id_name = "%s_type_id".printf (get_type_declaration ().get_lower_case_cname (null)); var type_block = new CCodeBlock (); var cdecl = new CCodeDeclaration ("GType"); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_id", new CCodeConstant ("0"))); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (type_id_name, new CCodeConstant ("0"))); cdecl.modifiers = CCodeModifiers.STATIC; - type_block.add_statement (cdecl); - - var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY")); - cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("g_define_type_id"), new CCodeConstant ("0"))); + if (!plugin) { + type_block.add_statement (cdecl); + } else { + definition_fragment.append (cdecl); + } + + CCodeFunction fun; + if (!plugin) { + fun = new CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType"); + } else { + fun = new CCodeFunction ("%s_register_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType"); + fun.add_parameter (new CCodeFormalParameter ("module", "GTypeModule *")); + + var get_fun = new CCodeFunction ("%s_get_type".printf (get_type_declaration ().get_lower_case_cname (null)), "GType"); + + declaration_fragment.append (get_fun.copy ()); + + get_fun.block = new CCodeBlock (); + get_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name))); + + definition_fragment.append (get_fun); + } + 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) %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")); + CCodeFunctionCall reg_call; + if (!plugin) { + reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static")); + } else { + reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_register_type")); + reg_call.add_argument (new CCodeIdentifier ("module")); + } reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ())); reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_declaration ().get_cname ()))); reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info")); reg_call.add_argument (new CCodeConstant (get_type_flags ())); - type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("g_define_type_id"), reg_call))); + type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call))); type_init.add_statement (get_type_interface_init_statements ()); - - var cif = new CCodeIfStatement (cond, type_init); - type_block.add_statement (cif); - type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("g_define_type_id"))); - block = type_block; + if (!plugin) { + var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY")); + cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0"))); + var cif = new CCodeIfStatement (cond, type_init); + type_block.add_statement (cif); + } else { + type_block = type_init; + } + + type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name))); + + declaration_fragment.append (fun.copy ()); + + fun.block = type_block; + + definition_fragment.append (fun); } /** @@ -130,9 +169,18 @@ public abstract class Vala.TypeRegisterFunction : CCodeFunction { /** * Returns the declaration for this type register function in C code. * - * @return C function declaration + * @return C function declaration fragment + */ + public CCodeFragment! get_declaration () { + return declaration_fragment; + } + + /** + * Returns the definition for this type register function in C code. + * + * @return C function definition fragment */ - public ref CCodeFunction! get_declaration () { - return new CCodeFunction (name, return_type); + public CCodeFragment! get_definition () { + return definition_fragment; } } diff --git a/vala/vapi/glib-2.0.vala b/vala/vapi/glib-2.0.vala index 832f0a5dd..11f637391 100644 --- a/vala/vapi/glib-2.0.vala +++ b/vala/vapi/glib-2.0.vala @@ -1,6 +1,6 @@ /* glib-2.0.vala * - * Copyright (C) 2006 Jürg Billeter, Raffaele Sandrini + * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -251,7 +251,16 @@ namespace GLib { public struct TypeClass { } - + + public interface TypePlugin { + } + + public class TypeModule : TypePlugin { + public bool use (); + public void unuse (); + public void set_name (string! name); + } + [ReferenceType ()] public struct ParamSpec { }