// File: /workspace/github_c_makefile_star2_O3/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 0x17ce1
movabsq $0xffffffffffff, %r13   # imm = 0xFFFFFFFFFFFF
andq %r15, %r13
movl (%r13), %eax
cmpq $0x8, %rax
ja 0x181d4
movq %rcx, %rbp
movq %rdx, %r14
leaq 0x5c35(%rip), %rcx      # 0x1d8c8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl 0x14(%r14), %eax
cmpl $0x5, %eax
je 0x17f37
cmpl $0x6, %eax
jne 0x17f80
leaq 0x1c(%r14), %rsi
leaq 0x62ed(%rip), %rdi      # 0x1dfaa
callq 0x2230
testl %eax, %eax
jne 0x17f80
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x18045
callq 0x75fd
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181ca
movq %r15, %rdi
callq 0xa89c
leaq 0x6258(%rip), %rsi      # 0x1df5a
movq %rbx, %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x94f4
jmp 0x18019
movl 0x14(%r14), %eax
cmpl $0x4, %eax
je 0x17f08
cmpl $0x5, %eax
jne 0x17f20
leaq 0x1c(%r14), %rsi
leaq 0x62bd(%rip), %rdi      # 0x1dff2
callq 0x2230
testl %eax, %eax
jne 0x17f20
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181ed
leaq 0x6256(%rip), %rsi      # 0x1dfb1
leaq 0x6290(%rip), %rdx      # 0x1dff2
jmp 0x181c2
cmpl $0x6, 0x14(%r14)
jne 0x17d86
leaq 0x1c(%r14), %rsi
leaq 0x6231(%rip), %rdi      # 0x1dfaa
callq 0x2230
testl %eax, %eax
je 0x18033
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff6
callq 0x74ef
leaq 0x1c(%r14), %r12
movl 0x14(%r14), %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0xa47b
cmpl $-0x1, %eax
je 0x17e8c
cmpl 0x28(%r13), %eax
jae 0x181de
movq 0x20(%r13), %rcx
cltq
movq %rbp, (%rcx,%rax,8)
jmp 0x18024
movl 0x14(%r14), %eax
cmpl $0x4, %eax
je 0x17fcc
cmpl $0x5, %eax
je 0x17f93
cmpl $0x7, %eax
jne 0x17fe4
leaq 0x1c(%r14), %rsi
leaq 0x61e3(%rip), %rdi      # 0x1dfdf
callq 0x2230
testl %eax, %eax
jne 0x17fe4
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18206
leaq 0x618f(%rip), %rsi      # 0x1dfb1
leaq 0x61b6(%rip), %rdx      # 0x1dfdf
jmp 0x181c2
movq %rbx, %rdi
movq %r13, %rsi
movq %r14, %rdx
movq %rbp, %rcx
callq 0xa72b
testb %al, %al
jne 0x18024
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18024
jmp 0x17ff6
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff6
callq 0x718f
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff6
callq 0x7159
movl 0x14(%r14), %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0xa40c
cmpl $-0x1, %eax
je 0x18058
cmpl 0x48(%r13), %eax
jae 0x181e3
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 0x18024
movq %r14, %rdi
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
jne 0x18024
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18224
leaq 0x60b4(%rip), %rsi      # 0x1dfb1
movq %rbx, %rdi
movq %r14, %rdx
jmp 0x17d08
leaq 0x1c(%r14), %rsi
leaq 0x5c77(%rip), %rdi      # 0x1db8a
callq 0x2230
testl %eax, %eax
je 0x180e9
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff6
callq 0x7231
leaq 0x1c(%r14), %r12
leaq 0x608b(%rip), %rdi      # 0x1dfcd
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x1810e
leaq 0x607a(%rip), %rdi      # 0x1dfd3
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x18155
leaq 0x6069(%rip), %rdi      # 0x1dfd9
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
je 0x181a6
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff6
callq 0x7633
leaq 0x1c(%r14), %rsi
leaq 0x6049(%rip), %rdi      # 0x1dfe7
callq 0x2230
testl %eax, %eax
jne 0x17fe4
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181fc
leaq 0x5ff1(%rip), %rsi      # 0x1dfb1
leaq 0x6020(%rip), %rdx      # 0x1dfe7
jmp 0x181c2
leaq 0x1c(%r14), %rsi
leaq 0x6016(%rip), %rdi      # 0x1dfed
callq 0x2230
testl %eax, %eax
je 0x18133
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181d9
movq %r15, %rdi
callq 0xa89c
addq $0x1c, %r14
leaq 0x5f6e(%rip), %rsi      # 0x1df77
movq %rbx, %rdi
movq %rax, %rdx
movq %r14, %rcx
xorl %eax, %eax
callq 0x94f4
movq 0x5f0(%rbx), %rcx
movq %rax, 0x58(%rcx)
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181e8
leaq 0x5f65(%rip), %rsi      # 0x1dfb1
leaq 0x5f57(%rip), %rdx      # 0x1dfaa
jmp 0x181c2
movl 0x14(%r14), %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0xa37e
cmpl $-0x1, %eax
je 0x18177
cmpl 0x58(%r13), %eax
jae 0x1820b
movq 0x50(%r13), %rcx
cltq
movq (%rcx,%rax,8), %rax
movl 0x18(%rax), %eax
cmpl 0x68(%r13), %eax
jae 0x18210
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 0x18024
movq %r15, %rdi
movq %r12, %rsi
callq 0x2230
testl %eax, %eax
jne 0x18024
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18229
leaq 0x5ed3(%rip), %rsi      # 0x1dfb1
movq %rbx, %rdi
movq %r15, %rdx
jmp 0x17d08
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181f2
leaq 0x5eaf(%rip), %rsi      # 0x1dfb1
leaq 0x5a81(%rip), %rdx      # 0x1db8a
jmp 0x181c2
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x181f7
leaq 0x5e8a(%rip), %rsi      # 0x1dfb1
leaq 0x5e9f(%rip), %rdx      # 0x1dfcd
jmp 0x181c2
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18201
leaq 0x5e65(%rip), %rsi      # 0x1dfb1
leaq 0x5e9a(%rip), %rdx      # 0x1dfed
jmp 0x181c2
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x18215
leaq 0x5e43(%rip), %rsi      # 0x1dfb1
leaq 0x5e5e(%rip), %rdx      # 0x1dfd3
jmp 0x181c2
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x1821a
movq %r15, %rdi
callq 0xa89c
leaq 0x5ddf(%rip), %rsi      # 0x1df77
movq %rbx, %rdi
movq %rax, %rdx
movq %r12, %rcx
jmp 0x18012
movq 0x5f0(%rbx), %rax
cmpq $0x0, 0x58(%rax)
jne 0x1821f
leaq 0x5df6(%rip), %rsi      # 0x1dfb1
leaq 0x5e17(%rip), %rdx      # 0x1dfd9
movq %rbx, %rdi
jmp 0x17d08
callq 0x7123
callq 0x74b9
callq 0x7669
callq 0x7483
callq 0x7267
callq 0x729d
callq 0x7525
callq 0x71fb
callq 0x71c5
callq 0x75c7
callq 0x7417
callq 0x73e1
callq 0x744d
callq 0x7309
callq 0x733f
callq 0x7591
callq 0x73ab
callq 0x755b
callq 0x72d3
callq 0x7375