2010-07-04 18 views
9

Mam częściowo ukończony interpreter dla leksykalnego "czystego Lispa" o nazwie leksykalnej (nr set!), który korzysta z modelu oceny wymagającego wezwania, który jest dostępny do wywołania przez nazwę z prostym buforowaniem, interpreter używa w naturalny sposób modelu ewaluacyjnego opartego na środowisku.Obciążenie wywołania po nazwie/wywołanie po nazwie Strategia tłumacza Lispa

Standardowy sposób oceny abstrakcji lambda, jak w przypadku konstruowania nowego środowiska z formalnych paramatrów i środowiska, w którym abstrakcja jest oceniana i po prostu umieszczania w niej ocen argumentów w ich własnym środowisku. Wtedy ocena treści abstrakcji w nowym środowisku nie działałaby, ponieważ oznaczałaby semantykę "po-wartości".

Moim rozwiązaniem tego problemu było zastąpienie w razie potrzeby idei "środowisk" za pomocą "funkcji wyszukiwania", które po prostu biorą symbol jako argument i tworzą skojarzony układ odniesienia. Które można łatwo zrobić ze środowiska. Aplikacje Lambda są po prostu wykonywane poprzez ponowną ocenę ciała za pomocą funkcji wyszukiwania, która jest tworzona zarówno w środowisku, w którym leży definicja, jak i w kłamstwie. Który ocenia je leniwie i tylko wtedy, gdy jest to wymagane.

Co jednak zastanawiam się, co jest kosztowne z tego modelu, jak drogie jest generowanie tych wyszukiwań dla każdej aplikacji, kod dla tych wyszukiwań jest dość duży. Wiem, że aplikacja i tworzenie aplikacji lambda w Scheme jest dość tania, a wiele źródeł opowiada się za ich szerokim użyciem, aby zachować czytelność kodu, mimo że w wielu przypadkach mieliby niewielki narzut. Ale ponieważ aplikacje Lambda są wszechobecne w każdym seplenienie, zastanawiam się, ile można zaoszczędzić na wykorzystaniu potencjalnie innego modelu. Próbowałem wyszukiwać to w google, ale wszystkie modele dla potrzebujących tłumaczeń, które znalazłem, były jeszcze bardziej niezręczne, ale często tak, aby pomieścić dla set!.

Niektóre odpowiednie kawałki mojego kodu:

Oceniający, który korzysta z funkcji wyszukiwania:

; evaluates a datum using a lookup 
; lookup is a function which takes a symbol as an argument and produces the value 
; some sorts of more powerful environment 
; if lookup is a standard environment, treats it as such 
(define (eval-datum! d lookup) 
    (cond 
    ((quoted? d) (dequote d)) ; if quoted, just dequote 
    ((hastype d symbol-type) ; symbols ... 
    (if (procedure? lookup) ; checks if it's an environment or a lookup function 
     (lookup d) 
     (lookup-symbol d lookup))) 
    ((hastype d pair-type) (eval-pair! d lookup)) ; function application 
    (else d))) ; rest is considered self-evaluating 

a funkcja, która generuje bardziej zaawansowanych wyszukiwań. Szczególnie mnie to niepokoi, chociaż jest rekurencyjny i używa bardzo tanich porównań, nie wygląda na tak efektywny, jak zwykłe używanie assq na liście środowisk, a czasami nawet brak dostępu losowego na tych zmartwieniach mnie trochę.

; extends a lookup for use in a lambda abstraction 
; the inner environment is where the lambda is defined 
; the outer environment where it is applied 
; params can be either a pair or a symbol 
; params automatically tries to match the argument's pattern 
(define (extend-lookup! params args inner-env outer-env) 
    (lambda (s) 
    (let checkparams ((params params) (args args)) 
     (cond 
     ((eq? s params) (datum args)) ; for an improper list or a single symbol, simply turn the arglist into an evaluable list 
     ((null? params) (lookup-symbol s inner-env)) ; if the number of paramatres are exhausted, simply use the inner-env 
     ((eq? s (car params)) ; in case of a formal parametre match ... 
       (refeval! args 0 outer-env)) ; evaluate the needed argument and return it 
     (else (checkparams (cdr params) (cdr args))))))) ; repeat for the next paramatre 

To powinno być oczywiste, że oceniający działa poprzez prosty system termin redukcji że podczas oceny wyrażeń na liście po prostu zastępuje je ich wyniku, cytując je, gdy wynik nie jest uważany za siebie oceny. Co jest możliwe, ponieważ jest to czysto funkcjonalne seplenienie. Przechwytuje również buforowanie i większość wyrzucania elementów za jednym razem.

Powinienem dodać, że jedną z rzeczy, które zawsze miałem bardzo kiepską koncepcję, jest teoria ogólnych i złożoności. Dla tych, którzy mówią: "Jeśli chcesz wydajności, dlaczego robisz tłumacza w Lisp?", To tylko test ogólnej struktury, aby zobaczyć, czy to działa, będę ją ponownie pisać w C-- wystarczająco szybko.

Ah, nie mogłem nawet złożyć tego na początku, ponieważ tag "call-by-need" już nie istnieje, obiecujący początek.

+0

Zobacz książkę Queinnec * Lisp in Small Pieces *. W szczególności Chp. 6, gdzie buduje serię tłumaczy, z których każdy jest szybszy od poprzedniego. Wyjaśnia zalety i wady kilku technik. – Allen

Odpowiedz

1

Inną rzeczą, którą "ty" możesz zrobić, to po prostu oznaczyć każdy punkt odniesienia własnym środowiskiem, które można pobrać z niego w strukturze danych, może wydawać się wyczerpujące, ale na końcu wszystko, co musi zostać oznaczone, pochodzi myśleć o nim to listy i bardzo szczególny przypadek, że ciało abstrakcji lambda zawiera tylko jeden symbol.W przypadku innych danych w modelu "twój" jego ocena jest niezależna od środowiska.

Rozwiązuje to również poważny problem z leniwymi komórkami i listami, które są przekazywane do innych miejsc w programie.

Zakładając, że sama lista jest oznaczona środowiskiem, można po prostu wyodrębnić środowisko, gdy ją ocenisz.

Powiązane problemy