www

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

commit 5747936c8f2161ef6627c5940898a5b0582065f6
parent 27eb8532d6e1f58b8b730ddac5436f30b17a6217
Author: Bertrand BRUN <bertrand.brun@me.com>
Date:   Fri,  5 Nov 2010 18:15:22 +0100

Recodage de la fonction lisp2li, car le langage intermediaire genere par la fonction ne correspondait pas au attente du prof

Diffstat:
Mlisp2li.lisp | 406++++++++++++++++++++++++++++---------------------------------------------------
Mtest-unitaire.lisp | 2+-
2 files changed, 144 insertions(+), 264 deletions(-)

diff --git a/lisp2li.lisp b/lisp2li.lisp @@ -1,24 +1,25 @@ -(load "environnement") -(erase-tests lisp2li) - +(load "util.lisp") ;; ` -(defvar my-quasiquote (car '`(,foo))) +(defvar my-quasiquote (car '`(,a))) ;; , -(defvar my-unquote (caaadr '`(,foo))) +(defvar my-unquote (caaadr '`(,a))) ;; ,@ -(defvar my-unquote-unsplice (caaadr '`(,@foo))) +(defvar my-unquote-unsplice (caaadr '`(,@a))) -(defun map-lisp2li (expr env-var env-fun) - (mapcar (lambda (x) (lisp2li x env-var env-fun)) expr)) +(defun map-lisp2li (expr env) + (mapcar (lambda (x) (lisp2li x env)) expr)) -(defun map-lisp2li-let (expr env) - (mapcar (lambda (x) (add-binding env (car x) (lisp2li (cadr x) env))) (cadr expr))) - -(defun make-stat-env (env params) - (mapcar (lambda (x) (add-binding env x nil)) params) - env) +(defun make-stat-env (params &optional env) + (append + (loop + for var in params + for j = 1 then (+ j 1) + for num-env = (+ (or (second (first env)) -1) 1) + collect (list var num-env j) + ) + env)) (defun transform-quasiquote (expr) (cond @@ -43,259 +44,138 @@ (T `(cons ,(transform-quasiquote (car expr)) ,(transform-quasiquote (cdr expr)))))) + +(defmacro get-defun (symb) + `(get ,symb :defun)) + +(defun set-defun (li) + (setf (get-defun (cdaddr li)) (cdddr li))) -(defun lisp2li (expr env-var env-fun) +(defun lisp2li (expr env) "Convertit le code LISP en un code intermédiaire reconnu par le compilateur et par l’interpréteur" - (cond ((null env-var) (lisp2li expr (empty-env-stack) env-fun)) - ((null env-fun) (lisp2li expr env-var (empty-env-stack))) - ;; literaux - ((and (atom expr) (constantp expr)) - (cons :lit expr)) - ;; symboles - ((symbolp expr) - (let ((cell (get-binding env-var expr))) - (if cell - (cons :var (car cell)) - (error "Variable ~S unknown" expr)))) - ;; lambda solitaire ex: (lambda (x) x) - ((eq 'lambda (car expr)) - (let ((env-bis (make-stat-env (push-new-env env-var "LAMBDA") (second expr)))) - `(:lclosure (,env-bis . ,env-fun) - ,(lisp2li (third expr) - env-bis env-fun)))) - ;; lambda ex: ((lambda (x) x) 1) - ((and (consp (car expr)) - (eq 'lambda (caar expr))) - `(:call ,(lisp2li (car expr) env-var env-fun) - ,@(mapcar (lambda (param) - (lisp2li param env-var env-fun)) - (cdr expr)))) - ;; (not-symbol ...) - ((not (symbolp (car expr))) - (warn "~S isn't a symbol" (car expr))) - ;; fonction inconnue - ((and (not (fboundp (car expr))) (not (get-binding env-fun (car expr)))) - `(:unknown ,expr (,env-var . ,env-fun))) - ;; if - ((eq 'if (car expr)) - (list :if - (lisp2li (second expr) env-var env-fun) - (lisp2li (third expr) env-var env-fun) - (lisp2li (fourth expr) env-var env-fun))) - ;; quote - ((eq 'quote (car expr)) - (cons :lit (second expr))) - ;; quasiquote ` - ((eq my-quasiquote (car expr)) - (lisp2li (transform-quasiquote (cadr expr)) env-var env-fun)) - ;; #'fn (FUNCTION fn) - ((eq 'function (car expr)) - (list :call 'function (car expr))) - ;; defun - ((eq 'defun (car expr)) - (let ((env-bis (make-stat-env (push-new-env env-var "DEFUN") (third expr)))) - (add-top-level-binding env-fun - (second expr) - (cons :lclosure (cons (cons env-bis env-fun) - (map-lisp2li (cdddr expr) - env-bis env-fun))))) - (cons :lit (second expr))) - ;; defvar - ((eq 'defvar (car expr)) - (add-top-level-binding env-var - (second expr) - (lisp2li (third expr) env-var env-fun))) - ;; setq/setf - ((eq 'setq (car expr)) - (cons :call (cons 'set-binding (list `(:lit . ,env-var) - (cons :lit (second expr)) - (cons :lit (third expr)))))) - ;; let - ((eq 'let (car expr)) - (let ((bindings (cadr expr)) - (body (cddr expr))) - (lisp2li `((lambda ,(mapcar #'car bindings) - ,@body) - ,@(mapcar #'cadr bindings)) env-var env-fun))) - ;; let* - ((eq 'let* (car expr)) - (let ((bindings (cadr expr)) - (body (caddr expr))) - (lisp2li (if (endp bindings) - body - `(let (,(car bindings)) - (let* ,(cdr bindings) - ,body))) env-var env-fun))) - ;; labels - ((eq 'labels (car expr)) - (let ((bindings (cadr expr)) - (body (cddr expr))) - (lisp2li `((lambda ,(mapcar #'car bindings) - ,@body) - ,@(mapcar #'cadr bindings)) env-var env-fun))) - ;; ` - ((eq '` (car expr)) - (print "Ca marche")) - ;; progn - ((eq 'progn (car expr)) - (cons :progn (map-lisp2li (cdr expr) env-var env-fun))) - ;; macros - ((macro-function (car expr)) - (lisp2li (macroexpand-1 expr) env-var env-fun)) - ;; fonctions normales - ((not (special-operator-p (car expr))) - (cons :call (cons (first expr) (map-lisp2li (cdr expr) env-var env-fun)))) - (T - (print expr) - (error "special form not yet implemented ~S" (car expr))) - )) - -(defun map-lisp2li (expr env-var env-fun) - (mapcar (curry #'lisp2li :skip env-var env-fun) expr)) - -(defun map-lisp2li-let (expr env) - (mapcar (lambda (x) (add-binding env (car x) (lisp2li (cadr x) env))) (cadr expr))) - -(defun make-stat-env (env params) - (mapcar (lambda (x) (add-binding env x nil)) params) - env) + (cond + ;; literaux + ((and (atom expr) (constantp expr)) + (cons :const expr)) + ;; symboles + ((symbolp expr) + (let ((cell (assoc expr env))) + (if cell + `(:cvar ,(cadr cell) ,(caddr cell)) + (error "Variable ~S unknown" expr)))) + ;; lambda solitaire ex: (lambda (x) x) + ((eq 'lambda (car expr)) + `(:lclosure . ,(cons (length (second expr)) + (lisp2li (third expr) + (make-stat-env (second expr)))))) + ;; lambda ex: ((lambda (x) x) 1) + ((and (consp (car expr)) + (eq 'lambda (caar expr))) + `(:mcall ,(lisp2li (car expr) env) + ,@(mapcar (lambda (param) + (lisp2li param env)) + (cdr expr)))) + ;; (not-symbol ...) + ((not (symbolp (car expr))) + (warn "~S isn't a symbol" (car expr))) + ;; fonction inconnue + ((and (not (fboundp (car expr))) + (not (get-defun (car expr)))) + `(:unknown ,expr ,env)) + ;; if + ((eq 'if (car expr)) + (list :if + (lisp2li (second expr) env) + (lisp2li (third expr) env) + (lisp2li (fourth expr) env))) + ;; quote + ((eq 'quote (car expr)) + (cons :const (second expr))) + ;; quasiquote ` + ((eq my-quasiquote (car expr)) + (lisp2li (transform-quasiquote (cadr expr)) env)) + ;; #'fn (FUNCTION fn) + ((eq 'function (car expr)) + `(:sclosure (cadr expr))) + ;; defun + ((eq 'defun (car expr)) + `(:mcall set-defun (:const . ,(second expr)) + ,(lisp2li `(lambda ,(third expr) ,@(cdddr expr)) env))) + ;; apply + ((eq 'apply (car expr)) + `(:sapply ,(second expr) (cddr expr))) + ;; setf + ((eq 'setf (car expr)) + (if (symbolp (cadr expr)) + (let ((cell (assoc (cadr expr) env))) + `(:set-var (,(second cell) ,(third cell)) ,(third expr))) + `(:set-fun ,(caadr expr) ,@(last expr) ,@(cdadr expr)))) + ;; progn + ((eq 'progn (car expr)) + (cons :progn (map-lisp2li (cdr expr) env))) + ;; macros + ((macro-function (car expr)) + (lisp2li (macroexpand-1 expr) env)) + ;; foctions normales + ((not (special-operator-p (car expr))) + `(:call ,(first expr) ,@(map-lisp2li (cdr expr) env))) + (T + (print expr) + (error "special form not yet implemented ~S" (car expr))))) ;; Test unitaire (load "test-unitaire") (erase-tests lisp2li) -(deftest (lisp2li :lit) - (lisp2li '3 () ()) - '(:lit . 3)) - -(deftest (lisp2li :lit) - (lisp2li ''x () ()) - '(:lit . x)) - -(deftest (lisp2li :lit) - (lisp2li ''(1 2 3) () ()) - '(:lit 1 2 3)) - -;; test des if -(deftest (lisp2li :if) - (lisp2li '(if T T nil) () ()) - '(:if (:lit . T) (:lit . T) (:lit . nil))) - -(deftest (lisp2li :if) - (lisp2li '(if T nil T) () ()) - '(:if (:lit . T) (:lit . nil) (:lit . T))) - -;; test des fonctions predefinies -(deftest (lisp2li :call) - (lisp2li '(eq 1 1) () ()) - '(:call eq (:lit . 1) (:lit . 1))) - -(deftest (lisp2li macros) - (lisp2li '(and 1 1) () ()) - '(:lit . 1)) - -;; test des variables -(deftest (lisp2li :var) - (lisp2li 'x '(("TOP-LEVEL" (x . 1) (y . 2))) ()) - '(:var . x)) - -(deftest (lisp2li :var) - (lisp2li '(if (eq x 3) (- x 3) (+ x 3)) '(("TOP-LEVEL" (x . 3))) ()) - '(:if (:call eq (:var . x) (:lit . 3)) - (:call - (:var . x) (:lit . 3)) - (:call + (:var . x) (:lit . 3)))) - -(deftest (lisp2li :var) - (lisp2li '(if (eq x 3) - (- z 3) - (- x 5)) - '(("TEST" (z . 5)) ("TOP-LEVEL" (x . 4))) ()) - '(:IF (:CALL EQ (:VAR . X) (:LIT . 3)) (:CALL - (:VAR . Z) (:LIT . 3)) - (:CALL - (:VAR . X) (:LIT . 5)))) - -;; Test avec des expression plus complexe -(deftest (lisp2li complexe) - (lisp2li '(if (eq 1 1) 2 2) () ()) - '(:if (:call eq (:lit . 1) (:lit . 1)) (:lit . 2) (:lit . 2))) - -(deftest (lisp2li complexe) - (lisp2li '(if (eq "abc" 1) "abc" 2) () ()) - '(:IF (:CALL EQ (:LIT . "abc") (:LIT . 1)) (:LIT . "abc") (:LIT . 2))) - -(deftest (lisp2li :unknown) - (lisp2li '(foo 1 1) () ()) - '(:unknown (foo 1 1) ((("TOP-LEVEL")) ("TOP-LEVEL")))) - -(deftest (lisp2li :unknown) - (lisp2li '(if (and (eq 1 1) (= 2 2)) (foo 1 2) (bar 3 4)) () ()) - '(:IF (:CALL = (:LIT . 2) - (:LIT . 2)) - (:UNKNOWN (FOO 1 2) ((("TOP-LEVEL")) ("TOP-LEVEL"))) - (:UNKNOWN (BAR 3 4) ((("TOP-LEVEL")) ("TOP-LEVEL"))))) - -;; Test sur le setq -(deftestvar (lisp2li setq) env (add-binding (empty-env-stack) 'x 1)) -(deftest (lisp2li setq) - (lisp2li '(setq x 2) env ()) - '(:call set-binding (:lit . (("TOP-LEVEL" (x . 1)))) (:lit . x) (:lit . 2))) - -;; Test sur le defun -(deftest (lisp2li defun valeur-de-retour) - (lisp2li '(defun fact (n r) - (if (= n 0) - r - (fact (- n 1) (* n r)))) - () ()) - '(:lit . fact)) - -(deftestvar (lisp2li defun environnement) env (empty-env-stack)) -(deftest (lisp2li defun environnement) - (progn - (lisp2li '(defun fact (n r) - (if (= n 0) - r - (fact (- n 1) (* n r)))) - () env) - env) - '#1=(("TOP-LEVEL" - (FACT :LCLOSURE (#2=(("DEFUN" (R) (N)) ("TOP-LEVEL")) . #1#) - (:IF (:CALL = (:VAR . N) (:LIT . 0)) (:VAR . R) - (:UNKNOWN (FACT (- N 1) (* N R)) (#2# . #1#))))))) - -;; Test sur la lambda expression -(deftest lisp2li - (lisp2li '(mapcar (lambda (x) x) '(1 2 3)) - () ()) - '(:call mapcar (:lclosure ((("LAMBDA" (X)) ("TOP-LEVEL")) ("TOP-LEVEL")) - (:var . x)) (:lit 1 2 3))) - -(deftest lisp2li - (lisp2li '((lambda (x y z) (list x y z)) 1 2 3) () ()) - '(:call (:lclosure ((("LAMBDA" (Z) (Y) (X)) ("TOP-LEVEL")) ("TOP-LEVEL")) - (:call list (:var . x) (:var . y) (:var . z))) - (:lit . 1) (:lit . 2) (:lit . 3))) - -;; Test sur le LET -(deftest lisp2li - (lisp2li '(let ((x 1) (y 2)) (list x y)) () ()) - '(:call (:lclosure ((("LAMBDA" (Y) (X)) ("TOP-LEVEL")) ("TOP-LEVEL")) - (:call list (:var . x) (:var . y))) - (:lit . 1) (:lit . 2))) - -(deftest lisp2li - (lisp2li '(let ((x 1) (y (+ x 2))) (list x y)) '(("TOP-LEVEL" (x . 1))) ()) - '(:call (:lclosure ((("LAMBDA" (Y) (X)) ("TOP-LEVEL" (x . 1))) ("TOP-LEVEL")) - (:call list (:var . x) (:var . y))) - (:lit . 1) (:call + (:var . x) (:lit . 2)))) - -;; Test sur le LET* -(deftest lisp2li - (lisp2li '(let* ((x 1) (y (+ x 2))) (list x y)) () ()) - '(:CALL (:LCLOSURE ((("LAMBDA" (X)) ("TOP-LEVEL")) ("TOP-LEVEL")) - (:CALL (:LCLOSURE ((("LAMBDA" (Y)) ("LAMBDA" (X)) ("TOP-LEVEL")) ("TOP-LEVEL")) - (:CALL LIST (:VAR . X) (:VAR . Y))) - (:CALL + (:VAR . X) (:LIT . 2)))) - (:LIT . 1))) - -;(run-tests t) -\ No newline at end of file +(deftest (lisp2li make-stat-env) + (make-stat-env '(x y z)) + '((x 0 1) (y 0 2) (z 0 3))) + +(deftest (lisp2li make-stat-env) + (make-stat-env '(a b c d)) + '((a 0 1) (b 0 2) (c 0 3) (d 0 4))) + +(deftest (lisp2li make-stat-env) + (make-stat-env '(a b) '((x 0 1) (y 0 2))) + '((a 1 1) (b 1 2) (x 0 1) (y 0 2))) + +(deftest (lisp2li constante) + (lisp2li '3 ()) + '(:const . 3)) + +(deftest (lisp2li constante) + (lisp2li ''x ()) + '(:const . x)) + +(deftest (lisp2li constante) + (lisp2li ''(1 2 3) ()) + '(:const 1 2 3)) + +(deftest (lisp2li defun) + (lisp2li '(defun foo (x) x) ()) + '(:mcall set-defun (:const . foo) (:lclosure 1 :cvar 0 1))) + +(deftest (lisp2li defun) + (lisp2li '(defun foo (x y z) (list x y z)) ()) + '(:mcall set-defun (:const . foo) + (:lclosure 3 :call list + (:cvar 0 1) + (:cvar 0 2) + (:cvar 0 3)))) + +(deftest (lisp2li setf) + (lisp2li '(setf y 42) '((x 0 1) (y 0 2))) + '(:set-var (0 2) 42)) + +(deftest (lisp2li setf) + (lisp2li '(setf (cdr '(1 2 3)) 42) ()) + '(:set-fun cdr 42 '(1 2 3))) + +(deftest (lisp2li lambda) + (lisp2li '(mapcar (lambda (x y z) (list x y z)) '(1 2 3)) ()) + '(:call mapcar (:lclosure 3 :call list + (:cvar 0 1) + (:cvar 0 2) + (:cvar 0 3)) + (:const 1 2 3))) +\ No newline at end of file diff --git a/test-unitaire.lisp b/test-unitaire.lisp @@ -40,7 +40,7 @@ (setf all-tests (list nil nil nil nil)) (let ((from (test-get-module (butlast module)))) (setf (first from) - (delete (last module) + (delete (car (last module)) (first from) :key #'car)))))