Sfoglia il codice sorgente

Ajout gestion lambda expression

Arthur Brandao 6 anni fa
parent
commit
858593f106

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

@@ -113,6 +113,10 @@ public class LispElement {
 	public String toString() {
 		return this.value.toString();
 	}
+	
+	public static void clear() {
+		cache.clear();
+	}
 
 	/**
 	 * Parse un element
@@ -146,6 +150,9 @@ public class LispElement {
 	 * @return
 	 */
 	public static LispElement generate(Object elt) {
+		if(elt.getClass() == LispElement.class) {
+			return (LispElement) elt;
+		}
 		if(elt.getClass() == Integer.class) {
 			elt = BigInteger.valueOf((Integer) elt);
 		}

+ 8 - 0
src/migl/lisp/LispFactory.java

@@ -22,10 +22,18 @@ public class LispFactory {
      * @return a new lisp interpreter.
      */
     public static Lisp makeIntepreter() {
+    	LispElement.clear();
     	DefineOperator.clear();
     	if(interpreter == null) {
     		interpreter = new LispImpl();
     	}
         return interpreter;
     }
+    
+    public static Lisp getInterpreter() {
+    	if(interpreter == null) {
+    		interpreter = new LispImpl();
+    	}
+        return interpreter;
+    }
 }

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

@@ -157,7 +157,7 @@ public class LispImpl implements Lisp {
 			throw new LispError("Invalid Format");
 		}
 		//Remplace les nil par ()
-		expr = expr.replaceAll(" nil", " ()");
+		expr = expr.replaceAll(" nil ", " () ").replaceAll("\\(nil ", "(() ").replaceAll(" nil\\)", " ())");
 		//Explose l'expression
 		Queue<String> explode = this.explode(expr);
 		//Analyse le type d'expression
@@ -329,7 +329,11 @@ public class LispImpl implements Lisp {
 		String operator = LispElement.generate(lisp.car()).toStr();
 		LispOperator op = operators.get(operator);
 		if(op == null) {
-			throw new LispError(operator + LispError.ERR_UNKNOW, new UnsupportedOperationException("Unknow operator"));
+			if(DefineOperator.isLambda(operator)) {
+				return operators.get("lambda").apply(operator, lisp.cdr());
+			} else {
+				throw new LispError(operator + LispError.ERR_UNKNOW, new UnsupportedOperationException("Unknow operator"));
+			}
 		}
 		try {
 			return op.apply(operator, lisp.cdr());

+ 60 - 8
src/migl/lisp/operator/DefineOperator.java

@@ -3,8 +3,10 @@ package migl.lisp.operator;
 import java.util.Map;
 import java.util.HashMap;
 
+import migl.lisp.Lisp;
 import migl.lisp.LispElement;
 import migl.lisp.LispError;
+import migl.lisp.LispFactory;
 import migl.lisp.LispImpl;
 import migl.lisp.LispOperator;
 import migl.util.ConsList;
@@ -20,6 +22,27 @@ public class DefineOperator implements LispOperator {
 		define.clear();
 	}
 	
+	@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;
+		}
+	}
+	
 	@SuppressWarnings("unchecked")
 	public static LispElement eval(Object elt) throws LispError {
 		if(elt instanceof ConsList) {
@@ -50,27 +73,23 @@ public class DefineOperator implements LispOperator {
 		}
 		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);
+				return this.lambda(operator, lisp);
 		}
 	}
 	
 	private LispElement define(ConsList<Object> lisp) throws LispError {
+		if(lisp.size() != 2) {
+			throw new LispError(LispError.ERR_NUM_ARG);
+		}
 		//Recup la clef
 		LispElement le = LispElement.generate(lisp.car());
 		String key;
@@ -88,6 +107,9 @@ public class DefineOperator implements LispOperator {
 	}
 
 	private LispElement set(ConsList<Object> lisp) throws LispError {
+		if(lisp.size() != 2) {
+			throw new LispError(LispError.ERR_NUM_ARG);
+		}
 		//Recup la clef
 		String key;
 		try {
@@ -106,5 +128,35 @@ public class DefineOperator implements LispOperator {
 		//Evalue pour le retour
 		return eval(lisp.cdr());
 	}
+	
+	private LispElement lambda(String operator, ConsList<Object> lisp) throws LispError {
+		if(!isLambda(operator)) {
+			throw new LispError(operator + LispError.ERR_UNKNOW);
+		}
+		//Recup les infos
+		ConsList<Object> lambda = (ConsList<Object>) define.get(operator).car();
+		ConsList<Object> param = (ConsList<Object>) lambda.cdr().car();
+		lambda = (ConsList<Object>) lambda.cdr().cdr().car();
+		System.out.println(operator);
+		System.out.println(lambda);
+		System.out.println(param);
+		System.out.println(lisp);
+		if(param.size() != lisp.size()) {
+			throw new LispError(LispError.ERR_NUM_ARG);
+		}
+		//Remplace les parametres
+		String lispExpr = lambda.toString();
+		while(!param.isEmpty()) {
+			lispExpr = lispExpr.replaceAll(" " + param.car() + " ", " " + lisp.car() + " ")
+					.replaceAll("\\(" + param.car() + " ", "\\(" + lisp.car() + " ")
+					.replaceAll(" " + param.car() + "\\)", " " + lisp.car() + "\\)");
+			param = param.cdr();
+			lisp = lisp.cdr();
+		}
+		System.out.println(lispExpr);
+		//Evalue le resultat
+		Lisp l = LispFactory.getInterpreter();
+		return LispElement.generate(l.eval(lispExpr));
+	}
 
 }