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

  // is_temproary will be set to true if the statement is an temporary
  // expression, it'll used to be pop from the stack.
  bool is_temproary = false;

  // This will be set to true if the statement is an expression. It'll used to
  // print it's value when running in REPL mode.
  bool is_expression = false;

  // If the statement is call, this will be set to true.
  compiler->is_last_call = false;

  if (match(compiler, TK_BREAK)) {
    if (compiler->loop == NULL) {
      parseError(compiler, "Cannot use 'break' outside a loop.");
      return;
    }

    ASSERT(compiler->loop->patch_count < MAX_BREAK_PATCH,
      "Too many break statements (" STRINGIFY(MAX_BREAK_PATCH) ")." );

    consumeEndStatement(compiler);
    // Pop all the locals at the loop's body depth.
    compilerPopLocals(compiler, compiler->loop->depth + 1);

    emitOpcode(compiler, OP_JUMP);
    int patch = emitShort(compiler, 0xffff); //< Will be patched.
    compiler->loop->patches[compiler->loop->patch_count++] = patch;

  } else if (match(compiler, TK_CONTINUE)) {
    if (compiler->loop == NULL) {
      parseError(compiler, "Cannot use 'continue' outside a loop.");
      return;
    }

    consumeEndStatement(compiler);
    // Pop all the locals at the loop's body depth.
    compilerPopLocals(compiler, compiler->loop->depth + 1);

    emitLoopJump(compiler);

  } else if (match(compiler, TK_RETURN)) {

    if (compiler->scope_depth == DEPTH_GLOBAL) {
      parseError(compiler, "Invalid 'return' outside a function.");
      return;
    }

    if (matchEndStatement(compiler)) {
      emitOpcode(compiler, OP_PUSH_NULL);
      emitOpcode(compiler, OP_RETURN);
    } else {
      compileExpression(compiler); //< Return value is at stack top.

      // Tail call optimization disabled at debug mode.
      if (compiler->options && !compiler->options->debug) {
        if (compiler->is_last_call) {
          ASSERT(_FN->opcodes.count >= 2, OOPS); // OP_CALL, argc
          ASSERT(_FN->opcodes.data[_FN->opcodes.count - 2] == OP_CALL, OOPS);
          _FN->opcodes.data[_FN->opcodes.count - 2] = OP_TAIL_CALL;

          // Now it's a return statement, not call.
          compiler->is_last_call = false;
        }
      }

      consumeEndStatement(compiler);
      emitOpcode(compiler, OP_RETURN);
    }
  } else if (match(compiler, TK_IF)) {
    compileIfStatement(compiler, false);

  } else if (match(compiler, TK_WHILE)) {
    compileWhileStatement(compiler);

  } else if (match(compiler, TK_FOR)) {
    compileForStatement(compiler);

  } else {
    compiler->new_local = false;
    compileExpression(compiler);
    consumeEndStatement(compiler);

    is_expression = true;
    if (!compiler->new_local) is_temproary = true;

    compiler->new_local = false;
  }

  // If running REPL mode, print the expression's evaluated value.
  if (compiler->options && compiler->options->repl_mode &&
      compiler->func->ptr == compiler->script->body &&
      is_expression /*&& compiler->scope_depth == DEPTH_GLOBAL*/) {
    emitOpcode(compiler, OP_REPL_PRINT);
  }

  if (is_temproary) emitOpcode(compiler, OP_POP);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x420, %rsp            # imm = 0x420
movq %rdi, %rbx
movb $0x0, 0x38ce(%rdi)
pushq $0x44
popq %rsi
callq 0xc438
testb %al, %al
je 0xceb7
movq 0x18b8(%rbx), %rax
testq %rax, %rax
je 0xcf3c
cmpl $0x100, 0x408(%rax)     # imm = 0x100
jge 0xd308
movq %rbx, %rdi
callq 0xc53b
movq 0x18b8(%rbx), %rax
movl 0x418(%rax), %esi
incl %esi
movq %rbx, %rdi
callq 0xd3f2
pushq $0x2b
popq %rsi
movq %rbx, %rdi
callq 0xc734
movq %rbx, %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0xc748
movq 0x18b8(%rbx), %rcx
movslq 0x408(%rcx), %rdx
leal 0x1(%rdx), %esi
movl %esi, 0x408(%rcx)
movl %eax, 0x8(%rcx,%rdx,4)
jmp 0xd274
pushq $0x45
popq %rsi
movq %rbx, %rdi
callq 0xc438
testb %al, %al
je 0xcf00
cmpq $0x0, 0x18b8(%rbx)
je 0xcf6c
movq %rbx, %rdi
callq 0xc53b
movq 0x18b8(%rbx), %rax
movl 0x418(%rax), %esi
incl %esi
movq %rbx, %rdi
callq 0xd3f2
movq %rbx, %rdi
callq 0xd499
jmp 0xd274
pushq $0x46
popq %rsi
movq %rbx, %rdi
callq 0xc438
testb %al, %al
je 0xcf48
cmpl $-0x1, 0xa0(%rbx)
je 0xd035
movq %rbx, %rdi
callq 0xd4cc
testb %al, %al
je 0xd055
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0xc734
jmp 0xd0b5
leaq 0xc14a(%rip), %rsi      # 0x1908d
jmp 0xd03c
pushq $0x41
popq %rsi
movq %rbx, %rdi
callq 0xc438
testb %al, %al
je 0xcf78
xorl %r14d, %r14d
movq %rbx, %rdi
xorl %esi, %esi
callq 0xd516
movb $0x1, %bpl
jmp 0xd27a
leaq 0xc16f(%rip), %rsi      # 0x190e2
jmp 0xd03c
pushq $0x3f
popq %rsi
movq %rbx, %rdi
callq 0xc438
testb %al, %al
je 0xd0f3
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movl 0x8(%rax), %eax
movq %rsp, %rcx
movl %eax, (%rcx)
andl $0x0, 0x408(%rcx)
movq 0x18b8(%rbx), %rax
movq %rax, 0x410(%rcx)
movl 0xa0(%rbx), %eax
movl %eax, 0x418(%rcx)
movq %rcx, 0x18b8(%rbx)
movq %rbx, %rdi
callq 0xd50e
pushq $0x2e
popq %rsi
movq %rbx, %rdi
callq 0xc734
movq %rbx, %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0xc748
movl %eax, %ebp
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0xcd27
movq %rbx, %rdi
callq 0xd499
movq %rbx, %rdi
movl %ebp, %esi
callq 0xd6a6
xorl %r14d, %r14d
movq 0x18b8(%rbx), %rax
movslq 0x408(%rax), %rcx
cmpq %rcx, %r14
jge 0xd0c5
movl 0x8(%rax,%r14,4), %esi
movq %rbx, %rdi
callq 0xd6a6
incq %r14
jmp 0xd00c
leaq 0xc0cc(%rip), %rsi      # 0x19108
movq %rbx, %rdi
xorl %eax, %eax
addq $0x420, %rsp            # imm = 0x420
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0xc455
movq %rbx, %rdi
callq 0xd50e
movq 0x98(%rbx), %rax
testq %rax, %rax
je 0xd0ad
cmpb $0x0, (%rax)
jne 0xd0ad
cmpb $0x1, 0x38ce(%rbx)
jne 0xd0ad
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl 0x8(%rcx), %eax
cmpl $0x1, %eax
jbe 0xd33d
movq (%rcx), %rcx
addl $-0x2, %eax
cmpb $0x27, (%rcx,%rax)
jne 0xd36b
movb $0x28, (%rcx,%rax)
movb $0x0, 0x38ce(%rbx)
movq %rbx, %rdi
callq 0xc53b
pushq $0x2f
popq %rsi
movq %rbx, %rdi
callq 0xc734
jmp 0xd274
movq 0x410(%rsp), %rax
movq %rax, 0x18b8(%rbx)
movq %rbx, %rdi
callq 0xd399
leaq 0xc091(%rip), %rdx      # 0x19174
pushq $0x35
popq %rsi
movq %rbx, %rdi
callq 0xc4fb
jmp 0xd274
pushq $0x40
popq %rsi
movq %rbx, %rdi
callq 0xc438
testb %al, %al
je 0xd2d8
incl 0xa0(%rbx)
leaq 0xc0b4(%rip), %rdx      # 0x191c7
pushq $0x47
popq %rsi
movq %rbx, %rdi
callq 0xc4fb
movq 0x38(%rbx), %r14
movl 0x40(%rbx), %ebp
movl 0x44(%rbx), %r15d
leaq 0xc0b2(%rip), %rdx      # 0x191e2
pushq $0x37
popq %rsi
movq %rbx, %rdi
callq 0xc4fb
leaq 0xc0c3(%rip), %rsi      # 0x19205
pushq $0x9
popq %r12
movq %rbx, %rdi
movl %r12d, %edx
movl %r15d, %ecx
callq 0xcc88
movq %rbx, %rdi
callq 0xd50e
leaq 0xc0ac(%rip), %rsi      # 0x1920f
movq %rbx, %rdi
movl %r12d, %edx
movl %r15d, %ecx
callq 0xcc88
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0xc734
movq %rbx, %rdi
movq %r14, %rsi
movl %ebp, %edx
movl %r15d, %ecx
callq 0xcc88
pushq $0x1
popq %rbp
movq %rbx, %rdi
movl %ebp, %esi
callq 0xc734
pushq $0x29
popq %rsi
movq %rbx, %rdi
callq 0xc734
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movl 0x8(%rax), %eax
movq %rsp, %rcx
movl %eax, (%rcx)
andl $0x0, 0x408(%rcx)
movq 0x18b8(%rbx), %rax
movq %rax, 0x410(%rcx)
movl 0xa0(%rbx), %eax
movl %eax, 0x418(%rcx)
movq %rcx, 0x18b8(%rbx)
pushq $0x2a
popq %rsi
movq %rbx, %rdi
callq 0xc734
movq %rbx, %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0xc748
movl %eax, %r14d
movq %rbx, %rdi
movl %ebp, %esi
callq 0xcd27
movq %rbx, %rdi
callq 0xd499
movq %rbx, %rdi
movl %r14d, %esi
callq 0xd6a6
xorl %r14d, %r14d
movq 0x18b8(%rbx), %rax
movslq 0x408(%rax), %rcx
cmpq %rcx, %r14
jge 0xd243
movl 0x8(%rax,%r14,4), %esi
movq %rbx, %rdi
callq 0xd6a6
incq %r14
jmp 0xd21e
movq 0x410(%rsp), %rax
movq %rax, 0x18b8(%rbx)
movq %rbx, %rdi
callq 0xd399
leaq 0xbf13(%rip), %rdx      # 0x19174
pushq $0x35
popq %rsi
movq %rbx, %rdi
callq 0xc4fb
movq %rbx, %rdi
callq 0xcdbf
movb $0x1, %bpl
xorl %r14d, %r14d
movq 0x98(%rbx), %rax
testq %rax, %rax
je 0xd2b8
cmpb $0x1, 0x1(%rax)
jne 0xd2b8
movq 0x18b0(%rbx), %rax
movq 0x18c0(%rbx), %rcx
movq 0x8(%rcx), %rcx
cmpq 0x80(%rax), %rcx
setne %al
orb %al, %bpl
jne 0xd2b8
pushq $0x4b
popq %rsi
movq %rbx, %rdi
callq 0xc734
testb %r14b, %r14b
je 0xd2c8
pushq $0x25
popq %rsi
movq %rbx, %rdi
callq 0xc734
addq $0x420, %rsp            # imm = 0x420
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
xorl %ebp, %ebp
movb %bpl, 0x38cc(%rbx)
movq %rbx, %rdi
callq 0xd50e
movq %rbx, %rdi
callq 0xc53b
movb 0x38cc(%rbx), %r14b
xorb $0x1, %r14b
movb %bpl, 0x38cc(%rbx)
jmp 0xd27a
movq 0x15ce9(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0xadd7(%rip), %rsi      # 0x180f0
leaq 0xbd90(%rip), %rdx      # 0x190b0
leaq 0xbdaa(%rip), %rcx      # 0x190d1
leaq 0xbb35(%rip), %r8       # 0x18e63
movl $0xa60, %r9d            # imm = 0xA60
xorl %eax, %eax
callq 0x2250
ud2
movq 0x15cb4(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0xada2(%rip), %rsi      # 0x180f0
leaq 0xaeaf(%rip), %rdx      # 0x18204
leaq 0xbd75(%rip), %rcx      # 0x190d1
leaq 0xbb00(%rip), %r8       # 0x18e63
movl $0xa86, %r9d            # imm = 0xA86
jmp 0xd334
movq 0x15c86(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0xad74(%rip), %rsi      # 0x180f0
leaq 0xae81(%rip), %rdx      # 0x18204
leaq 0xbd47(%rip), %rcx      # 0x190d1
leaq 0xbad2(%rip), %r8       # 0x18e63
movl $0xa87, %r9d            # imm = 0xA87
jmp 0xd334