void lily_list_shift(lily_vm_state *vm, uint16_t argc, uint16_t *code) { lily_value **vm_regs = vm->vm_regs; lily_list_val *list_val = vm_regs[code[1]]->value.list; lily_value *result_reg = vm_regs[code[0]]; if (list_val->num_values == 0) lily_raise(vm->raiser, lily_IndexError, "Shift on an empty list.\n"); lily_value *source = list_val->elems[0]; /* Do not use assign here: It will increase the refcount, and the element is no longer in the list. Instead, use move and pretend the value does not exist in the list any longer. */ lily_move(result_reg, source->value, source->flags); /* For now, free extra values instead of trying to keep reserves around. Not the best course of action, perhaps, but certainly the simplest. */ lily_free(list_val->elems[0]); if (list_val->num_values != 1) memmove(list_val->elems, list_val->elems + 1, (list_val->num_values - 1) * sizeof(lily_value *)); list_val->num_values--; list_val->extra_space++; }
void lily_list_delete_at(lily_vm_state *vm, uint16_t argc, uint16_t *code) { lily_value **vm_regs = vm->vm_regs; lily_list_val *list_val = vm_regs[code[1]]->value.list; int64_t pos = vm_regs[code[2]]->value.integer; if (list_val->num_values == 0) lily_raise(vm->raiser, lily_IndexError, "Cannot delete from an empty list.\n"); pos = get_relative_index(vm, list_val, pos); if (list_val->extra_space == 0) make_extra_space_in_list(list_val); lily_value *to_delete = list_val->elems[pos]; lily_deref(to_delete); lily_free(to_delete); /* Shove everything leftward hide the hole from erasing the value. */ if (pos != list_val->num_values) memmove(list_val->elems + pos, list_val->elems + pos + 1, (list_val->num_values - pos) * sizeof(lily_value *)); list_val->num_values--; list_val->extra_space++; }
static int64_t get_relative_index(lily_vm_state *vm, lily_list_val *list_val, int64_t pos) { if (pos < 0) { uint64_t unsigned_pos = -(int64_t)pos; if (unsigned_pos > list_val->num_values) lily_raise(vm->raiser, lily_IndexError, "Index %d is too small for list (minimum: %d)\n", pos, -(int64_t)list_val->num_values); pos = list_val->num_values - unsigned_pos; } else if (pos > list_val->num_values) lily_raise(vm->raiser, lily_IndexError, "Index %d is too large for list (maximum: %d)\n", pos, list_val->num_values); return pos; }
int lily_any_eq(lily_vm_state *vm, int *depth, lily_value *left, lily_value *right) { int ret; if (*depth == 100) lily_raise(vm->raiser, lily_RecursionError, "Infinite loop in comparison.\n"); lily_value *left_inner = left->value.any->inner_value; lily_value *right_inner = right->value.any->inner_value; if (left_inner->type == right_inner->type) { class_eq_func eq_func = left_inner->type->cls->eq_func; (*depth)++; ret = eq_func(vm, depth, left_inner, right_inner); (*depth)--; } else ret = 0; return ret; }
void lily_list_fill(lily_vm_state *vm, uint16_t argc, uint16_t *code) { lily_value **vm_regs = vm->vm_regs; int n = vm_regs[code[1]]->value.integer; if (n < 0) lily_raise(vm->raiser, lily_ValueError, "Repeat count must be >= 0 (%d given).\n", n); lily_value *to_repeat = vm_regs[code[2]]; lily_value *result = vm_regs[code[0]]; lily_list_val *lv = lily_new_list_val(); lily_move_list(result, lv); lily_tag_value(vm, result); lily_value **elems = lily_malloc(sizeof(lily_value *) * n); lv->elems = elems; int i; for (i = 0;i < n;i++) elems[i] = lily_copy_value(to_repeat); lv->num_values = n; }