More work for C++ mode:
[cparser] / walk_statements.c
1 #include <config.h>
2
3 #include "adt/error.h"
4 #include "ast_t.h"
5 #include "entity_t.h"
6 #include "walk_statements.h"
7
8
9 static void walk_expression(expression_t const *const expr,
10                             statement_callback const callback, void *const env)
11 {
12         switch (expr->base.kind) {
13         case EXPR_STATEMENT:
14                 walk_statements(expr->statement.statement, callback, env);
15                 return;
16
17         EXPR_BINARY_CASES
18                 walk_expression(expr->binary.left,  callback, env);
19                 walk_expression(expr->binary.right, callback, env);
20                 return;
21
22         EXPR_UNARY_CASES_OPTIONAL
23                 if (expr->unary.value == NULL)
24                         return;
25                 /* FALLTHROUGH */
26         EXPR_UNARY_CASES_MANDATORY
27                 walk_expression(expr->unary.value, callback, env);
28                 return;
29
30         case EXPR_CALL:
31                 for (call_argument_t *arg = expr->call.arguments; arg != NULL;
32                      arg = arg->next) {
33                         walk_expression(arg->expression, callback, env);
34                 }
35                 return;
36
37         case EXPR_UNKNOWN:
38         case EXPR_INVALID:
39                 panic("unexpected expr kind");
40
41         case EXPR_COMPOUND_LITERAL:
42                 /* TODO... */
43                 break;
44
45         case EXPR_CONDITIONAL:
46                 walk_expression(expr->conditional.condition,        callback, env);
47                 /* may be NULL because of gnu extension */
48                 if (expr->conditional.true_expression != NULL)
49                         walk_expression(expr->conditional.true_expression,  callback, env);
50                 walk_expression(expr->conditional.false_expression, callback, env);
51                 return;
52
53         case EXPR_BUILTIN_PREFETCH:
54                 walk_expression(expr->builtin_prefetch.adr,      callback, env);
55                 walk_expression(expr->builtin_prefetch.rw,       callback, env);
56                 walk_expression(expr->builtin_prefetch.locality, callback, env);
57                 return;
58
59         case EXPR_BUILTIN_CONSTANT_P:
60                 walk_expression(expr->builtin_constant.value, callback, env);
61                 return;
62
63         case EXPR_SELECT:
64                 walk_expression(expr->select.compound, callback, env);
65                 return;
66
67         case EXPR_ARRAY_ACCESS:
68                 walk_expression(expr->array_access.array_ref, callback, env);
69                 walk_expression(expr->array_access.index,     callback, env);
70                 return;
71
72         case EXPR_CLASSIFY_TYPE:
73                 walk_expression(expr->classify_type.type_expression, callback, env);
74                 return;
75
76         case EXPR_SIZEOF:
77         case EXPR_ALIGNOF: {
78                 expression_t *tp_expression = expr->typeprop.tp_expression;
79                 if (tp_expression != NULL) {
80                         walk_expression(tp_expression, callback, env);
81                 }
82                 return;
83         }
84
85         case EXPR_OFFSETOF:
86         case EXPR_REFERENCE:
87         case EXPR_REFERENCE_ENUM_VALUE:
88         case EXPR_CONST:
89         case EXPR_CHARACTER_CONSTANT:
90         case EXPR_WIDE_CHARACTER_CONSTANT:
91         case EXPR_STRING_LITERAL:
92         case EXPR_WIDE_STRING_LITERAL:
93         case EXPR_FUNCNAME:
94         case EXPR_BUILTIN_SYMBOL:
95         case EXPR_VA_START:
96         case EXPR_VA_ARG:
97         case EXPR_LABEL_ADDRESS:
98                 break;
99         }
100
101         /* TODO FIXME: implement all the missing expressions here */
102 }
103
104 static void walk_initializer(const initializer_t  *initializer,
105                              statement_callback    callback,
106                                                          void                 *env)
107 {
108         switch(initializer->kind) {
109         case INITIALIZER_VALUE:
110                 walk_expression(initializer->value.value, callback, env);
111                 return;
112         default:
113                 /* FIXME: should walk initializer hierarchies... */
114                 break;
115         }
116 }
117
118 static void walk_declarations(const entity_t*            entity,
119                               const entity_t*      const end,
120                               statement_callback   const callback,
121                               void                *const env)
122 {
123         for (; entity != end; entity = entity->base.next) {
124                 /* we only look at variables */
125                 if (entity->kind != ENTITY_VARIABLE)
126                         continue;
127
128                 const variable_t    *variable    = &entity->variable;
129                 const initializer_t *initializer = variable->initializer;
130                 if (initializer != NULL) {
131                         walk_initializer(initializer, callback, env);
132                 }
133         }
134 }
135
136
137 void walk_statements(statement_t *const stmt, statement_callback const callback, void *const env)
138 {
139         callback(stmt, env);
140
141         switch (stmt->kind) {
142                 case STATEMENT_COMPOUND:
143                         for (statement_t *s = stmt->compound.statements; s != NULL; s = s->base.next) {
144                                 walk_statements(s, callback, env);
145                         }
146                         return;
147
148                 case STATEMENT_FOR:
149                         walk_declarations(stmt->fors.scope.entities, NULL, callback, env);
150                         if (stmt->fors.initialisation != NULL)
151                                 walk_expression(stmt->fors.initialisation, callback, env);
152                         if (stmt->fors.condition != NULL)
153                                 walk_expression(stmt->fors.condition, callback, env);
154                         if (stmt->fors.step != NULL)
155                                 walk_expression(stmt->fors.step, callback, env);
156                         walk_statements(stmt->fors.body,           callback, env);
157                         return;
158
159                 case STATEMENT_IF:
160                         walk_expression(stmt->ifs.condition,      callback, env);
161                         walk_statements(stmt->ifs.true_statement, callback, env);
162                         if (stmt->ifs.false_statement != NULL)
163                                 walk_statements(stmt->ifs.false_statement, callback, env);
164                         return;
165
166                 case STATEMENT_SWITCH:
167                         walk_expression(stmt->switchs.expression, callback, env);
168                         walk_statements(stmt->switchs.body,       callback, env);
169                         return;
170
171                 case STATEMENT_LABEL:
172                         walk_statements(stmt->label.statement, callback, env);
173                         return;
174
175                 case STATEMENT_CASE_LABEL:
176                         walk_statements(stmt->case_label.statement, callback, env);
177                         return;
178
179                 case STATEMENT_WHILE:
180                         walk_expression(stmt->whiles.condition, callback, env);
181                         walk_statements(stmt->whiles.body,      callback, env);
182                         return;
183
184                 case STATEMENT_DO_WHILE:
185                         walk_statements(stmt->do_while.body,      callback, env);
186                         walk_expression(stmt->do_while.condition, callback, env);
187                         return;
188
189                 case STATEMENT_EXPRESSION:
190                         walk_expression(stmt->expression.expression, callback, env);
191                         return;
192
193                 case STATEMENT_RETURN:
194                         if (stmt->returns.value != NULL)
195                                 walk_expression(stmt->returns.value, callback, env);
196                         return;
197
198                 case STATEMENT_DECLARATION:
199                         walk_declarations(stmt->declaration.declarations_begin,
200                                           stmt->declaration.declarations_end->base.next,
201                                           callback, env);
202                         return;
203
204                 case STATEMENT_MS_TRY:
205                         walk_statements(stmt->ms_try.try_statement,   callback, env);
206                         walk_statements(stmt->ms_try.final_statement, callback, env);
207                         return;
208
209                 case STATEMENT_LOCAL_LABEL:
210                 case STATEMENT_INVALID:
211                 case STATEMENT_EMPTY:
212                 case STATEMENT_CONTINUE:
213                 case STATEMENT_BREAK:
214                 case STATEMENT_GOTO:
215                 case STATEMENT_ASM:
216                 case STATEMENT_LEAVE:
217                         return;
218         }
219
220         panic("unhandled statement");
221 }