Commit dc6d6847 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

support creating GTypeModule-based plug-ins with the ModuleInit attribute

2007-03-17  Jürg Billeter  <j@bitron.ch>

	* 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
parent caa6e731
2007-03-17 Jürg Billeter <j@bitron.ch>
* 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 <j@bitron.ch>
* vala/parser.y: accept attributes without parentheses
......
......@@ -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);
......
......@@ -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.
*/
......
......@@ -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));
......
/* 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<SourceFile> source_files;
private Symbol! root = new Symbol ();
......
......@@ -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);
}
}
}
......
......@@ -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));
......
......@@ -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);
......
......@@ -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;
}
}
/* 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 {
}
......
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