// File: /workspace/github_c_makefile_star2_O2/yangtau[P]hedgehog/src/ast.c
// Function: node_to_str
static void _node_to_str(const struct hg_ast_node* _node, uint32_t indent, uint32_t depth, struct hg_strbuf* buf) {
#define __add_indent hg_strbuf_append(buf, _get_indent_str(indent, depth))
#define __add_nl     hg_strbuf_append(buf, "\n")
#define __add_space  hg_strbuf_append(buf, " ")
#define __add_block(block, end)                                        \
    do {                                                               \
        if (__hg_ast_raw(block, struct hg_ast_node_array)->len == 0) { \
            hg_strbuf_append(buf, "{}%s", end);                        \
        } else {                                                       \
            hg_strbuf_append(buf, "{\n");                              \
            _node_to_str(block, indent, depth + 1, buf);               \
            __add_indent;                                              \
            hg_strbuf_append(buf, "}%s", end);                         \
        }                                                              \
    } while (0)

    switch (_node->type) {
    case HG_AST_NODE_ASSIGNMENT: {
        __hg_ast_raw_to(_node, struct hg_ast_assignment_stat, node);

        __add_indent;
        _node_to_str(node->vars, indent, depth, buf);
        hg_strbuf_append(buf, " = ");
        _node_to_str(node->exprs, indent, depth, buf);
        __add_nl;
    } break;
    case HG_AST_NODE_FOR: {
        __hg_ast_raw_to(_node, struct hg_ast_for_stat, node);

        __add_indent;
        hg_strbuf_append(buf, "for ");
        _node_to_str(node->params, indent, depth, buf);
        hg_strbuf_append(buf, " in ");
        _node_to_str(node->iterator, indent, depth, buf);

        __add_space;
        __add_block(node->block, "\n");
    } break;
    case HG_AST_NODE_IF: {
        __hg_ast_raw_to(_node, struct hg_ast_if_stat, node);

        __add_indent;
        hg_strbuf_append(buf, "if ");
        _node_to_str(node->condition, indent, depth, buf);
        __add_space;

        // if block
        __add_block(node->block, node->else_block ? " " : "\n");

        // else block
        if (node->else_block) {
            hg_strbuf_append(buf, "else ");
            // TODO: do not inline this
            __add_block(node->else_block, "\n");
        }
    } break;
    case HG_AST_NODE_FUNC: {
        __hg_ast_raw_to(_node, struct hg_ast_func_stat, node);

        __add_indent;
        hg_strbuf_append(buf, "fn ");
        _node_to_str(node->id, indent, depth, buf);

        hg_strbuf_append(buf, "(");
        if (node->params) {
            _node_to_str(node->params, indent, depth, buf);
        }
        hg_strbuf_append(buf, ") ");

        __add_block(node->block, "\n");
    } break;
    case HG_AST_NODE_BREAK: {
        __add_indent;
        hg_strbuf_append(buf, "break\n");
    } break;
    case HG_AST_NODE_CONTINUE: {
        __add_indent;
        hg_strbuf_append(buf, "continue\n");
    } break;
    case HG_AST_NODE_RETURN: {
        __hg_ast_raw_to(_node, struct hg_ast_return_stat, node);

        __add_indent;
        hg_strbuf_append(buf, "return");

        if (node->exprs) {
            __add_space;
            _node_to_str(node->exprs, indent, depth, buf);
        }
        __add_nl;
    } break;
    case HG_AST_NODE_EXPR_STAT: {
        __hg_ast_raw_to(_node, struct hg_ast_expr_stat, node);
        __add_indent;
        _node_to_str(node->expr, indent, depth, buf);
        __add_nl;
    } break;
    // exprs (no indent and no new line by default):
    case HG_AST_NODE_CALL: {
        __hg_ast_raw_to(_node, struct hg_ast_call_expr, node);

        _node_to_str(node->callable, indent, depth, buf);

        hg_strbuf_append(buf, "(");
        if (node->exprs) {
            _node_to_str(node->exprs, indent, depth, buf);
        }
        hg_strbuf_append(buf, ")");
    } break;
    case HG_AST_NODE_FIELD: {
        __hg_ast_raw_to(_node, struct hg_ast_field_expr, node);

        _node_to_str(node->prefix, indent, depth, buf);
        hg_strbuf_append(buf, ".");
        _node_to_str(node->field, indent, depth, buf);
    } break;
    case HG_AST_NODE_INDEX: {
        __hg_ast_raw_to(_node, struct hg_ast_index_expr, node);

        _node_to_str(node->prefix, indent, depth, buf);

        hg_strbuf_append(buf, "[");
        _node_to_str(node->index, indent, depth, buf);
        hg_strbuf_append(buf, "]");
    } break;
    case HG_AST_NODE_FUNC_DEF: {
        __hg_ast_raw_to(_node, struct hg_ast_func_def_expr, node);

        hg_strbuf_append(buf, "fn ");

        hg_strbuf_append(buf, "(");
        if (node->params) {
            _node_to_str(node->params, indent, depth, buf);
        }
        hg_strbuf_append(buf, ") ");

        __add_block(node->block, "");
    } break;
    case HG_AST_NODE_BINARY_EXPR: {
        __hg_ast_raw_to(_node, struct hg_ast_binary_expr, node);
        _node_to_str(node->left, indent, depth, buf);
        hg_strbuf_append(buf, " %s ", _op_to_str(node->op));
        _node_to_str(node->right, indent, depth, buf);
    } break;
    case HG_AST_NODE_UNARY_EXPR: {
        __hg_ast_raw_to(_node, struct hg_ast_unary_expr, node);
        hg_strbuf_append(buf, "%s%s", _op_to_str(node->op), node->op == HG_AST_NODE_OP_SUB ? "" : " ");
        _node_to_str(node->expr, indent, depth, buf);
    } break;
    case HG_AST_NODE_TABLE: {
        __hg_ast_raw_to(_node, struct hg_ast_table_expr, node);
        hg_strbuf_append(buf, "{");
        if (node->entries) {
            _node_to_str(node->entries, indent, depth, buf);
        }
        hg_strbuf_append(buf, "}");
    } break;
    case HG_AST_NODE_TABLE_ENTRY: {
        __hg_ast_raw_to(_node, struct hg_ast_table_entry, node);
        _node_to_str(node->key, indent, depth, buf);
        hg_strbuf_append(buf, ": ");
        _node_to_str(node->value, indent, depth, buf);
    } break;
    case HG_AST_NODE_BRACK_EXPR: {
        __hg_ast_raw_to(_node, struct hg_ast_brack_expr, node);
        hg_strbuf_append(buf, "(");
        _node_to_str(node->expr, indent, depth, buf);
        hg_strbuf_append(buf, ")");
    } break;
    case HG_AST_NODE_LITERAL_STR: {
        __hg_ast_raw_to(_node, struct hg_ast_literal, node);
        hg_strbuf_append(buf, "\"%s\"", node->as_str);
    } break;
    case HG_AST_NODE_LITERAL_SYMBOL: {
        __hg_ast_raw_to(_node, struct hg_ast_literal, node);
        hg_strbuf_append(buf, ".%s", node->as_str);
    } break;
    case HG_AST_NODE_LITERAL_ID: {
        __hg_ast_raw_to(_node, struct hg_ast_literal, node);
        hg_strbuf_append(buf, "%s", node->as_id);
    } break;
    case HG_AST_NODE_LITERAL_BOOL: {
        __hg_ast_raw_to(_node, struct hg_ast_literal, node);
        hg_strbuf_append(buf, "%s", node->as_bool ? "true" : "false");
    } break;
    case HG_AST_NODE_LITERAL_INT: {
        __hg_ast_raw_to(_node, struct hg_ast_literal, node);
        hg_strbuf_append(buf, "%" HGFormatInt, node->as_int);
    } break;
    case HG_AST_NODE_LITERAL_FLOAT: {
        __hg_ast_raw_to(_node, struct hg_ast_literal, node);
        hg_strbuf_append(buf, "%" HGFormatFloat, node->as_float);
    } break;
    case HG_AST_NODE_ARRAY_STATS: {
        __hg_ast_raw_to(_node, struct hg_ast_node_array, node);
        for (size_t i = 0; i < node->len; i++) {
            _node_to_str(node->arr[i], indent, depth, buf);
            // __add_nl;
        }
    } break;
    case HG_AST_NODE_ARRAY_EXPRS:
    case HG_AST_NODE_ARRAY_VARS:
    case HG_AST_NODE_ARRAY_PARAMS:
    case HG_AST_NODE_ARRAY_TABLE_ENTRIES: {
        __hg_ast_raw_to(_node, struct hg_ast_node_array, node);
        for (size_t i = 0; i < node->len; i++) {
            _node_to_str(node->arr[i], indent, depth, buf);
            if (i != node->len - 1) {
                hg_strbuf_append(buf, ", ");
            }
        }
    } break;
    default:
        unreachable_();
    }
#undef __add_indent
#undef __add_nl
#undef __add_space
#undef __add_block
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x408, %rsp            # imm = 0x408
movq %rcx, %rbx
movl %edx, %r14d
movl %esi, %ebp
movq %rdi, %r15
leaq 0x3426(%rip), %r12      # 0x6168
movl (%r15), %eax
decl %eax
cmpl $0x21, %eax
ja 0x33c7
movslq (%r12,%rax,4), %rax
addq %r12, %rax
pushq $0x10
popq %r13
jmpq *%rax
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3c6f(%rip), %rsi      # 0x69e4
jmp 0x2d8f
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3c69(%rip), %rsi      # 0x69f8
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
jmp 0x2e03
movl 0x8(%r15), %edi
callq 0x34b0
cmpl $0xb, 0x8(%r15)
leaq 0x32ec(%rip), %rdx      # 0x609c
leaq 0x3c74(%rip), %rcx      # 0x6a2b
cmoveq %rdx, %rcx
leaq 0x3c2d(%rip), %rsi      # 0x69ef
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x3929
jmp 0x2e03
movq 0x10(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
movl 0x8(%r15), %edi
callq 0x34b0
leaq 0x3bf8(%rip), %rsi      # 0x69ea
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x3929
pushq $0x18
popq %r13
movq (%r15,%r13), %r15
jmp 0x2d42
leaq 0x3bf9(%rip), %r12      # 0x6a0c
xorl %r13d, %r13d
cmpq 0x8(%r15), %r13
jae 0x338c
movq 0x18(%r15,%r13,8), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
movq 0x8(%r15), %rax
decq %rax
cmpq %rax, %r13
je 0x2e4b
movq %rbx, %rdi
movq %r12, %rsi
xorl %eax, %eax
callq 0x3929
incq %r13
jmp 0x2e16
movq 0x8(%r15), %rdx
leaq 0x3ba9(%rip), %rsi      # 0x6a04
jmp 0x33ac
leaq 0x3b67(%rip), %rsi      # 0x69ce
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
jmp 0x327d
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3b54(%rip), %rsi      # 0x69e6
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3b34(%rip), %rsi      # 0x69e8
jmp 0x3291
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x5b93(%rip), %rsi      # 0x8a6a
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
cmpq $0x0, 0x8(%r15)
je 0x3193
leaq 0x3b38(%rip), %rsi      # 0x6a2b
movq %rbx, %rdi
jmp 0x30b7
leaq 0x3ac8(%rip), %rsi      # 0x69ca
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
leaq 0x3abb(%rip), %rsi      # 0x69ce
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
testq %rdi, %rdi
je 0x2f33
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3a96(%rip), %rsi      # 0x69d0
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rax
cmpq $0x0, 0x8(%rax)
je 0x32ef
leaq 0x3a63(%rip), %rsi      # 0x69bd
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
leal 0x1(%r14), %edx
movl %ebp, %esi
movq %rbx, %rcx
callq 0x2d1f
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x3a25(%rip), %rsi      # 0x69b9
jmp 0x32f6
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x3a09(%rip), %rsi      # 0x69c0
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3a52(%rip), %r12      # 0x6a2b
movq %rbx, %rdi
movq %r12, %rsi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rax
cmpq $0x0, 0x8(%rax)
je 0x3302
leaq 0x39c1(%rip), %rsi      # 0x69bd
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
leal 0x1(%r14), %edx
movl %ebp, %esi
movq %rbx, %rcx
callq 0x2d1f
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x3983(%rip), %rsi      # 0x69b9
jmp 0x3309
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x3971(%rip), %rsi      # 0x69ca
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3953(%rip), %rsi      # 0x69ce
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
testq %rdi, %rdi
je 0x309b
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x392e(%rip), %rsi      # 0x69d0
jmp 0x3334
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
jmp 0x3186
leaq 0x3926(%rip), %rsi      # 0x69f4
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
testq %rdi, %rdi
je 0x30ee
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3901(%rip), %rsi      # 0x69f6
jmp 0x3291
movq 0x8(%r15), %rdx
jmp 0x32c3
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x38b2(%rip), %rsi      # 0x69d3
jmp 0x3291
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x3896(%rip), %rsi      # 0x69da
jmp 0x3291
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3832(%rip), %rsi      # 0x69aa
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x2f01(%rip), %rsi      # 0x609b
jmp 0x3291
xorl %r12d, %r12d
cmpq 0x8(%r15), %r12
jae 0x338c
movq 0x18(%r15,%r12,8), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
incq %r12
jmp 0x31a2
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x37cd(%rip), %rsi      # 0x69ae
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x37b0(%rip), %rsi      # 0x69b3
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3806(%rip), %rsi      # 0x6a2b
jmp 0x3334
movsd 0x8(%r15), %xmm0
leaq 0x37d1(%rip), %rsi      # 0x6a08
movq %rbx, %rdi
movb $0x1, %al
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3929
movq 0x8(%r15), %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x3764(%rip), %rsi      # 0x69ce
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x10(%r15), %rdi
testq %rdi, %rdi
je 0x328a
movl %ebp, %esi
movl %r14d, %edx
movq %rbx, %rcx
callq 0x2d1f
leaq 0x37bd(%rip), %rsi      # 0x6a4e
movq %rbx, %rdi
xorl %eax, %eax
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3929
leaq 0x57d5(%rip), %rax      # 0x8a88
cmpb $0x0, 0x8(%r15)
leaq 0x57d2(%rip), %rdx      # 0x8a91
cmovneq %rax, %rdx
leaq 0x55d1(%rip), %rsi      # 0x889b
jmp 0x33ac
movq 0x8(%r15), %rdx
leaq 0x3721(%rip), %rsi      # 0x69fb
jmp 0x33ac
movq 0x8(%r15), %rdx
leaq 0x3716(%rip), %rsi      # 0x6a00
jmp 0x33ac
leaq 0x36c2(%rip), %rsi      # 0x69b8
leaq 0x2d9f(%rip), %rdx      # 0x609c
jmp 0x33ac
leaq 0x36af(%rip), %rsi      # 0x69b8
cmpq $0x0, 0x18(%r15)
leaq 0x2d86(%rip), %rax      # 0x609b
cmoveq %rax, %r12
movq %rbx, %rdi
movq %r12, %rdx
xorl %eax, %eax
callq 0x3929
cmpq $0x0, 0x18(%r15)
je 0x338c
leaq 0x3690(%rip), %rsi      # 0x69c4
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x18(%r15), %rax
cmpq $0x0, 0x8(%rax)
je 0x339e
leaq 0x366d(%rip), %rsi      # 0x69bd
movq %rbx, %rdi
xorl %eax, %eax
callq 0x3929
movq 0x18(%r15), %rdi
leal 0x1(%r14), %edx
movl %ebp, %esi
movq %rbx, %rcx
callq 0x2d1f
movl %ebp, %edi
movl %r14d, %esi
callq 0x340b
movq %rbx, %rdi
movq %rax, %rsi
xorl %eax, %eax
callq 0x3929
leaq 0x362f(%rip), %rsi      # 0x69b9
jmp 0x33a5
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3613(%rip), %rsi      # 0x69b8
leaq 0x2cef(%rip), %rdx      # 0x609b
movq %rbx, %rdi
xorl %eax, %eax
addq $0x408, %rsp            # imm = 0x408
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3929
movq 0x8c2a(%rip), %rax      # 0xbff8
movq (%rax), %rdi
leaq 0x35a5(%rip), %rsi      # 0x697d
leaq 0x3630(%rip), %rdx      # 0x6a0f
xorl %eax, %eax
callq 0x2110
movq %rsp, %rbx
movq %rbx, %rdi
movl $0x80, %esi
callq 0x20d0
pushq $0x2
popq %rdx
movq %rbx, %rdi
movl %eax, %esi
callq 0x2040
pushq $-0x1
popq %rdi
callq 0x2190