В вычислительной технике метациклический оценщик ( MCE ) или метациклический интерпретатор ( MCI ) — это интерпретатор , который определяет каждую функцию интерпретируемого языка с помощью аналогичного средства основного языка интерпретатора. Например, интерпретация лямбда-приложения может быть реализована с помощью функционального приложения. [1] Метациклическая оценка наиболее заметна в контексте Lisp . [1] [2] Самоинтерпретатор — это метациклический интерпретатор, в котором интерпретируемый язык почти идентичен основному языку; эти два термина часто используются как синонимы. [3]
Диссертация Коррадо Бёма [4] описывает разработку самодостаточного компилятора. [5] Из-за сложности компиляции функций высшего порядка многие языки были определены с помощью интерпретаторов , наиболее известным из которых является Lisp. [1] [6] Сам термин был придуман Джоном К. Рейнольдсом [1] и популяризирован благодаря его использованию в книге «Структура и интерпретация компьютерных программ» . [3] [7]
Самоинтерпретатор — это мета-круговой интерпретатор, где принимающий язык также является интерпретируемым языком. [8] Самоинтерпретатор демонстрирует универсальную функцию для рассматриваемого языка и может быть полезен при изучении определенных аспектов языка. [2] Самоинтерпретатор предоставит круговое, бессодержательное определение большинства языковых конструкций и, таким образом, даст мало информации о семантике интерпретируемого языка, например, стратегии оценки . Решение этих проблем приводит к более общему понятию «определяющего интерпретатора». [1]
Эта часть основана на разделе 3.2.4 диссертации Дэнви. [9]
Вот ядро самооценщика для исчисления. Абстрактный синтаксис исчисления реализован следующим образом в OCaml , представляя переменные с их индексом де Брейна , т.е. с их лексическим смещением (начиная с 0):
тип term = IND int ( * индекс де Брёйна *) | АБС срока | Приложение срока * срока
Оценщик использует среду:
тип значение = FUN из ( значение -> значение )пусть получит eval ( t : term ) ( e : valuelist ) : value = сопоставить t с IND n - > List.nth e n | ABS t ' -> FUN ( fun v -> eval t' ( v :: e )) | APP ( t0 , t1 ) - > apply ( eval t0 e ) ( eval t1 e ) и применить ( FUN f : value ) ( a : value ) = f a пусть main ( t : term ) : value = eval t []
Значения (типа value
) объединяют выражаемые значения (результат оценки выражения в среде) и обозначаемые значения (значения, обозначаемые переменными в среде), терминология, которая принадлежит Кристоферу Стрейчи . [10] [11]
Окружения представлены в виде списков обозначаемых значений.
Основной оценщик состоит из трех пунктов:
Этот оценщик является композиционным в том смысле, что каждый из его рекурсивных вызовов выполняется над соответствующей подчастью данного термина. Он также является более высокого порядка, поскольку область значений является функциональным пространством.
В «Definitional Interpreters» Рейнольдс ответил на вопрос, хорошо ли определен такой самоинтерпретатор. Он ответил отрицательно, потому что стратегия оценки определенного языка (исходного языка) определяется стратегией оценки определяющего языка (метаязыка). Если метаязык следует вызову по значению (как это делает OCaml), исходный язык следует вызову по значению. Если метаязык следует вызову по имени (как это делает Algol 60 ), исходный язык следует вызову по имени. И если метаязык следует вызову по потребности (как это делает Haskell ), исходный язык следует вызову по потребности.
В "Definitional Interpreters" Рейнольдс сделал самоинтерпретатора хорошо определенным, сделав его независимым от стратегии оценки его определяющего языка. Он исправил стратегию оценки, преобразовав самоинтерпретатор в Continuation-Passing Style , который независим от стратегии оценки, как позже было зафиксировано в теоремах независимости Гордона Плоткина . [12]
Более того, поскольку логические отношения еще не были обнаружены, Рейнольдс сделал полученный оценщик продолжения первым порядком, (1) преобразовав его в замыкание и (2) дефункционализировав продолжение. Он указал на «машиноподобное качество» полученного интерпретатора, которое является источником машины CEK , поскольку преобразование CPS Рейнольдса было для вызова по значению. [13] Для вызова по имени эти преобразования отображают самоинтерпретатор на ранний экземпляр машины Кривина . [14] Машина SECD и многие другие абстрактные машины могут быть интерпроизведены таким образом. [15] [16]
Примечательно, что три самые известные абстрактные машины для исчисления функционально соответствуют одному и тому же самоинтерпретатору.
Все языки функционального программирования , которые строго нормализуют, не могут быть полными по Тьюрингу , в противном случае можно было бы решить проблему остановки, посмотрев, проверяет ли программа типы. Это означает, что существуют вычислимые функции, которые не могут быть определены в полном языке. [17] В частности, невозможно определить самоинтерпретатор в полном языке программирования, например, в любом из типизированных лямбда-исчислений, таких как просто типизированное лямбда-исчисление , Система F Жана-Ива Жирара или исчисление конструкций Тьерри Коканда . [ 18] [19] Здесь под «самоинтерпретатором» мы подразумеваем программу, которая принимает представление исходного терма в некотором простом формате (например, строку символов) и возвращает представление соответствующего нормализованного терма. Этот результат невозможности не распространяется на другие определения «самоинтерпретатора». Например, некоторые авторы называют функции типа самоинтерпретаторами, где — тип представлений -типизированных термов. Чтобы избежать путаницы, мы будем называть эти функции самораспознавателями . Браун и Палсберг показали, что самораспознаватели могут быть определены в нескольких сильно нормализующих языках, включая System F и System F ω . [20] Это оказалось возможным, поскольку типы закодированных терминов, отраженные в типах их представлений, не позволяют построить диагональный аргумент . В своей статье Браун и Палсберг утверждают, что опровергают «общепринятое мнение» о том, что самоинтерпретация невозможна (и ссылаются на Википедию как на пример общепринятого мнения), но на самом деле они опровергают невозможность самораспознавателей, отдельного понятия. В своей последующей работе они переходят на более конкретную терминологию «самораспознавателей», используемую здесь, в частности, отличая их от «самооценивателей» типа . [21] Они также признают, что реализация самооценки кажется сложнее, чем самораспознавания, и оставляют реализацию первой в сильно нормализующем языке как открытую проблему.
В сочетании с существующей реализацией языка метациклические интерпретаторы предоставляют базовую систему, от которой можно расширять язык, либо вверх, добавляя больше функций, либо вниз, компилируя функции, а не интерпретируя их. [22] Они также полезны для написания инструментов, которые тесно интегрированы с языком программирования, например, сложных отладчиков. [ требуется цитата ] Язык, разработанный с учетом метациклической реализации, часто больше подходит для создания языков в целом, даже тех, которые полностью отличаются от базового языка. [ требуется цитата ]
Во многих языках есть одна или несколько метациклических реализаций. Ниже приведен частичный список.
Некоторые языки с метациклической реализацией, разработанной снизу вверх, сгруппированы в хронологическом порядке:
Некоторые языки с метациклической реализацией через третьих лиц: