// File: /workspace/github_c_makefile_star2_O2/atomlang[P]atomlang/src/pk_var.c
// Function: toStringInternal
static void _toStringInternal(PKVM* vm, const Var v, pkByteBuffer* buff,
                              OuterSequence* outer, bool repr) {
  ASSERT(outer == NULL || repr, OOPS);

  if (IS_NULL(v)) {
    pkByteBufferAddString(buff, vm, "null", 4);
    return;

  } else if (IS_BOOL(v)) {
    if (AS_BOOL(v)) pkByteBufferAddString(buff, vm, "true", 4);
    else pkByteBufferAddString(buff, vm, "false", 5);
    return;

  } else if (IS_NUM(v)) {
    double value = AS_NUM(v);

    if (isnan(value)) {
      pkByteBufferAddString(buff, vm, "nan", 3);

    } else if (isinf(value)) {
      if (value > 0.0) {
        pkByteBufferAddString(buff, vm, "+inf", 4);
      } else {
        pkByteBufferAddString(buff, vm, "-inf", 4);
      }

    } else {
      char num_buff[STR_DBL_BUFF_SIZE];
      int length = sprintf(num_buff, DOUBLE_FMT, AS_NUM(v));
      pkByteBufferAddString(buff, vm, num_buff, length);
    }

    return;

  } else if (IS_OBJ(v)) {

    const Object* obj = AS_OBJ(v);
    switch (obj->type) {

      case OBJ_STRING:
      {
        const String* str = (const String*)obj;
        if (outer == NULL && !repr) {
          pkByteBufferAddString(buff, vm, str->data, str->length);
          return;
        } else {
          // If recursive return with quotes (ex: [42, "hello", 0..10]).
          pkByteBufferWrite(buff, vm, '"');
          for (const char* c = str->data; *c != '\0'; c++) {
            switch (*c) {
              case '"': pkByteBufferAddString(buff, vm, "\\\"", 2); break;
              case '\\': pkByteBufferAddString(buff, vm, "\\\\", 2); break;
              case '\n': pkByteBufferAddString(buff, vm, "\\n", 2); break;
              case '\r': pkByteBufferAddString(buff, vm, "\\r", 2); break;
              case '\t': pkByteBufferAddString(buff, vm, "\\t", 2); break;

              default:
                pkByteBufferWrite(buff, vm, *c);
                break;
            }
          }
          pkByteBufferWrite(buff, vm, '"');
          return;
        }
        UNREACHABLE();
      }

      case OBJ_LIST:
      {
        const List* list = (const List*)obj;
        if (list->elements.count == 0) {
          pkByteBufferAddString(buff, vm, "[]", 2);
          return;
        }

        // Check if the list is recursive.
        OuterSequence* seq = outer;
        while (seq != NULL) {
          if (seq->is_list && seq->list == list) {
            pkByteBufferAddString(buff, vm, "[...]", 5);
            return;
          }
          seq = seq->outer;
        }
        OuterSequence seq_list;
        seq_list.outer = outer; seq_list.is_list = true; seq_list.list = list;

        pkByteBufferWrite(buff, vm, '[');
        for (uint32_t i = 0; i < list->elements.count; i++) {
          if (i != 0) pkByteBufferAddString(buff, vm, ", ", 2);
          _toStringInternal(vm, list->elements.data[i], buff, &seq_list, true);
        }
        pkByteBufferWrite(buff, vm, ']');
        return;
      }

      case OBJ_MAP:
      {
        const Map* map = (const Map*)obj;
        if (map->entries == NULL) {
          pkByteBufferAddString(buff, vm, "{}", 2);
          return;
        }

        // Check if the map is recursive.
        OuterSequence* seq = outer;
        while (seq != NULL) {
          if (!seq->is_list && seq->map == map) {
            pkByteBufferAddString(buff, vm, "{...}", 5);
            return;
          }
          seq = seq->outer;
        }
        OuterSequence seq_map;
        seq_map.outer = outer; seq_map.is_list = false; seq_map.map = map;

        pkByteBufferWrite(buff, vm, '{');
        uint32_t i = 0;     // Index of the current entry to iterate.
        bool _first = true; // For first element no ',' required.
        do {

          // Get the next valid key index.
          bool _done = false;
          while (IS_UNDEF(map->entries[i].key)) {
            if (++i >= map->capacity) {
              _done = true;
              break;
            }
          }
          if (_done) break;

          if (!_first) pkByteBufferAddString(buff, vm, ", ", 2);

          _toStringInternal(vm, map->entries[i].key, buff, &seq_map, true);
          pkByteBufferWrite(buff, vm, ':');
          _toStringInternal(vm, map->entries[i].value, buff, &seq_map, true);

          i++; _first = false;
        } while (i < map->capacity);

        pkByteBufferWrite(buff, vm, '}');
        return;
      }

      case OBJ_RANGE:
      {
        const Range* range = (const Range*)obj;

        char buff_from[STR_DBL_BUFF_SIZE];
        const int len_from = snprintf(buff_from, sizeof(buff_from),
                                      DOUBLE_FMT, range->from);
        char buff_to[STR_DBL_BUFF_SIZE];
        const int len_to = snprintf(buff_to, sizeof(buff_to),
                                    DOUBLE_FMT, range->to);

        pkByteBufferAddString(buff, vm, "[Range:", 7);
        pkByteBufferAddString(buff, vm, buff_from, len_from);
        pkByteBufferAddString(buff, vm, "..", 2);
        pkByteBufferAddString(buff, vm, buff_to, len_to);
        pkByteBufferWrite(buff, vm, ']');
        return;
      }

      case OBJ_SCRIPT: {
        const Script* scr = (const Script*)obj;
        pkByteBufferAddString(buff, vm, "[Module:", 8);
        if (scr->module != NULL) {
          pkByteBufferAddString(buff, vm, scr->module->data,
                              scr->module->length);
        } else {
          pkByteBufferWrite(buff, vm, '"');
          pkByteBufferAddString(buff, vm, scr->path->data, scr->path->length);
          pkByteBufferWrite(buff, vm, '"');
        }
        pkByteBufferWrite(buff, vm, ']');
        return;
      }

      case OBJ_FUNC: {
        const Function* fn = (const Function*)obj;
        pkByteBufferAddString(buff, vm, "[Func:", 6);
        pkByteBufferAddString(buff, vm, fn->name, (uint32_t)strlen(fn->name));
        pkByteBufferWrite(buff, vm, ']');
        return;
      }

      case OBJ_FIBER: {
        const Fiber* fb = (const Fiber*)obj;
        pkByteBufferAddString(buff, vm, "[Fiber:", 7);
        pkByteBufferAddString(buff, vm, fb->func->name,
                            (uint32_t)strlen(fb->func->name));
        pkByteBufferWrite(buff, vm, ']');
        return;
      }

      case OBJ_CLASS: {
        const Class* ty = (const Class*)obj;
        pkByteBufferAddString(buff, vm, "[Class:", 7);
        String* ty_name = ty->owner->names.data[ty->name];
        pkByteBufferAddString(buff, vm, ty_name->data, ty_name->length);
        pkByteBufferWrite(buff, vm, ']');
        return;
      }

      case OBJ_INST:
      {
        const Instance* inst = (const Instance*)obj;
        pkByteBufferWrite(buff, vm, '[');
        pkByteBufferAddString(buff, vm, inst->name,
                              (uint32_t)strlen(inst->name));
        pkByteBufferWrite(buff, vm, ':');

        if (!inst->is_native) {
          const Class* ty = inst->ins->type;
          const Inst* ins = inst->ins;
          ASSERT(ins->fields.count == ty->field_names.count, OOPS);

          for (uint32_t i = 0; i < ty->field_names.count; i++) {
            if (i != 0) pkByteBufferWrite(buff, vm, ',');

            pkByteBufferWrite(buff, vm, ' ');
            String* f_name = ty->owner->names.data[ty->field_names.data[i]];
            pkByteBufferAddString(buff, vm, f_name->data, f_name->length);
            pkByteBufferWrite(buff, vm, '=');
            _toStringInternal(vm, ins->fields.data[i], buff, outer, repr);
          }
        } else {

          char buff_addr[STR_HEX_BUFF_SIZE];
          char* ptr = (char*)buff_addr;
          (*ptr++) = '0'; (*ptr++) = 'x';
          const int len = snprintf(ptr, sizeof(buff_addr) - 2,
                                "%08x", (unsigned int)(uintptr_t)inst->native);
          pkByteBufferAddString(buff, vm, buff_addr, (uint32_t)len);
        }

        pkByteBufferWrite(buff, vm, ']');
        return;
      }
    }

  }
  UNREACHABLE();
  return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %r8d, %ebp
testq %rcx, %rcx
sete %al
orb %bpl, %al
je 0x5700
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
movabsq $0x7ffc000000000000, %rax # imm = 0x7FFC000000000000
cmpq %rax, %rsi
jne 0x50c6
leaq 0x13323(%rip), %rdx     # 0x183cd
pushq $0x4
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3056
movq %rcx, %r12
movabsq $0x7ffd000000000000, %r13 # imm = 0x7FFD000000000000
movq %r15, %rcx
andq $-0x2, %rcx
leaq 0x2(%r13), %rdx
cmpq %rdx, %rcx
jne 0x50f9
addq $0x3, %r13
cmpq %r13, %r15
jne 0x51fb
leaq 0x132db(%rip), %rdx     # 0x183d2
jmp 0x50aa
movq %r15, %rcx
notq %rcx
testq %rcx, %rax
jne 0x5209
movq %r15, %rax
shrq $0x32, %rax
cmpl $0x3fff, %eax           # imm = 0x3FFF
jb 0x5735
movabsq $0xffffffffffff, %rax   # imm = 0xFFFFFFFFFFFF
andq %rax, %r15
movl (%r15), %eax
cmpq $0x8, %rax
ja 0x5735
leaq 0x12f0d(%rip), %rcx     # 0x18048
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
testq %r12, %r12
setne %al
orb %bpl, %al
je 0x54da
pushq $0x22
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
addq $0x1c, %r15
pushq $0x2
popq %rbp
leaq 0x1327c(%rip), %r13     # 0x183eb
leaq 0x13278(%rip), %r12     # 0x183ee
movzbl (%r15), %eax
cmpl $0x9, %eax
je 0x51c5
cmpl $0xa, %eax
je 0x51df
cmpl $0xd, %eax
je 0x51ab
cmpl $0x22, %eax
je 0x51d4
cmpl $0x5c, %eax
je 0x51ba
testl %eax, %eax
je 0x54f0
movzbl %al, %edx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
jmp 0x51f3
movq %r14, %rdi
movq %rbx, %rsi
leaq 0x1323c(%rip), %rdx     # 0x183f4
jmp 0x51ec
movq %r14, %rdi
movq %rbx, %rsi
movq %r12, %rdx
jmp 0x51ec
movq %r14, %rdi
movq %rbx, %rsi
leaq 0x13225(%rip), %rdx     # 0x183f7
jmp 0x51ec
movq %r14, %rdi
movq %rbx, %rsi
movq %r13, %rdx
jmp 0x51ec
movq %r14, %rdi
movq %rbx, %rsi
leaq 0x13205(%rip), %rdx     # 0x183f1
movl %ebp, %ecx
callq 0x3056
incq %r15
jmp 0x5176
leaq 0x167b8(%rip), %rdx     # 0x1b9ba
pushq $0x5
jmp 0x50ac
movq %r15, %rdi
callq 0xab8f
ucomisd %xmm0, %xmm0
jp 0x5763
movq %xmm0, %rax
btrq $0x3f, %rax
movabsq $0x7ff0000000000000, %rcx # imm = 0x7FF0000000000000
cmpq %rcx, %rax
jne 0x524a
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x527b
leaq 0x13196(%rip), %rdx     # 0x183db
jmp 0x50aa
movq %r15, %rdi
callq 0xab8f
leaq 0x1318c(%rip), %rsi     # 0x183e5
movq %rsp, %r15
movq %r15, %rdi
movb $0x1, %al
callq 0x2360
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movl %eax, %ecx
callq 0x3056
jmp 0x5659
leaq 0x1315e(%rip), %rdx     # 0x183e0
jmp 0x50aa
leaq 0x13189(%rip), %rdx     # 0x18417
pushq $0x8
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq 0x10(%r15), %rdx
testq %rdx, %rdx
jne 0x53c4
pushq $0x22
popq %rbp
movq %r14, %rdi
movq %rbx, %rsi
movl %ebp, %edx
callq 0x2c3c
movq 0x18(%r15), %rdx
movl 0x14(%rdx), %ecx
addq $0x1c, %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq %r14, %rdi
movq %rbx, %rsi
movl %ebp, %edx
callq 0x2c3c
jmp 0x544f
cmpq $0x0, 0x18(%r15)
je 0x56d1
movq %r12, %rax
testq %rax, %rax
je 0x55a1
cmpb $0x0, 0x8(%rax)
jne 0x5308
cmpq %r15, 0x10(%rax)
je 0x56e8
movq (%rax), %rax
jmp 0x52ef
movsd 0x10(%r15), %xmm0
leaq 0x130cb(%rip), %r13     # 0x183e5
movq %rsp, %rdi
pushq $0x18
popq %rbp
movq %rbp, %rsi
movq %r13, %rdx
movb $0x1, %al
callq 0x2160
movl %eax, %r12d
movsd 0x18(%r15), %xmm0
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %rbp, %rsi
movq %r13, %rdx
movb $0x1, %al
callq 0x2160
movl %eax, %ebp
leaq 0x130bb(%rip), %rdx     # 0x1840f
pushq $0x7
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq %r14, %rdi
movq %rbx, %rsi
movq %rsp, %rdx
movl %r12d, %ecx
callq 0x3056
leaq 0x16155(%rip), %rdx     # 0x1b4cf
pushq $0x2
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movl %ebp, %ecx
callq 0x3056
pushq $0x5d
jmp 0x564d
leaq 0x13089(%rip), %rdx     # 0x1842f
pushq $0x7
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq 0x10(%r15), %rax
movq 0x60(%rax), %rax
movl 0x18(%r15), %ecx
movq (%rax,%rcx,8), %rdx
movl 0x14(%rdx), %ecx
addq $0x1c, %rdx
movq %r14, %rdi
movq %rbx, %rsi
jmp 0x544a
cmpl $0x0, 0x18(%r15)
je 0x56da
movq %r12, %rax
testq %rax, %rax
je 0x5668
cmpb $0x1, 0x8(%rax)
jne 0x53fa
cmpq %r15, 0x10(%rax)
je 0x56f4
movq (%rax), %rax
jmp 0x53e1
leaq 0x1301a(%rip), %rdx     # 0x18420
pushq $0x6
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq 0x10(%r15), %r15
jmp 0x5437
leaq 0x13006(%rip), %rdx     # 0x18427
pushq $0x7
popq %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq 0x18(%r15), %rax
movq 0x10(%rax), %r15
movq %r15, %rdi
callq 0x2140
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movl %eax, %ecx
callq 0x3056
pushq $0x5d
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2c3c
pushq $0x5b
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
movq 0x10(%r15), %r13
movq %r13, %rdi
callq 0x2140
movq %r14, %rdi
movq %rbx, %rsi
movq %r13, %rdx
movl %eax, %ecx
callq 0x3056
pushq $0x3a
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
cmpb $0x0, 0x18(%r15)
je 0x54f7
leaq 0x2(%rsp), %rdi
movw $0x7830, -0x2(%rdi)     # imm = 0x7830
movl 0x20(%r15), %ecx
leaq 0x12f77(%rip), %rdx     # 0x18437
pushq $0x12
popq %rsi
xorl %eax, %eax
callq 0x2160
movq %rsp, %rdx
movq %r14, %rdi
movq %rbx, %rsi
movl %eax, %ecx
jmp 0x544a
movl 0x14(%r15), %ecx
addq $0x1c, %r15
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
jmp 0x50b3
pushq $0x22
jmp 0x5451
movq 0x20(%r15), %rax
movq (%rax), %r13
movq %rax, 0x18(%rsp)
movl 0x10(%rax), %eax
cmpl 0x30(%r13), %eax
jne 0x5771
xorl %r15d, %r15d
movzbl %bpl, %ebp
movl %eax, %eax
cmpq %rax, %r15
jae 0x544f
testq %r15, %r15
je 0x5535
movq %r14, %rdi
movq %rbx, %rsi
pushq $0x2c
popq %rdx
callq 0x2c3c
movq %r14, %rdi
movq %rbx, %rsi
pushq $0x20
popq %rdx
callq 0x2c3c
movq 0x10(%r13), %rax
movq 0x28(%r13), %rcx
movq 0x60(%rax), %rax
movl (%rcx,%r15,4), %ecx
movq (%rax,%rcx,8), %rdx
movl 0x14(%rdx), %ecx
addq $0x1c, %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3056
movq %r14, %rdi
movq %rbx, %rsi
pushq $0x3d
popq %rdx
callq 0x2c3c
movq 0x18(%rsp), %rax
movq 0x8(%rax), %rax
movq (%rax,%r15,8), %rsi
movq %rbx, %rdi
movq %r14, %rdx
movq %r12, %rcx
movl %ebp, %r8d
callq 0x506b
incq %r15
movl 0x30(%r13), %eax
jmp 0x5517
movq %rsp, %rax
movq %r12, (%rax)
movb $0x0, 0x8(%rax)
movq %r15, 0x10(%rax)
pushq $0x7b
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
xorl %ebp, %ebp
movb $0x1, %al
movq 0x18(%r15), %rcx
movl %ebp, %ebp
movq %rbp, %r12
shlq $0x4, %r12
movq (%rcx,%r12), %rsi
cmpq %r13, %rsi
jne 0x55e1
incl %ebp
cmpl 0x10(%r15), %ebp
jb 0x55c5
jmp 0x564b
testb $0x1, %al
jne 0x5602
movq %r14, %rdi
movq %rbx, %rsi
leaq 0x12e11(%rip), %rdx     # 0x18403
pushq $0x2
popq %rcx
callq 0x3056
movq 0x18(%r15), %rax
movq (%rax,%r12), %rsi
movq %rbx, %rdi
movq %r14, %rdx
movq %rsp, %rcx
pushq $0x1
popq %r8
callq 0x506b
movq %r14, %rdi
movq %rbx, %rsi
pushq $0x3a
popq %rdx
callq 0x2c3c
movq 0x18(%r15), %rax
movq 0x8(%rax,%r12), %rsi
movq %rbx, %rdi
movq %r14, %rdx
movq %rsp, %rcx
pushq $0x1
popq %r8
callq 0x506b
incl %ebp
xorl %eax, %eax
cmpl 0x10(%r15), %ebp
jb 0x55c1
pushq $0x7d
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rsp, %r13
movq %r12, (%r13)
movb $0x1, 0x8(%r13)
movq %r15, 0x10(%r13)
pushq $0x5b
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x2c3c
xorl %r12d, %r12d
pushq $0x1
popq %rbp
movl 0x18(%r15), %eax
cmpq %rax, %r12
jae 0x5398
testq %r12, %r12
je 0x56b3
movq %r14, %rdi
movq %rbx, %rsi
leaq 0x12d58(%rip), %rdx     # 0x18403
pushq $0x2
popq %rcx
callq 0x3056
movq 0x10(%r15), %rax
movq (%rax,%r12,8), %rsi
movq %rbx, %rdi
movq %r14, %rdx
movq %r13, %rcx
movl %ebp, %r8d
callq 0x506b
incq %r12
jmp 0x568c
leaq 0x12d2e(%rip), %rdx     # 0x18406
jmp 0x56e1
leaq 0x12d19(%rip), %rdx     # 0x183fa
pushq $0x2
jmp 0x50ac
leaq 0x12d1a(%rip), %rdx     # 0x18409
jmp 0x5202
leaq 0x12d02(%rip), %rdx     # 0x183fd
jmp 0x5202
movq 0x1d8f1(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x129df(%rip), %rsi     # 0x180f0
leaq 0x12aec(%rip), %rdx     # 0x18204
leaq 0x12c9c(%rip), %rcx     # 0x183bb
leaq 0x12a16(%rip), %r8      # 0x1813c
movl $0x581, %r9d            # imm = 0x581
xorl %eax, %eax
callq 0x2250
ud2
movq 0x1d8bc(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x12a34(%rip), %rsi     # 0x1817a
leaq 0x12c6e(%rip), %rdx     # 0x183bb
leaq 0x129e8(%rip), %rcx     # 0x1813c
movl $0x671, %r8d            # imm = 0x671
xorl %eax, %eax
callq 0x2250
ud2
leaq 0x12c6d(%rip), %rdx     # 0x183d7
pushq $0x3
jmp 0x50ac
movq 0x1d880(%rip), %rax     # 0x22ff8
movq (%rax), %rdi
leaq 0x1296e(%rip), %rsi     # 0x180f0
leaq 0x12a7b(%rip), %rdx     # 0x18204
leaq 0x12c2b(%rip), %rcx     # 0x183bb
leaq 0x129a5(%rip), %r8      # 0x1813c
movl $0x656, %r9d            # imm = 0x656
jmp 0x572c