authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 21:10:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 21:10:38-07:00
logb6354ddd5a4840d856899eca63267785355cbd3e
tree34314c10b8e1f7986395c36011c99c89a2efc20e
parentc281533638dd08bb84f4f538fd8c5ae85791d034

move AST rendering code to separate file


11 files changed, 789 insertions(+), 592 deletions(-)

CMakeLists.txt+1
......@@ -25,6 +25,7 @@ include_directories(
2525)
2626
2727set(ZIG_SOURCES
28 "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
2829 "${CMAKE_SOURCE_DIR}/src/bignum.cpp"
2930 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
3031 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
doc/targets.md+3
......@@ -11,3 +11,6 @@ for the target when an exported or external function has a byvalue struct.
1111Write the target-specific code in std.zig.
1212
1313Update the C integer types to be the correct size for the target.
14
15Add the conditional compilation code for the page size global. It is hardcoded
16for each target.
src/all_types.hpp+1
......@@ -894,6 +894,7 @@ struct ImportTableEntry {
894894 ZigList<int> *line_offsets;
895895 BlockContext *block_context;
896896 ZigList<ImporterInfo> importers;
897 bool is_c_import;
897898
898899 // reminder: hash tables must be initialized before use
899900 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
src/analyze.cpp+14-10
......@@ -1039,15 +1039,15 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo
10391039 }
10401040}
10411041
1042static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1042static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, AstNode *node) {
10431043 assert(node->type == NodeTypeCImport);
10441044
10451045 AstNode *block_node = node->data.c_import.block;
10461046
1047 BlockContext *child_context = new_block_context(node, import->block_context);
1047 BlockContext *child_context = new_block_context(node, parent_import->block_context);
10481048 child_context->c_import_buf = buf_alloc();
10491049
1050 TypeTableEntry *resolved_type = analyze_block_expr(g, import, child_context,
1050 TypeTableEntry *resolved_type = analyze_block_expr(g, parent_import, child_context,
10511051 g->builtin_types.entry_void, block_node);
10521052
10531053 if (resolved_type->id == TypeTableEntryIdInvalid) {
......@@ -1055,23 +1055,27 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *import, AstNode
10551055 }
10561056
10571057 find_libc_path(g);
1058
1059 ImportTableEntry child_import = {0};
1060 ZigList<ErrorMsg *> errors = {0};
1061
10581062 int err;
1059 ParseH parse_h = {{0}};
1060 if ((err = parse_h_buf(&parse_h, child_context->c_import_buf, g->clang_argv, g->clang_argv_len,
1063 if ((err = parse_h_buf(&child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len,
10611064 buf_ptr(g->libc_include_path))))
10621065 {
10631066 zig_panic("unable to parse h file: %s\n", err_str(err));
10641067 }
10651068
1066 if (parse_h.errors.length > 0) {
1069 if (errors.length > 0) {
10671070 ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
1068 for (int i = 0; i < parse_h.errors.length; i += 1) {
1069 ErrorMsg *err_msg = parse_h.errors.at(i);
1071 for (int i = 0; i < errors.length; i += 1) {
1072 ErrorMsg *err_msg = errors.at(i);
10701073 err_msg_add_note(parent_err_msg, err_msg);
10711074 }
1072 } else {
1073 zig_panic("TODO integrate the parsed AST");
1075 return;
10741076 }
1077
1078 zig_panic("TODO integrate the AST");
10751079}
10761080
10771081static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
src/ast_render.cpp created+682
......@@ -0,0 +1,682 @@
1#include "ast_render.hpp"
2
3#include <stdio.h>
4
5static const char *bin_op_str(BinOpType bin_op) {
6 switch (bin_op) {
7 case BinOpTypeInvalid: return "(invalid)";
8 case BinOpTypeBoolOr: return "||";
9 case BinOpTypeBoolAnd: return "&&";
10 case BinOpTypeCmpEq: return "==";
11 case BinOpTypeCmpNotEq: return "!=";
12 case BinOpTypeCmpLessThan: return "<";
13 case BinOpTypeCmpGreaterThan: return ">";
14 case BinOpTypeCmpLessOrEq: return "<=";
15 case BinOpTypeCmpGreaterOrEq: return ">=";
16 case BinOpTypeBinOr: return "|";
17 case BinOpTypeBinXor: return "^";
18 case BinOpTypeBinAnd: return "&";
19 case BinOpTypeBitShiftLeft: return "<<";
20 case BinOpTypeBitShiftRight: return ">>";
21 case BinOpTypeAdd: return "+";
22 case BinOpTypeSub: return "-";
23 case BinOpTypeMult: return "*";
24 case BinOpTypeDiv: return "/";
25 case BinOpTypeMod: return "%";
26 case BinOpTypeAssign: return "=";
27 case BinOpTypeAssignTimes: return "*=";
28 case BinOpTypeAssignDiv: return "/=";
29 case BinOpTypeAssignMod: return "%=";
30 case BinOpTypeAssignPlus: return "+=";
31 case BinOpTypeAssignMinus: return "-=";
32 case BinOpTypeAssignBitShiftLeft: return "<<=";
33 case BinOpTypeAssignBitShiftRight: return ">>=";
34 case BinOpTypeAssignBitAnd: return "&=";
35 case BinOpTypeAssignBitXor: return "^=";
36 case BinOpTypeAssignBitOr: return "|=";
37 case BinOpTypeAssignBoolAnd: return "&&=";
38 case BinOpTypeAssignBoolOr: return "||=";
39 case BinOpTypeUnwrapMaybe: return "??";
40 case BinOpTypeStrCat: return "++";
41 }
42}
43
44static const char *prefix_op_str(PrefixOp prefix_op) {
45 switch (prefix_op) {
46 case PrefixOpInvalid: return "(invalid)";
47 case PrefixOpNegation: return "-";
48 case PrefixOpBoolNot: return "!";
49 case PrefixOpBinNot: return "~";
50 case PrefixOpAddressOf: return "&";
51 case PrefixOpConstAddressOf: return "&const ";
52 case PrefixOpDereference: return "*";
53 case PrefixOpMaybe: return "?";
54 case PrefixOpError: return "%";
55 case PrefixOpUnwrapError: return "%%";
56 }
57}
58
59static const char *return_prefix_str(ReturnKind kind) {
60 switch (kind) {
61 case ReturnKindError: return "%";
62 case ReturnKindMaybe: return "?";
63 case ReturnKindUnconditional: return "";
64 }
65}
66
67static const char *visib_mod_string(VisibMod mod) {
68 switch (mod) {
69 case VisibModPub: return "pub ";
70 case VisibModPrivate: return "";
71 case VisibModExport: return "export ";
72 }
73}
74
75static const char *extern_string(bool is_extern) {
76 return is_extern ? "export " : "";
77}
78
79static const char *const_or_var_string(bool is_const) {
80 return is_const ? "const" : "var";
81}
82
83static const char *node_type_str(NodeType node_type) {
84 switch (node_type) {
85 case NodeTypeRoot:
86 return "Root";
87 case NodeTypeRootExportDecl:
88 return "RootExportDecl";
89 case NodeTypeFnDef:
90 return "FnDef";
91 case NodeTypeFnDecl:
92 return "FnDecl";
93 case NodeTypeFnProto:
94 return "FnProto";
95 case NodeTypeParamDecl:
96 return "ParamDecl";
97 case NodeTypeBlock:
98 return "Block";
99 case NodeTypeBinOpExpr:
100 return "BinOpExpr";
101 case NodeTypeUnwrapErrorExpr:
102 return "UnwrapErrorExpr";
103 case NodeTypeFnCallExpr:
104 return "FnCallExpr";
105 case NodeTypeArrayAccessExpr:
106 return "ArrayAccessExpr";
107 case NodeTypeSliceExpr:
108 return "SliceExpr";
109 case NodeTypeDirective:
110 return "Directive";
111 case NodeTypeReturnExpr:
112 return "ReturnExpr";
113 case NodeTypeVariableDeclaration:
114 return "VariableDeclaration";
115 case NodeTypeErrorValueDecl:
116 return "ErrorValueDecl";
117 case NodeTypeNumberLiteral:
118 return "NumberLiteral";
119 case NodeTypeStringLiteral:
120 return "StringLiteral";
121 case NodeTypeCharLiteral:
122 return "CharLiteral";
123 case NodeTypeSymbol:
124 return "Symbol";
125 case NodeTypePrefixOpExpr:
126 return "PrefixOpExpr";
127 case NodeTypeImport:
128 return "Import";
129 case NodeTypeCImport:
130 return "CImport";
131 case NodeTypeBoolLiteral:
132 return "BoolLiteral";
133 case NodeTypeNullLiteral:
134 return "NullLiteral";
135 case NodeTypeUndefinedLiteral:
136 return "UndefinedLiteral";
137 case NodeTypeIfBoolExpr:
138 return "IfBoolExpr";
139 case NodeTypeIfVarExpr:
140 return "IfVarExpr";
141 case NodeTypeWhileExpr:
142 return "WhileExpr";
143 case NodeTypeForExpr:
144 return "ForExpr";
145 case NodeTypeSwitchExpr:
146 return "SwitchExpr";
147 case NodeTypeSwitchProng:
148 return "SwitchProng";
149 case NodeTypeSwitchRange:
150 return "SwitchRange";
151 case NodeTypeLabel:
152 return "Label";
153 case NodeTypeGoto:
154 return "Goto";
155 case NodeTypeBreak:
156 return "Break";
157 case NodeTypeContinue:
158 return "Continue";
159 case NodeTypeAsmExpr:
160 return "AsmExpr";
161 case NodeTypeFieldAccessExpr:
162 return "FieldAccessExpr";
163 case NodeTypeStructDecl:
164 return "StructDecl";
165 case NodeTypeStructField:
166 return "StructField";
167 case NodeTypeStructValueField:
168 return "StructValueField";
169 case NodeTypeContainerInitExpr:
170 return "ContainerInitExpr";
171 case NodeTypeArrayType:
172 return "ArrayType";
173 case NodeTypeErrorType:
174 return "ErrorType";
175 }
176}
177
178
179void ast_print(FILE *f, AstNode *node, int indent) {
180 for (int i = 0; i < indent; i += 1) {
181 fprintf(f, " ");
182 }
183 assert(node->type == NodeTypeRoot || *node->parent_field == node);
184
185 switch (node->type) {
186 case NodeTypeRoot:
187 fprintf(f, "%s\n", node_type_str(node->type));
188 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
189 AstNode *child = node->data.root.top_level_decls.at(i);
190 ast_print(f, child, indent + 2);
191 }
192 break;
193 case NodeTypeRootExportDecl:
194 fprintf(f, "%s %s '%s'\n", node_type_str(node->type),
195 buf_ptr(&node->data.root_export_decl.type),
196 buf_ptr(&node->data.root_export_decl.name));
197 break;
198 case NodeTypeFnDef:
199 {
200 fprintf(f, "%s\n", node_type_str(node->type));
201 AstNode *child = node->data.fn_def.fn_proto;
202 ast_print(f, child, indent + 2);
203 ast_print(f, node->data.fn_def.body, indent + 2);
204 break;
205 }
206 case NodeTypeFnProto:
207 {
208 Buf *name_buf = &node->data.fn_proto.name;
209 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
210
211 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
212 AstNode *child = node->data.fn_proto.params.at(i);
213 ast_print(f, child, indent + 2);
214 }
215
216 ast_print(f, node->data.fn_proto.return_type, indent + 2);
217
218 break;
219 }
220 case NodeTypeBlock:
221 {
222 fprintf(f, "%s\n", node_type_str(node->type));
223 for (int i = 0; i < node->data.block.statements.length; i += 1) {
224 AstNode *child = node->data.block.statements.at(i);
225 ast_print(f, child, indent + 2);
226 }
227 break;
228 }
229 case NodeTypeParamDecl:
230 {
231 Buf *name_buf = &node->data.param_decl.name;
232 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
233
234 ast_print(f, node->data.param_decl.type, indent + 2);
235
236 break;
237 }
238 case NodeTypeReturnExpr:
239 {
240 const char *prefix_str = return_prefix_str(node->data.return_expr.kind);
241 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));
242 if (node->data.return_expr.expr)
243 ast_print(f, node->data.return_expr.expr, indent + 2);
244 break;
245 }
246 case NodeTypeVariableDeclaration:
247 {
248 Buf *name_buf = &node->data.variable_declaration.symbol;
249 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
250 if (node->data.variable_declaration.type)
251 ast_print(f, node->data.variable_declaration.type, indent + 2);
252 if (node->data.variable_declaration.expr)
253 ast_print(f, node->data.variable_declaration.expr, indent + 2);
254 break;
255 }
256 case NodeTypeErrorValueDecl:
257 {
258 Buf *name_buf = &node->data.error_value_decl.name;
259 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
260 break;
261 }
262 case NodeTypeFnDecl:
263 fprintf(f, "%s\n", node_type_str(node->type));
264 ast_print(f, node->data.fn_decl.fn_proto, indent + 2);
265 break;
266 case NodeTypeBinOpExpr:
267 fprintf(f, "%s %s\n", node_type_str(node->type),
268 bin_op_str(node->data.bin_op_expr.bin_op));
269 ast_print(f, node->data.bin_op_expr.op1, indent + 2);
270 ast_print(f, node->data.bin_op_expr.op2, indent + 2);
271 break;
272 case NodeTypeUnwrapErrorExpr:
273 fprintf(f, "%s\n", node_type_str(node->type));
274 ast_print(f, node->data.unwrap_err_expr.op1, indent + 2);
275 if (node->data.unwrap_err_expr.symbol) {
276 ast_print(f, node->data.unwrap_err_expr.symbol, indent + 2);
277 }
278 ast_print(f, node->data.unwrap_err_expr.op2, indent + 2);
279 break;
280 case NodeTypeFnCallExpr:
281 fprintf(f, "%s\n", node_type_str(node->type));
282 ast_print(f, node->data.fn_call_expr.fn_ref_expr, indent + 2);
283 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
284 AstNode *child = node->data.fn_call_expr.params.at(i);
285 ast_print(f, child, indent + 2);
286 }
287 break;
288 case NodeTypeArrayAccessExpr:
289 fprintf(f, "%s\n", node_type_str(node->type));
290 ast_print(f, node->data.array_access_expr.array_ref_expr, indent + 2);
291 ast_print(f, node->data.array_access_expr.subscript, indent + 2);
292 break;
293 case NodeTypeSliceExpr:
294 fprintf(f, "%s\n", node_type_str(node->type));
295 ast_print(f, node->data.slice_expr.array_ref_expr, indent + 2);
296 ast_print(f, node->data.slice_expr.start, indent + 2);
297 if (node->data.slice_expr.end) {
298 ast_print(f, node->data.slice_expr.end, indent + 2);
299 }
300 break;
301 case NodeTypeDirective:
302 fprintf(f, "%s\n", node_type_str(node->type));
303 break;
304 case NodeTypePrefixOpExpr:
305 fprintf(f, "%s %s\n", node_type_str(node->type),
306 prefix_op_str(node->data.prefix_op_expr.prefix_op));
307 ast_print(f, node->data.prefix_op_expr.primary_expr, indent + 2);
308 break;
309 case NodeTypeNumberLiteral:
310 {
311 NumLit kind = node->data.number_literal.kind;
312 const char *name = node_type_str(node->type);
313 if (kind == NumLitUInt) {
314 fprintf(f, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint);
315 } else {
316 fprintf(f, "%s float %f\n", name, node->data.number_literal.data.x_float);
317 }
318 break;
319 }
320 case NodeTypeStringLiteral:
321 {
322 const char *c = node->data.string_literal.c ? "c" : "";
323 fprintf(f, "StringLiteral %s'%s'\n", c,
324 buf_ptr(&node->data.string_literal.buf));
325 break;
326 }
327 case NodeTypeCharLiteral:
328 {
329 fprintf(f, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
330 break;
331 }
332 case NodeTypeSymbol:
333 fprintf(f, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
334 break;
335 case NodeTypeImport:
336 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path));
337 break;
338 case NodeTypeCImport:
339 fprintf(f, "%s\n", node_type_str(node->type));
340 ast_print(f, node->data.c_import.block, indent + 2);
341 break;
342 case NodeTypeBoolLiteral:
343 fprintf(f, "%s '%s'\n", node_type_str(node->type),
344 node->data.bool_literal.value ? "true" : "false");
345 break;
346 case NodeTypeNullLiteral:
347 fprintf(f, "%s\n", node_type_str(node->type));
348 break;
349 case NodeTypeIfBoolExpr:
350 fprintf(f, "%s\n", node_type_str(node->type));
351 if (node->data.if_bool_expr.condition)
352 ast_print(f, node->data.if_bool_expr.condition, indent + 2);
353 ast_print(f, node->data.if_bool_expr.then_block, indent + 2);
354 if (node->data.if_bool_expr.else_node)
355 ast_print(f, node->data.if_bool_expr.else_node, indent + 2);
356 break;
357 case NodeTypeIfVarExpr:
358 {
359 Buf *name_buf = &node->data.if_var_expr.var_decl.symbol;
360 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
361 if (node->data.if_var_expr.var_decl.type)
362 ast_print(f, node->data.if_var_expr.var_decl.type, indent + 2);
363 if (node->data.if_var_expr.var_decl.expr)
364 ast_print(f, node->data.if_var_expr.var_decl.expr, indent + 2);
365 ast_print(f, node->data.if_var_expr.then_block, indent + 2);
366 if (node->data.if_var_expr.else_node)
367 ast_print(f, node->data.if_var_expr.else_node, indent + 2);
368 break;
369 }
370 case NodeTypeWhileExpr:
371 fprintf(f, "%s\n", node_type_str(node->type));
372 ast_print(f, node->data.while_expr.condition, indent + 2);
373 ast_print(f, node->data.while_expr.body, indent + 2);
374 break;
375 case NodeTypeForExpr:
376 fprintf(f, "%s\n", node_type_str(node->type));
377 ast_print(f, node->data.for_expr.elem_node, indent + 2);
378 ast_print(f, node->data.for_expr.array_expr, indent + 2);
379 if (node->data.for_expr.index_node) {
380 ast_print(f, node->data.for_expr.index_node, indent + 2);
381 }
382 ast_print(f, node->data.for_expr.body, indent + 2);
383 break;
384 case NodeTypeSwitchExpr:
385 fprintf(f, "%s\n", node_type_str(node->type));
386 ast_print(f, node->data.switch_expr.expr, indent + 2);
387 for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
388 AstNode *child_node = node->data.switch_expr.prongs.at(i);
389 ast_print(f, child_node, indent + 2);
390 }
391 break;
392 case NodeTypeSwitchProng:
393 fprintf(f, "%s\n", node_type_str(node->type));
394 for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
395 AstNode *child_node = node->data.switch_prong.items.at(i);
396 ast_print(f, child_node, indent + 2);
397 }
398 if (node->data.switch_prong.var_symbol) {
399 ast_print(f, node->data.switch_prong.var_symbol, indent + 2);
400 }
401 ast_print(f, node->data.switch_prong.expr, indent + 2);
402 break;
403 case NodeTypeSwitchRange:
404 fprintf(f, "%s\n", node_type_str(node->type));
405 ast_print(f, node->data.switch_range.start, indent + 2);
406 ast_print(f, node->data.switch_range.end, indent + 2);
407 break;
408 case NodeTypeLabel:
409 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
410 break;
411 case NodeTypeGoto:
412 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name));
413 break;
414 case NodeTypeBreak:
415 fprintf(f, "%s\n", node_type_str(node->type));
416 break;
417 case NodeTypeContinue:
418 fprintf(f, "%s\n", node_type_str(node->type));
419 break;
420 case NodeTypeUndefinedLiteral:
421 fprintf(f, "%s\n", node_type_str(node->type));
422 break;
423 case NodeTypeAsmExpr:
424 fprintf(f, "%s\n", node_type_str(node->type));
425 break;
426 case NodeTypeFieldAccessExpr:
427 fprintf(f, "%s '%s'\n", node_type_str(node->type),
428 buf_ptr(&node->data.field_access_expr.field_name));
429 ast_print(f, node->data.field_access_expr.struct_expr, indent + 2);
430 break;
431 case NodeTypeStructDecl:
432 fprintf(f, "%s '%s'\n",
433 node_type_str(node->type), buf_ptr(&node->data.struct_decl.name));
434 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
435 AstNode *child = node->data.struct_decl.fields.at(i);
436 ast_print(f, child, indent + 2);
437 }
438 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
439 AstNode *child = node->data.struct_decl.fns.at(i);
440 ast_print(f, child, indent + 2);
441 }
442 break;
443 case NodeTypeStructField:
444 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name));
445 if (node->data.struct_field.type) {
446 ast_print(f, node->data.struct_field.type, indent + 2);
447 }
448 break;
449 case NodeTypeStructValueField:
450 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));
451 ast_print(f, node->data.struct_val_field.expr, indent + 2);
452 break;
453 case NodeTypeContainerInitExpr:
454 fprintf(f, "%s\n", node_type_str(node->type));
455 ast_print(f, node->data.container_init_expr.type, indent + 2);
456 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
457 AstNode *child = node->data.container_init_expr.entries.at(i);
458 ast_print(f, child, indent + 2);
459 }
460 break;
461 case NodeTypeArrayType:
462 {
463 const char *const_str = node->data.array_type.is_const ? "const" : "var";
464 fprintf(f, "%s %s\n", node_type_str(node->type), const_str);
465 if (node->data.array_type.size) {
466 ast_print(f, node->data.array_type.size, indent + 2);
467 }
468 ast_print(f, node->data.array_type.child_type, indent + 2);
469 break;
470 }
471 case NodeTypeErrorType:
472 fprintf(f, "%s\n", node_type_str(node->type));
473 break;
474 }
475}
476
477struct AstRender {
478 int indent;
479 int indent_size;
480 FILE *f;
481};
482
483static void print_indent(AstRender *ar) {
484 for (int i = 0; i < ar->indent; i += 1) {
485 fprintf(ar->f, " ");
486 }
487}
488
489static void render_node(AstRender *ar, AstNode *node) {
490 assert(node->type == NodeTypeRoot || *node->parent_field == node);
491
492 switch (node->type) {
493 case NodeTypeRoot:
494 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
495 AstNode *child = node->data.root.top_level_decls.at(i);
496 print_indent(ar);
497 render_node(ar, child);
498
499 if (child->type == NodeTypeImport ||
500 child->type == NodeTypeVariableDeclaration ||
501 child->type == NodeTypeErrorValueDecl)
502 {
503 fprintf(ar->f, ";");
504 }
505 fprintf(ar->f, "\n");
506 }
507 break;
508 case NodeTypeRootExportDecl:
509 zig_panic("TODO");
510 case NodeTypeFnProto:
511 {
512 const char *fn_name = buf_ptr(&node->data.fn_proto.name);
513 const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
514 const char *extern_str = extern_string(node->data.fn_proto.is_extern);
515 fprintf(ar->f, "%s%sfn %s(", pub_str, extern_str, fn_name);
516 int arg_count = node->data.fn_proto.params.length;
517 bool is_var_args = node->data.fn_proto.is_var_args;
518 for (int arg_i = 0; arg_i < arg_count; arg_i += 1) {
519 AstNode *param_decl = node->data.fn_proto.params.at(arg_i);
520 assert(param_decl->type == NodeTypeParamDecl);
521 const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);
522 const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
523 fprintf(ar->f, "%s%s: ", noalias_str, arg_name);
524 render_node(ar, param_decl->data.param_decl.type);
525
526 if (arg_i + 1 < arg_count || is_var_args) {
527 fprintf(ar->f, ", ");
528 }
529 }
530 if (is_var_args) {
531 fprintf(ar->f, "...");
532 }
533 fprintf(ar->f, ")");
534
535 AstNode *return_type_node = node->data.fn_proto.return_type;
536 bool is_void = return_type_node->type != NodeTypeSymbol &&
537 buf_eql_str(&return_type_node->data.symbol_expr.symbol, "void");
538 if (!is_void) {
539 fprintf(ar->f, " -> ");
540 render_node(ar, return_type_node);
541 }
542 fprintf(ar->f, ";");
543 break;
544 }
545 case NodeTypeFnDef:
546 zig_panic("TODO");
547 case NodeTypeFnDecl:
548 zig_panic("TODO");
549 case NodeTypeParamDecl:
550 zig_panic("TODO");
551 case NodeTypeBlock:
552 zig_panic("TODO");
553 case NodeTypeDirective:
554 zig_panic("TODO");
555 case NodeTypeReturnExpr:
556 zig_panic("TODO");
557 case NodeTypeVariableDeclaration:
558 {
559 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
560 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
561 const char *var_name = buf_ptr(&node->data.variable_declaration.symbol);
562 const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);
563 fprintf(ar->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name);
564 if (node->data.variable_declaration.type) {
565 fprintf(ar->f, ": ");
566 render_node(ar, node->data.variable_declaration.type);
567 }
568 if (node->data.variable_declaration.expr) {
569 fprintf(ar->f, " = ");
570 render_node(ar, node->data.variable_declaration.expr);
571 }
572 break;
573 }
574 case NodeTypeErrorValueDecl:
575 zig_panic("TODO");
576 case NodeTypeBinOpExpr:
577 zig_panic("TODO");
578 case NodeTypeUnwrapErrorExpr:
579 zig_panic("TODO");
580 case NodeTypeNumberLiteral:
581 zig_panic("TODO");
582 case NodeTypeStringLiteral:
583 zig_panic("TODO");
584 case NodeTypeCharLiteral:
585 zig_panic("TODO");
586 case NodeTypeSymbol:
587 fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol));
588 break;
589 case NodeTypePrefixOpExpr:
590 {
591 PrefixOp op = node->data.prefix_op_expr.prefix_op;
592 fprintf(ar->f, "%s", prefix_op_str(op));
593
594 render_node(ar, node->data.prefix_op_expr.primary_expr);
595 break;
596 }
597 case NodeTypeFnCallExpr:
598 zig_panic("TODO");
599 case NodeTypeArrayAccessExpr:
600 zig_panic("TODO");
601 case NodeTypeSliceExpr:
602 zig_panic("TODO");
603 case NodeTypeFieldAccessExpr:
604 zig_panic("TODO");
605 case NodeTypeImport:
606 zig_panic("TODO");
607 case NodeTypeCImport:
608 zig_panic("TODO");
609 case NodeTypeBoolLiteral:
610 zig_panic("TODO");
611 case NodeTypeNullLiteral:
612 zig_panic("TODO");
613 case NodeTypeUndefinedLiteral:
614 zig_panic("TODO");
615 case NodeTypeIfBoolExpr:
616 zig_panic("TODO");
617 case NodeTypeIfVarExpr:
618 zig_panic("TODO");
619 case NodeTypeWhileExpr:
620 zig_panic("TODO");
621 case NodeTypeForExpr:
622 zig_panic("TODO");
623 case NodeTypeSwitchExpr:
624 zig_panic("TODO");
625 case NodeTypeSwitchProng:
626 zig_panic("TODO");
627 case NodeTypeSwitchRange:
628 zig_panic("TODO");
629 case NodeTypeLabel:
630 zig_panic("TODO");
631 case NodeTypeGoto:
632 zig_panic("TODO");
633 case NodeTypeBreak:
634 zig_panic("TODO");
635 case NodeTypeContinue:
636 zig_panic("TODO");
637 case NodeTypeAsmExpr:
638 zig_panic("TODO");
639 case NodeTypeStructDecl:
640 {
641 const char *struct_name = buf_ptr(&node->data.struct_decl.name);
642 const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod);
643 fprintf(ar->f, "%sstruct %s {\n", pub_str, struct_name);
644 ar->indent += ar->indent_size;
645 for (int field_i = 0; field_i < node->data.struct_decl.fields.length; field_i += 1) {
646 AstNode *field_node = node->data.struct_decl.fields.at(field_i);
647 assert(field_node->type == NodeTypeStructField);
648 const char *field_name = buf_ptr(&field_node->data.struct_field.name);
649 print_indent(ar);
650 fprintf(ar->f, "%s: ", field_name);
651 render_node(ar, field_node->data.struct_field.type);
652 fprintf(ar->f, ",\n");
653 }
654
655 ar->indent -= ar->indent_size;
656 fprintf(ar->f, "}\n");
657 break;
658 }
659 case NodeTypeStructField:
660 zig_panic("TODO");
661 case NodeTypeContainerInitExpr:
662 zig_panic("TODO");
663 case NodeTypeStructValueField:
664 zig_panic("TODO");
665 case NodeTypeArrayType:
666 zig_panic("TODO");
667 case NodeTypeErrorType:
668 zig_panic("TODO");
669 }
670}
671
672
673void ast_render(FILE *f, AstNode *node, int indent_size) {
674 AstRender ar = {0};
675 ar.f = f;
676 ar.indent_size = indent_size;
677 ar.indent = 0;
678
679 assert(node->type == NodeTypeRoot);
680
681 render_node(&ar, node);
682}
src/ast_render.hpp created+20
......@@ -0,0 +1,20 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_AST_RENDER_HPP
9#define ZIG_AST_RENDER_HPP
10
11#include "all_types.hpp"
12
13#include <stdio.h>
14
15void ast_print(FILE *f, AstNode *node, int indent);
16
17void ast_render(FILE *f, AstNode *node, int indent_size);
18
19#endif
20
src/codegen.cpp+2-1
......@@ -13,6 +13,7 @@
1313#include "error.hpp"
1414#include "analyze.hpp"
1515#include "errmsg.hpp"
16#include "ast_render.hpp"
1617
1718#include <stdio.h>
1819#include <errno.h>
......@@ -3117,7 +3118,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
31173118 &g->next_node_index);
31183119 assert(import_entry->root);
31193120 if (g->verbose) {
3120 ast_print(import_entry->root, 0);
3121 ast_print(stderr, import_entry->root, 0);
31213122 }
31223123
31233124 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
src/main.cpp+29-112
......@@ -11,6 +11,7 @@
1111#include "os.hpp"
1212#include "error.hpp"
1313#include "parseh.hpp"
14#include "ast_render.hpp"
1415
1516#include <stdio.h>
1617
......@@ -162,41 +163,10 @@ static int build(const char *arg0, int argc, char **argv) {
162163 return 0;
163164}
164165
165struct ParseHPrint {
166 ParseH parse_h;
167 FILE *f;
168 int cur_indent;
169};
170
171static const int indent_size = 4;
172
173static void print_indent(ParseHPrint *p) {
174 for (int i = 0; i < p->cur_indent; i += 1) {
175 fprintf(p->f, " ");
176 }
177}
178
179static Buf *node_to_buf(AstNode *node) {
180 if (node->type == NodeTypeSymbol) {
181 return &node->data.symbol_expr.symbol;
182 } else if (node->type == NodeTypePrefixOpExpr) {
183 PrefixOp op = node->data.prefix_op_expr.prefix_op;
184 const char *child_type_str = buf_ptr(node_to_buf(node->data.prefix_op_expr.primary_expr));
185 if (op == PrefixOpAddressOf) {
186 return buf_sprintf("&%s", child_type_str);
187 } else if (op == PrefixOpConstAddressOf) {
188 return buf_sprintf("&const %s", child_type_str);
189 } else {
190 zig_unreachable();
191 }
192 } else {
193 zig_unreachable();
194 }
195}
196
197166static int parseh(const char *arg0, int argc, char **argv) {
198167 char *in_file = nullptr;
199168 ZigList<const char *> clang_argv = {0};
169 ErrColor color = ErrColorAuto;
200170 for (int i = 0; i < argc; i += 1) {
201171 char *arg = argv[i];
202172 if (arg[0] == '-') {
......@@ -206,10 +176,24 @@ static int parseh(const char *arg0, int argc, char **argv) {
206176 if (i + 1 >= argc) {
207177 return usage(arg0);
208178 }
179 i += 1;
209180 clang_argv.append("-isystem");
210 clang_argv.append(argv[i + 1]);
181 clang_argv.append(argv[i]);
182 } else if (strcmp(arg, "--color") == 0) {
183 if (i + 1 >= argc) {
184 return usage(arg0);
185 }
211186 i += 1;
212 } else {
187 if (strcmp(argv[i], "auto") == 0) {
188 color = ErrColorAuto;
189 } else if (strcmp(argv[i], "on") == 0) {
190 color = ErrColorOn;
191 } else if (strcmp(argv[i], "off") == 0) {
192 color = ErrColorOff;
193 } else {
194 return usage(arg0);
195 }
196 } else {
213197 fprintf(stderr, "unrecognized argument: %s", arg);
214198 return usage(arg0);
215199 }
......@@ -231,91 +215,24 @@ static int parseh(const char *arg0, int argc, char **argv) {
231215 clang_argv.append("-isystem");
232216 clang_argv.append(buf_ptr(libc_include_path));
233217
234 ParseHPrint parse_h_print = {{{0}}};
235 ParseHPrint *p = &parse_h_print;
236 p->f = stdout;
237 p->cur_indent = 0;
238
239 parse_h_file(&p->parse_h, &clang_argv);
218 ImportTableEntry import = {0};
219 ZigList<ErrorMsg *> errors = {0};
220 int err = parse_h_file(&import, &errors, &clang_argv);
240221
241 if (p->parse_h.errors.length > 0) {
242 for (int i = 0; i < p->parse_h.errors.length; i += 1) {
243 ErrorMsg *err_msg = p->parse_h.errors.at(i);
244 // TODO respect --color arg
245 print_err_msg(err_msg, ErrColorAuto);
246 }
222 if (err) {
223 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
247224 return EXIT_FAILURE;
248225 }
249226
250 for (int var_i = 0; var_i < p->parse_h.var_list.length; var_i += 1) {
251 AstNode *var_decl = p->parse_h.var_list.at(var_i);
252 assert(var_decl->type == NodeTypeVariableDeclaration);
253 const char *pub_str = (var_decl->data.variable_declaration.visib_mod == VisibModPub) ? "pub " : "";
254 const char *extern_str = var_decl->data.variable_declaration.is_extern ? "extern " : "";
255 const char *var_name = buf_ptr(&var_decl->data.variable_declaration.symbol);
256 const char *const_or_var = var_decl->data.variable_declaration.is_const ? "const" : "var";
257 print_indent(p);
258 fprintf(p->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name);
259 if (var_decl->data.variable_declaration.type) {
260 fprintf(p->f, ": %s", buf_ptr(node_to_buf(var_decl->data.variable_declaration.type)));
261 }
262 if (var_decl->data.variable_declaration.expr) {
263 fprintf(p->f, " = %s", buf_ptr(node_to_buf(var_decl->data.variable_declaration.expr)));
227 if (errors.length > 0) {
228 for (int i = 0; i < errors.length; i += 1) {
229 ErrorMsg *err_msg = errors.at(i);
230 print_err_msg(err_msg, color);
264231 }
265 fprintf(p->f, ";\n");
266 }
267
268 for (int struct_i = 0; struct_i < p->parse_h.struct_list.length; struct_i += 1) {
269 AstNode *struct_decl = p->parse_h.struct_list.at(struct_i);
270 assert(struct_decl->type == NodeTypeStructDecl);
271 const char *struct_name = buf_ptr(&struct_decl->data.struct_decl.name);
272 print_indent(p);
273 fprintf(p->f, "struct %s {\n", struct_name);
274 p->cur_indent += indent_size;
275 for (int field_i = 0; field_i < struct_decl->data.struct_decl.fields.length; field_i += 1) {
276 AstNode *field_node = struct_decl->data.struct_decl.fields.at(field_i);
277 assert(field_node->type == NodeTypeStructField);
278 const char *field_name = buf_ptr(&field_node->data.struct_field.name);
279 Buf *type_name = node_to_buf(field_node->data.struct_field.type);
280 print_indent(p);
281 fprintf(p->f, "%s: %s,\n", field_name, buf_ptr(type_name));
282 }
283
284 p->cur_indent -= indent_size;
285 fprintf(p->f, "}\n\n");
232 return EXIT_FAILURE;
286233 }
287234
288 for (int fn_i = 0; fn_i < p->parse_h.fn_list.length; fn_i += 1) {
289 AstNode *fn_proto = p->parse_h.fn_list.at(fn_i);
290 assert(fn_proto->type == NodeTypeFnProto);
291 print_indent(p);
292 const char *fn_name = buf_ptr(&fn_proto->data.fn_proto.name);
293 const char *pub_str = (fn_proto->data.fn_proto.visib_mod == VisibModPub) ? "pub " : "";
294 const char *extern_str = fn_proto->data.fn_proto.is_extern ? "extern " : "";
295 fprintf(p->f, "%s%sfn %s(", pub_str, extern_str, fn_name);
296 int arg_count = fn_proto->data.fn_proto.params.length;
297 bool is_var_args = fn_proto->data.fn_proto.is_var_args;
298 for (int arg_i = 0; arg_i < arg_count; arg_i += 1) {
299 AstNode *param_decl = fn_proto->data.fn_proto.params.at(arg_i);
300 assert(param_decl->type == NodeTypeParamDecl);
301 const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);
302 Buf *arg_type = node_to_buf(param_decl->data.param_decl.type);
303 const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
304 fprintf(p->f, "%s%s: %s", noalias_str, arg_name, buf_ptr(arg_type));
305 if (arg_i + 1 < arg_count || is_var_args) {
306 fprintf(p->f, ", ");
307 }
308 }
309 if (is_var_args) {
310 fprintf(p->f, "...");
311 }
312 fprintf(p->f, ")");
313 Buf *return_type_name = node_to_buf(fn_proto->data.fn_proto.return_type);
314 if (!buf_eql_str(return_type_name, "void")) {
315 fprintf(p->f, " -> %s", buf_ptr(return_type_name));
316 }
317 fprintf(p->f, ";\n");
318 }
235 ast_render(stdout, import.root, 4);
319236
320237 return 0;
321238}
src/parseh.cpp+33-8
......@@ -9,6 +9,8 @@
99#include "config.h"
1010#include "os.hpp"
1111#include "error.hpp"
12#include "parser.hpp"
13#include "all_types.hpp"
1214
1315#include <clang/Frontend/ASTUnit.h>
1416#include <clang/Frontend/CompilerInstance.h>
......@@ -18,10 +20,12 @@
1820using namespace clang;
1921
2022struct Context {
21 ParseH *parse_h;
23 ImportTableEntry *import;
24 ZigList<ErrorMsg *> *errors;
2225 bool warnings_on;
2326 VisibMod visib_mod;
2427 AstNode *c_void_decl_node;
28 AstNode *root;
2529 HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;
2630};
2731
......@@ -30,6 +34,7 @@ static AstNode *make_qual_type_node(Context *c, QualType qt);
3034static AstNode *create_node(Context *c, NodeType type) {
3135 AstNode *node = allocate<AstNode>(1);
3236 node->type = type;
37 node->owner = c->import;
3338 return node;
3439}
3540
......@@ -44,6 +49,10 @@ static const char *decl_name(const Decl *decl) {
4449 return (const char *)named_decl->getName().bytes_begin();
4550}
4651
52static ZigList<AstNode *> *create_empty_directives(Context *c) {
53 return allocate<ZigList<AstNode*>>(1);
54}
55
4756static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_node) {
4857 if (!target_node) {
4958 return nullptr;
......@@ -53,7 +62,10 @@ static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_n
5362 node->data.variable_declaration.is_const = true;
5463 node->data.variable_declaration.visib_mod = c->visib_mod;
5564 node->data.variable_declaration.expr = target_node;
56 c->parse_h->var_list.append(node);
65 node->data.variable_declaration.directives = create_empty_directives(c);
66 normalize_parent_ptrs(node);
67
68 c->root->data.root.top_level_decls.append(node);
5769 return node;
5870}
5971
......@@ -79,6 +91,7 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
7991 AstNode *node = create_node(c, NodeTypePrefixOpExpr);
8092 node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf;
8193 node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node);
94 normalize_parent_ptrs(node);
8295 return node;
8396}
8497
......@@ -255,6 +268,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
255268 AstNode *node = create_node(c, NodeTypeFnProto);
256269 node->data.fn_proto.is_extern = true;
257270 node->data.fn_proto.visib_mod = c->visib_mod;
271 node->data.fn_proto.directives = create_empty_directives(c);
258272 node->data.fn_proto.is_var_args = fn_decl->isVariadic();
259273 buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl));
260274
......@@ -276,6 +290,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
276290 break;
277291 }
278292
293 normalize_parent_ptrs(param_decl_node);
279294 node->data.fn_proto.params.append(param_decl_node);
280295 }
281296
......@@ -296,8 +311,9 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
296311 return;
297312 }
298313
299 c->parse_h->fn_list.append(node);
314 normalize_parent_ptrs(node);
300315
316 c->root->data.root.top_level_decls.append(node);
301317}
302318
303319static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
......@@ -322,6 +338,7 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
322338 AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt));
323339
324340 if (node) {
341 normalize_parent_ptrs(node);
325342 c->type_table.put(type_name, true);
326343 }
327344}
......@@ -345,7 +362,9 @@ static bool decl_visitor(void *context, const Decl *decl) {
345362 return true;
346363}
347364
348int parse_h_buf(ParseH *parse_h, Buf *source, const char **args, int args_len, const char *libc_include_path) {
365int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
366 const char **args, int args_len, const char *libc_include_path)
367{
349368 int err;
350369 Buf tmp_file_path = BUF_INIT;
351370 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
......@@ -361,17 +380,18 @@ int parse_h_buf(ParseH *parse_h, Buf *source, const char **args, int args_len, c
361380 clang_argv.append(args[i]);
362381 }
363382
364 err = parse_h_file(parse_h, &clang_argv);
383 err = parse_h_file(import, errors, &clang_argv);
365384
366385 os_delete_file(&tmp_file_path);
367386
368387 return err;
369388}
370389
371int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {
390int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<const char *> *clang_argv) {
372391 Context context = {0};
373392 Context *c = &context;
374 c->parse_h = parse_h;
393 c->import = import;
394 c->errors = errors;
375395 c->type_table.init(64);
376396
377397 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
......@@ -455,13 +475,18 @@ int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {
455475
456476 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
457477
458 parse_h->errors.append(err_msg);
478 c->errors->append(err_msg);
459479 }
460480
461481 return 0;
462482 }
463483
484 c->root = create_node(c, NodeTypeRoot);
464485 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
486 normalize_parent_ptrs(c->root);
487
488 import->root = c->root;
489 import->is_c_import = true;
465490
466491 return 0;
467492}
src/parseh.hpp+4-2
......@@ -11,7 +11,9 @@
1111
1212#include "all_types.hpp"
1313
14int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv);
15int parse_h_buf(ParseH *parse_h, Buf *source, const char **args, int args_len, const char *libc_include_path);
14int parse_h_file(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,
15 ZigList<const char *> *clang_argv);
16int parse_h_buf(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,
17 Buf *source, const char **args, int args_len, const char *libc_include_path);
1618
1719#endif
src/parser.cpp-459
......@@ -14,465 +14,6 @@
1414#include <limits.h>
1515#include <errno.h>
1616
17static const char *bin_op_str(BinOpType bin_op) {
18 switch (bin_op) {
19 case BinOpTypeInvalid: return "(invalid)";
20 case BinOpTypeBoolOr: return "||";
21 case BinOpTypeBoolAnd: return "&&";
22 case BinOpTypeCmpEq: return "==";
23 case BinOpTypeCmpNotEq: return "!=";
24 case BinOpTypeCmpLessThan: return "<";
25 case BinOpTypeCmpGreaterThan: return ">";
26 case BinOpTypeCmpLessOrEq: return "<=";
27 case BinOpTypeCmpGreaterOrEq: return ">=";
28 case BinOpTypeBinOr: return "|";
29 case BinOpTypeBinXor: return "^";
30 case BinOpTypeBinAnd: return "&";
31 case BinOpTypeBitShiftLeft: return "<<";
32 case BinOpTypeBitShiftRight: return ">>";
33 case BinOpTypeAdd: return "+";
34 case BinOpTypeSub: return "-";
35 case BinOpTypeMult: return "*";
36 case BinOpTypeDiv: return "/";
37 case BinOpTypeMod: return "%";
38 case BinOpTypeAssign: return "=";
39 case BinOpTypeAssignTimes: return "*=";
40 case BinOpTypeAssignDiv: return "/=";
41 case BinOpTypeAssignMod: return "%=";
42 case BinOpTypeAssignPlus: return "+=";
43 case BinOpTypeAssignMinus: return "-=";
44 case BinOpTypeAssignBitShiftLeft: return "<<=";
45 case BinOpTypeAssignBitShiftRight: return ">>=";
46 case BinOpTypeAssignBitAnd: return "&=";
47 case BinOpTypeAssignBitXor: return "^=";
48 case BinOpTypeAssignBitOr: return "|=";
49 case BinOpTypeAssignBoolAnd: return "&&=";
50 case BinOpTypeAssignBoolOr: return "||=";
51 case BinOpTypeUnwrapMaybe: return "??";
52 case BinOpTypeStrCat: return "++";
53 }
54 zig_unreachable();
55}
56
57static const char *prefix_op_str(PrefixOp prefix_op) {
58 switch (prefix_op) {
59 case PrefixOpInvalid: return "(invalid)";
60 case PrefixOpNegation: return "-";
61 case PrefixOpBoolNot: return "!";
62 case PrefixOpBinNot: return "~";
63 case PrefixOpAddressOf: return "&";
64 case PrefixOpConstAddressOf: return "&const";
65 case PrefixOpDereference: return "*";
66 case PrefixOpMaybe: return "?";
67 case PrefixOpError: return "%";
68 case PrefixOpUnwrapError: return "%%";
69 }
70 zig_unreachable();
71}
72
73static const char *return_prefix_str(ReturnKind kind) {
74 switch (kind) {
75 case ReturnKindError: return "%";
76 case ReturnKindMaybe: return "?";
77 case ReturnKindUnconditional: return "";
78 }
79 zig_unreachable();
80}
81
82const char *node_type_str(NodeType node_type) {
83 switch (node_type) {
84 case NodeTypeRoot:
85 return "Root";
86 case NodeTypeRootExportDecl:
87 return "RootExportDecl";
88 case NodeTypeFnDef:
89 return "FnDef";
90 case NodeTypeFnDecl:
91 return "FnDecl";
92 case NodeTypeFnProto:
93 return "FnProto";
94 case NodeTypeParamDecl:
95 return "ParamDecl";
96 case NodeTypeBlock:
97 return "Block";
98 case NodeTypeBinOpExpr:
99 return "BinOpExpr";
100 case NodeTypeUnwrapErrorExpr:
101 return "UnwrapErrorExpr";
102 case NodeTypeFnCallExpr:
103 return "FnCallExpr";
104 case NodeTypeArrayAccessExpr:
105 return "ArrayAccessExpr";
106 case NodeTypeSliceExpr:
107 return "SliceExpr";
108 case NodeTypeDirective:
109 return "Directive";
110 case NodeTypeReturnExpr:
111 return "ReturnExpr";
112 case NodeTypeVariableDeclaration:
113 return "VariableDeclaration";
114 case NodeTypeErrorValueDecl:
115 return "ErrorValueDecl";
116 case NodeTypeNumberLiteral:
117 return "NumberLiteral";
118 case NodeTypeStringLiteral:
119 return "StringLiteral";
120 case NodeTypeCharLiteral:
121 return "CharLiteral";
122 case NodeTypeSymbol:
123 return "Symbol";
124 case NodeTypePrefixOpExpr:
125 return "PrefixOpExpr";
126 case NodeTypeImport:
127 return "Import";
128 case NodeTypeCImport:
129 return "CImport";
130 case NodeTypeBoolLiteral:
131 return "BoolLiteral";
132 case NodeTypeNullLiteral:
133 return "NullLiteral";
134 case NodeTypeUndefinedLiteral:
135 return "UndefinedLiteral";
136 case NodeTypeIfBoolExpr:
137 return "IfBoolExpr";
138 case NodeTypeIfVarExpr:
139 return "IfVarExpr";
140 case NodeTypeWhileExpr:
141 return "WhileExpr";
142 case NodeTypeForExpr:
143 return "ForExpr";
144 case NodeTypeSwitchExpr:
145 return "SwitchExpr";
146 case NodeTypeSwitchProng:
147 return "SwitchProng";
148 case NodeTypeSwitchRange:
149 return "SwitchRange";
150 case NodeTypeLabel:
151 return "Label";
152 case NodeTypeGoto:
153 return "Goto";
154 case NodeTypeBreak:
155 return "Break";
156 case NodeTypeContinue:
157 return "Continue";
158 case NodeTypeAsmExpr:
159 return "AsmExpr";
160 case NodeTypeFieldAccessExpr:
161 return "FieldAccessExpr";
162 case NodeTypeStructDecl:
163 return "StructDecl";
164 case NodeTypeStructField:
165 return "StructField";
166 case NodeTypeStructValueField:
167 return "StructValueField";
168 case NodeTypeContainerInitExpr:
169 return "ContainerInitExpr";
170 case NodeTypeArrayType:
171 return "ArrayType";
172 case NodeTypeErrorType:
173 return "ErrorType";
174 }
175 zig_unreachable();
176}
177
178void ast_print(AstNode *node, int indent) {
179 for (int i = 0; i < indent; i += 1) {
180 fprintf(stderr, " ");
181 }
182 assert(node->type == NodeTypeRoot || *node->parent_field == node);
183
184 switch (node->type) {
185 case NodeTypeRoot:
186 fprintf(stderr, "%s\n", node_type_str(node->type));
187 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
188 AstNode *child = node->data.root.top_level_decls.at(i);
189 ast_print(child, indent + 2);
190 }
191 break;
192 case NodeTypeRootExportDecl:
193 fprintf(stderr, "%s %s '%s'\n", node_type_str(node->type),
194 buf_ptr(&node->data.root_export_decl.type),
195 buf_ptr(&node->data.root_export_decl.name));
196 break;
197 case NodeTypeFnDef:
198 {
199 fprintf(stderr, "%s\n", node_type_str(node->type));
200 AstNode *child = node->data.fn_def.fn_proto;
201 ast_print(child, indent + 2);
202 ast_print(node->data.fn_def.body, indent + 2);
203 break;
204 }
205 case NodeTypeFnProto:
206 {
207 Buf *name_buf = &node->data.fn_proto.name;
208 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
209
210 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
211 AstNode *child = node->data.fn_proto.params.at(i);
212 ast_print(child, indent + 2);
213 }
214
215 ast_print(node->data.fn_proto.return_type, indent + 2);
216
217 break;
218 }
219 case NodeTypeBlock:
220 {
221 fprintf(stderr, "%s\n", node_type_str(node->type));
222 for (int i = 0; i < node->data.block.statements.length; i += 1) {
223 AstNode *child = node->data.block.statements.at(i);
224 ast_print(child, indent + 2);
225 }
226 break;
227 }
228 case NodeTypeParamDecl:
229 {
230 Buf *name_buf = &node->data.param_decl.name;
231 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
232
233 ast_print(node->data.param_decl.type, indent + 2);
234
235 break;
236 }
237 case NodeTypeReturnExpr:
238 {
239 const char *prefix_str = return_prefix_str(node->data.return_expr.kind);
240 fprintf(stderr, "%s%s\n", prefix_str, node_type_str(node->type));
241 if (node->data.return_expr.expr)
242 ast_print(node->data.return_expr.expr, indent + 2);
243 break;
244 }
245 case NodeTypeVariableDeclaration:
246 {
247 Buf *name_buf = &node->data.variable_declaration.symbol;
248 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
249 if (node->data.variable_declaration.type)
250 ast_print(node->data.variable_declaration.type, indent + 2);
251 if (node->data.variable_declaration.expr)
252 ast_print(node->data.variable_declaration.expr, indent + 2);
253 break;
254 }
255 case NodeTypeErrorValueDecl:
256 {
257 Buf *name_buf = &node->data.error_value_decl.name;
258 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
259 break;
260 }
261 case NodeTypeFnDecl:
262 fprintf(stderr, "%s\n", node_type_str(node->type));
263 ast_print(node->data.fn_decl.fn_proto, indent + 2);
264 break;
265 case NodeTypeBinOpExpr:
266 fprintf(stderr, "%s %s\n", node_type_str(node->type),
267 bin_op_str(node->data.bin_op_expr.bin_op));
268 ast_print(node->data.bin_op_expr.op1, indent + 2);
269 ast_print(node->data.bin_op_expr.op2, indent + 2);
270 break;
271 case NodeTypeUnwrapErrorExpr:
272 fprintf(stderr, "%s\n", node_type_str(node->type));
273 ast_print(node->data.unwrap_err_expr.op1, indent + 2);
274 if (node->data.unwrap_err_expr.symbol) {
275 ast_print(node->data.unwrap_err_expr.symbol, indent + 2);
276 }
277 ast_print(node->data.unwrap_err_expr.op2, indent + 2);
278 break;
279 case NodeTypeFnCallExpr:
280 fprintf(stderr, "%s\n", node_type_str(node->type));
281 ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2);
282 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
283 AstNode *child = node->data.fn_call_expr.params.at(i);
284 ast_print(child, indent + 2);
285 }
286 break;
287 case NodeTypeArrayAccessExpr:
288 fprintf(stderr, "%s\n", node_type_str(node->type));
289 ast_print(node->data.array_access_expr.array_ref_expr, indent + 2);
290 ast_print(node->data.array_access_expr.subscript, indent + 2);
291 break;
292 case NodeTypeSliceExpr:
293 fprintf(stderr, "%s\n", node_type_str(node->type));
294 ast_print(node->data.slice_expr.array_ref_expr, indent + 2);
295 ast_print(node->data.slice_expr.start, indent + 2);
296 if (node->data.slice_expr.end) {
297 ast_print(node->data.slice_expr.end, indent + 2);
298 }
299 break;
300 case NodeTypeDirective:
301 fprintf(stderr, "%s\n", node_type_str(node->type));
302 break;
303 case NodeTypePrefixOpExpr:
304 fprintf(stderr, "%s %s\n", node_type_str(node->type),
305 prefix_op_str(node->data.prefix_op_expr.prefix_op));
306 ast_print(node->data.prefix_op_expr.primary_expr, indent + 2);
307 break;
308 case NodeTypeNumberLiteral:
309 {
310 NumLit kind = node->data.number_literal.kind;
311 const char *name = node_type_str(node->type);
312 if (kind == NumLitUInt) {
313 fprintf(stderr, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint);
314 } else {
315 fprintf(stderr, "%s float %f\n", name, node->data.number_literal.data.x_float);
316 }
317 break;
318 }
319 case NodeTypeStringLiteral:
320 {
321 const char *c = node->data.string_literal.c ? "c" : "";
322 fprintf(stderr, "StringLiteral %s'%s'\n", c,
323 buf_ptr(&node->data.string_literal.buf));
324 break;
325 }
326 case NodeTypeCharLiteral:
327 {
328 fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
329 break;
330 }
331 case NodeTypeSymbol:
332 fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
333 break;
334 case NodeTypeImport:
335 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path));
336 break;
337 case NodeTypeCImport:
338 fprintf(stderr, "%s\n", node_type_str(node->type));
339 ast_print(node->data.c_import.block, indent + 2);
340 break;
341 case NodeTypeBoolLiteral:
342 fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
343 node->data.bool_literal.value ? "true" : "false");
344 break;
345 case NodeTypeNullLiteral:
346 fprintf(stderr, "%s\n", node_type_str(node->type));
347 break;
348 case NodeTypeIfBoolExpr:
349 fprintf(stderr, "%s\n", node_type_str(node->type));
350 if (node->data.if_bool_expr.condition)
351 ast_print(node->data.if_bool_expr.condition, indent + 2);
352 ast_print(node->data.if_bool_expr.then_block, indent + 2);
353 if (node->data.if_bool_expr.else_node)
354 ast_print(node->data.if_bool_expr.else_node, indent + 2);
355 break;
356 case NodeTypeIfVarExpr:
357 {
358 Buf *name_buf = &node->data.if_var_expr.var_decl.symbol;
359 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
360 if (node->data.if_var_expr.var_decl.type)
361 ast_print(node->data.if_var_expr.var_decl.type, indent + 2);
362 if (node->data.if_var_expr.var_decl.expr)
363 ast_print(node->data.if_var_expr.var_decl.expr, indent + 2);
364 ast_print(node->data.if_var_expr.then_block, indent + 2);
365 if (node->data.if_var_expr.else_node)
366 ast_print(node->data.if_var_expr.else_node, indent + 2);
367 break;
368 }
369 case NodeTypeWhileExpr:
370 fprintf(stderr, "%s\n", node_type_str(node->type));
371 ast_print(node->data.while_expr.condition, indent + 2);
372 ast_print(node->data.while_expr.body, indent + 2);
373 break;
374 case NodeTypeForExpr:
375 fprintf(stderr, "%s\n", node_type_str(node->type));
376 ast_print(node->data.for_expr.elem_node, indent + 2);
377 ast_print(node->data.for_expr.array_expr, indent + 2);
378 if (node->data.for_expr.index_node) {
379 ast_print(node->data.for_expr.index_node, indent + 2);
380 }
381 ast_print(node->data.for_expr.body, indent + 2);
382 break;
383 case NodeTypeSwitchExpr:
384 fprintf(stderr, "%s\n", node_type_str(node->type));
385 ast_print(node->data.switch_expr.expr, indent + 2);
386 for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
387 AstNode *child_node = node->data.switch_expr.prongs.at(i);
388 ast_print(child_node, indent + 2);
389 }
390 break;
391 case NodeTypeSwitchProng:
392 fprintf(stderr, "%s\n", node_type_str(node->type));
393 for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
394 AstNode *child_node = node->data.switch_prong.items.at(i);
395 ast_print(child_node, indent + 2);
396 }
397 if (node->data.switch_prong.var_symbol) {
398 ast_print(node->data.switch_prong.var_symbol, indent + 2);
399 }
400 ast_print(node->data.switch_prong.expr, indent + 2);
401 break;
402 case NodeTypeSwitchRange:
403 fprintf(stderr, "%s\n", node_type_str(node->type));
404 ast_print(node->data.switch_range.start, indent + 2);
405 ast_print(node->data.switch_range.end, indent + 2);
406 break;
407 case NodeTypeLabel:
408 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
409 break;
410 case NodeTypeGoto:
411 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name));
412 break;
413 case NodeTypeBreak:
414 fprintf(stderr, "%s\n", node_type_str(node->type));
415 break;
416 case NodeTypeContinue:
417 fprintf(stderr, "%s\n", node_type_str(node->type));
418 break;
419 case NodeTypeUndefinedLiteral:
420 fprintf(stderr, "%s\n", node_type_str(node->type));
421 break;
422 case NodeTypeAsmExpr:
423 fprintf(stderr, "%s\n", node_type_str(node->type));
424 break;
425 case NodeTypeFieldAccessExpr:
426 fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
427 buf_ptr(&node->data.field_access_expr.field_name));
428 ast_print(node->data.field_access_expr.struct_expr, indent + 2);
429 break;
430 case NodeTypeStructDecl:
431 fprintf(stderr, "%s '%s'\n",
432 node_type_str(node->type), buf_ptr(&node->data.struct_decl.name));
433 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
434 AstNode *child = node->data.struct_decl.fields.at(i);
435 ast_print(child, indent + 2);
436 }
437 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
438 AstNode *child = node->data.struct_decl.fns.at(i);
439 ast_print(child, indent + 2);
440 }
441 break;
442 case NodeTypeStructField:
443 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name));
444 if (node->data.struct_field.type) {
445 ast_print(node->data.struct_field.type, indent + 2);
446 }
447 break;
448 case NodeTypeStructValueField:
449 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));
450 ast_print(node->data.struct_val_field.expr, indent + 2);
451 break;
452 case NodeTypeContainerInitExpr:
453 fprintf(stderr, "%s\n", node_type_str(node->type));
454 ast_print(node->data.container_init_expr.type, indent + 2);
455 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
456 AstNode *child = node->data.container_init_expr.entries.at(i);
457 ast_print(child, indent + 2);
458 }
459 break;
460 case NodeTypeArrayType:
461 {
462 const char *const_str = node->data.array_type.is_const ? "const" : "var";
463 fprintf(stderr, "%s %s\n", node_type_str(node->type), const_str);
464 if (node->data.array_type.size) {
465 ast_print(node->data.array_type.size, indent + 2);
466 }
467 ast_print(node->data.array_type.child_type, indent + 2);
468 break;
469 }
470 case NodeTypeErrorType:
471 fprintf(stderr, "%s\n", node_type_str(node->type));
472 break;
473 }
474}
475
47617struct ParseContext {
47718 Buf *buf;
47819 AstNode *root;