Meval peut maintenant gere les appels recursifs

This commit is contained in:
Bertrand BRUN 2010-11-13 00:49:49 +01:00
parent 5416bb34d8
commit c603beaebe
2 changed files with 47 additions and 29 deletions

View File

@ -167,7 +167,8 @@ par le compilateur et par linterpréteur"
,@(mapcar (lambda (x) (lisp2li x env)) (cdr expr))))
;; fonction inconnue
((and (not (fboundp (car expr)))
(not (get (car expr) :defun)))
(not (get (car expr) :defun))
(not (get (car expr) :defmacro)))
`(:unknown ,expr ,env))
;; if
((eq 'if (car expr))
@ -233,13 +234,16 @@ par le compilateur et par linterpréteur"
(cons :const nil))
;; macros
((macro-function (car expr))
(lisp2li (macroexpand expr) env))
(print "macro-function")
(lisp2li (macroexpand-1 expr) env))
;; foctions normales
((not (special-operator-p (car expr)))
`(:call ,(first expr) ,@(map-lisp2li (cdr expr) env)))
(T
(error "special form not yet implemented ~S" (car expr)))))
;; TODO : demander au prof comment corriger (or (= n 0) (= n 1)) qui rend nil car il fait 2 macroexpand 1: (COND ((= N 0)) (T (= N 1))) 2: (LET (#1=#:RESULT-7048) (IF (SETQ #1# (= N 0)) #1# (= N 1))) et 2 vaux nil car n != 0
;; Test unitaire
(load "test-unitaire")
(erase-tests lisp2li)

View File

@ -1,15 +1,29 @@
(load "match")
(defun get-env-num (num env)
"Récupère lenvironnement correspondant à celui souhaité."
(defun get-env-num-t (num env counter)
(cond ((= counter num) env)
((eq (aref env 0) nil) nil)
(T
(get-env-num-t num (aref env 0) (+ 1 counter))
)))
(get-env-num-t num env 0))
(defun env-size (env)
(if (or (equalp env #()) (eq env nil))
0
(+ 1 (env-size (aref env 0)))))
(defun get-env-num (num env)
"Récupère lenvironnement correspondant à celui souhaité."
(defun get-env-num-r (num env counter)
(cond ((or (equalp env #()) (eq env nil))
env)
((= num counter)
env)
(T
(get-env-num-t num (aref env 0) (- counter 1)))))
(get-env-num-r num env (- (env-size env) 1)))
(defun current-env (env)
(let ((env-size (- (env-size env) 1)))
(defun current-env-r (env counter)
(if (= counter env-size)
env
(current-env-r (aref env 0) (+ counter 1))))
(current-env-r env 0)))
(defun get-lower-env (env)
"Récupère lenvironnement le plus bas"
(if (or (= (array-total-size env) 0)
@ -37,16 +51,17 @@ du &rest dans une cellule de l'env sous forme d'une liste"
correspondantes et signale une exception si paramètres et arguments
ne concordent pas. Si lenvironnement passe en paramètre nest pas vide,
le nouvel environnement y est inclus."
(cond ((and (not pos-rest)
(< size (length list-values)))
(error "Too arguments"))
((> size (length list-values))
(error "Too few arguments"))
(T
(if (= (array-total-size env) 0)
(setf env (make-array (+ 1 size)))
(setf (aref (get-lower-env env) 0) (make-array (+ 1 size))))
(let ((lower-env (get-lower-env env)))
(let ((new-env (copy-all env)))
(cond ((and (not pos-rest)
(< size (length list-values)))
(error "Too arguments"))
((> size (length list-values))
(error "Too few arguments"))
(T
(if (= (array-total-size new-env) 0)
(setf new-env (make-array (+ 1 size)))
(setf (aref (get-lower-env new-env) 0) (make-array (+ 1 size))))
(let ((lower-env (get-lower-env new-env)))
(if pos-rest
(make-rest lower-env
list-values
@ -56,7 +71,7 @@ du &rest dans une cellule de l'env sous forme d'une liste"
for rank = 1 then (+ rank 1)
do (setf (aref lower-env rank) value)
)))
env)))
new-env))))
(defun map-meval (list env)
(mapcar (lambda (x) (meval x env)) list))
@ -111,13 +126,13 @@ darguments dans un certain environnement."
(cond-match expr
((:nil :const :val . _) expr val)
((:nil :cvar :num-env (? integerp) :index (? integerp))
(let ((sub-env (get-env-num num-env env)))
(if sub-env
(aref sub-env index)
(error "The variable unbound : ~w" expr))))
(if (= num-env 0)
(aref (current-env env) index)
(let ((sub-env (get-env-num num-env env)))
(if sub-env
(aref sub-env index)
(error "The variable unbound : ~w" expr)))))
((:nil :if :predicat @. :expr1 @. :expr2 @.)
(print "Je suis dans le if")
(print env)
(if (meval predicat env)
(meval expr1 env)
(meval expr2 env)))
@ -146,7 +161,6 @@ darguments dans un certain environnement."
((:nil :mcall :lambda (:nil :lclosure (? integerp) (? integerp)? _*) :args _*)
(meval-lambda lambda (meval-args args env) env))
((:nil :call :func-name _ :body _*)
(print "je suis dans le :call")
(apply (symbol-function func-name) (meval-args body env)))
((:nil :progn :body @.+)
(meval-body body env))