// File: /workspace/github_c_makefile_star2_O1/atomlang[P]atomlang/src/pk_core.c
// Function: varSetAttrib
void varSetAttrib(PKVM* vm, Var on, String* attrib, Var value) {

#define ATTRIB_IMMUTABLE(name)                                                \
do {                                                                          \
  if ((attrib->length == strlen(name) && strcmp(name, attrib->data) == 0)) {  \
    VM_SET_ERROR(vm, stringFormat(vm, "'$' attribute is immutable.", name));  \
    return;                                                                   \
  }                                                                           \
} while (false)

  if (!IS_OBJ(on)) {
    VM_SET_ERROR(vm, stringFormat(vm, "$ type is not subscriptable.",
                                  varTypeName(on)));
    return;
  }

  Object* obj = AS_OBJ(on);
  switch (obj->type) {
    case OBJ_STRING:
      ATTRIB_IMMUTABLE("length");
      ATTRIB_IMMUTABLE("lower");
      ATTRIB_IMMUTABLE("upper");
      ATTRIB_IMMUTABLE("strip");
      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_LIST:
      ATTRIB_IMMUTABLE("length");
      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_MAP:
      // Not sure should I allow string values could be accessed with
      // this way. ex:
      // map = { "foo" : 42, "can't access" : 32 }
      // map.foo = 'bar'
      TODO;

      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_RANGE:
      ATTRIB_IMMUTABLE("as_list");
      ATTRIB_IMMUTABLE("first");
      ATTRIB_IMMUTABLE("last");
      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_SCRIPT: {
      Script* scr = (Script*)obj;

      // Check globals.
      int index = scriptGetGlobals(scr, attrib->data, attrib->length);
      if (index != -1) {
        ASSERT_INDEX((uint32_t)index, scr->globals.count);
        scr->globals.data[index] = value;
        return;
      }

      // Check function (Functions are immutable).
      index = scriptGetFunc(scr, attrib->data, attrib->length);
      if (index != -1) {
        ASSERT_INDEX((uint32_t)index, scr->functions.count);
        ATTRIB_IMMUTABLE(scr->functions.data[index]->name);
        return;
      }

      index = scriptGetClass(scr, attrib->data, attrib->length);
      if (index != -1) {
        ASSERT_INDEX((uint32_t)index, scr->classes.count);
        ASSERT_INDEX(scr->classes.data[index]->name, scr->names.count);
        String* name = scr->names.data[scr->classes.data[index]->name];
        ATTRIB_IMMUTABLE(name->data);
        return;
      }

      ERR_NO_ATTRIB(vm, on, attrib);
      return;
    }

    case OBJ_FUNC:
      ATTRIB_IMMUTABLE("arity");
      ATTRIB_IMMUTABLE("name");
      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_FIBER:
      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_CLASS:
      ERR_NO_ATTRIB(vm, on, attrib);
      return;

    case OBJ_INST:
    {
      if (!instSetAttrib(vm, (Instance*)obj, attrib, value)) {
        // If we has error by now, that means the set value type is
        // incompatible. No need for us to set an other error, just return.
        if (VM_HAS_ERROR(vm)) return;
        ERR_NO_ATTRIB(vm, on, attrib);
      }

      // If we reached here, that means the attribute exists and we have
      // updated the value.
      return;
    }

    default:
      UNREACHABLE();
  }
  UNREACHABLE();

#undef ATTRIB_IMMUTABLE
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rax
shrq $0x32, %rax
cmpl $0x3ffe, %eax           # imm = 0x3FFE
jbe 0x188f6
movabsq $0xffffffffffff, %r13   # imm = 0xFFFFFFFFFFFF
andq %r15, %r13
movl (%r13), %eax
cmpq $0x8, %rax
ja 0x18d89
movq %rcx, %rbp
movq %rdx, %r14
leaq 0x602b(%rip), %rcx      # 0x1e888
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x14(%r14), %ebp
cmpl $0x6, %ebp
jne 0x18887
leaq 0x1c(%r14), %rsi
leaq 0x66f0(%rip), %rdi      # 0x1ef6a
callq 0x2230
testl %eax, %eax
je 0x18b66
cmpl $0x5, %ebp
jne 0x188df
leaq 0x1c(%r14), %r12
leaq 0x66f6(%rip), %rdi      # 0x1ef8d
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x18bc3
cmpl $0x5, %ebp
jne 0x188df
leaq 0x66e0(%rip), %rdi      # 0x1ef93
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x18d39
cmpl $0x5, %ebp
jne 0x188df
leaq 0x66ca(%rip), %rdi      # 0x1ef99
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x18d5b
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18ab5
callq 0x7591
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18d7f
movq %r15, %rdi
callq 0xaa1a
leaq 0x6603(%rip), %rsi      # 0x1ef1a
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x95d0
jmp 0x18ad8
movl 0x14(%r14), %ebp
cmpl $0x4, %ebp
je 0x18954
cmpl $0x5, %ebp
jne 0x1896c
leaq 0x1c(%r14), %rsi
leaq 0x6670(%rip), %rdi      # 0x1efb2
callq 0x2230
testl %eax, %eax
je 0x18c9e
cmpl $0x4, %ebp
jne 0x1896c
leaq 0x1c(%r14), %rsi
leaq 0x61eb(%rip), %rdi      # 0x1eb4a
callq 0x2230
testl %eax, %eax
je 0x18b9e
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18ab5
callq 0x7267
cmpl $0x6, 0x14(%r14)
jne 0x189a2
leaq 0x1c(%r14), %rsi
leaq 0x65d5(%rip), %rdi      # 0x1ef6a
callq 0x2230
testl %eax, %eax
je 0x18b79
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18ab5
callq 0x7525
leaq 0x1c(%r14), %r12
movl 0x14(%r14), %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0xa5d9
cmpl $-0x1, %eax
je 0x18af2
cmpl 0x28(%r13), %eax
jae 0x18d93
movq 0x20(%r13), %rcx
cltq
movq %rbp, (%rcx,%rax,8)
jmp 0x18ae3
movl 0x14(%r14), %ebp
cmpl $0x4, %ebp
je 0x18a40
cmpl $0x5, %ebp
je 0x18a23
cmpl $0x7, %ebp
jne 0x18a58
leaq 0x1c(%r14), %rsi
leaq 0x6593(%rip), %rdi      # 0x1ef9f
callq 0x2230
testl %eax, %eax
je 0x18ce8
cmpl $0x4, %ebp
je 0x18a40
cmpl $0x5, %ebp
jne 0x18a58
leaq 0x1c(%r14), %rsi
leaq 0x6579(%rip), %rdi      # 0x1efa7
callq 0x2230
testl %eax, %eax
je 0x18cc3
cmpl $0x4, %ebp
jne 0x18a58
leaq 0x1c(%r14), %rsi
leaq 0x6562(%rip), %rdi      # 0x1efad
callq 0x2230
testl %eax, %eax
je 0x18be8
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18ab5
callq 0x74b9
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
movq %rbp, %rcx
callq 0xa8a6
testb %al, %al
jne 0x18ae3
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18ae3
jmp 0x18ab5
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18ab5
callq 0x71c5
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18d8e
movq %r15, %rdi
callq 0xaa1a
addq $0x1c, %r14
leaq 0x646f(%rip), %rsi      # 0x1ef37
movq %rbx, %rdi
movq %rax, %rdx
movq %r14, %rcx
xorl %eax, %eax
callq 0x95d0
movq 0x5f0(%rbx), %rcx
movq %rax, 0x58(%rcx)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl 0x14(%r14), %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0xa54c
cmpl $-0x1, %eax
je 0x18c0d
cmpl 0x48(%r13), %eax
jae 0x18d98
movl 0x14(%r14), %r15d
movq 0x40(%r13), %rcx
cltq
movq (%rcx,%rax,8), %rax
movq 0x10(%rax), %r14
movq %r14, %rdi
callq 0x2140
cmpq %r15, %rax
jne 0x18ae3
movq %r14, %rdi
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
jne 0x18ae3
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dd4
leaq 0x6416(%rip), %rsi      # 0x1ef71
movq %rbx, %rdi
movq %r14, %rdx
jmp 0x1891d
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18b8b
callq 0x7669
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18d9d
leaq 0x63df(%rip), %rsi      # 0x1ef71
leaq 0x63d1(%rip), %rdx      # 0x1ef6a
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18da2
leaq 0x63ba(%rip), %rsi      # 0x1ef71
leaq 0x5f8c(%rip), %rdx      # 0x1eb4a
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18da7
leaq 0x6395(%rip), %rsi      # 0x1ef71
leaq 0x63aa(%rip), %rdx      # 0x1ef8d
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dac
leaq 0x6370(%rip), %rsi      # 0x1ef71
leaq 0x63a5(%rip), %rdx      # 0x1efad
jmp 0x18d77
movl 0x14(%r14), %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0xa4a4
cmpl $-0x1, %eax
je 0x18d0a
cmpl 0x58(%r13), %eax
jae 0x18dc0
movq 0x50(%r13), %rcx
cltq
movq (%rcx,%rax,8), %rax
movl 0x18(%rax), %eax
cmpl 0x68(%r13), %eax
jae 0x18dc5
movq 0x60(%r13), %rcx
movq (%rcx,%rax,8), %r15
movl 0x14(%r14), %r14d
addq $0x1c, %r15
movq %r15, %rdi
callq 0x2140
cmpq %r14, %rax
jne 0x18ae3
movq %r15, %rdi
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
jne 0x18ae3
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dd9
leaq 0x62de(%rip), %rsi      # 0x1ef71
movq %rbx, %rdi
movq %r15, %rdx
jmp 0x1891d
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18db1
leaq 0x62ba(%rip), %rsi      # 0x1ef71
leaq 0x62f4(%rip), %rdx      # 0x1efb2
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18db6
leaq 0x6295(%rip), %rsi      # 0x1ef71
leaq 0x62c4(%rip), %rdx      # 0x1efa7
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dbb
leaq 0x6270(%rip), %rsi      # 0x1ef71
leaq 0x6297(%rip), %rdx      # 0x1ef9f
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dca
movq %r15, %rdi
callq 0xaa1a
leaq 0x620c(%rip), %rsi      # 0x1ef37
movq %rbx, %rdi
movq %rax, %rdx
movq %r12, %rcx
jmp 0x18ad1
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dcf
leaq 0x621f(%rip), %rsi      # 0x1ef71
leaq 0x623a(%rip), %rdx      # 0x1ef93
jmp 0x18d77
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18dde
leaq 0x6201(%rip), %rsi      # 0x1ef71
leaq 0x6222(%rip), %rdx      # 0x1ef99
movq %rbx, %rdi
jmp 0x1891d
callq 0x7159
callq 0x74ef
callq 0x769f
callq 0x718f
callq 0x729d
callq 0x72d3
callq 0x755b
callq 0x71fb
callq 0x7633
callq 0x7417
callq 0x7231
callq 0x744d
callq 0x7483
callq 0x733f
callq 0x7375
callq 0x73e1
callq 0x75fd
callq 0x7309
callq 0x73ab
callq 0x75c7