Поправил ошибку в bc
Вчера часа проснулся около часа ночи, сна ни в одном глазу.
Бродил по коду
for (i = 0; i < f->autos.len; ++i)
{
// Get the auto.
BcAuto* aptr = bc_vec_item(&f->autos, i);
// If they match, barf.
if (BC_ERR(idx == aptr->idx && type == aptr->type))
{
const char* array = type == BC_TYPE_ARRAY ? "[]" : "";
bc_error(BC_ERR_PARSE_DUP_LOCAL, line, name, array);
}
}Посмотрел что тут происходит и заметил, что в перечислении, описывающем виды параметров,
define a(*t[], t[]) {}Подумал, что уже достаточно утомился, чтобы лечь спать,
Уже утром я прочитал сообщение по моему коммиту — автор bc попросил отформатировать код и написать небольшой тест. Я всё исправил и теперь ещё немного моего кода есть в этой прекрасной утилите!
Странности bc
Чем больше узнаёшь bc, тем больше в нём находишь странностей. Особенно меня поражают массивы.
Например, как вы думаете, чему равна длина массива, в который мы ещё ни разу не инициализировали? Правильно, единице. Почему? Да чёрт его знает, так в коде написано:
void
bc_array_init(BcVec* a, bool nums)
{
BC_SIG_ASSERT_LOCKED;
// Set the proper vector.
if (nums) bc_vec_init(a, sizeof(BcNum), BC_DTOR_NUM);
else bc_vec_init(a, sizeof(BcVec), BC_DTOR_VEC);
// We always want at least one item in the array.
bc_array_expand(a, 1);
}Или вот такой код:
define void f(*a[]) {
. = a[99]
}
f(b[]); length(b[])Чему будет равна длина массива b[]?
Правильный ответ — она будет равна ста. Потому что в функции, куда мы передали этот массив по ссылке, происходит чтение
// The bc spec says that if an element is accessed that does not
// exist, it should be preinitialized to 0. Well, if we access
// an element *way* out there, we have to preinitialize all
// elements between the current last element and the actual
// accessed element.
if (v->len <= idx)
{
BC_SIG_LOCK;
bc_array_expand(v, bc_vm_growSize(idx, 1));
BC_SIG_UNLOCK;
}Как только идёт обращение к несуществующему элементу массива, неважно, для чтения или записи, он получается значение «ноль».
В этих случаях я даже уже и не понимаю — баги это или нет. Вроде нет, но выглядит контринтуитивно.