// File: /workspace/github_c_makefile_star2_O0/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:
subq $0x18, %rsp
movq %rdi, 0x10(%rsp)
movb $0x0, 0xf(%rsp)
movb $0x0, 0xe(%rsp)
movq 0x10(%rsp), %rax
movb $0x0, 0x38ce(%rax)
movq 0x10(%rsp), %rdi
movl $0x44, %esi
callq 0x15f50
testb $0x1, %al
jne 0x174c7
jmp 0x175c8
movq 0x10(%rsp), %rax
cmpq $0x0, 0x18b8(%rax)
jne 0x174ee
movq 0x10(%rsp), %rdi
leaq 0x13d1f(%rip), %rsi     # 0x2b201
movb $0x0, %al
callq 0x15f90
jmp 0x1794e
jmp 0x174f0
movq 0x10(%rsp), %rax
movq 0x18b8(%rax), %rax
cmpl $0x100, 0x408(%rax)     # imm = 0x100
jl 0x17542
movq 0x1bae9(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x12c37(%rip), %rsi     # 0x2a150
leaq 0x13d04(%rip), %rdx     # 0x2b224
leaq 0x13d1e(%rip), %rcx     # 0x2b245
leaq 0x13aa9(%rip), %r8      # 0x2afd7
movl $0xa60, %r9d            # imm = 0xA60
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x17544
movq 0x10(%rsp), %rdi
callq 0x16110
movq 0x10(%rsp), %rdi
movq 0x10(%rsp), %rax
movq 0x18b8(%rax), %rax
movl 0x418(%rax), %esi
addl $0x1, %esi
callq 0x17a00
movq 0x10(%rsp), %rdi
movl $0x2b, %esi
callq 0x16650
movq 0x10(%rsp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq 0x16690
movl %eax, 0x8(%rsp)
movl 0x8(%rsp), %edx
movq 0x10(%rsp), %rax
movq 0x18b8(%rax), %rax
movq 0x10(%rsp), %rcx
movq 0x18b8(%rcx), %rsi
movl 0x408(%rsi), %ecx
movl %ecx, %edi
addl $0x1, %edi
movl %edi, 0x408(%rsi)
movslq %ecx, %rcx
movl %edx, 0x8(%rax,%rcx,4)
jmp 0x178dc
movq 0x10(%rsp), %rdi
movl $0x45, %esi
callq 0x15f50
testb $0x1, %al
jne 0x175dd
jmp 0x1763c
movq 0x10(%rsp), %rax
cmpq $0x0, 0x18b8(%rax)
jne 0x17604
movq 0x10(%rsp), %rdi
leaq 0x13c5e(%rip), %rsi     # 0x2b256
movb $0x0, %al
callq 0x15f90
jmp 0x1794e
movq 0x10(%rsp), %rdi
callq 0x16110
movq 0x10(%rsp), %rdi
movq 0x10(%rsp), %rax
movq 0x18b8(%rax), %rax
movl 0x418(%rax), %esi
addl $0x1, %esi
callq 0x17a00
movq 0x10(%rsp), %rdi
callq 0x17ae0
jmp 0x178da
movq 0x10(%rsp), %rdi
movl $0x46, %esi
callq 0x15f50
testb $0x1, %al
jne 0x17654
jmp 0x17826
movq 0x10(%rsp), %rax
cmpl $-0x1, 0xa0(%rax)
jne 0x1767a
movq 0x10(%rsp), %rdi
leaq 0x13c0e(%rip), %rsi     # 0x2b27c
movb $0x0, %al
callq 0x15f90
jmp 0x1794e
movq 0x10(%rsp), %rdi
callq 0x17b40
testb $0x1, %al
jne 0x1768a
jmp 0x176ad
movq 0x10(%rsp), %rdi
movl $0x1, %esi
callq 0x16650
movq 0x10(%rsp), %rdi
movl $0x2f, %esi
callq 0x16650
jmp 0x17821
movq 0x10(%rsp), %rdi
callq 0x17be0
movq 0x10(%rsp), %rax
cmpq $0x0, 0x98(%rax)
je 0x17808
movq 0x10(%rsp), %rax
movq 0x98(%rax), %rax
testb $0x1, (%rax)
jne 0x17808
movq 0x10(%rsp), %rax
testb $0x1, 0x38ce(%rax)
je 0x17806
jmp 0x176f3
movq 0x10(%rsp), %rax
movq 0x18c0(%rax), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
cmpl $0x2, 0x8(%rax)
jae 0x17747
movq 0x1b8e4(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x12a32(%rip), %rsi     # 0x2a150
leaq 0x12b3f(%rip), %rdx     # 0x2a264
leaq 0x13b19(%rip), %rcx     # 0x2b245
leaq 0x138a4(%rip), %r8      # 0x2afd7
movl $0xa86, %r9d            # imm = 0xA86
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x17749
jmp 0x1774b
movq 0x10(%rsp), %rax
movq 0x18c0(%rax), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movq (%rax), %rax
movq 0x10(%rsp), %rcx
movq 0x18c0(%rcx), %rcx
movq 0x8(%rcx), %rcx
movq 0x38(%rcx), %rcx
movl 0x8(%rcx), %ecx
subl $0x2, %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %eax
cmpl $0x27, %eax
je 0x177c1
movq 0x1b86a(%rip), %rax     # 0x32ff8
movq (%rax), %rdi
leaq 0x129b8(%rip), %rsi     # 0x2a150
leaq 0x12ac5(%rip), %rdx     # 0x2a264
leaq 0x13a9f(%rip), %rcx     # 0x2b245
leaq 0x1382a(%rip), %r8      # 0x2afd7
movl $0xa87, %r9d            # imm = 0xA87
movb $0x0, %al
callq 0x2240
ud2
callq 0x2040
jmp 0x177c3
movq 0x10(%rsp), %rax
movq 0x18c0(%rax), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movq (%rax), %rax
movq 0x10(%rsp), %rcx
movq 0x18c0(%rcx), %rcx
movq 0x8(%rcx), %rcx
movq 0x38(%rcx), %rcx
movl 0x8(%rcx), %ecx
subl $0x2, %ecx
movl %ecx, %ecx
movb $0x28, (%rax,%rcx)
movq 0x10(%rsp), %rax
movb $0x0, 0x38ce(%rax)
jmp 0x17808
movq 0x10(%rsp), %rdi
callq 0x16110
movq 0x10(%rsp), %rdi
movl $0x2f, %esi
callq 0x16650
jmp 0x178d8
movq 0x10(%rsp), %rdi
movl $0x41, %esi
callq 0x15f50
testb $0x1, %al
jne 0x1783b
jmp 0x1784c
movq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x17c00
jmp 0x178d6
movq 0x10(%rsp), %rdi
movl $0x3f, %esi
callq 0x15f50
testb $0x1, %al
jne 0x17861
jmp 0x1786d
movq 0x10(%rsp), %rdi
callq 0x17d70
jmp 0x178d4
movq 0x10(%rsp), %rdi
movl $0x40, %esi
callq 0x15f50
testb $0x1, %al
jne 0x17882
jmp 0x1788e
movq 0x10(%rsp), %rdi
callq 0x17ef0
jmp 0x178d2
movq 0x10(%rsp), %rax
movb $0x0, 0x38cc(%rax)
movq 0x10(%rsp), %rdi
callq 0x17be0
movq 0x10(%rsp), %rdi
callq 0x16110
movb $0x1, 0xe(%rsp)
movq 0x10(%rsp), %rax
testb $0x1, 0x38cc(%rax)
jne 0x178c6
movb $0x1, 0xf(%rsp)
movq 0x10(%rsp), %rax
movb $0x0, 0x38cc(%rax)
jmp 0x178d4
jmp 0x178d6
jmp 0x178d8
jmp 0x178da
jmp 0x178dc
movq 0x10(%rsp), %rax
cmpq $0x0, 0x98(%rax)
je 0x17938
movq 0x10(%rsp), %rax
movq 0x98(%rax), %rax
testb $0x1, 0x1(%rax)
je 0x17938
movq 0x10(%rsp), %rax
movq 0x18c0(%rax), %rax
movq 0x8(%rax), %rax
movq 0x10(%rsp), %rcx
movq 0x18b0(%rcx), %rcx
cmpq 0x80(%rcx), %rax
jne 0x17938
testb $0x1, 0xe(%rsp)
je 0x17938
movq 0x10(%rsp), %rdi
movl $0x4b, %esi
callq 0x16650
testb $0x1, 0xf(%rsp)
je 0x1794e
movq 0x10(%rsp), %rdi
movl $0x25, %esi
callq 0x16650
addq $0x18, %rsp
retq
nopw %cs:(%rax,%rax)