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)...@@ -43,9 +43,7 @@ static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node)
43 }43 }
44}44}
4545
46static void find_declarations(CodeGen *g, AstNode *node);46static void resolve_type(CodeGen *g, AstNode *node) {
47
48static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {
49 assert(!node->codegen_node);47 assert(!node->codegen_node);
50 node->codegen_node = allocate<CodeGenNode>(1);48 node->codegen_node = allocate<CodeGenNode>(1);
51 TypeNode *type_node = &node->codegen_node->data.type_node;49 TypeNode *type_node = &node->codegen_node->data.type_node;
...@@ -65,7 +63,7 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {...@@ -65,7 +63,7 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {
65 }63 }
66 case AstNodeTypeTypePointer:64 case AstNodeTypeTypePointer:
67 {65 {
68 find_declarations(g, node->data.type.child_type);66 resolve_type(g, node->data.type.child_type);
69 TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node;67 TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node;
70 if (child_type_node->entry->id == TypeIdUnreachable) {68 if (child_type_node->entry->id == TypeIdUnreachable) {
71 add_node_error(g, node,69 add_node_error(g, node,
...@@ -94,7 +92,29 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {...@@ -94,7 +92,29 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) {
94 }92 }
95}93}
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) {
98 switch (node->type) {118 switch (node->type) {
99 case NodeTypeExternBlock:119 case NodeTypeExternBlock:
100 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {120 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) {...@@ -113,7 +133,7 @@ static void find_declarations(CodeGen *g, AstNode *node) {
113 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);133 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
114 assert(fn_decl->type == NodeTypeFnDecl);134 assert(fn_decl->type == NodeTypeFnDecl);
115 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;135 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
116 find_declarations(g, fn_proto);136 resolve_function_proto(g, fn_proto);
117 Buf *name = &fn_proto->data.fn_proto.name;137 Buf *name = &fn_proto->data.fn_proto.name;
118138
119 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);139 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
...@@ -148,35 +168,10 @@ static void find_declarations(CodeGen *g, AstNode *node) {...@@ -148,35 +168,10 @@ static void find_declarations(CodeGen *g, AstNode *node) {
148 g->fn_table.put(proto_name, fn_table_entry);168 g->fn_table.put(proto_name, fn_table_entry);
149 g->fn_defs.append(fn_table_entry);169 g->fn_defs.append(fn_table_entry);
150170
151 find_declarations(g, proto_node);171 resolve_function_proto(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);
166 }172 }
167 find_declarations(g, node->data.fn_proto.return_type);
168 break;
169 }173 }
170 break;174 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;
180 case NodeTypeRootExportDecl:175 case NodeTypeRootExportDecl:
181 for (int i = 0; i < node->data.root_export_decl.directives->length; i += 1) {176 for (int i = 0; i < node->data.root_export_decl.directives->length; i += 1) {
182 AstNode *directive_node = node->data.root_export_decl.directives->at(i);177 AstNode *directive_node = node->data.root_export_decl.directives->at(i);
...@@ -189,7 +184,36 @@ static void find_declarations(CodeGen *g, AstNode *node) {...@@ -189,7 +184,36 @@ static void find_declarations(CodeGen *g, AstNode *node) {
189 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));184 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
190 }185 }
191 }186 }
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 }
192 break;212 break;
213 case NodeTypeDirective:
214 case NodeTypeParamDecl:
215 case NodeTypeFnProto:
216 case NodeTypeType:
193 case NodeTypeFnDecl:217 case NodeTypeFnDecl:
194 case NodeTypeReturnExpr:218 case NodeTypeReturnExpr:
195 case NodeTypeRoot:219 case NodeTypeRoot:
...@@ -260,113 +284,22 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {...@@ -260,113 +284,22 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
260 }284 }
261}285}
262286
263static void analyze_node(CodeGen *g, AstNode *node) {287static void analyze_expression(CodeGen *g, AstNode *node) {
264 switch (node->type) {288 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;
356 case NodeTypeBlock:289 case NodeTypeBlock:
357 for (int i = 0; i < node->data.block.statements.length; i += 1) {290 for (int i = 0; i < node->data.block.statements.length; i += 1) {
358 AstNode *child = node->data.block.statements.at(i);291 AstNode *child = node->data.block.statements.at(i);
359 analyze_node(g, child);292 analyze_expression(g, child);
360 }293 }
361 break;294 break;
362 case NodeTypeReturnExpr:295 case NodeTypeReturnExpr:
363 if (node->data.return_expr.expr) {296 if (node->data.return_expr.expr) {
364 analyze_node(g, node->data.return_expr.expr);297 analyze_expression(g, node->data.return_expr.expr);
365 }298 }
366 break;299 break;
367 case NodeTypeBinOpExpr:300 case NodeTypeBinOpExpr:
368 analyze_node(g, node->data.bin_op_expr.op1);301 analyze_expression(g, node->data.bin_op_expr.op1);
369 analyze_node(g, node->data.bin_op_expr.op2);302 analyze_expression(g, node->data.bin_op_expr.op2);
370 break;303 break;
371 case NodeTypeFnCallExpr:304 case NodeTypeFnCallExpr:
372 {305 {
...@@ -390,13 +323,10 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -390,13 +323,10 @@ static void analyze_node(CodeGen *g, AstNode *node) {
390323
391 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {324 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
392 AstNode *child = node->data.fn_call_expr.params.at(i);325 AstNode *child = node->data.fn_call_expr.params.at(i);
393 analyze_node(g, child);326 analyze_expression(g, child);
394 }327 }
395 break;328 break;
396 }329 }
397 case NodeTypeDirective:
398 // we looked at directives in the parent node
399 break;
400 case NodeTypeCastExpr:330 case NodeTypeCastExpr:
401 zig_panic("TODO");331 zig_panic("TODO");
402 break;332 break;
...@@ -409,10 +339,93 @@ static void analyze_node(CodeGen *g, AstNode *node) {...@@ -409,10 +339,93 @@ static void analyze_node(CodeGen *g, AstNode *node) {
409 case NodeTypeSymbol:339 case NodeTypeSymbol:
410 // nothing to do340 // nothing to do
411 break;341 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"));
412 }425 }
413}426}
414427
415static void add_types(CodeGen *g) {428static void define_primitive_types(CodeGen *g) {
416 {429 {
417 TypeTableEntry *entry = allocate<TypeTableEntry>(1);430 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
418 entry->id = TypeIdU8;431 entry->id = TypeIdU8;
...@@ -491,8 +504,8 @@ void semantic_analyze(CodeGen *g) {...@@ -491,8 +504,8 @@ void semantic_analyze(CodeGen *g) {
491 g->dbuilder = new llvm::DIBuilder(*llvm::unwrap(g->module), true);504 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);
497}510}
498511