www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 93f54283de2c42181c6c12c83dea4cab494cebab
parent cab9589f06a4bf012c056c52d630787ff641d030
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date:   Sat,  4 Dec 2010 20:59:11 +0100

implémentation ratée de la détection de capture pour le let & let*

Diffstat:
Mimplementation/squash-lisp.lisp | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mutil.lisp | 1+
2 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/implementation/squash-lisp.lisp b/implementation/squash-lisp.lisp @@ -1,4 +1,5 @@ (require 'mini-meval "implementation/mini-meval") +(require 'match "match") ;; TODO : emballer le résultat de squash-lisp dans un (macrolet ...) pour les "special-operator" qu'on rajoute. @@ -359,6 +360,18 @@ On a donc une pile de cette forme (les vieilles données sont en haut) : ((jump :dest _) expr) + ((let :bindings ((:name $$ :value _)*) :body _) + `(let ,(mapcar (lambda (n v) `(,n ,(squash-lisp v))) name value) + ,(squash-lisp body))) + + ((let :bindings _ :body _*) + (squash-lisp `(let ,bindings (progn ,@body)))) + + ;; TODO : simplifier la lambda-list. + + ((lambda :params _ :body _*) + (squash-lisp `(lambda ,params (progn ,@body)))) + ;; Les constantes sont renvoyées telles qu'elles ((? or numberp stringp) expr) @@ -367,6 +380,72 @@ On a donc une pile de cette forme (les vieilles données sont en haut) : (nil nil))) +(defun squash-lisp-3 (expr &optional env) + "Détecte les variables capturées." + (cond-match + expr + + ((let :bindings ((:name $$ :value _)*) :body _) + (let ((new-env (cons (mapcar-append (car env) (lambda (x) `(,x nil)) name) + (cdr env)))) + `(let ,(mapcar (lambda (x) (squash-lisp-3 x new-env)) bindings) + ,(squash-lisp-3 body new-env)))) + + (((? (eq x 'let*)) :bindings ((:name $$ :value _)*) :body _) + (let ((new-local-env (car env))) + `(let ,(mapcar (lambda (var val) (prog1 (squash-lisp-3 x (cons new-local-env (cdr env))) + (push `(x nil) new-local-env))) + name value) + ,(squash-lisp-3 body new-env)))) + + (let ((new-env (cons (mapcar-append (car env) (lambda (x) (list x nil)) name) (cdr env)))) + `(let ,(mapcar (lambda (x) (squash-lisp-3 x new-env)) bindings) + ,(squash-lisp-3 body new-env)))) + + ((lambda :params ($$*) :body _) + `(lambda ,params ;; TODO + ,(squash-lisp-3 body + (cons nil + (cons (mapcar-append (car env) + (lambda (x) (list x nil)) + (delete '&rest params)) + (cdr env)))))) + ((:fun $$ :args _*) + (cons fun (mapcar (lambda (x) (squash-lisp-3 x env)) args))) + ($$ ;; Utilisation d'une variable, à mettre tout à la fin ! + (let ((res (list 'maybe-indirection expr)) + (variable (assoc expr (car env))) + (search-env env) + (references nil)) + (if variable ;; Variable trouvée dans l'environnement local + (if (second variable) + `(indirection ,expr) + (progn (push res (cddr variable)) + res)) + (progn + (tagbody + search-loop + (setq search-env (cdr search-env)) + (when (endp search-env) + ;; TODO globals + (error "Globals not implemented yet !~&expr = ~a~&env = ~a" expr env) + (go fin)) + (setq variable (assoc expr (car search-env))) ;; Rechercher dans cet environnement + (unless variable + (go search-loop)) ;; Rechercher dans l'environnement suivant si on ne trouve pas. + (when (second variable) + (go fin)) ;; La variable est déjà marquée comme capturée + (setq references (cddr variable)) + (setf (cdr variable) '(t)) ;; Marquer la variable comme étant capturée + convert-to-captured-loop + (when (endp references) (go fin)) + (setf (caar references) 'indirection) ;; 'maybe-indirection -> 'indirection . + (setq references (cdr references)) + (go convert-to-captured-loop) + fin + (setq res (list 'indirection expr))) + res)))))) + #| ;; Formes pouvant créer des variables capturables : diff --git a/util.lisp b/util.lisp @@ -125,6 +125,7 @@ (flatten (cdr lst) rest (cons (car lst) result))))) (defun mapcar-append (append function &rest lists) + ;; TODO : dérécurser (cond ((null lists) append) ((member nil lists)