mirror of
https://github.com/ziglang/zig.git
synced 2024-12-12 14:16:59 +00:00
move AST rendering code to separate file
This commit is contained in:
parent
c281533638
commit
b6354ddd5a
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -894,6 +894,7 @@ struct ImportTableEntry {
|
||||
ZigList<int> *line_offsets;
|
||||
BlockContext *block_context;
|
||||
ZigList<ImporterInfo> importers;
|
||||
bool is_c_import;
|
||||
|
||||
// reminder: hash tables must be initialized before use
|
||||
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
|
||||
|
@ -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<ErrorMsg *> 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) {
|
||||
|
682
src/ast_render.cpp
Normal file
682
src/ast_render.cpp
Normal file
@ -0,0 +1,682 @@
|
||||
#include "ast_render.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
20
src/ast_render.hpp
Normal file
20
src/ast_render.hpp
Normal file
@ -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 <stdio.h>
|
||||
|
||||
void ast_print(FILE *f, AstNode *node, int indent);
|
||||
|
||||
void ast_render(FILE *f, AstNode *node, int indent_size);
|
||||
|
||||
#endif
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "error.hpp"
|
||||
#include "analyze.hpp"
|
||||
#include "errmsg.hpp"
|
||||
#include "ast_render.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
@ -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));
|
||||
|
145
src/main.cpp
145
src/main.cpp
@ -11,6 +11,7 @@
|
||||
#include "os.hpp"
|
||||
#include "error.hpp"
|
||||
#include "parseh.hpp"
|
||||
#include "ast_render.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -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<const char *> 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<ErrorMsg *> 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;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "config.h"
|
||||
#include "os.hpp"
|
||||
#include "error.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "all_types.hpp"
|
||||
|
||||
#include <clang/Frontend/ASTUnit.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
@ -18,10 +20,12 @@
|
||||
using namespace clang;
|
||||
|
||||
struct Context {
|
||||
ParseH *parse_h;
|
||||
ImportTableEntry *import;
|
||||
ZigList<ErrorMsg *> *errors;
|
||||
bool warnings_on;
|
||||
VisibMod visib_mod;
|
||||
AstNode *c_void_decl_node;
|
||||
AstNode *root;
|
||||
HashMap<Buf *, bool, buf_hash, buf_eql_buf> 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<AstNode>(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<AstNode *> *create_empty_directives(Context *c) {
|
||||
return allocate<ZigList<AstNode*>>(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<ErrorMsg *> *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<const char *> *clang_argv) {
|
||||
int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, ZigList<const char *> *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<const char *> *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;
|
||||
}
|
||||
|
@ -11,7 +11,9 @@
|
||||
|
||||
#include "all_types.hpp"
|
||||
|
||||
int parse_h_file(ParseH *parse_h, ZigList<const char *> *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<ErrorMsg *> *out_errs,
|
||||
ZigList<const char *> *clang_argv);
|
||||
int parse_h_buf(ImportTableEntry *out_import, ZigList<ErrorMsg *> *out_errs,
|
||||
Buf *source, const char **args, int args_len, const char *libc_include_path);
|
||||
|
||||
#endif
|
||||
|
459
src/parser.cpp
459
src/parser.cpp
@ -14,465 +14,6 @@
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user