Как транслировать программный код?
Недавно я изучал Lisp (Scheme, Racket и Clojure в различной степени) и читал соответствующую литературу на известном разработчику Playstation Naughty Dog.
В этой статье Gamasutra упоминается, что их движок потоковой передачи фактически транслирует код игры в дополнение к игровым данным. Теперь у них есть диалект Lisp, называемый GOAL, который они широко используют. Я знаю о "коде как данных" Лиспа, хотя мне еще предстоит полностью реализовать эту концепцию. Итак, мне было интересно, является ли способность потокового кода свойством их кода быть данными Lisp или скомпилированным машинным кодом, а не общим шаблоном проектирования, который может использоваться во многих языках?
Может кто-нибудь указать мне литературу на эту тему?
Бонус: Может ли кто-нибудь указать мне на литературу по компиляторам для длительного прослушивания, как упомянуто в статье в Википедии?
3 ответа
"Слушатель" на языке Lisp - это REPL (Read Eval Print Loop). Слушатели обычно предоставляют несколько служб, таких как встроенный отладчик, истории команд, интерпретаторы команд и другие. Во многих случаях слушатель запускается внутри используемого Lisp. В некоторых случаях весь код, введенный в REPL/Listener, компилируется перед выполнением (например, Clozure CL, SBCL). Если это не так, код может быть скомпилирован по требованию (см. Функции COMPILE или COMPILE-FILE в Common Lisp).
Здесь я бы предположил, что среда разработки была реализована в Allegro Common Lisp и среда выполнения работает на Playstation. Среда разработки предоставляет интерфейс для взаимодействия со средой выполнения и позволяет компилировать код и загружать его во время выполнения. Я предполагаю, что компилятор работает не на Playstation, а в среде разработки. Слушатель также обеспечивает функциональность для просмотра состояния запущенного приложения на Playstation, включая таблицу символов. Таким образом, один подключает среду разработки к работающему приложению Playstation и может взаимодействовать с ним, включая изменение данных и кода.
Поскольку типичный Lisps может загружать как исходный, так и скомпилированный код во время выполнения, потоковый код не так сложен. Это просто означает, что вы загружаете код (возможно, в фоновом режиме), пока игрок перемещается в игре. Если код организован определенным образом, он также может быть собран мусором, когда он больше не нужен. Например, если "комната" в игре является объектом, и комната указывает на различные функции по имени, функции могут быть автоматически загружены по требованию, если игрок находится в комнате. Если игрок покидает комнату, код может быть автоматически или полуавтоматически выгружен. В типичном Лиспе сборщик мусора собирал бы код без ссылок. В игре, которая может быть задачей не GC, а какого-то другого, более "ручного" процесса. Это будет функциональность среды выполнения GOAL. Сравните это со стандартной JVM, которая не может собирать выгруженный код (AFAIK).
Их механизм потоковой передачи более или менее повторяет то, что загрузка DLL (windows), SO(Linux) или Dylib делает на более общих ОС, и не так уж интересен, если не считать того, что они реализовали его сами. Это не имеет ничего общего с языком, который они используют. Что касается долгосрочных прослушивающих компиляторов, то это первый раз, когда я слышу редактирование и продолжаю приписывать его компилятору, это, как правило, особенность отладчика.
Я немного разбирался с подобными вещами в Common Lisp, и ваш код может выглядеть так:
on connection:
read Lisp form
eval Lisp form
close connection
Концептуально он не сильно отличается от, скажем, слизи.
Также обратите внимание, что из-за природы Common Lisp, код с возможностью горячей замены не важен.