Главная | Настройки | NSFW
Тема:
Доски


[Ответить в тред] Ответить в тред

[Назад] [Обновить тред] [Вниз] [Каталог] [ Автообновление ] 250 / 12 / 203

Anonymous No.989
pst.png (58 KB, 715x853)
Laisi. Это язык программирования, который я создаю + icolaisi, его компилятор-интерпретатор. В связи со смертью эндчана, переношу свой блог сюда. Долго я не делал иколайси.
https://gitlab.com/Ninikaita/icolaisi — страница проекта, есть и документация к самому Лайси. Так же есть сайт в онионе, но он сейчас лежит, мне не хватает одного или нескольких компонентов.
Как будет происходить процесс компиляции лайси:
0. Препроцессирование кода, обработка дефайнов, инклудов, импортов, загрузка инклудов и импортов, и их препроцессирование.
1. Парсинг полученного кода.
2. Преобразование парс-дерева в лайси-байткод.
3. Компиляция лайси-байткода в LLVM IR.
4. Компиляция LLVM IR в таргетный выход.

Я пишу компилятор на питоне в связи с наличием хороших библиотек для парсинга. Раньше я использовал pyparsing для всего, препроцессирования и самого парсинга. Но у меня какие-то проблемы с локацией отпарсенного и вообще код плохой, так что сейчас я его немного переписываю. Я собираюсь препроцессировать самостоятельно и только препроцессированный код парсить через pyparsing.
Уже почти написал функцию, которая очищает код от комментариев и возвращает словарь со значениями пропуска символов, чтобы потом, при синтаксической ошибке корректно пользователю выводить сообщение об ошибке.
Затем надо будет загружать дефайны, импорты и всё такое, а затем парсить полученный код.
В нынешней версии компилятора, которая есть на гитлабе Лайси поддерживается в очень маленьком количестве, вообще маленьком.
В Лайси есть 2 типа типов — статические и динамические, есть ещё и undefined behavior.
Статические типы — uN, sN, fNeM (или fN). где N и M это какие-либо целые положительные числа. Тут всё ясно в LLVM uN и sN это просто iN + определённые инструкции при вычислениях. А вот fN это небольшая проблема. Я хотел раньше сделать так, что f32e8 это IEEE 754 single, f64e11 это IEE754 double, f50e3 будет сам компилятором считаться. Но недавно я узнал о так называемом posit, совершенно новый тип для флоатских значений. И я подумал, что нужен тип fN. В любом случае, в спецификации лайси указано, что в fN(eM) может быть undefined behavior в зависимости от таргета, так что не используйте это для точных вычислений. Не уверен, стоит ли выпилить этот undefined behavior. Может стоит ввести типы single, double, quadruple и всё такие, всё поменять. Может и стоит. Я ещё подумаю над этим.
Динамические типы — int, float, string, func, proc. Про них читайте в документации, сам скажу, что их я буду реализовывать через liblaisi, это стандартная библиотека для лайси, которая будет иметь функции для арифметико-логических операций над типами и другие штуки. Будет линковаться статически, но не обязательно.
Почему лайси хороший?
Есть умное и безопасное управление памятью (в следующих версиях будут исключения для segfault и out of memory); параллелизм из-коробки, то есть вы можете написать один код, который будет исполняться на одноядерном микроконтроллере и многоядерном GPU или кластере, результат будет один и тот же, но с разной скоростью; есть хорошее статическое метапрограммирование (а в будущем планируется и динамическое), благодаря которому достигаются дженерики, полиморфизм, предрасчёт значений функций в заданном диапазоне для оптимизации (например указать, до какого N просчитать факториал и засунуть в глобальную переменную).
Так же я бы хотел добавить много юзабельных библиотек, например:
0. audio — набор инструментов для загрузки и сохранения стандартных форматов аудио.
1. video — набор инструментов для загрузки и сохранения стандартных форматов картинок и видео.
2. dapa — парсинг данных. Предполагается, что строковых, но темплейты, которые будут там, должны быть способны принимать любые итерируемые данные.
3. fs — взаимодействие с файловой системой, директории, права доступа, теги.
4. hash (?) — набор функций для хеширования.
5. io — input/output, может быть в файлы, stdion, сокеты, в зависимости от расширений.
6. json — парсинг json.
7. laisi — библиотека для компиляции и исполнения лайси.
8. llvm (?) — генерация LLVM IR?
9. math — библиотека с большим набором разнообразных математических функций. Синусы, матрицы, пересечение фигур в 3D, поворот фигур в 3D, интерполяция и всё такое.
10. module ­— Загрузка подгружаемых модулей, будь-то шейред обджект, длл, питонокод, луакод или ещё что-то.
11. noise — набор функций для разных шумов.
12. opengl — биндинг к опенглу.
13. sdl2 — биндинг к SDL2.
14. repr — репрезентация данных в human-readable вид. Благодаря препроцессеговой штучке @ifhas могут быть репрезентованы и ваши типы.
15. os (?) — взаимодействие с OS?
16. socket — сокеты.
17. thread — потоки от OS, явно паралелльные.
18. time — взаимодействие с временем, часы, вызов функций-коллбеков раз в N времени.
19. xml — Парсинг XML.

Сейчас я опять меняю стандарт лайси. В Laisi 0.7.3 будет добавлен @call(f), позволяющий вызвать объект, если вызов происходит без сайд-эффектов, для препроцессингового расчёта значений. Таким образом, в библиотеке math можно прописать сколько значений препроцессировать для какого-нибудь фактрориала или чего ещё и это будет оптимизация.
Ещё я пересмотрел f-типы. Я решил, что не стоит вводить fNeM или fN. Лучше сделать стандарт laisi-float, описывающий поддерживаемые флоат-типы. Это связано с будущим, ведь и форматы флоатских чисел не стоят на месте — https://en.wikipedia.org/wiki/Unum_(number_format), в то время как i-формат целых чисел это просто нормальная такая абстракция. В этой версси будут поддерживаться, вероятно, IEEE 754 half, single, double, quadruple, octuple. Над posit подумаю ещё. Может быть также некий brain half.
Я пересмотрел f-типы, так как в стандарте прямым язык указано, что поведение может быть машинно-зависимым, то есть undefined behavior, а зачем программистам на моём ЯП лишняя головная боль, когда они решат точные расчёт вести на даблах и скомпилируют под обычный x86-64 и какую-нибудь экзотическую архитектуру, у которой вместо IEEE 754 double нечто своё?
Anonymous No.990
>>989 (OP)
И зачем нам ещё один высокоуровневый язык программирования? Какая у него область применения? Всё описанное тобой можно реализовать на C и Python, зачем плодить сущности?
Пост отредактировал Anonymous
Anonymous No.993
>>990
>зачем плодить сущности?

>зачем плодить языки
>зачем плодить художественные произведения
>зачем плодить людей
>зачем жить

Опять выходишь на связь, мудило?
Anonymous No.994
Где гайды? Оно умеет в tls сокеты уже?
Anonymous No.995
>>994
Нет, оно ничего не умеет, язык поддерживается в очень маленьком количестве.
Я думал, что записал это, не заметил.
Компилятор на очень раннем этапе развития. Даже импорты не поддерживаются.
По сути компилятор пока что бесполезен.
Anonymous No.1000
О, ты с эндчана? Где теперь /bb и /ca?
Anonymous No.1001
>>989 (OP)
Как на нём сделать классы?
Anonymous No.1002
>>989 (OP)
А какая у него область применения? Что послужило причиной для начала разработки?
Anonymous No.1003
>>989 (OP)
Кстати, это не ты ранее mctagfs пилил?
Anonymous No.1005
>>1000
Незнаю, мне не интересны были те доски. Меня больше интересует куда алармист-кун ушёл.
>>1001
В Лайси класс — макрос. И дженерик — макрос. При этом они структуры либо юнионы.
@define myclass as struct {
u8 var0;
s32 var1;
int var2 := 53333333333335555423; #автозаполнение значения при декларировании переменной.
float var3;

__constant__ func (self,u8 a) := { #по сути, инкапсулировання функция. self — указатель с типом myclass.
self->var0 += a;
};

func (self,u8 a,u8 b); #коллбек
func (s32[] l); #ещё один коллбек, он не знает где данный объект, так как self не передаётся.
};

func () progentry 'main' := {
myclass instance; #декларирование переменной
};

Пока компилятор такого не может. Мне надо сделать препроцессирование кода и парсинг препроцессированного кода, а потом компиляцию.
Наследований в нынешнем стандарте нет, но, может быть, потом добавлю.
Полиморфизм достигается через @template

>>1002
>область применения
Лайси — язык для приложений, но не обязательно ОСевых, может и микроконтроллерных. На нём можно будет писать обычные приложения, прошивки для МК (с системой памяти в куче из-коробки), он безопасный по памяти, имеет исключения в случае SEGFAULT и OUT OF MEMORY. Первый можно достигнуть при помощи setjmp перед каждым переходом по оператору -> (но не индексированию, индексирования должно быть и так безопасным), а в случае MK, обращаться к внутренним структурам памяти, чтобы узнать, можно ли туда обращаться. Тем не менее, у компилятора, наверное, будет возможность отключить обработку таких исключений.
Кроме того, Лайси имеет встроенную параллельность через конструкцию each и векторные вычисления, благодаря чему он автоматически будет использовать вычислительные устройства для ускорения вычислений (как минимум сам процессор), хотя, в таком случае может быть потребность интерпретировать код или байткод, компиляция будет сложнее.
Для чего он не подходит, так это для очень худых и производительных программ (для совсем малых МК и бутылочных горлышек) и для разработки ядра ОС (хотя и тут это не сильно мешает).
Лайси будет иметь несколько уровней структуры кода:
0. Машинный — не имеет динамических переменных, исключений или чего-то ещё, благодаря чему компилятор должен не давать инструменты для доступа к памяти в куче — библиотеке для данной ОС или структуры данных для bare metal (МК, например).
1. Память в куче — имеет динамические переменные, так что будет память в куче.
2. Компиляторский — это для будущих версий, объяснять не буду.

Почему я начал разрабатывать его? Потому что мне не нравятся нынешние ЯП. Я хочу удобный для себя инструмент. Даже не так, может ЯП не очень плохие, но какие инструменты для них! В гайдах для си на каждом шагу предлагают велосипедить. А из-за популярности C++ сложно найти библиотеки с биндингом для C. В питоне уже получше, но я бы хотел более машинный и компилируемый язык.
Разработка языка началась 1 июня 2018 года, в конце Мая 2019 я выпустил первую версию стандарта и что-то, что немного компилировало.

>>1003
Да. Помню, что сейчас он удалён из публичного доступа. Говорил ещё, что подлатаю и снова выпущу, но так и не прикасался. Хочешь, могу немного изменить и выпущу снова. Там поддержка JSON будет.
Я до сих пор не посмотрел донаты на софт с монеро-кошелька. Блокчейн не докачан. Вряд ли мне кто-то донатил, но если задонатил, значит надо потратить эти деньги на разработку соответствующего софта.
Anonymous No.1011
>>1005
>На нём можно будет писать обычные приложения, прошивки для МК
А компиляторы для микроконтроллеров есть? Если есть то для каких?
Anonymous No.1012
>>1011
Не совсем понял тебя.
Повторюсь, что компилятор для Laisi ещё не готов.

Как происходит компиляция под микроконтроллеры:
В компиляторе делаешь пометку --platform baremetal (или что-то такое), чтобы компилятор вместо линковки всяких libc или моего liblaisi статически прилинковал liblaisibaremetal или что-то подобное. В данном объектнике будут функции и переменные, в которых будут содержаться данные об памяти в куче (если нужно).
Далее, вне зависимости от выбора, компилятор генерирует лайси-байткод, а потом LLVM IR. И уже какой-нибудь бекенд LLVM генерирует машинный код или целую прошивку (ELF, Intel Hex, etc) для соответствующего компилятора. Вот и всё. На самом деле я мало МК программировал, только AVR, но, думаю, для STM32 и PIC приблизительно одинаково будет. Даже если прошивка принимает коллбеки как ESP8266???, то всё-равно получится, ведь основная единица кода в Laisi — глобальная переменная.
Что насчёт SDK для МК, то это уже нужно отдельно для каждого контроллера создавать. Для AVR, наверное, будет не сложно, установи пакеты avr-gcc и у тебя будут хедеры для AVR, где есть все нужные константы и структуры, надо лишь преобразовать в лайси-код для импортируемой библиотеки.
Anonymous No.1018
Адаптирую ядро парсинга и подумал, раз я такое с флоатскими типами делаю, то и тип float надо поменять на другое имя. Он же не float на самом деле, а rational. И какое имя делать? rational, ratio, rati? Я незнаю.
Ещё надо, чтобы потом была библиотека autofloat, которая возьмёт дефолтный для таргетной платформы флоат fN или fNeM. Если x86-64, то f1...32 будет single, а f33... или f33...64 double. Либо можно исключения бросать, если битность слишком большая и это, тогда, надо ввести @assert, препроцессинговое исключение.
Anonymous No.1019
>>1012
То есть оно сначала компилируется в некий промежуточный код, а дальше уже в машинный?
Anonymous No.1021
>>993
Ты скажи, в чём фишка твоего языка, что особенного ты хочешь реализовать, или же что тебе не нравится в существующих языках? Или ты пишешь проект для себя, чтобы понять все тонкости. На какие другие языки ты больше всего ориентируешься при создании своего?
Anonymous No.1022
>Есть умное и безопасное управление памятью (в следующих версиях будут исключения для segfault и out of memory); параллелизм из-коробки, то есть вы можете написать один код, который будет исполняться на одноядерном микроконтроллере и многоядерном GPU или кластере, результат будет один и тот же, но с разной скоростью; есть хорошее статическое метапрограммирование (а в будущем планируется и динамическое), благодаря которому достигаются дженерики, полиморфизм, предрасчёт значений функций в заданном диапазоне для оптимизации (например указать, до какого N просчитать факториал и засунуть в глобальную переменную).
Сори, за фичи ты написал. Можешь ещё раскрыть, за счёт чего достигается параллелизм?
Anonymous No.1023
>>1019
Он компилируется в первый промежуточный код — laisi-bytecode, затем laisi-bytecode компилируется в LLVM IR (либо другой), а потом уже в машинные инструкции.

>>1022
Есть слой языка. Там есть each конструкция и векторные операции:
a[:][3:8][2:5] := b[:] + c[4:]; — векторные операции.

double[] arr := getarray();
double[] arr2 := getarray();

double out;

n,m in each arr,arr2 {
out += n;
out *= m;
};

— each-конструкция. Тут для каждой комбинации между элементами arr и arr2 к out будет приплюсован элемент arr, а затем умножен на элемент arr2.

А сама параллельность уже будет при исполнении компилированного или при интерпретации, причём при интерпретации должно быть параллельнее, так как всё точно будет инициализировано.
Те инструкции могут быть скомпилированы как и в просто цикл и по одному делаться, а могут быть распараллелены. Причём, в некоторых случаях придётся мьютексы вставлять, из-за чего такой код можно будет только интерпретировать интерпретатором (тот же icolaisi), либо инициализировать всё в единственной функции для входа, либо пробовать инициализировать во всех или выбранных на стадии компиляции (с помощью аргументов командной строки) функциях, чтобы потом использовать как бинарную библиотеку, но тут тоже нужен грамотный подход со стороны программиста.
Как это можно распараллелить? OpenCL, потоки и SIMD.
Anonymous No.1043
Эх, как же хочется доделать иколайси.
Anonymous No.1044
Увидел статью https://habr.com/ru/post/466181/
А ведь там может быть штука, которую я не смог сделать когда к ныне замороженному nnaamapeiko пытался поддержку OSM приделать.
Надо будет потом проверить.
Anonymous No.1048
>>1018
> И какое имя делать? rational, ratio, rati? Я незнаю.
Чем хуже, тем лучше. Назови rat.
Anonymous No.1049
>>1043
Так доделывай и выпускай релиз, что тебе мешает? Быстрее выпустишь - больше времени на доработку будет. Тянуть не стоит.
Anonymous No.1050
u8[[]3,5,8][][][64]{s64[54]}[5] b — переменная b с типом указателя на массив из пяти элементов, которые являются указателями на указатели на ассоциативный массив, где в качестве ключей используются 54-размерные массивы s64 (int signed 64-bit), а в качестве значений 64-размерные массивы динамических массивов динамических массивов массивов с неизвестным количеством измерений, но которые имеют повторяющуюся размерность 3, 5 и 8 типа u8 (int unsigned 8-bit).

>>1049
>что тебе мешает
отсутствие достаточного количества воли и мотивации.
Впрочем, я уже почти могу сделать парсер препроцессированного кода и компиляцию его части, со всякими статическими типами.
Но такой компилятор всё-равно будет на-посмотреть, ведь импорт библиотек и определение классов/макросов это дело препроцессора.
Вроде бы всё и легко, но почему-то сложно. Мне может так казаться из-за ранних рудиментов, когда я ещё не представлял структуру компилятора и на питоне плохо программировал, да и вообще опыта в программировании мало было.
Anonymous No.1051
u8[[]*3,5,8][][][64]{s64[54]}**[5]* b
коде забыл поставить
Anonymous No.1052
Короче еще один шизик, расходимся
Anonymous No.1095
Хотя не, парсить довольно сложно. Ещё и пипарсингом.
Например, такой код:
func (u8 a,[u8 b,s32 c],s32 exc) f := {
s32 a := if a: b, elif c: c + 5, else: abc*3;
s32 b := try: a + 3, except: a/0, except: aaa + 3 - b();
};

Тут используются if и try для операндов. Но в случае с иф такое у меня почему-то заняло всю ОЗУ, я думал там утечка памяти какая-то, но программа исполнилась. В общем, не получится пока ифы или надо искать некоторую альтернативу.
А вот с try ситуация лучше. Но всё-равно эти 3 строчки кода парсятся где-то секунду, потому что парсится он питоном! Не просто питоном, а пипарсингом!
Anonymous No.1107
Боюсь, не получится полностью парсить лайси-код пипарсингом. Сейчас он занимает где-то 1 ГБ памяти.
Есть вариант для начала парсить лайси-байткод.
Anonymous No.1117
Эх, очень сложно с этим пипарсингом. Это не так уж и просто. Вот почему он занимает 1 ГБ ОЗУ? Всего-то на парсинг кода. При этом он часто где-то ломается, в некоторых конструкциях образуются какие-то циклы, из-за чего программа попадет в бесконечный цикл. А всё потому, что пипарсинг не предназначен для таких сложных правил.
Я мог бы парсер на си писать, но как и везде рекомендуют, на си надо писать велосипеды. Никаких подключаемых библиотек, слышишь? Сам выбрал си, вот и пиши велосипеды. Мы тут си++ используем с библиотеками и нам нормально.
Конечно, я планирую icolaisi переписать на лайси, но для этого надо бы сделать icolaisi сначала.
Anonymous No.1126
Оказывается, posit может быть не только 32-битным или что-то такое.
В https://habr.com/ru/post/465723/ статье и https://habr.com/ru/post/466813/ статье написано что-то про posit. Я почти ничего не понял, потом переварю эту информацию.
Может быть posit подойдёт для моих бесконечные int и rat (бывший float)?
Тем не менее, я собираюсь добавить и поддержку типов стандарта IEEE 754, с позитом надо подумать и поизучать его.
С парсингом самого кода проблемы, но я решил, может мне пока сделать парсинг репрезентованного лайси-байткода? Он парсится гораздо легче.
Ещё я решил отказаться от концепции, что функция это переменная, которая, к тому же, может быть переопределена или изменена. Теперь функции будут иметь следующий вид:

func (ret,[args],exc) {
ins
}

либо
proc (ret,[args]) {
ins
}

proc не может бросать исключения и является чистой по ABI, наверное, аналогичной Си, но мне надо поизучать.
Anonymous No.1178
Снова я забыл про то, что в Лайси нельзя параллельно с другими инструкциями исполнять goto, branch, return и, наверное, alloca. Это инструкции лайси-байткода.
Вот, например:
proc (u8,[s32,s32]) @0 'funcname' {
%2 := alloca u8;
}

Преобразуется в LLVM ир:
; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

define i8 @"funcname"(i32 %".1", i32 %".2")
{
.4:
%".5" = alloca i32
store i32 %".1", i32* %".5"
%".7" = alloca i32
store i32 %".2", i32* %".7"
%".9" = alloca i8
}

Надо добавить поддержку ещё большого количества инструкций, а также индексирования, обращения к членам структуры или юниона, получения значения по указателю, получения указателя.
Текстовая форма лайси-байткода очень похожа на LLVM IR. Те же функции (хотя раньше, они были бы переменными), переменные. Разве что используются laisi-типы, некоторые инструкции могут быть параллельными, может быть несколько субоперандов через запятую и они могут иметь индексы или слайсы, например:
%3[5],@4[7:] := @4[2:6],%1[6][:6] + dup(%0);
Anonymous No.1180
Bokuman-artist-[...].jpeg (121 KB, 811x552)
Задам очень тупой вопрос, только не ссы на меня, автор, твой язык поддерживает ARMx64-архитектуру?

Если да, то, может быть, начать на нем пилить приложения для ведра и выкладывать в F-Droid для продвижения? Само собой не тебе, автор, а тем, кому язык понравится. Ты итак сделал гигантскую работу, инфраструктуру создадут последователи.
Anonymous No.1181
Нет, всё-таки даже уровень лайси-байткод ---> LLVM IR довольно сложный. Надо сделать всю эту поддержку индексаций, слайсов, и для ассоциативных массивов. И все эти операторы для каждых типов проделать и преобразования типов. Потом ещё надо написать liblaisi, стандартную библиотеку лайси, которая будет иметь функции для маллокирования, реаллокирования, фриианга, операторов для некоторых типов и других функций для них. Ещё и поддержку пяти типов IEEE 754, даже если таргет-архитектура не поддерживает. Насчёт posit подумаю, когда станет популярным. Но загвоздка в том, что чтобы написать liblaisi, надо доделать иколайси с его поддержкой и препроцессинга и всего.
Кстати, ещё я подумал, что стоит вернуть alloc, realloc и free как встроенные стандартизированные функции для выделения памяти в куче. Динамические массивы это, конечно, хорошо, но часто бывает так, что указатель на переменную должен быть много в каких местах и даже если оно будет ссылаться на какой-либо элемент динамического массива, стоит его изменить и указатель может начать ссылаться не туда, куда надо.

>>1180
Лайси будет компилироваться прежде всего в LLVM IR, остальные действия делаются llvm-as и линковщиком для выбранного таргета, которые тоже будут управляться icolaisi. Как известно, LLVM IR это промежуточный код между фронтендом — языком программирования и бекендом — машинным кодом. Соответственно, его можно скомпилировать хоть в AArch64 (который ARM64), хоть в ARMv7, хоть MIPS be, le, MIPS32, Эльбрус, какую-нибудь экзотическую VLIW-архитектуру, AVR, MicroBlaze и твой собственный процессор, напылённый на германиевый кристалл органическими полупроводниками с твоей собственной архитектурой, лишь бы библиотека-модуль для бекенда была. А для всех популярных архитектур они есть. Даже для джава-байткода есть бекенд!
Но с андроидом есть проблемка. Дело в том, что хоть и есть возможность подключения бинарных библиотек к APK, оболочка всё-равно пишется на джаве. Незнаю, насколько сложно через тот же LLVM скомпилировать dex-код APK-приложения, вместе с классами от гугла и я не хочу с этим разбираться.
В любом случае, такое не подходит. Писать ELF .so Shared Object бинарные библиотеке на этом ЯП можно, а тип proc аналогичен классической сишной функции, так что Laisi можно использовать хоть вместе с C, хоть с C++, Python через уже готовый модуль ctypes, с чем угодно!
Но вообще андроид мне не нравится, особенно с его пригвоздённой джавой. Я хочу сделать свой ГУИ + гипертекст МаркРассвет язык с embedded laisi-функциональными скриптами и всё это в виде убийцы-воскрешателя WEBа. И всё это работает поверх опенгла либо другого бекенда-растерайзера + SDL2.
Чтобы сделать язык юзабельным, надо сделать к нему библиотеки. Самые первые библиотеки это будут math, video (для картинок и видео), sdl2 биндинг, opengl-биндинг, input-output и что-то с сокетами, про потоки и процессы не забываем и можно использовать супер-мешанину.
>гигантскую
Нет, пока что это средняя. Вот сделаю парсинг ЯП и препроцессирование, тогда поговорим.
>инфраструктуру создадут последователи
И это тоже нет. Я уже делал небольшой сайтец, который открывал в онионе (сейчас не работает), но хотелось бы получить сервер и поставить его где-нибудь с доступом к интернету и открыть уже реальный клирнетовский домен. Это, может быть, потом.
В этом сайте должна быть документация, туториалы и репозиторий библиотек, что главное. Библиотеки будут распространяться в виде исходного кода и надо без зловреда.

Но сначала мне надо хотя бы уровень лайси-байткод —> LLVM IR доделать.
Anonymous No.1182
Сохранение переменных на диск? Да.
У меня есть тип string. По сути это u8[], то есть динамический массив беззнаковых байтов. Но у него во-первых только 2 оператора — + и * и они работают по-другому. + конкатенирует, а умножение повторяет. И иные динамические типы могут быть сконкачены с помощью встроенной функции concat. Главное предназначение string — сохранение переменных. Предполагается, что чтобы сохранить некоторый тип (база данных, логи какие-нибудь) на диск, надо преобразовать его в string. Такая стандартизация. Но это подходит, есои у такого типа есть единый или преимущественный формат для сохранение. Например, для uN и sN это не подойдёт, потому что они могут быть сохранены в разном endianless. Для них существуют встроенные функции littleendian и bigendian, возвращающие соостветствующие строки. Что насчёт IEEE 754 float-типов, то для них подходит такая фича (если я ничего не путаю, и они не зависят от endianless). Так же у меня есть тип int и rat (бывший float). Раньше я тоже хотел сохранять их при помощи преобразования в string, но недавно понял, что не уверен с форматом для таких чисел. Вдруг я придумаю или узнаю что-нибудь получше для хранения таких чисел на диске? Тогда то преобразование в string станет deprecated и legacy.
Сохранение на диск это лишь частный случай. string (почти аналог bytes в питоне) использовался бы и для передачи данных по сети и много чего ещё.
Anonymous No.1189
Что? Исключения? Динамически типизированные исключения не нужны для Laisi!

Пока я делал компиляторский уровень, вспомнил, что забыл про исключения. У меня были и раньше проблемы, я попробовал узнать, а как они в C++ реализованы. Как оказалось, он имеет особую очень сложную RTTI структуру для типов.
Ещё и LLVM имеет некоторые инструменты для создания исключений.
Я подумал и прикинул такой вариант: пусть каждый тип, используемый в иключениях имеет свой ID. Но я вспомнил про экстернал файлы. Если сделать бинарную библиотеку, где есть типы func (способные к исключениям), пусть их будет 5 штук, скомпилировать это как шейред обджект, а в хедерах к этой библиотеке заэкстернить только 3 func. Тогда 2 id потеряется, а ведь и они могут быть типом для исключения. Потом я подумал, что можно это продолжить, если запретить func экстернировать. И это не страшно, ведь предполагается, что те же лайси-библиотеки распространяются в виде исходников и особым образом подключаются к проекту. А потом я понял, что ещё не обязательно func иметь свой особый тип исключения, можно разные типы кидать. А потом я ещё понял, что так и неметапрограммческий полиморфизм реализовать можно. В общем, это не то, что подходит Лайси. Это совсем не то, Лайси не про это. Я подумал и решил, что пусть исключения будут, но они не будут возращать каких либо данных. Просто будет конструкция:
try {

}
except {

}

Где в случае исключения код из try перейдёт в except.
Ну а зачем вообще исключения нужны? Я на си писал и мне было не так уж и плохо без исключений. А на питоне исключения мне очень понравились, но и там я не использовал весь их потенциал. Я просто делал
try:
todo
except:
pass

или подобное. Хахаха, мои сишные мозги!
В общем, Лайси сильно меняется, пока ещё не реализован полностью. Вот так. Типы proc и func так же останутся, наверное на уровне ABI в func первым аргументом просто будет идти указатель на некоторый контекст, где содержатся данные для исключения. И сами исключения будут реализованы, наверное, через setjmp+longjmp. Надеюсь это не сказится на скорости слишком сильно. Исключения хороши для дебаггинга, но и на си можно вполне нормально писать, дебажа через gdb. А к Лайси я хочу сделать усовершенствованный дебаггер, где можно будет смотреть значения переменных и много другого.
Anonymous No.1190
В иколайси, наверное, будет 2 типа оптимизаций:
0. Логические.
1. Платформенные.
Логические это всякие там избавления от лишних переменных, разворачивание циклов, предсказание всяких операций и подобное.
А платформенные это те, которые зависят от платформы:
0. SIMD.
1. thread.
2. OpenCL.
3. VLIW.
SIMD-оптимизации подойдут, когда происходят векторные операции, например:
a[:] := (b[:] + c[:])*dup(3)*dup(d[:2])
Если типы элементов этих массивов какой-нибудь поддерживаемый float, например, single, то через LLVMный asm можно загрузить b,c, 3 и d в соответствующие SIMD-регистры и просто провести операции.
thread-оптимизации подойдут для параллельного исполнения больших функций. Например:
a(arg0,arg1),,b(args),,c(args);
Это подразумевает исполнения a, b и c в неопределённом или параллельном порядке. Если функция будет довольно большая, то вполне можно перед вызовом через libpthread создать потоки и мьютексы, если нужны и исполнить их в разных потоках, а потом pthread_join.
Кроме того, each-конструкция на уровне байткода раскладывается в функцию и инструкцию:
a each d,e,f, где a — функция, а d,e,f — массивы, из которых надо составить все комбинации элементов.
OpenCL-оптимизации подойдут, если надо совершать очень много простых операций и если есть устройства, позволяющие быстро так сделать, например, для double в GPU.
VLIW-оптимизация это очень экзотическая, которую я не собираюсь реализовывать, оптимизация. Она позволит распараллелить вычисления для VLIW-архитектуры.
Anonymous No.1193
Оказывается, в LLVM есть векторные операции:
; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

define void @"funcname"()
{
.2:
%".3" = alloca <5 x i8>
%".4" = alloca <5 x i8>
%".5" = alloca <5 x i8>
%".6" = load <5 x i8>, <5 x i8>* %".3"
%".7" = load <5 x i8>, <5 x i8>* %".4"
%".8" = add <5 x i8> %".6", %".7"
store <5 x i8> %".8", <5 x i8>* %".5"
ret void
}

Этим и отличаются Array Type и Vector Type в LLVM. Это значительно упрощает разработку. LLVM-ассемблер, небось, ещё и сам может проводить SIMD-оптимизации?
Anonymous No.1194
Как я понял, векторный тип в LLVM может иметь такое положение в памяти, что элементы не будут идти одни за другим как в сишном массиве. А ведь в Laisi в статических массивах каждый элемент идёт один за другим, как в си. Это меня расстроило, но это не страшно, ведь Vector Type в Array Type можно преобразовывать только при передаче аргументов в функцию или, например, получении адреса какого-нибудь элемента. Придётся строить массив и по-элементно копировать значения.
Anonymous No.1197
Нужны ли в Лайси комплексные числа? Я думаю, что да. Вообще, я только вчера впервые использовал комплексные числа в программировании. И это для построения множества Мандельброта. Но мой ЯП делает так, чтобы много чего было из-коробки. У меня есть куча вспомогательных функций, таких как rotate, позволяющая вращать данные в массиве или биты в числе, popcount, считающий количество повторений в массиве или числе (эту функцию я недавно добавил в стандарт, который ещё не вышел и не уверен, а нужна ли она), со строками и просто итеративными данными replace, startswith, endswith, find, join, reverse, ceil, floor, round...
Пока я занимаюсь слайсовыми операциями на уровне байткод —> LLVM IR. Первая версия liblaisi будет написана на си. Она будет содержать функции для динамических массивов, ассоциативных массивов, операций для int, rat, и некоторых встроенных функций.
Ассоциативные массивы будут сделать просто в виде структуры, содержащей ключ и данные, но потом, когда буду переписывать на Лайси, сделаю хеш-таблицы, бинарные деревья или ещё что-то. Я этого пока ещё не делал.
Anonymous No.1198
>>1197
Не нужны. Внешний подключаемый модуль с ними, не более. Они делаются с помощью конструкций любого языка за 10 минут и нужны очень редко.
Количества повторений в массиве вот уместны, да.
Anonymous No.1200
>>1198
Ну незнаю. Вот в питоне есть комплексные числа из-коробки. А мой ЯП подразумевает много из-коробочности. Может комплексные числа это действительно лишние и стоит сделать отдельную библиотечку complex, содержащую макрос для генерации комплексных чисел и темплейты для переопределения операторов. Но в таком случае нельзя будет что-то типа 5 + (ab + 2)1j или 0 + 3j.
И преобразовывать в тип комплексных чисел придётся так:
complex(basetype)(value0,value1)
или сделать переменную var с тип complex(basetype) и
var.re = value0
var.im = value1
Причём нынешний стандарт Лайси не позволяет преобразовывать несколько значений в тип, надо будет подумать как добавить это.
basetype это тип внутри комплексных чисел, чтобы те могли быть как double, s32 так и int, rat и другие числовые типы.
Думаю, библиотека лучше.

А про popcount я узнал из одной хабр-статьи. Там писалось, что инструкция popcount раньше использовалась для шифрования от АНБ. Потом её перестали включать, а недавно снова стали. В любом случае, я подумал, что это полезная функция и пусть будет в Лайси из-коробки.
Anonymous No.1221
Теперь я могу компилировать и такой код:
proc (u8,[]) @0 'funcname' {
%0 := alloca u8[2];
%0[0] := 3;
%0[1] := 23;

%1 := alloca u8[2];
%1[0] := 255;
%1[1] := 43;

%2 := alloca u8[2];
%2[0:2] := %0[0:2] + %1[0:2];

return %2[1];
}


Долго (4 дня) не мог понять, почему у меня получается undefined behavior, но потом я понял. Типичная ошибка новичка в LLVM, инсертил элементы в загруженный вектор, но его обратно не сторил в аллокированное место на каждой итерации. Попытка записать LLVM IR вручную помогает, так как включается логика.
Anonymous No.1228
Сравнение скорости моего ЯП и Си:
Моя функция на байткоде лайси:
proc (u32,[]) @0 'funcname' {
%0 := alloca u32[20];
%0[0] := 3;
%0[1] := 23;
%0[2] := 23;
%0[3] := 23;
%0[4] := 23;
%0[5] := 23;
%0[6] := 23;
%0[7] := 23;
%0[8] := 23;
%0[9] := 23;
%0[10] := 23;
%0[11] := 23;
%0[12] := 23;
%0[13] := 23;
%0[14] := 4323;
%0[15] := 23;
%0[16] := 23;
%0[17] := 23;
%0[18] := 23;
%0[19] := 23;

%1 := alloca u32[20];
%1[0] := 20;
%1[1] := 43;
%1[2] := 43;
%1[3] := 43;
%1[4] := 43;
%1[5] := 43;
%1[6] := 43;
%1[7] := 43;
%1[8] := 43;
%1[9] := 43;
%1[10] := 43;
%1[11] := 43;
%1[12] := 43;
%1[13] := 43;
%1[14] := 43;
%1[15] := 43;
%1[16] := 43;
%1[17] := 43;
%1[18] := 7656;
%1[19] := 43;

%2 := alloca u32[20];
%2[0:20] := %0[0:20] * %1[0:20];

return %2[18];
}


И похожая функция на си:
#include <stdint.h>

void ftest(uint32_t* out) {
uint32_t op0[20];
op0[0] = 534;
op0[1] = 534;
op0[2] = 534;
op0[3] = 534;
op0[4] = 534;
op0[5] = 534;
op0[6] = 534;
op0[7] = 534;
op0[8] = 534;
op0[9] = 534;
op0[10] = 534;
op0[11] = 534;
op0[12] = 534;
op0[13] = 534;
op0[14] = 534;
op0[15] = 534;
op0[16] = 534;
op0[17] = 231;
op0[18] = 534;
op0[19] = 534;

uint32_t op1[20];
op1[0] = 534;
op1[1] = 534;
op1[2] = 534;
op1[3] = 534;
op1[4] = 534;
op1[5] = 2356;
op1[6] = 534;
op1[7] = 534;
op1[8] = 534;
op1[9] = 534;
op1[10] = 534;
op1[11] = 534;
op1[12] = 534;
op1[13] = 534;
op1[14] = 534;
op1[15] = 534;
op1[16] = 534;
op1[17] = 231;
op1[18] = 534;
op1[19] = 534;

for (uint32_t i = 0; i < 20; i++) {
out[i] = op0[i] * op1[i];
}
}


Проверющий код:
#include <stdio.h>
#include <stdint.h>

static inline size_t rdtsc() {
static unsigned lo, hi;
asm volatile("rdtsc\n"
: "=a"(lo), "=d"(hi));
return ((size_t)hi << 32) | lo;
}

uint32_t funcname();

void ftest(uint32_t*);

int main() {
/*uint32_t a = funcname();
printf("%i\n",a);*/

size_t start = rdtsc();
uint32_t a = funcname();
size_t end = rdtsc();

printf("first %lu\n",end - start);

uint32_t out[20];
start = rdtsc();
ftest(out);
end = rdtsc();

printf("second %lu\n",end - start);
}


Компилирую с -O0 через кланг:
Моя функция выдаёт около 10000 тактов.
Сишная функция выдаёт около 1200 тактов.
Что же это такое? Мой ЯП в 8 раз медленнее Си в нынешний момент? Возможно. Но стоит включить оптимизацию -O3 и:
Моя функция: 120 тактов.
Сишная функция: 160 тактов.
Ура, я выиграл? Нет, ведь эксперимент не чистый. Я возвращаю одно значения и вполне вероятно, что LLVM оптимизатор сократил всё до инструкции с одним числом. Я пока не ввёл возможность по указателю из аргумента что-то делать. Надо будет потом проверить.
В любом случае я предсказываю, что без использования параллелизма на процессоре и через OpenCL, мой ЯП будет немного медленнее Си из-за исключений, setjmp будут копировать регистры, стек и всё, что нужно, что слегка снизит скорость. Конечно, на си тоже можно параллелить на всю, но это будет не из-коробки.
Anonymous No.1232
Я бы хотел уже доделать какую-нибудь реализацию компилятор Лайси, но мне не хватает времени. Я могу уделять 1-2 часа в день, но это будет вместо отдыха + мозг некоторое время кеширует код и архитектуру, мне это надо для эффективного программирования. Вот сделал я операции слайсами по числовым субоперандам, а надо ещё нечисловые и с большим количеством индексов, в 2D, 3D и ND. И пересылать callbacks для индексации в функцию для постройки вектора, чтобы отделять обычные массивы и динамические.
Anonymous No.1236
Хмм, я читал статью на хабре и понял, что в Лайси надо будет ввести какое-нибудь прилагательное для переменной-массива, позволяющей при изменении элементов, таких как del() (удалить элемент), чтобы элементы могли быть в другом порядке. Это нужно для тех штук, когда не важен порядок, таким образом, при удалении элемента в середине на его место может стать последний вместо того, чтобы передвигать весь массив. Но я пока не уверен с реализацией del для статического массива. А динамические массивы я собирался хранить в виде связанного списка блоков памяти из элементов. Но, наверное, там это тоже понадобится. Лишняя оптимизация не помешает, даже если для этого отдельное слово вводить.
Anonymous No.1250
Я смотрю на OpenGL и вижу очень плохую вещь. Но это ладно, ведь она старая. Но тогда я посмотрю на Vulkan и увижу то же самое. Может быть для видеокарт это и нормально — работать сразу с функциями отрисовки, которые создаются каждый раз переписанным драйвером API опенгла для функций видеокарты или чего-то такого... Но когда я напишу Иколайси (Когда? Делай, я сказал! Но как мне сделать?), я бы хотел написать свой растерайзер 3D- и 2D-сцен. Где просто кидаешь в темплейт функции некоторую структуру данных со всеми объектами (меши + ещё что-то или функции) и он выдаёт буфера, в частности, буфер пикселей, чтобы выводить. В таком подходе есть минус — как выводить сразу на экран? Но его можно решить расширениями. С библиотекой video для загрузки картинок и видео я тоже хотел бы сделать расширение, чтобы сразу на экран выводить и увеличить производительность.
Конечно, я очень плохо разбираюсь в 3D-графике, я максимум, что делал, так рейтрейсил одноцветные сферы, даже без освещения.
Мне стоит изучить OpenGL получше, посмотреть на Vulkan и DirectX, учесть сложные сцены рендеринга, типа шейдеров, зеркал, порталов, текстур с рендерингом, чтобы узнать как лучше делать свой растерайзер.
Лайси позволяет распараллелить исполнение, так что видеокарты смогут ускорить рендеринг, а темплейты позволяют в качестве чисел использовать любые типы, для которых определены используемые операторы.
Но это в дальнейшем. Я до сих пор не сделал иколайси, даже маленькую поддержку Лайси, хотя, намёки появляются.
И свою ГУИ-систему я буду делать с бекендом прежде всего на опенгле, так как его немного знаю и опенгл много где поддерживается.
Делать!
Anonymous No.1255
>>1250
>я бы хотел написать свой растерайзер 3D- и 2D-сцен
>В таком подходе есть минус — как выводить сразу на экран?
Там помоему минус в том, что у тебя нет доступа к растерезатору видеокарт. Можно посчитать на видеокарте, но оно всё-равно не сможет использовать хардверные блоки растеризации, только cuda-подобные блоки общего назначения, хотя в видеокарте есть далеко не только они.
Anonymous No.1259
>>1255
Не совсем понял тебя, но если это софтварная проблема и есть драйвер, позволяющий обращаться к блокам растеризации напрямую, то теоретически можно сделать оптимизацию для исколайси, чтобы пиксели считались не через OpenCL, а через эту видеокарту. Другой уровень абстракции. Но я этим заниматься не стал бы, наверное. А может быть и вовсе преобразовывать некоторый код в какой-нибудь промежуточный код шейдеров (? вулкан?), либо некие вычислительные шейдеры и пусть на них вычисляет.
Anonymous No.1264
>>1259
>а через эту видеокарту
Но там уже зашитый растеризатор-конвейер. Или ты пишешь свой медленный, или используешь обычный. Его алгоритм ты не поменяешь - а если он остаётся таким же, зачем тебе вообще писать свой драйвер, если можно использовать уже имеющийся через любой милое тебе api вроде ogl?
>в какой-нибудь промежуточный код шейдеров
Обрати внимание на spir-v.
Anonymous No.1269
Ладно, до параллелизма ещё далеко. Сначала мне надо продумать структуры динамического и ассоциативного массивов. Они будут обрабатываться в первых версиях библиотекой liblaisi, написанной на си.
Я пока понял только двоичное, префиксное деревья и хеш-таблицу. А всякие красно-чёрные, квадро- и октодеревья нет. Незнаю, можно ли натянуть квадро и окто деревья на мой ЯП, но если не получится, пользователи всегда могут сделать свою реализацию, ведь в стандарт я добавил штуки для работы с памятью в куче alloc, realloc и free или будет что-то подобное.
Вот сишный код для ассоциативного массива в виде префиксного дерева:
typedef struct _prefix64_t prefix64_t;
struct _prefix64_t {
void* key;
uint64_t keysize; //in bytes

void* data;

prefix64_t* nodes;
uint64_t NodeNum;
};

typedef struct _assoc64_t assoc64_t;
struct _assoc64prefix_t {
uint64_t valuesize;
_prefix64_t root;
}

Тут сам ассоциативный массив имеет размер элемента значения (для void* data в _prefix64_t) и само это дерево. В Лайси префиксные деревья могут быть использованы для индексации итеративных ключей, таких как u8[N], u8[], struct {s32 a; u8 b; double c}, проверяя каждый элемент. Но я вообще плохо разбираюсь в этих всяких структурах данных и не уверен, насколько это рентабельно. Может быть хеш-таблица эффективнее, но я всё-равно без лишних телодвижений не могу реализовать хеш-функцию для произвольного типа данных, так как си не поддерживает полиморфизм. Вот будет готов Лайси, тогда можно подумать над этим, ведь он поддерживает полиморфизм на уровне темплейтов (которые являются частью препроцессинга).
Вот код для динамического массива:
typedef struct _list64block_t list64block_t;
struct _list64block_t {
uint64_t size; //in elements
void* data;
list64block_t* next;
list64block_t* prev;
};

typedef struct {
uint64_t elmsize;
uint64_t num; //size in elements
list64block_t* first;
} list64_t;

Он состоит из связного списка блоков, которые имеют в себе указатель на элементы. Я предполагаю, что реаллокировать очень большие массивы было бы медленно, учитывая то, что для выделения памяти используется brk, который просто изменяет кол-во памяти, а не перемещает страницы или что-то такое, переносом данных занимается libc. Поэтому, я думаю, что когда динамический массив перейдёт размер в много элементов (несколько мегабайт), будет заполняться следующий блок. Кроме того, подход со связным списком позволит так же удалять и перемещать большое кол-во элементов без лишних затрат вычислительных устройств.
По хорошему стоило бы для каждого возможного типа сделать структуру ассоциативных массивов, динамических массивов, но, как я уже написал, для этого следует использовать Лайси с его полиморфизмом. Не хочу на ходу генерировать си-код для каждого типа. Хотя в прошлых версиях (которые сейчас на гитлабе лежат) я так и делал, только генерировал LLVM IR для каждого типа.
Алсо, ассоциативные массивы со статическим размером есть в Лайси и для них тоже нужна своя структура.
Anonymous No.1276
Я подумал, что, наверное, динамическим и ассоциативным массивам не место в стандарте Laisi, но место в liblaisi. Думаю, я сделаю так, что будут макросы list() и dict(), с помощью которых можно будет представить динамические и ассоциативные массивы. Не будет type[] и type_value{type_key}, но, может быть, в новых версиях добавлю синтаксические штучки, чтобы можно было сделать макрос вида type[...] или type{...} и уже препроцессор будет заниматься этим.
В итоге, получится, что Лайси это скриптовый язык генерации базового лайси-кода, который является по сути своей более чистым си, но со стандартизированным управлением памяти в куче (через операторы alloc, realloc и free/del (думаю, del)), с параллелизмом и простыми исключениями (без возвращения типа).
Ещё раньше я собирался добавить функцию concat, позволяющую конкатенировать массивные типы, потом понял, что можно использовать join, там можно делимитер указать. Но сейчас я дополнительно подумал, что логиченее будет, если:
list(t) var0 := [5,3,5];
list(t) var1 := [3,6,8];
auto var2 := var0 + var1;

будет конкатенировать var0 к var1. (auto это автоопределение типа по возвращаемому значению функции, либо выражения). Раньше я планировал в такой штуке произвести сложение всех элементов var0 к var1, но для этого и так есть индексация [:].
Также в liblaisi будет и int, и rat, которые динамические типы. Возможно и floatские типы: half, single, double, etc, но в будущем.
Пора делать компилятор Лайси.
Anonymous No.1277
Я тут посмотрел https://gamedev.ru/code/articles/VulkanTriangle?page=1 гайд по отрисовке треугольникчка на вулкане. Сам не пробовал, но выглядит очень чисто, без рудиментов старых десятилетий. Как я понял, основная рисующая штучка в вулкане это шейдер, без всяких лишних вызовов?
Но я думаю, что рендеринг должен отображаться в виде математически-алгоритмического кода, отображающего пиксельные данные прежде всего в некоторый буфер, а потом уже экран или окно. А не странные шейдеры или вызовы непонятных функций, где непонятно как что отредендерится. Лайси же, в своём стандарте имеет параллелизм. Мне надо сделать компилятор Лайси, а потом свой растеризатор. Хотя мой очень высокоуровневый. Если опенгл оперирует примитивами типа треугольников, линий, то у меня будут и кривые, и источники света или что-то подобное. Я плохо разбираюсь в 3D-графике, так что пока не уверен, а стандарт растеризатора имеет маленькие наброски. И сначала ГУИ, а потом растеризатор. Когда же я буду делать иколайси? Надо делать иколайси.
Anonymous No.1281
Теперь и такой репрезентованный лайси-байткод я могу компилировать:
u8 @1 'nname'

proc () @0 'funcname' {
%0 := alloca u8[5][3];
%1 := alloca u8[5][3];

%0[3][4] := %1[2][0];

return;
}

Есть глобальные переменные (@1 'nname'), которые не функции и есть индексация по большему количеству квадратиков. Теперь надо сделать такое, но в вектороном построчном способе. То есть, можно сложить из двумерного массива 2 прямоугольные области в разных местах и положить в третью. В связи с отставкой динамического массива в либлайси, в лайси-байткоде не нужно dup(), ведь теперь он может быть расчитан во время компиляции, а не исполнения. Его придётся всё-равно расчитывать во время исполнения для динамических массивов, но это уже будет записано в либлайси как перегруженный оператор/подобное.
Потом останется ввести try,except + raise; each и ещё парочку фич. И тогда компиляция лайси-байткода будет готова. Следующим шагом будет компиляция машинной части лайси-кода, а потом уже самое сложное — препроцессирование. Одновременно с этим я буду эксперементировать с OpenCL- и потоковыми оптимизациями. Это не так уж и просто. Не всегда можно просто запустить кучу потоков для некоторой функции, в некоторых местах нужны и мьютексы. Например, если для некоторого объекта с неатомарными операциями будут произведены операции. И всё это будет инициализироваться налету.
Anonymous No.1349
Работуют ли метаклассы в лейзи?
Anonymous No.1364
>>1349
Скорее всего да. Любой тип (класс, но без методов) может определяться через макрос (дефайн). А через макрос может определяться другой макрос, это препроцессирование как в си, но более направленное на кодогенерацию со всякими дженерик типами и другими вещами.

На днях собирался обновить на гитлабе иколайси, теперь он будет поддерживать где-то половину репрезентованного лайси-байткода. Но не сам лайси, даже немного пока не поддерживается, потому что я мало занимаюсь им.
Anonymous No.1374
>>989 (OP)
> Я пишу компилятор на питоне в связи с наличием хороших библиотек для парсинга.
ООП и процедурное программирование не подходит для парсинга.
Anonymous No.1375
>>1281
Nim наркомана.
Anonymous No.1385
>>1374
Не понимаю о чём ты, но в питоне есть библиотека pyparsing, с помощью которой я и парсю код. Для си я не нашёл библиотек для парсинга текста.
>>1375
Вряд ли. У меня более си-подобный. По сути, у меня си с современными численными типами и некоторыми фичами для параллельности.
Anonymous No.1397
Ой, уже неделя прошла с тех пор, как я собирался обновить иколайси на гитлабе.
Мне надо сначала хотя бы компиляцию исключений и обращение по элементам к структуруе и юнионы сделать, а потом уже заливать эту переписанную версию.
Anonymous No.1398
изображение.png (16 KB, 984x494)
>>989 (OP)
>https://gitlab.com/Ninikaita/icolaisi
onion адрес из описания не работает.
Anonymous No.1400
>>1398
Действительно. Указал, что сайт временно не работает.
Anonymous No.1401
В прошлый раз когда я скачивал репозиторий, там была папка с кодом на C(liblaisi?) и в доках были английский и украинский язык.
Добавь .gitignore чтобы в коммит не попадал кеш питона __pycache__ (а в коде на C были объектные файлы)
>>1397
>Для си я не нашёл библиотек для парсинга текста.
А они есть, но это не совсем библиотека.
Забавно, что ты пишешь компилятор в собственный байткод уже год(когда там был тред на лолифоксе?) или больше, но не разобрался нормально в вопросе. Столько сил в никуда!
Anonymous No.1406
>>1401
Да, доки временно удалены. Надо сначала довести до более рабочего состояния.
>Столько сил в никуда!
на самом деле немного, я очень мало времени уделяю icolaisi.
Anonymous No.1412
Вот потратил всего лишь час и уже научил компилировать такие несложные выражения:
proc (u8,[s32 a,s32 b]) function {
return 5;
};

в
; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

define i8 @"function"(i32 %".1", i32 %".2")
{
.4:
%".5" = alloca i32
store i32 %".1", i32* %".5"
%".7" = alloca i32
store i32 %".2", i32* %".7"
%".9" = trunc i32 5 to i8
ret i8 %".9"
}


На самом деле, такими темпами, иколайси был бы готов уже через 3-5 месяцев после выхода в Мае 2019.
Anonymous No.1414
Ты на C будешь переписывать?
Anonymous No.1418
>>1414
Не, на Лайси. Но это ещё может упереться в скорость. Если компиляция через питоновский код будет слишком медленной, то придётся думать как это решать. Но в таком случае я скорее просто упрощу правила парсинга и часть Лайси не будет поддерживаться.
Суть в том, что я хочу сделать библиотеку на Лайси под названием dapa (акроним от data parsing), она, наверное, будет похожа на pyparsing. Напоминаю, что лайси-библиотеки состоят в основном из лайси-кода или лайси-байткода, это не бинарные машинные библиотеки. Благодаря метапрограммированию на dapa можно будет парсить любые итерируемые данные, строки в частности.
При помощи этой либы я и буду парсить Лайси.
И вторая библиотека для компилятора лайси — laisi или что-то подобное, она будет заниматься компиляцией лайси. Эта библиотека может быть использована в icolaisi или, например, моём будущем ГУИ-вебкиллере-маркдаун-лангвадж со скриптами на лайси.
Третья библиотека — биндинг к LLVM, это будет просто промежуточный слой. Сейчас я использую питон-модуль llvmlite.
Anonymous No.1435
Теперь можно скомпилировать и:
proc (u8,[s32 a,s32 b]) function {
return b;
};

такой код.
Но только одну функцию.
Я запушил и вы тоже можете попробовать ./icolaisi test.lic -o out.ll
Эти файлы есть там как примеры.
Anonymous No.1474
Эх, вот бы делать иколайси, но я его не делаю. Если бы я сегодня целый день им занимался, то мог бы добавить и циклы, и вызовы функций на уровне laisi. Но я этого не сделал, ая-яй. Тем не менее, я сделал зачатки операций (с операторами), но ещё не закоммитил.
Ещё надо бы mctagfs поднимать, а лежит, а я свои картинки не могу просмотреть по тегам. Зачем я его вообще удалял и перекраивал сорсы, если он и так неплохо работал? Вот я дурачок. Мог бы использовать прямо сейчас. Джейсона мне захотелось, видите ли.

Алсо, я задумался над одной лайси-фичей, но в питоне. Ведь там есть такая штука как map. Вроде бы логично, что исполняя функции через него, можно делать это параллельно. И я находил какие-то модули, которые позволяли это, но сделано это было как-то топорно, там то ли целые процессы новые создавались, то ли ещё что-то. А я хочу, чтобы это было распараллелено по потокам. Может и попробую, ведь есть же модули для векторных операций, используя ЦПУ и ГПУ, например. Незнаю, может и такой модуль тоже уже есть, не уверен. Может быть, при реализации такого в питоне, я внезапно обнаружу проблемы, из-за которых не получится такое сделать в лайси, но это вряд ли.
Anonymous No.1494
dfs.png (85 KB, 1107x794)
Я восстановил https://gitlab.com/Ninikaita/mctagfs mctagfs.
Кладёте картинки в какую-нибудь директорию, назовём её /home/user/imgs. Делаете текстовый файл, где описываете:
kartinka0.png
abu
bordy
kaka

krasivayakarting.jpg
ne abu
gnu+linux
@
anime

plohayaimga.jpeg
abu
kaka
sperma
semen
aladin

someamv.webm
anime
manga
koshkodevochki
bydlokontent
ne animeshnaya pesnya


Говорите, мол ./mctagfs /home/user/img tags.txt /tagfs/mnt и получаете чудо. Поддерживаются операции открытия файлов, получения некоторых аттрибутов, чтения и чтения директории. То есть, писать нельзя.
Anonymous No.1562
Добавил немного поддержки строк. Теперь можно скомпилировать такой код:

proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
puts(s);
return 0;
};


в такой:

; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

declare i32 @"puts"(i8* %".1")

@"s" = global [4 x i8] c"abc\00"
define i32 @"main"()
{
.2:
%".3" = alloca i32
%".4" = getelementptr [4 x i8], [4 x i8]* @"s", i32 0, i32 0
%".5" = call i32 @"puts"(i8* %".4")
store i32 %".5", i32* %".3"
ret i32 0
}


И его, даже, можно скомпилировать в исполняемую программу clang out.ll -o out и запустить.
Anonymous No.1563
Переосмысление параллелизма:
А знаете, параллелизм, описанный в стандарте Лайси вызывает UB. А так ненадо. Короче, лайси постепенно превращается в мою версию си, а each-конструкция просто станет синтаксическим сахаром для for { for { for {} } }. Но это не значит, что я откажусь от параллелизма, наоборот, я сделаю только лучше. Легко узнать, функция имеет сайд-эффекты или нет. Если она не обращается к глобальным переменным, если не вызывает неизвестные функции (экстернальные), то она точно без сайд-эффектов. И такую функцию можно легко параллелить, что даст оптимизаций.
Anonymous No.1704
Теперь есть немного поддержки while:
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
while 1 {
puts(s);
};
return 0;
};

станет
; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

declare i32 @"puts"(i8* %".1")

@"s" = global [4 x i8] c"abc\00"
define i32 @"main"()
{
.2:
%".4" = alloca i32
%".5" = getelementptr [4 x i8], [4 x i8]* @"s", i32 0, i32 0
%".6" = call i32 @"puts"(i8* %".5")
store i32 %".6", i32* %".4"
%".8" = icmp ne i32 1, 0
br i1 %".8", label %".2", label %".3"
.3:
ret i32 0
}


Думал, это будет сложно, а оказалось, что за 15 минут решается.
Anonymous No.1705
>>1704
Ой, то есть:
; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

declare i32 @"puts"(i8* %".1")

@"s" = global [4 x i8] c"abc\00"
define i32 @"main"()
{
.2:
%".5" = icmp ne i32 1, 0
br i1 %".5", label %".3", label %".4"
.3:
%".7" = alloca i32
%".8" = getelementptr [4 x i8], [4 x i8]* @"s", i32 0, i32 0
%".9" = call i32 @"puts"(i8* %".8")
store i32 %".9", i32* %".7"
br label %".2"
.4:
ret i32 0
}

Кстати, этот код компилируется, так что лайси уже немного не только в моей голове. Но надо ещё очень много сделать.
Anonymous No.1736
Добавил немного поддержки while, do while и if elif else.
Например, такой код:
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
if 1 {
puts(s);
}
elif 0 {
puts(s);
}
else {
puts(s);
};
return 0;
};

Компилируется в такой лайси-байткод:
proc (s32,[s8*]) @0 'puts';

s8* @1 's' := &'abc\x00';

proc (s32) @2 'main' {
.1:
branch 1 .0 .3;
.0:
alloca s32 %0;
%0 := @0 call [@1];
goto .5;
.3:
branch 0 .2 .4;
.2:
alloca s32 %1;
%1 := @0 call [@1];
goto .5;
.4:
alloca s32 %2;
%2 := @0 call [@1];
goto .5;
.5:
return 0;
};

а он в такой LLVM IR:
; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

declare i32 @"puts"(i8* %".1")

@"s" = global [4 x i8] c"abc\00"
define i32 @"main"()
{
.2:
%".8" = icmp ne i32 1, 0
br i1 %".8", label %".3", label %".4"
.3:
%".10" = alloca i32
%".11" = getelementptr [4 x i8], [4 x i8]* @"s", i32 0, i32 0
%".12" = call i32 @"puts"(i8* %".11")
store i32 %".12", i32* %".10"
br label %".7"
.4:
%".15" = icmp ne i32 0, 0
br i1 %".15", label %".5", label %".6"
.5:
%".17" = alloca i32
%".18" = getelementptr [4 x i8], [4 x i8]* @"s", i32 0, i32 0
%".19" = call i32 @"puts"(i8* %".18")
store i32 %".19", i32* %".17"
br label %".7"
.6:
%".22" = alloca i32
%".23" = getelementptr [4 x i8], [4 x i8]* @"s", i32 0, i32 0
%".24" = call i32 @"puts"(i8* %".23")
store i32 %".24", i32* %".22"
br label %".7"
.7:
ret i32 0
}
Anonymous No.1737
Но зачем
Anonymous No.1738
Думал над реализацией типа list в liblaisi и что-то типа такого:
@ifdef not(LIST_BLOCK_SIZE)
@define LIST_BLOCK_SIZE 4194304 #bytes
@end

@define list_block(T) as struct {
T[] data;
int num;

list_block(T)* prev;
list_block(T)* next;
};

@define list(T,unordered := False,floatmul := False) as struct {
list_block(T)* root;

bool unordered := unordered;

func (T*,[self,int index]) __index__ {
int goti;
list_block(T)* node = self->root;
while (node != NULL) {
if (index - goti < node->num) {
return &node->data[index - goti]; #return element address
};
goti += node->num;

node := node->next;
};
raise; #index out of range
};

func (list(T),[self,list(T) added]) __add__ {

};

func (list(T),[self,list(T) added]) __mul__ {

};

func ([self,T data]) append {
@defne append_newblock(node) as {
node := alloc list_block(T);

node->data := alloc T;
node->data[0] := data;
node->num := 1;
};

if (self->root == NULL) {
append_newblock(node);
}
else {
list_block(T)* node := self->root;
list_block(T)* prenode;
while (node != NULL) {
if (node->num*sizeof(T) < LIST_BLOCK_SIZE) {
node->data := realloc T[node->num + 1];
node->data[node->num] := data;
node->num++;
return;
};

prenode := node;
node := node->next;
}
else {
append_newblock(prenode);
};
}
};

func ([self,int index]) del {

}
};

выходит. Я синтаксис не проверял программно и тут много чего нет. Тип list базируется на предположении, что при реаллокировании участки памяти могут копироваться, что приведёт к плохой производительности. А связные списки имеют поиск O(n). Поэтому я сделал связной список блоков с указателями на память в куче. unordered — флаг, позволяющий указать, можно ли менять порядок членов во время удаления и других действий. Чтобы не меммовить. floatmul — для умножения потом, может быть, сделаю. Если list([5,8,4])3, то это будет [5,8,4,5,8,4,5,8,4], но от floatmul зависит list([5,8,4])3.7 будет [5,8,4,5,8,4,5,8,4] или [5,8,4,5,8,4,5,8,4,5,8]. Не путать с индексацией, слайсами и dup. list([5,8,4])[:]dup(3) всё так же будет [15,24,12].
Ещё я думал над штуковиной с названием uniform или чем-то таким. Суть в том, что этот тот же многомерный массив, но индексируя не целыми числами, а флоатскими, будет происходить линейная, билинейная, N-линейная интерполяция.
Ещё я подумал не делать dict, а сделать отдельные типы ассоциативных массивов. hashtable, деревья всякие и что там ещё можно.
Алсо, int — бесконечное целое число, rat — бесконечное рациональное число.
Эх вот бы реализовать это! Ой, ещё парсить препроцессинг этот, ох!
Кстати, я подумал и решил, что T
это указатель на переменную типа T и можно ссылаться по ->, а T[] это тот же указатель, но ссылаться можно только индексацией. И в отличие от массив с определённым размером, тут нет встроенных исключений.
Anonymous No.1739
>>1737
Мне не нравится си, вот я и делаю свой ЯП.
Anonymous No.1741
Чтобы отрендерить треугольник рейтрейсингом, надо:
0. Спроецировать его на плоскость перпендикулярную взгляду (лучу из камеры для данного пикселя).
1. Проверить, попадает ли луч в круг, описывающий треугольник.
2. Если да, то проверить, попадает ли луч в треугольник.
3. Если да, то окрасить пиксель в цвет треугольника или
4. Высчитать угол падения луча на треугольник.
5. Просчитать освещённость относительно всех точечных или ортогональных источников света для этой точки. Если точечный источник света находится за треугольником, то его отбрасываем. Если ортогональный (лучи падают) падает на обратную сторону треугольника, то тоже отбрасываем.
6. Считаем свет относительно нормали и оптических свойств треугольника (количество отражения относительно угла падения).
7. Если треугольник прозрачный или зеркальный, отражаем и/или преломляем луч(и), считаем всё и для них.
8. Смешиваем полученный цвет со всеми от отражённых/преломлённых вещей.
9. Если треугольник является членом замкнутого тела, то можно устроить пару нюансов.
10. Можно постобработать картинку фрагментным шейдером.
Наверное.
Вопрос скорее в том, а как отрендерить поверхность Безье?
Лайси позволит спрограммировать такой рейтрейсер/растеризатор, ещё и выбирать тип float какой-нибудь, rat или ваш тип благодаря препроцессинговому полиморфизму или дженерикам, ну вы поняли. А opencl позволит исполнить это на всяких устройствах типа GPU. Конечно, это будет, скорее всего, медленнее, чем рендерить на самом GPU, но GPU это уже мёртвая технология. Пора абстрагироваться от них.
Я ещё подумываю над своей процессорной архитектурой, где можно будет проводить операции сразу над ranged количеством элементов. Я уже когда-то делал свою процессорную архитектуру, но не доделал. Она, кстати, была более классической, ещё и RISC, но одноядерной, без конвееров и других highлевел оптимизаций, ещё и без MMU. Проектирование процессоров это не так уж и сложно, как кажется. Для своей новой архитектуры, я планирую, чтобы для ranged-инструкции процессор как бы блокировался и переводил вычисления на легко конфигурирумый (в пределах разных микроархитектур) модуль распределённых вычислений с большим кол-вом АЛУ. Ещё хочу инструкцию для longjmp и вообще, инструкшион сет может быть сильно похож на лайси-байткод. Я пишу архитектуру в виде логических элементов, потому что всякие HDL плохо знаю и незнаю, какими инструментами можно преобразовать в хуман-ридейбл логические схемы. Вот бы ещё и реализовать их, только для этого нужны деньги. Ну там кремний добывать, плавить, напылять доноров и акцепторов и всё такое.
Anonymous No.1742
Смотрите на такой код-тест производительности OpenCL перед процессором:
#!/bin/python3

import torch

import numpy as np

import ctypes

import pyopencl as cl
from pyopencl import cltypes

import time
import sys

platforms = cl.get_platforms()
device = platforms[0].get_devices(cl.device_type.GPU)[0]
context = cl.Context([device])

start = time.process_time()

if sys.argv[1] == 'torch':
tensor = torch.randn((1000,1000),dtype=torch.float32)
tensor = torch.nn.functional.relu(tensor)
elif sys.argv[1] == 'opencl':
f = open('kernel.cl')
s = f.read()
f.close()

prog = cl.Program(context,s).build()
queue = cl.CommandQueue(context)

vector = np.random.rand(1000000).astype(np.float32)

mem_flags = cl.mem_flags
vector_buf = cl.Buffer(context,mem_flags.READ_ONLY | mem_flags.COPY_HOST_PTR,hostbuf=vector)

result_buf = cl.Buffer(context,mem_flags.WRITE_ONLY,vector.nbytes)

prog.relu(queue,vector.shape,None,vector_buf,result_buf)

result = np.empty_like(vector)
cl.enqueue_copy(queue,result,result_buf)

end = time.process_time()
print("Execution: {} secs".format(end - start))


и opencl-кернель:
float maximum(float a,float b) {
return a > b ? a : b;
}

__kernel void relu(__global float* in,__global float* out) {
out[get_global_id(0)] = maximum(0.0,in[get_global_id(0)]);
};

(Для стандартной max функции у меня выскочили какие-то ошибки)

Тут выбирается, использовать питорч (по дефолту использует цпу, может в куда, не умеет в opencl) или numpy с opencl. Тесты на моей машине показали, что при размере в 10000 элементов (шейп не важен) опенкл работает в 7-8 раз медленее, но когда кол-во элементов уже миллион, опенкл работает в 1.4 раза быстрее, а у меня слабый видивокартум.
Надеюсь, я ничего не напутал.
Anonymous No.1743
Поверхность Безье ограничивается кривыми Безье, так что, если кривые Безье можно легко проецировать, то достаточно к функции определения, попадает ли луч в треугольник добавить ещё эту кривую Безье. Но я не знаю, с какой стороны надо считать, попадает или нет. Я, в общем то, и в обычном прямоугольнике не знаю, но нашёл одну формулу:
(Ax - x)(By - Ay) - (Bx - Ax)(Ay - y);
(Bx - x)(Cy - By) - (Cx - Bx)(By - y);
(Cx - x)(Ay - Cy) - (Ax - Cx)(Cy - y);
или что-то типа такого. Если знаки одинаковые, то внутри, если 0, то на стороне точка. A, B и C — вертексы треугольника, x и y — координаты точки.
Ещё перед этим, для быстрой проверки сферой и радиусами, надо, наверное, использовать радиус не описанного круга вокруг спроецированного треугольника, а радиус описанной сферы вокруг всех контрольных точек поверхности Безье.
Кстати, LLVM может быть скомпилирован в SPIRV, так что, я предполагаю, для генерации кернелей OpenCL в Laisi будет достаточно только главную функцию __kernel генерировать в си-подобном .cl коде, а остальное в LLVM, если иное не предусмотрено инструментами SPIRV. Это удобно.
Вопрос ещё в том, как преломление и другие оптические искажения сделать для телесных предметов, рендеря только поверхости? Ещё желательно, чтобы это было order-independent. Есть вариант, чтобы когда луч входит в поверхность, ему присваивалось id (адрес, индекс) объекта и тогда, когда он переходит снова в поверхность этого же объекта, ясно, что он находился в среде со степенью преломелния этого объекта и пора пересчитать для следующей среды. И это не вложенно, ведь если одна среда внутри другого, эти среды всё-равно имеют свои коэффициенты преломления и нужно только 2 коеффициента — среды, из которой луч выходит, и в которую входит. Хотя, что делать, если поверхности пересекаются? В реальности вы такое не встретите, но в компьютерной графике ещё как! Возможно, это не важно в связи с бессмысленностью такого расположения предметов, кроме редких случаев всяких игровых график.
Вообще, для рендеринга на Laisi можно будет сделать классы для произвольного объекта, который коллбеками взаимодействует с лучём, так и условные шейдеры можно сотворить и всякие сложные штуки типа порталов с телепортированием лучей.
Эх, вот бы сделать icolaisi!
Anonymous No.1744
Kaustik.jpg (15 KB, 320x225)
>>1743
>как преломление и другие оптические искажения сделать для телесных предметов, рендеря только поверхости?
Угу. И ещё чтобы свет от источников света тоже преломлялся и искажался при прохождении через прозрачное.
Никак, тут нет никакого вопроса. Можно какой-нибудь костыль прикрутить, который в некоторых случаях будет выглядеть правдоподобно, но не более.
Anonymous No.1745
Оп, как ты относишься к тому факту, что у тебя в итоге ничего не получится?
Anonymous No.1746
>>1744
Ну это и не очень-то и нужно для компьютерной 3D-графики. Как я понимаю, для этого нужно из точки падения луча бросить N лучей во всех возможных направлениях и уже их значения сблендить на результирующий пиксель. Только если эти N для просто дисплея являются кол-вом пикселей в окне, то тут N надо уже подбирать вручную. Ещё и максимульную глубину вот размножений лучей, чтобы они вечно не веселилсь.
Anonymous No.1747
Ты понимаешь что ты поехавший? Ты даже пишешь нескладно
Anonymous No.1748
>>1747
Да че ты доебался? Челлвек свой язык создает, а чего ты добился?
Anonymous No.1755
>>1745
Он упоротый, поэтому он может чего-то добиться.
Anonymous No.1798
Конечно, блоки это хорошо, но я с ними пока не совладал. Мне надо сколлапсировать иерархичную блочную структуру в просто строку инструкций+меток. Я сделал костыль и его надо исправить.
Вот, например такой:
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
if 1 {
puts(s);
}
elif 0 {
puts(s);
}
else {
puts(s);
};
return 0;
};

код компилируется в такой лайси-байткод:
proc (s32,[s8*]) @0 'puts';

s8* @1 's' := &'abc\x00';

proc (s32) @2 'main' {
.0:
branch 1 .1 .2;
.1:
alloca s32 %0;
%0 := @0 call [@1];
goto .5;
.2:
branch 0 .3 .4;
.3:
alloca s32 %1;
%1 := @0 call [@1];
goto .5;
.4:
alloca s32 %2;
%2 := @0 call [@1];
goto .5;
.5:
return 0;
}


Но стоит добавить второй уровень вложенности блоков, как:
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
if 1 {
puts(s);
}
elif 0 {
puts(s);
if 1 {
puts(s);
};
}
else {
puts(s);
};
return 0;
};

тут, так и он скомпилируется в бред уровня:
proc (s32,[s8*]) @0 'puts';

s8* @1 's' := &'abc\x00';

proc (s32) @2 'main' {
.0:
branch 1 .1 .2;
.1:
alloca s32 %0;
%0 := @0 call [@1];
goto .5;
.2:
branch 0 .3 .4;
.3:
alloca s32 %2;
%2 := @0 call [@1];
alloca s32 %1;
.1:
branch 1 .2 .3;
.2:
alloca s32 %2;
%2 := @0 call [@1];
goto .3;
.3:
goto .5;
.4:
alloca s32 %3;
%3 := @0 call [@1];
goto .5;
.5:
return 0;
};


Кстати, недавно наступил новый год. Надеюсь, хоть в этом-то году к лету будет готов хоть немного, но полно рабочая версия Иколайси, как раз годик исполнится стандарту, если за рождение считать дату его выпуска в свет.
Anonymous No.1803
Надеюсь правильно скомпилировалась, головка временно не варит.
incode:
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
if 1 {
puts(s);
}
elif 0 {
if 1 {
puts(s);
};
puts(s);
}
else {
puts(s);
};
return 0;
};


outcode:
proc (s32,[s8*]) @0 'puts';

s8* @1 's' := &'abc\x00';

proc (s32) @2 'main' {
.0:
branch 1 .1 .3;
.1:
goto .2;
.2:
alloca s32 %0;
%0 := @0 call [@1];
goto .11;
.3:
branch 0 .4 .9;
.4:
goto .5;
.5:
branch 1 .6 .8;
goto .6;
.6:
goto .7;
goto .7;
.7:
alloca s32 %1;
%1 := @0 call [@1];
goto .8;
goto .8;
.8:
alloca s32 %2;
%2 := @0 call [@1];
goto .11;
.9:
goto .10;
.10:
alloca s32 %3;
%3 := @0 call [@1];
goto .11;
.11:
return 0;
};

Он грязный и надо будет дополнительно пройтись функцией, которая снимет дубли и инструкции после unrechable-инструкций таких как goto, branch, return. конечно, я же не умею компилировать понастоящему. Не могу сделать сразу функцию, которая будет создавать чистый результат. Приходится сборщиком мусора проходиться, лол
Anonymous No.1838
Культ ГПУ рудиментарен и отвратителен, эта технология должна быть похоронена. Алгоритм не должен пересекаться с хардвейром. Будущее за софтрендером. И Лайси, когда будет создан его компилятор-интерпретатор icolaisi, поспособствует этому, ведь чтобы включить параллелизм, не нужно разбираться с OpenCL или CUDA, даже pthreadы можно оставить позади.
Уже сейчас я перевёл while, do while и if elif else на новый способ представления инструкций — блочный, как в LLVMовском API. Да, я мог и 2 недели назад это сделать, но сделал только сегодня.
Сейчас я занимаюсь аллокацией переменных и преобразованием экспрешионов, но всё-равно ключевой вещью в Laisi остаётся препроцессор, который почти полностью не готов. Ведь именно препроцессор в Laisi позволяет включать в программу laisi-библиотеки. Я, кстати, подумываю об отделении чистого Laisi от его стандартной библиотеки. Пусть юзер включает библиотеку @import std.*;. Немного бойлерблейта, но это не так уж и плохо, я думаю.
Всё-таки, мой ЯП не для скриптов. Типы из std: int, rat, list(T) и некоторые ассоциативные массивы типа HashTable или hashtable, деревья какие-нибудь, не буду обобщать в словарь.
Как я уже писал, макросы могут иметь аргументы с дефолтными значениями, например, unordered в list(T), чтобы разрешить перемещать предметы на разные места при удалении для оптимизации.
Что насчёт параллелизма, то вот ещё немного и начну им заниматься. А может и потом. В любом случае, это не так уж и сложно. Надо функцию проверить на то, чтобы там не было сайд-эффектов и тогда можно даже мьютексы не включать. Поддержку OpenCL я так же планирую, хоть ГПУ мне и не нравятся, но не выбрасывать же ресурсы!
Далее за std должна пойти библиотека io, которая позволит открывать и закрывать всякие файлы и потоки в памяти, да хоть сокеты и всё через один интерфейс. Ну а от неё небольшой аппендикс stdio, который даст определения stdout, stdin и stderr для этих ваших юниксов.
Anonymous No.1870
Добавил поддержку лист-данных для циферок:
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

proc (s32) main {
s32[3] a := [3,3,5];
s32[3] b := [8,6,5];
s32[3] c;

return 0;
};
Anonymous No.1943
>>989 (OP)
>Препроцессирование кода
Добавь препроцессирование на уровне AST, т.е после парсинга. Как в nim.
Алсо, надеюсь ты типы не добавлял?
Anonymous No.1944
>>1385
>Не понимаю о чём ты, но в питоне есть библиотека pyparsing, с помощью которой я и парсю код. Для си я не нашёл библиотек для парсинга текста.
Концептуально не подходит. Для парсинга нужен декларативный подход.
Anonymous No.1953
>>1944
> Для парсинга нужен декларативный подход.
Кажется, я прочитал какую-то хуйню. Не потрудишься пояснить, как ты пришёл к такому выводу? Если в императивном стиле циклом читать входящий текст и преобразовывать его в какие-то данные — это будет уже не парсер?
Anonymous No.1954
Какой же мир
Русский ужасен. В нём нет нематерных слов.
Тогда напишу странно.
Какой же мир странный(больше гнева). Никто не может сделать ни нормальный ЯП, ни плохой(в смысле блядский) 3D-редактор. Я попробовал блендер, это плохой 3D-редактор. Позиционирует себя как 3D-редактор, а сам умеет только в 2D-тела, хоть и с 3D-положением.
Мне что, самому писать свой 3D-редактор, софтрендер, геометрический движок? На си я не могу это реализовывать, потому что придётся на каждый чих отдельный макрос писать. Почему люди до сих пор не сделали такие продукты, которые бы понравились мне? Они странные.
Программирование сложное. Чтобы сделать 3D-редактор, надо одновременно делать компилятор языка программирования. И ладно, будь это в каких-нибудь 90-х, но с тех пор прошло 30 лет. Пока я копаюсь в основах, люди вокруг анализируют друг-друга нейросетями, увеличивая мозговые ресурсы в 20 раз, игры делают в 10 кликов и 50 клацаний, модельки в 4 клика, а картинки через нейроинтерфейс рисуют. Ненавижу вас, потому что я вам завидую.

>>1943
Мне кажется, это плохое решение. Ладно, если бы дефайнами у меня обозначались только структуры и импортирование библиотек, но ведь и полиморфизм у меня сделан при помощи препроцессинга, и функции с неограниченным кол-вом аргументов, темплейты.
>надеюсь ты типы не добавлял
У меня есть несколько основных типов — uN, sN, несколько IEEE 754 флоатов и 2 типа для функций, а к ним ещё можно суффиксы добавить, чтобы сделать их указателями или массивами.

>>1944
>Для парсинга нужен декларативный подход
Такой?:
farg = pp.Group(VarType + pp.Optional(name) + pp.Optional(pp.Suppress(pplit['assign']) + VarAssign)) | pplit['ellipsis']
funcargs = pp.Group(pp.Suppress(pplit["lrbracket"]) + pp.Optional(farg) + pp.Optional(pp.Suppress(pplit['comma']) + pp.Optional(pplit['lqbracket'] + pp.delimitedList(farg,pplit['comma']) + pp.Suppress(pplit['rqbracket']))) + pp.Suppress(pplit["rrbracket"]))
simpletype = (numbertype | floattype | ppkwd["int"] | ppkwd["rat"] | ppkwd["string"] | (ppkwd["proc"] + funcargs) | (ppkwd["func"] + funcargs) | name)





arrsize = (number | name)
ListSuffix = pplit['lqbracket'] + pp.Optional(arrsize) + pplit['rqbracket']
TypeSuffix = pp.ZeroOrMore(ListSuffix | pplit['ptr'])

def MakeSuffix(toks):
toks = toks.asList()

#print('MakeSuffix',toks)

suffix = None

if len(toks) > 0:
if toks[0] in ('['):
suffix = toks[1]
else:
suffix = toks[0]

return suffix

TypeSuffix.setParseAction(MakeSuffix)



LaisiData = pp.Forward()

StunDataMember = pp.delimitedList(VarType + name + pp.Optional(string),pplit['comma']) + pp.Optional(pplit['assign'] + pp.delimitedList(LaisiData,pplit['comma'])) + pp.Suppress(pplit['semicolon'])
StunData = pplit['lcbracket'] + pp.ZeroOrMore(StunDataMember) + pplit['rcbracket']
stun = (ppkwd['struct'] | ppkwd['union']) + StunData




Кстати, я сломал листданные, потому что мне надо индексацию делать.
Anonymous No.1969
>>1953
>Не потрудишься пояснить, как ты пришёл к такому выводу?
Чисто опыт.
>Если в императивном стиле циклом читать входящий текст и преобразовывать его в какие-то данные — это будет уже не парсер?
Будет парсер, и возможно - даже неплохой. Однако, императивный подход действительно не подходит для подобного, особенно если грамматика сложная, ведь муть из тысяч форов и ифов никогда не станет лучше, чем это:
sentence = p:phrase "." {return p}
phrase = w:word+ ws? {return w}
word = i:leter+ {return i}
leter = [a-z]i
ws = \s / \n \t
Anonymous No.1970
>>1954
>Такой?
Да.
Anonymous No.1971
Теперь можно дефайнить структуры и аллокировать их, но не взаимодействовать с их элементами.
proc (s32,[s8* str]) puts;

s8* s := &'abc\x00';

@define MyType as struct {
s32 a;
s32 b;
};

proc (s32) main {
MyType a;
return 0;
};


>>1970
Как раз такой он и есть на стейдже парсинга препроцессированного кода. Разве что, только два подобніх правила генерируются функцией в зависимости от аргументов.
Anonymous No.1977
У меня часто бывают if ((a && b) || (c && d)) {if (a && b) {...} else if (c && d) {...} ... }, а это WET!, можно записывать результат в переменные, но зачем, когда можно ввести в Laisi синтаксический сахар? Надо как-то метки проделать, чтобы после ифа шёл в соответсвующий блок, а потом в общий блок.
Anonymous No.2007
>>1977
Зачем? Просто используй логические операторы в функциях Или что у тебя там. В js можно сделать так:
// Типа лямбда
myfunc = arg => (a && b) || (c && d) && (f && g) || (r && s) && dosomething()

Мне нравится такой стиль. Взял из пролога, где подобными(правда покрасивее, но суть та же) вообще всё делается.
Пост отредактировал Anonymous
Anonymous No.2011
Стоит ли вводить в стандарт перегрузку элементов члена структуры другими именами?
Например:
@define vector as struct {
double[3] : (x,y,z) v;
};

То есть, можно будет обращаться по одному и том же адресу как по .x, так и по .v[0].



>>2007
Не понял.
А если надо сделать 2 разные вещи для (a && b) и (c && d), но одинаковую для них обоих?
То есть:
if ((a && b) || (c && d)) {
if (a && b) {
do_one();
}
else if (c && d) {
do_two();
}
do_all();
}
Anonymous No.2020
Что насчёт сахарка из >>1977, мне пока представляется вариант:
if ((a && b) => 0 || (c && d) => 1) {
case 0 {
...
}
case 1 {
...
}
...
}
Anonymous No.2056
Сейчас я делаю всё новым, с нормальными классами. Я добавляю новый слой обработки — парсинг будет происходить в свои структуры и только потом они будут преобразованы в байткод, это гораздо удобнее и быстрее разрабатывать. Сейчас я почти доделал опять if-elif-else, скоро перейду к while и do while.
Но у меня остаётся вопрос по for. Когда происходит for a in lst, как лучше сделать, чтобы a было псевдонимом для элемента из lst и таким образом можно изменять lst или чтобы значение копировалось, как в питоне?
Anonymous No.2073
Еле ввёл опять ифконды. Зато вложенность работает
Такой
proc (s32,[s32 a,s32 b]) func {
s32 abc;
if 1 {
abc := a*b;
}
elif 0 {
abc := a + b;
}
else {
if 1 {
abc := a;
}
else {
abc := b;
}
}
return a + b;
};

код компилируется в такой байткод:
proc (s32,[s32 %0,s32 %1]) @0 'func' {
.0:
alloca s32 %2;
goto .1;
.1:
branch 1 .2 .3;
.2:
%3 := %0 * %1;
%2 := %3;
goto .10;
.3:
branch 0 .9 .4;
.4:
goto .5;
.5:
branch 1 .7 .6;
.6:
%2 := %1;
goto .8;
.7:
%2 := %0;
goto .8;
.8:
goto .10;
.9:
%4 := %0 + %1;
%2 := %4;
goto .10;
.10:
%5 := %0 + %1;
return %5;
};


В реальность я пока не компилировал, сначала введу опять вайлы-дувайлы, а потом примусь фиксить баги компилятора в LLVM.
Это похоже на карму. Я сделал плохую вещь раньше — парсил токены в байткод, а теперь токены в структуры, а структуры в байткод и пришлось менять всё. Со временем ещё один удар от такой "кармы" получу, потому что у меня есть функция OperandToBytecode (сейчас его нет в гитлабовской версии) и он возвращает тупл suboperand_t и инструкций, которые нужны для его получения. А надо блоки возвращать, так как эти инструкции потом смогут содержать ветвление, наверное. Сейчас я, конечно же, не буду это исправлять, потому что я недостаточно мудрый, а на самом деле я просто не уверен, будут ли ветвления во экспрешионах. Ведь я собирался добавить что-то типа a := if b {c} else {d} или a := try: func0() except: func1() except: func2().
Anonymous No.2136
Я, кажется, придумал как совместить мультиязычность и не предвзятость.
Пусть будет так, что есть переменные среды, которые можно задать через дефайн, а можно в рантайме и если есть функция __repr__ (которая будет использоваться функцией print), то в зависимости от переменных среды она может выдать текст на разных кодировках или языках, если такое реализовал автор.
Ещё я подумал над исключениями и, думаю, можно сделать так, чтобы в исключение бросалась функция и аргументы для этой функции, таким образом, можно понять что это именно за исключение. Такая функция может запринтовать, что за ошибка была и тоже, в зависимости от переменных среды.
А то я удумал добавить исключения без каких-либо опознавательных знаков. Так не стоит, наверное.
Anonymous No.2137
Залил новую версию. Добавил поддержку вайлов (теперь и с постинсами, которые исполняются после каждой итерации, в т. ч. и после continue, что позволяет сишный for записывать как s32 i := 0; while (i < n): {i++;} {инструкции}, а сам for сделать питоно/баше-подобным).

Например,

proc (s32,[s32 a,s32 b]) fnc {
s32 abc;
while 1: {abc := a + b;} {
abc := a*b;
}
return a + b;
};


такой код компилируется в такой лайси-

proc (s32,[s32 %0,s32 %1]) @0 'fnc' {
.0:
alloca s32 %2;
goto .1;
.1:
branch 1 .2 .4;
.2:
%3 := %0 * %1;
%2 := %3;
goto .3;
.3:
%4 := %0 + %1;
%2 := %4;
goto .1;
.4:
%5 := %0 + %1;
return %5;
};


байткод или в

; ModuleID = "module"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""

define i32 @"fnc"(i32 %".1", i32 %".2")
{
.4:
%".9" = alloca i32
store i32 %".1", i32* %".9"
%".11" = alloca i32
store i32 %".2", i32* %".11"
%".13" = alloca i32
br label %".5"
.5:
%".15" = icmp ne i32 1, 0
br i1 %".15", label %".6", label %".8"
.6:
%".17" = load i32, i32* %".9"
%".18" = load i32, i32* %".11"
%".19" = mul i32 %".17", %".18"
store i32 %".19", i32* %".13"
br label %".7"
.7:
%".22" = load i32, i32* %".9"
%".23" = load i32, i32* %".11"
%".24" = add i32 %".22", %".23"
store i32 %".24", i32* %".13"
br label %".5"
.8:
%".27" = load i32, i32* %".9"
%".28" = load i32, i32* %".11"
%".29" = add i32 %".27", %".28"
ret i32 %".29"
}


такой LLVM IR.

Ох, только что вспомнил, что забыл добавить вайловский елсе. Но он всё-равно бессмысленен, пока нет поддержки break.
Anonymous No.2143
Добавил возможность вызова функции. Теперь снова работает
proc (s32,[s8* s]) puts;

s8* s := &'Hello, World!\n';

proc (s32,[s32 argc,s8** argv]) main {
puts(s);
return 0;
};

Хеллоу Ворлд, можно скомпилировать. ./icolaisi test.lic -o out.ll; clang out.ll -o out; ./out

Я думал, что закончу первую версию icolaisi к Маю, но почему мне не закончить к концу Марта? Надо попробовать.
Anonymous No.2148
Потихоньку добавляю обращение к членам.
Скоро можно будет даже библиотеки загружать и сделаю библиотеку io, stdio, std.

proc (s32,[s8* path,s32 flags,s32 mode := 0]) open;
proc (s32,[s32 fd]) close;
proc (s64,[s32 fd,u8* buf,u64 count]) write;
proc (s64,[s32 fd,u8* buf,u64 count]) read;

s8* s := &'Hello, World!\n';

@define stream as struct {
s32 fd;
};

proc (s32,[s32 argc,s8** argv]) main {
stream file;
file.fd := 1;
write(file.fd,s,14);
return 0;
};
Anonymous No.2149
>>2148
>return 0;
Не хочешь сделать как в паскалях - где вместо return выкидывающего из функции есть переменная result, в которую нужно записать результат?
Так rvo будет намного яснее и явнее, если нужно вернуть какую-то структуру.

И вообще это намного понятнее, записать:
result.x=123
result.y=124
exit // < если нужно выйти из функции тут

чем писать что-то вроде
Type temp
temp.x=..
temp.y=..
return temp

где могут вызываться какие-то явные и неявные конструкторы, операторы присваивания и ещё что-нибудь из move-семантики, если ориентироваться на си.
Anonymous No.2150
>>2149
А у меня как раз есть в стандарте такая фича!
Надо просто объявить функцию с именованным возвращаемым результатом:
proc (s32 result,[s32 arg0,s32 arg1]) {
if 0 {
return 5; #возвратить 5 вместо result
}
else {
result := 3;
return; #возвратить result
}
};

Только это равно как если бы объявить переменную где-то в функции и потом только её возвращать. А если человеку надо изменить состояние какой-либо переменной, находящейся вне функции, то пусть передаёт указатель на неё.
Anonymous No.2163
Хмм, нужен ли в Laisi юнион? Он мне кажется немного уродливым.
2 единственных применения, которые я ему нахожу — экономия памяти (когда 2 структуры объеденены юнионом и внешняя переменная показывает, что надо использовать) и некоторые структуры для хардварных регистров, типа каких-то таблиц системных вызов и чего-то такого.
Но точно ли это нужно в таком высокоуровневом нет ЯП как Лайси? Всегда можно буферизовать кол-во байт max(sizeof(type0),sizeof(type1)) в структуре и обращаться явно преобразовывая типы type0*(&structure.bufer)->members.
Anonymous No.2164
А приведи пример хвостовой рекурсии на лайзи для вычисления чисео Фиббоначи.
Anonymous No.2196
>>2164
Извини, хотел написать тебе сообщение, но тучка как раз умерла. А теперь я удалил пост, сохранённый в txt.
Но там по сути то же самое, как и в Си.
Anonymous No.2234
Пока меня тут не было, добавил немного поддержки импортирования модулей и
немного поддержки дженерикв.
Смотрите код:
@define vec!n! as struct {
s32[n] v;
};

proc (s32,[s32 argc,s8** argv]) main {
vec2 var0;
vec3 var1;
vec2 var2;
return 0;
};


Он компилируется в такой лайси-байткод:
struct {
s32[2] v;
} vec2;

struct {
s32[3] v;
} vec3;

proc (s32,[s32 %0,s8** %1]) @0 'main' {
.0:
alloca vec2 %2;
alloca vec3 %3;
alloca vec2 %4;
return 0;
};


Теперь надо научить макросы принимать аргументы, чтобы можно было написать vec3(fsingle) или vec5(bool). Но я подумал и может изменить скобки макросов с () на <>? Я тут недавно в C++ покопался и такие скобки выглядят нормально. Будет vec3<fdouble> вместо vec3(fdouble), чтобы не путать с вызовом функции или преобразованием типа.
vec!n!<T> это будущий прототип типа вектора библиотеки math. Не путать с std.vector, который будет больше похож на сипипишный std::vector.
Anonymous No.2236
А впрочем, что там делать.
Держите:
@define vec!n!<T> as struct {
T[n] v;
};

proc (s32,[s32 argc,s8** argv]) main {
vec2<s32> var0;
vec3<s8> var1;
vec2<u64> var2;
vec2<u64> var3;
return 0;
};

--->
struct {
s32[2] v;
} vec2_s32;

struct {
s8[3] v;
} vec3_s8;

struct {
u64[2] v;
} vec2_u64;

proc (s32,[s32 %0,s8** %1]) @0 'main' {
.0:
alloca vec2_s32 %2;
alloca vec3_s8 %3;
alloca vec2_u64 %4;
alloca vec2_u64 %5;
return 0;
};




Ваш навык программирования повысился до 5
Anonymous No.2238
>>989 (OP)
Лучше mctagfs доведи до стабильного состояния, ещё один высокоуровневый язык не нужен. Ada хватит всем.
Anonymous No.2239
>>2238
Не, на Лайси можно написать много чего, а mctagfs даже мне не очень-то и нужен.
Посмотри сюда: https://www.shadertoy.com/. Архаичный попиксельный вызов функций и всё без указателей. С помощью embedded laisi я собираюсь сделать новый формат видео (картинка/анимация + аудио + субтитры), где всё строится лайси-кодом. Я собираюсь снова добавить each-конструкцию в стандарт, так как вызов функций типа processpixel(pixelpointer[:],blablabla) вряд ли я пущу, есть некоторый проблемы. Лучше написать x,y in each w,h { processpixel(&image[y][x],...) }. С помощью этого можно будет в main сгенерировать какие-нибудь объекты, а потом уже опираясь на них рендерить картинку, перенося данные по выделенному внешней программой указателю на буфер. Не хочу сказать, что такое сможет заменить всякие webm и png, и у них, и у моей идеи есть свои плюсы и минусы. Но, по крайней мере, прикольным инструментом похожим на шейдертой станет.
А ведь потом мне надо будет и веб свой сделать, со своим гуи (на самом деле у меня уже разрабатывается гуи-библиотека, но на си, я потом перепишу на Лайси), а к нему я прикручу подобную технологию в виде эмбеддед лайси-кода и это будет как флеш. Можно и игры свои создавать и на мойвеб-сайтах размещать и выкачивать, и просто интересные штуки. Да, это даёт небольшие возможности SAAS, но не думаю, что такая проблема должна меня волновать. Разве сделал ли бы разраб не saas вместо saas, не будь у него возможности?
Кроме этого, можно и ядро целой ОС написать на Лайси, на замену Линуксу. Чтобы не писать тонны драйверов, можно сделать поддержку линукс .ko-модулей, конечно же.
И вообще, всю ОС можно сделать лайсишной. Представь, открываешь /usr/lib, а там вместо бинарных .so лайси-код и его скомпилированный кеш. И в небольшом уголке немного легаси-наследия в виде неплохих библиотек и прочих программ как SDL2, питона, баша. Хотя и их можно будет перекомпилировать в лайси-байткод.
Anonymous No.2240
P.s. Если я не умру от сердечного приступа или чего-то подобного.
Anonymous No.2243
>>2239
> Чтобы не писать тонны драйверов, можно сделать поддержку линукс .ko-модулей
А ничего, что их сам линукс перестаёт поддерживать не только от смены версии ядра, но и от каждого чиха в его конфигурации? Внутренее ABI у ядра нестабильное, модули не живут в отрыве от компиляции самого ядра.
Anonymous No.2244
>>2239
>что такое сможет заменить всякие webm
Я точно не уверен, но что-то мне подсказывает что эквивалентный по качество/размер кодек в одиночку можно лет десять разрабатывать даже примерно зная что и как нужно получить в итоге.
Хотя может быть сейчас наоборот можно выдрать наиболее удачные фильтры из нейросетки обученной по imagenet - и они будут в 10 раз лучше выглядеть, чем прибитые гвоздями трансформации блоков из vpx вроде вращения.
Anonymous No.2247
>>2243
Это, конечно, плохо. Мне нужно больше данных для оценки совместимости, но я не собираюсь их искать сейчас.

>>2244
Ну, как раз программа, которую я описал не является кодеком, она есть обычная программа с ограниченным интерфейсом.
>нейросетки
Вот это одобряю, нейросети и генетические алгоритмы могут помочь качественнее сжимать данные.
Тут больше проблема в том, с какой скоростью видео будет кодироваться и декодироваться.
Anonymous No.2249
>>2247
>с какой скоростью видео будет кодироваться и декодироваться.
С такой же. Я предлагаю просто взять порождённые нейросетью преобразования блоков вместо высосанных из пальца человеком. Вот в кодеках есть преобразование переноса, когда содержимое блока просто вбок уплывает вбок - есть поворот и ещё всякие. В vp9 много полос - из-за чего на низком битрейте прям видно как эти полосы выступают. В h265 диагонали в этих блоках. Просто человек их по сути от балды накидал, чтобы кое-как работала, а нейросеть может максимизировать эффективность и ортогональность блоков - чтобы они не дублировали друг друга и были более выразительны. Вот та фигота, которую автокодировщики порождают в самом узком слое - вот её нужно взять.

Есть ещё ультимативный способ - предварительно обученную сеть дообучать на конкретном видео - чтобы она выработала фильтры максимально подходящие для сжатия данного видео - вот тогда время кодирование станет катастрофичным, но качество скорее выше будет - потому что при кодировании мультяшных картинок оно выкинет все фильтры подходящие для ирл изображений и оставит очень лаконичные фильтры для сохранения контрастных границ.
Видео это ещё тот эверест, но на картинках можно за разумное время попробовать что-то сделать самостоятельно, возможно.
Anonymous No.2265
>>989 (OP)
А привязка для COBOL будет? Мне бы очень пригодилось, заодно можно попробовать внедрить на работе как замену Java.
Anonymous No.2266
>>2265
Кобол выходи за рамки моих знаний, но что я могу сказать, так это функции должны копировать или иметь похожий как у Си ABI функций (для типа proc, но не func).
Если у тебя в коболе библиотеки линкуются как для си-программ, то можно будет написать библиотеку на Лайси и скомпилировать в бинарную библиотеку и инкдулить оттуда proc как сишные функции.
Anonymous No.2267
А в каких прикладных сферах лейси опережает другие ЯП?
Anonymous No.2295
>>2267
Пока что никаких, так как его компилятор до сих пор не сделан. Планируется в Мае выпустить первую рабочую версию.
Но вообще Лайси годится для общего программирования, кроме разработки ядра ОС (там могут быть некоторые оговорки, так как я планирвал в Лайси внести поддержку собственной heap).
Anonymous No.2297
Что будешь делать, когда не взлетит, как и индусворкс?
Anonymous No.2302
>>2297
Бред же пишешь. Лайси это исключительно мой инструмент, который я смогу дать и другим людям, которым он понравится. Некоторые, может быть, будут делать даже библиотеки. Но, например, для ряда библиотек типа video, audio, math и прочих я планировал зарезервировать названия (что будет потом написано на сайте, который я восстановлю и попробую в клирнет пустить). С зарезервированными названиями, я не дам права другим программистам закачивать в дефолтный репозиторий лайси-библиотек на сайте код, если они хотят назвать свою библиотеку так и код мне не понравится.
Если смотреть на всякие игры типа Индусворкс, то они, вероятно, сделаны исключительно для денежной или иной выгоды. Никогда не понимал геймдеверов, которые "делают игру своей мечты". Они что, играть в неё собираются? Это уже почти, что разговоры с самим собой. Компьютерные игры, фильмы, сериалы это всё высокоуровневое общение, за которое, к тому же, надо платить ваши шлюхи нервно курят в сторонке. А что насчёт клонов майнкрафта, то это, скорее свего, проигрышный вариант. Люди имеют отношение копателя онлайн, блок стори и других ноунеймов к майнкрафту совсем не такое как ори и блинд форест к кастельвании и метроиду.
Так же никогда не понимал анонов, которые хотят себе голосового помощника, чтоб сказать сюжет фильма и он сгенерировал ганами своими видео. Ну это же бред! Пропадает вся ценность общения. Это всё-равно, что робосекскуклу заказать и жениться на ней как в недавно вышедшем россйском говносериале "Лучше, чем люди" (они даже запятую не смогли правильно поставить).
Anonymous No.2326
Что у laisi с метапрограммированием? Зачем нужен laisi, когда есть lisp?
Anonymous No.2327
В последнее время я начал делать память в куче, но там с парсингом проблемки, мда. Скоро конец Мая, надо успеть доделать первую версию.

>>2326
Лайси почти полностью полностью будет состоять из метапрограммирования.

>Зачем нужен laisi, когда есть lisp?
Чтобы я обустроил свою собственную инфраструктуру библиотек и юзер-софта.
Anonymous No.2328
>>2302
>Они что, играть в неё собираются?
Да. Я хочу сделать игру своей мечты для себя, и чтобы ещё несколько рандомов ко мне в мультиплеер заходили иногда. В единственное законченное мною поделие я наиграл в десять раз больше времени, чем потратил на его написание.
Если бы я хотел прибыли и денег - то я занялся бы чем-то куда более рентабельным и более предсказуемым, чем делать свою игру без команды (или даже с ней), которая в 19 из 20 случае будет убыточна. Игра даст обратную связь в лучшем случае через несколько месяцев, а в худшем через несколько лет - и скорее всего за то же время я бы больше получил собирая металлолом или занимаясь чем-то насколько же невразумительным. Глупо надеяться, что именно у меня получится лучше, чем у тысяч других.
Разговоры с самим собой тоже веду в виде дневника кстати.

>Скоро конец Мая, надо успеть доделать первую версию.
>Некоторые, может быть, будут делать даже библиотеки.
Давай, это может быть интересно. Писать свою библиотеку в десять раз увлекательнее, чем искать документацию и играть в телепатию пытаясь понять как использовать уже имеющуюся.
Anonymous No.2336
Я ввожу void тип. Он будет использоваться и разрешён только в виде void. Мне не очень это нравится, это архаизм от си.
void
имеет такие свойства, что его можно приравнивать к любому указателю и ему можно приравнивать любой указатель без явного преобразования указателей. Раньше я планировал использовать u8*, но такой подход может сбить с толку программиста, так как он подумает, что это указатель для байтов, а не для всего.

Память в куче:
alloc N/type — аллокировать N байт или тип.
ptr vary N/type,N/type — реаллокировать ptr, изменив его размер в первый аргумент и, опционально, сдвинув начальную позицию на второй аргумент.
del ptr — освободить память, если ptr это указатель, а если просто тип, то надо вызвать перегруженную функцию __del__.
Кстати, у меня будет подобие сборщика мусора, но на самом деле он будет просто вызывать del для переменных, которые уже не используются. Например, если в функции сделать вектор или аллокировать память и он никуда не будет передаваться (по указателю, возвращаемым аргументом или в глобальную переменную), то будет вызван del для него.

Пока я буду использовать malloc, realloc и free, но потом надо будет написать свой аллокатор памяти в куче.

Все данные должны быть иницализированы.
(на самом деле нет, я потом в стандарте пропишу, что если в переменную не было записи, то при чтении будет инициализационные данные для данной переменной. Это лишает бойлерблейта приравнивать всё к нулю)
Anonymous No.2406
Добавил немного поддержки alloc. Теперь надо vary (но пока я использую realloc, нельзя будет смещать начало) и del, чтобы сделать vector из библиотеки mem (ранее std). Реализуя библиотеки я буду приближать реализацию компилятора Лайси, а потом просто добавлю окончательные штрихи, чтобы соответствовать стандарту.
Я собираюсь такие структуры в mem добавить: vector, list, hashtable, stack. vector имеет в себе указатель на элементы и кол-во элементов, каждый элемент идёт за каждым. list это связанный список блоков vector (нужна ли вообще такая структура? А может лучше вообще оставить list как просто связанный список?). hashtable это один из ассоциативных массивов (про деревья подумаю потом). stack это стек, но я не имею понятия, где он может использоваться. Я никогда не использовал, но в сипипишном он есть.
Кстати, в сипипи есть и всякие deque, но у меня можно будет менять начало элементов и в векторе, и в листе и так.
Надо будет ещё библиотеку sort сделать.
Anonymous No.2408
>>2406
Дек это и есть много маленьких связных векторов же. И плюсовый стек по умолчанию работает как дек внутри.
Anonymous No.2420
Думаю, надо будет потом из mem vector превратить в vector!N!d. То есть vector2d, vector3d, vector555d. И псевдоним vector для vector1d.
Только в Лайси, получается, придётся сделать так, чтобы можно было провести индексацию через много индексов. То есть vector3d v; v[y][z][x]. А это очень похоже на вызов обычной функции, разве что известно, что при индесации внутри возвращается указатель на элемент, когда вызов функции может произвольный результат выводить.

А в math будет vec!N!, который означает массив из N элементов и должен будет уметь взаимодействовать (через метапрограммирование) с mem.vector1d, а math.matrix и math.mat!h!x!w! с mem.vector2d.

>>2408
Надеюсь, у меня не возникнет подводных камней, когда свою систему аллокации памяти в куче буду писать, учитывая, что можно реаллокировать (vary), меняя начало.
Кстати, раз у меня своя память в куче, то следует и lenof() для неё реализовать, чтобы показывало сколько байт аллокировано.
Anonymous No.2421
>>989 (OP)
>Смерть эндчана
Вмысле смерти? - http://enxx3byspwsdo446jujc52ucy2pf5urdbhqw3kbsfhlfjwmbpj5smdad.onion/

>Компилятор-интерпритатор
А вот сейчас вообще не понял, разве языки не делятся на транслируемые и интерпритируемые(ну и ещё джава, что-то гибридное).

>Компилятор на питоне
Отлично ещё один слой абстракции.

Итог: К хуям не нужный язык, зачем его двигать на АИБ не ясно. Для практики написать язык - ок. Но юзать его никто не будет. Твой язык толком ничего не решает.

P.s. Я в программировании новичок, т.к. последнии два года тупо стагнировал и только сейчас взялся за Таненбаума, поэтому буду рад если ты оспоришь моё мнение и всё мне объяснишь)
Anonymous No.2425
>>2421
>Вмысле смерти
Я не помню, что тогда имел ввиду. Для меня и тучка недавно умирала (от рук админа же), хотя почти все аноны не заметили этого.

>Компилятор-интерпритатор
Это немного шуточное название. Почти все языки программирования и так JIT-компилируются, а интерпретировать можно не только код, но и исполняемый файл. Вот в люниксах можно написать текстовый файл с #!/path_to_intepreter и интерпретатором будет считать бинарник по пути. А ld-linux-... это интепретатор ELF-файлов. Вот и файлы Лайси-кода будут интерпретироваться в исполнение.
Языки программирования не совсем делятся на компилируемые и интерпретируемые. Тот же си можно интерпретировать через tcc (хотя он по сути компилируется без сохранения бинарника). А трансляция это вообще процесс перевода одного в другое. Можно транслировать какой-нибудь ЯП в Си. Можно в байткод, а можно в машинные коды.
Лайси-код предназначен для исполнения из исходников. Как минимум, ради компиляции именно на целевую систему, с её кол-вом ядер и вычислительных устройств (ЦПУ, ГПУ) и их расширений.

>Но юзать его никто не будет. Твой язык толком ничего не решает.
Я буду его использовать и этого достаточно. Это я людям дам возможность пользоваться своим языком программирования, а не они будут пользоваться в угоду мне. Сейчас Лайси ничего не решает, потому что компилятор ещё не написан. Значительная фича в Лайси это each-конструкции (они пока что удалены из стандарта), позволяющие распараллелить код. Принцип похож на использование OpenMP в C/C++.
Считай Лайси частью моей культуры, а не технологией.
Anonymous No.2428
>>2425
Ясно, спасибо за ответ.
Хотя кое какие вопросы остались. Компилятор переводит код полностью и дальнейший процесс (выполнение) интерпритацией назвать (как я думаю и если вы не имеете в виду интерпритацию между абстракциями) нельзя это уже именно выполнение.
Anonymous No.2449
>>2428
Интерпретацией исполняемого файла занимается линковщик (в случае ELF в линуксе), а интерпретация исполняемого файла это его исполнение на процессоре+ОС.
Интерпретация баш-скрипта башем это его исполнение внутри баша.
Так я думаю.
Anonymous No.2473
Лайси-кун, а как потрогать твой язык мимоанону? Скоро будет рабочая версия?
Anonymous No.2474
>>2473
К концу Мая собирался выпустить.
К сожалению, я очень много времени трачу на развлечения и псевдоразвлечения. Пора заканчивать с этим и делать Лайси, Иколайси и другие продукты, которые будут меня "кормить".

Вот что мне надо сделать:
0. Приравнивания в аргументах в определении макроса.
1. @undef
2. @for
3. Темплейты.
4. Улучшенное импортирование.
5. Улучшенный препроцессинг.
6. Включение бинарных файлов.
7. Вызов сайдэффектфри функций препроцессором.
8. Тип auto (автоопределение типа).
9. Энумерация чисел (рандж).
10. Оператор возведения в степень.
11. Поддержку float-чисел (хотя бы single и double).
12. Многомерные массивы.
13. Энумерации (как структуры).
14. func-тип.
15. vp (void pointer) тип.
16. Обращение по референсу (->). Как раз занимаюсь этим.
17. self-аргумент.
18. Аттрибуты переменных.
19. Видимость глобальных переменных.
20. Перегрузка операторов.
21. Инкремент, декремент.
22. Преобразование типов.
23. Операции сравнения.
24. Оператор in.
25. Исключения.
26. Перечисление элементов в массиве.
27. Псевдонимы для элементов структур.
28. Перечисление элементов структур.
29. lenof.
30. sizeof.
31. dup.
32. Списковые данные, их передача в функциях для перегрузки операторов.
33. Null, True, False.
34. Аллокатор памяти в куче.
35. Дефолтные исключения.
36. switch.
37. for.
38. each-конструкция.
39. abs, max, min.
40. Вывод ошибок синтаксиса

Как мы видим, фич больше, чем дней до конца Мая, так что я точно не успею.
Anonymous No.2507
Эх, вот бы дописать Иколайси!
Я хочу столько всего спрограммировать на Лайси...
Начиная простыми структурами данных типа mem.vector и math.matrix + функции сортировки и поиска в деревьях и хеш таблицы, заканчивая библиотеками ГУИ и графических движков и юзерспейс софта.
У меня есть своя система ГУИ и графический движок. Надо только перевести их на Лайси и выпустить официально.
Представляете, выходит Лайси, а у него уже есть библиотека для ГУИ.
Моя библиотека ГУИ представляет собой древо виджетов, а виджеты имеют в себе данные о локации и указатель на ВиджетДата. Можно 2 одинаковых виджета в разных местах поставить. У меня только простые-элементарные виджеты типа квадрата, круга, полигона и можно настроить события для клика или клавиша двойного, тройного, четверного и т. д. одинарного нажатия разными кнопками, с разной силой (если стилус для графического планшета), поворота и прочего. Можно инвертировать нажатие и сделать так, чтобы вызов был, когда нажимается или когда отпускается.
Но это пока что. Я собираюсь добавить ряд стандартных метавиджетов. Кнопка, слайдер, текстинпут, лейбел и некоторые другие. Внутри них сидят другие виджеты. Например, можно сделать виджет иконку с альфамаской и привязать его к кнопке и он станет кнопкой. Слайдер имеет 2 виджета — щель и двигающийся камушек. Про текстинпут и лейбел я пока не придумал. Думаю, лейбел будет очень мощным с возможностью писать и обычный, и жирный, и курсив, и цветной и т. д. текст. Ещё и с анимацией вывода текста по времени. Ещё хорошо бы уметь добавлять виджеты-фильтры для отдельных частей текста, чтобы можно было создать, например, спойлер.
Ещё хорошо бы научиться применять фильтры на виджеты, например, чтобы слайдер смог стать круговым. Для этого надо его как-то преобразовать через кривую Безье.
Позиция виджетов может быть привязана к лейауту, к пикселям, к части между виджетами или концом виджет (например, несколько пикселей вверх от нижнего конца окна) или к расстоянию на дисплее в метрах (или милиметрах).
Anonymous No.2529
Кажется, я допустил большую ошибку.
Я пытался скомпилировать этот код:
@define vector<T> as struct {
T[] elms;
usize num;
};

proc (s32,[s32 argc,s8** argv]) main {
vector<s32> v;

vector<s32>* vecp := &v;

vecp->num := 5;

return 0;
};

У меня получился такой байткод:
struct {
s32[] elms;
u64 num;
} vector_s32;

proc (s32,[s32 %0,s8** %1]) @0 'main' {
.0:
alloca vector_s32 %2;
alloca vector_s32* %3;
%4 := addrof %2;
%3 := %4;
%5 := %3->;
%5.1 := 5;
return 0;
};

Я хочу приравнять 5 по определённому адресу, но у меня тут нет адресов членов переменных, потому что у меня другой уровень абстрации, отличный от LLVM.
Видимо, придётся рефернс -> делать как бы индексом и кажды операнд в байткоде сможет ссылаться сколько угодно раз.
Anonymous No.2582
Выпуск полной версии Иколайси переносится на Июнь.
Anonymous No.2583
Добавил поддержку -> но дополнительно мог что-то сломать.

Можно скомпилить такой:
@define vector<T> as struct {
T[] elms;
usize num;
};

proc (s32,[s32 argc,s8** argv]) main {
vector<s32> v;

vector<s32>* vecp := &v;

vecp->num := 5;

return 0;
};

код.
Anonymous No.2593
Добавил немного поддержки vary, но код пока пушить не буду:
@define vector<T> as struct {
T[] elms;
usize num;
};

proc (s32,[s32 argc,s8** argv]) main {
vector<s32> v;

v.elms := v.elms vary 10;

return 0;
};
Anonymous No.2595
Добавил инкремент для int-типов.

Теперь можно скомпилировать такой код:
@define vector<T> as struct {
T[] elms;
usize num;
};

proc (s32,[s32 argc,s8** argv]) main {
vector<s32> v;

s32 data := 1234;

v.num++;

return 0;
};


Это надо, чтобы сделать темплейт для аппенда для mem.vector, там будет как-то так:
v.elms := v.elms vary typeof(v.elms[0])[v.num + 1];
v.elms[v.num + 1] := data;
v.num++;
Anonymous No.2602
Теперь можно скомпилировать и такой
@define vector<T> as struct {
T[] elms;
usize num;
};

proc (s32,[s32 argc,s8** argv]) main {
vector<s32> v;

v.elms := v.elms vary typeof(v.elms[0])[v.num + 1];
v.elms[v.num + 1] := 1234;
v.num++;

return 0;
};

код.

Надо теперь его как-то в темплейты организовать, чтобы делать аппенд/пуш_бек для любого вектора.
Anonymous No.2603
Компилировать?
Как ты компилируешь?
Anonymous No.2604
>>2603
Скачать код с гитлаба. cd директория.
./icolaisi test.lic -o out.ll
Далее, out.ll можно скомпилировать с помощью clang out.ll -o out

Компиляция происходит при помощи питон-модуля llvmlite. Но я сначала компилирую в абстрактный промежуточный код, который когда-нибудь станет байткодом. А уже его в LLVM IR.
Anonymous No.2605
Ладно, меняю := на =.
:= больше подошёл бы всяким странным языкам программирования, где пишут let (лолшто?), чтобы дать переменной приравнять значение.
Во всех юзер-френдли ЯП, таких как C, Python и других присваивание пишется через равно.
Anonymous No.2606
В паскале, по моему, присваивание как-то так делается.
Anonymous No.2611
>>2606
Паскаль вообще язык уродливый. С его-то then else begin end.
Всё-же, большинство привыкло присваивать через равно, я под него прогнусь, чтобы получить немного больше поддержки. А то вдруг Лайси станет популярным и будут потом жаловаться написал "ж=" вместо ":=" автор исправь.
Anonymous No.2612
>>2611
За то ошибки легче найти в коде
Anonymous No.2623
>>2605
>let
Так в Хаскелле раньше писали. Думаю, что это пошло из математики.
Пусть x это скорость...
Anonymous No.2624
Не уверен, нужны ли в Лайси исключения. Где они вообще используются? Зачем программе следить за своими ошибками?
Может быть, будет лучше убрать исключения и сделать assert? assert будет вызывать единую функцию, которая расскажет об ошибке.
Я хотел ещё сделать чтоб можно было типа if (try: ptr->elm[534]) { todo }. В таком случае, если бросится исключение, то выйдет false. То есть, если ptr это NULL или массив/вектор/etc elm слишком мал для такого индекса, то не будет никаких сегфолтов. Но зачем, если можно написать функции или макросы автоматической проверки указателей на NULL, а индексов на валидность. Можно даже сделать общий базовый макрос, который автоматически как-то раскроет выражение и проверит каждый член на NULL и на наличие индекса.
Но с другой стороны, это значит, что надо будет ввести функцию, определяющую, есть ли индекс в массиве. Так как у меня можно будет написать:
u32 num = 12;
u8 arr[num];

И если индекс к arr слишком большой, то всё.
Anonymous No.2632
15639795432460[...].jpg (46 KB, 273x440)
>>2624
>Где они вообще используются
Почти везде же в промышленных современных языках.

>Зачем программе следить за своими ошибками
Ошибки это нормально, но когда у тебя программа почему-то не работает или ещё хуже начинает зависить от фазы Луны, то это добавляет лишней головной боли.
Anonymous No.2638
>>2632
>Почти везде же в промышленных современных языках.
Странно, но сколько я писал на Си, а исключения не очень то и нужны были. Только на питоне исключения юзал в качестве костыля, чтобы проверять файл на наличие или чтобы не происходила запись вне пределов списка, индексы не хотел пересчитывать. try: инструкции except: pass
По-моему, для Лайси всё-таки достаточно только возвращаемого значения и опционально указатель на переменную для записи ошибки. Автору функции ещё можно приделать дефолтное значение Null, если он не хочет, чтобы незаинтересованным программистам надо было каждый раз прописывать Null.
Например, в случае для открытия файла можно вернуть Null указатель на структуру, как это делается в C, а ошибка пусть записывается в отдельную переменную (не в errno, программобоги упасите) по указателю в аргументах.
Для каких-то других случаев можно возвращать целую структуру статуса (можно анонимную).
А assert использовать для критических ошибок, которые совсем не должны быть и если есть, значит программа работает неправильно, надо исправить и вызывается глобальный обработчик ассерта. Для десктоп-программы она может в stderr написать о проблеме, строке в коде и прочем, для прошивки микроконтроллера по UARTу отправить то же самое, например.
Для какого-нибудь mem.vec assert (index > vec->num) "Error! Index is out of range".
Тогда и ABI типа func можно сделать как в C (точнее, как в LLVM), как тип proc Laisi, а сам proc убрать.

А исключения всегда можно реализовать и так, через setjmp+longjmp, хоть в Си, хоть в другом подобном ЯП.
Всё-таки мой язык программирования приближён к машинам как и си. Что оправдывает наличие глобальных переменных, например.
Если бы я хотел сделать ЯП, где каждый код — объект (почти как в питоне), то и глобальных переменных не должно было бы быть.
Anonymous No.2655
Сука, на этом долбанном питоне нельзя писать настоящие большие программы! По крайней мере, я так не умею.
Я не понимаю, какие типы принимает функция, я это не комментировал. Я наугдал пихаю значения, пока не перестанут возникать исключения.
Ещё эта мультипарадигменность... Тут такого нет, но недавно я написал несколько графических программ на питоне на заказ. И знаете, что я делал? Туториалы по PyQt предлагаю писать класс для приложения, что я и сделал. И даже функции для обработки нажатий клавиш в класс ставил. Но все другие функции, которые сохраняют конфиг, обращаются к интернету я делал вне класса и вызывал их. А сами эти функции пишут в глобальные переменные, дополнительно.

Вот в Лайси не будет никакой мультипарадигменности. Всё просто: есть структуры, а в них коллбеки, если нужны. Все переменные публичные. Глобальные переменные существуют
И никаких исключений. Только assert, приводящий к остановке программы (или вызову другой функции, если программист так обозначил). Если происходят ошибки, значит программа либо работает не верно, либо программисту надо вручную прописать проверку значений на валидность (что, по-сути и делают с исключениями с try except/catch, только менее муторно).
Anonymous No.2673
Из-за своей плохой архитектуры программы в питон-коде не получается ввести темплейты. Плохо.
Аргумент не имеет alloc.тип
Anonymous No.2674
>>2655
Привет, у меня вопрос по лайси. Этот язык интерпретируемый или компилируемый? На чем написан интерпретатор/компилятор?
Anonymous No.2675
>>2674
ЗЫ. Долблюсь в глаза, в оппосте написано "компилятор на питоне".
Тогда другой вопрос. А как на питоне можно написать компилятор на питоне, если сам питон интерпретируемый?

И еще, что такое лайси-байткод? Для его запуска нужна какая-то виртуальная машина? Как это работает?
Anonymous No.2677
>>2675
>А как на питоне можно написать компилятор на питоне, если сам питон интерпретируемый?
Не важно какая программа — интерпретируемая или компилируемая, она просто работает. Компилятор тоже просто работает. Вот так и компилирую. Парсю через pyparsing, LLVM IR накидываю через llvmlite.

>что такое лайси-байткод
В будущем это будет промежуточной штукой между Лайси и LLVM. Поддерживает некоторые фичи Лайси, но уже прекомпилированный, осталось только в LLVM IR и машинный код перевести.
Для его запуска не нужна будет виртуальная машина, а тот же компилятор-интерпретатор icolaisi (вмысле, он будет не только компилировать код, но и запускать его).

>Как это работает?
Сейчас никак.
Что ты можешь сделать, так это скачать код и исполнить ./icolaisi test.lic -o out.ll, где test.lic — тот файл в коде. Он работает и компилируется. Если попробуешь написать свой код, то скорее всего ошибёшься либо ты, либо компилятор и ничего не получится и ничего понятно не будет, так как компилятор ещё не умеет в вывод ошибок.


Думаю, мне надо начать потихоньку переписывать icolaisi на Laisi, а то с питоном ужас. Но пока я не введу темплейты, перегрузку операторов и ещё некоторые фичи, это сделать будет сложно!
Anonymous No.2678
А я придумал хорошую традицию. Если функция может принимать некорректные данные (например, матрицы на сложение/умножение с неподходящими размерами), то можно сделать такую же функцию, но приписать .check. И будет if (matmul.check(mat0,mat1,error=&err)) {matmul(mat0,mat1)}
Тогда программисту надо будет меньше в документацию заглядывать. Но всё-равно надо будет, чтобы узнать энумерации/дефайны для ошибок.
Anonymous No.2679
Думаю, выпущу icolaisi и Лайси где-то в Августе, а не в Июне, а то сложно. Я уже почти выгорел к Иколайси, но не к Лайси.
Кстати, .check можно сделать так, чтоб представлять и к операторам. mat0 *.check() mat1.
Anonymous No.2685
out.webm (87 KB, 1200x800, 00:00:08)
Вот, это моя недоделанная библиотека ГУИ, которую я собираюсь потом переписать на Лайси и сделать биндинги под питон и, возможно, C (а соответственно, много ЯП).
Она позволяет работать с очень низкоуровневыми виджетами, которые состоят из полигонов, текстурок и подобного. А коллбеки дают возможность: вызывать функцию перед и после отрисовки; фокус-ин и фокус-аут; курсор-хит; событие колёсика; событие ввода текста (или чего-то другого); drag-n-drop; потом, наверное, добавлю файлдиалог при помощи native file dialog nfd или какой-нибудь другой библиотеки; клики и нажатия на клавиши.
При этом события могут быть двойными (двойной щелчок), недвойными, тройными, N-ными (но это пока не реализовано), клик может быть инвертированным или нет (когда действие срабатывает по нажатию или по отпусканию), не путать с самими коллбеками нажатия или отпускания кнопки/клавиши. Курсор может иметь положение, силу нажатия (графический планшет), поворот и ещё ряд характеристик.
Будут 2 отдельные библиотеки. Первая позволяет быстро создать окно и сразу использовать приложение, а второе добавит часто используемые виджеты.
Насчёт второй, вы можете видеть это в видео. По середине кнопка, которая вызывает коллбек по нажатия. а выше и правее слайдер. Слайдер не доделанный, он должен реагировать, пока не будет отпущена кнопка мыши. Не смотрите на плохой дизайн, вместо этих квадратиков смогут быть любые виджеты, хоть другие слайдеры. Как тебе такое, Qt?
Также будет виджет контекстного меню (когда есть один виджет и показывается менюшка при наведении на него), виджет иконки, виджет лейбла, лайнэдита, текстинпута; виджет, где можно сделать столбец с элементами и выбирать один из них, аналог QListWidget из Qt.
Мне надо ещё лейауты разработать. Кстати, насчёт лейаутов. Есть же лейауты виджетов, а есть лейауты текста. В моей библиотеке будут поддерживать лейауты текста по всем четырём направлениям, то есть можно и японский наоборот.
Anonymous No.2687
Сейчас у меня нет доступа к нормальному интернету, делать нечего, поэтому посоветуйте книгу по питону, не для вката, чисто для хобби
p.s некоторые вещи знаю, но можно сказать все еще на начальном уровне
Anonymous No.2688
>>2687
А официальное руководство не подходит чем-то?
Anonymous No.2689
>>2688
Ты по руководству учил?
Anonymous No.2690
>>2689
Да. Но бидон был далеко не первым изученным мной ЯП.
Anonymous No.2691
E28CFD51-13BE-4[...].jpeg (88 KB, 736x920)
>>2690
Тогда и я попробую) какой у тебя первый язык программирования?
Anonymous No.2693
>>2691
Бейсик zx spectrum. Олсо, тред здесь слегка не об этом, если ты не заметил.
Anonymous No.2694
Что можно сказать по темплейтам. Я почти сделал их.
Смотрите на такой код:
@define vector<T> as struct {
T[] elms;
usize num;
};

@template with T func (s32,[T* v]) VectorAppend {
v->num = 5;
return 0;
};

func (s32,[s32 argc,s8** argv]) main {
vector<s32> v;

vector<s32>* vec = &v;

VectorAppend(vec);

return 0;
};


Он
struct {
s32[] elms;
usize num;
} vector_s32;

func (s32,[vector_s32* %0]) @1 'VectorAppend' {
.0:
%0->1 = 5;
return 0;
};

func (s32,[s32 %0,s8** %1]) @0 'main' {
.0:
alloca vector_s32 %2;
alloca vector_s32* %3;
%4 = addrof %2;
%3 = %4;
%5 = @1 'VectorAppend' call [%3];
return 0;
};

компилируется в такой байткод.
Плохо, плохо. Я ещё и забыл добавить изменение имени темплейтовой функции для разных типов...
Что насчёт бага, то я делал почти нормальный темплейт для добавления данных в вектор, но при компиляции в LLVM IR взялась левая переменная, которая передавалась в функцию и я не понял откуда она. Я решил переписать Icolaisi, но потом передумал.
Надо ввести полную поддержку темплейтов и перегрузок операторов, так как на них будет держаться вся инфраструктура!
Anonymous No.2744
Попробовал побыстрячку нарисовать график функции в питоне. Открыл матплотлиб ­— пыхтит, свистит, фокус на себя переводит, оси перемасштабирует, еле закрыл (когда мог убить).
Мне что, теперь нельзя поучить математику и физику в программировании, пока не доделаю Иколайси? Человечество в упадке.
Anonymous No.2745
>>2744
Поставь терминал с sixel graphics и выводи в него.
python -c 'import sys; import matplotlib.pyplot as plt; plt.savefig(sys.stdout)' | convert - sixel:-

Ещё можешь посмотреть gnuplot, он умеет sixel graphics сам.
Anonymous No.2747
>>2745
Каку менять на костыли? Не, лучше разработать пре-версию моей гуи либы на C++ и быстренько набросать биндинг для питона и там рисовать. На самом деле, биндинг для питона можно сразу делать, в следующий раз просто функции можно будет поменять и всё.
Кстати, есть вероятность, что потом модуль для плотов моей гуи станет официальным наряду с модулем обычных виджетов (кнопка, слайдер и другое). Только, раз есть 2D-графики, то почему бы не сделать и 3D-графики? А для 3D придётся уже отдельно рендерить всё, надо подумать, как это всё орагизовать красиво. В любом случае, рендеринг предполагается прежде всего на моём софтрендере.
А если есть модуль обычных виджетов и плотов, то можно сразу побольше официальных модулей наделать. Например, для отображения видео и картинок. Потом в своём монополичном мойвеб мойбраузере юзать их и одновременно в каком-нибудь просмотрщике картинок.
Главное — не переусердствовать и не начать добавлять виджеты, которые общаются к dbus, чтобы открыть сокет, а там из интернета подтянуть самомодифицирующийся код с генетическим алгоритмом и нейросетями, чтобы открыть файл в /usr/lib/myguilibnametopsecret/module.so, а окажется, что либа лежит в /bin/myguilibnametopsecret/module.so (лолчто?) и получится новый qt.
Anonymous No.2754
>>2747
Где ты там костыли увидел? Это вывод графики в терминал — костыли?
ИМХО, здесь ситуация противоположная: костыли — это организация полноценного GUI-приложения с event loop'ом для такой простой задачи как единичный вывод картинки.

Программа, выполнив требуемое от неё, должна завершаться. Для вывода графика интерактив не нужен — соответственно, его организация является напрасной тратой ресурсов, включая время пользователя и программиста.
Anonymous No.2756
>>2754
>вывод графики в терминал — костыли?
В некоторой степени, да. Конечно, можно выводить графику, но зачем использовать устаревший sixel? У него даже цвета шестибитные. А вообще, можно выводить сразу не только графику, но и какой-нибудь HTML или другой markdown-language. Когда-то я так и хотел сделать, но потом передумал.
Просто, надо один раз определить какой-нибудь новый и нормальный стандарт вывода в терминале и использовать его. Можно сохранить поддержку некоторых рудиментов, стилей некоторых и подобного, но не больше.

>такой простой задачи как единичный вывод картинки
С этим и matplotlib справляется, а мне нужны анимированные графики, чтобы смотреть, как функции изменяются.
Anonymous No.2757
>>2756
> зачем использовать устаревший sixel?
Потому что для статичных графиков его вполне достаточно, например. Зачем тебе в них более шести бит на цвет?

> надо один раз определить какой-нибудь новый и нормальный стандарт вывода в терминале
Уже было несколько попыток. Правда, в основном это делали с привязкой к локальной ФС (ссылками на файлы), что ставило крест на использовании данной фичи через последовательное соединение терминала (в т.ч. через ssh).

Нужен протокол, позволяющий не только выводить полноцветные изображения, но и соотносить их при этом с выводом текста, что с sixel graphics проблематично (позиция курсора после вывода изображения непредсказуема).
Anonymous No.2760
>>2757
Когда доделаю Иколайси и одну библиотеку ГУИ, может быть, напишу свой эмулятор терминала.
Рудиментами оставлю простой вывод текста (это мастхев, не будет же каждая программа пытаться во всякие последовательности для вывода обычного текста), вызов простых стилей типа цвета, жирноты и подобного. Насчёт curses не уверен.
А остальное — моё.
>привязкой к локальной ФС (ссылками на файлы)
Лолчто, зачем? Я бы сделал вывод картинок просто: сигнатура вывода картинки -> размер в байтах -> картинка PNG (или некоторые другие форматы). Данные получены, эмулятор терминала размещает в себе.
Anonymous No.2778
Я придумал добавить в Laisi новый тип ­— float. Раньше я планировал вводить fsingle, fdouble и прочие, но я подумал, что можно сделать дополнительно тип float. Он означает предпочитаемый float-тип. На обычных системах x86-64 это будет single, на какой-нибудь экзотической, которая не поддерживает single, но поддерживает double — double, а если это узкоспециализированный контроллер, который поддерживает только half, то будет half.
Можно ввести float, а можно ещё тип как float_max (только надо название получше придумать). Он будет означать наибольший предпочитаемый float-тип. Такое может быть полезно, если программист хочет иметь высокую точность, но при этом высокую скорость, то есть можно легко перейти от системы, поддерживающей максимум double на систему, которая поддерживает аж octuple.

Системо-зависимое поведение не плохое, ведь и usize+ssize используются много где, где есть связь с памятью, так как эти типы имеют статический размер + адрес в памяти не выйдет за их значения.

Перед исполнением icolaisi можно будет указать как воспринимать данные системо-зависимые типы: usize, ssize, float и max-float.

Так же я думал над тем, насколько хороша избыточность из-коробки. Я собираюсь в Laisi когда-нибудь добавить встроенные функции, такие как max, min, clamp, abs, popcount, ceil, round, floor. Так же есть функцие-подобные штуки как dup и sum, но это скорее относится к самому Laisi. А те функции можно будет использовать из-коробки и не подключать целый модуль math для того, чтобы склампить значение.
Но что если ввести больше и добавить поддержку из-коробки sin, cos? Тогда же можно ввести и математические вектора, матрицы, это будут встроенные дженерики. Не надо будет подключать math, чтобы посчитать dot между векторами или умножить матрицы друг на друга. Тогда можно и комплексные числа ввести и всё это.
Зачем вообще нужны библиотеки? Они нужны, чтобы подключать уже написанный код. Написанный код может быть разным, ладно, если он с сайд-эффектами, такое в ЯП как Laisi не нужно. Но если это синус, функция, которая встречается везде в мире? А матрицы? Что, есть какие-то предложения по умножению матриц как-то по-своему или с использованием новых функций для матриц? Так функции можно будет и так вводить.
Так же я понимаю, что не очень нужно вводить встроенную функцию типа сортировки пузырьком или какую ещё, так как сортировки могут быть очень разными. Но что если ввести sort, который попытается сам распознать, что это за данные и как их следует сортировать?
А может тогда ещё ввести и mem.vector, mem.hashtable и всё это в сам Laisi?
Из плюсов это может дать больший разворот для оптимизаций. Вот синус можно будет сразу преобразовать в инструкцию для процессора, если процессор поддерживает её. Вместо того, чтобы парсить фукнцию синуса, детектить её и заменять на инструкцию-синус.

Я, конечно, не буду вводить mem.vector и всё это в сам Laisi, но точно ли не нужно вводить sin, cos и другие тригонометрические функции, которые, к тому же, скалярные, в Laisi?

Всё очень сложно, но, думаю, не стоит делать язык таким перегруженным. Нормально, если Laisi будет поддерживать max, min, abs, clamp, ведь это почти логические функции, которые просто выбирают одно значение из других.
Anonymous No.2782
Кстати, когда буду делать библиотеку mem, то решил vector переименовать в array. Потому что вектор это более математическое, а у меня будет и array1d, и array2d, в общем array!N!d.
Надо ещё очень много фич ввести, чтобы использовать хотя бы такую библиотеку.
Anonymous No.2783
Всмысле, серьёзно, посмотрите.
Вот это
@define array!!d as struct;

@define array as array1d;


@template with V,T func ([V* array,T elm]) VectorAppend {
array->elms = array->elms vary typeof(V.elms[0])[array->dims[-1] + 1];
T[](array->elms[array->dims[-1]]) = elm;
array->dims[-1]++;
};


@define array!N!d<T,unorder=False> as struct {
u8 unordered = unorder;

T* elms;
usize[N] dims;

func (self*,T![N - 1]!)* append = template<self*,T![N - 1]!> VectorAppend;
func (self*,ssize index)* insert = template<self*> VectorInsert;
func (self*,ssize index)* delete = template<self*> VectorDelete;
func (self*,usize start,usize end)* resize = template<self*> VectorResize;
};

лишь кусочек кода для mem.array (не дописал, переписываю).

А всё, что может мой компилятор это:
@define vector<T> as struct {
T[] elms;
usize num;
};

@template with T func (s32,[T* v,typeof(T.elms[0]) data]) VectorAppend {
v->elms = v->elms vary typeof(T.elms[0])[v->num + 1];
v->elms[v->num] = data;
v->num++;
return 0;
};

func (s32,[s32 argc,s8** argv]) main {
vector<s32> v;
vector<s32>* vec = &v;

VectorAppend(vec,34);
#VectorAppend(vec,12);

vector<u16> ve2;
vector<u16>* vece2 = &ve2;

VectorAppend(vece2,156);

return 0;
};

и то, там откуда-то лишний inttoptr (LLVMовский) возникает, я не знаю, где он находится.
Я ещё и на питоне не умею программировать, не привык к объектам, а нормальных указателей нет.
Anonymous No.2784
gdfg.png (7 KB, 336x137)
Исправил баг с лишним inttoptr, там просто в глобальные local и labels надо было {} записать.

Запушил, теперь можно скомпилить и такой конд:
@define vector<T> as struct {
T[] elms;
usize num;
};

@template with T func (s32,[T* v,typeof(T.elms[0]) data]) VectorAppend {
v->elms = v->elms vary typeof(T.elms[0])[v->num + 1];
v->elms[v->num] = data;
v->num++;
return 0;
};

func (s32,[s32 argc,s8** argv]) main {
vector<s32> v;
vector<s32>* vec = &v;

VectorAppend(vec,34);
VectorAppend(vec,12);

vector<u16> ve2;
vector<u16>* vece2 = &ve2;

VectorAppend(vece2,156);

return 0;
};


Осталось ввести перегрузку операторов, мультивекторные вычисления, self-аргумент и можно будет начинать переписывать Icolaisi на Laisi. Как людям скомпилировать Иколайси, если им нуженн Иколайси? А я выложу прекомпилированную в LLVM IR версию и легко скомпилить да хоть клангом.

Кстати, гитлаб перестал пускать под тором. Пора переходить на новый сервис для выкладывания кода? Гитхаб подмайкрософтен, битбакет я ещё не пробовал.



И ещё, смотрите как можно будет без лишних слов делать dot и length над math.vec:
@define dot(v0,v1) (sum(v0.v[:] * v1.v[:]));

@define length(vec) (dot(vec,vec)**0.5);


Хотя я не уверен, насколько желательно простые функции заменять макросами.
Anonymous No.2785
>>1418
>Сейчас я использую питон-модуль llvmlite.
А есть си++ или си модуль llvmlite или ещё что-то подобное, чтобы он весил меньше чем 10 мб как в питоне, а не чтобы ставить гигантскую либу на тонны метров?
Anonymous No.2786
>>2785
Слинковать статически не думал?
Anonymous No.2787
>>2786
Мне в рантайме нужно.
Можно конечно через условный gcc (который весит не очень много) скомпилировать минимальный файл и его запускать, но хотелось бы прямо в память писать инструкции и там их запускать.
Anonymous No.2795
Еъ, вот бы доделать Иколайси, тогда я смогу писать и другой софт (как бы меня не разорвало на части. У моих почек и кишечника нет отдельного мозга, а сам я не децентрализован).

Надо как-то взять и добавить в темплейты поддержку троеточия, чтобы можно было вызывать темплейты с большим кол-вом аргументов, что нужно для io.print.
Anonymous No.2803
Я читал некоторые статьи про data oriented design и вычитал такую мудрость, что структура массивов быстрее массива структур, если обращение происходит к аналогичным элементам, так как тогда происходит попадание в кеш, а иначе нет или что-то типа того.
Я думал о том как сделать удобства для этого в Лайси. Например, я же собираюсь добавить псевдонимы в структуры, так можно сделать и псевдонимы для индексации.
То есть, чтобы в структуре
@define s as struct {
s32[200] a;
s32[200] b;
};

...
s var;


Можно было обращаться не как var.a[index], а как var[index].a. Это выглядит немного удобнее для чтения кода, но ведь всё-равно не получится взять указатель &var[index].
На самом деле мне бы реальных примеров, где полезен DOD. Я видел какой-то с умножением матриц, но не понял его до конца. К тому же, я хочу, чтобы Иколайси сам мог распознавать некоторые типы кода, чтобы вставлять нужные оптимизации. В случае с умножением матриц, можно сделать как бы шаблон в базе данных Иколайси, который показывает, что это умножение матриц и его можно оптимизировать путём переделывания под DOD или использованием специальной инструкции для умножения матриц, если процессор поддерживает это. Главное, чтобы функции из библиотеки math оптимизировались, если какой-то чел будет писать велосипеды, то я не обещаю, что они оптимизируются.

Кстати, аналогично я собираюсь оптимизировать тригонометрические функции библиотеки math.
Если я правильно понимаю, синусы и косинусы считаются через https://ru.wikipedia.org/wiki/Тригонометрические_функции#Определение_через_ряды линкрелейтед.
Вот так и будет записан код синуса и косинуса, мол ретурн сум(n,sinuschlen), но в иколайси будет запись, что если есть такая последовательность лайси-байткод инструкций, а целевая архитектура x86-64 с FPU, поддерживаемая sin и cos, то следует заменить на соответсвующие машинные инструкции.
Если представить чужие велосипеды, то тут могут возникнуть проблемы, так как велосипедист можно сделать не через sum() (sum — функция-оператор (как это назвать?) из Лайси), а через each-конструкцию, через for, через while, do while или вообще рекурсию (за рекурсию пусть и так будет наказан). И что мне, делать записи для всех комбинаций реализаций синусов? Не надо.
Anonymous No.2804
>>2803
>Если я правильно понимаю, синусы и косинусы считаются через
Я же пробовал и скидывал картинку, и получилось что процессор через fsincos как-то немного иначе считает синус, а ряд выдаёт в некоторых местах немного другой результат.
Вот это вычислительно лучше будет работать, мне кажется, посмотри при случае: https://ru.wikipedia.org/wiki/CORDIC
По крайне мере стоило бы попробовать.

>чтобы Иколайси сам мог распознавать некоторые типы кода, чтобы вставлять нужные оптимизации
Не сработает, скорее всего. Если будет какой-то профилировщик, который сможет запускать код и смотреть куда в памяти и в какой последовательности обращаются запросы - то может быть это возможно, но на стадии компиляции определить это звучит как что-то нереальное.
Например, если у тебя 120к частиц, то не нужно делать отдельный массив x-координат, и потом затем за ним массив y-координат - потому что (почти) во всех случаях они считаются вместе. Как оказалось быстрее всего вынести координаты и скорость в один массив (которые только на чтения в цикле взаимодействия частиц и где обновления кеша не будет происходить при многопоточной работе), ускорения в другой, и статичную информацию вроде цвета и другого мусора в третий.
Anonymous No.2806
>>2804
>CORDIC
Интересная вещь, надо будет попробовать. Я даже и не думал, что что-то такое может быть сделано так легко, а ведь это очевидно, что можно просто вектор поворачить N раз к ближайшему значению.

>через fsincos как-то немного иначе считает синус, а ряд выдаёт в некоторых местах немного другой результат.
Значит придётся вводить отдельный флаг компилятору, который позволит заменять нативный точный синус на машинный неточный.
Anonymous No.2824
Ого, тучка ожила.
Пока вы спали я там ввёл частично поддержку "..." в темплейтах.

А сейчас я придумал как перегружать операторы. Скину кусочек документации:
Перегрузка операторов и некоторых действий:
Операторы перегружаются через аттрибут переменной operator.
Пример:
operator func (strc,[const strc* strc0,const strc* strc1]) __add__ {
strc strcout;

strcout.a = strc0->a + strc1->a;
strcout.b = strc0->b + strc1->b;

return strcout;
};

Можно использовать и темплейты. Пример:
@template with T operator func (T,[T one,T two]) __add__ {
#TODO написать документацию с проверкой типов
};

В данном случае __add__ — субимя-псевдоним оператора +, которое используется для декларации переменных.
Другие псевдонимы см. в разделе операторов.


Переопределить оператор можно и для отдельной переменной, если её тип это структура, которая содержит операторный тип. Пример:
@define str as struct {
u8 a;
u8 b;

operator func (str,[str* s0,str* s1])* __add__;
};
Если __add__ не равен Null, то будет вызван он. Если равен, то будет вызван определённый ранее оператор, если определён.

Можно определить произвольную функцию, которая начинается с оператора.
Например:
operator func (bool,[str0 s0,str1 s1]) __add__.check {
if (s0.size != s1.size) {
return False;
}
return True;
}
... # спустя много кода
if (a +.check b) {
c = a + b;
}


operator также можно использовать как перегруженные функции.


Теперь это надо реализовать. Я хотел поскорее начать переписывать Иколайси на Лайси, но, думаю, надо сначала хотя бы сделать библиотеки io, math (зачаток) и dapa.
Anonymous No.2830
Добавил пример перегрузки операторов.
Вот:

@define str as struct {
u8 a;
u8 b;
};

operator func (str,[str in0,str in1]) __add__ {
str out;

out.a = in0.a + in1.a;
out.b = in0.b + in1.b;

return out;
};

func ([s32 argc,s8[][] argv]) main {
str out;
str in0;
str in1;

in0.a = 4;
in0.b = 8;

in1.a = 12;
in1.b = 1;

out = in0 + in1;
};


Это компилится в
struct {
u8 a;
u8 b;
} str;

operator func (str,[str %0,str %1]) @0 '__add__' {
.0:
alloca str %2;
%3 = %0.0 + %1.0;
%2.0 = %3;
%4 = %0.1 + %1.1;
%2.1 = %4;
return %2;
};

func ([s32 %0,s8[][] %1]) @1 'main' {
.0:
alloca str %2;
alloca str %3;
alloca str %4;
%3.0 = 4;
%3.1 = 8;
%4.0 = 12;
%4.1 = 1;
%5 = @0 '__add__' call [%3, %4];
%2 = %5;
};

Надеюсь, оно работает.

Это ещё не закончено, там надо с нейм манглингом придумать кое-что, а вообще, мне пора начинать полноценно писать библиотеку mem. Вспомнил, надо ещё self-аргумент ввести
Anonymous No.2841
Пока занимаюсь библиотекой mem. Мне надо сделать библиотеку mem; math (её начало, хотя бы); io, stdio и repr (для вывода данных, чтоб дебажить компиляцию); а потом dapa, чтобы, наконец, перевести icolaisi на лайси.

Смотрите, какой монстрик растёт:
@define array!N!D<T> as struct {
T[] elms;
usize[N] dims;
};


В моей дев-версии такое уже компилируется.
Но это ещё не самое страшное, вот подождите math.vec
Anonymous No.2884
Какой же у меня ужасный код Иколайси.

Ввёл оператор оверлоадинг — сломал темплейты. Починил темплейты — сломал оператор инкремента и декремента.

Наверное, мне стоит переписать icolaisi. Но смогу ли я сделать это? Сколько раз я уже пытался, в итоге возращался к старому коду.
Anonymous No.2908
Ладно, всё-таки у меня получается переписывать компилятор и выходит довольно неплохо.

Но случилась одно вещь. Когда-то я собирался написать свой собственный 3D-редактор, так как блендер угный, но Лайси так и не готов. Теперь мне придётся писать тридередактор на C++, а потом, когда-нибудь, переписывать на Лайси. Исход не очень хороший, но это из-за того что я мало времени уделял Иколайси.
Anonymous No.2911
15982092434540[...].webm (3620 KB, 854x480, 00:00:14)
>>989 (OP)
Ты пенсию получаешь или мамка кормит? Таким фуфлом безприбыльным занимаешься.
Алиса No.2912
Да вы чё все на бабле то помешались,русские блин,никто никаких смыслов больше не создает кроме одного сраного кеша (( собрались бы в группу устроили бы мозговой штурм,ребята в гугле не этим занимаются а поиском смыслов.
Anonymous No.2913
>>2912
>ребята в гугле не этим занимаются а поиском смыслов.
Не совсем. Они ищут идеи, которые привлекут массы пользователей. И корпорацией не поощряется поведение, которое отвлекает от этой единственной цели разраба. Типа фикса багов или черезмерное внимание к несущественным деталям.

Чем оп собственно и занимается. Он создал высокоуровневую обертку над ЛЛВМ, пропуская многие важные этапы построения, без которых будет постоянно упираться в переписывание и переделывание одного и того же.
https://www.wikihow.com/Create-a-Programming-Language
Anonymous No.2924
Когда на Лайси можно будет написать блокнот?
Anonymous No.2925
>>2924
Уже скорее всего https://github.com/xoreaxeaxeax/movfuscator
Anonymous No.2933
>>2924
Наверно, месяца через 4. Я уже запушил новую версию Иколайси. Теперь основные процессы происходят в объекте класса context_t.
Пока временно убран некоторый функционал, например, while, do while, if-elif-else, так как я ещё не добавил.
Теперь мне надо его перенести, затем некоторые операторы, снова сделать перегрузку функций и операторов через аттрибут overload (вместо прошлого operator), добавить возможность создания экземляра темплейта вне вызова (например, если надо приравнять к указателю на функцию). Затем лучше бы заняться conditional compilation, снова ввести @for, добавить всякие @ifdef, @elif и т. д. @if и @call пока делать не буду, оставлю на потом.
Затем более сложные вещи — мультивекторные выражения с индексами, ссыланиями и вызовами и всё это завёрнуто в dup. Потом надо будет сделать что-то с лист-данными, дикт-данными, научиться энумерировать числа в массив через оператор :, слайсировать индексы. Потом for, each и sum. И, наконец, встроенные функции типа abs, max, min, clamp, popcount, find, split, join и других.
И Лайси будет почти готов. Но не библиотеки. Мне надо сделать библиотеку mem для всяких векторов и хеш-таблиц, библиотеки io и repr для вывода данных в консоль и просто форматирования текста, библиотеку math для скалярных, векторных, матричных и других вычислений. Затем можно браться за мой графический движок. Он представляет из себя просто структуры графических объектов (меши, нурбсы, источники света, линии, полигоны), а рисует их бекенды. Сейчас у меня 2 бекенда — софтрендер-рейтрейсер и глсл-рейтрейсер. Планирую написать и софтрендер-растеризатор, специально для 2D-случая во всяких ГУИ или, даже, 2D-игр.
После графической либы, надо будет написать мою ГУИ-либу, а с помощью неё и стандартных виджетов можно будет набросать текстовый редактор.
Параллельно с этим, надо будет писать библиоткеи video и audio — библиотеки для декодирования и кодирования растровых (картинки и видео) и аудио- данных, соответственно. А где-то между ними должна быть библиотека для кодирования и декодирования видео-медиаконтейнеров.
Также не стоит забывать про такие важные системные библиотеки, как socket, thread и time.
Пока буду писать все библиотеки, мне надо будет и Иколайси переписать на Лайси, надо написать библиотеки laisi (laisi) и dapa (data parsing).
Anonymous No.2934
Как там в 80-ых, норм?
Anonymous No.2936
>>2934
Вообще-то, сейчас 20-е, неграмотный.
Anonymous No.2937
>>2936
>сейчас 20-е
Я ровно на это тебе и намекал.
Anonymous No.2938
В Лайси, кстати, будут else к циклам как в питоне.
Пример:
func () main {
u8 a = 0;

while 1 {
a = 5;
}
else {
a = 3;
};
};

Это уже работает. Чтобы доделать вайл-цикл, мне осталось добавить поддержку постинсов.

Кстати, недавно увидел бугурт питонозумерков, что else для for и while неинтуитивен. Не знаю что там про while, но для for они твердят, мол ему было бы логичнее исполняться, когда ничего не итерировалось вообще, а не после последнего элемента.
Мне, как бывшему сишнику, совершенно логично поведение else для for и while в питоне. Для меня это так и звучит, что если условие цикла возвращает True (сравнение в while, наличие элемента для for), то надо перейти в тело цикла, а если нет, то в else.
Так же и в Лайси будет. Условие истинно — в тело, нет — в else.
Anonymous No.2939
eto byl posledn[...].jpeg (884 KB, 1200x1785)
>>2937
Не так и плохо, как говорили в начале. Катаклизмы, войны, терракты, крысисы, у большинства людей жизнь ухудшилась на порядки, но меня задело не сильно.
Anonymous No.2940
>>2938
>Условие истинно — в тело, нет — в else.
Что поменяется, если убрать слово else и написать просто a = 3; после цикла?
Вижу вариант только с областью видимости, если есть возможность инициализировать что-то внутри условия цикла, как с if/for/switch в си.
Anonymous No.2941
>>2938
>Для меня это так и звучит, что если условие цикла возвращает True (сравнение в while, наличие элемента для for), то надо перейти в тело цикла, а если нет, то в else.
Я не понял, два блока (у while и у else) это что два цикла? А выход типо только по break или что?
Anonymous No.2942
>>2940
Я тоже сначала так подумал. Но это вроде как два цикла, я не уверен
Anonymous No.2943
>>2940
>если убрать слово else и написать просто a = 3; после цикла
Тогда к a будет приравниваться 3 всегда. Но если это будет в else, то при break else не исполнится. Как и в питоне, забыл об этом написать.

Я ещё забыл, что мне надо break и continue ввести в Иколайси...


>>2941
То есть это будет выглядеть так:
func () main {
u8 a = 0;

s32 i = 0;
while (i < 5) {
a = 5;
i++;
break;
}
else {
a = 3; # тут не исполняется
};
};


Код выше пока не поддерживается комплятором, скорее всего
Anonymous No.2944
Долго читать тред, ты уже исправил присваивание с ":=" на "=" или еще нет?
(потому что да, первое математично, но второе, де-факто, устоявшийся стандарт, к которому привычны все от Си-богов до Котлиноблядей как я)
Anonymous No.2945
Смотрите, какой у меня будет break и continue:
Такое:
func () main {
u8 a = 0;

while 1 {
while 2 {
a = 55;
break;
}
}
};

Компилится в такое:
func () @0 'main' {
.0:
alloca u8 %0;
%0 = 0;
goto .1;
.1:
branch 1 .2 .6;
.2:
goto .3;
.3:
branch 2 .4 .5;
.4:
%0 = 55;
goto .5; #!!!
goto .3;
.5:
goto .1;
.6:
};


А такое:
func () main {
u8 a = 0;

while 1 {
while 2 {
a = 55;
break,break;
}
}
};

Компилится в такое:
func () @0 'main' {
.0:
alloca u8 %0;
%0 = 0;
goto .1;
.1:
branch 1 .2 .6;
.2:
goto .3;
.3:
branch 2 .4 .5;
.4:
%0 = 55;
goto .6; #!!!
goto .3;
.5:
goto .1;
.6:
};


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


>>2944
Да. Я решил дать людям поблажки.


>>2946
Видимо, да.
Пост отредактировал Anonymous (Причина: видимо)
Anonymous No.2946
>>2943
т.е это синтаксический сахар для
loop {
if i < 5 {
a = 5;
i++;
break;
} else {
a = 3;
}
}
Anonymous No.2947
>>2945
А почему не сделать
break(2)
или
,
это оператор?
Anonymous No.2948
>>2947
Незнакомые с Лайси люди подумают, что можно вместо двойки переменную вставить. Лучше уж пусть будут через запятую столько бреаков, сколько нужно.

> запятая оператор
Ни в коем случае!
Anonymous No.2949
>>2948
А что будет если 3 штуки поставить когда циклов 2 ?

>Незнакомые с Лайси люди подумают
еще можно
break_2;
Anonymous No.2951
>>2949
>еще можно
Можно было бы, но уже не буду исправлять. Через запятую мне больше нравится. Вообще, когда-то давно я хотел дать возможность записывать параллельные инструкции через запятую, чтобы показать компилятору, что эти инструкции можно исполнять параллельно. Но потом понял, что это выглядит так себе, да и компилятор и сам может определить, какие инструкции можно исполнять параллельно.

>А что будет если 3 штуки поставить когда циклов 2 ?
Сообщение об ошибке компиляции.
Anonymous No.2956
>>2939
Я говорил исключительно в контексте сабжа этого треда.
Anonymous No.2957
Наверно это вкусовщина, и правда. Мне всегда нравилась максимальная краткость синтаксиса не в ущерб понятности. Синтаксис пользователь и так выучит рано или поздно, а писать ему одно и то же много раз придется.
Anonymous No.2958
>Незнакомые с Лайси люди подумают
Если бы я увидел break,break я бы подумал что запятая - оператор.
Anonymous No.2960
>>2956
Ок, в начале двадцатых Лайси был на стадии рождения, первые несколько лет он не был популярным, а в середине и конце стал совсем непопулярным, так как почти все люди разучились программировать. Им не до этого было, надо же где-то консервы искать.
Anonymous No.2961
>>2960
Скажите пожалуйста что это я такой тупой, и нихуя не понял.
Anonymous No.2962
>>2961
Я имел ввиду, что дцатые года правильно говорить не как (100 - N)-ные, а N-ные. То есть ты спросил "как там в 80-х", значит имеешь ввиду 20-х. Я тебе написал, как в двадцатых живётся.
Anonymous No.2963
>>2962
Это не я спросил, но зато теперь я лучше понимаю для чего ты свой язык пишешь.
Anonymous No.2968
Добавил поддержку continue. На самом деле это на пять минут, а не на день, но я не всегда выбираю верные микрорешения.

Такое:
func () main {
u8 a = 0;

while 2 {
while 1 : {a = 3;} {
continue,continue;
a = 5;
};
}
};

Компилируется в такое:
func () @0 'main' {
.0:
alloca u8 %0;
%0 = 0;
goto .1;
.1:
branch 2 .2 .7;
.2:
goto .3;
.3:
branch 1 .4 .6;
.4:
goto .1;
%0 = 5;
goto .5;
.5:
%0 = 3;
goto .3;
.6:
goto .1;
.7:
};


Что насчёт постинсов, то их можно наблюдать после ":". Это инструкции, которые выполняются по окончанию итерации цикла, в том числе и после континуе.
Сишный for (a; b; c) {} можно переписать на Лайси как a; while (b) : {c} {}.
";" с некоторых пор необязательна после if-elif-else и циклов, иначе было бы ужасно.

Теперь пришла пора заняться очень сложными выражениями. Например:
a[3][4][:][2:]-> = bfunc(5,3)[3:]->[:] * dup(str.(a,b,c)[3:5]);
Anonymous No.2969
>>2945
>Но на самом деле, это плохое решение, так как позволит быдлокодерам писать макаронезированные функции с десятью вложенными циклами.
Без вложенных циклов иногда не обойтись, они нужны, и возможность выйти из любого уровня вложенности нужна. Только конструкция break,break; вообще не очевидна, и некрасива, в других языках это делается так: break 2;
Anonymous No.2970
>>2969
>break 2;
И в итоге путать программистов, которые не знают, первый элемент это 0-й или 1-й?
Почему бы тогда не написать break 1, а break был бы равен break 0?
Лично мне программирование показало, что начинать счёт (номер) надо с нуля, а не с единцы и в своих записях я начинаю с нуля. Только для некоторых других людей пишу 1-й в качестве первого элемента.
Пусть лучше будут несколько break и continue.
Если буду писать туториал на своём сайте (надо поднять после того, как напишу Иколайси и парочку библиотек), то покажу, что делает break,break и continue,continue.
Anonymous No.2971
>>2970
>программистов
>которые не знают, первый элемент это 0-й или 1-й
На ноль поделил. По моему это стандартное поведение во всех языках, делать нумерацию с нулевого элемента. Что это за программист, который не знает об этом?

В примере выше цифра просто для примера, твои break, break заменяются на break 1 - это понятнее и привычнее, так как такая конструкция уже применяется в других языках программирования.
Anonymous No.2972
>>2971
>По моему это стандартное поведение во всех языках, делать нумерацию с нулевого элемента
Скажи это луа, у которого первый элемент начинается с единицы, а нулевой означает что-то типа None.

Вот так и твой пример break, откуда программисту знать — два бреака это break 2 или break 1?
Anonymous No.2973
>>2972
Дак я ж не навязываю ) Делай как считаешь нужным. Просто я привык к такому синтаксису и знаю, что похожий используется в других языках.

А если будет десять вложенных циклов, как будет выглядеть возврат из самого вложенного? break,break,break,break,break,break,break,break,break,break
Понятно, что десять вложенных циклов никто делать не будет, но если язык такую возможность предполагает, то должно быть и красивое решение сделать break из любого уровня вложенности.
Anonymous No.2974
>>2973
Незнаю, меня больше смущает запятая в этой конструкции, выглядит будто у нее есть значение.
Anonymous No.2975
Я надеюсь оп не СЖВ мусор, и не обижается на мнение посторонних, рандомных челиков. Похвально, конечно, изучать сложные вещи самостоятельно. Путем проб и ошибок. Я что, опять насрал?
Anonymous No.2982
Смотрите, какая сложность получилась.
Возьмём код:
func () main {
s32[10][10] a;
s32[10][10] b;
s32[10][10] c;

a[3][0:10] = b[7][0:10] + c[0:10][9];
};


или прекомпелированный "байткод":
func () @0 'main' {
.0:
alloca s32[10][10] %0;
alloca s32[10][10] %1;
alloca s32[10][10] %2;
%3 = %1[7][0:10] + %2[0:10][9];
%0[3][0:10] = %3;
};


Как видите, я складываю одновременно 10 элементов каждого массива и результат кладу в другой.

Но как это реализовать на LLVM? Надо сделать цикл, в котором сложить каждый элемент и от этого сложности. Если раньше я каждую инструкцию из второго кода компилировал отдельно, то теперь я понял, что мне надо проверять, а не слайсированы (slice, но на самом деле немного другое) ли операнды. И когда я дохожу до insassign_t или аргументов функции, мне надо взять и пройтись по всем операндам, которые не были скомпилированы.
На самом деле это не так уж и сложно и я почти сделал. Заодно разобрался, как будут работать мультивекторные операции. Каждому слайсированному индексу будет соответствовать номер.
Можно рассмотреть 2 варианта:
a[:][3] = b[:][5];
c[:][3] = d[8][:];

В первом случае каждому четвёртому элемента N-ного столбца (строки, ряда) приравняется шестой элемент b. А во втором все элементы девятого столбца.

При этом я решил отказаться от dup и сделать его по-умолчанию. То есть, умножение arr[:] ×= 5 (× это звёздочка) элементов массива на пятёрку будет происходить для всех элементов, а не для первого. Когда происходит оператор на два элемента arr[:] ×= ops[0:2], то будут умножаться поочердёно. Чётные на первый, нечётные на второй (с этими номерами запутаешься).

Также для всяких интов и флоатов надо будет завезти веткоризацию. LLVM уже имеет векторизированные типы, которые потом, скорее всего, вкомпилятся с использованием SIMD-инструкций. Когда-то я её делал, но тот код уже давно забыт и я не хочу его опять поднимать, всё-равно там почти то же самое, просто в конце надо будет векторизованные LLVM типых сложить/умножить/съесть, а затем обратно распаковать в массив (как я понимаю, векторизованные типы LLVM не обязаны иметь строгое друг-за-другом нахождение в памяти, а в массиы в Лайси обязаны. Как и в Си).
Пост отредактировал Anonymous (Причина: ×x×)
Anonymous No.2999
Я только сегодня узнал, что у питона, оказывается, слайсинг идёт как start:end:step. Заодно понял смысл конструкции ::-1 (реверс, раньше я думал, что это что-то типа :(:-1)).
Это же прекрасное решение! Его надо добавить и в Лайси. Тогда и встроенные функции reverse и fiter не надо будет вводить. Первый будет ::-1, а второй start.0:end.0:step.0.
В отличие от питона, в Лайси start:stop:end будет использоваться не только для индексации или деления на слайсы, но и для генерации ранджей. То есть [0:5] это [0,1,2,3,4]. А, соответственно, [0.0:1.2:0.55] это [0.0,0.55,1.1].

Но это может ввести небольшую путаницу, так как оператор энумерации и слайсинг можно перегрузить разными операторами. То есть, если есть структура, с перегруженной индексацией/слайсированием, то поведение var[0:12] и var[(0:12)] может быть разным, так как второй эквивалентен var[0,1,2,3,4,5,6,7,8,9,10,11]. В первом случае будет вызвана перегруженная функция с аргументами 0 и 12, а во втором 12 раз функция индексации со своим номером.
Anonymous No.3014
Всё же, спустя столько времени, я вижу, что я делал это не зря, раз есть такой прогресс, что можно компилировать хотя бы такое:

array.lic:
@define array!N!D<T> as struct {
u8 unordered;

T[] elms;
usize[N] dims;

func ([self*,T])* append;
};

@template with A func ([A* arr,typeof(A.elms[0]) data]) append {
arr->elms = alloc 5;

arr->dims[-1] = 45;
};


(код в append пока тестовый)

mem.lic:
@import .array;

@define string as array.array1D<u8>;

func () main {
array.array1D<s32> arr;

array.append(&arr,5);
};


Но ещё очень много надо сделать. Надо ввести больше индексации.
Anonymous No.3018
Во втором питоне, чтобы запринтить, надо было написать print string, теперь же print(string).
Автор(ы) питона руководствовались той же логикой, что и я со своими alloc N, P vary N, del N?

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

Ведь все эти мои alloc, vary и del можно сделать просто функциями или темплейтами. Так и sum и встроенные функции abs, min, max и прочее. Но получается, что мне надо в темплейты ввести функционал передавать не только переменные, но и просто куски текста как в макрос. Например sum(var[:],+).
Anonymous No.3023
От добавления фичей язык не становится тяжеловесным?
Anonymous No.3030
Я решил, что пусть будет отдельная liblaisi, которую придётся бойлерблейтом импортировать (в связи с существованием @ifimp), а она в свою очередь будет включать библиотеку thread, так как я осознал, что для управления памятью надо мьютексы лочить! Ну ладно.
Я уже добавил столько контента, что можно скомпилировать эти темплейты:
@template with T func (T,[T value]) abs {
if (value < 0) {
return -value;
}
return value;
};

@template with T func (s8,[T value]) sign {
if (value < 0) {
return -1;
}
return 1;
};

@template with T func (T,[T v0,T v1]) max {
if (v1 > v0) {
return v1;
}
return v0;
};

@template with T func (T,[T v0,T v1]) min {
if (v1 < v0) {
return v1;
}
return v0;
};

@template with T func (T,[T value,T vmin,T vmax]) clamp {
if (value < vmin) {
return vmin;
}
elif (value > vmax) {
return vmax;
}
else {
return value;
}
};


Они будут находиться в liblaisi.

liblaisi будет состоять из нескольких частей:
memory.lic — файл для управления памятью в куче. Пока что он будет использовать либсишные malloc, realloc и free, но потом я хотел бы запилить свой велосипед! Также я планировал ввести в Лайси такие правила для инклудов или импортов, чтобы можно было имортировать все файлы из некоторой директории и добавлять модули просто добавляя новые субдиректории. То есть хочешь поддержку не только для линдовса, но и для экзотической ОС — просто перекинь сабдиректори-бекенд в специальную директорию и без всяких правлений конфига.
Вообще я недавно хотел ввести такую фичу темплейтам, чтобы можно было передавать не только операнды, но и типы, чтобы можно было написать alloc(u8[54]) вместо alloc(sizeof(u8[54])), но это сложновато и я лучше сначала выпущу рабочую версию Иколайси+Лайси, а потом буду добавлять фичи, а то надоело без нормального программирования сидеть! Уж лучше первое время побойлерблейчу!
math.lic — abs, sign, min, max, clamp, ceil, floor, round.
bytes.lic — кодирование и декордирование интов в массив байтов?
assert.lic — возможно, функция для asserta? Но я хотел писать не assert(blablabla), а assert "blablabla" и чтобы в функцию сразу передавались данные строки, символа, стека. Я думаю, что надо будет ввести новую директиву @pragma или как-то так. С помощью неё переопределять некоторые правила. Например, заменять функцию, которая вызывается при asserte. Или запретить указателю приравнивать число (полезно для моего будущего веба). Или при ссылке по указателю вызывать другую функцию/макрос, которая проверяла бы, а выделен ли такой участок в куче или высветить assert. Это было бы важно для дебаггинга, так как ОС выделяет память страницами, а я мог бы по байтам определить диапазоны.
Anonymous No.3031
Кстати, я же ещё давно придумал такую фичу для mem.vector, как интерполяция значений по индексу. То есть, если есть mem.vector2D и у него элементы, то по индексам [4.56][2.4] произойдёт билинейная интерполяция между значениями, чтоб программисту не пришлось писать своё.

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

Я хочу сделать так, чтобы можно было взять и присвоить типу аттрибут, который виден из препроцессинга.
В таком случае mem.vector получит следующий вид:
@define vector!N!D<T,unorder = False,floated = False> as struct {
@ FloatIndex = floated;

bool unordered = unorder;

T[] elms;
usize[N] dims;

func ([self*,T])* append;
#...
};


То есть @ обозначает аттрибут для типа или темплейта.
Когда в темплейт индексации будет передан вектор с аттрибутом FloatIndex равным True, то он поймёт, что аргументы можно принимать не только интовые, но и флоатские.
Anonymous No.3041
Крутяк, сделал себе такой код:
@import liblaisi.*;

func () main {
s32 a = 5;

vp ptr = alloc(12);
};

(alloc находится в liblaisi).
Вы не сможете его запустить, так как всё-равно вам понадобятся библиотеки, которые я ещё не выпустил в открытый доступ.
Скоро можно будет начать писать реальные библиотеки и снова поднимать сайт по Лайси.
Для начала биндинги для SDL2, OpenGL, кусочек математической и mem библиотеки, а также io и repr.
Anonymous No.3045
Начал пилить библиотеку io.
В Иколайси ввёл энамы, но не полностью. Заново ввёл возможность обращения к элементам структуры.
Также увидил конфликты с посиксовыми open и прочими, но в Лайси есть возможность решить такую проблему через стринговые имена:
func (s32,[u8[] name,s32 flags,s32 mode]) posix_open 'open';

@define stream as struct {
ssize fd;
u8[] membuf;
usize size;
};

@define mode as enum {
READONLY;
WRITEONLY;
READWRITE;
APPEND;
};

func (stream,[u8[] name,mode m]) open 'io.open' {
stream ret;

ret.fd = posix_open(name,65,0);

return ret;
};

func () main {

};


Видите, что энамы без всяких префиксов типа IO_READONLY или MODE_READONLY? Я собираюсь сделать так, чтобы при операциях с типом enum были доступны имена из его дефайна и можно было написать mode m = APPEND, например;
Anonymous No.3046
Мне так придётся замакаронить код OperandToBytecode, чтобы добавить поддержку пересылки enum-значений в аргументы!

func (s32,[u8[] name,s32 flags,s32 mode]) posix_open 'open';

@define stream as struct {
ssize fd;
u8[] membuf;
usize size;
};

@define mode as enum {
READONLY;
WRITEONLY;
READWRITE;
APPEND;
};

func (stream,[u8[] name,mode m]) open 'io.open' {
stream ret;

ret.fd = posix_open(name,65,0);

return ret;
};

func () main {
stream s = open(&'filename\0',WRITEONLY);
};

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

Скоро мне понадобится снова заняться библиотекой mem, чтобы полноценно ввести mem.vector. Он понадобится для библиотеки io. А ведь он сложный! Там надо ввести и аттрибуты типов (FloatIndex) и пересылку большего кол-ва аргументов в макросы, и дефайн макросов с тем же началом имени, что и у другого макроса. Например, vector и vector1D. Я хочу сделать @define vector<T> as vector1D<T>, но эти имена сейчас считаются одинаковыми. Также ещё хотелось бы vector!N!Df<T> as vector!N!D<T, FloatIndex=True>. И надо будет ещё ввести возможность генерации темплейтов не при вызове, а при приравнивании указателя на функцию. То есть, пишу член структуры как func (...)* __index__ = template templatename<args>; Хотя и этом не совсем так. Я не собираюсь для mem делать члены структуры vector изменяемыми. Поэтому мне надо ввести оверлоадинг функций и чтобы они подключались к своим типам и с ними происходили все действия!

Там надо будет ещё ввести препроцессингового conditional compilation. Например, в оверлоаде для mem.vector функции индексации надо будет проверять, тип имеет аттрибут FloatIndex равным True или нет и исходя из этого превращать аргументы-индексы в инты или нет.
Это понадобится и для io. Вон там функция open принимает указатель на u8, а я хочу сделать темплейт, чтобы могла принимать и указатель на Null-terminated string, и mem.string (который дефайн mem.vector<u8>), и mem.vector<mem.string>. Насчёт последнего, мне не нравится посиксовое или линуксоидское движение, что директории разделяются через '/'. А если я использую не ASCII-совместимую кодировку? Поэтому для других гипотетических ОС надо ввести пересылку списка директорий/файлов (таким образом в лине '/home/user/file' будет аналогично ['/','home','user','file'] для open).
Не бойтесь, такая шиза не везде будет. Библиотеку repr я собираюсь сделать human-friendly и её format и repr будет принимать и использовать как бы ASCII-символы для форматирования. Например, format('text {}',number); Почти как в питоне. И внутри скобок аргументы типа format('text {o} {x} {X} {25} {%03}',number,number,number,number,number). Это для примера. Такое может означать в окте, в хексе (прописные буквы), хексе (большие буквы), 25-ричной системе счисления или заполнить нулями в три символа. Это уже не языковой стандарт, а реализация оверлоад-функций __repr__ для типов. Вот в библиотеке repr должны быть реализации для обычных типов uN, sN, списка и т.д.. А если автор какой-нибудь библиотеки захочет сделать __repr__ для своего типа, то он уже сам решит какие ему там аргументы нужны.
Anonymous No.3051
Придумал фичу для темплейтов.
Надо сделать так, чтобы они могли принимать не любой тип, а один из списка. Таким образом не придётся писать лишние ассерты.
Например, вот так будет выглядеть темплейт для умножения матриц:
@template with M0(mat!H!x!W!<T>), M1(mat!W!x!N!<T>) func (mat!H!x!N!<T> out,[const M0 mat0,const M1 mat1]) __mul__ {
x,y in each (0:N),(0:H) {
out.v[y][x] = sum(m0.v[0:W][x]*m1.v[y][0:W]);
}
};

Надеюсь, в коде ничего не перепутал, но всё равно я буду проверять это потом.
Anonymous No.3125
Ух ух ух работка поглотила, не получалось создавать Лайси и писать Иколайси.

Мне надо написать библиотку io (хотя бы черновую версию), чтобы написать библиотеку repr. И параллельно вводя в Иколайси всё больше поддержки Лайси.

Пока что она выглядит так:
extern s32 errno;

# as on bits/fcntl-linux.h
@define LINUX_RDONLY as 0;
@define LINUX_WRONLY as 1;
@define LINUX_RDWR as 2;
@define LINUX_CREAT as 0x40;
@define LINUX_TRUNC as 0x200;
@define LINUX_APPEND as 0x400;

func (s32,[u8[] name,s32 flags,s32 mode]) linux_open 'open';
func (s32,[s32 fd]) linux_close 'close';
func (ssize,[s32 fd,u8[] buf,ssize count]) linux_read 'read';
func (ssize,[s32 fd,u8[] buf,ssize count]) linux_write 'write';
func (ssize,[s32 fd,ssize off,s32 whence]) linux_seek 'lseek';

@define stream as struct {
ssize fd;
u8[] membuf;
usize size;
};

@define mode as enum {
READONLY;
WRITEONLY;
READWRITE;
APPEND;
};

func (stream,[u8[] name,mode m]) open 'io.open' {
stream ret;

ret.fd = linux_open(name,(LINUX_WRONLY | LINUX_CREAT | LINUX_TRUNC),0);

return ret;
};

func ([stream* s]) close 'io.close' {

};

func () main {
stream s = open(&'filename\0',WRITEONLY);
};


Вон те линуксоые хеджеры надо будет вынести в отдельные сабмодули, куда добавлять как файлы подбиблиотеки и делать поддержку хоть под линду, хоть под шиздоус или вашу велосипедную операционку на stm32-МКУ.
Anonymous No.3135
Кстати, недавно я узнал, что у питона почти нельзя делать уже определённые аргументы в функциях.
То есть вы можете написать def func(arg=[]), но arg будет с одним и тем же значение в начале каждой функции. Нельзя сделать что-то типа dev func(arg=datetime.datetime.now()) и жить нормально.
Хотя, возможно, там ещё хуже и определение аргументов можно переопределить, у меня как раз баг состоялся.

В Лайси будет не так. Вечно я тащу в Лайси фичи из других языков программирования, а потом оказывается, что их у языков на самом деле нет.

Вот в Си я очень много писал и продолжаю писать типы указателей как int var, а не int var, хотя по сишной логике второй это лучше. Так же и указатель на фунцию в си пишется как rettype (*funcname)(args). Не, ну вы видели? В Лайси я сделал нормально, звёздочка это суффикс типа.
Также в Лайси я собираюсь ввести, чтобы значения, присваеваемые аргументам функции по-умолчанию исполнялись при вызове, а не при объявлении (к тому же, Лайси это не интерпретируемый ЯП, так что так всё-равно нельзя).
Anonymous No.3136
>>3135
Поведение питона логично: выполняется дефиниция функции, и при её (дефиниции) исполнении присваиваются все предопределённые параметры. Если функции что-то нужно получить в runtime, это делается в её теле. Иное мне было бы неочевидно.
Anonymous No.3238
>>3135
You should buy webcam to stream you achievements.
Anonymous No.3248
golaya falshyva[...].png (2617 KB, 1953x2800)
Помню, ещё на том самом лолифоксе отправил пост с пикрилейтедом (чтобы заякорить взгляд) и писал шизоту, что в консолечке должен быть не stdin, stdout, stderr, а stdin, stdout, stdlog, stdtype.
stdin и stdout Для взаимодействия с файлами, а stdtype и stdlog для взаимодействия с пользователем и самой консолечкой. Тогда появилась бы возможность, например, запилить ГУИ-элементы типа кнопочек прямо в консоль и через stdtype получать их значения. А через stdlog посылать текст или команды по управлению ГУИ-элементами. И это было бы совместимо со многими современными консольными программами, так как переключение на ГУИ можно оформить через те же специальные последовательности, что и переключение стилей, цвета текста мигающие буковки.
И сейчас я засомневался в этой идее. Недавно я изучал бытность телеграма и знаете, там есть некие боты и они способные делать что-то подобное. Они умеют отправлять посты с текстом и дополнительно с кнопочками. + они умеют менять клавиатуру пользователя, создавая кнопки с подготовленными ответами. Например, "Да", "Нет"; numpad; "золото", "серебро", "медь". И все эти боты удачно создают SaaS и другие сервисы.
Идея, конечно, интересная. Но если её как-то впихнуть в скрипты. Можно было бы получить идеальный баланс между ГУИ и автоматизацией. Вы, наверное, понимаете. Когда открываешь ГИМП, чтобы перекодировать + подредактировать 5-8 изображений это ок. А если этих изображений 100 или 1000000, то тут следует использовать скрипты + imagemagick.
Во всех этих консольных программах есть проблема, которая отпугивает зумерков, привыкших к смартфонах с трёх лет. Надо запоминать сотни не совсем интуитивных параметров или читать многотомники документаций, чтобы прописать нужную команду. А что если как-то сделать эту часть ГУИшной? Пишешь for f in *; do ffmpeg --interactive; done и тебе выскакивает меню, которое настроит все параметры в удобном ГУИ и они будут настроены для каждого инстанста в этом цикле.
Хотя, это уже занятие для самой оболочки, а не для GUI в консоле, но зоны почти смежные.
А знаете, как ещё можно улучшить консольку? Ввести интерактивные скрипты. Можно сделать, чтобы у файлового менеджера было дополнительное окошко, где прописать пайпы между выделенными файлами и программами с опциями графически и ещё можно разделить пайпы для разных программ или промежуточных результатов. Вообще, я не поклонник интерактивного программирования как ноды в Блендере или блюпринты в юнитях всяких, но в данном случае это кажется хорошей идеей.

А то что там эти бедные африканцы. Им дали задание перерисовать миллион картинок, 1000 работяг на заводе достают свои сяоми и хуавеи и в debian gnu приложение консоле вводят команду вручную каждый раз. Зарабатывают копейки. А так можно на смартфоны запилить интерактивную консоль и один работник сможет выполнять работу всего завода и остальные сдохнут с голову
Anonymous No.3251
Немножко подчистил документация Лайси.
Немного стандартизировал контекст восприятия типа.
Также добавил, что в вычисляемые выражения идут side-эффект-фри функции.
Ещё map переделал на each.

Думаю, мне надо сделать парочку тестовых кодов и на них тренироваться весь Лайси компилировать.
Но сначала мне придётся изрешетать код, чтобы подогнать типы под новый и настоящий стандарт.
Anonymous No.3277
Я недавно рассматривал HTML и продолжаю убеждаться: какая же это шизофрения-то!
Вот поэтому мне и надо доделать Иколайси. Чтобы сделать Лайси, а потом маркдаун лангвадж и мой веб! С лайси-скриптами.
Не будет никаких глупых div или table, вместо них просто лейауты и виджеты. Немного гиперлинковости. Встроенная поддержка просмотра и фоток, и видео, и, даже, 3D-форматов.
Также я планировал вскоре после создания Лайси написать утилиту, которая будет работать подобного инструментарию сайта shadertoy.com. То есть вызывать код для генерации картинки (и звука). Но не GLSL, а лайси-байткод. В таком случае можно будет делать демосцены не только рейтрейсинговые, но и растеризационные. Да и вообще по-сути можно любой кодек внутрь засунуть и просто пытаться ужать видео без потерь или с минимальными потерями. Но это для энтузиастов и любителей, если кому-то понадобится мой софт. К тому же, размер будет зависеть от жирноты кодека. Вот libpng в линуксе весит пару сотен килобайт, а многие PNG-картинки даже столько не весят.
Вот поддержку таких демосцен надо будет в мой веб засунуть.
А учитывая все эти факторы и то, что у меня создаются движки графический и ГУИшный, а потом я, может быть, возьмусь за физические, то дойдёт до целого игрового движка. Хотя я и не планировал заниматься этим.
К сожалению, в последнее время, у меня мало времени заниматься Лайси. Надо успеть хотя бы до первой половины января следующего года.
А ведь там немного осталось. Подправить поддержку синтаксиса и готово! В крайнем случае можно часть синтаксиса урезать и добавлять в следующих версиях. Например, switch а ещё я там в стандарт добавил match, но это ни о чём не говорит. Только даже при поддержке Лайси компилятор почти никто не сможет использовать кроме меня, ведь надо же ещё об синтаксических ошибках сигнализировать! Это я прочувствовал Лайси как моё создание и понимаю, что в том-то месте просто точки с запятой не хватает. Хотя и я при объёмах кода выше 500 строк просто не смогу следить за всем и дебажить случайную ошибку.
Anonymous No.3278
>>3277
>и мой веб
Гипертекстовый фидонет.
sage sage No.3505
>>3277
ебать ты ебанулся. Нихуя у тебя задачи, делать тебе нехуй. Пиздос. Иди ещё C перепиши бля

[Назад] [Обновить тред] [Вверх] [Каталог] [ Автообновление ]
250 / 12 / 203

[Ответить в тред] Ответить в тред

15000

Ответ в тред No.989
Настройки
Избранное
Топ тредов