LINUX.ORG.RU

Мои проги на PureBasic

 


4

5

Если у кого есть желание ознакомится можете скачать архив прог (53Мб), в комплекте общая справка по прогам в CHM со скриншотами. Можно посмотреть её в онлайн

В комплекте исходники и можно их скомпилировать. Для Linux собраны 3 варианта пакетов deb (Mint-x64 и MX-x86), rpm (Fedora), zst (Arch), и исполняемые для Raspberry-x32, и есть отдельно архив для Андроида Можете посмотреть видео о PureBasic на моём ютуб канале


Ответ на: комментарий от hobbit

Ну поясни тогда, в чём там обязательность и ясная видимость операторных скобок. Я что-то запутался.

Тем, что у тебя не может быть вот такой херни:

cleanup:
  if FError and Assigned(FOnError) and (ParseDepth=1) then
    FOnError(Self, ErrorHead, ErrorMessage);
  FreeAndNil(Words);
  Head:=SaveHead;

Ты обязан написать

  if FError and Assigned(FOnError) and (ParseDepth=1) then
    FOnError(Self, ErrorHead, ErrorMessage)
  end if
  FreeAndNil(Words)
  Head=SaveHead

(Если же ты захочешь написать это в одну строку, теоретически это возможно, используя двоеточие вместо новой строки для разделителя statements, но на практике настолько неудобно, что никто так не делает.)

Составные операторы всегда включают в себя не «оператор» (которым является begin… end), а список операторов, и список операторов всегда зарывается отдельным ключевым словом.

Это то, что придумали в Algol 68 и то, что Вирт не успел перетянуть в свой Паскаль.

Аналогично в Ada, аналогично в bash:

if ...then
   ...
end if;

while ... loop
   ...
end loop;
if ...then
   ...
fi

while ... do
   ...
done

if fi в баше это прямое копирование с Algol 68.

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

Всё, догнал, спасибо. Про операторные скобки убедил. Тогда получается, что это намного лучше питона, например.

Я, кстати, когда-то недолго писал на оракловом PL/SQL. Там синтаксис как раз был с Ады слизан. Выглядело красиво, жаль, что отладка серверных пакетов – геморрой, но это не из-за языка, конечно.

Да, для человека, привыкшего к обязательному end if, это получше, чем begin и end.

Жаль, в бейсике нет обязательности указания типов, а то был бы идеал.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 2)
Ответ на: комментарий от hobbit

Хотя это может служить мотиватором не писать методы больше, чем на один экран, например, в маленьких функциях отдельный блок объявлений большой проблемой не является. Да, я сам этого правила придерживаюсь далеко не всегда.

Приму конструктивную критику, как сделать эту функцию короче (:

https://github.com/wandrien/qod/blob/58e4d9da726cac1c53a9b28f3a6e76ada3e6f219/src/backend_code_emitter_ctrl.qdi#L242

Но самое страшное там не это. Самое страшное в том исходнике находится здесь:

https://github.com/wandrien/qod/blob/58e4d9da726cac1c53a9b28f3a6e76ada3e6f219/src/backend_code_emitter.qdi#L1161

Эта функция просится на рефакторинг, конечно. Но свою задачу она выполняет.

wandrien ★★★
()
Ответ на: комментарий от hobbit

Кстати, насчёт длины функций и видимости имён.

Нередко я делаю так:

void foo(...)
{
    blabla...

    {
        int a = ...
        int b = ...
        ...
    }

    blabla...
}

То есть ограничиваю видимость имён блоком, даже если нет управляющей конструкции вокруг него.

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

Паскаль (и Ада, и Оберон…) не помогают такой эволюции кода и не помогают делать рефакторинг.

Также как и не помогал классический var в JS, до появления let.

Большинство других интерпретируемых языков не помогают тоже.

Си и Си++ – да, помогают.

wandrien ★★★
()
Ответ на: комментарий от wandrien

Тем, что не нужно засовывать переменные в отдельный блок объявлений, а можно объявлять их там, где они используются.

Это наоборот провоцирует писать плохой код.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Да-да.

Открываешь типичный кусок опенсорца из этого нашего линукса, а там:

int foo(бла бла)
{
    MyLibMyStruct1* s;
    MyLibMyStruct2* a;
    MyLibMyStruct3* b;

    и 4 страницы кода, где s, а и b используются в хвост и в гриву
}

Отдельное спасибо хакерским одно-, двухбуквенным называниям, по которым даже грепать не получится.

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от hobbit

почему деловые аннотации на каждую программу должны вызвать отрицательную реакцию

Я разные отзывы наслушался - вирус, реклама, фигня. Надо иметь 2000 сообщений, чтобы не услышать такие отзывы, когда уже составится мнение что лучше не лезть с примитивными аргументами.

AZJIO
() автор топика
Ответ на: комментарий от firkax

Это наоборот провоцирует писать плохой код.

Главное не перепутать, где плохой код, а где хороший.

int foo(int x, int y, int z)
{
    int что-то, что-то, что-то, fast_result, что-то;

    fast_result = try_fast_foo(x, y, z);
    if (fast_result != 0)
        return fast_result;


    страница кода

}
int foo(int x, int y, int z)
{
    {
        int fast_result = try_fast_foo(x, y, z);
        if (fast_result != 0)
            return fast_result;
    }

    страница кода
}
wandrien ★★★
()
Ответ на: комментарий от AZJIO

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

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

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

А если бы я задумал сделать альтернативу diff или find или ncdu, то сначала посмотрел бы, какие альтернативы уже написаны, и смогу ли я предложить миру что-то действительно новое. И хватит ли мне времени и запала, например, переплюнуть difftastic.

Chiffchaff
()
Последнее исправление: Chiffchaff (всего исправлений: 1)
Ответ на: комментарий от wandrien

и писать херню, что людям не нужны сорцы

забавный

у нас ведь нет эталона, кого считать идеальным, а кто отклоняется от нормы, так же как и не любитель я один код называть шедевром, а другое говнобейсиком, так как если привыкаешь то легко анализируешь, это всего лишь предпочтения. При переходе с одного на другой язык или в общении естественно то к чему привык то кажется идеальным. Регулярные выражения вообще одним символом определяются и когда их наизусть выучишь, кажется что в трёх буквах выразил всё. Если что я на питоне и джаваскрипт немного писал. Ну не хотел я с одного бейсикового переходить на что-то совсем другое, с типами через «as» c «begin» и ещё всякими выкрутасами.

На счёт сырцов, они нужны чаще после того как чел увидел интересное в проге, в остальном я даже не знаю чем они нужны. Мало что-ли сырцов в инете? Этого мусора лопатой греби. А вот чтобы решить свою проблему, захочешь не найдёшь.

AZJIO
() автор топика
Последнее исправление: AZJIO (всего исправлений: 1)
Ответ на: комментарий от AZJIO

Просто данный раздел – для обсуждения разработки.

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

Вот про FreeBASIC тут упомянули, я сходил на гитхаб, почитал из README и часть сорцов, потому что мне было любопытно.

А чтобы твои исходники почитать, надо качать архив.

wandrien ★★★
()
Ответ на: комментарий от AZJIO

чтобы решить свою проблему

Не найдëшь – напишешь и опубликуешь. А потом кто-то найдëт написанное тобой, доработает и пришлëт патч. Именно так СПО и развивается (в идеале).

yars068 ★★★★★
()
Ответ на: комментарий от wandrien

Сейчас 50 Мб залетает секунду. Если только не Плюшкин, чтобы лишним байтом инет нагрузил.

кстати if…fi это был бы мой любимый вариант, условия часто используются и если что-то долго напрягает то начинаешь также рассуждать о лаконичности кода. По поводу длинных ProcedureReturn, я копирую «Procedure» выделяя двойным кликом, дописываю одну букву «r» автоподстановка даёт мне вставить слово. А так я не любитель писать на англ. языке. Я даже использую кальки, например могу ввести «гуи», вызвать хоткей и получить конструкцию или «мессага» и получить предложения одной из форм. Либо использую свою прогу автоподстановки фрагментов (показывает окно с кучей найденного в базе), либо свою прогу замены аббревиатур.

AZJIO
() автор топика

В общем, кому будет интересно, сообщаю:

  • Программы под линь линкуются динамически с системными либами.
  • Под линь в качестве тулкита используется GTK3.
  • Типичный размер после компиляции простейшей программы с GUI, не использующей сложных библиотек: 180 кБ. (На примере Compare_string. Размер исходника порядка 25 килобайт.)

@hobbit, может тебе будет интересно)

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 2)
Ответ на: комментарий от wandrien

А вот такие дубли файлов зачем?

В PB нет встроенных средств локализации программ?

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

Средство есть, но скорее оно не как средство, а как пример кода. У каждого ведь своя стратегия локализации. Если использовать метод ресурсов, то они не работают в Linux, По факту надо кроссплатформенный локализатор.

AZJIO
() автор топика
Ответ на: комментарий от wandrien

Под линь в качестве тулкита используется GTK3.

PureBasic может скомпилировать с GTK2 и Qt, но я всегда использую по умолчанию GTK3. В GTK2 нет автоматического увеличения контролов, как и в Qt, но я изначально использовал GTK3, так как GTK2 в любой момент могут отключить.

AZJIO
() автор топика
Ответ на: комментарий от wandrien

Code Localization - мой инструмент локализации.

AutoCompletionIDE -автозавершение кода в том числе фрагментами, там же скриншоты (или тут).

TextCorrection - замена аббревиатур, можно гуи заменить на конструкцию.

AZJIO
() автор топика
Последнее исправление: AZJIO (всего исправлений: 1)
Ответ на: комментарий от wandrien

Хороший код тут такой:

int foo(int x, int y, int z)
{
    int r;

    if(r = try_fast_foo(x, y, z)) return r;

    полстраницы кода
}

Обрати внимание: вместо 3 (из первого варианта) или 5 (из ещё более ужасного второго) строк всего одна, компактная и очевидно что делающая. Заменив так везде, нижеупомянутая страница кода превратится в полстраницы или даже в треть, в итоге весь код будет читать намного приятнее, не бегая глазами вниз-вверх.

firkax ★★★★★
()
Ответ на: комментарий от AZJIO

Исходники, да даже и бинарники, выложенные в открытый доступ (в т.ч. там, где можно оставить комментарий/отзыв и т.п.), хотя бы теоретически могут быть проверены.

anonymous
()
Ответ на: комментарий от AZJIO

Какова цель? Большинству не нужны исходники, им нужны проги, и желательно опакеченные, чтобы ставить без возни.

цель такая, чтобы оставшееся меньшинство занималось дальнейшей разработкой, или могло что-то исправлять.

anonymous
()
Ответ на: комментарий от firkax

Вот только вместо int r; на практике будет такое:

ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
{
    Section *tcc_sect;
    SCNHDR *coff_sec;
    int file_pointer;
    char *Coff_str_table, *pCoff_str_table;
    int CoffTextSectionNo, coff_nb_syms;
    FILHDR file_hdr;
    Section *stext, *sdata, *sbss;
    int i, NSectionsToOutput = 0;

Немножко ты попутал, как реальный код на си выглядит.

очевидно что делающая

Очевидно делающая присваивание внутри условия? Это для кого очевидно, для инопланетян?

Или return в конце строки — это очевидно при чтении?

компактная

А кто тебе сказал, что компактность увеличивает надежность кода?

Хороший код тут такой

А теперь добавь туда assert, чтобы проверить результат вызова try_fast_foo().

А следом добавь гарантию, что r не может быть использован далее в теле функции.

r

хакерские однобуквенные переменные

Ну всё логично.

wandrien ★★★
()
Ответ на: комментарий от AZJIO

На счёт сырцов, они нужны чаще после того как чел увидел интересное в проге, в остальном я даже не знаю чем они нужны. Мало что-ли сырцов в инете? Этого мусора лопатой греби. А вот чтобы решить свою проблему, захочешь не найдёшь.

возьмем пример. Пару месяцев назад мне была нужна функциональность, которой не было в той, проге, что мне нравилась. Я взял и запилил эту функциональность за один-два дня. И потом может даже в апстрим примут.

anonymous
()
Ответ на: комментарий от firkax

я ни разу с ошибками именно этим спровоцированными не сталкивался.

Мне тут вчера потребовалось подсчитать количество узлов в дереве. Ну и я витая где-то в облаках, вместо inc Count;, написал inc P;:

word NodeGetTreeSize(word P) of
	word Count = 0;
	while P != nNODE loop
		Count = Count + NodeGetTreeSize(Node[P].pLeft);
		P = Node[P].pRight;
		inc Count;
	end:while
	return Count;
end

Естественно, программа крашнулась.

Искал я ошибку минут 15 наверное, потому что искал даже не в том модуле.

И чем больше у тебя мусорных имён болтается в пространстве имён бесконтрольно, тем выше вероятность тупых ошибок, которые компилятор не заметит.

wandrien ★★★
()
Ответ на: комментарий от AZJIO

мой инструмент локализации.

То есть, программа просто берëт исходник и заменяет все строки на их переводы? Это достаточно уныло. Везде есть более-менее вменяемые средства, которые заменяют данные в программе прямо на ходу, например, gettext. Ну как, на ходу, все подлежащие переводу данные сначала специальным образом подготавливаются, и при запуске программа в соответствии с системной локалью подгружает нужный перевод из файла. При этом язык оригинала из программы никуда не девается, и если перевода нет, будет показан оригинал. Ну, а так как локаль можно менять на горячую, можно сделать LANG=ЯЗ прога и показать заокеанскому визави. При этом локаль всего остального как была, так и останется нетронутой.

yars068 ★★★★★
()
Последнее исправление: yars068 (всего исправлений: 1)
Ответ на: комментарий от wandrien

Вот только вместо int r; на практике будет такое:

Ну и что? Дописать в этот список int r; не проблема.

Очевидно делающая присваивание внутри условия? Это для кого очевидно, для инопланетян?

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

Конструкция, кстати, по смыслу такая: «если функция что-то вернула то пробросить это значение дальше», сама переменная r тут нужна только ради сишного синтаксиса и внимание привлекать вообще не должна.

А кто тебе сказал, что компактность увеличивает надежность кода?

Тебе надо прочитать в 3-5 раз меньше строк (и при этом эти строки ещё и почти не длиннее выходят), ты не бегаешь глазами по коду и меньше напрягается, видишь целиком весь алгоритм а не только его кусок, остаётся больше внимания на собственно анализ хода его выполнения. Это определённо способствует большему его качеству на выходе.

Суть примерно такая же как когда данные стараются локализовать чтобы процовый кеш не замусоривать и не создавать тормоза. Только тут не только тормоза, а ещё и повышенный шанс ошибиться появляется (например, 0.001% вместо 0.0001% на строку). Зрительный мусор (лишние не несущие смысла строки, лишние буквы в именах переменных когда и без них контекст достаточный чтобы всё понять итд) крайне вреден.

А теперь добавь туда assert, чтобы проверить результат вызова try_fast_foo().

Вот когда там понадобится assert - и подумаю над этим. Зависит ктстаи от длины условия. Если там assert(r>10); то засуну его в ту же строчку добавив {}.

А следом добавь гарантию, что r не может быть использован далее в теле функции.

Чего? Он как раз и сделан таким простым чтобы его можно было использовать дальше в аналогичных местах.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от wandrien

Мнение Линуса по этому вопросу такое: а вы не пишите функции где по 100 локальных переменных.

Это настоящее решение проблемы, а определение переменной в своем блоке это не решение, она может наоборот затенить переменную выше, и будет та же самая проблема только наоборот.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

она может наоборот затенить переменную выше

vadim@aquila:/tmp/2$ cat 1.c 

int f(int x, int y)
{
	int a = x + y;

	{
		int a = x - y;
	}

	return a;
}
vadim@aquila:/tmp/2$ LANG=C gcc -Werror=shadow -c 1.c 
1.c: In function 'f':
1.c:7:21: error: declaration of 'a' shadows a previous local [-Werror=shadow]
    7 |                 int a = x - y;
      |                     ^
1.c:4:13: note: shadowed declaration is here
    4 |         int a = x + y;
      |             ^
cc1: some warnings being treated as errors
Status: 1
vadim@aquila:/tmp/2$ 
wandrien ★★★
()
Ответ на: комментарий от firkax

Очевидно для любого опытного Си-программиста.

Нет, очевидно и структурно верно — это то, что в современных языках: https://metanit.com/rust/tutorial/2.22.php

сама переменная r тут нужна только ради сишного синтаксиса и внимание привлекать вообще не должна.

Надо же: оказывается, у Си херовый синтаксис, а херовые практики использования языка делают его еще хуже. Кто бы мог подумать.

Чего? Он как раз и сделан таким простым чтобы его можно было использовать дальше в аналогичных местах.

Типичный говнохакерский подход, который постоянно стреляет в ноги, и который я в коде, с которым работаю, удаляю как только вижу. Гнать ссаными тряпками за такое.

Ты память компилятора экономишь или что?

wandrien ★★★
()
Ответ на: комментарий от MOPKOBKA

Ну так и твой пример ловится компилятором.

Какой пример ловится компилятором?

MyStruct *p;

p = GetMyStruct(...);

...

FreeMyStruct(p);

... через страницу кода

foo(p);

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

И этот пример, и предыдущий: Мои проги на PureBasic (комментарий)

через страницу кода (скорее несколько)

В этом и проблема.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 3)
Ответ на: комментарий от MOPKOBKA

И этот пример

Никаких пруфов конечно же не будет.

и предыдущий: Мои проги на PureBasic (комментарий)

Ты головой ударился?

Инкремент одного целого вместо инкремента другого целого ловится компилятором?

wandrien ★★★
()
Ответ на: комментарий от wandrien

Ты головой ударился?

Нет, пока еще могу вбить пару строк и посмотреть что скажет компилятор. Что я собственно и сделал перед написанием комментария. А у тебя какие проблемы? Если не знаешь что вводить, то вот минимальный набор: -fanalyzer -Wall -Wextra

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

В этом и проблема.

Да, и это типичная проблема РЕАЛЬНОГО кода на сишечке.

Когда у тебя в начале функции объявлено 8 строк с переменными, а потом идёт три экранных страницы кода, где эти переменные используются как попало.

Вот ровно как firkax написал: «Он как раз и сделан таким простым чтобы его можно было использовать дальше в аналогичных местах.»

А потом ты это говно пытаешься отрефакторить или исправить в нём баг, и не понимаешь, какая переменная должна что означать по СМЫСЛУ, потому что внезапно смысл одно и того же имени в разных точках функции РАЗНЫЙ.

И ты такой говнокод защищать взялся.

wandrien ★★★
()
Ответ на: комментарий от MOPKOBKA

Примера конечно же не будет, как я и говорил.

-fanalyzer

Понятно.

Сишное дрочево всё-таки повреждает мозг.

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

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

MOPKOBKA ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Верхний пример бесконечный цикл,

Верхний пример делает segfault, обращаясь к рандомной памяти.

нижний use-after-free

Ты понимаешь, что там может быть неочевидная для статистических анализаторов логика? Или это может быть библиотечный вызов, не покрытый описанием семантики для анализатора? Или что там вообще может не быть никакого free, а тупо программист опечатался и не то целое в последующем вычислении подставил? Или от значения не той переменной сделал ветвление. (А учитывая еще и приколы с UB, это может очень прикольно в ногу стрелять.)

Есть какая-то разумная причина, почему нужно забивать пространство имён переменными, которые в конкретных точках программы будут ЕЩЕ содержать мусор и УЖЕ содержать мусор?

Ты понимаешь маразм того, что у тебя синтаксически доступно имя, которое заведомо содержит мусор, и обращение которому не имеет смысла?

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

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

А вот нижний пример с used after free ловится и обычным Wall, хотя непонятно твое сопротивление fanalyzer.

MOPKOBKA ★★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

хотя непонятно твое сопротивление fanalyzer.

Я fanalyzer использую при сборке кода.

Мне непонятно твоё сопротивление против грамотного оформления кода и твоя святая вера в то, что эвристики могут проверить любой плохой код.

wandrien ★★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

Нет, очевидно и структурно верно — это то, что в современных языках

Я же специально уточнил «для любого опытного Си-программиста». Всякие расты и подобное это результат того что кто-то этим самым стать не смог.

Надо же: оказывается, у Си херовый синтаксис, а херовые практики использования языка делают его еще хуже. Кто бы мог подумать.

Я такого не писал, не надо выдумывать. Хотя, возможно, что-нить типа

if(f(a,b,c)) return $;
или
return? f(a,b,c);
было бы чуточку (совсем чуточку) удобнее, но я не уверен. Текущий синтаксис, касательно данного вопроса, норм, и указанная мной «практика использования» тоже норм.

Ты память компилятора экономишь или что?

Я же прямым текстом расписал, что там непонятного то? Ещё раз напишу: экономлю свою память и своё внимание. Зрительный мусор их жрёт не принося взамен ничего.

firkax ★★★★★
()