LINUX.ORG.RU

Qod. Опубликовал исходники компилятора, над которым работаю

 , qod, ,


4

5

Финально определился с названием языка, подчистил разные хвосты и написал README. Теперь наконец-то можно посмотреть на нечто большее, чем просто фрагменты кода в постах на форуме: https://github.com/wandrien/qod/

Драфты по дизайну языка пока еще не готовы. Если перед НГ завала работы не будет, то может выложу их в течение пары недель. Черновики пишу на русском, осилить всё чётко сформулировать на английском в разумные сроки я точно не смогу. На русском-то не всегда получается.

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

А пока можно посмотреть на сам код вживую.

Слушайте, меня чо-то щас осенило. Язык, на котором Intel описывает работу машинных инструкций в документации, это же по сути Алгол 68, не?

Только вместо ELSE IF надо писать ELIF по правилам Алгола 68.

IF SRC = 0
    THEN #DE; FI; (* Divide Error *)
IF OperandSize = 8 (* Word/Byte Operation *)
    THEN
        temp := AX / SRC;
        IF temp > FFH
            THEN #DE; (* Divide error *)
            ELSE
                AL := temp;
                AH := AX MOD SRC;
        FI;
    ELSE IF OperandSize = 16 (* Doubleword/word operation *)
        THEN
            temp := DX:AX / SRC;
            IF temp > FFFFH
                THEN #DE; (* Divide error *)
            ELSE
                AX := temp;
                DX := DX:AX MOD SRC;
            FI;
        FI;
    ELSE IF Operandsize = 32 (* Quadword/doubleword operation *)
        THEN
            temp := EDX:EAX / SRC;
            IF temp > FFFFFFFFH
                THEN #DE; (* Divide error *)
            ELSE
                EAX := temp;
                EDX := EDX:EAX MOD SRC;
            FI;
        FI;
    ELSE IF 64-Bit Mode and Operandsize = 64 (* Doublequadword/quadword operation *)
        THEN
            temp := RDX:RAX / SRC;
            IF temp > FFFFFFFFFFFFFFFFH
                THEN #DE; (* Divide error *)
            ELSE
                RAX := temp;
                RDX := RDX:RAX MOD SRC;
            FI;
        FI;
FI;
wandrien ★★
() автор топика
Ответ на: комментарий от wandrien

Вот кстати там в первых строчках пример того, какие выкрутасы приходится делать для кейсов, специально для которых у меня сделан when:

IF SRC = 0
    THEN #DE; FI; (* Divide Error *)
wandrien ★★
() автор топика
Ответ на: комментарий от wandrien

Я вчера пока суп грелся думал интерпретатор браинфана по приколу на твоём языке написать, но споткнулся от того что часто семантика языка непонятная, не понял как массив инициализировать несколькими значениями за раз и прочее, суп нагрелся, я наелся и уснул =)

Пока видимо рано, так как ты ещё на ходу синтаксис и его семантику придумываешь =)

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

dron@gnu:~/Рабочий-стол/brainfucqoud$ tree -L1
.
├── app.qd
├── core
├── Makefile
└── qodc

2 directories, 3 files

Так удобнее собирать. По идее базовые вещи вроде ввода/вывода можно вшить в бинарь компилятора, тогда можно будет просто закинуть его в /bin/qodc и не надо рядом всё остальное держать.

########################################
APP_BIN=app
APP_ASM=app.qd.asm
APP_SRC=app.qd
########################################
CC=./qodc
FASM=fasm
CHMOD=chmod +x
CFLAGS=--optimize speed --linux
########################################
all:
	$(CC) $(CFLAGS) $(PWD)/$(APP_SRC)
	$(FASM) $(APP_ASM) $(APP_BIN)
	$(CHMOD) $(APP_BIN)
########################################
run:
	./$(APP_BIN)
########################################
clean:
	-rm $(APP_ASM)
	-rm $(APP_BIN)
#########################################
  • app.qd
include "core/sys4lnx.qdi";
include "core/include/hosted.qdi";

word memory[30000];
char source = "+++++++++++[>+++++++<-]>-----.>+++++[<++++++>-]<-.+++++++..+++.>++++[>+++<-]>--.";
int  ptr = 0;

word execute(char @source)

end

begin
	puts("This program is compiled with ");
	puts(@__TRANSLATOR__);
	puts(" ");
	puts(@__TRANSLATOR_VERSION__);
	puts(" on host ");
	puts(@__TRANSLATOR_HOST__);
	puts("~r~n");
	puts("Target is ");
	puts(@__TRANSLATOR_TARGET__);
	puts("~r~n");
	puts("Qod Version is ");
	puts(@__QOD_VERSION_STR__);
	puts("~r~n");
end

На этом мои приключения закончились.

А ещё у тебя тесты используют заголовки для винды sys4win.qdi по умолчанию хотя ты ранее говорил что у тебя есть условное подключение заголовков.

Ну и пока некоторые вещи вроде @ и ~ можно понять только методом тыка по наитию. Я понял что это указатель и экранирование, но вот что из себя представляет тип word я не понял, у тебя типы требуют описания, где-то он описан, но повторюсь, вчера суп нагрелся быстрее чем я смог понять, с сегодня чвота лень.

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

О великий суп наварили!
О шикарный суп наварили!

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

И ещё, пока не удобно своё собирать, примеры лежат внутри заголовочных файлов.

Да вроде заголовочные файлы в отдельном каталоге лежат. Но надо сделать аналог директивы -I, да. Пожалуй, сегодня и сделаю, если не усну.

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

CFLAGS

QODFLAGS тогда уж =)

А ещё у тебя тесты используют заголовки для винды sys4win.qdi по умолчанию хотя ты ранее говорил что у тебя есть условное подключение заголовков.

Тесты в каталоге tests - не должны.

Файлы в каталоге samples - да. Там нечто очень древнее, что мне нужно бы пересмотреть. Еще от Хохлова что-то вроде осталось.

Условные инклуды-то я сделал, а общую их организацию еще не пересмотрел.

У Хохлова не было аналога main(), после блока begin ты сразу попадаешь в место, где тебе ядро передало управление. Надо это доделывать.

путь к исходнику для сборки должен быть абсолютным, ./ не канает.

o_O

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

Пожалуй, сегодня и сделаю, если не усну.

Неа, не сделаю.

Потому что сначала надо сделать вот это:

У Хохлова не было аналога main(), после блока begin ты сразу попадаешь в место, где тебе ядро передало управление. Надо это доделывать.

Спать пойду, короче. Без супа)

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

Ну сделай уже if x : y вдобавок к обычному if без двоеточия. Видишь как лоровцы рвутся от этого when. Так и все гипотетические юзеры будут рваться. Оно и правда необычно, дуиаешь то ли это паттерн матчинг какой, то ли хз что.

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

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

when же стандартная конструкция во многих языках, зачем if перегружать. Это if без else, условное выполнение стейтмента. Странно, почему эта мысль для некоторых настолько необычна, что они от этого рвутся.

anonymous
()

Были планы этим вечером хорошенько посидеть над кодом. Но я чо-то так на работе задолбался, что сил хватило только немного почистить код, связанный с преобразованием целых чисел, да написать небольшой черновик: https://github.com/wandrien/qod/blob/master/drafts/bin-op-integer-conversions.md

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

Прикольно, что один комментатор пишет, «где xor», а другой «битовые операции должны быть определены только для беззнаковых».)) Вот и гадайте, то ли лишнего вставил при копипесте, то ли наоборот.)

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

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

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

Расширение разрядности не противоречит добавлению знака. Была область значений меньше, стала больше. Безопасно относительно значения выражения.

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

Так прикольно, что требования противоположные.

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

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

when же стандартная конструкция во многих языках, зачем if перегружать

Такой when не нужен. Это частный случай if. Лучше сделать однострочные варианты всех управляющих конструкций, если уж автор так любит однострочники. Это хотя бы консистентно, а не просто «дай накидаю ключевых слов для случайных юзкейсов».

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

Такой when не нужен. Это частный случай if.

Отчего такое отвращение к дополнительным ключевым словам? if подразумевает возможность else, тогда как when семантически читается как ограждающее условие и else не подразумевает.

Лучше сделать однострочные варианты всех управляющих конструкций

Путаницу это не исключает никак, только провоцирует ошибки.

консистентно

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

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

Отчего такое отвращение к дополнительным ключевым словам?

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

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

if подразумевает возможность else, тогда как when семантически читается как ограждающее условие и else не подразумевает.

А когда тебе приспичит добавить else к существующему when тебе придется менять when на if и в патче будет лишняя строчка о которую ты будешь спотыкаться глазами - «там действительно только when на if заменили или еще что-то в условии поправили?»

Я не против экстра ключевых слов кстати. Можно unless и until обсудить например. Только вот выгядят они слишком одинаково на мой глаз (надо синонимы поискать). Ключевые слова никто не читает - их окидывают взглядом и понимают где какое слово по размеру и форме. if, else, for, while, do, break, continue, return, struct, union в этом смысле подобраны очень удачно.

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

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

Лучше сделать однострочные варианты всех управляющих конструкций, если уж автор так любит однострочники.

1. Автор не «любит» однострочники. У автора даже в коде компилятора when используется исключительно в виде двух строк:

when что-то:
  что-то делаем;

2. «Лучше сделать однострочные варианты всех управляющих конструкций». Лучше для чего? Есть какие-то критерии этого лучше? Выше по треду же подробно обсуждалось, почему when именно when, а не if, для чего он нужен, и почему для этих кейсов if работает плохо.

Это хотя бы консистентно

Консистентно сделали в Паскале и Си. Проблемы с консистентностью синтаксических форм обсуждались парой страниц ранее.

В данном случае задача обратная – сломать консистентность. Мозг не машина, он не парсит грамматику так же, как компилятор. А ЯП предназначены в первую очередь для чтения человеком.

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

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

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

А когда тебе приспичит добавить else к существующему when тебе придется менять when на if и в патче будет лишняя строчка о которую ты будешь спотыкаться глазами - «там действительно только when на if заменили или еще что-то в условии поправили?»

А когда предложенный гипотетический вариант if ... : менять на if .. then, то дополнительная строчка в патче не появится?

Я не против экстра ключевых слов кстати. Можно unless и until обсудить например.

А я как раз против unless и until. unless это понты разработчика ЯП.

С until ситуация сложнее. В Си синтаксис позволяет записать do statement while cond, и это будет парситься однозначно.

Но в синтаксисе с неявным блоком, while будет парситься как начало цикла с пред-условием. Поэтому для цикла с пост-условием приходится придумывать материально отличающееся выражение ключевых слов. По этой причине у меня есть:

repeat
  что-то делаем
until обратное_условие;

Но он мне активно не нравится. Он существует только потому, что я не придумал, чем заменить until.

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

Путаницу это не исключает никак, только провоцирует ошибки.

Именно так. Мало того, что предложено по сути вернуться к синтаксису Си и Паскаля и вернуть все их проблемы, которые обсуждались ранее. Так еще и оставить при этом формы операторов с неявным блоком.

Это получится уже совсем лютый треш.

when сделан отдельным ключевым словом именно потому, что он единственный, в отличие от остальных управляющих конструкций, требует после себя одиночный statement.

И поэтому должен чётко и однозначно считываться в тексте.

А такое:

if условие & и еще какое-то условие & и еще:

это какое-то издевательство над читателем, игра «найди двоеточие в конце».

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

а зачем единить имён пространство - тока для текста поиска безконтекстного шоля?

патомушто лексер будет ковертировать поток буков в поток лексем. и будут у него вместо идентификаторов лексемы навроде lex_while, lex_if, lex_when. и если ты напишешь when как идентификатор, это будет лексемой lex_when, что естественно компилятор воспримет как ошибку.

auto when = 100; 

Чоо? - скажет компилятор, - у меня when это оператор такой, типа условный.

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

Но в синтаксисе с неявным блоком, while будет парситься как начало цикла с пред-условием.

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

some_result parse_block (LexTypeSet end_block_symbols);

и поскольку блок может заканчиваться разными символвами - end, }, until, else, case, default… и так далее (от грамматики зависит разумеется ) - то парсинг блока делается с конкретным набором символов, которые могут закончить данный блок.

если ты парсишь блок после «if cond then…» то будешь парсить блок с множеством стоп-символов {else_sy, elsif_sy, end_sy}, если после «case 100:» то будет множество - {case_sy, end_sy, else_sy}.

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

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

не будет

Да правда что ли. А ну-ка распарси мне грамматику в тексте без отступов:

int i = 0;
int x;
repeat
x = foo(i);
inc i;
while
x != 0 or
fooBarBaz(x)
/* дальше не видно */

если ты парсишь блок после «if cond then…» то будешь парсить блок с множеством стоп-символов {else_sy, elsif_sy, end_sy}, если после «case 100:» то будет множество - {case_sy, end_sy, else_sy}.

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

Вопрос не в том КАК это сделать, а ЗАЧЕМ так делать.

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

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

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

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

Золотце

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

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

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

дерзай короче, исследователь.

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

Про этап лексического анализа в «настоящих компиляторах» особенно задорно получилось.

Код:

template <typename T>
struct X {
    T x;
};

template <typename T>
struct Y {
    T x;
};

Y<X<int>> y;

В gcc -std=c++11 – компилируется.

В gcc -std=c++98 – получаем это:

<source>:16:8: error: '>>' should be '> >' within a nested template argument list
   16 | Y<X<int>> y;
      |        ^~
      |        > >

Сломанный к херам этап лексического анализа выглядит именно так.

wandrien ★★
() автор топика