|  | @@ -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;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	
 | 
	
		
			
				|  |  |  }
 |