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

Ü (Programmiersprache) (33 стр)

Страницы: 132 33 34 3537 Следующая »
#480
(Правка: 22 июля 2019, 22:14) 16:50, 21 июля 2019

Panzerschrek[CN]
> случаях потребуется enable_if, чтобы шаблонные функции не инстнцировались для
> каких не надо аргументов.
предлагаю "хитрый но полноценный codegen" прикрутить так чтобы неиспользуемый но "как бы сгенереный код" вообще не генерировался, тоесть речь о реализации концепции "on demand" и "не плати затратами временем компиляции за то что попросил нагенерить, но затем использовать так и не стал" до такой степени чтобы можно было "как бы генерировать" бесконечное кол-во кода, но при этом чтобы всё быстро компилировалось. // на правах бреда.

upd:
ниже из уровня аргументации видно что термин "хитрый но полноценный codegen" был не понят, поэтому уточню:
это такая штука которая по идеи для пользователя должна не сильно отличаться от простого генерирования, по "алгоритму пользователя", строки_с_кодом для последующей компиляции, а компилятор должен умудриться быть настолько ленивым чтобы вообще ничего не делать пока это не будет где-то вызвано.

upd2:
хотя наверно шаблоны не дураки придумывали и возможно запрет на генерирование кода как строки - это чуть ли не один единственный вариант достичь баланса между "временем компиляции" и "сложность написания шаблонов", но это не точно.

#481
(Правка: 17:08) 17:06, 21 июля 2019

Adler
> не плати затратами временем компиляци
Да плевать, сколько оно там компилируется. C++ тормознуто компилируется, относительно других языков, но на это всем пофигу. Компилятор Ü может в 3-10 раз медленнее компилировать, и всё равно, не страшно будет.
Вообще, на больших проектах, всё упирается в доступ к диску и компоновку, а чё там в компиляторе тормозит - плевать.

> до такой степени чтобы можно было как бы генерировать бесконечное кол-во кода,
> но приэтом чтобы всё быстро компилировалось.
Ты или крестик сними, или трусы одень. Бесконечное количество кода будет генерироваться бесконечно долго. Так что, на практике, количество кода всегда конечно.

#482
14:31, 25 июля 2019

Реализовал разделяемые указатели
Теперь в Ü есть аналог shared_ptr из C++. Всего, пока что, реализованы 6 классов разделяемых указателей: shared_ptr_mut, shared_ptr_imut, shared_ptr_nullable_mut, shared_ptr_nullable_imut, weak_ptr_mut, weak_ptr_imut. mut-указатели можно преобразовать в imut, non-nullable можно преобразовать в nullable, все указатели можно преобразовать в weak и из weak можно получить nullable указатели.

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

Чтобы не возникало проблем с многопоточностью, реализован тег "shared" для классов и структур. Библиотечные классы разделяемых указателей помечены этим тегом. Данный тег наследуют все типы, содержащие в себе типы с этим тегом. Нужно это, чтобы запретить передавать в другой поток разделяемые данные, тем самым, создав возможность гонки.

Теперь предстоит добавить разделяемые указатели для многопоточного доступа. Но это будет позже.

#483
11:15, 26 июля 2019

Фичи всё нафичёвываются, а документация всё не документируется.

#484
14:15, 26 июля 2019

Sbtrn. Devil
> а документация всё не документируется.
Проблема в нехватке времени и соответствующих навыков. Писать документацию придётся долго, а не имея писательского таланта, я напишу её ещё очень длинной и непонятной.

Вообще, проект дорос до такой стадии, что в одиночку его тянуть тяжело. Надо привлекать энтузиастов.

#485
13:14, 29 июля 2019

С первой страницы:
> Некоторые особенности крестов я принципиально реализовывать не собираюсь, а
> именно:
> *) Указатели (как часть языка).

С этой страницы:
> Реализовал разделяемые указатели

#486
(Правка: 13:29) 13:29, 29 июля 2019

Cerber
Разделяемые указатели реализованы как классы стандартной библиотеки, а не как примитивы языка.
В нулевом посте же шла речь об указателях, как они есть в Си и C++.

#487
6:25, 8 авг. 2019

Реализовал преобразователь заголовочных файлов Си

Суть такова: утилита преобразует заголовочные файлы Си в файлы на языке Ü. Преобразуются протитипы функций, объявления структур, псевдонимы типов, объявление числовых и строковых констант через #define. Объединения выгружаются как структуры с данными-заглушками. Перечисления вытаскиваются или как пространство имён + псевдоним типа, или, если это возможно, как перечисление Ü.
Пример:

+ вход
+ выход

Но, пока что с утилитой есть ряд проблем:

  • Отсутствие указателей в Ü. В аргументах функций и возвращаемом значении, в структурах указатели заменяются ссылками, в остальных случаях указатели заменяются на size_type.
  • Пока что глючат конструкции, вроде typedef struct X{} X;
  • Более сложные объявления констант через #define не работают
  • Есть проблемы с структурами с ссылками внутри. В Ü есть ряд ограничений на это, поэтому преобразованные из Си структуры могут не быть правильными
  • С C++ всё плохо, и не понятно, возможно ли хоть как то преобразовывать C++ заголовки
  • Исходя из имеющихся проблем, данную утилиту стоит рассматривать не как универсальную штуку для работы с любыми Си-шными заголовками, а как инструмент для автоматизации написания биндингов для Си-шных библиотек, выхлоп которого надо править вручную для получения работоспособных ü-заголовков.

    #488
    11:02, 20 авг. 2019

    Впервые за долгое время я пошатал систему типов. Я добавил новый вид типа - кортеж.

    Кортеж есть тип, представляющий собой упорядоченную последовательность элементов других типов. Элемент определяется только своим положением в последовательности, в отличии от структуры, где элемент определяется именем. Обозначается тип кортежа через ключевое слово "tup" и список типов элементов в квадратных скобках, следующий за ним.

    type IntPair= tup[ i32, i32 ];
    type EmptyTuple= tup[];
    type LongTuple= tup[ bool, f32, [ i32, 4 ], i128, char8 ];

    Доступ к элементам кортежа осуществляется через оператор [], (похоже на массивы), но индекс должен быть константным.

    fn Foo() : i32
    {
      var tup[ f32, i32 ] t= zero_init;
      return t[0];
    }

    Кортеж можно не инициализировать (если элементы конструируемы по-умолчанию), инициализировать нулём, инициализировать другим кортежем, инициализировать через последовательный инициализатор:

    var tup[ i32, f32 ] t0[ 1, 2.0f ];
    var tup[ i32, f32 ] t1= t0;
    var tup[ i32, f32 ] t2(t0);
    var tup[ i32, f32 ] t3= zero_init;

    Элементы кортежа можно перебирать через цикл "for". Тело цикла повторится для каждого элемента кортежа, при этом переменная цикла будет иметь разный тип, в зависимости от типа элемента. Внутри такого эрзац-цикла также должны работать break/continue.

    var tup[ f32, i32, i64 ] t[ 952.1f, 56, 741i64 ];
    var i32 mut res= 0;
    for( e : t )
    {
      res+= i32(e);
    } 

    Также кортежи можно присваивать (если составляющие их типы присваеваемы), передавать по значению в функцию и возвращать по значению из функции. Кортежи можно использовать как параметры сигнатуры шаблонов типов (для специализации).

    #489
    11:05, 20 авг. 2019

    Реализовав кортежи, я также поменял представление typeinfo структур. Теперь все списки в typeinfo реализованы через кортежи, раньше там были односвязные списки.
    Теперь перебор элементов typeinfo стал проще, не надо обмазываться рекурсией:

    template</ type T, size_type name_size />
    fn constexpr has_field( [ char8, name_size]& field_name ) : bool
    {
      for( &field_info : typeinfo</T/>.fields_list )
      {
        if( string_equals( field_info.name, field_name ) ) { return true; }
      }
      return false;
    }

    #490
    7:03, 23 авг. 2019

    Внезапно, столкнулся вот с этим:
    Изображение

    Началось всё с того, что я решил собрать компилятор, используя clang, а не g++. При сборке начали валиться тесты на числовые константы, к примеру, падало вот это: static_assert( 18446744073709551615u64 == ~0u64 ). Оказалось, что разбор чисел работает не совсем точно.
    Для разбора чисел использовался тип long double, у которого есть 64 бит точности, и который, вроде, должен уметь умещать в себя точно все 64-битные целые. Но, как оказалось, clang генерирует код, который не даёт нужной точности.
    Поэтому пришлось переписывать код разбора, чтобы число разбиралось и как double, и как uint64_t. Суть нового алгоритма разбора следующая: разбираются отдельно целая часть, дробная часть, экспонента. Потом это комбинируется в число. Этот способ сработал, и ране упавшие тесты прошли.
    Но плавающий петух клюнул с другой стороны. Оказалось, что в новом алгоритме разбора получалось так, что 0.3 != 3.0 / 10.0. Начал разбираться, и выяснил, что проблема вот в чём:

    result.value_double_=
      double(fractional_part) * std::pow( double(base), double( exponent - fractional_part_digits ) ) +
      double(integer_part) * std::pow( double(base), double(exponent) ); 
    Проблема оказалось в том, что std::pow( 10, -1 ) даёт 1/10, что не представимо точно в double. Потом происходит умножение на это число и результат выходит не тем, что надо. Пришлось проявить хитрость и сделать несколько иначе:
    if( exponent >= 0 )
        result.value_double_= double(integer_part) * PowI( base, exponent );
      else
        result.value_double_= double(integer_part) / PowI( base, -exponent );
      if( exponent >= fractional_part_digits )
        result.value_double_+= double(fractional_part) * PowI( base, exponent - fractional_part_digits );
      else
        result.value_double_+= double(fractional_part) / PowI( base, fractional_part_digits - exponent );
    Суть тут следующая - base всегда возводится в положительную степень, положительная степень от base всегда есть целое число, которое (за некотором исключением) всегда представимо в double. Далее происходит деление или умножение на точное значение степени, и потерь точности не происходит.

    #491
    (Правка: 14:16) 14:11, 23 авг. 2019

    Поправил компилятор, чтобы работали процессорозависимые оптимизации.
    Теперь у меня работает тот самый popcnt:

    Исходный Ü-код

    fn foo( u32 mut x ) : u32
    {
      var u32 mut v(0);
      while( x != 0u )
      {
        x &= x-1u;
        ++v;
      }
      return v;
    }
    Результирующий asm:
    _Z3fooj:
      popcntl  %edi, %eax
      retq
    .Lfunc_end0:

    Или вот, например, bswap:

    fn my_bswap( u32 x ) : u32
    {
      return (x << 24u) | ( (x << 8u) & 0x00FF0000u ) | ( (x >> 8u) & 0x0000FF00u ) | (x >> 24u);
    }
    _Z8my_bswapj:
      bswapl  %edi
      movl  %edi, %eax
      retq

    #492
    21:00, 23 авг. 2019
    Черная магия какая-то, но выглядит круто)
    #493
    14:06, 3 сен. 2019

    Написал вводную статейку про Ü для Хабра: https://habr.com/ru/post/465553/

    #494
    14:25, 3 сен. 2019

    Panzerschrek[CN]
    Внезапно, коллеги оповестили меня раньше чем я успел зайти на гд.

    Страницы: 132 33 34 3537 Следующая »
    ФлеймФорумПроЭкты