// File: /workspace/github_c_makefile_star2_O3/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 %rbx
subq $0x428, %rsp            # imm = 0x428
movq %rdi, %rbx
movb $0x0, 0x38ce(%rdi)
movl 0x50(%rdi), %eax
addl $-0x3f, %eax
cmpl $0x7, %eax
ja 0x11765
leaq 0xb793(%rip), %rcx      # 0x1cd74
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, %rdi
callq 0x10771
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movl 0x8(%rax), %eax
leaq 0x8(%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 0x11eb4
movq %rbx, %rdi
movl $0x2e, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq %rbx, %rdi
movl $0xff, %esi
callq 0x10fbe
movq %rbx, %rdi
movl $0xff, %esi
callq 0x10fbe
leal -0x1(%rax), %ebp
movq %rbx, %rdi
movl $0x1, %esi
callq 0x114e1
movq %rbx, %rdi
callq 0x11c93
movq %rbx, %rdi
movl %ebp, %esi
callq 0x11f33
movq 0x18b8(%rbx), %rax
cmpl $0x0, 0x408(%rax)
jle 0x116cc
xorl %r14d, %r14d
movl 0x8(%rax,%r14,4), %esi
movq %rbx, %rdi
callq 0x11f33
incq %r14
movq 0x18b8(%rbx), %rax
movslq 0x408(%rax), %rcx
cmpq %rcx, %r14
jl 0x116a9
movq 0x418(%rsp), %rax
movq %rax, 0x18b8(%rbx)
movq %rbx, %rdi
callq 0x11bcc
leaq 0xbaaa(%rip), %rdx      # 0x1d194
movq %rbx, %rdi
movl $0x35, %esi
callq 0x10df5
jmp 0x11a84
movq %rbx, %rdi
callq 0x10771
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11d3f
jmp 0x11b48
movq %rbx, %rdi
callq 0x10771
cmpl $-0x1, 0xa0(%rbx)
je 0x11a8d
movq %rbx, %rdi
callq 0x11cf3
movq %rbx, %rdi
movl $0x1, %esi
testb %al, %al
je 0x11abd
callq 0x10fbe
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq %rbx, %rdi
movl $0x2f, %esi
callq 0x10fbe
jmp 0x11b3e
movb $0x0, 0x38cc(%rbx)
movq %rbx, %rdi
movl $0x1, %esi
callq 0x11eb4
movq %rbx, %rdi
callq 0x11cf3
testb %al, %al
jne 0x11796
leaq 0xbdc9(%rip), %rsi      # 0x1d555
movq %rbx, %rdi
xorl %eax, %eax
callq 0x10d4f
movb 0x38cc(%rbx), %bpl
xorb $0x1, %bpl
movb $0x0, 0x38cc(%rbx)
xorl %eax, %eax
jmp 0x11b4a
movq %rbx, %rdi
callq 0x10771
incl 0xa0(%rbx)
leaq 0xba23(%rip), %rdx      # 0x1d1e7
movq %rbx, %rdi
movl $0x47, %esi
callq 0x10df5
movq 0x38(%rbx), %r14
movl 0x40(%rbx), %ebp
movl 0x44(%rbx), %r15d
leaq 0xba1f(%rip), %rdx      # 0x1d202
movq %rbx, %rdi
movl $0x37, %esi
callq 0x10df5
leaq 0xba2e(%rip), %rsi      # 0x1d225
movq %rbx, %rdi
movl $0x9, %edx
movl %r15d, %ecx
callq 0x11440
movq %rbx, %rdi
movl $0x1, %esi
callq 0x11eb4
leaq 0xba14(%rip), %rsi      # 0x1d22f
movq %rbx, %rdi
movl $0x9, %edx
movl %r15d, %ecx
callq 0x11440
movq %rbx, %rdi
movl $0x2, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq %rbx, %rdi
movq %r14, %rsi
movl %ebp, %edx
movl %r15d, %ecx
callq 0x11440
movq %rbx, %rdi
movl $0x1, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq %rbx, %rdi
movl $0x29, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rax
movl 0x8(%rax), %eax
leaq 0x8(%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 $0x2a, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq %rbx, %rdi
movl $0xff, %esi
callq 0x10fbe
movq %rbx, %rdi
movl $0xff, %esi
callq 0x10fbe
leal -0x1(%rax), %ebp
movq %rbx, %rdi
movl $0x1, %esi
callq 0x114e1
movq %rbx, %rdi
callq 0x11c93
movq %rbx, %rdi
movl %ebp, %esi
callq 0x11f33
movq 0x18b8(%rbx), %rax
cmpl $0x0, 0x408(%rax)
jle 0x1194d
xorl %r14d, %r14d
movl 0x8(%rax,%r14,4), %esi
movq %rbx, %rdi
callq 0x11f33
incq %r14
movq 0x18b8(%rbx), %rax
movslq 0x408(%rax), %rcx
cmpq %rcx, %r14
jl 0x1192a
movq 0x418(%rsp), %rax
movq %rax, 0x18b8(%rbx)
movq %rbx, %rdi
callq 0x11bcc
leaq 0xb829(%rip), %rdx      # 0x1d194
movq %rbx, %rdi
movl $0x35, %esi
callq 0x10df5
movq %rbx, %rdi
callq 0x11588
jmp 0x11a84
movq %rbx, %rdi
callq 0x10771
movq 0x18b8(%rbx), %rax
testq %rax, %rax
je 0x11a96
cmpl $0x100, 0x408(%rax)     # imm = 0x100
jge 0x11bbd
movq %rbx, %rdi
callq 0x11cf3
testb %al, %al
jne 0x119ca
leaq 0xbb95(%rip), %rsi      # 0x1d555
movq %rbx, %rdi
xorl %eax, %eax
callq 0x10d4f
movq 0x18b8(%rbx), %rax
movl 0x418(%rax), %esi
incl %esi
movq %rbx, %rdi
callq 0x11c20
movq %rbx, %rdi
movl $0x2b, %esi
callq 0x10fbe
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movq %rbx, %rdi
movl $0xff, %esi
callq 0x10fbe
movq %rbx, %rdi
movl $0xff, %esi
callq 0x10fbe
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 0x11b48
movq %rbx, %rdi
callq 0x10771
cmpq $0x0, 0x18b8(%rbx)
je 0x11a9f
movq %rbx, %rdi
callq 0x11cf3
testb %al, %al
jne 0x11a65
leaq 0xbafa(%rip), %rsi      # 0x1d555
movq %rbx, %rdi
xorl %eax, %eax
callq 0x10d4f
movq 0x18b8(%rbx), %rax
movl 0x418(%rax), %esi
incl %esi
movq %rbx, %rdi
callq 0x11c20
movq %rbx, %rdi
callq 0x11c93
movb $0x1, %al
xorl %ebp, %ebp
jmp 0x11b4a
leaq 0xb694(%rip), %rsi      # 0x1d128
jmp 0x11aa6
leaq 0xb610(%rip), %rsi      # 0x1d0ad
jmp 0x11aa6
leaq 0xb65c(%rip), %rsi      # 0x1d102
movq %rbx, %rdi
xorl %eax, %eax
addq $0x428, %rsp            # imm = 0x428
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x10d4f
callq 0x11eb4
movq 0x98(%rbx), %rax
testq %rax, %rax
je 0x11b12
cmpb $0x0, (%rax)
jne 0x11b12
cmpb $0x1, 0x38ce(%rbx)
jne 0x11b12
movq 0x18c0(%rbx), %rax
movq 0x8(%rax), %rax
movq 0x38(%rax), %rcx
movl 0x8(%rcx), %eax
cmpl $0x1, %eax
jbe 0x11bc2
movq (%rcx), %rcx
addl $-0x2, %eax
cmpb $0x27, (%rcx,%rax)
jne 0x11bc7
movb $0x28, (%rcx,%rax)
movb $0x0, 0x38ce(%rbx)
movq %rbx, %rdi
callq 0x11cf3
testb %al, %al
jne 0x11b2f
leaq 0xba30(%rip), %rsi      # 0x1d555
movq %rbx, %rdi
xorl %eax, %eax
callq 0x10d4f
movq %rbx, %rdi
movl $0x2f, %esi
callq 0x10fbe
xorl %ebp, %ebp
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
movb $0x1, %al
movq 0x98(%rbx), %rcx
testq %rcx, %rcx
je 0x11b93
cmpb $0x1, 0x1(%rcx)
jne 0x11b93
movq 0x18b0(%rbx), %rcx
movq 0x18c0(%rbx), %rdx
movq 0x8(%rdx), %rdx
cmpq 0x80(%rcx), %rdx
setne %cl
orb %cl, %al
jne 0x11b93
movq %rbx, %rdi
movl $0x4b, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
testb %bpl, %bpl
je 0x11baf
movq %rbx, %rdi
movl $0x25, %esi
callq 0x10fbe
movq %rbx, %rdi
xorl %esi, %esi
callq 0x11014
addq $0x428, %rsp            # imm = 0x428
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
callq 0x4d8b
callq 0x4d1f
callq 0x4d55