Это основано на разговоре о компиляторах, которые я слушал некоторое время назад, но я, к сожалению, не могу вспомнить, когда и где.
Создайте самый короткий компилятор на любом языке, который может компилироваться сам. Предназначайтесь для любого разумного ISA (68K, x86, MIPS, ARM, SPARC, IBM BAL и т. Д.), У которого нет инструкции «compile-program» (это может исключать некоторые версии VAX). Читайте исходные программы stdin
и печатайте сгенерированный код stdout
. Вы можете использовать стандартную библиотеку C для ввода / вывода и обработки строк (например, _printf
). Вам не нужно компилировать весь язык, только любое подмножество, содержащее компилятор (то есть, просто печать квин на ассемблере, хотя и впечатляет, не считается решением).
#!/usr/local/bin/tcc -run
в первую строку вашего источника C и выполните его прямо из командной строки." Это круто.Ответы:
Подмножество Haskell → C - 18926 символов
Это компилирует небольшое подмножество Haskell в C. Функции, которые он поддерживает:
Самые большие отсутствующие функции - это вложенные переменные (т.е. не лямбда / let / where / case), проверка типов и классы типов. В результате программы теряют память, а самокомпиляция занимает в моей системе около 200 мегабайт ( сборщик мусора Boehm очень помогает, но только в том случае, если компилятор хорошо оптимизирует хвостовую рекурсию).
Для начальной загрузки, раскомментируйте первые три строки (не учитываются в счете) и скомпилируйте с GHC. Компилятор берет код подмножества Haskell на стандартный вывод и генерирует код C на стандартный вывод.
Это долго не потому что язык сложный, а потому что я ленивый.
Тем не менее, в настоящее время это самое короткое решение. Думаю, мне не будет скучно в эти выходные.источник
Пользовательский язык → C - (7979)
Поскольку вопрос не исключает возможности создания собственного языка, я решил попробовать.
Окружающая среда
Язык имеет доступ к двум стекам: стека вызовов и стека данных. Стек вызовов используются для команд прыжков
{
и}
, в то время как Стек данных используются большинство других команд. Стек вызовов непрозрачен для приложений.Стек данных может содержать три различных типа значений: целое, текстовое и пустое. Целые числа имеют тип intptr_t, а текст хранится в виде строк в стиле C.
^
Команда имеет доступ к массиву. Массив представляет собой постоянный массив длиной 17 текстовых элементов. Вероятно, вы должны увидеть источник для схемы индексации, поскольку она немного шаткая.Язык
Компилятор
Это компилятор. Это не игра в гольф, и я ожидаю, что это может быть значительно сокращено. Должна быть возможность использовать машинный код напрямую и выводить COM-файл с DOS, но я пока не дошел до этого. Я знаю, что это похоже на C-программу, но фактическая реализация компилятора в конце не работает.
В настоящее время компилятор генерирует много отладочной информации о stderr.
Чтобы скомпилировать сгенерированный код C:
Кодировка требуется, потому что компилятор экранирует специальные символы, добавляя 128.
Бутстрап
Чтобы скомпилировать первый компилятор, я написал интерпретатор языка Python.
Собираем все вместе
Предполагая, что вы сохранили компилятор как
compiler.cmp
и загрузчик какbootstrap.py
, вот как собрать компилятор, а затем использовать его для компиляции:Так что я не большой программист на C, и я не большой языковой дизайнер, поэтому любые предложения по улучшению этого приветствуются!
Примеры программ
Привет, мир!
источник
Extended Brainfuck v0.9: 618 байт (не считая ненужных перевода строки)
Это гольф-версия моей самой первой версии EBF с удаленной поддержкой комментариев и мертвым кодом для поддержки удаления переменных.
Так что в основном это BrainFuck с переменными.
:x
создает переменные х. Компилятор знает, где вы находитесь, поэтому$y
будет производить <и s, чтобы добраться до этой позиции. Иногда вам нужны асимметричные циклы, а затем вам нужно сообщить компилятору, где вы находитесь@x
. Как текущий EBF он компилируется в Brainfuck.Эта первая версия имела только одно имя переменной char, но я использовал эту версию для компиляции следующей версии и так далее, пока текущая версия не обладает впечатляющим набором функций. При компиляции из исходного кода github он фактически загружает двоичный файл, откомпилированный вручную, в начальную загрузку промежуточных версий ebf 6, чтобы создать текущую версию.
Чтобы загрузить его, вы можете использовать этот первый и единственный двоичный файл в git-репозитории EBF, который был успешно скомпилирован вручную после нескольких попыток.
Brainfuck имеет несколько аппаратных реализаций, например. это , это и это, чтобы упомянуть несколько. Но в основном это так просто реализовать, что вы можете практически реализовать интерпретатор в любой системе. Я шучу, что Zozotez LISP , написанный на EBF, вероятно, самый переносимый LISP за всю историю.
источник
Hex, 550 байт
Это специально предназначено для систем x86_64 под управлением Linux.
На этом языке исходный код состоит из байтов, представленных в виде двух шестнадцатеричных цифр в нижнем регистре
[0-9a-f][0-9a-f]
. Эти байты могут иметь любое количество окружающих пробелов, но между цифрами, образующими один байт, может не произойти ничего. Кроме того,'!'
это символ комментария к строке: он игнорируется, как и все, что находится между ним и следующим'\n'
символом.Если вы понимаете сборку x86, вот гораздо более читаемая версия исходного кода:
Если вы извлекаете язык ассемблера из комментариев ниже
! Program Code
, вы можете собрать и запустить Hex-компилятор. Для ввода и вывода используются stdin и stdout.источник
Hex
это не языкПодмножество Javascript -> Java, 504 байта
источник
05AB1E , 2 байта (возможно, не конкурирующие)
Попробуйте онлайн!
Код в первой строке ввода, ввод в последующих строках.
источник
Пиломатериалы , 0 байт
Lumber - это полный эзотерический язык программирования, изобретенный Unrelated String, написанный всего за 10 строк кода Prolog.
Не можете в это поверить? В этих программах удалены комментарии, что делает источник интерпретатора более лаконичным.
lumber_corefuncs.pl:
lumber_types.pl
lumber_corefuncs.pl принимает в библиотеке lumber_types; и, в свою очередь, эта библиотека определяет модуль, в котором ничего нет. Поэтому Lumber ничего не делает для произвольных входных данных, что, в свою очередь, является само-компилятором.
источник
Ноль , 0 байт
источник