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