Войти
ФлеймФорумПроЭкты

Ü (Programmiersprache) (58 стр)

Страницы: 154 55 56 57 58 59 Следующая »
#855
19:24, 1 янв. 2021

Panzerschrek[CN]
> Имеет ли это какой-либо смысл?
Оптимизация пары (адрес массива + индекс), в горячих циклах может дать существенный прирост.

> Во-вторых: какой тип должен быть у разности указателей?
Заведи специальный, который внутри хранит разницу адресов, не деленную на sizeof(T).

> А может ну её, эту разность и она никому не нужна?
Лично мне в C++ не хватает разности (и соответствующей суммы) указателей разных типов.
Т. е. нужна типобезопасная замена reinterpret_cast хакам с offsetof:

struct S
{
    float a;
    int b;
    float c;
};

void test()
{
    S s, *ps = &s;
    float *pc = &s.c;
    float S::*mp = pc - ps;  // аналогов нет
    S *ps1 = pc - mp;        // аналогов нет
    float *pc1 = ps + mp;    // = &(ps->*mp)
    assert(ps1 == ps && pc1 == pc);
}
Нужно это если делать интрузивные контейнеры агрегацией, а не наследованием.

#856
(Правка: 20:55) 20:21, 1 янв. 2021
// версия с одними скобками, и особым значком "<--" вместо пропечатки "="

fn u32_to_str; // function ... number to text.
var.u32 x,    // локальный параметр хикс создаётся с 1-го аргумента.
// link r;   // линк result_str, как любой масив.
link.u8[ 64] r; // линк на внешний аргумент.
// После такого указания, компилятор обязан выдавать ошибку, если
// второй аргумент не опознался, как масив в 64 байта.

[
  var[ link.type] zero_char <-- 48;
  if x == 0;
  [
    r[ 0] <-- zero_char;
    r[ 1] <-- 0;
    return;
  ]

  var.u32 dst <-- 0;
  var.u32 div <-- 1000000000;

  while div > x; [ div /= 10;]

  while div >= 1;
  [
    var[ link.type] digit <-- x / div;
    r[ dst] <-- zero_char + digit; // 48 + 1 для пропечатки единицы
    x -= digit * div;
    div /= 10;
    dst += 1;
  ]
  r[ dst] <-- 0;
]
// call:
// var.u8[ 64] buf; u32_to_str[ 123, buf];
правка.. link.type имел ввиду "r.type" чтобы узнать типаж второго аргумента
#857
22:05, 1 янв. 2021

}:+()___ [Smile]
> разности (и соответствующей суммы) указателей разных типов
> нужна типобезопасная замена reinterpret_cast
Где тут типобезопасность?
Да и не вижу я проблем с reinterpret_cast-ами. Ну преобразовал в char* и посчитал разность, это вполне дозволено.

> Заведи специальный, который внутри хранит разницу адресов, не деленную на sizeof(T).
Дополнительная сущность в системе типов. Оно нам надо?

slatazan
В чём смысл переделки синтаксиса? Не уловил мысль.

#858
22:19, 1 янв. 2021

Panzerschrek[CN]
> Ну преобразовал в char* и посчитал разность, это вполне дозволено.
А вот я не уверен, что по стандарту можно вычитать указатели на разные объекты.
Там, вроде, даже выход за границу массива в процессе промежуточных вычислений — UB.

> Дополнительная сущность в системе типов. Оно нам надо?
Решать тебе. На мой взгляд, без лишнего деления более оптимально, плюс есть возможность работать с невыровненными парами объектов:

struct Vertex
{
    vec3 pos;
    int flags;
};

void process_pos(vec3 *pos, ptrdiff<vec3> step, int n)
{
    for(int i = 0; i < n; i++, pos += step) {...}
}

Vertex v[4];
process_pos(&v.pos, &v[1].pos - &v[0].pos, 4);
process_pos(&v.pos, sizeof(Vertex), 4);  // или даже так

#859
22:22, 1 янв. 2021

}:+()___ [Smile]
> можно вычитать указатели на разные объекты.
Можно, если они получены в результате одной аллокации (стековой или через new).

> ptrdiff<vec3>
Ага, и ещё шаблонность. Нафиг надо, проще сделать тупо разницу в знаковом типе с размером указателя.

Ещё есть вопрос в том, надо ли делить разницу на sizeof(element_type). По факту оно не сильно дорого, т. к. деление на константу заменяется умножением. А если разница тупо сравнивается с нулём, то и этого делать не надо.

#860
22:36, 1 янв. 2021

Panzerschrek[CN]
// В чём смысл "других значков"
Просто так. Вдруг тебе понравится :)

#861
12:43, 6 янв. 2021

Реализовал таки сырые указатели.
Что это включает:

  • Тип сырого указателя объявляется через $(element_type). Нету модификатора изменяемости указателя, как в C++, все сырые указатели считаются указывающими на изменяемые данные.
  • Есть оператор преобразования ссылки в указатель - $<(reference). Преобразовать в указатель можно только изменяемую ссылку, если нужно преобразовать в указатель неизменяемую ссылку, нужно позвать оператор cast_mut, который позволен только в unsafe блоке.
  • Есть оператор преобразования указателя в ссылку - $>(pointer). Позвать такой оператор можно только в unsafe блоке. Возвращаемая ссылка - изменяемая. К тому же с возвращаемой ссылкой не связан никакой узел графа проверки ссылок, так что все проверки для производных этой ссылки будут отключены.
  • Есть арифметика указателей. Позволено складывать указатель с целым числом, вычитать целое число, главное, чтобы размер числа был не более размера указателя. Есть +=, ++, -- для указателей. Есть разница указателей, она возвращает знаковый тип (i32 или i64), с размером, равным указателю. Разница не работает (компилятор порождает ошибку) для указателей на типы нулевого размера.
  • Сырые указатели совсем не позволены в constexpr вычислениях. Тип сырого указателя не является constexpr типом, а значит его нельзя использовать в сигнатуре или в теле constexpr функций и в типах, использующихся в constexpr функциях.
  • Для сырых указателей работает специализация шаблонных типов и функций, есть typeinfo для них, для них строится отладочная информация. Короче, как для любых других классов типов.
  • Что не реализовано, в сравнении с C++:

  • Нету изменяемости у указателей.
  • Нету оператора []. Вместо него надо будет писать $>(pointer + index).
  • Нету преобразований между типами указателей. Вместо них есть преобразования типов ссылок, так что если надо преобразовать тип указателя, это надо будет делать через преобразование в ссылку, преобразование типа, обратное преобразование в указатель.
  • Я уже переписал на использование сырых указателей стандартную библиотеку, выкинул самописный контейнер raw_ptr_mut, который внутри был реализован через целое число. Местами от этого код даже немного упростился. Ещё я малость поменял преобразователь заголовочных файлов Си, поддержал проброс указателей из Си в указатели Ü.

    Теперь я ещё на один шаг ближе к внедрению TBAA (type based alias analysis), т. к. теперь из кода выкинуты многочисленные int_to_ptr/ptr_to_int преобразования, которые могли ему мешать.

    #862
    12:46, 6 янв. 2021

    В процессе реализации сырых указателей опять ощутил масштаб языка. По ходу действия я много раз натыкался на то, что оказывается, надо ещё что-то поправить, чтобы нормально добавить новый класс типов - реализовать инициализаторы и функции копирования для сырых указателей, поддержать специализацию в шаблонах, не забыть о требовании полноты типа элемента при выполнении арифметики над указателями, не забыть о разнице между указателями на типы нулевого размера, не забыть кодирование типов указателей в именах символов, добавить поддержку указателей в отладочной информации и т. д.

    #863
    16:20, 17 янв. 2021

    Решил тут немного переделать тип void. Сейчас он очень поход на void из С++. Тип этот неполон, но разрешены неявные преобразования к нему.
    Сейчас я его решил переделать. Цель - чтобы можно было спокойно присвоить переменной результат вызова void функции и что-то с этим значением сделать. Дополнительно думаю открутить неявные преобразования ссылок в void, ибо нефиг.

    Что скажете на этот счёт? Здравые ли это идеи?

    #864
    16:25, 17 янв. 2021

    Panzerschrek[CN]
    > присвоить переменной результат вызова void функции и что-то с этим значением
    > сделать.
    А для чего это может быть полезно? Я что-то сам не придумаю так навскидку.

    #865
    16:43, 17 янв. 2021

    Vlad2001_MFS
    > А для чего это может быть полезно?
    В шаблонном коде полезно, чтобы не городить разную логику там, где может быть void или не void.

    #866
    (Правка: 19:33) 19:32, 17 янв. 2021

    Panzerschrek[CN]
    > Что скажете на этот счёт? Здравые ли это идеи?
    Если у тебя есть нормальная поддержка типов нулевого размера, то мастхев.
    В C++, кстати, есть ограниченная поддержка сабжа:

    void foo() {}
    void bar() { return foo(); }
    #867
    19:57, 17 янв. 2021

    }:+()___ [Smile]
    > нормальная поддержка типов нулевого размер
    Есть такое. В языке есть пустые кортежи и структуры, которые имеют нулевой размер.

    #868
    12:18, 18 янв. 2021

    Panzerschrek[CN]
    > В языке есть пустые кортежи и структуры, которые имеют нулевой размер.
    И их можно делать полями структуры брать на эти поля указатель и ничего не ломается?
    Или делать из них массив и итерирование не зависнет от того что указатель инкрементируется на ноль?

    #869
    (Правка: 12:35) 12:34, 18 янв. 2021

    kipar
    > И их можно делать полями структуры брать на эти поля указатель и ничего не ломается?
    > Или делать из них массив и итерирование не зависнет от того что указатель инкрементируется на ноль?
    Ничего не ломается. Брать указатель - это тупо выполнить инструкцию getelementptr. Этот указатель будет указывать куда-то, но читать по нему что-то будет нельзя (ибо размер нулевой).
    С итерированием история следующая: я специально реализовал шаблонный класс random_access_range, чтобы он хранил указатель + размер, а не пару указателей на начало и конец. В таком варианте всё работает нормально, итераций выходит сколько надо.

    Есть ещё разность указателей. Компилятор генерирует ошибку, если указываемый тип имеет нулевой размер.

    Страницы: 154 55 56 57 58 59 Следующая »
    ФлеймФорумПроЭкты