// File: /workspace/github_c_makefile_star2_O0/atomlang[P]atomlang/src/pk_compiler.c
// Function: compileType
static int compileType(Compiler* compiler) {

  // Consume the name of the type.
  consume(compiler, TK_NAME, "Expected a type name.");
  const char* name = compiler->previous.start;
  int name_len = compiler->previous.length;
  NameSearchResult result = compilerSearchName(compiler, name, name_len);
  if (result.type != NAME_NOT_DEFINED) {
    parseError(compiler, "Name '%.*s' already exists.", name_len, name);
  }

  // Create a new type.
  Class* type = newClass(compiler->vm, compiler->script,
                         name, (uint32_t)name_len);
  type->ctor->arity = 0;

  // Check count exceeded.
  int fn_index = (int)compiler->script->functions.count - 1;
  if (fn_index == MAX_FUNCTIONS) {
    parseError(compiler, "A script should contain at most %d functions.",
               MAX_FUNCTIONS);
  }

  int ty_index = (int)(compiler->script->classes.count - 1);
  if (ty_index == MAX_CLASSES) {
    parseError(compiler, "A script should contain at most %d types.",
               MAX_CLASSES);
  }

  // Compile the constructor function.
  ASSERT(compiler->func->ptr == compiler->script->body, OOPS);
  Func curr_fn;
  compilerPushFunc(compiler, &curr_fn, type->ctor, fn_index);
  compilerEnterBlock(compiler);

  // Push an instance on the stack.
  emitOpcode(compiler, OP_PUSH_INSTANCE);
  emitByte(compiler, ty_index);

  skipNewLines(compiler);
  TokenType next = peek(compiler);
  while (next != TK_END && next != TK_EOF) {

    // Compile field name.
    consume(compiler, TK_NAME, "Expected a type name.");
    const char* f_name = compiler->previous.start;
    int f_len = compiler->previous.length;

    uint32_t f_index = scriptAddName(compiler->script, compiler->vm,
                                     f_name, f_len);

    // TODO: Add a string compare macro.
    String* new_name = compiler->script->names.data[f_index];
    for (uint32_t i = 0; i < type->field_names.count; i++) {
      String* prev = compiler->script->names.data[type->field_names.data[i]];
      if (new_name->hash == prev->hash && new_name->length == prev->length &&
          memcmp(new_name->data, prev->data, prev->length) == 0) {
        parseError(compiler, "Class field with name '%s' already exists.",
                   new_name->data);
      }
    }

    pkUintBufferWrite(&type->field_names, compiler->vm, f_index);

    // Consume the assignment expression.
    consume(compiler, TK_EQ, "Expected an assignment after field name.");
    compileExpression(compiler); // Assigned value.
    consumeEndStatement(compiler);

    // At this point the stack top would be the expression.
    emitOpcode(compiler, OP_INST_APPEND);

    skipNewLines(compiler);
    next = peek(compiler);
  }
  consume(compiler, TK_END, "Expected 'end' after type declaration end.");

  compilerExitBlock(compiler);

  // At this point, the stack top would be the constructed instance. Return it.
  emitFunctionEnd(compiler);

  compilerPopFunc(compiler);

  return -1; // TODO;
}

// Assembly:
subq $0x98, %rsp
movq %rdi, 0x90(%rsp)
movq 0x90(%rsp), %rdi
leaq 0x12244(%rip), %rdx     # 0x2b712
movl $0x47, %esi
callq 0x160a0
movq 0x90(%rsp), %rax
movq 0x38(%rax), %rax
movq %rax, 0x88(%rsp)
movq 0x90(%rsp), %rax
movl 0x40(%rax), %eax
movl %eax, 0x84(%rsp)
movq 0x90(%rsp), %rdi
movq 0x88(%rsp), %rsi
movl 0x84(%rsp), %edx
callq 0x16dd0
movl %edx, 0x70(%rsp)
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rax
movq %rax, 0x78(%rsp)
movl 0x70(%rsp), %eax
movl %eax, 0x80(%rsp)
cmpl $0x0, 0x78(%rsp)
je 0x19564
movq 0x90(%rsp), %rdi
movl 0x84(%rsp), %edx
movq 0x88(%rsp), %rcx
leaq 0x11b0c(%rip), %rsi     # 0x2b069
movb $0x0, %al
callq 0x15f90
movq 0x90(%rsp), %rax
movq (%rax), %rdi
movq 0x90(%rsp), %rax
movq 0x18b0(%rax), %rsi
movq 0x88(%rsp), %rdx
movl 0x84(%rsp), %ecx
callq 0x4d50
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rax
movq 0x20(%rax), %rax
movl $0x0, 0x20(%rax)
movq 0x90(%rsp), %rax
movq 0x18b0(%rax), %rax
movl 0x48(%rax), %eax
subl $0x1, %eax
movl %eax, 0x5c(%rsp)
cmpl $0x100, 0x5c(%rsp)      # imm = 0x100
jne 0x195e5
movq 0x90(%rsp), %rdi
leaq 0x11ab9(%rip), %rsi     # 0x2b092
movl $0x100, %edx            # imm = 0x100
movb $0x0, %al
callq 0x15f90
movq 0x90(%rsp), %rax
movq 0x18b0(%rax), %rax
movl 0x58(%rax), %eax
subl $0x1, %eax
movl %eax, 0x58(%rsp)
cmpl $0xff, 0x58(%rsp)
jne 0x19623
movq 0x90(%rsp), %rdi
leaq 0x12111(%rip), %rsi     # 0x2b728
movl $0xff, %edx
movb $0x0, %al
callq 0x15f90
jmp 0x19625
movq 0x90(%rsp), %rax
movq 0x18c0(%rax), %rax
movq 0x8(%rax), %rax
movq 0x90(%rsp), %rcx
movq 0x18b0(%rcx), %rcx
cmpq 0x80(%rcx), %rax
je 0x1968a
movq 0x199a1(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x10aef(%rip), %rsi     # 0x2a150
leaq 0x10bfc(%rip), %rdx     # 0x2a264
leaq 0x120e3(%rip), %rcx     # 0x2b752
leaq 0x11961(%rip), %r8      # 0x2afd7
movl $0x7b1, %r9d            # imm = 0x7B1
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x1968c
movq 0x90(%rsp), %rdi
movq 0x60(%rsp), %rax
movq 0x20(%rax), %rdx
movl 0x5c(%rsp), %ecx
leaq 0x38(%rsp), %rsi
callq 0x16fe0
movq 0x90(%rsp), %rdi
callq 0x17050
movq 0x90(%rsp), %rdi
movl $0x8, %esi
callq 0x16650
movq 0x90(%rsp), %rdi
movl 0x58(%rsp), %esi
callq 0x166d0
movq 0x90(%rsp), %rdi
callq 0x15f40
movq 0x90(%rsp), %rdi
callq 0x17480
movl %eax, 0x34(%rsp)
xorl %eax, %eax
cmpl $0x35, 0x34(%rsp)
movb %al, 0x7(%rsp)
je 0x19712
cmpl $0x1, 0x34(%rsp)
setne %al
movb %al, 0x7(%rsp)
movb 0x7(%rsp), %al
testb $0x1, %al
jne 0x1971f
jmp 0x198ea
movq 0x90(%rsp), %rdi
movl $0x47, %esi
leaq 0x11fdf(%rip), %rdx     # 0x2b712
callq 0x160a0
movq 0x90(%rsp), %rax
movq 0x38(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x90(%rsp), %rax
movl 0x40(%rax), %eax
movl %eax, 0x24(%rsp)
movq 0x90(%rsp), %rax
movq 0x18b0(%rax), %rdi
movq 0x90(%rsp), %rax
movq (%rax), %rsi
movq 0x28(%rsp), %rdx
movl 0x24(%rsp), %ecx
callq 0x4c60
movl %eax, 0x20(%rsp)
movq 0x90(%rsp), %rax
movq 0x18b0(%rax), %rax
movq 0x60(%rax), %rax
movl 0x20(%rsp), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x18(%rsp)
movl $0x0, 0x14(%rsp)
movl 0x14(%rsp), %eax
movq 0x60(%rsp), %rcx
cmpl 0x30(%rcx), %eax
jae 0x19865
movq 0x90(%rsp), %rax
movq 0x18b0(%rax), %rax
movq 0x60(%rax), %rax
movq 0x60(%rsp), %rcx
movq 0x28(%rcx), %rcx
movl 0x14(%rsp), %edx
movl (%rcx,%rdx,4), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x8(%rsp)
movq 0x18(%rsp), %rax
movl 0x10(%rax), %eax
movq 0x8(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jne 0x19853
movq 0x18(%rsp), %rax
movl 0x14(%rax), %eax
movq 0x8(%rsp), %rcx
cmpl 0x14(%rcx), %eax
jne 0x19853
movq 0x18(%rsp), %rdi
addq $0x1c, %rdi
movq 0x8(%rsp), %rsi
addq $0x1c, %rsi
movq 0x8(%rsp), %rax
movl 0x14(%rax), %eax
movl %eax, %edx
callq 0x2200
cmpl $0x0, %eax
jne 0x19853
movq 0x90(%rsp), %rdi
movq 0x18(%rsp), %rdx
addq $0x1c, %rdx
leaq 0x11f12(%rip), %rsi     # 0x2b75e
movb $0x0, %al
callq 0x15f90
jmp 0x19855
movl 0x14(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x14(%rsp)
jmp 0x197ac
movq 0x60(%rsp), %rdi
addq $0x28, %rdi
movq 0x90(%rsp), %rax
movq (%rax), %rsi
movl 0x20(%rsp), %edx
callq 0x3020
movq 0x90(%rsp), %rdi
movl $0x1a, %esi
leaq 0x11ef3(%rip), %rdx     # 0x2b789
callq 0x160a0
movq 0x90(%rsp), %rdi
callq 0x17be0
movq 0x90(%rsp), %rdi
callq 0x16110
movq 0x90(%rsp), %rdi
movl $0xb, %esi
callq 0x16650
movq 0x90(%rsp), %rdi
callq 0x15f40
movq 0x90(%rsp), %rdi
callq 0x17480
movl %eax, 0x34(%rsp)
jmp 0x196f9
movq 0x90(%rsp), %rdi
movl $0x35, %esi
leaq 0x11eb4(%rip), %rdx     # 0x2b7b2
callq 0x160a0
movq 0x90(%rsp), %rdi
callq 0x17300
movq 0x90(%rsp), %rdi
callq 0x16240
movq 0x90(%rsp), %rdi
callq 0x173c0
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x98, %rsp
retq
nopw (%rax,%rax)