1 /* valaccodefunction.vala
3 * Copyright (C) 2006-2012 Jürg Billeter
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.1 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>
26 * Represents a function declaration in the C code.
28 public class Vala
.CCodeFunction
: CCodeNode
{
30 * The name of this function.
32 public string name
{ get; set; }
35 * The function return type.
37 public string return_type
{ get; set; }
39 public bool is_declaration
{ get; set; }
44 public CCodeBlock block
{ get; set; }
47 * The current line directive.
49 public CCodeLineDirective current_line
{ get; set; }
52 * The current block to be written into.
54 public CCodeBlock current_block
{ get; set; }
56 private List
<CCodeParameter
> parameters
= new ArrayList
<CCodeParameter
> ();
58 List
<CCodeStatement
> statement_stack
= new ArrayList
<CCodeStatement
> ();
60 public CCodeFunction (string name
, string return_type
= "void") {
62 this
.return_type
= return_type
;
63 this
.block
= new
CCodeBlock ();
64 current_block
= block
;
68 * Appends the specified parameter to the list of function parameters.
70 * @param param a formal parameter
72 public void add_parameter (CCodeParameter param
) {
73 parameters
.add (param
);
76 public void insert_parameter (int position
, CCodeParameter param
) {
77 parameters
.insert (position
, param
);
80 public int get_parameter_count () {
81 return parameters
.size
;
84 public CCodeParameter
get_parameter (int position
) {
85 return parameters
[position
];
89 * Returns a copy of this function.
91 * @return copied function
93 public CCodeFunction
copy () {
94 var func
= new
CCodeFunction (name
, return_type
);
95 func
.modifiers
= modifiers
;
97 /* no deep copy for lists available yet
98 * func.parameters = parameters.copy ();
100 foreach (CCodeParameter param
in parameters
) {
101 func
.parameters
.add (param
);
104 func
.is_declaration
= is_declaration
;
109 public override void write (CCodeWriter writer
) {
110 writer
.write_indent (line
);
111 if (CCodeModifiers
.INTERNAL
in modifiers
) {
112 writer
.write_string ("G_GNUC_INTERNAL ");
114 if (CCodeModifiers
.STATIC
in modifiers
) {
115 writer
.write_string ("static ");
117 if (CCodeModifiers
.INLINE
in modifiers
) {
118 writer
.write_string ("inline ");
120 writer
.write_string (return_type
);
121 writer
.write_string (" ");
122 writer
.write_string (name
);
123 writer
.write_string (" (");
125 bool has_args
= (CCodeModifiers
.PRINTF
in modifiers
|| CCodeModifiers
.SCANF
in modifiers
);
127 int format_arg_index
= -1;
129 foreach (CCodeParameter param
in parameters
) {
131 writer
.write_string (", ");
133 param
.write (writer
);
134 if (CCodeModifiers
.FORMAT_ARG
in param
.modifiers
) {
135 format_arg_index
= i
;
137 if (has_args
&& param
.ellipsis
) {
139 } else if (has_args
&& param
.type_name
== "va_list" && format_arg_index
< 0) {
140 format_arg_index
= i
- 1;
145 writer
.write_string ("void");
148 writer
.write_string (")");
150 if (is_declaration
) {
151 if (CCodeModifiers
.DEPRECATED
in modifiers
) {
152 writer
.write_string (" G_GNUC_DEPRECATED");
155 if (CCodeModifiers
.PRINTF
in modifiers
) {
156 format_arg_index
= (format_arg_index
>= 0 ? format_arg_index
+ 1 : args_index
);
157 writer
.write_string (" G_GNUC_PRINTF(%d,%d)".printf (format_arg_index
, args_index
+ 1));
158 } else if (CCodeModifiers
.SCANF
in modifiers
) {
159 format_arg_index
= (format_arg_index
>= 0 ? format_arg_index
+ 1 : args_index
);
160 writer
.write_string (" G_GNUC_SCANF(%d,%d)".printf (format_arg_index
, args_index
+ 1));
161 } else if (format_arg_index
>= 0) {
162 writer
.write_string (" G_GNUC_FORMAT(%d)".printf (format_arg_index
+ 1));
165 if (CCodeModifiers
.CONST
in modifiers
) {
166 writer
.write_string (" G_GNUC_CONST");
168 if (CCodeModifiers
.UNUSED
in modifiers
) {
169 writer
.write_string (" G_GNUC_UNUSED");
172 if (CCodeModifiers
.CONSTRUCTOR
in modifiers
) {
173 writer
.write_string (" __attribute__((constructor))");
174 } else if (CCodeModifiers
.DESTRUCTOR
in modifiers
) {
175 writer
.write_string (" __attribute__((destructor))");
178 writer
.write_string (";");
180 block
.write (writer
);
181 writer
.write_newline ();
183 writer
.write_newline ();
186 public void add_statement (CCodeNode stmt
) {
187 stmt
.line
= current_line
;
188 current_block
.add_statement (stmt
);
191 public void open_block () {
192 statement_stack
.add (current_block
);
193 var parent_block
= current_block
;
195 current_block
= new
CCodeBlock ();
197 parent_block
.add_statement (current_block
);
200 public void open_if (CCodeExpression condition
) {
201 statement_stack
.add (current_block
);
202 var parent_block
= current_block
;
204 current_block
= new
CCodeBlock ();
206 var cif
= new
CCodeIfStatement (condition
, current_block
);
207 cif
.line
= current_line
;
208 statement_stack
.add (cif
);
210 parent_block
.add_statement (cif
);
213 public void add_else () {
214 current_block
= new
CCodeBlock ();
216 var cif
= (CCodeIfStatement
) statement_stack
[statement_stack
.size
- 1];
217 cif
.line
= current_line
;
218 assert (cif
.false_statement
== null);
219 cif
.false_statement
= current_block
;
222 public void else_if (CCodeExpression condition
) {
223 var parent_if
= (CCodeIfStatement
) statement_stack
[statement_stack
.size
- 1];
224 assert (parent_if
.false_statement
== null);
226 statement_stack
.remove_at (statement_stack
.size
- 1);
228 current_block
= new
CCodeBlock ();
230 var cif
= new
CCodeIfStatement (condition
, current_block
);
231 cif
.line
= current_line
;
232 parent_if
.false_statement
= cif
;
233 statement_stack
.add (cif
);
236 public void open_while (CCodeExpression condition
) {
237 statement_stack
.add (current_block
);
238 var parent_block
= current_block
;
240 current_block
= new
CCodeBlock ();
242 var cwhile
= new
CCodeWhileStatement (condition
, current_block
);
243 cwhile
.line
= current_line
;
244 parent_block
.add_statement (cwhile
);
247 public void open_for (CCodeExpression? initializer
, CCodeExpression condition
, CCodeExpression? iterator
) {
248 statement_stack
.add (current_block
);
249 var parent_block
= current_block
;
251 current_block
= new
CCodeBlock ();
253 var cfor
= new
CCodeForStatement (condition
, current_block
);
254 cfor
.line
= current_line
;
255 if (initializer
!= null) {
256 cfor
.add_initializer (initializer
);
258 if (iterator
!= null) {
259 cfor
.add_iterator (iterator
);
262 parent_block
.add_statement (cfor
);
265 public void open_switch (CCodeExpression expression
) {
266 statement_stack
.add (current_block
);
267 var parent_block
= current_block
;
269 var cswitch
= new
CCodeSwitchStatement (expression
);
270 cswitch
.line
= current_line
;
271 current_block
= cswitch
;
273 parent_block
.add_statement (cswitch
);
276 public void add_label (string label
) {
277 add_statement (new
CCodeLabel (label
));
280 public void add_case (CCodeExpression expression
) {
281 add_statement (new
CCodeCaseStatement (expression
));
284 public void add_default () {
285 add_statement (new
CCodeLabel ("default"));
288 public void add_goto (string target
) {
289 add_statement (new
CCodeGotoStatement (target
));
292 public void add_expression (CCodeExpression expression
) {
293 add_statement (new
CCodeExpressionStatement (expression
));
296 public void add_assignment (CCodeExpression left
, CCodeExpression right
) {
297 add_expression (new
CCodeAssignment (left
, right
));
300 public void add_return (CCodeExpression? expression
= null) {
301 add_statement (new
CCodeReturnStatement (expression
));
304 public void add_break () {
305 add_statement (new
CCodeBreakStatement ());
308 public void add_continue () {
309 add_statement (new
CCodeContinueStatement ());
312 public void add_declaration (string type_name
, CCodeDeclarator declarator
, CCodeModifiers modifiers
= 0) {
313 var stmt
= new
CCodeDeclaration (type_name
);
314 stmt
.add_declarator (declarator
);
315 stmt
.modifiers
= modifiers
;
316 add_statement (stmt
);
319 public void close () {
321 var top
= statement_stack
[statement_stack
.size
- 1];
322 statement_stack
.remove_at (statement_stack
.size
- 1);
323 current_block
= top as CCodeBlock
;
324 } while (current_block
== null);