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


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

[Назад] [Обновить тред] [Вниз] [Каталог] [ Автообновление ] 71 / 4 / 61

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
}

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

[Назад] [Обновить тред] [Вверх] [Каталог] [ Автообновление ]
71 / 4 / 61

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

Ответ в тред No.989
15000
Файлы. Макс объем: 20 MB, макс кол-во файлов: 4

Ответ в тред No.989X
15000
Файлы. Макс объем: 20 MB, макс кол-во файлов: 4
Кликни/Брось файл/ctrl-v
НастройкиX
X
Избранное
Топ тредов