Программа:
модуль x
@внешняя фн tri_welcome()
вход {
tri_welcome()
}
Скомпилирована в С:
#include «trirun.h»
#include «x.h»
int main() {
tri_welcome();
return 0;
}
и выполнена:
Функция tri_welcome написана на С и печатает: Trivil!
Трудозатраты на компилятор до этого момента — примерно 25-30 часов, не пытался точно засекать. Я вполне доволен скоростью разработки.
Компилятор делаю в самом удобном для меня стиле — сначала делаю «скелет», потом наращиваю «жир».
Скелет готов, в него входит:
- Сканер — практически полный, нет экспоненты у вещественных.
- Парсер — часть грамматики: модуль, функция, оператор только один, выражение — только вызов. Строит AST
- Семантика — один обход AST — построение таблицы имен и поиск, типы не проверяются
- Генерация — только того, что есть в AST
- Обработка ошибок вполне рабочая
Далее наращивание возможностей:
- более-менее полный набор операторов и выражений. Проверка: факториал
- импорт. Проверка: библиотека консольной печати
- массивы и классы
Постоянная ссылка
Мои поздравления и соболезнования))
Русский язык горячо поддерживаю, собака впереди внешнего объявления (сугубо имхо) — лишняя. Лучше сделать в форме стандартного импорта Но с каким-нибудь спецификатором в объявлении импорта.
Окончание модуля часть опциональная, но по опыту Компонентного Паскаля — лучше добавить. За окончанием модуля можно вставлять документацию, команды запуска, да хоть котиков. Имхо, очень удобно.
Постоянная ссылка
«собака впереди внешнего объявления (сугубо имхо) — лишняя.»
Вполне возможно, что в модификаторы (@имя) придется добавить доп. параметры, например: @внешняя{имя=»printf», ABI=»C»}. А это не сделаешь импортом. Да и использование собаки уже устоялось — Java annotations, Typescript decorators, Swift attributes…
«Окончание модуля часть опциональная, но по опыту Компонентного Паскаля — лучше добавить» — может быть, но я уже пришел к мысли, что модули надо делать много-файловыми (как в Го), иначе неудобно. А тогда смысл добавления «котиков» изрядно теряется.
Постоянная ссылка
А зачем, по вашему опыту, делать модули многофайловыми?
Недостаточно делать их иерархическими, как в Rust?
Может быть «если что-то требует нескольких файлов, это стоит рассмотреть как больше чем один модуль?»
Постоянная ссылка
Сейчас парсер в Тривиле 1200 строк и будет раза в полтора больше. Делить парсер на несколько модулей нет смысла, это лишний импорт/экспорт. Я предпочитаю разбить его на несколько файлов, сейчас их 7: из них 5 основных (описания, типы, операторы, выражения, функции), один отладочный и один для тестирования.
В принципе, можно весь парсер запихать в один файл. Например, основная часть Go парсера — около 3000 строк в одном файле, впрочем кроме этого файла, есть еще два файла поменьше. Но мне так неудобно.