Fix symbol resolution and enable control flow analysis for signals
[vala-lang.git] / ccode / valaccodefunction.vala
blob20725eea571a22425a42bb2684f93478ce2336b4
1 /* valaccodefunction.vala
3 * Copyright (C) 2006-2010 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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents a function declaration in the C code.
28 public class Vala.CCodeFunction : CCodeNode {
29 /**
30 * The name of this function.
32 public string name { get; set; }
34 /**
35 * The function modifiers.
37 public CCodeModifiers modifiers { get; set; }
39 /**
40 * The function return type.
42 public string return_type { get; set; }
44 public string attributes { get; set; }
46 public bool is_declaration { get; set; }
48 /**
49 * The function body.
51 public CCodeBlock block { get; set; }
53 private List<CCodeParameter> parameters = new ArrayList<CCodeParameter> ();
55 CCodeBlock current_block;
56 List<CCodeStatement> statement_stack = new ArrayList<CCodeStatement> ();
58 public CCodeFunction (string name, string return_type = "void") {
59 this.name = name;
60 this.return_type = return_type;
61 this.block = new CCodeBlock ();
62 current_block = block;
65 /**
66 * Appends the specified parameter to the list of function parameters.
68 * @param param a formal parameter
70 public void add_parameter (CCodeParameter param) {
71 parameters.add (param);
74 public void insert_parameter (int position, CCodeParameter param) {
75 parameters.insert (position, param);
78 /**
79 * Returns a copy of this function.
81 * @return copied function
83 public CCodeFunction copy () {
84 var func = new CCodeFunction (name, return_type);
85 func.modifiers = modifiers;
86 func.attributes = attributes;
88 /* no deep copy for lists available yet
89 * func.parameters = parameters.copy ();
91 foreach (CCodeParameter param in parameters) {
92 func.parameters.add (param);
95 func.is_declaration = is_declaration;
96 func.block = block;
97 return func;
100 public override void write (CCodeWriter writer) {
101 writer.write_indent (line);
102 if (CCodeModifiers.STATIC in modifiers) {
103 writer.write_string ("static ");
105 if (CCodeModifiers.INLINE in modifiers) {
106 writer.write_string ("inline ");
108 writer.write_string (return_type);
109 writer.write_string (" ");
110 writer.write_string (name);
111 writer.write_string (" (");
113 bool first = true;
114 foreach (CCodeParameter param in parameters) {
115 if (!first) {
116 writer.write_string (", ");
117 } else {
118 first = false;
120 param.write (writer);
122 if (first) {
123 writer.write_string ("void");
126 writer.write_string (")");
128 if (CCodeModifiers.DEPRECATED in modifiers) {
129 writer.write_string (" G_GNUC_DEPRECATED");
132 if (is_declaration) {
133 if (attributes != null) {
134 writer.write_string (" ");
135 writer.write_string (attributes);
138 writer.write_string (";");
139 } else {
140 block.write (writer);
141 writer.write_newline ();
143 writer.write_newline ();
146 public void add_statement (CCodeNode stmt) {
147 current_block.add_statement (stmt);
150 public void open_block () {
151 statement_stack.add (current_block);
152 var parent_block = current_block;
154 current_block = new CCodeBlock ();
156 parent_block.add_statement (current_block);
159 public void open_if (CCodeExpression condition) {
160 statement_stack.add (current_block);
161 var parent_block = current_block;
163 current_block = new CCodeBlock ();
165 var cif = new CCodeIfStatement (condition, current_block);
166 statement_stack.add (cif);
168 parent_block.add_statement (cif);
171 public void add_else () {
172 current_block = new CCodeBlock ();
174 var cif = (CCodeIfStatement) statement_stack[statement_stack.size - 1];
175 assert (cif.false_statement == null);
176 cif.false_statement = current_block;
179 public void else_if (CCodeExpression condition) {
180 var parent_if = (CCodeIfStatement) statement_stack[statement_stack.size - 1];
181 assert (parent_if.false_statement == null);
183 statement_stack.remove_at (statement_stack.size - 1);
185 current_block = new CCodeBlock ();
187 var cif = new CCodeIfStatement (condition, current_block);
188 parent_if.false_statement = cif;
189 statement_stack.add (cif);
192 public void open_while (CCodeExpression condition) {
193 statement_stack.add (current_block);
194 var parent_block = current_block;
196 current_block = new CCodeBlock ();
198 parent_block.add_statement (new CCodeWhileStatement (condition, current_block));
201 public void open_for (CCodeExpression? initializer, CCodeExpression condition, CCodeExpression? iterator) {
202 statement_stack.add (current_block);
203 var parent_block = current_block;
205 current_block = new CCodeBlock ();
207 var cfor = new CCodeForStatement (condition, current_block);
208 if (initializer != null) {
209 cfor.add_initializer (initializer);
211 if (iterator != null) {
212 cfor.add_iterator (iterator);
215 parent_block.add_statement (cfor);
218 public void open_switch (CCodeExpression expression) {
219 statement_stack.add (current_block);
220 var parent_block = current_block;
222 var cswitch = new CCodeSwitchStatement (expression);
223 current_block = cswitch;
225 parent_block.add_statement (cswitch);
228 public void add_label (string label) {
229 current_block.add_statement (new CCodeLabel (label));
232 public void add_case (CCodeExpression expression) {
233 current_block.add_statement (new CCodeCaseStatement (expression));
236 public void add_default () {
237 current_block.add_statement (new CCodeLabel ("default"));
240 public void add_goto (string target) {
241 current_block.add_statement (new CCodeGotoStatement (target));
244 public void add_expression (CCodeExpression expression) {
245 current_block.add_statement (new CCodeExpressionStatement (expression));
248 public void add_return (CCodeExpression? expression = null) {
249 current_block.add_statement (new CCodeReturnStatement (expression));
252 public void add_break () {
253 current_block.add_statement (new CCodeBreakStatement ());
256 public void add_continue () {
257 current_block.add_statement (new CCodeContinueStatement ());
260 public void add_declaration (string type_name, CCodeDeclarator declarator, CCodeModifiers modifiers = 0) {
261 var stmt = new CCodeDeclaration (type_name);
262 stmt.add_declarator (declarator);
263 stmt.modifiers = modifiers;
264 current_block.add_statement (stmt);
267 public void close () {
268 do {
269 var top = statement_stack[statement_stack.size - 1];
270 statement_stack.remove_at (statement_stack.size - 1);
271 current_block = top as CCodeBlock;
272 } while (current_block == null);