как lisp реализован на языке ассемблера? [закрытый]
многие (может быть все?) язык программирования состоит из ассемблера
Как lisp реализован на языке ассемблера?
есть ли хорошая ссылка, руководство, учебник или ключевое слово для google?
любое официальное правило / конвенция для создания собственной реализации lisp?
например, хвостовая рекурсия должна следовать какому-то правилу воплощения или чему-то еще..
спасибо
5 ответов
хотя другие комментарии и сообщения правы, этот вопрос слишком расплывчатый и, возможно, немного запутанный, я не могу не поделиться некоторыми рекомендациями. Я собрал ряд ссылок и книг по реализации Lisp, поскольку я недавно развил немного очарование реализацией языка. Конечно, это глубокая тема, но чтение материалов, связанных с Lisp, особенно убедительно, потому что вы можете пропустить много интенсивного чтения при разборе, если вы реализуете компилятор Lisp или переводчик в Лиспе, и просто используйте read
. Это позволяет авторам быстро добраться до сути компиляции или интерпретации. Эти рекомендации-книги, которые я прочитал, или начал, или читаю, и в основном касаются схемы, а не обычного Шепелявства, но все же могут представлять некоторый интерес.
Если у вас нет опыта в языковой реализации и вы никогда не имели удовольствия читать о классическом Lisp и схеме "метациркулярные оценщики", я бы рекомендовал структура и Интерпретация компьютерных программ. Если вы видели Lisp-in-Lisp (или Scheme-in-Scheme...) можно пропустить. В последних двух главах SICP авторы представляют несколько различных интерпретаторов Lisp / Scheme и несколько вариантов, а также компилятор байтового кода и виртуальную машину. Это просто блестящая и бесплатная книга.
Если у вас нет времени читать SICP или не хотите пробираться через него, чтобы добраться до глав интерпретации и компиляции, я бы рекомендовал Маленький Интриган. Хотя он очень короткий и предназначен для новичков в Lisp и Scheme, если вы никогда не видели переводчика Lisp, написанного на Lisp, они представляют его, и это довольно восхитительная книга, но может быть не для всех из-за симпатичного стиля.
есть еще одна бесплатная книга по схеме, похожей на SICP, называется введение в схему и ее реализацию, который я не читал, но использовал в качестве ссылки для нескольких бит. Есть разделы об интерпретаторах и компиляторах там, и это, кажется, немного глубже, чем SICP, имея дело с более волосатыми вещами, такими как разбор. Возможно, ему нужен был редактор, но тем не менее это впечатляющее предложение.
с приличным представлением о том, как делать Lisp в Lisp, вы можете подойти к реализации Lisp на более низком уровне.
шепелявить маленькими кусочками часто рекомендуют. Я прочитал большую часть этого и могу сказать, что это определенно отличная книга, полная nitty песчаный материал. Я возвращаюсь к нему с прекрасной расческой, потому что его легко снять, когда вы ничего не понимаете. Я также боролся с получением кода с сайта автора для запуска; если вы его получите, я рекомендую использовать схему Гамбита и запускать код, который полагается на Meroonet с Meroon, от этой рассылки. Lisp в небольших частях представляет ряд интерпретаторов, написанных в схеме, а также компилятор байтового кода и компилятор-к-C.
Lisp в небольших частях движется быстро, и он довольно плотный. Если это слишком много для вас, возможно, начинаются с основы языков программирования. Я читал некоторые из них, и это довольно хорошо, но это больше переводчиков. По-видимому, одно из старых изданий (1st? Я не уверен...) включен компилятор. Кажется, что между выпусками 3 много изменений, но первый супер дешевый на Amazon, поэтому проверьте его.
что касается компиляции на C, это своего рода грубая тема с большим количеством волосатых биты. Компиляция на C вызывает все эти странные угловые проблемы, такие как оптимизация хвостовых вызовов и обработка замыканий, первоклассные продолжения и сбор мусора, но это довольно интересно, и много "реальных" реализаций схемы идут по этому маршруту. Презентация Марка Фили об этом довольно интересная, под названием 90-минутная схема компилятора C.
У меня меньше ресурсов для компиляции вплоть до сборки, но есть часто рекомендуемый документ который вводит компиляцию схемы в x86, называемую инкрементный подход к построению компилятора. предполагается, мало читателей, но я обнаружил, что он просто идет слишком быстро и не достаточно детально. Может, тебе повезет больше.
многие из вышеперечисленных рекомендаций исходит из этого комментария монстра на хакерских новостях более года назад, от Махмуд. Он ссылается на ряд ресурсов ML и компиляцию с использованием продолжений. Я у меня в кабинете не так далеко зашло, поэтому я не могу сказать, что хорошо, а что плохо. Но это невероятно ценный комментарий. Упомянутые работы включают в себя "компиляцию с продолжениями" Эндрю Аппеля и "методы сбора мусора" пола Уилсона.
удачи!
Я немного думал об этом в прошлом (затем прибегнул к использованию ядра C). Конечно, нет единой "сборки", но для x86/32bit это то, что я планировал:
базовые значения хранятся в 64-битных узлах с тремя самыми низкими битами, используемыми в качестве тега со следующим значением:
000 -> cell (64 bits are basically two pointers: car/cdr)
001 -> fixnum (64-3-1 bits usable for values)
010 -> vector (32-3 bits for size and 32 bit for pointer to first element)
011 -> symbol (32 bits pointing to values in global env, 32 pointing to name)
100 -> native code (32 bits pointing to executable machine code, 32 bits to args)
101 -> float (using 64-3-1 bit by dropping 4 bits from mantissa)
110 -> string (using 32-3 bits for size and 32 bits pointing to bytes)
111 -> struct (32 bits pointing to definition, 32 bits pointing to content)
3 бита остаются полезными при рассмотрении указателей, если все распределения считаются кратными 8 байтам (разумно с размером ячейки 8 байтов). Один дополнительный бит будет необходимых для реализации простого сборщика мусора ("живой" бит). В реализации C я в конечном итоге выделил этот бит в различных частях (например, наименее значительный бит более высоких 32 бит, если это был указатель) в зависимости от типа узла.
моя идея состояла в том, чтобы иметь память двух типов: "память узлов" (с описанным выше макетом), которая была выделена на страницах и повторно использована со свободным списком, и "двоичная память", которая будет использоваться для переменной размера строки/код/массивы.
конкретный код, нужно в зависимости от типа узла для реализации touch
функция, рекурсивно помечающая как живые узлы, на которые ссылается живой узел.
все это, конечно, просто наивный подход, но все же я получил его работу в "C", и я уверен, что мог бы сделать это и в сборке (мой код C использует void *
везде так в основном просто портативный 32-битный ассемблер). Для lazyness в моей реализации C я использовал только 32 бита для поплавков и для целых чисел (используя более высокие 32 бита) вместо использования всех доступных битов.
посмотри Clozure Common Lisp для примера языка ассемблера, используемого при реализации lisp. Clozure CL в основном реализован в Common Lisp, но есть ядро, написанное на C, и некоторые функции низкого уровня в сборке.
например, вот макрос из компилятор / X86 / x86-lapmacros.шепелявить!--10--> реализует первобытный CAR
функция на оборудовании x86, с одной инструкцией по сборке Для соответственно 32bit и 64бит:
(defx86lapmacro %car (src dest)
(target-arch-case
(:x8632
`(movl (@ x8632::cons.car (% ,src)) (% ,dest)))
(:x8664
`(movq (@ x8664::cons.car (% ,src)) (% ,dest)))))
как показано, код сборки сам кодируется в форме Lisp. Перенос на другую платформу включает (среди прочего) перевод этих низкоуровневых операций на другой язык ассемблера и кросс-компиляцию для создания среды выполнения на новой платформе.
ECL (Embeddable Common Lisp) использует другой подход, компилируя в C. Это позволяет удобно переносить реализацию на платформы, имеющие компилятор C.
Ваш вопрос основан на очень устаревших предположений. В наши дни почти никакие языковые реализации не написаны на языке ассемблера, и я не знаю никаких реализаций Lisp. Помимо само-хостинговых реализаций, C является общим языком реализации в эти дни.
Если вы хотите увидеть представление языка ассемблера функции lisp, есть демонтировать функцию.