// File: /workspace/github_c_makefile_star2_O1/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 %r14
pushq %rbx
subq $0x420, %rsp            # imm = 0x420
movq %rdi, %rbx
movb $0x0, 0x38ce(%rdi)
cmpl $0x44, 0x50(%rdi)
jne 0x11ae1
movq %rbx, %rdi
callq 0x10b76
movq 0x18b8(%rbx), %rax
testq %rax, %rax
je 0x11b99
cmpl $0x100, 0x408(%rax)     # imm = 0x100
jge 0x11e57
movq %rbx, %rdi
callq 0x11f83
testb %al, %al
jne 0x11a75
leaq 0xcaae(%rip), %rsi      # 0x1e519
movq %rbx, %rdi
xorl %eax, %eax
callq 0x110cb
movq 0x18b8(%rbx), %rax
movl 0x418(%rax), %esi
incl %esi
movq %rbx, %rdi
callq 0x11eb9
movq %rbx, %rdi
movl $0x2b, %esi
callq 0x1135b
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x113b1
movq %rbx, %rdi
movl $0xff, %esi
callq 0x1135b
movq %rbx, %rdi
movl $0xff, %esi
callq 0x1135b
decl %eax
movq 0x18b8(%rbx), %rcx
movslq 0x408(%rcx), %rdx
leal 0x1(%rdx), %esi
movl %esi, 0x408(%rcx)
movl %eax, 0x8(%rcx,%rdx,4)
jmp 0x11d91
cmpl $0x45, 0x50(%rbx)
jne 0x11b43
movq %rbx, %rdi
callq 0x10b76
cmpq $0x0, 0x18b8(%rbx)
je 0x11bc4
movq %rbx, %rdi
callq 0x11f83
testb %al, %al
jne 0x11b1a
leaq 0xca09(%rip), %rsi      # 0x1e519
movq %rbx, %rdi
xorl %eax, %eax
callq 0x110cb
movq 0x18b8(%rbx), %rax
movl 0x418(%rax), %esi
incl %esi
movq %rbx, %rdi
callq 0x11eb9
movq %rbx, %rdi
callq 0x11f23
movb $0x1, %r14b
xorl %ebp, %ebp
jmp 0x11d94
cmpl $0x46, 0x50(%rbx)
jne 0x11ba5
movq %rbx, %rdi
callq 0x10b76
cmpl $-0x1, 0xa0(%rbx)
je 0x11cea
movq %rbx, %rdi
callq 0x11f83
movq %rbx, %rdi
movl $0x1, %esi
testb %al, %al
je 0x11d06
callq 0x1135b
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x113b1
movq %rbx, %rdi
movl $0x2f, %esi
callq 0x1135b
jmp 0x11d87
leaq 0xc4d1(%rip), %rsi      # 0x1e071
jmp 0x11cf1
cmpl $0x41, 0x50(%rbx)
jne 0x11bd0
movq %rbx, %rdi
callq 0x10b76
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11fcf
jmp 0x11d91
leaq 0xc4fb(%rip), %rsi      # 0x1e0c6
jmp 0x11cf1
cmpl $0x3f, 0x50(%rbx)
jne 0x11e06
movq %rbx, %rdi
callq 0x10b76
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movl 0x8(%rax), %eax
movq %rsp, %rcx
movl %eax, (%rcx)
movl $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
movl $0x1, %esi
callq 0x12323
movq %rbx, %rdi
movl $0x2e, %esi
callq 0x1135b
movq %rbx, %rdi
xorl %esi, %esi
callq 0x113b1
movq %rbx, %rdi
movl $0xff, %esi
callq 0x1135b
movq %rbx, %rdi
movl $0xff, %esi
callq 0x1135b
leal -0x1(%rax), %ebp
movq %rbx, %rdi
movl $0x1, %esi
callq 0x11919
movq %rbx, %rdi
callq 0x11f23
movq %rbx, %rdi
movl %ebp, %esi
callq 0x123a2
movq 0x18b8(%rbx), %rax
cmpl $0x0, 0x408(%rax)
jle 0x11cba
xorl %r14d, %r14d
movl 0x8(%rax,%r14,4), %esi
movq %rbx, %rdi
callq 0x123a2
incq %r14
movq 0x18b8(%rbx), %rax
movslq 0x408(%rax), %rcx
cmpq %rcx, %r14
jl 0x11c97
movq 0x410(%rsp), %rax
movq %rax, 0x18b8(%rbx)
movq %rbx, %rdi
callq 0x11e66
leaq 0xc480(%rip), %rdx      # 0x1e158
movq %rbx, %rdi
movl $0x35, %esi
callq 0x11171
jmp 0x11b39
leaq 0xc3fb(%rip), %rsi      # 0x1e0ec
movq %rbx, %rdi
xorl %eax, %eax
addq $0x420, %rsp            # imm = 0x420
popq %rbx
popq %r14
popq %rbp
jmp 0x110cb
callq 0x12323
movq 0x98(%rbx), %rax
testq %rax, %rax
je 0x11d5b
cmpb $0x0, (%rax)
jne 0x11d5b
cmpb $0x1, 0x38ce(%rbx)
jne 0x11d5b
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl 0x8(%rcx), %eax
cmpl $0x1, %eax
jbe 0x11e5c
movq (%rcx), %rcx
addl $-0x2, %eax
cmpb $0x27, (%rcx,%rax)
jne 0x11e61
movb $0x28, (%rcx,%rax)
movb $0x0, 0x38ce(%rbx)
movq %rbx, %rdi
callq 0x11f83
testb %al, %al
jne 0x11d78
leaq 0xc7ab(%rip), %rsi      # 0x1e519
movq %rbx, %rdi
xorl %eax, %eax
callq 0x110cb
movq %rbx, %rdi
movl $0x2f, %esi
callq 0x1135b
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x113b1
movb $0x1, %r14b
movq 0x98(%rbx), %rax
testq %rax, %rax
je 0x11dde
cmpb $0x1, 0x1(%rax)
jne 0x11dde
movq 0x18b0(%rbx), %rax
movq 0x18c0(%rbx), %rcx
movq 0x8(%rcx), %rcx
cmpq 0x80(%rax), %rcx
setne %al
orb %al, %r14b
jne 0x11dde
movq %rbx, %rdi
movl $0x4b, %esi
callq 0x1135b
movq %rbx, %rdi
xorl %esi, %esi
callq 0x113b1
testb %bpl, %bpl
je 0x11dfa
movq %rbx, %rdi
movl $0x25, %esi
callq 0x1135b
movq %rbx, %rdi
xorl %esi, %esi
callq 0x113b1
addq $0x420, %rsp            # imm = 0x420
popq %rbx
popq %r14
popq %rbp
retq
cmpl $0x40, 0x50(%rbx)
jne 0x11e21
movq %rbx, %rdi
callq 0x10b76
movq %rbx, %rdi
callq 0x1213f
jmp 0x11b39
xorl %r14d, %r14d
movb %r14b, 0x38cc(%rbx)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x12323
movq %rbx, %rdi
callq 0x111b1
movb 0x38cc(%rbx), %bpl
xorb $0x1, %bpl
movb %r14b, 0x38cc(%rbx)
jmp 0x11d94
callq 0x4dc1
callq 0x4d55
callq 0x4d8b