浏览代码

Ajout base define et set!

Arthur Brandao 6 年之前
父节点
当前提交
313fa2569c
共有 3 个文件被更改,包括 131 次插入4 次删除
  1. 3 1
      src/migl/lisp/LispElement.java
  2. 29 3
      src/migl/lisp/LispImpl.java
  3. 99 0
      src/migl/lisp/operator/DefineOperator.java

+ 3 - 1
src/migl/lisp/LispElement.java

@@ -3,6 +3,7 @@ package migl.lisp;
 import java.math.BigInteger;
 import java.util.Map;
 
+import migl.lisp.operator.DefineOperator;
 import migl.util.ConsList;
 
 import java.util.HashMap;
@@ -173,7 +174,8 @@ public class LispElement {
 		if(elt instanceof ConsList) {
 			return LispImpl.evaluateList((ConsList<Object>) elt);
 		}
-		return generate(elt);
+		//return generate(elt);
+		return DefineOperator.eval(elt);
 	}
 
 }

+ 29 - 3
src/migl/lisp/LispImpl.java

@@ -10,6 +10,8 @@ import java.util.regex.Pattern;
 
 import migl.lisp.operator.ComparatorOperator;
 import migl.lisp.operator.ConsOperator;
+import migl.lisp.operator.DefineOperator;
+import migl.lisp.operator.MinMaxOperator;
 import migl.util.ConsList;
 import migl.util.ConsListFactory;
 
@@ -23,12 +25,16 @@ public class LispImpl implements Lisp {
 	private static Map<String, LispOperator> operators = new HashMap<>();
 	static {
 		//Définition des opérateurs
+		operators.put("define", new DefineOperator());
+		operators.put("set!", new DefineOperator());
 		operators.put("cons", new ConsOperator());
 		operators.put(">", new ComparatorOperator());
 		operators.put(">=", new ComparatorOperator());
 		operators.put("<", new ComparatorOperator());
 		operators.put("<=", new ComparatorOperator());
 		operators.put("=", new ComparatorOperator());
+		operators.put("min", new MinMaxOperator());
+		operators.put("max", new MinMaxOperator());
 		operators.put("quote", (op, lisp) -> {
 			if(lisp.size() != 1) {
 				throw new LispError(LispError.ERR_NUM_ARG);
@@ -174,7 +180,8 @@ public class LispImpl implements Lisp {
 		}
 		//Si element seul on évalue directement sa valeur
 		try {
-			return LispElement.generate(lisp);
+			//return LispElement.generate(lisp);
+			return DefineOperator.eval(lisp);
 		} catch (IllegalArgumentException ex) {
 			throw new LispError(ex.getMessage(), ex);
 		}
@@ -209,7 +216,7 @@ public class LispImpl implements Lisp {
 	 * @return
 	 */
 	private boolean verifyList(String expr) {
-		Pattern p = Pattern.compile("\\(([ |\t]*[A-Za-z0-9\\.\\+\\-\\/\\*<>=#]+[ |\t]*)*\\)");
+		Pattern p = Pattern.compile("\\(([ |\t]*[A-Za-z0-9\\.\\+\\-\\/\\*<>=#!]+[ |\t]*)*\\)");
 		Matcher m = p.matcher(expr);
 		//Si pas de correspondance
 		if(!m.find()) {
@@ -321,7 +328,7 @@ public class LispImpl implements Lisp {
 		String operator = LispElement.generate(lisp.car()).toStr();
 		LispOperator op = operators.get(operator);
 		if(op == null) {
-			throw new LispError(new UnsupportedOperationException("Unknow expression"));
+			throw new LispError(new UnsupportedOperationException(operator + LispError.ERR_UNKNOW));
 		}
 		try {
 			return op.apply(operator, lisp.cdr());
@@ -331,5 +338,24 @@ public class LispImpl implements Lisp {
 			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 {
+		//Verifie que ce n'est pas une valeur (double, bool, ...)
+		try {
+			LispElement.valueOf(name).toStr();
+		} catch (IllegalStateException ex) {
+			throw new LispError(name + " is not a valid identifier", ex);
+		}
+		//Verifie que ce n'est pas le nom d'un operateur
+		if(operators.containsKey(name)) {
+			throw new LispError(name + " is not a valid identifier");
+		}
+	}
 
 }

+ 99 - 0
src/migl/lisp/operator/DefineOperator.java

@@ -0,0 +1,99 @@
+package migl.lisp.operator;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import migl.lisp.LispElement;
+import migl.lisp.LispError;
+import migl.lisp.LispImpl;
+import migl.lisp.LispOperator;
+import migl.util.ConsList;
+
+public class DefineOperator implements LispOperator {
+	
+	private static Map<String, ConsList<Object>> define = new HashMap<>();
+	
+	@SuppressWarnings("unchecked")
+	public static LispElement eval(Object elt) {
+		if(elt instanceof ConsList) {
+			return eval((ConsList<Object>) elt);
+		}
+		LispElement le = LispElement.generate(elt);
+		try {
+			ConsList<Object> cl = define.get(le.toStr());
+			if(cl != null) {
+				LispElement lelt = LispElement.generate(cl.car());
+				if(!lelt.toString().contains("lambda")) {
+					return lelt;
+				}
+			}
+		} catch(IllegalStateException ex) {
+			//Rien 
+		}
+		return le;
+	}
+	
+	public static LispElement eval(ConsList<Object> lisp) {
+		LispElement le = LispElement.generate(lisp.car());
+		if(le.toString().contains("lambda")) {
+			return evalLambda(lisp);
+		}
+		return LispElement.generate(lisp.car());
+	}
+	
+	private static LispElement evalLambda(ConsList<Object> lisp) {
+		return null;
+	}
+
+	@Override
+	public LispElement apply(String operator, ConsList<Object> lisp) throws LispError {
+		if(lisp.size() != 2) {
+			throw new LispError(LispError.ERR_NUM_ARG);
+		}
+		switch(operator) {
+			case "define":
+				return this.define(lisp);
+			case "set!":
+				return this.set(lisp);
+			default:
+				throw new LispError(operator + LispError.ERR_UNKNOW);
+		}
+	}
+	
+	private LispElement define(ConsList<Object> lisp) throws LispError {
+		//Recup la clef
+		String key;
+		try {
+			key = LispElement.generate(lisp.car()).toStr();
+		} catch(IllegalStateException ex) {
+			throw new LispError(ex);
+		}
+		//Verification de sa validité
+		LispImpl.verifyForbiddenName(key);
+		//Ajoute dans la map
+		define.put(key, lisp.cdr());
+		//Evalue pour le retour
+		return eval(lisp.cdr());
+	}
+
+	private LispElement set(ConsList<Object> lisp) throws LispError {
+		//Recup la clef
+		String key;
+		try {
+			key = LispElement.generate(lisp.car()).toStr();
+		} catch(IllegalStateException ex) {
+			throw new LispError(ex);
+		}
+		//Verification de sa validité
+		LispImpl.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());
+		//Evalue pour le retour
+		return eval(lisp.cdr());
+	}
+
+}