Недельки 2 назад я написал статью про свой скриптовый язык для wiremock wiremockjs В комментариях мне написал Гаузер Эрих Генрихович. Он рассказал, что ещё в 1999 году разработал собственный язык программирования — «Эллочка».
Мне стало дико интересно, что это за зверь. Я не думал долго: взял Perplexity, скормил ему всё, что нашёл про язык на сайтах автора. И попробовал тут же, раз есть описание языка и синтаксиса реализовать на windows. Язык выбрал не самый популярный, но на нем я уже пробовал создавать свою маленькую консольную операционную систему Prometheus OS, но это тема отдельной статьи. Мне показалось это жутко интересным. Это некое подобие потока, вам интересно и вы уже пишите и разбираете язык, а не задаете вопросы зачем и почему. Пропал для общества примерно на час.
Почему стало интересно? Для языка wiremockjs я использовал ANTLR. А тут DOS и «Эллочка» это однопроходный интерпретатор. Не надо разбирать и строить синтаксическое дерево, обход этого дерева в ANTLR. Плюс ограничения самой операционной системы DOS. Да и накатили воспоминания когда игры таскал на floppy дисках, хотя у меня уже стояла windows 98.
За час получилось реализовать:
Числовые переменные (A-Z), одномерные и двумерные массивы.
Присваивание:
A=expr,A[i]=expr,A[i,j]=expr, неявные циклыA[]=expr,A[,]=expr.Управляющие операторы:
GOTO,ESLI(с условиями >>,<<,>=,<=,==,|=),SLEP,RADI/GRDS,ORUP/ORDN.Ввод/вывод (текстовый режим через ANSI):
LIST,VVOD,CLSC,CFON,CSIM,STRO,STLB.Математические функции:
&RAN#,&SIN,&COS,&TAN,&ASN,&ACS,&ATN,&EXP,&LOG,&INT,&FRC,&ABS,&SGN,&SQR.Метки (
@label) и переходы по номеру строки или метке.Системные:
EXIT,STOP, базовыйMEMC.
Простейший скрипт который получилось выполнить выглядел так.
! Пример программы на Ellochka: приветствие и простой цикл ! (комментарии начинаются с восклицательного знака) LIST 'Введите ваше имя: ' VVOD $0 LIST 'Привет, '; $0; '!' A=1 @LOOP LIST 'Итерация номер '; A A=A+1 ESLI A << 6; @LOOP LIST 'Готово!' EXIT
А структура проекта так:
src/state.zig— таблицы переменных, массивов, строк (включая массив статических строк$A-$Zфиксированной длины 75 символов и динамические строки$0-$9произвольной длины до 1024 символов), режимы исполнения, палитра.src/errors.zig— единый набор ошибок парсинга и выполнения.src/lexer.zig— построчный лексер (токенизация одной строки), поддерживает числа без ведущего нуля (.011).src/expr.zig— парсер и вычислитель арифметических выражений; математические функции (&SIN,&COS,&SQRи т.д.), унарные+/-, индексация массивов включая сокращённую формуA[](индекс текущей неявной итерации).src/program.zig— загрузка программы, таблица меток, адресация по номерам строк; лимит длины строки (75) считается в Unicode-символах, а не в байтах UTF-8 (важно для кириллицы).src/statement.zig— разбор и выполнение всех 62 операторов.src/graphics.zig— графический слой: окно Win32 + закадровый DIB-буфер 24bpp, насос сообщений (pumpMessages) для отзывчивости окна во время блокирующих операций (WAIT,MENU).src/main.zig— точка входа, главный цикл интерпретатора.
Честное признание: возможно, вы скажете, что код писал не я. И будете правы — код генерировала нейросеть. Моя роль заключалась в поиске информации, её агрегации, архитектурных решениях, ревью, код-дирекшене и тестировании.
Воодушевлённый успехом, я решил продолжить вечером. И мне хотелось попробовать запустить оригинальный скрипт sample.ela.
Тут стоит указать оригинальную информацию про язык «Эллочка»
«Эллочка» — интерпретируемый язык, созданный Гаузером Эрихом Генриховичем в Баку. Он задумывался как язык, доступный пользователю без специальной подготовки в программировании, но при этом получил возможности для прикладных и научных расчётов.
Язык поддерживает числовые и текстовые переменные, одномерные и двумерные массивы, работу с файлами, графику, переходы, математические функции и специализированные операции. В оригинальном описании определены 62 оператора — системные, управляющие, файловые, графические, математические и другие.
Оригинальный DIKAR v7 разрабатывался для MS-DOS в 1999–2001 годах. Он включал редактор, справку, пошаговый и командный режимы, диагностику ошибок и комплект примеров. (https://erichware.com/inform/dikar.htm)
Как укротить ИИ и реализовать 62 оператора за 9 часов
Вот тут стоит сделать отступление. Я не использовал в данном случае cloude code или open code или codex. Вся магия происходила в чате. Но в последних обновлениях Claude Sonnet 4.5, а именно эту нейросеть я использовал для генерации кода, есть нюанс. Claude Sonnet 4.5 изменился по сравнению с предыдущей версией. Она начинала спорить и не делала, то что я просил или упрощала код. Я нашел решение. Я описывал подробно задачу и просил задать вопросы Cloude Sonet. И вот с этими вопросам я шел в другую нейросеть, а именно в обычный поисковик google в режиме ИИ. Составлял подробнейшие многостраничные ответы. Дополнительно уточняя или искал информацию в интернете. Где то ходил отдельно по некоторым вопросам в DeepSeek. И вот с такими подробными ответами Cloude Sonet уже не сопротивлялся. На реализацию всех 62 операторов потратил примерно 9 часов.
Вы не представляете, сколько нюансов и вопросов возникало при переносе интерпретатора. Но это было жутко интересно.
Реализация на Zig
Интерпретатор я писал на Zig 0.16.0-dev. Кульминацией было запустить оригинальный sample.ela. На zig это расширения *.ell. Оригинальный скрипт sample.ela я переводил в utf-8 и потом уже запускал. Конечно же с первого раза не запустилось. Но скрипт sample.ela я запустил даже раньше чем перевел все операторы “Эллочки”. Это был успех. Не имея исходников, только по описанию удалось воссоздать язык «Эллочка».
По своей невнимательности я не сразу нашел скрипты написанные автором на языке Эллочка. Эрих Генрихович потом подсказал, что все есть тут. Запускать Dikar-я в эмуляторе DOS я стал только после того как запустил sample.ela. У Эриха Генриховича Dikar это не только интерпретатор Эллочки но и программа, которая имеет редактор, помощник, пошаговый и командный режимы работы, а также подробную диагностику ошибок. То есть если встречается ошибка в скрипте Dikar останавливается на данной строке и предлагает поправить. В интерпретаторе я лишь в консоль вывожу строку где произошла ошибка. Ну и я реализовывал только интерпретатор без IDE Dikar.
В последствии я еще в течении недели комитил измененения, запускал оригинальные скрипты в DOS и проверял все операторы. Проверил все кроме сложных математических операторов:
LIRA— линейная алгебра / решение СЛАУ;POLI— вычисление полинома;DTRM— определитель;APRO— полиномиальная МНК-аппроксимация;REAK— нелинейная реакционная модель;NTGR— численное интегрирование;TRAN— решение нелинейной системы;USER— пользовательская модель.
В отличие от версии DOS в Windows в консоли нельзя реализовать графику и все графические операторы я уже реализовывал и запускал в отдельном окне. Позже чтобы максимально Эллочка соотвествовала оригинальной я в графическом режиме добавил меню и вывод текста в самом графическом режиме.
Игры на «Эллочке»: Змейка и Питон
Раз интерпретатор был написан, то почему бы не написать игру и вспомнить старые добрые игры на DOS.
В репозитории на GitHub есть каталог examples с программами для проверки и изучения реализации.
Два наглядных примера игр:
snake.ell — игра «Змейка» в текстовом режиме;
snake_graphics.ell — графическая версия игры.
Они полезны не только как демонстрации. Текстовая «Змейка» проверяет обработку клавиатуры, экранный вывод, условия, переходы и переменные. Графическая версия дополнительно проверяет графический режим и рисование.


А вот как выглядит оригинальный код игры «Piton» Эриха Генриховича (публикуется с разрешения автора):
!================== piton.ela ============================================= ! A - код клавиши ! B - размер описания ! C - флаг ожидания ! D - текущая длина питона ! E - оставшееся число кроликов ! F - оптимальное число ходов ! G - текущий шаг по X ! H - текущий шаг по Y ! I - счетчик ! J - счетчик ! K - максимальное число кроликов ! L - число записей ! M - количество очков ! N - текущее число ходов ! O - текущая задержка ! P - ширина окна ! Q - высота окна ! R - X начала окна ! S - Y начала окна ! T - текущая задержка ! U - текущий уровень ! V - X кролика ! W - Y кролика ! X - X головы питона ! Y - Y головы питона ! Z - ширина питона !========================================================================== B:20 P:50 Q:50 R:20 S:120 K:9 Z:5 size B size [99]=X;Y;P data 1;B;@opisanie $0='piton.dat' graf csim 3 I:0 incr I stro I stlb 40 $1=$I list $1 esli I << B; -5\ cvet 8;63;63;63 orup csim 8 rama R-1; S-1; R+P*Z; S+Q*Z pain R+1; S+1; 8 csim 15 rama R; S; R+P*Z-1; S+Q*Z-1 pain R+1; S+1; 15 csim 1 rama R; S; R+P*Z-1; S+Q*Z-1 U:1 D:2 M:0 G:1 H:0 X=&int(P/2) Y=&int(Q/2) X[1]=X-1 Y[1]=Y-1 X[2]=X Y[2]=Y E=K lenf $0;L esli &frc(L/16) |= 0; @newkrolik L=L/16 csim 13 I:0 @cikl1 incr I esli I >> L; @newkrolik getf $0;$1;12;I*16-16 getf $0;J;4;I*16-4 P[I]=J stro I+B stlb 40 list $1;J goto @cikl1 @newkrolik V=&int((P-1)*&ran#+1) W=&int((Q-1)*&ran#+1) csim 4 krug R+V*Z; S+W*Z; Z/2; 1 pixl R+V*Z; S+W*Z N:0 stro 2 stlb 1 csim 11 list ' Уровень:';U\ list ' Осталось кроликов:';E\ O=600-U*100 F=&int(&sqr((X-V)^2+(Y-W)^2)) @stepudav csim 2 krug R+X*Z; S+Y*Z; Z/2; 1 pixl R+X*Z; S+Y*Z csim 15 krug R+X[1]*Z; S+Y[1]*Z; Z/2; 1 pixl R+X[1]*Z; S+Y[1]*Z esli C |= 0; +3\ wait C esli C == 27; @konec I:0 incr I X[I]=X[I+1] Y[I]=Y[I+1] esli I << D-1; -3\ incr N slep O keys A esli A == 27; @konec esli A |= {49,57} +6\ A=A-48 H=&sgn((A-4)*(A-5)*(A-6)) G=A-&int(A/3)*3-2 esli G >> -2; +2\ G=G+3 X=X+G Y=Y+H esli X |= {1,P-1} @rezultat esli Y |= {1,Q-1} @rezultat I:0 incr I esli X[I] |= X; +2\ esli Y[I] == Y; @rezultat esli I << D; -3\ X[D]=X Y[D]=Y esli X |= V; @stepudav esli Y |= W; @stepudav M=M+&int(F/N*50000/O*&sqr(U)) incr D decr E esli E >> 0; +4\ E=K incr U esli U >> 5; +2\ goto @newkrolik stro 2 stlb 1 csim 11 list ' Осталось кроликов:';E stro 28 stlb 2 csim 4 list 'Все кролики съедены!' @rezultat stro 29 stlb 2 csim 14 list 'Результат:';M csim 7 stro 30 stlb 1 maxa P;J esli P[J] >> M; @label1 A:1e6 I:0 incr I esli A <= P[I]; +3\ A=P[I] J=I esli I << 10; -4\ vvod ' Введите Ваше имя: ';$1 $1=$1+%chr(12,32) $1=%mid($1,1,12) putf $0;$1;12;J*16-16 putf $0;M;4;J*16-4 @label1 wait @konec exit !-------------------------------------------------------------------------- @opisanie Установите режим NUM LOCK! Игра проходит в квадратном поле, всего 5 уровней сложности, различающихся скоростью движения и длиной питона. Управление движением питона произ- водится цифровыми клавишами на дополни- тельной клавиатуре в соответствующем направлении (в режиме NUM LOCK). Клавиша 5 прекращает игру с выводом результата, клавиша <Esc> - немедленно. В случае, если питон ударится о края поля или пересечет свое тело, он погибает и выводится результат игры. На каждом уровне необходимо прогло- тить 9 кроликов и проползти при этом ми- нимальный путь. Текущий уровень и остав- шееся количество кроликов постоянно вы- водятся на экран. 10 лучших результатов запоминаются в файле `piton.dat`: !==========================================================================

Пример игры в Морской бой:

Эти примеры показывают, что Эллочка подходит не только для расчётов. На её основе можно было создавать и интерактивные графические программы и игры.
Автор и исходники
Автор языка — Гаузер Эрих Генрихович. Информация об авторе: hauserich.vgd.name.
Исходный код на zig: github.com/malexple/ellochka-zig

