// File: /workspace/github_c_makefile_star2_O2/atomlang[P]atomlang/src/pk_compiler.c
// Function: exprName
static void exprName(Compiler* compiler) {

  const char* start = compiler->previous.start;
  int length = compiler->previous.length;
  int line = compiler->previous.line;
  NameSearchResult result = compilerSearchName(compiler, start, length);

  if (result.type == NAME_NOT_DEFINED) {
    if (compiler->l_value && match(compiler, TK_EQ)) {
      skipNewLines(compiler);

      int index = compilerAddVariable(compiler, start, length, line);

      // Compile the assigned value.
      compileExpression(compiler);

      // Store the value to the variable.
      if (compiler->scope_depth == DEPTH_GLOBAL) {
        emitStoreVariable(compiler, index, true);

      } else {
        // This will prevent the assignment from being popped out from the
        // stack since the assigned value itself is the local and not a temp.
        compiler->new_local = true;
        emitStoreVariable(compiler, index, false);
      }
    } else {

      // The name could be a function which hasn't been defined at this point.
      if (peek(compiler) == TK_LPARAN) {
        emitOpcode(compiler, OP_PUSH_FN);
        int index = emitByte(compiler, 0xff);
        compilerAddForward(compiler, index, _FN, start, length, line);
      } else {
        parseError(compiler, "Name '%.*s' is not defined.", length, start);
      }
    }

  } else {

    switch (result.type) {
      case NAME_LOCAL_VAR:
      case NAME_GLOBAL_VAR: {
        const bool is_global = result.type == NAME_GLOBAL_VAR;

        if (compiler->l_value && matchAssignment(compiler)) {
          skipNewLines(compiler);

          TokenType assignment = compiler->previous.type;
          if (assignment != TK_EQ) {
            emitPushVariable(compiler, result.index, is_global);
            compileExpression(compiler);
            emitAssignment(compiler, assignment);

          } else {
            compileExpression(compiler);
          }

          emitStoreVariable(compiler, result.index, is_global);

        } else {
          emitPushVariable(compiler, result.index, is_global);
        }
        break;
      }

      case NAME_FUNCTION:
        emitOpcode(compiler, OP_PUSH_FN);
        emitByte(compiler, result.index);
        break;

      case NAME_CLASS:
        emitOpcode(compiler, OP_PUSH_TYPE);
        emitByte(compiler, result.index);
        break;

      case NAME_BUILTIN:
        emitOpcode(compiler, OP_PUSH_BUILTIN_FN);
        emitByte(compiler, result.index);
        break;

      case NAME_NOT_DEFINED:
        UNREACHABLE(); // Case already handled.
    }
  }

  compiler->is_last_call = false;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movq %rdi, %rbx
movq 0x38(%rdi), %r15
movl 0x40(%rdi), %ebp
movl 0x44(%rdi), %r12d
movq %r15, %rsi
movl %ebp, %edx
callq 0xcb5c
movq %rax, %r14
cmpl $0x5, %r14d
ja 0xb5ce
movl %r14d, %eax
leaq 0xd77e(%rip), %rcx      # 0x18c70
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpb $0x1, 0x38cd(%rbx)
jne 0xb538
movq %rbx, %rdi
callq 0xd760
testb %al, %al
je 0xb538
movq %rbx, %rdi
callq 0xd399
movl 0x30(%rbx), %ebp
cmpl $0x1a, %ebp
jne 0xb63c
movq %rbx, %rdi
callq 0xd50e
movq %r14, %r15
shrq $0x20, %r15
jmp 0xb669
xorl %edx, %edx
cmpl $0x2, %r14d
sete %dl
shrq $0x20, %r14
movq %rbx, %rdi
movl %r14d, %esi
callq 0xd80b
jmp 0xb5ce
pushq $0x22
jmp 0xb5b6
cmpb $0x1, 0x38cd(%rbx)
jne 0xb5de
pushq $0x1a
popq %rsi
movq %rbx, %rdi
callq 0xc438
testb %al, %al
je 0xb5de
movq %rbx, %rdi
callq 0xd399
movq %rbx, %rdi
movq %r15, %rsi
movl %ebp, %edx
movl %r12d, %ecx
callq 0xcc88
movl %eax, %ebp
movq %rbx, %rdi
callq 0xd50e
cmpl $-0x1, 0xa0(%rbx)
je 0xb6c9
movb $0x1, 0x38cc(%rbx)
movq %rbx, %rdi
movl %ebp, %esi
xorl %edx, %edx
jmp 0xb678
pushq $0x24
jmp 0xb5b6
pushq $0x23
popq %rsi
movq %rbx, %rdi
callq 0xc734
shrq $0x20, %r14
movq %rbx, %rdi
movl %r14d, %esi
callq 0xc773
movb $0x0, 0x38ce(%rbx)
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x9, 0x50(%rbx)
jne 0xb624
pushq $0x22
popq %rsi
movq %rbx, %rdi
callq 0xc734
movq %rbx, %rdi
movl $0xff, %esi
callq 0xc773
movslq 0x38c8(%rbx), %rcx
cmpq $0x100, %rcx            # imm = 0x100
jne 0xb682
leaq 0xdc2e(%rip), %rsi      # 0x19241
movq %rbx, %rdi
movl $0x100, %edx            # imm = 0x100
xorl %eax, %eax
callq 0xc455
jmp 0xb5ce
leaq 0xd7f2(%rip), %rsi      # 0x18e1d
movq %rbx, %rdi
movl %ebp, %edx
movq %r15, %rcx
xorl %eax, %eax
callq 0xc455
jmp 0xb5ce
xorl %edx, %edx
cmpl $0x2, %r14d
sete %dl
movq %r14, %r15
shrq $0x20, %r15
movq %rbx, %rdi
movl %r15d, %esi
callq 0xd80b
movq %rbx, %rdi
callq 0xd50e
movq %rbx, %rdi
movl %ebp, %esi
callq 0xd851
xorl %edx, %edx
cmpl $0x2, %r14d
sete %dl
movq %rbx, %rdi
movl %r15d, %esi
callq 0xd71a
jmp 0xb5ce
movq 0x18c0(%rbx), %rdx
movq 0x8(%rdx), %rdx
movq 0x38(%rdx), %rdx
leal 0x1(%rcx), %esi
movl %esi, 0x38c8(%rbx)
shlq $0x5, %rcx
movl %eax, 0x18c8(%rbx,%rcx)
movq %rdx, 0x18d0(%rbx,%rcx)
movq %r15, 0x18d8(%rbx,%rcx)
movl %ebp, 0x18e0(%rbx,%rcx)
movl %r12d, 0x18e4(%rbx,%rcx)
jmp 0xb5ce
pushq $0x1
popq %rdx
movq %rbx, %rdi
movl %ebp, %esi
jmp 0xb678