Разработка динамического языка

11

Я создал несколько рукописных компиляторов для очень простых языков, но теперь я хочу попробовать свои силы в разработке динамического языка, похожего на упрощенный Python или Ruby. Однако мне было легко обдумать, как работают компиляторы. Примитивные компиляторы просто переводят. Но я не могу этого сделать, если язык динамичен. Мне нужно написать интерпретатор или виртуальную машину, которая отслеживает информацию во время выполнения и требует от меня гораздо больше работы.

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

Я ищу информацию о том, как перейти от компилятора к интерпретатору. Если я уже сделал компилятор для языка X, но что теперь писать для интерпретатора, что нужно сделать, и есть ли какие-либо ресурсы, которые влияют на процесс?

Мне не нужны широкие или абстрактные ресурсы, рассказывающие о работе компиляторов или виртуальных машин. У меня много учебников на эту тему. Все ресурсы, которые я нашел в Интернете, предполагают, что у вас 0 опыта, и поэтому начинают с лексического или синтаксического анализа, или они чрезвычайно абстрактны. У меня есть работающий компилятор, но теперь я хочу превратить его в интерпретатор и добавить в язык динамические функции.

Я не мог найти ресурсы для этого процесса, он может быть слишком ограничен по объему, или ресурсы на «бэкэнде» переводчика, не будучи слишком теоретическими, поэтому я разместил здесь.

Остин Хенли
источник
1
Есть тонны таких ресурсов. Обратите внимание, что грань между компилятором и интерпретатором более размыта, чем вы думаете; Компилятор C # 4.0 поддерживает динамическое программирование, как и ряд других компиляторов.
Роберт Харви
@RobertHarvey Да, я прошу ресурсы для создания собственной среды выполнения / интерпретатора / виртуальной машины. Интерпретатор .Net слишком сложен для меня, чтобы основывать его на!
Остин Хенли
1
И проверьте этот ТАК вопрос , есть пара комментариев со ссылками на другие вопросы, которые довольно интересны ...
Яннис

Ответы:

4

Сначала узнайте о реализации переводчиков. Я рекомендую PLAI (Языки программирования: применение и интерпретация) . Он быстро достигает сути интерпретации, не останавливаясь на синтаксисе.

Для вашего языка вы сможете повторно использовать интерфейсную часть компилятора (в основном анализатор) и библиотеку времени выполнения (GC, структуры данных, примитивные операции и т. Д.).

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

Райан Калпеппер
источник
5

Если вы хотите изучить основы реализации интерпретатора для динамического языка, я не могу представить себе лучшего места для начала, чем истоки самого первого динамического интерпретируемого языка программирования: Lisp.

В своей оригинальной статье 1960 года Джон Маккарти определил 5 примитивных функций, необходимых для Лиспа. Конечно, Маккарти только предназначил свою статью о Лиспе как академическое упражнение; это был аспирант, который участвовал evalв сборке и создал первого переводчика Lisp. Пол Грэм идентифицирует семь примитивов : цитата, атом, эквалайзер, автомобиль, CDR и конд.

Дело в том, что вы можете реализовать Lisp на любом языке; После того, как вы внедрите eval, легко настроить REPL, и у вас будет интерактивный переводчик. Людям было скучно или достаточно любопытно реализовать Lisps на C, Java, Ruby, Python и многих других языках. И не всегда нарочно; важно помнить Десятое Правило Гринспуна :

Любая достаточно сложная программа на C или Fortran содержит специальную, неформально определенную, медленную реализацию половины Common Lisp.

Я не говорю, что вашей конечной целью должна быть реализация Lisp; но гомойконичность имеет свои преимущества при обучении реализации динамического языка; зачем иметь дело с проблемами синтаксиса, когда вы можете учиться на языке, в котором идиоматический синтаксис идентичен AST языка, использующего лексер / парсер?

Во всяком случае ... просто предложение. Но есть веская причина, что большинство замечательных языков программирования, начиная с C, имеют хотя бы немного Lisp-природы.

Джейсон Льюис
источник
1
Я хотел бы принять два ответа. Спасибо, я думаю, что я действительно буду реализовывать интерпретатор Lisp. Он легко разбирается, имеет массу документации и существующего кода и должен дать мне основу для работы. К сожалению, я взяла курс для студентов, который использовал Scheme, и это заставило меня выдернуть волосы;)
Остин Хенли,
1
Теперь я испытываю желание собрать свой язык в свой собственный диалект Лиспа!
Остин Хенли
1
Смотрите также Лисп в маленьких
кусочках
0

Я поместил это (~ 600 строк C #) в общественное достояние, которое поддерживает quote / list / apply / eval / test / etc и позволяет легко настроить Lisp-подобный синтаксис и / или семантические встроенные функции:

https://repl.it/CdjV/3

Например:

        var factorial = (Lambda)language.
            Evaluate
            (@"
                ( => ( n ) (
                        ? ( != n 0 )
                        ( * n ( this ( - n 1 ) ) )
                        1
                    )
                )
            ");

        var sw = new System.Diagnostics.Stopwatch();
        var n = 12;
        var r = 0;
        int k;
        sw.Start();
        for (k = 0; k < 10000; k++)
        {
            r = (int)factorial.Invoke(null, n);
        }
        sw.Stop();
        Console.WriteLine("{0}! = {1}", n, r);
        Console.WriteLine();
        Console.WriteLine("in {0} ms (for {1} times)", sw.ElapsedMilliseconds, k.ToString("0,0"));

«НТН,

YSharp
источник
0

Предполагая, что вы немного знакомы со Scheme (например, читали SICP ) или Lisp, я рекомендую книгу Queinnec Lisp In Small Pieces . Он объясняет несколько вариантов Lisp-подобных интерпретаторов и компиляторов (включая байт-код или C).

Кроме того, прочитайте « Прагматику языка программирования» Скотта , последнюю « Книгу драконов» , справочник по ГК , « Типы и языки программирования» Пирса .

Я ищу информацию о том, как перейти от компилятора к интерпретатору.

Тогда частичная оценка (и проекции Футамуры) и стиль продолжения могут быть важны.

Василий Старынкевич
источник