authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-11-30 14:13:00-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-11-30 14:13:00-07:00
log757ebefd6075ba2fb3c33af717a2b188347600e9
tree21c6d791a70b501cfe6de51133ef94f33247f5a9
parent014711c57ef6544745444e7867d4d03ffd8d389a

untangle analyze_node into a stricter call graph


1 files changed, 148 insertions(+), 135 deletions(-)

src/analyze.cpp+148-135
......@@ -43,9 +43,7 @@ static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node)
4343 }
4444}
4545
46static void find_declarations(CodeGen *g, AstNode *node);
47
48static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {
46static void resolve_type(CodeGen *g, AstNode *node) {
4947 assert(!node->codegen_node);
5048 node->codegen_node = allocate<CodeGenNode>(1);
5149 TypeNode *type_node = &node->codegen_node->data.type_node;
......@@ -65,7 +63,7 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {
6563 }
6664 case AstNodeTypeTypePointer:
6765 {
68 find_declarations(g, node->data.type.child_type);
66 resolve_type(g, node->data.type.child_type);
6967 TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node;
7068 if (child_type_node->entry->id == TypeIdUnreachable) {
7169 add_node_error(g, node,
......@@ -94,7 +92,29 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {
9492 }
9593}
9694
97static void find_declarations(CodeGen *g, AstNode *node) {
95static void resolve_function_proto(CodeGen *g, AstNode *node) {
96 assert(node->type == NodeTypeFnProto);
97
98 for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {
99 AstNode *directive_node = node->data.fn_proto.directives->at(i);
100 Buf *name = &directive_node->data.directive.name;
101 add_node_error(g, directive_node,
102 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
103 }
104
105 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
106 AstNode *child = node->data.fn_proto.params.at(i);
107 assert(child->type == NodeTypeParamDecl);
108
109 // parameter names are not important here.
110
111 resolve_type(g, child->data.param_decl.type);
112 }
113
114 resolve_type(g, node->data.fn_proto.return_type);
115}
116
117static void preview_function_declarations(CodeGen *g, AstNode *node) {
98118 switch (node->type) {
99119 case NodeTypeExternBlock:
100120 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {
......@@ -113,7 +133,7 @@ static void find_declarations(CodeGen *g, AstNode *node) {
113133 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
114134 assert(fn_decl->type == NodeTypeFnDecl);
115135 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
116 find_declarations(g, fn_proto);
136 resolve_function_proto(g, fn_proto);
117137 Buf *name = &fn_proto->data.fn_proto.name;
118138
119139 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
......@@ -148,35 +168,10 @@ static void find_declarations(CodeGen *g, AstNode *node) {
148168 g->fn_table.put(proto_name, fn_table_entry);
149169 g->fn_defs.append(fn_table_entry);
150170
151 find_declarations(g, proto_node);
152 }
153 break;
154 }
155 case NodeTypeFnProto:
156 {
157 for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {
158 AstNode *directive_node = node->data.fn_proto.directives->at(i);
159 Buf *name = &directive_node->data.directive.name;
160 add_node_error(g, directive_node,
161 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
162 }
163 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
164 AstNode *child = node->data.fn_proto.params.at(i);
165 find_declarations(g, child);
171 resolve_function_proto(g, proto_node);
166172 }
167 find_declarations(g, node->data.fn_proto.return_type);
168 break;
169173 }
170174 break;
171 case NodeTypeParamDecl:
172 find_declarations(g, node->data.param_decl.type);
173 break;
174 case NodeTypeType:
175 resolve_type_and_recurse(g, node);
176 break;
177 case NodeTypeDirective:
178 // we handled directives in the parent function
179 break;
180175 case NodeTypeRootExportDecl:
181176 for (int i = 0; i < node->data.root_export_decl.directives->length; i += 1) {
182177 AstNode *directive_node = node->data.root_export_decl.directives->at(i);
......@@ -189,7 +184,36 @@ static void find_declarations(CodeGen *g, AstNode *node) {
189184 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
190185 }
191186 }
187
188 if (g->root_export_decl) {
189 add_node_error(g, node,
190 buf_sprintf("only one root export declaration allowed"));
191 } else {
192 g->root_export_decl = node;
193
194 if (!g->out_name)
195 g->out_name = &node->data.root_export_decl.name;
196
197 Buf *out_type = &node->data.root_export_decl.type;
198 OutType export_out_type;
199 if (buf_eql_str(out_type, "executable")) {
200 export_out_type = OutTypeExe;
201 } else if (buf_eql_str(out_type, "library")) {
202 export_out_type = OutTypeLib;
203 } else if (buf_eql_str(out_type, "object")) {
204 export_out_type = OutTypeObj;
205 } else {
206 add_node_error(g, node,
207 buf_sprintf("invalid export type: '%s'", buf_ptr(out_type)));
208 }
209 if (g->out_type == OutTypeUnknown)
210 g->out_type = export_out_type;
211 }
192212 break;
213 case NodeTypeDirective:
214 case NodeTypeParamDecl:
215 case NodeTypeFnProto:
216 case NodeTypeType:
193217 case NodeTypeFnDecl:
194218 case NodeTypeReturnExpr:
195219 case NodeTypeRoot:
......@@ -260,113 +284,22 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
260284 }
261285}
262286
263static void analyze_node(CodeGen *g, AstNode *node) {
287static void analyze_expression(CodeGen *g, AstNode *node) {
264288 switch (node->type) {
265 case NodeTypeRoot:
266 {
267 // Iterate once over the top level declarations to build the function table
268 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
269 AstNode *child = node->data.root.top_level_decls.at(i);
270 find_declarations(g, child);
271 }
272 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
273 AstNode *child = node->data.root.top_level_decls.at(i);
274 analyze_node(g, child);
275 }
276 if (!g->out_name) {
277 add_node_error(g, node,
278 buf_sprintf("missing export declaration and output name not provided"));
279 } else if (g->out_type == OutTypeUnknown) {
280 add_node_error(g, node,
281 buf_sprintf("missing export declaration and export type not provided"));
282 }
283 break;
284 }
285 case NodeTypeRootExportDecl:
286 if (g->root_export_decl) {
287 add_node_error(g, node,
288 buf_sprintf("only one root export declaration allowed"));
289 } else {
290 g->root_export_decl = node;
291
292 if (!g->out_name)
293 g->out_name = &node->data.root_export_decl.name;
294
295 Buf *out_type = &node->data.root_export_decl.type;
296 OutType export_out_type;
297 if (buf_eql_str(out_type, "executable")) {
298 export_out_type = OutTypeExe;
299 } else if (buf_eql_str(out_type, "library")) {
300 export_out_type = OutTypeLib;
301 } else if (buf_eql_str(out_type, "object")) {
302 export_out_type = OutTypeObj;
303 } else {
304 add_node_error(g, node,
305 buf_sprintf("invalid export type: '%s'", buf_ptr(out_type)));
306 }
307 if (g->out_type == OutTypeUnknown)
308 g->out_type = export_out_type;
309 }
310 break;
311 case NodeTypeExternBlock:
312 for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) {
313 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
314 analyze_node(g, fn_decl);
315 }
316 break;
317 case NodeTypeFnDef:
318 {
319 if (node->codegen_node && node->codegen_node->data.fn_def_node.skip) {
320 // we detected an error with this function definition which prevents us
321 // from further analyzing it.
322 break;
323 }
324
325 AstNode *proto_node = node->data.fn_def.fn_proto;
326 assert(proto_node->type == NodeTypeFnProto);
327 analyze_node(g, proto_node);
328
329 check_fn_def_control_flow(g, node);
330 analyze_node(g, node->data.fn_def.body);
331 break;
332 }
333 case NodeTypeFnDecl:
334 {
335 AstNode *proto_node = node->data.fn_decl.fn_proto;
336 assert(proto_node->type == NodeTypeFnProto);
337 analyze_node(g, proto_node);
338 break;
339 }
340 case NodeTypeFnProto:
341 {
342 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
343 AstNode *child = node->data.fn_proto.params.at(i);
344 analyze_node(g, child);
345 }
346 analyze_node(g, node->data.fn_proto.return_type);
347 break;
348 }
349 case NodeTypeParamDecl:
350 analyze_node(g, node->data.param_decl.type);
351 break;
352
353 case NodeTypeType:
354 // ignore; we handled types with find_declarations
355 break;
356289 case NodeTypeBlock:
357290 for (int i = 0; i < node->data.block.statements.length; i += 1) {
358291 AstNode *child = node->data.block.statements.at(i);
359 analyze_node(g, child);
292 analyze_expression(g, child);
360293 }
361294 break;
362295 case NodeTypeReturnExpr:
363296 if (node->data.return_expr.expr) {
364 analyze_node(g, node->data.return_expr.expr);
297 analyze_expression(g, node->data.return_expr.expr);
365298 }
366299 break;
367300 case NodeTypeBinOpExpr:
368 analyze_node(g, node->data.bin_op_expr.op1);
369 analyze_node(g, node->data.bin_op_expr.op2);
301 analyze_expression(g, node->data.bin_op_expr.op1);
302 analyze_expression(g, node->data.bin_op_expr.op2);
370303 break;
371304 case NodeTypeFnCallExpr:
372305 {
......@@ -390,13 +323,10 @@ static void analyze_node(CodeGen *g, AstNode *node) {
390323
391324 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
392325 AstNode *child = node->data.fn_call_expr.params.at(i);
393 analyze_node(g, child);
326 analyze_expression(g, child);
394327 }
395328 break;
396329 }
397 case NodeTypeDirective:
398 // we looked at directives in the parent node
399 break;
400330 case NodeTypeCastExpr:
401331 zig_panic("TODO");
402332 break;
......@@ -409,10 +339,93 @@ static void analyze_node(CodeGen *g, AstNode *node) {
409339 case NodeTypeSymbol:
410340 // nothing to do
411341 break;
342 case NodeTypeDirective:
343 case NodeTypeFnDecl:
344 case NodeTypeFnProto:
345 case NodeTypeParamDecl:
346 case NodeTypeType:
347 case NodeTypeRoot:
348 case NodeTypeRootExportDecl:
349 case NodeTypeExternBlock:
350 case NodeTypeFnDef:
351 zig_unreachable();
352 }
353}
354
355static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
356 switch (node->type) {
357 case NodeTypeFnDef:
358 {
359 if (node->codegen_node && node->codegen_node->data.fn_def_node.skip) {
360 // we detected an error with this function definition which prevents us
361 // from further analyzing it.
362 break;
363 }
364
365 AstNode *fn_proto_node = node->data.fn_def.fn_proto;
366 assert(fn_proto_node->type == NodeTypeFnProto);
367
368 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
369 for (int i = 0; i < fn_proto->params.length; i += 1) {
370 AstNode *param_decl_node = fn_proto->params.at(i);
371 assert(param_decl_node->type == NodeTypeParamDecl);
372 // TODO: define local variables for parameters
373 }
374
375 check_fn_def_control_flow(g, node);
376 analyze_expression(g, node->data.fn_def.body);
377 }
378 break;
379
380 case NodeTypeRootExportDecl:
381 case NodeTypeExternBlock:
382 // already looked at these in the preview pass
383 break;
384
385 case NodeTypeDirective:
386 case NodeTypeParamDecl:
387 case NodeTypeFnProto:
388 case NodeTypeType:
389 case NodeTypeFnDecl:
390 case NodeTypeReturnExpr:
391 case NodeTypeRoot:
392 case NodeTypeBlock:
393 case NodeTypeBinOpExpr:
394 case NodeTypeFnCallExpr:
395 case NodeTypeNumberLiteral:
396 case NodeTypeStringLiteral:
397 case NodeTypeUnreachable:
398 case NodeTypeSymbol:
399 case NodeTypeCastExpr:
400 case NodeTypePrefixOpExpr:
401 zig_unreachable();
402 }
403}
404
405static void analyze_root(CodeGen *g, AstNode *node) {
406 assert(node->type == NodeTypeRoot);
407
408 // find function declarations
409 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
410 AstNode *child = node->data.root.top_level_decls.at(i);
411 preview_function_declarations(g, child);
412 }
413
414 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
415 AstNode *child = node->data.root.top_level_decls.at(i);
416 analyze_top_level_declaration(g, child);
417 }
418
419 if (!g->out_name) {
420 add_node_error(g, node,
421 buf_sprintf("missing export declaration and output name not provided"));
422 } else if (g->out_type == OutTypeUnknown) {
423 add_node_error(g, node,
424 buf_sprintf("missing export declaration and export type not provided"));
412425 }
413426}
414427
415static void add_types(CodeGen *g) {
428static void define_primitive_types(CodeGen *g) {
416429 {
417430 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
418431 entry->id = TypeIdU8;
......@@ -491,8 +504,8 @@ void semantic_analyze(CodeGen *g) {
491504 g->dbuilder = new llvm::DIBuilder(*llvm::unwrap(g->module), true);
492505
493506
494 add_types(g);
507 define_primitive_types(g);
495508
496 analyze_node(g, g->root);
509 analyze_root(g, g->root);
497510}
498511