// File: /workspace/github_cpp_makefile_star2_O3/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 0x34c8
movq 0x10(%rbx), %rax
orq 0x8(%rbx), %rax
je 0x98da
callq 0x34ef
movl (%rbx), %edi
movq 0x8(%rbx), %rdx
leaq 0xa2b5(%rip), %rsi      # 0x1369d
callq 0x9942
movq 0x30(%r14), %rax
testq %rax, %rax
je 0x946c
movq 0x8(%rbx), %rdx
testq %rdx, %rdx
je 0x98f9
imull $0x5f5e505, %edx, %ecx  # imm = 0x5F5E505
imulq %rax, %rcx
shrq $0x20, %rcx
movq 0x38(%r14), %rsi
xorl %r8d, %r8d
movq %rcx, %rdi
movq (%rsi,%rdi,8), %r9
cmpq %rdx, %r9
je 0x943a
testq %r9, %r9
je 0x946c
incq %rdi
cmpq %rax, %rdi
cmoveq %r8, %rdi
cmpq %rcx, %rdi
jne 0x941b
jmp 0x946c
movq 0x40(%r14), %rax
movq (%rax,%rdi,8), %r15
testq %r15, %r15
je 0x946c
cmpl $0x0, 0x4(%r15)
movl (%rbx), %edi
je 0x9792
leaq 0xa25b(%rip), %rsi      # 0x136b6
leaq 0xa264(%rip), %rcx      # 0x136c6
callq 0x998c
jmp 0x9779
movl $0x90, %edi
movl $0x3, %esi
callq 0x23ef
movq %rax, %r15
movq 0x8(%rbx), %rsi
movq 0x20(%rbx), %rdx
movq 0x38(%rbx), %rcx
movq %rax, %rdi
callq 0xf712
movl (%rbx), %eax
movl %eax, (%r15)
movq 0x8(%r15), %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x8d6c
movq 0x10(%rbx), %rsi
testq %rsi, %rsi
je 0x94ca
movl (%rbx), %edx
movq %r14, %rdi
callq 0x8c92
movq %rax, 0x78(%r15)
movq %rax, %rdi
movq %r15, %rsi
callq 0xf7ac
jmp 0x9506
movq 0x135a7(%rip), %rax     # 0x1ca78
leaq 0x1(%rax), %r12
cmpq 0x13594(%rip), %r12     # 0x1ca70
jbe 0x94f4
leaq 0x1358b(%rip), %rdi     # 0x1ca70
movq %r12, %rsi
callq 0x10112
movq 0x13584(%rip), %rax     # 0x1ca78
movq 0x13585(%rip), %rcx     # 0x1ca80
movq %r15, (%rcx,%rax,8)
movq %r12, 0x13572(%rip)     # 0x1ca78
movq 0x20(%rbx), %rax
testq %rax, %rax
je 0x9636
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 0x95a7
movq 0x18(%rsi), %rcx
testq %rcx, %rcx
je 0x984f
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 0x9579
testq %r9, %r9
je 0x95a7
incq %rdi
cmpq %rax, %rdi
movl $0x0, %r9d
cmoveq %r9, %rdi
cmpq %rdx, %rdi
jne 0x9554
jmp 0x95a7
movq 0x20(%r15), %rax
movq (%rax,%rdi,8), %rax
testq %rax, %rax
je 0x95a7
movl (%rsi), %edi
movq 0x8(%rbx), %rdx
movq (%rax), %r8
leaq 0xa14c(%rip), %rsi      # 0x136e2
leaq 0xa159(%rip), %rcx      # 0x136f6
callq 0x9a58
jmp 0x9629
movq %r14, %rdi
callq 0x9c28
movb $0x2, 0x38(%rax)
movq 0x30(%r15), %rcx
cmpq 0x38(%r15), %rcx
je 0x9629
movq (%rax), %rsi
testq %rsi, %rsi
je 0x9885
movq 0x10(%r15), %rdx
testq %rdx, %rdx
je 0x98a4
imull $0x5f5e505, %esi, %edi  # imm = 0x5F5E505
imulq %rdx, %rdi
shrq $0x20, %rdi
movq 0x18(%r15), %r9
movq %rdi, %r8
movq (%r9,%r8,8), %r10
testq %r10, %r10
je 0x960e
cmpq %rsi, %r10
je 0x97bf
incq %r8
cmpq %rdx, %r8
cmoveq %r13, %r8
cmpq %rdi, %r8
jne 0x95eb
jmp 0x9629
movq %rsi, (%r9,%r8,8)
movq 0x20(%r15), %rdx
movq %rax, (%rdx,%r8,8)
movq 0x28(%r15), %rdx
movq %rax, (%rdx,%rcx,8)
incq %rcx
movq %rcx, 0x30(%r15)
addq $0x8, %rbp
cmpq %r12, %rbp
jne 0x9525
movq 0x38(%rbx), %rax
testq %rax, %rax
je 0x9779
movq 0x40(%rbx), %r12
leaq (%r12,%rax,8), %r13
xorl %ebp, %ebp
movq (%r12), %rsi
movq 0x40(%r15), %rax
testq %rax, %rax
je 0x96e5
movq 0x18(%rsi), %rcx
testq %rcx, %rcx
je 0x9866
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 0x96a5
testq %r9, %r9
je 0x96e5
incq %rdi
cmpq %rax, %rdi
movl $0x0, %r9d
cmoveq %r9, %rdi
cmpq %rdx, %rdi
jne 0x9680
jmp 0x96e5
movq 0x50(%r15), %rax
movq (%rax,%rdi,8), %rax
testq %rax, %rax
je 0x96e5
movl (%rsi), %edi
movq 0x8(%rbx), %rdx
movq (%rax), %r8
leaq 0xa0ad(%rip), %rax      # 0x1376f
movq %rax, (%rsp)
leaq 0xa015(%rip), %rsi      # 0x136e2
leaq 0xa046(%rip), %rcx      # 0x1371a
leaq 0xa064(%rip), %r9       # 0x1373f
callq 0x9b47
jmp 0x976c
movq %r14, %rdi
callq 0x9e12
testq %rax, %rax
je 0x9830
movq (%rax), %rsi
testq %rsi, %rsi
je 0x9811
movq 0x60(%r15), %rcx
cmpq 0x68(%r15), %rcx
je 0x976c
movq 0x40(%r15), %rdx
testq %rdx, %rdx
je 0x98bb
imull $0x5f5e505, %esi, %edi  # imm = 0x5F5E505
imulq %rdx, %rdi
shrq $0x20, %rdi
movq 0x48(%r15), %r9
movq %rdi, %r8
movq (%r9,%r8,8), %r10
testq %r10, %r10
je 0x9751
cmpq %rsi, %r10
je 0x97e4
incq %r8
cmpq %rdx, %r8
cmoveq %rbp, %r8
cmpq %rdi, %r8
jne 0x972e
jmp 0x976c
movq %rsi, (%r9,%r8,8)
movq 0x50(%r15), %rdx
movq %rax, (%rdx,%r8,8)
movq 0x58(%r15), %rdx
movq %rax, (%rdx,%rcx,8)
incq %rcx
movq %rcx, 0x60(%r15)
addq $0x8, %r12
cmpq %r13, %r12
jne 0x964d
leaq 0x17(%rsp), %rdi
callq 0x34dc
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %edi, (%r15)
movq 0x20(%rbx), %rsi
movq 0x38(%rbx), %r12
movl $0x4, 0x4(%r15)
leaq 0x10(%r15), %rdi
callq 0xfb16
leaq 0x40(%r15), %rdi
movq %r12, %rsi
callq 0xff62
jmp 0x94a6
leaq 0xb55e(%rip), %rdi      # 0x14d24
xorl %eax, %eax
callq 0x2030
leaq 0x8ece(%rip), %rdi      # 0x126a2
leaq 0xafae(%rip), %rsi      # 0x14789
leaq 0xb5b1(%rip), %rcx      # 0x14d93
jmp 0x9807
leaq 0xb539(%rip), %rdi      # 0x14d24
xorl %eax, %eax
callq 0x2030
leaq 0x8ea9(%rip), %rdi      # 0x126a2
leaq 0xaf89(%rip), %rsi      # 0x14789
leaq 0xb654(%rip), %rcx      # 0x14e5b
movl $0x53, %edx
callq 0x20b0
leaq 0x9f60(%rip), %rdi      # 0x13778
leaq 0x9bdf(%rip), %rsi      # 0x133fe
leaq 0x9e45(%rip), %rcx      # 0x1366b
movl $0x288, %edx            # imm = 0x288
callq 0x20b0
leaq 0x9f3a(%rip), %rdi      # 0x13771
leaq 0x9bc0(%rip), %rsi      # 0x133fe
leaq 0x9e26(%rip), %rcx      # 0x1366b
movl $0x287, %edx            # imm = 0x287
callq 0x20b0
leaq 0xaf2f(%rip), %rdi      # 0x14785
leaq 0xaf2c(%rip), %rsi      # 0x14789
leaq 0xb4d0(%rip), %rcx      # 0x14d34
jmp 0x987b
leaq 0xaf18(%rip), %rdi      # 0x14785
leaq 0xaf15(%rip), %rsi      # 0x14789
leaq 0xb57f(%rip), %rcx      # 0x14dfa
movl $0x5e, %edx
callq 0x20b0
leaq 0xaef9(%rip), %rdi      # 0x14785
leaq 0xaef6(%rip), %rsi      # 0x14789
leaq 0xb4f9(%rip), %rcx      # 0x14d93
movl $0x46, %edx
callq 0x20b0
leaq 0xb470(%rip), %rdi      # 0x14d1b
leaq 0xaed7(%rip), %rsi      # 0x14789
leaq 0xb4da(%rip), %rcx      # 0x14d93
jmp 0x98d0
leaq 0xb459(%rip), %rdi      # 0x14d1b
leaq 0xaec0(%rip), %rsi      # 0x14789
leaq 0xb58b(%rip), %rcx      # 0x14e5b
movl $0x47, %edx
callq 0x20b0
leaq 0x9d6f(%rip), %rdi      # 0x13650
leaq 0x9b16(%rip), %rsi      # 0x133fe
leaq 0x9d7c(%rip), %rcx      # 0x1366b
movl $0x238, %edx            # imm = 0x238
callq 0x20b0
leaq 0xae85(%rip), %rdi      # 0x14785
leaq 0xae82(%rip), %rsi      # 0x14789
leaq 0xae8a(%rip), %rcx      # 0x14798
jmp 0x987b
movq %rax, %rbx
movl $0x90, %esi
movq %r15, %rdi
callq 0x2100
jmp 0x9930
jmp 0x992d
jmp 0x992d
jmp 0x992d
jmp 0x992d
movq %rax, %rbx
leaq 0x17(%rsp), %rdi
callq 0x34dc
movq %rbx, %rdi
callq 0x21c0