Мой опыт переноса интерпретатора «Эллочка» из DOS в Windows на Zig

от автора

Недельки 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 $0LIST 'Привет, '; $0; '!'A=1@LOOPLIST 'Итерация номер '; AA=A+1ESLI A << 6; @LOOPLIST 'Готово!'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) для отзывчивости окна во время блокирующих операций (WAITMENU).

  • 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 — графическая версия игры.

Они полезны не только как демонстрации. Текстовая «Змейка» проверяет обработку клавиатуры, экранный вывод, условия, переходы и переменные. Графическая версия дополнительно проверяет графический режим и рисование.

image-20260808161315422.png

image-20260808161315422.png
image-20260808162153134

image-20260808162153134

А вот как выглядит оригинальный код игры «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:20P:50Q:50R:20S:120K:9Z:5size Bsize [99]=X;Y;Pdata 1;B;@opisanie$0='piton.dat'grafcsim 3I:0incr I     stro I     stlb 40     $1=$I     list $1esli I << B; -5\cvet 8;63;63;63orupcsim 8rama R-1; S-1; R+P*Z; S+Q*Zpain R+1; S+1; 8csim 15rama R; S; R+P*Z-1; S+Q*Z-1pain R+1; S+1; 15csim 1rama R; S; R+P*Z-1; S+Q*Z-1U:1D:2M:0G:1H:0X=&int(P/2)Y=&int(Q/2)X[1]=X-1Y[1]=Y-1X[2]=XY[2]=YE=Klenf $0;Lesli &frc(L/16) |= 0; @newkrolikL=L/16csim 13I:0@cikl1incr 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;Jgoto @cikl1@newkrolikV=&int((P-1)*&ran#+1)W=&int((Q-1)*&ran#+1)csim 4krug R+V*Z; S+W*Z; Z/2; 1pixl R+V*Z; S+W*ZN:0stro 2stlb 1csim 11list ' Уровень:';U\list ' Осталось кроликов:';E\O=600-U*100F=&int(&sqr((X-V)^2+(Y-W)^2))@stepudavcsim 2krug R+X*Z; S+Y*Z; Z/2; 1pixl R+X*Z; S+Y*Zcsim 15krug R+X[1]*Z; S+Y[1]*Z; Z/2; 1pixl R+X[1]*Z; S+Y[1]*Zesli C |= 0; +3\     wait C     esli C == 27; @konecI:0incr I     X[I]=X[I+1]     Y[I]=Y[I+1]esli I << D-1; -3\incr Nslep Okeys Aesli A == 27; @konecesli 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+3X=X+GY=Y+Hesli X |= {1,P-1} @rezultatesli Y |= {1,Q-1} @rezultatI:0incr I     esli X[I] |= X; +2\     esli Y[I] == Y; @rezultatesli I << D; -3\X[D]=XY[D]=Yesli X |= V; @stepudavesli Y |= W; @stepudavM=M+&int(F/N*50000/O*&sqr(U))incr Ddecr Eesli E >> 0; +4\     E=K     incr U     esli U >> 5; +2\goto @newkrolikstro 2stlb 1csim 11list ' Осталось кроликов:';Estro 28stlb 2csim 4list 'Все кролики съедены!'@rezultatstro 29stlb 2csim 14list 'Результат:';Mcsim 7stro 30stlb 1maxa P;Jesli 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@label1wait@konecexit!--------------------------------------------------------------------------@opisanie       Установите режим NUM LOCK!     Игра проходит  в  квадратном  поле,всего 5 уровней сложности, различающихсяскоростью движения и длиной питона.     Управление движением питона  произ-водится цифровыми клавишами на  дополни-тельной  клавиатуре  в   соответствующемнаправлении (в режиме NUM LOCK).     Клавиша 5 прекращает игру с выводомрезультата, клавиша <Esc> - немедленно.     В случае,  если  питон  ударится  окрая поля или пересечет свое тело,    онпогибает и выводится результат игры.     На каждом уровне необходимо прогло-тить 9 кроликов и проползти при этом ми-нимальный путь. Текущий уровень и остав-шееся количество кроликов постоянно  вы-водятся на экран.     10 лучших результатов  запоминаютсяв файле `piton.dat`:!==========================================================================
image-20260808162454408

image-20260808162454408

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

image-20260808162629553

image-20260808162629553

Эти примеры показывают, что Эллочка подходит не только для расчётов. На её основе можно было создавать и интерактивные графические программы и игры.

Автор и исходники

Автор языка — Гаузер Эрих Генрихович. Информация об авторе: hauserich.vgd.name.

Исходный код на zig: github.com/malexple/ellochka-zig

ссылка на оригинал статьи https://habr.com/ru/articles/1072306/