Pārlūkot izejas kodu

Refactoring de la gestion des variables et des fonctions

Arthur Brandao 6 gadi atpakaļ
vecāks
revīzija
b9cfe325db

+ 0 - 29
src/migl/lisp/LispElement.java

@@ -3,9 +3,6 @@ package migl.lisp;
 import java.math.BigInteger;
 import java.util.Map;
 
-import migl.lisp.operator.DefineOperator;
-import migl.util.ConsList;
-
 import java.util.HashMap;
 
 /**
@@ -205,31 +202,5 @@ public class LispElement {
 		}
 		return new LispElement(elt);
 	}
-	
-	/**
-	 * Récupère un élément dans la liste lisp
-	 * Si l'element est une liste elle seras alors analyser
-	 * 
-	 * @param elt L'element à récupérer
-	 * @return L'element ou le resultat de l'analyse si l'element est une liste
-	 * @throws LispError
-	 */
-	@SuppressWarnings("unchecked")
-	public static LispElement getElement(Object elt) throws LispError {
-		if(elt instanceof ConsList) {
-			return LispEval.evaluateList((ConsList<Object>) elt);
-		} else if(elt instanceof String) {
-			//Si c'est un string qui n'est pas un nom reservé
-			String str = (String) elt;
-			boolean skip = false;
-			try {
-				LispEval.verifyForbiddenName(str);
-			} catch (LispError ex) {
-				skip = true;
-			}
-			if(!skip) return DefineOperator.eval(elt);
-		}
-		return generate(elt);
-	}
 
 }

+ 188 - 133
src/migl/lisp/LispEval.java

@@ -16,16 +16,73 @@ import migl.util.ConsList;
  * @author Arthur Brandao
  */
 public class LispEval {
-	
+
 	/**
 	 * Les operateurs gérés par l'interpréteur
 	 */
-	private static Map<String, LispOperator> operators = new HashMap<>();
-	static {
+	private Map<String, LispOperator> operators = new HashMap<>();
+	
+	/**
+	 * L'interpreteur utilisant cet evaluateur pour les appels récursifs
+	 */
+	private final Lisp interpreter;
+	
+	/**
+	 * L'instance de gestion des variables et des fonctions
+	 */
+	private final DefineOperator define = new DefineOperator();
+
+	/**
+	 * Un element lisp
+	 */
+	private Object lispElt = null;
+
+	/**
+	 * Une liste d'elements lisp
+	 */
+	private ConsList<Object> lispList = null;
+
+	/**
+	 * Creation d'un evaluateur lisp
+	 */
+	public LispEval(Lisp interpreter) {
+		this(interpreter, null);
+	}
+
+	/**
+	 * Creation d'un evaluateur lisp
+	 * @param lisp Un element lisp (Object) ou une liste de lisp (ConsList<Object>)
+	 */
+	public LispEval(Lisp interpreter, Object lisp) {
+		this.interpreter = interpreter;
+		if(lisp != null) {
+			this.setLisp(lisp);
+		}
+		this.setUpOperators();
+	}
+
+	/**
+	 * Change l'objet lisp à evaluer
+	 * @param lisp Un element lisp (Object) ou une liste de lisp (ConsList<Object>)
+	 */
+	@SuppressWarnings("unchecked")
+	public final void setLisp(Object lisp) {
+		if(lisp == null) {
+			throw new IllegalArgumentException("Expression is null");
+		} else if(lisp instanceof ConsList) {
+			this.lispElt = null;
+			this.lispList = (ConsList<Object>) lisp;
+		} else {
+			this.lispElt = lisp;
+			this.lispList = null;
+		}
+	}
+
+	private final void setUpOperators() {
 		//Définition des opérateurs
-		operators.put("define", new DefineOperator());
-		operators.put("set!", new DefineOperator());
-		operators.put("lambda", new DefineOperator());
+		operators.put("define", this.define);
+		operators.put("set!", this.define);
+		operators.put("lambda", this.define);
 		operators.put("cons", new ConsOperator());
 		operators.put(">", new ComparatorOperator());
 		operators.put(">=", new ComparatorOperator());
@@ -42,108 +99,108 @@ public class LispEval {
 		operators.put("rint", new MathOperator());
 		operators.put("round", new MathOperator());
 		operators.put("signum", new MathOperator());
-		operators.put("quote", (op, lisp) -> {
+		operators.put("quote", (eval, op, lisp) -> {
 			if(lisp.size() != 1) {
 				throw new LispError(LispError.ERR_NUM_ARG);
 			}
 			return LispElement.generate(lisp.car().toString());
 		});
-		operators.put("if", (op, lisp) -> {
+		operators.put("if", (eval, op, lisp) -> {
 			if(lisp.size() != 3) {
 				throw new LispError(LispError.ERR_NUM_ARG);
 			}
-			if(LispElement.getElement(lisp.car()).toBoolean()) {
-				return LispElement.getElement(lisp.cdr().car());
+			if(this.getElement(lisp.car()).toBoolean()) {
+				return eval.getElement(lisp.cdr().car());
 			} else {
-				return LispElement.getElement(lisp.cdr().cdr().car());
+				return eval.getElement(lisp.cdr().cdr().car());
 			}
 		});
-		operators.put("not", (op, lisp) -> {
+		operators.put("not", (eval, op, lisp) -> {
 			if(lisp.size() != 1) {
 				throw new LispError(LispError.ERR_NUM_ARG);
 			}
-			boolean result = !LispElement.getElement(lisp.car()).toBoolean();
+			boolean result = !eval.getElement(lisp.car()).toBoolean();
 			return LispElement.generate(result);
 		});
-		operators.put("and", (op, lisp) -> {
+		operators.put("and", (eval, op, lisp) -> {
 			boolean result = true;
 			while(!lisp.isEmpty()) {
-				result = result && LispElement.getElement(lisp.car()).toBoolean();
+				result = result && eval.getElement(lisp.car()).toBoolean();
 				lisp = lisp.cdr();
 			}
 			return LispElement.generate(result);
 		});
-		operators.put("or", (op, lisp) -> {
+		operators.put("or", (eval, op, lisp) -> {
 			boolean result = false;
 			while(!lisp.isEmpty()) {
-				result = result || LispElement.getElement(lisp.car()).toBoolean();
+				result = result || eval.getElement(lisp.car()).toBoolean();
 				lisp = lisp.cdr();
 			}
 			return LispElement.generate(result);
 		});
-		operators.put("+", (op, lisp) -> {
+		operators.put("+", (eval, op, lisp) -> {
 			BigInteger resultInt = new BigInteger("0");
-            while(!lisp.isEmpty()){
-                LispElement eltInt = LispElement.getElement(lisp.car());
-                if(eltInt.value.getClass() != BigInteger.class) break;
-                resultInt = resultInt.add(eltInt.toInt());
-                lisp = lisp.cdr();
-            }
-            //Si on finit la liste avec que des entier on retourne
-            if(lisp.isEmpty()) return LispElement.generate(resultInt);
-            //Sinon on continue en passant en double
-            double result = resultInt.doubleValue();
-            while(!lisp.isEmpty()) {
-                LispElement elt = LispElement.getElement(lisp.car());
-                result += elt.toNumber();
-                lisp = lisp.cdr();
-            }
-            return LispElement.generate(result);
+			while(!lisp.isEmpty()){
+				LispElement eltInt = eval.getElement(lisp.car());
+				if(eltInt.value.getClass() != BigInteger.class) break;
+				resultInt = resultInt.add(eltInt.toInt());
+				lisp = lisp.cdr();
+			}
+			//Si on finit la liste avec que des entier on retourne
+			if(lisp.isEmpty()) return LispElement.generate(resultInt);
+			//Sinon on continue en passant en double
+			double result = resultInt.doubleValue();
+			while(!lisp.isEmpty()) {
+				LispElement elt = eval.getElement(lisp.car());
+				result += elt.toNumber();
+				lisp = lisp.cdr();
+			}
+			return LispElement.generate(result);
 		});
-		operators.put("*", (op, lisp) -> {
+		operators.put("*", (eval, op, lisp) -> {
 			BigInteger resultInt = new BigInteger("1");
-            while(!lisp.isEmpty()){
-                LispElement eltInt = LispElement.getElement(lisp.car());
-                if(eltInt.value.getClass() != BigInteger.class) break;
-                resultInt = resultInt.multiply(eltInt.toInt());
-                lisp = lisp.cdr();
-            }
-            //Si on finit la liste avec que des entier on retourne
-            if(lisp.isEmpty()) return LispElement.generate(resultInt);
-            //Sinon on continue en passant en double
-            double result = resultInt.doubleValue();
-            while(!lisp.isEmpty()) {
-                LispElement elt = LispElement.getElement(lisp.car());
-                result *= elt.toNumber();
-                lisp = lisp.cdr();
-            }
-            return LispElement.generate(result);
+			while(!lisp.isEmpty()){
+				LispElement eltInt = eval.getElement(lisp.car());
+				if(eltInt.value.getClass() != BigInteger.class) break;
+				resultInt = resultInt.multiply(eltInt.toInt());
+				lisp = lisp.cdr();
+			}
+			//Si on finit la liste avec que des entier on retourne
+			if(lisp.isEmpty()) return LispElement.generate(resultInt);
+			//Sinon on continue en passant en double
+			double result = resultInt.doubleValue();
+			while(!lisp.isEmpty()) {
+				LispElement elt = eval.getElement(lisp.car());
+				result *= elt.toNumber();
+				lisp = lisp.cdr();
+			}
+			return LispElement.generate(result);
 		});
-		operators.put("-", (op, lisp) -> {
+		operators.put("-", (eval, op, lisp) -> {
 			switch(lisp.size()) {				
-				case 1:
-					LispElement elt = LispElement.getElement(lisp.car());
-					if(elt.isInt()) {
-						return LispElement.generate(elt.toInt().multiply(new BigInteger("-1")));
-					}
-					return LispElement.generate(elt.toNumber() * -1); //Pb pitest qui remplace * par / or *-1 == /-1
-				case 2:
-					LispElement elt1 = LispElement.getElement(lisp.car());
-					LispElement elt2 = LispElement.getElement(lisp.cdr().car());
-					if(elt1.isInt() && elt2.isInt()) {
-						return LispElement.generate(elt1.toInt().subtract(elt2.toInt()));
-					}
-					return LispElement.generate(elt1.toNumber() - elt2.toNumber());
-				default:
-					throw new LispError(LispError.ERR_NUM_ARG);
+			case 1:
+				LispElement elt = eval.getElement(lisp.car());
+				if(elt.isInt()) {
+					return LispElement.generate(elt.toInt().multiply(new BigInteger("-1")));
+				}
+				return LispElement.generate(elt.toNumber() * -1); //Pb pitest qui remplace * par / or *-1 == /-1
+			case 2:
+				LispElement elt1 = eval.getElement(lisp.car());
+				LispElement elt2 = eval.getElement(lisp.cdr().car());
+				if(elt1.isInt() && elt2.isInt()) {
+					return LispElement.generate(elt1.toInt().subtract(elt2.toInt()));
+				}
+				return LispElement.generate(elt1.toNumber() - elt2.toNumber());
+			default:
+				throw new LispError(LispError.ERR_NUM_ARG);
 			}
 		});
-		operators.put("/", (op, lisp) -> {
+		operators.put("/", (eval, op, lisp) -> {
 			if(lisp.size() != 2) {
 				throw new LispError(LispError.ERR_NUM_ARG);
 			}
-			LispElement elt1 = LispElement.getElement(lisp.car());
-			LispElement elt2 = LispElement.getElement(lisp.cdr().car());
+			LispElement elt1 = eval.getElement(lisp.car());
+			LispElement elt2 = eval.getElement(lisp.cdr().car());
 			if(elt2.toNumber() == 0) {
 				throw new LispError("Division by zero");
 			}
@@ -152,66 +209,24 @@ public class LispEval {
 			}
 			return LispElement.generate(elt1.toNumber() / elt2.toNumber());
 		});
-		operators.put("abs", (op, lisp) -> {
+		operators.put("abs", (eval, op, lisp) -> {
 			if(lisp.size() != 1) {
 				throw new LispError(LispError.ERR_NUM_ARG);
 			}
-			LispElement le = LispElement.getElement(lisp.car());
+			LispElement le = eval.getElement(lisp.car());
 			if(le.isInt()) {
 				return LispElement.generate(le.toInt().abs());
 			}
 			return LispElement.generate(Math.abs(le.toNumber()));
 		});
-		operators.put("pow", (op, lisp) -> {
+		operators.put("pow", (eval, op, lisp) -> {
 			if(lisp.size() != 2) {
 				throw new LispError(LispError.ERR_NUM_ARG);
 			}
-			return LispElement.generate(Math.pow(LispElement.getElement(lisp.car()).toNumber(), LispElement.getElement(lisp.cdr().car()).toNumber()));
+			return LispElement.generate(Math.pow(eval.getElement(lisp.car()).toNumber(), eval.getElement(lisp.cdr().car()).toNumber()));
 		});
 	}
 
-	/**
-	 * Un element lisp
-	 */
-	private Object lispElt = null;
-	
-	/**
-	 * Une liste d'elements lisp
-	 */
-	private ConsList<Object> lispList = null;
-	
-	/**
-	 * Creation d'un evaluateur lisp
-	 */
-	public LispEval() {
-		
-	}
-	
-	/**
-	 * Creation d'un evaluateur lisp
-	 * @param lisp Un element lisp (Object) ou une liste de lisp (ConsList<Object>)
-	 */
-	public LispEval(Object lisp) {
-		this.setLisp(lisp);
-	}
-	
-	/**
-	 * Change l'objet lisp à evaluer
-	 * @param lisp Un element lisp (Object) ou une liste de lisp (ConsList<Object>)
-	 */
-	@SuppressWarnings("unchecked")
-	public final void setLisp(Object lisp) {
-		if(lisp == null) {
-			throw new IllegalArgumentException("Expression is null");
-		} else if(lisp instanceof ConsList) {
-			this.lispElt = null;
-			this.lispList = (ConsList<Object>) lisp;
-		} else {
-			this.lispElt = lisp;
-			this.lispList = null;
-		}
-	}
-	
 	/**
 	 * Evalue l'element lisp
 	 * @return L'element retourner par l'évaluation
@@ -221,11 +236,11 @@ public class LispEval {
 		if(this.lispElt != null) {
 			return this.evalElt();
 		} else if(this.lispList != null) {
-			return this.evalList();
+			return this.evaluateList();
 		}
 		return null;
 	}
-	
+
 	/**
 	 * Evalue un element
 	 * @return L'element retourner par l'évaluation
@@ -233,23 +248,21 @@ public class LispEval {
 	 */
 	public LispElement evalElt() throws LispError {
 		try {
-			return LispElement.getElement(this.lispElt);
+			return this.getElement(this.lispElt);
 		} catch (IllegalArgumentException ex) {
 			throw new LispError(ex.getMessage(), ex);
 		}
 	}
-	
+
 	/**
 	 * Evalue une liste d'elements lisp
 	 * @return L'element retourner par l'évaluation
 	 * @throws LispError
 	 */
-	public LispElement evalList() throws LispError {
-		return evaluateList(this.lispList);
+	public LispElement evaluateList() throws LispError {
+		return this.evaluateList(this.lispList);
 	}
-	
-	/* --- Méthode static utilisé pour l'évaluation (dans cette class et dans les autres) --- */
-	
+
 	/**
 	 * Evalue un liste d'élément lisp parser dans un ConsList
 	 * 
@@ -257,35 +270,35 @@ public class LispEval {
 	 * @return Valeur évaluer
 	 * @throws LispError
 	 */
-	public static LispElement evaluateList(ConsList<Object> lisp) throws LispError {
+	public LispElement evaluateList(ConsList<Object> lisp) throws LispError {
 		if(lisp.isEmpty()) {
 			return LispElement.generate("()");
 		}
 		String operator = LispElement.generate(lisp.car()).toStr();
-		LispOperator op = operators.get(operator);
+		LispOperator op = this.operators.get(operator);
 		if(op == null) {
-			if(DefineOperator.isLambda(operator)) {
-				return operators.get("lambda").apply(operator, lisp.cdr());
+			if(this.define.isLambda(operator)) {
+				return this.operators.get("lambda").apply(this, operator, lisp.cdr());
 			} else {
 				throw new LispError(operator + LispError.ERR_UNKNOW, new UnsupportedOperationException("Unknow operator"));
 			}
 		}
 		try {
-			return op.apply(operator, lisp.cdr());
+			return op.apply(this, operator, lisp.cdr());
 		} catch (IllegalStateException ex) {
 			throw new LispError(ex.getMessage(), ex);
 		} catch (IllegalArgumentException ex) {
 			throw new LispError("List Lisp malformed: " + ex.getMessage(), ex);
 		}
 	}
-	
+
 	/**
 	 * Verifie que le nom pour une variable n'est pas interdit
 	 * 
 	 * @param name Nom pour la variable
 	 * @throws LispError Si le nom n'est pas valide
 	 */
-	public static void verifyForbiddenName(String name) throws LispError {
+	public void verifyForbiddenName(String name) throws LispError {
 		//Verifie que ce n'est pas une valeur (double, bool, ...)
 		try {
 			LispElement.valueOf(name).toStr();
@@ -293,9 +306,51 @@ public class LispEval {
 			throw new LispError(name + LispError.ERR_INVALID, ex);
 		}
 		//Verifie que ce n'est pas le nom d'un operateur
-		if(operators.containsKey(name)) {
+		if(this.operators.containsKey(name)) {
 			throw new LispError(name + LispError.ERR_INVALID);
 		}
 	}
 	
+	/**
+	 * Récupère un élément dans la liste lisp
+	 * Si l'element est une liste elle seras alors analyser
+	 * 
+	 * @param elt L'element à récupérer
+	 * @return L'element ou le resultat de l'analyse si l'element est une liste
+	 * @throws LispError
+	 */
+	@SuppressWarnings("unchecked")
+	public LispElement getElement(Object elt) throws LispError {
+		if(elt instanceof ConsList) {
+			return this.evaluateList((ConsList<Object>) elt);
+		} else if(elt instanceof String) {
+			//Si c'est un string qui n'est pas un nom reservé
+			String str = (String) elt;
+			boolean skip = false;
+			try {
+				this.verifyForbiddenName(str);
+			} catch (LispError ex) {
+				skip = true;
+			}
+			if(!skip) return this.define.eval(elt);
+		}
+		return LispElement.generate(elt);
+	}
+	
+	/**
+	 * Retourne l'interpreteur utilisant cet évaluateur
+	 * @return
+	 */
+	public Lisp getInterpreter() {
+		return this.interpreter;
+	}
+	
+	/**
+	 * Retourne l'instance de gestion des variables et des fonctions
+	 * @return
+	 */
+	public DefineOperator getDefine() {
+		return this.define;
+	}
+	
 }

+ 7 - 12
src/migl/lisp/LispFactory.java

@@ -1,6 +1,5 @@
 package migl.lisp;
 
-import migl.lisp.operator.DefineOperator;
 
 /**
  * Simple factory to access the interpreter implementation.
@@ -10,35 +9,31 @@ import migl.lisp.operator.DefineOperator;
  */
 public class LispFactory {
 	
-	private static Lisp interpreter;
+	private static Lisp lastInterpreter;
 
     private LispFactory() {
         // do nothing
     }
 
     /**
-     * Reset and get an instance of the interpreter.
+     * Create new instance of the interpreter.
      * 
      * @return a new lisp interpreter.
      */
     public static Lisp makeIntepreter() {
     	LispElement.clear();
-    	DefineOperator.clear();
-    	if(interpreter == null) {
-    		interpreter = new LispImpl();
-    	}
-        return interpreter;
+    	return lastInterpreter = new LispImpl();
     }
     
     /**
-     * Get an instance of the interpreter.
+     * Get last instance of the interpreter.
      * 
      * @return a new lisp interpreter.
      */
     public static Lisp getInterpreter() {
-    	if(interpreter == null) {
-    		interpreter = new LispImpl();
+    	if(lastInterpreter == null) {
+    		lastInterpreter = new LispImpl();
     	}
-        return interpreter;
+        return lastInterpreter;
     }
 }

+ 18 - 2
src/migl/lisp/LispImpl.java

@@ -2,9 +2,9 @@ package migl.lisp;
 
 public class LispImpl implements Lisp {
 	
-	private LispParser parser = new LispParser();
+	private final LispParser parser = new LispParser();
 	
-	private LispEval eval = new LispEval();
+	private final LispEval eval = new LispEval(this);
 	
 	@Override
 	public Object parse(String expr) throws LispError {
@@ -20,5 +20,21 @@ public class LispImpl implements Lisp {
 		this.eval.setLisp(lisp);
 		return this.eval.evaluate();
 	}
+	
+	/**
+	 * Retourne l'instance utilisée pour analyser les epxressions lisp
+	 * @return
+	 */
+	public LispParser getParser() {
+		return this.parser;
+	}
+	
+	/**
+	 * Retourne l'instance utilisée pour évaluer les epxressions lisp
+	 * @return
+	 */
+	public LispEval getEval() {
+		return this.eval;
+	}
 
 }

+ 2 - 1
src/migl/lisp/LispOperator.java

@@ -12,11 +12,12 @@ public interface LispOperator {
 
 	/**
 	 * Applique l'operateur lisp sur une liste
+	 * @param L'instance à utiliser pour évaluer l'expression
 	 * @param operator Symbole de l'operateur
 	 * @param lisp Liste d'element à traiter sans le symbole de l'operateur
 	 * @return
 	 * @throws LispError
 	 */
-	LispElement apply(String operator, ConsList<Object> lisp) throws LispError;
+	LispElement apply(LispEval eval, String operator, ConsList<Object> lisp) throws LispError;
 	
 }

+ 4 - 3
src/migl/lisp/operator/ComparatorOperator.java

@@ -2,13 +2,14 @@ package migl.lisp.operator;
 
 import migl.lisp.LispElement;
 import migl.lisp.LispError;
+import migl.lisp.LispEval;
 import migl.lisp.LispOperator;
 import migl.util.ConsList;
 
 public class ComparatorOperator implements LispOperator {
 
 	@Override
-	public LispElement apply(String operator, ConsList<Object> lisp) throws LispError {
+	public LispElement apply(LispEval eval, String operator, ConsList<Object> lisp) throws LispError {
 		if(lisp.size() == 0) {
 			throw new LispError(LispError.ERR_NUM_ARG);
 		}
@@ -17,10 +18,10 @@ public class ComparatorOperator implements LispOperator {
 		double value = 0;
 		while(!lisp.isEmpty()) {
 			if(first) {
-				value = LispElement.getElement(lisp.car()).toNumber();
+				value = eval.getElement(lisp.car()).toNumber();
 				first = false;
 			} else {
-				double temp = LispElement.getElement(lisp.car()).toNumber();
+				double temp = eval.getElement(lisp.car()).toNumber();
 				switch(operator) {
 					case ">":
 						result = result && (value > temp);

+ 5 - 4
src/migl/lisp/operator/ConsOperator.java

@@ -2,6 +2,7 @@ package migl.lisp.operator;
 
 import migl.lisp.LispElement;
 import migl.lisp.LispError;
+import migl.lisp.LispEval;
 import migl.lisp.LispOperator;
 import migl.util.ConsList;
 import migl.util.ConsListFactory;
@@ -9,19 +10,19 @@ import migl.util.ConsListFactory;
 public class ConsOperator implements LispOperator {
 
 	@Override
-	public LispElement apply(String operator, ConsList<Object> lisp) throws LispError {
+	public LispElement apply(LispEval eval, String operator, ConsList<Object> lisp) throws LispError {
 		if(lisp.size() != 2) {
 			throw new LispError(LispError.ERR_NUM_ARG);
 		}
 		ConsList<Object> cl;
 		if(lisp.cdr().car() instanceof ConsList) {
 			//Recup + evaluation de la liste
-			cl = this.parseList(LispElement.getElement(lisp.cdr().car()).toString());
+			cl = this.parseList(eval.getElement(lisp.cdr().car()).toString());
 			//Ajoute la valeur de gauche devant
-			cl = cl.prepend(LispElement.getElement(lisp.car()).value);
+			cl = cl.prepend(eval.getElement(lisp.car()).value);
 		} else {
 			LispElement le;
-			le = LispElement.getElement(lisp.car());
+			le = eval.getElement(lisp.car());
 			cl = ConsListFactory.asList(le + " . " + lisp.cdr().car());
 		}
 		return LispElement.generate(cl.toString());

+ 82 - 90
src/migl/lisp/operator/DefineOperator.java

@@ -7,98 +7,22 @@ import migl.lisp.Lisp;
 import migl.lisp.LispElement;
 import migl.lisp.LispError;
 import migl.lisp.LispEval;
-import migl.lisp.LispFactory;
 import migl.lisp.LispOperator;
 import migl.util.ConsList;
 
 public class DefineOperator implements LispOperator {
 	
-	private static Map<String, ConsList<Object>> define = new HashMap<>();
-	
-	/**
-	 * Vide la liste des variable et expression lambda definit
-	 */
-	public static void clear() {
-		define.clear();
-	}
-	
-	/**
-	 * Indique si un Objet est la representation d'une expression lambda
-	 * @param elt L'objet à evaluer
-	 * @return
-	 */
-	@SuppressWarnings("unchecked")
-	public static boolean isLambda(Object elt) {
-		if(!(elt instanceof String)) {
-			return false;
-		}
-		String key = (String) elt;
-		ConsList<Object> cl = define.get(key);
-		if(cl == null) {
-			return false;
-		}
-		if(!(cl.car() instanceof ConsList)) {
-			return false;
-		}
-		cl = (ConsList<Object>) cl.car();
-		try {
-			return "lambda".equals(LispElement.generate(cl.car()).toStr());
-		} catch (IllegalStateException ex) {
-			return false;
-		}
-	}
-	
-	/**
-	 * Evalue un objet
-	 * @param elt
-	 * @return
-	 * @throws LispError
-	 */
-	@SuppressWarnings("unchecked")
-	public static LispElement eval(Object elt) throws LispError {
-		if(elt instanceof ConsList) {
-			return eval((ConsList<Object>) elt);
-		}
-		//Recup la valeur de l'element
-		LispElement lelt = LispElement.generate(elt);
-		String key;
-		try {
-			key = lelt.toStr();
-		} catch(IllegalStateException ex) {
-			throw new LispError(lelt.toString() + LispError.ERR_UNKNOW, ex);
-		}
-		//Recup la valeur dans la map
-		ConsList<Object> cl = define.get(key);
-		if(cl == null) {
-			//Si aucune valeur alors erreur
-			throw new LispError(key + LispError.ERR_UNKNOW);
-		}
-		//ToDo verifier si ce n'est pas une lambda expression
-		return LispElement.generate(cl.car());
-	}
-	
-	/**
-	 * Evalue une liste
-	 * @param lisp
-	 * @return
-	 */
-	public static LispElement eval(ConsList<Object> lisp) {
-		if(lisp.car() instanceof ConsList) {
-			String res = lisp.car().toString();
-			return LispElement.generate(res.substring(1, res.length() - 1));
-		}
-		return LispElement.generate(lisp.car());
-	}
+	private final Map<String, ConsList<Object>> define = new HashMap<>();
 
 	@Override
-	public LispElement apply(String operator, ConsList<Object> lisp) throws LispError {
+	public LispElement apply(LispEval eval, String operator, ConsList<Object> lisp) throws LispError {
 		switch(operator) {
 			case "define":
-				return this.define(lisp);
+				return this.define(eval, lisp);
 			case "set!":
-				return this.set(lisp);
+				return this.set(eval, lisp);
 			default:
-				return this.lambda(operator, lisp);
+				return this.lambda(eval, operator, lisp);
 		}
 	}
 	
@@ -108,7 +32,7 @@ public class DefineOperator implements LispOperator {
 	 * @return
 	 * @throws LispError
 	 */
-	private LispElement define(ConsList<Object> lisp) throws LispError {
+	private LispElement define(LispEval eval, ConsList<Object> lisp) throws LispError {
 		if(lisp.size() != 2) {
 			throw new LispError(LispError.ERR_NUM_ARG);
 		}
@@ -121,9 +45,9 @@ public class DefineOperator implements LispOperator {
 			throw new LispError(le.toString() + LispError.ERR_INVALID, ex);
 		}
 		//Verification de sa validité
-		LispEval.verifyForbiddenName(key);
+		eval.verifyForbiddenName(key);
 		//Ajoute dans la map
-		define.put(key, lisp.cdr());
+		this.define.put(key, lisp.cdr());
 		//Evalue pour le retour
 		return eval(lisp.cdr());
 	}
@@ -134,7 +58,7 @@ public class DefineOperator implements LispOperator {
 	 * @return
 	 * @throws LispError
 	 */
-	private LispElement set(ConsList<Object> lisp) throws LispError {
+	private LispElement set(LispEval eval, ConsList<Object> lisp) throws LispError {
 		if(lisp.size() != 2) {
 			throw new LispError(LispError.ERR_NUM_ARG);
 		}
@@ -146,13 +70,13 @@ public class DefineOperator implements LispOperator {
 			throw new LispError(ex);
 		}
 		//Verification de sa validité
-		LispEval.verifyForbiddenName(key);
+		eval.verifyForbiddenName(key);
 		//Regarde si la valeur est deja presente
 		if(!define.containsKey(key)) {
 			throw new LispError(key + LispError.ERR_UNKNOW);
 		}
 		//Ajoute dans la map
-		define.put(key, lisp.cdr());
+		this.define.put(key, lisp.cdr());
 		//Evalue pour le retour
 		return eval(lisp.cdr());
 	}
@@ -165,7 +89,7 @@ public class DefineOperator implements LispOperator {
 	 * @throws LispError
 	 */
 	@SuppressWarnings("unchecked")
-	private LispElement lambda(String operator, ConsList<Object> lisp) throws LispError {
+	private LispElement lambda(LispEval eval, String operator, ConsList<Object> lisp) throws LispError {
 		if(!isLambda(operator)) {
 			throw new LispError(operator + LispError.ERR_UNKNOW);
 		}
@@ -173,7 +97,7 @@ public class DefineOperator implements LispOperator {
 		ConsList<Object> lambda;
 		ConsList<Object> param;
 		try {
-			lambda = (ConsList<Object>) define.get(operator).car();
+			lambda = (ConsList<Object>) this.define.get(operator).car();
 			param = (ConsList<Object>) lambda.cdr().car();
 			lambda = (ConsList<Object>) lambda.cdr().cdr().car();
 			if(param.size() != lisp.size()) {
@@ -193,8 +117,76 @@ public class DefineOperator implements LispOperator {
 			lisp = lisp.cdr();
 		}
 		//Evalue le resultat
-		Lisp l = LispFactory.getInterpreter();
+		Lisp l = eval.getInterpreter();
 		return LispElement.generate(l.eval(lispExpr));
 	}
+	
+	/**
+	 * Indique si un Objet est la representation d'une expression lambda
+	 * @param elt L'objet à evaluer
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	public boolean isLambda(Object elt) {
+		if(!(elt instanceof String)) {
+			return false;
+		}
+		String key = (String) elt;
+		ConsList<Object> cl = this.define.get(key);
+		if(cl == null) {
+			return false;
+		}
+		if(!(cl.car() instanceof ConsList)) {
+			return false;
+		}
+		cl = (ConsList<Object>) cl.car();
+		try {
+			return "lambda".equals(LispElement.generate(cl.car()).toStr());
+		} catch (IllegalStateException ex) {
+			return false;
+		}
+	}
+	
+	/**
+	 * Evalue un objet
+	 * @param elt
+	 * @return
+	 * @throws LispError
+	 */
+	@SuppressWarnings("unchecked")
+	public LispElement eval(Object elt) throws LispError {
+		if(elt instanceof ConsList) {
+			return eval((ConsList<Object>) elt);
+		}
+		//Recup la valeur de l'element
+		LispElement lelt = LispElement.generate(elt);
+		String key;
+		try {
+			key = lelt.toStr();
+		} catch(IllegalStateException ex) {
+			throw new LispError(lelt.toString() + LispError.ERR_UNKNOW, ex);
+		}
+		//Recup la valeur dans la map
+		ConsList<Object> cl = define.get(key);
+		if(cl == null) {
+			//Si aucune valeur alors erreur
+			throw new LispError(key + LispError.ERR_UNKNOW);
+		}
+		//ToDo verifier si ce n'est pas une lambda expression
+		return LispElement.generate(cl.car());
+	}
+	
+	/**
+	 * Evalue une liste
+	 * @param lisp
+	 * @return
+	 */
+	public LispElement eval(ConsList<Object> lisp) {
+		if(lisp.car() instanceof ConsList) {
+			String res = lisp.car().toString();
+			return LispElement.generate(res.substring(1, res.length() - 1));
+		}
+		return LispElement.generate(lisp.car());
+	}
 
 }

+ 3 - 2
src/migl/lisp/operator/MathOperator.java

@@ -2,17 +2,18 @@ package migl.lisp.operator;
 
 import migl.lisp.LispElement;
 import migl.lisp.LispError;
+import migl.lisp.LispEval;
 import migl.lisp.LispOperator;
 import migl.util.ConsList;
 
 public class MathOperator implements LispOperator {
 
 	@Override
-	public LispElement apply(String operator, ConsList<Object> lisp) throws LispError {
+	public LispElement apply(LispEval eval, String operator, ConsList<Object> lisp) throws LispError {
 		if(lisp.size() != 1) {
 			throw new LispError(LispError.ERR_NUM_ARG);
 		}
-		LispElement elt = LispElement.getElement(lisp.car());
+		LispElement elt = eval.getElement(lisp.car());
 		switch(operator) {
 			case "cbrt":
 				return LispElement.generate(Math.cbrt(elt.toNumber()));

+ 5 - 4
src/migl/lisp/operator/MinMaxOperator.java

@@ -4,25 +4,26 @@ import java.math.BigInteger;
 
 import migl.lisp.LispElement;
 import migl.lisp.LispError;
+import migl.lisp.LispEval;
 import migl.lisp.LispOperator;
 import migl.util.ConsList;
 
 public class MinMaxOperator implements LispOperator {
 
 	@Override
-	public LispElement apply(String operator, ConsList<Object> lisp) throws LispError {
+	public LispElement apply(LispEval eval, String operator, ConsList<Object> lisp) throws LispError {
 		if(lisp.size() != 2 /* Mettre == 0 Pour nombre infini variable */) {
 			throw new LispError(LispError.ERR_NUM_ARG);
 		}
 		//Initialise avec la 1er valeur
-		LispElement elt = LispElement.getElement(lisp.car());
+		LispElement elt = eval.getElement(lisp.car());
 		lisp = lisp.cdr();
 		double result;
 		try {
 			BigInteger res = elt.toInt();
 			//Parcours les elements suivants
 			while(!lisp.isEmpty()) {
-				elt = LispElement.getElement(lisp.car());
+				elt = eval.getElement(lisp.car());
 	            if(elt.value.getClass() != BigInteger.class) break;
 	            switch(operator) {
 					case "max":
@@ -44,7 +45,7 @@ public class MinMaxOperator implements LispOperator {
 			result = elt.toNumber();
 		}
         while(!lisp.isEmpty()) {
-             double value = LispElement.getElement(lisp.car()).toNumber();
+             double value = eval.getElement(lisp.car()).toNumber();
              switch(operator) {
 				case "max":
 					result = (value > result) ? value : result;