1 /* valacodegeneratorinterface.vala
3 * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
21 * Raffaele Sandrini <rasa@gmx.ch>
26 public class Vala
.CodeGenerator
{
27 public override void visit_interface (Interface
! iface
) {
28 current_symbol
= iface
.symbol
;
29 current_type_symbol
= iface
.symbol
;
31 if (!iface
.is_static
) {
32 type_struct
= new
CCodeStruct ("_%s".printf (iface
.get_type_cname ()));
34 header_type_declaration
.append (new
CCodeNewline ());
35 var macro
= "(%s_get_type ())".printf (iface
.get_lower_case_cname (null));
36 header_type_declaration
.append (new
CCodeMacroReplacement (iface
.get_upper_case_cname ("TYPE_"), macro
));
38 macro
= "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface
.get_upper_case_cname ("TYPE_"), iface
.get_cname ());
39 header_type_declaration
.append (new
CCodeMacroReplacement ("%s(obj)".printf (iface
.get_upper_case_cname (null)), macro
));
41 macro
= "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface
.get_upper_case_cname ("TYPE_"));
42 header_type_declaration
.append (new
CCodeMacroReplacement ("%s(obj)".printf (iface
.get_upper_case_cname ("IS_")), macro
));
44 macro
= "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface
.get_upper_case_cname ("TYPE_"), iface
.get_type_cname ());
45 header_type_declaration
.append (new
CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface
.get_upper_case_cname (null)), macro
));
46 header_type_declaration
.append (new
CCodeNewline ());
49 if (iface
.source_reference
.file
.cycle
== null) {
50 header_type_declaration
.append (new
CCodeTypeDefinition ("struct _%s".printf (iface
.get_cname ()), new
CCodeVariableDeclarator (iface
.get_cname ())));
51 header_type_declaration
.append (new
CCodeTypeDefinition ("struct %s".printf (type_struct
.name
), new
CCodeVariableDeclarator (iface
.get_type_cname ())));
54 type_struct
.add_field ("GTypeInterface", "parent");
56 if (iface
.source_reference
.comment
!= null) {
57 header_type_definition
.append (new
CCodeComment (iface
.source_reference
.comment
));
59 header_type_definition
.append (type_struct
);
62 iface
.accept_children (this
);
64 if (!iface
.is_static
) {
65 add_interface_base_init_function (iface
);
67 var type_fun
= new
InterfaceRegisterFunction (iface
);
68 type_fun
.init_from_type ();
69 header_type_member_declaration
.append (type_fun
.get_declaration ());
70 source_type_member_definition
.append (type_fun
.get_definition ());
73 current_type_symbol
= null;
76 private CCodeFunctionCall
! get_param_spec (Property
! prop
) {
77 var cspec
= new
CCodeFunctionCall ();
78 cspec
.add_argument (prop
.get_canonical_cconstant ());
79 cspec
.add_argument (new
CCodeConstant ("\"foo\""));
80 cspec
.add_argument (new
CCodeConstant ("\"bar\""));
81 if (prop
.type_reference
.data_type is Class
|| prop
.type_reference
.data_type is Interface
) {
82 cspec
.call
= new
CCodeIdentifier ("g_param_spec_object");
83 cspec
.add_argument (new
CCodeIdentifier (prop
.type_reference
.data_type
.get_upper_case_cname ("TYPE_")));
84 } else if (prop
.type_reference
.data_type
== string_type
.data_type
) {
85 cspec
.call
= new
CCodeIdentifier ("g_param_spec_string");
86 cspec
.add_argument (new
CCodeConstant ("NULL"));
87 } else if (prop
.type_reference
.data_type
== int_type
.data_type
88 || prop
.type_reference
.data_type is Enum
) {
89 cspec
.call
= new
CCodeIdentifier ("g_param_spec_int");
90 cspec
.add_argument (new
CCodeConstant ("G_MININT"));
91 cspec
.add_argument (new
CCodeConstant ("G_MAXINT"));
92 cspec
.add_argument (new
CCodeConstant ("0"));
93 } else if (prop
.type_reference
.data_type
== uint_type
.data_type
) {
94 cspec
.call
= new
CCodeIdentifier ("g_param_spec_uint");
95 cspec
.add_argument (new
CCodeConstant ("0"));
96 cspec
.add_argument (new
CCodeConstant ("G_MAXUINT"));
97 cspec
.add_argument (new
CCodeConstant ("0U"));
98 } else if (prop
.type_reference
.data_type
== long_type
.data_type
) {
99 cspec
.call
= new
CCodeIdentifier ("g_param_spec_long");
100 cspec
.add_argument (new
CCodeConstant ("G_MINLONG"));
101 cspec
.add_argument (new
CCodeConstant ("G_MAXLONG"));
102 cspec
.add_argument (new
CCodeConstant ("0L"));
103 } else if (prop
.type_reference
.data_type
== ulong_type
.data_type
) {
104 cspec
.call
= new
CCodeIdentifier ("g_param_spec_ulong");
105 cspec
.add_argument (new
CCodeConstant ("0"));
106 cspec
.add_argument (new
CCodeConstant ("G_MAXULONG"));
107 cspec
.add_argument (new
CCodeConstant ("0UL"));
108 } else if (prop
.type_reference
.data_type
== bool_type
.data_type
) {
109 cspec
.call
= new
CCodeIdentifier ("g_param_spec_boolean");
110 cspec
.add_argument (new
CCodeConstant ("FALSE"));
111 } else if (prop
.type_reference
.data_type
== float_type
.data_type
) {
112 cspec
.call
= new
CCodeIdentifier ("g_param_spec_float");
113 cspec
.add_argument (new
CCodeConstant ("-G_MAXFLOAT"));
114 cspec
.add_argument (new
CCodeConstant ("G_MAXFLOAT"));
115 cspec
.add_argument (new
CCodeConstant ("0.0F"));
116 } else if (prop
.type_reference
.data_type
== double_type
.data_type
) {
117 cspec
.call
= new
CCodeIdentifier ("g_param_spec_double");
118 cspec
.add_argument (new
CCodeConstant ("-G_MAXDOUBLE"));
119 cspec
.add_argument (new
CCodeConstant ("G_MAXDOUBLE"));
120 cspec
.add_argument (new
CCodeConstant ("0.0"));
122 cspec
.call
= new
CCodeIdentifier ("g_param_spec_pointer");
125 var pflags
= "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB";
126 if (prop
.get_accessor
!= null) {
127 pflags
= "%s%s".printf (pflags
, " | G_PARAM_READABLE");
129 if (prop
.set_accessor
!= null) {
130 pflags
= "%s%s".printf (pflags
, " | G_PARAM_WRITABLE");
131 if (prop
.set_accessor
.construction
) {
132 if (prop
.set_accessor
.writable
) {
133 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT");
135 pflags
= "%s%s".printf (pflags
, " | G_PARAM_CONSTRUCT_ONLY");
139 cspec
.add_argument (new
CCodeConstant (pflags
));
144 private CCodeFunctionCall
! get_signal_creation (Signal
! sig
, DataType
! type
) {
145 var csignew
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_new"));
146 csignew
.add_argument (new
CCodeConstant ("\"%s\"".printf (sig
.name
)));
147 csignew
.add_argument (new
CCodeIdentifier (type
.get_upper_case_cname ("TYPE_")));
148 csignew
.add_argument (new
CCodeConstant ("G_SIGNAL_RUN_LAST"));
149 csignew
.add_argument (new
CCodeConstant ("0"));
150 csignew
.add_argument (new
CCodeConstant ("NULL"));
151 csignew
.add_argument (new
CCodeConstant ("NULL"));
153 string marshaller
= get_signal_marshaller_function (sig
);
155 var marshal_arg
= new
CCodeIdentifier (marshaller
);
156 csignew
.add_argument (marshal_arg
);
158 var params
= sig
.get_parameters ();
159 var params_len
= params
.length ();
160 if (sig
.return_type
.type_parameter
!= null) {
161 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
162 } else if (sig
.return_type
.data_type
== null) {
163 csignew
.add_argument (new
CCodeConstant ("G_TYPE_NONE"));
165 csignew
.add_argument (new
CCodeConstant (sig
.return_type
.data_type
.get_type_id ()));
167 csignew
.add_argument (new
CCodeConstant ("%d".printf (params_len
)));
168 foreach (FormalParameter param
in params
) {
169 if (param
.type_reference
.type_parameter
!= null) {
170 csignew
.add_argument (new
CCodeConstant ("G_TYPE_POINTER"));
172 csignew
.add_argument (new
CCodeConstant (param
.type_reference
.data_type
.get_type_id ()));
176 marshal_arg
.name
= marshaller
;
181 private void add_interface_base_init_function (Interface
! iface
) {
182 var base_init
= new
CCodeFunction ("%s_base_init".printf (iface
.get_lower_case_cname (null)), "void");
183 base_init
.add_parameter (new
CCodeFormalParameter ("iface", "%sIface *".printf (iface
.get_cname ())));
184 base_init
.modifiers
= CCodeModifiers
.STATIC
;
186 var init_block
= new
CCodeBlock ();
188 /* make sure not to run the initialization code twice */
189 base_init
.block
= new
CCodeBlock ();
190 var decl
= new
CCodeDeclaration (bool_type
.get_cname ());
191 decl
.modifiers
|= CCodeModifiers
.STATIC
;
192 decl
.add_declarator (new CCodeVariableDeclarator
.with_initializer ("initialized", new
CCodeConstant ("FALSE")));
193 base_init
.block
.add_statement (decl
);
194 var cif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("initialized")), init_block
);
195 base_init
.block
.add_statement (cif
);
196 init_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("initialized"), new
CCodeConstant ("TRUE"))));
198 /* create properties */
199 var props
= iface
.get_properties ();
200 foreach (Property prop
in props
) {
201 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_interface_install_property"));
202 cinst
.add_argument (new
CCodeIdentifier ("iface"));
203 cinst
.add_argument (get_param_spec (prop
));
205 init_block
.add_statement (new
CCodeExpressionStatement (cinst
));
209 foreach (Signal sig
in iface
.get_signals ()) {
210 init_block
.add_statement (new
CCodeExpressionStatement (get_signal_creation (sig
, iface
)));
213 source_type_member_definition
.append (base_init
);