Esempio n. 1
0
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++;
}
Esempio n. 2
0
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++;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}