// File: /workspace/github_cpp_makefile_star2_O1/baziotis[P]minijava-cpp/typecheck.cpp
// Function: DeclarationVisitor::visit(TypeDeclaration*)
void DeclarationVisitor::visit(TypeDeclaration *type_decl) {
    LOG_SCOPE;
    assert(!type_decl->is_undefined());
    print_indentation();
    debug_log(type_decl->loc, "Pass1::TypeDeclaration: ", type_decl->id, "\n");
    IdType *type = this->type_table.find(type_decl->id);
    // If it exists and it's declared (i.e. we have processed
    // a type with the same `id`), then we have redeclaration error.
    if (type) {
        if (type->is_defined()) {
            typecheck_error(type_decl->loc, "Type with id: `", type_decl->id,
                            "` has already been declared");
            return;
        } else {
            // Overwrite the location. If the type is already inserted, its
            // loc is its first usage.
            type->loc = type_decl->loc;
            type->set_sizes(type_decl->vars.len, type_decl->methods.len);
        }
    } else {
        type = new IdType(type_decl->id, type_decl->vars.len, type_decl->methods.len);
        type->loc = type_decl->loc;
        this->type_table.insert(type->id, type);
    }
    // Handle inheritance
    if (type_decl->extends) {
        IdType *parent = this->id_to_type(type_decl->extends, type_decl->loc);
        type->set_parent(parent);
        parent->add_child(type);
    } else {
        inher_roots.push(type);
    }
    for (LocalDeclaration *ld : type_decl->vars) {
        // Check redefinition in fields.
        // IMPORTANT:
        // - A field must not conflict with a field of the current class.
        // - A field can conflict with a field of the parent class and
        //   this is called shadowing. And it's correct (when we refer
        //   to the field, we refer to the most immediate in the
        //   inheritance tree).
        // - A field can't possibly conflict with a method
        //   of the current class because first we define all the fields,
        //   then all the methods (so, only a method can conflict with a field).
        // - A field can conflict with a method of a parent class, but that's
        //   NOT an error. Because it is disambiguated in what we refer to
        //   by the way we dereference.

        Field *field = type->fields.find(ld->id);
        if (field) {
            typecheck_error(ld->loc, "In class with id: `", type_decl->id,
                            "`, redefinition of field with id: `", field->id, "`");
        } else {
            field = ld->accept(this);
            field->kind = (int)LOCAL_KIND::FIELD;
            type->fields.insert(field->id, field);
        }
    }
    for (MethodDeclaration *md : type_decl->methods) {
        // Check redefinition
        // IMPORTANT:
        // - A method must not conflict with a method of the current class.
        // - A method must not conflict with a field of the current class.
        // - A method can conflict with a method of the parent class:
        //   -- If the methods have the same return type and the _same_
        //      parameters, then it's valid overriding.
        //   -- Otherwise, it's an error.
        //   We CAN'T check this in the first pass as it is possible that
        //   we have not processed the parent type yet. Note that we don't
        //   check this at the typecheck visitor but at the offset computation.
        // - A method can conflict with a field of the parent 
        //   but that's NOT an error.  Because it is disambiguated in what
        //   we refer to by the way we dereference.

        Method *method = type->methods.find(md->id);
        if (method) {
            typecheck_error(md->loc, "In class with id: `", type_decl->id,
                            "`, redefinition of method with id: `", method->id,
                            "`. Note that you can override but not overload ",
                            "a method");
        } else {
            method = md->accept(this);
            assert(method);
            assert(method->id);
            type->methods.insert(method->id, method);
        }
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x17(%rsp), %rdi
callq 0x34d0
movq 0x10(%rbx), %rax
orq 0x8(%rbx), %rax
je 0x9a61
callq 0x34f7
movl (%rbx), %edi
movq 0x8(%rbx), %rdx
leaq 0x91ef(%rip), %rsi      # 0x1272d
callq 0x9ac9
movq 0x8(%rbx), %rdx
movq 0x30(%r14), %rax
testq %rax, %rax
je 0x9590
testq %rdx, %rdx
je 0x9a80
imull $0x5f5e505, %edx, %ecx  # imm = 0x5F5E505
imulq %rax, %rcx
shrq $0x20, %rcx
movq 0x38(%r14), %rdi
xorl %r15d, %r15d
movq %rcx, %rsi
movq (%rdi,%rsi,8), %r8
cmpq %rdx, %r8
je 0x9595
testq %r8, %r8
je 0x959d
incq %rsi
cmpq %rax, %rsi
cmoveq %r15, %rsi
cmpq %rcx, %rsi
jne 0x9571
jmp 0x959d
xorl %r15d, %r15d
jmp 0x959d
movq 0x40(%r14), %rax
movq (%rax,%rsi,8), %r15
testq %r15, %r15
je 0x95c3
cmpl $0x0, 0x4(%r15)
movl (%rbx), %edi
je 0x95ff
leaq 0x9194(%rip), %rsi      # 0x12746
leaq 0x919d(%rip), %rcx      # 0x12756
callq 0x9b13
jmp 0x992d
movl $0x90, %edi
movl $0x3, %esi
callq 0x23f5
movq %rax, %r15
movq 0x8(%rbx), %rsi
movq 0x20(%rbx), %rdx
movq 0x38(%rbx), %rcx
movq %rax, %rdi
callq 0xeee6
movl (%rbx), %eax
movl %eax, (%r15)
movq 0x8(%r15), %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x8e86
jmp 0x9627
movl %edi, (%r15)
movq 0x20(%rbx), %rsi
movq 0x38(%rbx), %r12
movl $0x4, 0x4(%r15)
leaq 0x10(%r15), %rdi
callq 0xf2ea
leaq 0x40(%r15), %rdi
movq %r12, %rsi
callq 0xf74a
movq 0x10(%rbx), %rsi
testq %rsi, %rsi
je 0x964b
movl (%rbx), %edx
movq %r14, %rdi
callq 0x8da6
movq %rax, 0x78(%r15)
movq %rax, %rdi
movq %r15, %rsi
callq 0xef80
jmp 0x9686
movq 0x12426(%rip), %r12     # 0x1ba78
incq %r12
cmpq 0x12414(%rip), %r12     # 0x1ba70
jbe 0x966d
leaq 0x1240b(%rip), %rdi     # 0x1ba70
movq %r12, %rsi
callq 0xf8fa
movq 0x1240c(%rip), %rax     # 0x1ba80
movq 0x123fd(%rip), %rcx     # 0x1ba78
movq %r15, (%rax,%rcx,8)
movq %r12, 0x123f2(%rip)     # 0x1ba78
movq 0x20(%rbx), %rax
testq %rax, %rax
je 0x97d4
movq 0x28(%rbx), %rbp
leaq (,%rax,8), %r12
addq %rbp, %r12
xorl %r13d, %r13d
movq (%rbp), %rsi
movq 0x10(%r15), %rax
testq %rax, %rax
je 0x96f9
movq 0x18(%rsi), %rcx
testq %rcx, %rcx
je 0x9998
imull $0x5f5e505, %ecx, %edx  # imm = 0x5F5E505
imulq %rax, %rdx
shrq $0x20, %rdx
movq 0x18(%r15), %r8
movq %rdx, %rdi
movq (%r8,%rdi,8), %r9
cmpq %rcx, %r9
je 0x96fe
testq %r9, %r9
je 0x96f9
incq %rdi
cmpq %rax, %rdi
cmoveq %r13, %rdi
movl $0x0, %r9d
cmpq %rdx, %rdi
jne 0x96d4
jmp 0x9706
xorl %r9d, %r9d
jmp 0x9706
movq 0x20(%r15), %rax
movq (%rax,%rdi,8), %r9
testq %r9, %r9
je 0x972c
movl (%rsi), %edi
movq 0x8(%rbx), %rdx
movq (%r9), %r8
leaq 0x9057(%rip), %rsi      # 0x12772
leaq 0x9064(%rip), %rcx      # 0x12786
callq 0x9bdb
jmp 0x97c7
movq %r14, %rdi
callq 0x9da2
movb $0x2, 0x38(%rax)
movq 0x30(%r15), %rcx
cmpq 0x38(%r15), %rcx
je 0x97c7
movq (%rax), %rsi
testq %rsi, %rsi
je 0x9a23
movq 0x10(%r15), %rdx
testq %rdx, %rdx
je 0x9a0c
imull $0x5f5e505, %esi, %edi  # imm = 0x5F5E505
imulq %rdx, %rdi
shrq $0x20, %rdi
movq 0x18(%r15), %r8
movq (%r8,%rdi,8), %r10
movq %rdi, %r9
testq %r10, %r10
je 0x97a9
cmpq %rsi, %r10
je 0x9946
movq %r9, %r10
incq %r10
cmpq %rdx, %r10
movl $0x0, %r9d
cmovneq %r10, %r9
cmpq %rdi, %r9
je 0x97c7
movq (%r8,%r9,8), %r10
testq %r10, %r10
jne 0x977d
jmp 0x97ac
movq %rdi, %r9
movq %rsi, (%r8,%r9,8)
movq 0x20(%r15), %rdx
movq %rax, (%rdx,%r9,8)
movq 0x28(%r15), %rdx
movq %rax, (%rdx,%rcx,8)
incq %rcx
movq %rcx, 0x30(%r15)
addq $0x8, %rbp
cmpq %r12, %rbp
jne 0x96a5
movq 0x38(%rbx), %rax
testq %rax, %rax
je 0x992d
movq 0x40(%rbx), %r12
leaq (%r12,%rax,8), %r13
xorl %ebp, %ebp
movq (%r12), %rsi
movq 0x40(%r15), %rax
testq %rax, %rax
je 0x983f
movq 0x18(%rsi), %rcx
testq %rcx, %rcx
je 0x99af
imull $0x5f5e505, %ecx, %edx  # imm = 0x5F5E505
imulq %rax, %rdx
shrq $0x20, %rdx
movq 0x48(%r15), %r8
movq %rdx, %rdi
movq (%r8,%rdi,8), %r9
cmpq %rcx, %r9
je 0x9844
testq %r9, %r9
je 0x983f
incq %rdi
cmpq %rax, %rdi
cmoveq %rbp, %rdi
movl $0x0, %r9d
cmpq %rdx, %rdi
jne 0x981a
jmp 0x984c
xorl %r9d, %r9d
jmp 0x984c
movq 0x50(%r15), %rax
movq (%rax,%rdi,8), %r9
testq %r9, %r9
je 0x9884
movl (%rsi), %edi
movq 0x8(%rbx), %rdx
movq (%r9), %r8
leaq 0x8f9e(%rip), %rax      # 0x127ff
movq %rax, (%rsp)
leaq 0x8f06(%rip), %rsi      # 0x12772
leaq 0x8f37(%rip), %rcx      # 0x127aa
leaq 0x8f55(%rip), %r9       # 0x127cf
callq 0x9cc6
jmp 0x9920
movq %r14, %rdi
callq 0x9f84
testq %rax, %rax
je 0x99ed
movq (%rax), %rsi
testq %rsi, %rsi
je 0x99ce
movq 0x60(%r15), %rcx
cmpq 0x68(%r15), %rcx
je 0x9920
movq 0x40(%r15), %rdx
testq %rdx, %rdx
je 0x9a42
imull $0x5f5e505, %esi, %edi  # imm = 0x5F5E505
imulq %rdx, %rdi
shrq $0x20, %rdi
movq 0x48(%r15), %r8
movq (%r8,%rdi,8), %r10
movq %rdi, %r9
testq %r10, %r10
je 0x9902
cmpq %rsi, %r10
je 0x996b
movq %r9, %r10
incq %r10
cmpq %rdx, %r10
movl $0x0, %r9d
cmovneq %r10, %r9
cmpq %rdi, %r9
je 0x9920
movq (%r8,%r9,8), %r10
testq %r10, %r10
jne 0x98d6
jmp 0x9905
movq %rdi, %r9
movq %rsi, (%r8,%r9,8)
movq 0x50(%r15), %rdx
movq %rax, (%rdx,%r9,8)
movq 0x58(%r15), %rdx
movq %rax, (%rdx,%rcx,8)
incq %rcx
movq %rcx, 0x60(%r15)
addq $0x8, %r12
cmpq %r13, %r12
jne 0x97eb
leaq 0x17(%rsp), %rdi
callq 0x34e4
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xa454(%rip), %rdi      # 0x13da1
xorl %eax, %eax
callq 0x2030
leaq 0x7dfd(%rip), %rdi      # 0x11758
leaq 0x9eb6(%rip), %rsi      # 0x13818
leaq 0xa4a7(%rip), %rcx      # 0x13e10
jmp 0x998e
leaq 0xa42f(%rip), %rdi      # 0x13da1
xorl %eax, %eax
callq 0x2030
leaq 0x7dd8(%rip), %rdi      # 0x11758
leaq 0x9e91(%rip), %rsi      # 0x13818
leaq 0xa54a(%rip), %rcx      # 0x13ed8
movl $0x53, %edx
callq 0x20b0
leaq 0x9e75(%rip), %rdi      # 0x13814
leaq 0x9e72(%rip), %rsi      # 0x13818
leaq 0xa404(%rip), %rcx      # 0x13db1
jmp 0x99c4
leaq 0x9e5e(%rip), %rdi      # 0x13814
leaq 0x9e5b(%rip), %rsi      # 0x13818
leaq 0xa4b3(%rip), %rcx      # 0x13e77
movl $0x5e, %edx
callq 0x20b0
leaq 0x8e33(%rip), %rdi      # 0x12808
leaq 0x8ab2(%rip), %rsi      # 0x1248e
leaq 0x8d18(%rip), %rcx      # 0x126fb
movl $0x288, %edx            # imm = 0x288
callq 0x20b0
leaq 0x8e0d(%rip), %rdi      # 0x12801
leaq 0x8a93(%rip), %rsi      # 0x1248e
leaq 0x8cf9(%rip), %rcx      # 0x126fb
movl $0x287, %edx            # imm = 0x287
callq 0x20b0
leaq 0xa385(%rip), %rdi      # 0x13d98
leaq 0x9dfe(%rip), %rsi      # 0x13818
leaq 0xa3ef(%rip), %rcx      # 0x13e10
jmp 0x9a57
leaq 0x9dea(%rip), %rdi      # 0x13814
leaq 0x9de7(%rip), %rsi      # 0x13818
leaq 0xa3d8(%rip), %rcx      # 0x13e10
movl $0x46, %edx
callq 0x20b0
leaq 0xa34f(%rip), %rdi      # 0x13d98
leaq 0x9dc8(%rip), %rsi      # 0x13818
leaq 0xa481(%rip), %rcx      # 0x13ed8
movl $0x47, %edx
callq 0x20b0
leaq 0x8c78(%rip), %rdi      # 0x126e0
leaq 0x8a1f(%rip), %rsi      # 0x1248e
leaq 0x8c85(%rip), %rcx      # 0x126fb
movl $0x238, %edx            # imm = 0x238
callq 0x20b0
leaq 0x9d8d(%rip), %rdi      # 0x13814
leaq 0x9d8a(%rip), %rsi      # 0x13818
leaq 0x9d92(%rip), %rcx      # 0x13827
jmp 0x99c4
movq %rax, %rbx
movl $0x90, %esi
movq %r15, %rdi
callq 0x2100
jmp 0x9ab7
jmp 0x9ab4
jmp 0x9ab4
jmp 0x9ab4
jmp 0x9ab4
movq %rax, %rbx
leaq 0x17(%rsp), %rdi
callq 0x34e4
movq %rbx, %rdi
callq 0x21c0