diff --git a/CMakeLists.txt b/CMakeLists.txt index a745cf1faa..29a270d224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ include_directories( ) set(ZIG_SOURCES + "${CMAKE_SOURCE_DIR}/src/ast_render.cpp" "${CMAKE_SOURCE_DIR}/src/bignum.cpp" "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" "${CMAKE_SOURCE_DIR}/src/parser.cpp" diff --git a/doc/targets.md b/doc/targets.md index 4d8e22f0e5..eb856a3d53 100644 --- a/doc/targets.md +++ b/doc/targets.md @@ -11,3 +11,6 @@ for the target when an exported or external function has a byvalue struct. Write the target-specific code in std.zig. Update the C integer types to be the correct size for the target. + +Add the conditional compilation code for the page size global. It is hardcoded +for each target. diff --git a/src/all_types.hpp b/src/all_types.hpp index 4e464d7137..c731e5fd99 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -894,6 +894,7 @@ struct ImportTableEntry { ZigList *line_offsets; BlockContext *block_context; ZigList importers; + bool is_c_import; // reminder: hash tables must be initialized before use HashMap fn_table; diff --git a/src/analyze.cpp b/src/analyze.cpp index a8434cde36..121c4c04ff 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1039,15 +1039,15 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo } } -static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { +static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, AstNode *node) { assert(node->type == NodeTypeCImport); AstNode *block_node = node->data.c_import.block; - BlockContext *child_context = new_block_context(node, import->block_context); + BlockContext *child_context = new_block_context(node, parent_import->block_context); child_context->c_import_buf = buf_alloc(); - TypeTableEntry *resolved_type = analyze_block_expr(g, import, child_context, + TypeTableEntry *resolved_type = analyze_block_expr(g, parent_import, child_context, g->builtin_types.entry_void, block_node); if (resolved_type->id == TypeTableEntryIdInvalid) { @@ -1055,23 +1055,27 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *import, AstNode } find_libc_path(g); + + ImportTableEntry child_import = {0}; + ZigList errors = {0}; + int err; - ParseH parse_h = {{0}}; - if ((err = parse_h_buf(&parse_h, child_context->c_import_buf, g->clang_argv, g->clang_argv_len, + if ((err = parse_h_buf(&child_import, &errors, child_context->c_import_buf, g->clang_argv, g->clang_argv_len, buf_ptr(g->libc_include_path)))) { zig_panic("unable to parse h file: %s\n", err_str(err)); } - if (parse_h.errors.length > 0) { + if (errors.length > 0) { ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed")); - for (int i = 0; i < parse_h.errors.length; i += 1) { - ErrorMsg *err_msg = parse_h.errors.at(i); + for (int i = 0; i < errors.length; i += 1) { + ErrorMsg *err_msg = errors.at(i); err_msg_add_note(parent_err_msg, err_msg); } - } else { - zig_panic("TODO integrate the parsed AST"); + return; } + + zig_panic("TODO integrate the AST"); } static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { diff --git a/src/ast_render.cpp b/src/ast_render.cpp new file mode 100644 index 0000000000..084191bdc8 --- /dev/null +++ b/src/ast_render.cpp @@ -0,0 +1,682 @@ +#include "ast_render.hpp" + +#include + +static const char *bin_op_str(BinOpType bin_op) { + switch (bin_op) { + case BinOpTypeInvalid: return "(invalid)"; + case BinOpTypeBoolOr: return "||"; + case BinOpTypeBoolAnd: return "&&"; + case BinOpTypeCmpEq: return "=="; + case BinOpTypeCmpNotEq: return "!="; + case BinOpTypeCmpLessThan: return "<"; + case BinOpTypeCmpGreaterThan: return ">"; + case BinOpTypeCmpLessOrEq: return "<="; + case BinOpTypeCmpGreaterOrEq: return ">="; + case BinOpTypeBinOr: return "|"; + case BinOpTypeBinXor: return "^"; + case BinOpTypeBinAnd: return "&"; + case BinOpTypeBitShiftLeft: return "<<"; + case BinOpTypeBitShiftRight: return ">>"; + case BinOpTypeAdd: return "+"; + case BinOpTypeSub: return "-"; + case BinOpTypeMult: return "*"; + case BinOpTypeDiv: return "/"; + case BinOpTypeMod: return "%"; + case BinOpTypeAssign: return "="; + case BinOpTypeAssignTimes: return "*="; + case BinOpTypeAssignDiv: return "/="; + case BinOpTypeAssignMod: return "%="; + case BinOpTypeAssignPlus: return "+="; + case BinOpTypeAssignMinus: return "-="; + case BinOpTypeAssignBitShiftLeft: return "<<="; + case BinOpTypeAssignBitShiftRight: return ">>="; + case BinOpTypeAssignBitAnd: return "&="; + case BinOpTypeAssignBitXor: return "^="; + case BinOpTypeAssignBitOr: return "|="; + case BinOpTypeAssignBoolAnd: return "&&="; + case BinOpTypeAssignBoolOr: return "||="; + case BinOpTypeUnwrapMaybe: return "??"; + case BinOpTypeStrCat: return "++"; + } +} + +static const char *prefix_op_str(PrefixOp prefix_op) { + switch (prefix_op) { + case PrefixOpInvalid: return "(invalid)"; + case PrefixOpNegation: return "-"; + case PrefixOpBoolNot: return "!"; + case PrefixOpBinNot: return "~"; + case PrefixOpAddressOf: return "&"; + case PrefixOpConstAddressOf: return "&const "; + case PrefixOpDereference: return "*"; + case PrefixOpMaybe: return "?"; + case PrefixOpError: return "%"; + case PrefixOpUnwrapError: return "%%"; + } +} + +static const char *return_prefix_str(ReturnKind kind) { + switch (kind) { + case ReturnKindError: return "%"; + case ReturnKindMaybe: return "?"; + case ReturnKindUnconditional: return ""; + } +} + +static const char *visib_mod_string(VisibMod mod) { + switch (mod) { + case VisibModPub: return "pub "; + case VisibModPrivate: return ""; + case VisibModExport: return "export "; + } +} + +static const char *extern_string(bool is_extern) { + return is_extern ? "export " : ""; +} + +static const char *const_or_var_string(bool is_const) { + return is_const ? "const" : "var"; +} + +static const char *node_type_str(NodeType node_type) { + switch (node_type) { + case NodeTypeRoot: + return "Root"; + case NodeTypeRootExportDecl: + return "RootExportDecl"; + case NodeTypeFnDef: + return "FnDef"; + case NodeTypeFnDecl: + return "FnDecl"; + case NodeTypeFnProto: + return "FnProto"; + case NodeTypeParamDecl: + return "ParamDecl"; + case NodeTypeBlock: + return "Block"; + case NodeTypeBinOpExpr: + return "BinOpExpr"; + case NodeTypeUnwrapErrorExpr: + return "UnwrapErrorExpr"; + case NodeTypeFnCallExpr: + return "FnCallExpr"; + case NodeTypeArrayAccessExpr: + return "ArrayAccessExpr"; + case NodeTypeSliceExpr: + return "SliceExpr"; + case NodeTypeDirective: + return "Directive"; + case NodeTypeReturnExpr: + return "ReturnExpr"; + case NodeTypeVariableDeclaration: + return "VariableDeclaration"; + case NodeTypeErrorValueDecl: + return "ErrorValueDecl"; + case NodeTypeNumberLiteral: + return "NumberLiteral"; + case NodeTypeStringLiteral: + return "StringLiteral"; + case NodeTypeCharLiteral: + return "CharLiteral"; + case NodeTypeSymbol: + return "Symbol"; + case NodeTypePrefixOpExpr: + return "PrefixOpExpr"; + case NodeTypeImport: + return "Import"; + case NodeTypeCImport: + return "CImport"; + case NodeTypeBoolLiteral: + return "BoolLiteral"; + case NodeTypeNullLiteral: + return "NullLiteral"; + case NodeTypeUndefinedLiteral: + return "UndefinedLiteral"; + case NodeTypeIfBoolExpr: + return "IfBoolExpr"; + case NodeTypeIfVarExpr: + return "IfVarExpr"; + case NodeTypeWhileExpr: + return "WhileExpr"; + case NodeTypeForExpr: + return "ForExpr"; + case NodeTypeSwitchExpr: + return "SwitchExpr"; + case NodeTypeSwitchProng: + return "SwitchProng"; + case NodeTypeSwitchRange: + return "SwitchRange"; + case NodeTypeLabel: + return "Label"; + case NodeTypeGoto: + return "Goto"; + case NodeTypeBreak: + return "Break"; + case NodeTypeContinue: + return "Continue"; + case NodeTypeAsmExpr: + return "AsmExpr"; + case NodeTypeFieldAccessExpr: + return "FieldAccessExpr"; + case NodeTypeStructDecl: + return "StructDecl"; + case NodeTypeStructField: + return "StructField"; + case NodeTypeStructValueField: + return "StructValueField"; + case NodeTypeContainerInitExpr: + return "ContainerInitExpr"; + case NodeTypeArrayType: + return "ArrayType"; + case NodeTypeErrorType: + return "ErrorType"; + } +} + + +void ast_print(FILE *f, AstNode *node, int indent) { + for (int i = 0; i < indent; i += 1) { + fprintf(f, " "); + } + assert(node->type == NodeTypeRoot || *node->parent_field == node); + + switch (node->type) { + case NodeTypeRoot: + fprintf(f, "%s\n", node_type_str(node->type)); + for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { + AstNode *child = node->data.root.top_level_decls.at(i); + ast_print(f, child, indent + 2); + } + break; + case NodeTypeRootExportDecl: + fprintf(f, "%s %s '%s'\n", node_type_str(node->type), + buf_ptr(&node->data.root_export_decl.type), + buf_ptr(&node->data.root_export_decl.name)); + break; + case NodeTypeFnDef: + { + fprintf(f, "%s\n", node_type_str(node->type)); + AstNode *child = node->data.fn_def.fn_proto; + ast_print(f, child, indent + 2); + ast_print(f, node->data.fn_def.body, indent + 2); + break; + } + case NodeTypeFnProto: + { + Buf *name_buf = &node->data.fn_proto.name; + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); + + for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { + AstNode *child = node->data.fn_proto.params.at(i); + ast_print(f, child, indent + 2); + } + + ast_print(f, node->data.fn_proto.return_type, indent + 2); + + break; + } + case NodeTypeBlock: + { + fprintf(f, "%s\n", node_type_str(node->type)); + for (int i = 0; i < node->data.block.statements.length; i += 1) { + AstNode *child = node->data.block.statements.at(i); + ast_print(f, child, indent + 2); + } + break; + } + case NodeTypeParamDecl: + { + Buf *name_buf = &node->data.param_decl.name; + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); + + ast_print(f, node->data.param_decl.type, indent + 2); + + break; + } + case NodeTypeReturnExpr: + { + const char *prefix_str = return_prefix_str(node->data.return_expr.kind); + fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type)); + if (node->data.return_expr.expr) + ast_print(f, node->data.return_expr.expr, indent + 2); + break; + } + case NodeTypeVariableDeclaration: + { + Buf *name_buf = &node->data.variable_declaration.symbol; + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); + if (node->data.variable_declaration.type) + ast_print(f, node->data.variable_declaration.type, indent + 2); + if (node->data.variable_declaration.expr) + ast_print(f, node->data.variable_declaration.expr, indent + 2); + break; + } + case NodeTypeErrorValueDecl: + { + Buf *name_buf = &node->data.error_value_decl.name; + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); + break; + } + case NodeTypeFnDecl: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.fn_decl.fn_proto, indent + 2); + break; + case NodeTypeBinOpExpr: + fprintf(f, "%s %s\n", node_type_str(node->type), + bin_op_str(node->data.bin_op_expr.bin_op)); + ast_print(f, node->data.bin_op_expr.op1, indent + 2); + ast_print(f, node->data.bin_op_expr.op2, indent + 2); + break; + case NodeTypeUnwrapErrorExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.unwrap_err_expr.op1, indent + 2); + if (node->data.unwrap_err_expr.symbol) { + ast_print(f, node->data.unwrap_err_expr.symbol, indent + 2); + } + ast_print(f, node->data.unwrap_err_expr.op2, indent + 2); + break; + case NodeTypeFnCallExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.fn_call_expr.fn_ref_expr, indent + 2); + for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { + AstNode *child = node->data.fn_call_expr.params.at(i); + ast_print(f, child, indent + 2); + } + break; + case NodeTypeArrayAccessExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.array_access_expr.array_ref_expr, indent + 2); + ast_print(f, node->data.array_access_expr.subscript, indent + 2); + break; + case NodeTypeSliceExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.slice_expr.array_ref_expr, indent + 2); + ast_print(f, node->data.slice_expr.start, indent + 2); + if (node->data.slice_expr.end) { + ast_print(f, node->data.slice_expr.end, indent + 2); + } + break; + case NodeTypeDirective: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + case NodeTypePrefixOpExpr: + fprintf(f, "%s %s\n", node_type_str(node->type), + prefix_op_str(node->data.prefix_op_expr.prefix_op)); + ast_print(f, node->data.prefix_op_expr.primary_expr, indent + 2); + break; + case NodeTypeNumberLiteral: + { + NumLit kind = node->data.number_literal.kind; + const char *name = node_type_str(node->type); + if (kind == NumLitUInt) { + fprintf(f, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint); + } else { + fprintf(f, "%s float %f\n", name, node->data.number_literal.data.x_float); + } + break; + } + case NodeTypeStringLiteral: + { + const char *c = node->data.string_literal.c ? "c" : ""; + fprintf(f, "StringLiteral %s'%s'\n", c, + buf_ptr(&node->data.string_literal.buf)); + break; + } + case NodeTypeCharLiteral: + { + fprintf(f, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value); + break; + } + case NodeTypeSymbol: + fprintf(f, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); + break; + case NodeTypeImport: + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path)); + break; + case NodeTypeCImport: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.c_import.block, indent + 2); + break; + case NodeTypeBoolLiteral: + fprintf(f, "%s '%s'\n", node_type_str(node->type), + node->data.bool_literal.value ? "true" : "false"); + break; + case NodeTypeNullLiteral: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + case NodeTypeIfBoolExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + if (node->data.if_bool_expr.condition) + ast_print(f, node->data.if_bool_expr.condition, indent + 2); + ast_print(f, node->data.if_bool_expr.then_block, indent + 2); + if (node->data.if_bool_expr.else_node) + ast_print(f, node->data.if_bool_expr.else_node, indent + 2); + break; + case NodeTypeIfVarExpr: + { + Buf *name_buf = &node->data.if_var_expr.var_decl.symbol; + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); + if (node->data.if_var_expr.var_decl.type) + ast_print(f, node->data.if_var_expr.var_decl.type, indent + 2); + if (node->data.if_var_expr.var_decl.expr) + ast_print(f, node->data.if_var_expr.var_decl.expr, indent + 2); + ast_print(f, node->data.if_var_expr.then_block, indent + 2); + if (node->data.if_var_expr.else_node) + ast_print(f, node->data.if_var_expr.else_node, indent + 2); + break; + } + case NodeTypeWhileExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.while_expr.condition, indent + 2); + ast_print(f, node->data.while_expr.body, indent + 2); + break; + case NodeTypeForExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.for_expr.elem_node, indent + 2); + ast_print(f, node->data.for_expr.array_expr, indent + 2); + if (node->data.for_expr.index_node) { + ast_print(f, node->data.for_expr.index_node, indent + 2); + } + ast_print(f, node->data.for_expr.body, indent + 2); + break; + case NodeTypeSwitchExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.switch_expr.expr, indent + 2); + for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) { + AstNode *child_node = node->data.switch_expr.prongs.at(i); + ast_print(f, child_node, indent + 2); + } + break; + case NodeTypeSwitchProng: + fprintf(f, "%s\n", node_type_str(node->type)); + for (int i = 0; i < node->data.switch_prong.items.length; i += 1) { + AstNode *child_node = node->data.switch_prong.items.at(i); + ast_print(f, child_node, indent + 2); + } + if (node->data.switch_prong.var_symbol) { + ast_print(f, node->data.switch_prong.var_symbol, indent + 2); + } + ast_print(f, node->data.switch_prong.expr, indent + 2); + break; + case NodeTypeSwitchRange: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.switch_range.start, indent + 2); + ast_print(f, node->data.switch_range.end, indent + 2); + break; + case NodeTypeLabel: + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name)); + break; + case NodeTypeGoto: + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name)); + break; + case NodeTypeBreak: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + case NodeTypeContinue: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + case NodeTypeUndefinedLiteral: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + case NodeTypeAsmExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + case NodeTypeFieldAccessExpr: + fprintf(f, "%s '%s'\n", node_type_str(node->type), + buf_ptr(&node->data.field_access_expr.field_name)); + ast_print(f, node->data.field_access_expr.struct_expr, indent + 2); + break; + case NodeTypeStructDecl: + fprintf(f, "%s '%s'\n", + node_type_str(node->type), buf_ptr(&node->data.struct_decl.name)); + for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) { + AstNode *child = node->data.struct_decl.fields.at(i); + ast_print(f, child, indent + 2); + } + for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { + AstNode *child = node->data.struct_decl.fns.at(i); + ast_print(f, child, indent + 2); + } + break; + case NodeTypeStructField: + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name)); + if (node->data.struct_field.type) { + ast_print(f, node->data.struct_field.type, indent + 2); + } + break; + case NodeTypeStructValueField: + fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); + ast_print(f, node->data.struct_val_field.expr, indent + 2); + break; + case NodeTypeContainerInitExpr: + fprintf(f, "%s\n", node_type_str(node->type)); + ast_print(f, node->data.container_init_expr.type, indent + 2); + for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) { + AstNode *child = node->data.container_init_expr.entries.at(i); + ast_print(f, child, indent + 2); + } + break; + case NodeTypeArrayType: + { + const char *const_str = node->data.array_type.is_const ? "const" : "var"; + fprintf(f, "%s %s\n", node_type_str(node->type), const_str); + if (node->data.array_type.size) { + ast_print(f, node->data.array_type.size, indent + 2); + } + ast_print(f, node->data.array_type.child_type, indent + 2); + break; + } + case NodeTypeErrorType: + fprintf(f, "%s\n", node_type_str(node->type)); + break; + } +} + +struct AstRender { + int indent; + int indent_size; + FILE *f; +}; + +static void print_indent(AstRender *ar) { + for (int i = 0; i < ar->indent; i += 1) { + fprintf(ar->f, " "); + } +} + +static void render_node(AstRender *ar, AstNode *node) { + assert(node->type == NodeTypeRoot || *node->parent_field == node); + + switch (node->type) { + case NodeTypeRoot: + for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { + AstNode *child = node->data.root.top_level_decls.at(i); + print_indent(ar); + render_node(ar, child); + + if (child->type == NodeTypeImport || + child->type == NodeTypeVariableDeclaration || + child->type == NodeTypeErrorValueDecl) + { + fprintf(ar->f, ";"); + } + fprintf(ar->f, "\n"); + } + break; + case NodeTypeRootExportDecl: + zig_panic("TODO"); + case NodeTypeFnProto: + { + const char *fn_name = buf_ptr(&node->data.fn_proto.name); + const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); + const char *extern_str = extern_string(node->data.fn_proto.is_extern); + fprintf(ar->f, "%s%sfn %s(", pub_str, extern_str, fn_name); + int arg_count = node->data.fn_proto.params.length; + bool is_var_args = node->data.fn_proto.is_var_args; + for (int arg_i = 0; arg_i < arg_count; arg_i += 1) { + AstNode *param_decl = node->data.fn_proto.params.at(arg_i); + assert(param_decl->type == NodeTypeParamDecl); + const char *arg_name = buf_ptr(¶m_decl->data.param_decl.name); + const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : ""; + fprintf(ar->f, "%s%s: ", noalias_str, arg_name); + render_node(ar, param_decl->data.param_decl.type); + + if (arg_i + 1 < arg_count || is_var_args) { + fprintf(ar->f, ", "); + } + } + if (is_var_args) { + fprintf(ar->f, "..."); + } + fprintf(ar->f, ")"); + + AstNode *return_type_node = node->data.fn_proto.return_type; + bool is_void = return_type_node->type != NodeTypeSymbol && + buf_eql_str(&return_type_node->data.symbol_expr.symbol, "void"); + if (!is_void) { + fprintf(ar->f, " -> "); + render_node(ar, return_type_node); + } + fprintf(ar->f, ";"); + break; + } + case NodeTypeFnDef: + zig_panic("TODO"); + case NodeTypeFnDecl: + zig_panic("TODO"); + case NodeTypeParamDecl: + zig_panic("TODO"); + case NodeTypeBlock: + zig_panic("TODO"); + case NodeTypeDirective: + zig_panic("TODO"); + case NodeTypeReturnExpr: + zig_panic("TODO"); + case NodeTypeVariableDeclaration: + { + const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod); + const char *extern_str = extern_string(node->data.variable_declaration.is_extern); + const char *var_name = buf_ptr(&node->data.variable_declaration.symbol); + const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const); + fprintf(ar->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name); + if (node->data.variable_declaration.type) { + fprintf(ar->f, ": "); + render_node(ar, node->data.variable_declaration.type); + } + if (node->data.variable_declaration.expr) { + fprintf(ar->f, " = "); + render_node(ar, node->data.variable_declaration.expr); + } + break; + } + case NodeTypeErrorValueDecl: + zig_panic("TODO"); + case NodeTypeBinOpExpr: + zig_panic("TODO"); + case NodeTypeUnwrapErrorExpr: + zig_panic("TODO"); + case NodeTypeNumberLiteral: + zig_panic("TODO"); + case NodeTypeStringLiteral: + zig_panic("TODO"); + case NodeTypeCharLiteral: + zig_panic("TODO"); + case NodeTypeSymbol: + fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol)); + break; + case NodeTypePrefixOpExpr: + { + PrefixOp op = node->data.prefix_op_expr.prefix_op; + fprintf(ar->f, "%s", prefix_op_str(op)); + + render_node(ar, node->data.prefix_op_expr.primary_expr); + break; + } + case NodeTypeFnCallExpr: + zig_panic("TODO"); + case NodeTypeArrayAccessExpr: + zig_panic("TODO"); + case NodeTypeSliceExpr: + zig_panic("TODO"); + case NodeTypeFieldAccessExpr: + zig_panic("TODO"); + case NodeTypeImport: + zig_panic("TODO"); + case NodeTypeCImport: + zig_panic("TODO"); + case NodeTypeBoolLiteral: + zig_panic("TODO"); + case NodeTypeNullLiteral: + zig_panic("TODO"); + case NodeTypeUndefinedLiteral: + zig_panic("TODO"); + case NodeTypeIfBoolExpr: + zig_panic("TODO"); + case NodeTypeIfVarExpr: + zig_panic("TODO"); + case NodeTypeWhileExpr: + zig_panic("TODO"); + case NodeTypeForExpr: + zig_panic("TODO"); + case NodeTypeSwitchExpr: + zig_panic("TODO"); + case NodeTypeSwitchProng: + zig_panic("TODO"); + case NodeTypeSwitchRange: + zig_panic("TODO"); + case NodeTypeLabel: + zig_panic("TODO"); + case NodeTypeGoto: + zig_panic("TODO"); + case NodeTypeBreak: + zig_panic("TODO"); + case NodeTypeContinue: + zig_panic("TODO"); + case NodeTypeAsmExpr: + zig_panic("TODO"); + case NodeTypeStructDecl: + { + const char *struct_name = buf_ptr(&node->data.struct_decl.name); + const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod); + fprintf(ar->f, "%sstruct %s {\n", pub_str, struct_name); + ar->indent += ar->indent_size; + for (int field_i = 0; field_i < node->data.struct_decl.fields.length; field_i += 1) { + AstNode *field_node = node->data.struct_decl.fields.at(field_i); + assert(field_node->type == NodeTypeStructField); + const char *field_name = buf_ptr(&field_node->data.struct_field.name); + print_indent(ar); + fprintf(ar->f, "%s: ", field_name); + render_node(ar, field_node->data.struct_field.type); + fprintf(ar->f, ",\n"); + } + + ar->indent -= ar->indent_size; + fprintf(ar->f, "}\n"); + break; + } + case NodeTypeStructField: + zig_panic("TODO"); + case NodeTypeContainerInitExpr: + zig_panic("TODO"); + case NodeTypeStructValueField: + zig_panic("TODO"); + case NodeTypeArrayType: + zig_panic("TODO"); + case NodeTypeErrorType: + zig_panic("TODO"); + } +} + + +void ast_render(FILE *f, AstNode *node, int indent_size) { + AstRender ar = {0}; + ar.f = f; + ar.indent_size = indent_size; + ar.indent = 0; + + assert(node->type == NodeTypeRoot); + + render_node(&ar, node); +} diff --git a/src/ast_render.hpp b/src/ast_render.hpp new file mode 100644 index 0000000000..a971fd7a2f --- /dev/null +++ b/src/ast_render.hpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_AST_RENDER_HPP +#define ZIG_AST_RENDER_HPP + +#include "all_types.hpp" + +#include + +void ast_print(FILE *f, AstNode *node, int indent); + +void ast_render(FILE *f, AstNode *node, int indent_size); + +#endif + diff --git a/src/codegen.cpp b/src/codegen.cpp index c05dde8f69..edbaf0b871 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -13,6 +13,7 @@ #include "error.hpp" #include "analyze.hpp" #include "errmsg.hpp" +#include "ast_render.hpp" #include #include @@ -3117,7 +3118,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, &g->next_node_index); assert(import_entry->root); if (g->verbose) { - ast_print(import_entry->root, 0); + ast_print(stderr, import_entry->root, 0); } import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); diff --git a/src/main.cpp b/src/main.cpp index 8505340239..188346fb21 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ #include "os.hpp" #include "error.hpp" #include "parseh.hpp" +#include "ast_render.hpp" #include @@ -162,41 +163,10 @@ static int build(const char *arg0, int argc, char **argv) { return 0; } -struct ParseHPrint { - ParseH parse_h; - FILE *f; - int cur_indent; -}; - -static const int indent_size = 4; - -static void print_indent(ParseHPrint *p) { - for (int i = 0; i < p->cur_indent; i += 1) { - fprintf(p->f, " "); - } -} - -static Buf *node_to_buf(AstNode *node) { - if (node->type == NodeTypeSymbol) { - return &node->data.symbol_expr.symbol; - } else if (node->type == NodeTypePrefixOpExpr) { - PrefixOp op = node->data.prefix_op_expr.prefix_op; - const char *child_type_str = buf_ptr(node_to_buf(node->data.prefix_op_expr.primary_expr)); - if (op == PrefixOpAddressOf) { - return buf_sprintf("&%s", child_type_str); - } else if (op == PrefixOpConstAddressOf) { - return buf_sprintf("&const %s", child_type_str); - } else { - zig_unreachable(); - } - } else { - zig_unreachable(); - } -} - static int parseh(const char *arg0, int argc, char **argv) { char *in_file = nullptr; ZigList clang_argv = {0}; + ErrColor color = ErrColorAuto; for (int i = 0; i < argc; i += 1) { char *arg = argv[i]; if (arg[0] == '-') { @@ -206,10 +176,24 @@ static int parseh(const char *arg0, int argc, char **argv) { if (i + 1 >= argc) { return usage(arg0); } - clang_argv.append("-isystem"); - clang_argv.append(argv[i + 1]); i += 1; - } else { + clang_argv.append("-isystem"); + clang_argv.append(argv[i]); + } else if (strcmp(arg, "--color") == 0) { + if (i + 1 >= argc) { + return usage(arg0); + } + i += 1; + if (strcmp(argv[i], "auto") == 0) { + color = ErrColorAuto; + } else if (strcmp(argv[i], "on") == 0) { + color = ErrColorOn; + } else if (strcmp(argv[i], "off") == 0) { + color = ErrColorOff; + } else { + return usage(arg0); + } + } else { fprintf(stderr, "unrecognized argument: %s", arg); return usage(arg0); } @@ -231,91 +215,24 @@ static int parseh(const char *arg0, int argc, char **argv) { clang_argv.append("-isystem"); clang_argv.append(buf_ptr(libc_include_path)); - ParseHPrint parse_h_print = {{{0}}}; - ParseHPrint *p = &parse_h_print; - p->f = stdout; - p->cur_indent = 0; + ImportTableEntry import = {0}; + ZigList errors = {0}; + int err = parse_h_file(&import, &errors, &clang_argv); - parse_h_file(&p->parse_h, &clang_argv); + if (err) { + fprintf(stderr, "unable to parse .h file: %s\n", err_str(err)); + return EXIT_FAILURE; + } - if (p->parse_h.errors.length > 0) { - for (int i = 0; i < p->parse_h.errors.length; i += 1) { - ErrorMsg *err_msg = p->parse_h.errors.at(i); - // TODO respect --color arg - print_err_msg(err_msg, ErrColorAuto); + if (errors.length > 0) { + for (int i = 0; i < errors.length; i += 1) { + ErrorMsg *err_msg = errors.at(i); + print_err_msg(err_msg, color); } return EXIT_FAILURE; } - for (int var_i = 0; var_i < p->parse_h.var_list.length; var_i += 1) { - AstNode *var_decl = p->parse_h.var_list.at(var_i); - assert(var_decl->type == NodeTypeVariableDeclaration); - const char *pub_str = (var_decl->data.variable_declaration.visib_mod == VisibModPub) ? "pub " : ""; - const char *extern_str = var_decl->data.variable_declaration.is_extern ? "extern " : ""; - const char *var_name = buf_ptr(&var_decl->data.variable_declaration.symbol); - const char *const_or_var = var_decl->data.variable_declaration.is_const ? "const" : "var"; - print_indent(p); - fprintf(p->f, "%s%s%s %s", pub_str, extern_str, const_or_var, var_name); - if (var_decl->data.variable_declaration.type) { - fprintf(p->f, ": %s", buf_ptr(node_to_buf(var_decl->data.variable_declaration.type))); - } - if (var_decl->data.variable_declaration.expr) { - fprintf(p->f, " = %s", buf_ptr(node_to_buf(var_decl->data.variable_declaration.expr))); - } - fprintf(p->f, ";\n"); - } - - for (int struct_i = 0; struct_i < p->parse_h.struct_list.length; struct_i += 1) { - AstNode *struct_decl = p->parse_h.struct_list.at(struct_i); - assert(struct_decl->type == NodeTypeStructDecl); - const char *struct_name = buf_ptr(&struct_decl->data.struct_decl.name); - print_indent(p); - fprintf(p->f, "struct %s {\n", struct_name); - p->cur_indent += indent_size; - for (int field_i = 0; field_i < struct_decl->data.struct_decl.fields.length; field_i += 1) { - AstNode *field_node = struct_decl->data.struct_decl.fields.at(field_i); - assert(field_node->type == NodeTypeStructField); - const char *field_name = buf_ptr(&field_node->data.struct_field.name); - Buf *type_name = node_to_buf(field_node->data.struct_field.type); - print_indent(p); - fprintf(p->f, "%s: %s,\n", field_name, buf_ptr(type_name)); - } - - p->cur_indent -= indent_size; - fprintf(p->f, "}\n\n"); - } - - for (int fn_i = 0; fn_i < p->parse_h.fn_list.length; fn_i += 1) { - AstNode *fn_proto = p->parse_h.fn_list.at(fn_i); - assert(fn_proto->type == NodeTypeFnProto); - print_indent(p); - const char *fn_name = buf_ptr(&fn_proto->data.fn_proto.name); - const char *pub_str = (fn_proto->data.fn_proto.visib_mod == VisibModPub) ? "pub " : ""; - const char *extern_str = fn_proto->data.fn_proto.is_extern ? "extern " : ""; - fprintf(p->f, "%s%sfn %s(", pub_str, extern_str, fn_name); - int arg_count = fn_proto->data.fn_proto.params.length; - bool is_var_args = fn_proto->data.fn_proto.is_var_args; - for (int arg_i = 0; arg_i < arg_count; arg_i += 1) { - AstNode *param_decl = fn_proto->data.fn_proto.params.at(arg_i); - assert(param_decl->type == NodeTypeParamDecl); - const char *arg_name = buf_ptr(¶m_decl->data.param_decl.name); - Buf *arg_type = node_to_buf(param_decl->data.param_decl.type); - const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : ""; - fprintf(p->f, "%s%s: %s", noalias_str, arg_name, buf_ptr(arg_type)); - if (arg_i + 1 < arg_count || is_var_args) { - fprintf(p->f, ", "); - } - } - if (is_var_args) { - fprintf(p->f, "..."); - } - fprintf(p->f, ")"); - Buf *return_type_name = node_to_buf(fn_proto->data.fn_proto.return_type); - if (!buf_eql_str(return_type_name, "void")) { - fprintf(p->f, " -> %s", buf_ptr(return_type_name)); - } - fprintf(p->f, ";\n"); - } + ast_render(stdout, import.root, 4); return 0; } diff --git a/src/parseh.cpp b/src/parseh.cpp index 3721c83e79..49872a97b3 100644 --- a/src/parseh.cpp +++ b/src/parseh.cpp @@ -9,6 +9,8 @@ #include "config.h" #include "os.hpp" #include "error.hpp" +#include "parser.hpp" +#include "all_types.hpp" #include #include @@ -18,10 +20,12 @@ using namespace clang; struct Context { - ParseH *parse_h; + ImportTableEntry *import; + ZigList *errors; bool warnings_on; VisibMod visib_mod; AstNode *c_void_decl_node; + AstNode *root; HashMap type_table; }; @@ -30,6 +34,7 @@ static AstNode *make_qual_type_node(Context *c, QualType qt); static AstNode *create_node(Context *c, NodeType type) { AstNode *node = allocate(1); node->type = type; + node->owner = c->import; return node; } @@ -44,6 +49,10 @@ static const char *decl_name(const Decl *decl) { return (const char *)named_decl->getName().bytes_begin(); } +static ZigList *create_empty_directives(Context *c) { + return allocate>(1); +} + static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_node) { if (!target_node) { return nullptr; @@ -53,7 +62,10 @@ static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_n node->data.variable_declaration.is_const = true; node->data.variable_declaration.visib_mod = c->visib_mod; node->data.variable_declaration.expr = target_node; - c->parse_h->var_list.append(node); + node->data.variable_declaration.directives = create_empty_directives(c); + normalize_parent_ptrs(node); + + c->root->data.root.top_level_decls.append(node); return node; } @@ -79,6 +91,7 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) { AstNode *node = create_node(c, NodeTypePrefixOpExpr); node->data.prefix_op_expr.prefix_op = is_const ? PrefixOpConstAddressOf : PrefixOpAddressOf; node->data.prefix_op_expr.primary_expr = convert_to_c_void(c, type_node); + normalize_parent_ptrs(node); return node; } @@ -255,6 +268,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { AstNode *node = create_node(c, NodeTypeFnProto); node->data.fn_proto.is_extern = true; node->data.fn_proto.visib_mod = c->visib_mod; + node->data.fn_proto.directives = create_empty_directives(c); node->data.fn_proto.is_var_args = fn_decl->isVariadic(); buf_init_from_str(&node->data.fn_proto.name, decl_name(fn_decl)); @@ -276,6 +290,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { break; } + normalize_parent_ptrs(param_decl_node); node->data.fn_proto.params.append(param_decl_node); } @@ -296,8 +311,9 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { return; } - c->parse_h->fn_list.append(node); + normalize_parent_ptrs(node); + c->root->data.root.top_level_decls.append(node); } static 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) AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt)); if (node) { + normalize_parent_ptrs(node); c->type_table.put(type_name, true); } } @@ -345,7 +362,9 @@ static bool decl_visitor(void *context, const Decl *decl) { return true; } -int parse_h_buf(ParseH *parse_h, Buf *source, const char **args, int args_len, const char *libc_include_path) { +int parse_h_buf(ImportTableEntry *import, ZigList *errors, Buf *source, + const char **args, int args_len, const char *libc_include_path) +{ int err; Buf tmp_file_path = BUF_INIT; 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 clang_argv.append(args[i]); } - err = parse_h_file(parse_h, &clang_argv); + err = parse_h_file(import, errors, &clang_argv); os_delete_file(&tmp_file_path); return err; } -int parse_h_file(ParseH *parse_h, ZigList *clang_argv) { +int parse_h_file(ImportTableEntry *import, ZigList *errors, ZigList *clang_argv) { Context context = {0}; Context *c = &context; - c->parse_h = parse_h; + c->import = import; + c->errors = errors; c->type_table.init(64); char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS"); @@ -455,13 +475,18 @@ int parse_h_file(ParseH *parse_h, ZigList *clang_argv) { ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); - parse_h->errors.append(err_msg); + c->errors->append(err_msg); } return 0; } + c->root = create_node(c, NodeTypeRoot); ast_unit->visitLocalTopLevelDecls(c, decl_visitor); + normalize_parent_ptrs(c->root); + + import->root = c->root; + import->is_c_import = true; return 0; } diff --git a/src/parseh.hpp b/src/parseh.hpp index b7cb9af279..e2bb272401 100644 --- a/src/parseh.hpp +++ b/src/parseh.hpp @@ -11,7 +11,9 @@ #include "all_types.hpp" -int parse_h_file(ParseH *parse_h, ZigList *clang_argv); -int parse_h_buf(ParseH *parse_h, Buf *source, const char **args, int args_len, const char *libc_include_path); +int parse_h_file(ImportTableEntry *out_import, ZigList *out_errs, + ZigList *clang_argv); +int parse_h_buf(ImportTableEntry *out_import, ZigList *out_errs, + Buf *source, const char **args, int args_len, const char *libc_include_path); #endif diff --git a/src/parser.cpp b/src/parser.cpp index be5acd9a95..170d579956 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -14,465 +14,6 @@ #include #include -static const char *bin_op_str(BinOpType bin_op) { - switch (bin_op) { - case BinOpTypeInvalid: return "(invalid)"; - case BinOpTypeBoolOr: return "||"; - case BinOpTypeBoolAnd: return "&&"; - case BinOpTypeCmpEq: return "=="; - case BinOpTypeCmpNotEq: return "!="; - case BinOpTypeCmpLessThan: return "<"; - case BinOpTypeCmpGreaterThan: return ">"; - case BinOpTypeCmpLessOrEq: return "<="; - case BinOpTypeCmpGreaterOrEq: return ">="; - case BinOpTypeBinOr: return "|"; - case BinOpTypeBinXor: return "^"; - case BinOpTypeBinAnd: return "&"; - case BinOpTypeBitShiftLeft: return "<<"; - case BinOpTypeBitShiftRight: return ">>"; - case BinOpTypeAdd: return "+"; - case BinOpTypeSub: return "-"; - case BinOpTypeMult: return "*"; - case BinOpTypeDiv: return "/"; - case BinOpTypeMod: return "%"; - case BinOpTypeAssign: return "="; - case BinOpTypeAssignTimes: return "*="; - case BinOpTypeAssignDiv: return "/="; - case BinOpTypeAssignMod: return "%="; - case BinOpTypeAssignPlus: return "+="; - case BinOpTypeAssignMinus: return "-="; - case BinOpTypeAssignBitShiftLeft: return "<<="; - case BinOpTypeAssignBitShiftRight: return ">>="; - case BinOpTypeAssignBitAnd: return "&="; - case BinOpTypeAssignBitXor: return "^="; - case BinOpTypeAssignBitOr: return "|="; - case BinOpTypeAssignBoolAnd: return "&&="; - case BinOpTypeAssignBoolOr: return "||="; - case BinOpTypeUnwrapMaybe: return "??"; - case BinOpTypeStrCat: return "++"; - } - zig_unreachable(); -} - -static const char *prefix_op_str(PrefixOp prefix_op) { - switch (prefix_op) { - case PrefixOpInvalid: return "(invalid)"; - case PrefixOpNegation: return "-"; - case PrefixOpBoolNot: return "!"; - case PrefixOpBinNot: return "~"; - case PrefixOpAddressOf: return "&"; - case PrefixOpConstAddressOf: return "&const"; - case PrefixOpDereference: return "*"; - case PrefixOpMaybe: return "?"; - case PrefixOpError: return "%"; - case PrefixOpUnwrapError: return "%%"; - } - zig_unreachable(); -} - -static const char *return_prefix_str(ReturnKind kind) { - switch (kind) { - case ReturnKindError: return "%"; - case ReturnKindMaybe: return "?"; - case ReturnKindUnconditional: return ""; - } - zig_unreachable(); -} - -const char *node_type_str(NodeType node_type) { - switch (node_type) { - case NodeTypeRoot: - return "Root"; - case NodeTypeRootExportDecl: - return "RootExportDecl"; - case NodeTypeFnDef: - return "FnDef"; - case NodeTypeFnDecl: - return "FnDecl"; - case NodeTypeFnProto: - return "FnProto"; - case NodeTypeParamDecl: - return "ParamDecl"; - case NodeTypeBlock: - return "Block"; - case NodeTypeBinOpExpr: - return "BinOpExpr"; - case NodeTypeUnwrapErrorExpr: - return "UnwrapErrorExpr"; - case NodeTypeFnCallExpr: - return "FnCallExpr"; - case NodeTypeArrayAccessExpr: - return "ArrayAccessExpr"; - case NodeTypeSliceExpr: - return "SliceExpr"; - case NodeTypeDirective: - return "Directive"; - case NodeTypeReturnExpr: - return "ReturnExpr"; - case NodeTypeVariableDeclaration: - return "VariableDeclaration"; - case NodeTypeErrorValueDecl: - return "ErrorValueDecl"; - case NodeTypeNumberLiteral: - return "NumberLiteral"; - case NodeTypeStringLiteral: - return "StringLiteral"; - case NodeTypeCharLiteral: - return "CharLiteral"; - case NodeTypeSymbol: - return "Symbol"; - case NodeTypePrefixOpExpr: - return "PrefixOpExpr"; - case NodeTypeImport: - return "Import"; - case NodeTypeCImport: - return "CImport"; - case NodeTypeBoolLiteral: - return "BoolLiteral"; - case NodeTypeNullLiteral: - return "NullLiteral"; - case NodeTypeUndefinedLiteral: - return "UndefinedLiteral"; - case NodeTypeIfBoolExpr: - return "IfBoolExpr"; - case NodeTypeIfVarExpr: - return "IfVarExpr"; - case NodeTypeWhileExpr: - return "WhileExpr"; - case NodeTypeForExpr: - return "ForExpr"; - case NodeTypeSwitchExpr: - return "SwitchExpr"; - case NodeTypeSwitchProng: - return "SwitchProng"; - case NodeTypeSwitchRange: - return "SwitchRange"; - case NodeTypeLabel: - return "Label"; - case NodeTypeGoto: - return "Goto"; - case NodeTypeBreak: - return "Break"; - case NodeTypeContinue: - return "Continue"; - case NodeTypeAsmExpr: - return "AsmExpr"; - case NodeTypeFieldAccessExpr: - return "FieldAccessExpr"; - case NodeTypeStructDecl: - return "StructDecl"; - case NodeTypeStructField: - return "StructField"; - case NodeTypeStructValueField: - return "StructValueField"; - case NodeTypeContainerInitExpr: - return "ContainerInitExpr"; - case NodeTypeArrayType: - return "ArrayType"; - case NodeTypeErrorType: - return "ErrorType"; - } - zig_unreachable(); -} - -void ast_print(AstNode *node, int indent) { - for (int i = 0; i < indent; i += 1) { - fprintf(stderr, " "); - } - assert(node->type == NodeTypeRoot || *node->parent_field == node); - - switch (node->type) { - case NodeTypeRoot: - fprintf(stderr, "%s\n", node_type_str(node->type)); - for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { - AstNode *child = node->data.root.top_level_decls.at(i); - ast_print(child, indent + 2); - } - break; - case NodeTypeRootExportDecl: - fprintf(stderr, "%s %s '%s'\n", node_type_str(node->type), - buf_ptr(&node->data.root_export_decl.type), - buf_ptr(&node->data.root_export_decl.name)); - break; - case NodeTypeFnDef: - { - fprintf(stderr, "%s\n", node_type_str(node->type)); - AstNode *child = node->data.fn_def.fn_proto; - ast_print(child, indent + 2); - ast_print(node->data.fn_def.body, indent + 2); - break; - } - case NodeTypeFnProto: - { - Buf *name_buf = &node->data.fn_proto.name; - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); - - for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { - AstNode *child = node->data.fn_proto.params.at(i); - ast_print(child, indent + 2); - } - - ast_print(node->data.fn_proto.return_type, indent + 2); - - break; - } - case NodeTypeBlock: - { - fprintf(stderr, "%s\n", node_type_str(node->type)); - for (int i = 0; i < node->data.block.statements.length; i += 1) { - AstNode *child = node->data.block.statements.at(i); - ast_print(child, indent + 2); - } - break; - } - case NodeTypeParamDecl: - { - Buf *name_buf = &node->data.param_decl.name; - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); - - ast_print(node->data.param_decl.type, indent + 2); - - break; - } - case NodeTypeReturnExpr: - { - const char *prefix_str = return_prefix_str(node->data.return_expr.kind); - fprintf(stderr, "%s%s\n", prefix_str, node_type_str(node->type)); - if (node->data.return_expr.expr) - ast_print(node->data.return_expr.expr, indent + 2); - break; - } - case NodeTypeVariableDeclaration: - { - Buf *name_buf = &node->data.variable_declaration.symbol; - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); - if (node->data.variable_declaration.type) - ast_print(node->data.variable_declaration.type, indent + 2); - if (node->data.variable_declaration.expr) - ast_print(node->data.variable_declaration.expr, indent + 2); - break; - } - case NodeTypeErrorValueDecl: - { - Buf *name_buf = &node->data.error_value_decl.name; - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); - break; - } - case NodeTypeFnDecl: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.fn_decl.fn_proto, indent + 2); - break; - case NodeTypeBinOpExpr: - fprintf(stderr, "%s %s\n", node_type_str(node->type), - bin_op_str(node->data.bin_op_expr.bin_op)); - ast_print(node->data.bin_op_expr.op1, indent + 2); - ast_print(node->data.bin_op_expr.op2, indent + 2); - break; - case NodeTypeUnwrapErrorExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.unwrap_err_expr.op1, indent + 2); - if (node->data.unwrap_err_expr.symbol) { - ast_print(node->data.unwrap_err_expr.symbol, indent + 2); - } - ast_print(node->data.unwrap_err_expr.op2, indent + 2); - break; - case NodeTypeFnCallExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2); - for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { - AstNode *child = node->data.fn_call_expr.params.at(i); - ast_print(child, indent + 2); - } - break; - case NodeTypeArrayAccessExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.array_access_expr.array_ref_expr, indent + 2); - ast_print(node->data.array_access_expr.subscript, indent + 2); - break; - case NodeTypeSliceExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.slice_expr.array_ref_expr, indent + 2); - ast_print(node->data.slice_expr.start, indent + 2); - if (node->data.slice_expr.end) { - ast_print(node->data.slice_expr.end, indent + 2); - } - break; - case NodeTypeDirective: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypePrefixOpExpr: - fprintf(stderr, "%s %s\n", node_type_str(node->type), - prefix_op_str(node->data.prefix_op_expr.prefix_op)); - ast_print(node->data.prefix_op_expr.primary_expr, indent + 2); - break; - case NodeTypeNumberLiteral: - { - NumLit kind = node->data.number_literal.kind; - const char *name = node_type_str(node->type); - if (kind == NumLitUInt) { - fprintf(stderr, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint); - } else { - fprintf(stderr, "%s float %f\n", name, node->data.number_literal.data.x_float); - } - break; - } - case NodeTypeStringLiteral: - { - const char *c = node->data.string_literal.c ? "c" : ""; - fprintf(stderr, "StringLiteral %s'%s'\n", c, - buf_ptr(&node->data.string_literal.buf)); - break; - } - case NodeTypeCharLiteral: - { - fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value); - break; - } - case NodeTypeSymbol: - fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); - break; - case NodeTypeImport: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path)); - break; - case NodeTypeCImport: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.c_import.block, indent + 2); - break; - case NodeTypeBoolLiteral: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), - node->data.bool_literal.value ? "true" : "false"); - break; - case NodeTypeNullLiteral: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypeIfBoolExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - if (node->data.if_bool_expr.condition) - ast_print(node->data.if_bool_expr.condition, indent + 2); - ast_print(node->data.if_bool_expr.then_block, indent + 2); - if (node->data.if_bool_expr.else_node) - ast_print(node->data.if_bool_expr.else_node, indent + 2); - break; - case NodeTypeIfVarExpr: - { - Buf *name_buf = &node->data.if_var_expr.var_decl.symbol; - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); - if (node->data.if_var_expr.var_decl.type) - ast_print(node->data.if_var_expr.var_decl.type, indent + 2); - if (node->data.if_var_expr.var_decl.expr) - ast_print(node->data.if_var_expr.var_decl.expr, indent + 2); - ast_print(node->data.if_var_expr.then_block, indent + 2); - if (node->data.if_var_expr.else_node) - ast_print(node->data.if_var_expr.else_node, indent + 2); - break; - } - case NodeTypeWhileExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.while_expr.condition, indent + 2); - ast_print(node->data.while_expr.body, indent + 2); - break; - case NodeTypeForExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.for_expr.elem_node, indent + 2); - ast_print(node->data.for_expr.array_expr, indent + 2); - if (node->data.for_expr.index_node) { - ast_print(node->data.for_expr.index_node, indent + 2); - } - ast_print(node->data.for_expr.body, indent + 2); - break; - case NodeTypeSwitchExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.switch_expr.expr, indent + 2); - for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) { - AstNode *child_node = node->data.switch_expr.prongs.at(i); - ast_print(child_node, indent + 2); - } - break; - case NodeTypeSwitchProng: - fprintf(stderr, "%s\n", node_type_str(node->type)); - for (int i = 0; i < node->data.switch_prong.items.length; i += 1) { - AstNode *child_node = node->data.switch_prong.items.at(i); - ast_print(child_node, indent + 2); - } - if (node->data.switch_prong.var_symbol) { - ast_print(node->data.switch_prong.var_symbol, indent + 2); - } - ast_print(node->data.switch_prong.expr, indent + 2); - break; - case NodeTypeSwitchRange: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.switch_range.start, indent + 2); - ast_print(node->data.switch_range.end, indent + 2); - break; - case NodeTypeLabel: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name)); - break; - case NodeTypeGoto: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name)); - break; - case NodeTypeBreak: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypeContinue: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypeUndefinedLiteral: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypeAsmExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - case NodeTypeFieldAccessExpr: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), - buf_ptr(&node->data.field_access_expr.field_name)); - ast_print(node->data.field_access_expr.struct_expr, indent + 2); - break; - case NodeTypeStructDecl: - fprintf(stderr, "%s '%s'\n", - node_type_str(node->type), buf_ptr(&node->data.struct_decl.name)); - for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) { - AstNode *child = node->data.struct_decl.fields.at(i); - ast_print(child, indent + 2); - } - for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { - AstNode *child = node->data.struct_decl.fns.at(i); - ast_print(child, indent + 2); - } - break; - case NodeTypeStructField: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name)); - if (node->data.struct_field.type) { - ast_print(node->data.struct_field.type, indent + 2); - } - break; - case NodeTypeStructValueField: - fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); - ast_print(node->data.struct_val_field.expr, indent + 2); - break; - case NodeTypeContainerInitExpr: - fprintf(stderr, "%s\n", node_type_str(node->type)); - ast_print(node->data.container_init_expr.type, indent + 2); - for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) { - AstNode *child = node->data.container_init_expr.entries.at(i); - ast_print(child, indent + 2); - } - break; - case NodeTypeArrayType: - { - const char *const_str = node->data.array_type.is_const ? "const" : "var"; - fprintf(stderr, "%s %s\n", node_type_str(node->type), const_str); - if (node->data.array_type.size) { - ast_print(node->data.array_type.size, indent + 2); - } - ast_print(node->data.array_type.child_type, indent + 2); - break; - } - case NodeTypeErrorType: - fprintf(stderr, "%s\n", node_type_str(node->type)); - break; - } -} - struct ParseContext { Buf *buf; AstNode *root;