В SECD Machine как работает рэп?

Я пишу симулятор SECD-машины на C#, руководствуясь описанием в Википедии. У меня завершены основные операции, но я не уверен, как реализовать rap инструкция.

В Википедии говорится о rap:

рэп работает как ap, только то, что заменяет вхождение фиктивной среды на текущую, что делает возможными рекурсивные функции

И для ap это говорит:

ap открывает закрытие и список значений параметров из стека. Замыкание применяется к параметрам, устанавливая его окружение как текущее, выдвигая перед ним список параметров, очищая стек и устанавливая C для указателя функции замыкания. Предыдущие значения S, E и следующее значение C сохраняются в дампе.

Вот моя реализация ap

    public void ap() 
    { 
        Push(S, ref D); 
        Push(E, ref D); 
        Push(C, ref D); 
        List closure = Pop(ref S);
        List paramlist = Pop(ref S);
        E = closure.Tail;
        Push(paramlist, ref E);
        C = closure.Head;
        S = List.Nil;
    }

Обратите внимание, что List моя реализация "против" ячейки в стиле Lisp.

Что смущает меня именно как rap отличается от ap? Например, что именно происходит с регистром среды (E)? Я нахожу определение в Википедии несколько двусмысленным и не смог найти ничего другого, что бы это хорошо объясняло.

3 ответа

Решение

SECD is not tail recursive, although you can build a tail recursive SECD machine (PDF).

The AP instruction is used to compile a 'let' binding whereas the RAP instruction is used to compile a 'letrec' binding.

'letrec' is different from 'let' because you can 'see' the environment where the recursive function is defined, so that you can call it recursively (so, for instance, you define a 'factorial' function and you can call it in the body of the function).

RAP изменяет среду, вызывая rplaca (аналогично setcar! В схеме). Предыдущая инструкция DUM добавляет в среду "фиктивный" автомобиль (который никогда не используется), а RAP удаляет этот "фиктивный" автомобиль в среде и заменяет его соответствующим.

Состояния переходов таковы:

((c'.e ') vs) e               (AP.c)  d         =>
NIL          (v.e')          c'      (s e cd)

((c'.e ') vs) (?.e)           (RAP.c) d         =>
NIL          (setcar! E ', v) c' (sed)

Смотрите также Revisiting SECD и мощь Lisp, цитируя:

Инструкция RAP используется для поддержки рекурсивных вызовов функций и работает путем замены ранее созданной фиктивной среды в стеке, называемой OMEGA, на ту, которая содержит все функции, видимые в рекурсивной области. Спецификация использует RPLACA для обозначения этой операции замены, и это то, что мы использовали в нашей реализации SECD на Lisp:

а также

При попытке реализовать RAP в Erlang я застрял, потому что в списках нет разрушительных операций. Не в стандартном API и, похоже, не в системном API. Итак, Erlang SECD выглядит красиво, только не запускается.

Вы действительно должны взять копию замечательной маленькой книги Питера Хендерсона "Применение и внедрение функционального программирования". В нем он тщательно описывает и создает SECD-машину и Lispkit Lisp.

В дополнение к превосходному принятому ответу, я хотел бы дать больше объяснения того, почему rap необходимо.

Окружающая среда (E в SECD) хранит все постоянные объекты (функции, константы, переменные и т. д.). E по сути, это стек списков. Вещи в E загружаются в стек S а затем выполняется или используется командами в C, Все в E дается идентификатор, чтобы на него можно было ссылаться позже. Этот идентификатор обычно является кортежем (x,y), где x представляет местоположение списка в стеке, и y представляет позицию в этом списке.

При типичном вызове функции добавляется новый список E и теперь любые локальные переменные могут иметь идентификаторы, такие как (|E|, y), где |E| обозначает размер E, Однако это очень проблематично для рекурсивных функций, поскольку размер стека увеличивается с каждым вызовом функции, поэтому нет возможности назначить локальным переменным идентификаторы, которые можно использовать.

Для решения этой проблемы, rap делает большинство вещей ap делает, но вместо того, чтобы помещать новый список в стек среды, он заменяет все, что находится во главе E с новым списком среды.

Другие вопросы по тегам