www

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

commit 709ef979c67725f02e158aa242141e0df76954ca
parent 57eb25bfd7e199e007edad68725d8b131143b2e7
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date:   Wed, 12 Jan 2011 00:06:42 +0100

Début de squash-lisp-3.

Diffstat:
Mlisp/main.lisp | 1-
Mlisp/notes/soutenance.markdown | 2+-
Mlisp/squash-lisp-1.lisp | 3++-
Alisp/squash-lisp-3.lisp | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlisp/test-unitaire.lisp | 2+-
5 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/lisp/main.lisp b/lisp/main.lisp @@ -12,7 +12,6 @@ (load "mini-meval") (load "squash-lisp") (load "squash-lisp-1") -(load "squash-lisp-2") (load "equiv-tests") (provide 'main) diff --git a/lisp/notes/soutenance.markdown b/lisp/notes/soutenance.markdown @@ -61,7 +61,7 @@ squash-lisp (lambda (x y) (+ x y)) → (simple-lambda (simple-let (x y) (setq x (get-param 0)) (setq y (get-param 1)) (+ x y))) * Passe 3 - * On lorsqu'une variable à l'intérieur d'une `lambda` référence une déclaration à l'extérieur de la `lambda`, on la marque comme étant *capturée*. + * Lorsqu'une variable à l'intérieur d'une `lambda` référence une déclaration à l'extérieur de la `lambda`, on la marque comme étant *capturée*. * On fusionne tous les `let` d'une `lambda` en les remontant dans un `let` unique à la racine de la `lamdba`. * On sort toutes les lambdas (fonctions anonymes), on les nomme avec un symbole unique, et on les met au top-level. diff --git a/lisp/squash-lisp-1.lisp b/lisp/squash-lisp-1.lisp @@ -286,6 +286,7 @@ (aux (cdr (assoc 'aux sliced-lambda-list)))) (push (cons whole-sym whole-sym) env-var) `(lambda (&rest ,whole-sym) + ,(transform whole-sym) ;; pour pas qu'il soit unused si aucun paramètre. ,(transform `(super-let (,@fixed ,@(mapcar #'car optional) @@ -477,7 +478,7 @@ Attention : il y a quelques invariants qui ne sont pas présents dans cette vér t) ((let ($$*) :body _) (squash-lisp-1-check body)) - ((lambda (&rest $$) :body _) + ((lambda (&rest $$) :unused _ :body (let ($$*) _*)) (squash-lisp-1-check body)) ((funcall :fun _ :params _*) (every #'squash-lisp-1-check (cons fun params))) diff --git a/lisp/squash-lisp-3.lisp b/lisp/squash-lisp-3.lisp @@ -0,0 +1,103 @@ +(require 'match "match") + +(defun squash-lisp-3 (expr local-env globals) + "Lorsqu'une variable à l'intérieur d'une `lambda` référence une déclaration à l'extérieur de la `lambda`, on la marque comme étant *capturée*. + + On fusionne tous les `let` d'une `lambda` en les remontant dans un `let` unique à la racine de la `lamdba`. + + On sort toutes les lambdas (fonctions anonymes), on les nomme avec un symbole unique, et on les met au top-level." + (macrolet ((transform (expr &optional (local-env 'local-env)) `(squash-lisp-3 ,expr ,local-env globals))) + (cond-match + expr + ;; simple-tagbody est équivalent à un progn, mais nécessaire pour les macrolet. + (((? (member x '(progn simple-tagbody))) :body _*) + (let ((res (list 'progn))) + (labels ((squash-progn (body) + (dolist (e body) + (if (and (consp e) (eq 'progn (car e))) + (squash-progn (cdr e)) + (push (squash-lisp-3 e local-env globals) res))))) + (squash-progn body)) + ;; TODO : ici : filtrer les expressions de `res' qui sont sans effet de bord, sauf la dernière. + (print res) + (if (cdr res) ;; res != '(progn) + (if (cddr res) ;; res != '(single-expr progn) + (reverse res) + (car res)) + '(quote nil)))) + ((if :condition _ :si-vrai _ :si-faux _) + (and (squash-lisp-3 condition) + (squash-lisp-3 si-vrai) + (squash-lisp-3 si-faux))) + ((unwind-protect :body _ :cleanup _) + (and (squash-lisp-3 body) + (squash-lisp-3 cleanup))) + ;; tagbody-unwind-catch est équivalent à unwind-catch, mais nécessaire pour les macrolet. + (((? (member x '(unwind-catch tagbody-unwind-catch))) :object _ :body (progn _*) :catch-code _) + (and (squash-lisp-3 object) + (squash-lisp-3 body) + (squash-lisp-3 catch-code))) + ((unwind :object _) + (squash-lisp-3 object)) + ((unwind-for-tagbody :object _ :post-unwind-code _) + (and (squash-lisp-3 object) + (squash-lisp-3 post-unwind-code))) + ((jump-label :name $$) + t) + ((jump :dest $$) + t) + ((let ($$*) :body _) + (squash-lisp-3 body)) + ((lambda :params (&rest $$) :unused _ :body (let ($$*) _*)) + (push let-vars stack) + (push `(lambda ,params + ,unused + (let (,let-vars) + ,(squash-lisp-3 body))) + top-level) + (setq let-vars (pop stack))) + ((funcall :fun _ :params _*) + (every #'squash-lisp-3 (cons fun params))) + ((quote _) + t) + ((get-var :var $$) + ;; chercher si var est dans local-env ou bien dans global + ;; si oui -> get-var + ;; sinon, -> get-captured-var + t) + ((setq :name $$ :value _) + ;; comme ci-dessus + (squash-lisp-3 value)) + ((fdefinition (quote $$)) + t) + ((symbol-value (quote $$)) + t) + ((set (quote $$) :value _) + (squash-lisp-3 value))))) + +(require 'test-unitaire "test-unitaire") +(erase-tests squash-lisp-3) + +(deftest (squash-lisp-3 progn) + (squash-lisp-3 '(progn + (progn (progn) (progn)) + (progn) + (progn (progn) (progn) (progn)))) + ''nil) + +(deftest (squash-lisp-3 progn) + (squash-lisp-3 '(progn)) + ''nil) + +(deftest (squash-lisp-3 progn) + (squash-lisp-3 '(progn (symbol-value 'a))) + '(symbol-value 'a)) + +(deftest (squash-lisp-3 progn) + (squash-lisp-3 '(progn + (progn (progn (symbol-value 'a)) (progn)) + (progn) + (progn (progn) (progn) (progn)))) + '(symbol-value 'a)) + +;(run-tests squash-lisp-3) +\ No newline at end of file diff --git a/lisp/test-unitaire.lisp b/lisp/test-unitaire.lisp @@ -152,7 +152,7 @@ (defmacro erase-tests (&optional module) (unless (listp module) (setq module (list module))) - `(test-remove-module ',module)) + `(progn (test-remove-module ',module) t)) (erase-tests test-unitaire) (deftest (test-unitaire copy-all)