123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- package migl.lisp;
- import java.math.BigInteger;
- import java.util.Map;
- import migl.util.Cons;
- import java.util.HashMap;
- /**
- * Class pour gérer les élément des expressions Lisp
- *
- * @author Arthur Brandao
- */
- public class LispElement {
-
- /**
- * Garde en cache les elements deja créer pour eviter de recreer plusieurs fois les meme elements
- */
- private static Map<Object, LispElement> cache = new HashMap<>();
- /**
- * La valeur de l'element
- */
- private final Object value;
- /**
- * Constructeur privée pour construire un element à partir de valueOf
- *
- * @param val
- */
- private LispElement(Object val) {
- this.value = val;
- cache.put(val, this);
- }
-
- /**
- * Retourne la valeur de l'element lisp
- * @return
- */
- public Object getValue() {
- return this.value;
- }
-
- /**
- * Retourne la valeur d'un element sous forme d'entier
- *
- * @throws IllegalStateException Si l'element ne peut pas être converti en BigInteger
- * @return
- */
- public BigInteger toInt() {
- if(this.isInt()) {
- return (BigInteger) this.value;
- }
- throw new IllegalStateException("Not an integer");
- }
-
- /**
- * Retourne la valeur d'un element sous forme de nombre
- *
- * @throws IllegalStateException Si l'element ne peut pas être converti en Double
- * @return
- */
- public double toNumber() {
- if(this.value.getClass() == BigInteger.class) {
- BigInteger bi = (BigInteger) this.value;
- return bi.doubleValue();
- } else if(this.value.getClass() == Double.class) {
- return (Double) this.value;
- }
- throw new IllegalStateException("Not a number");
- }
-
- /**
- * Retourne la valeur d'un element sous forme de boolean
- *
- * @throws IllegalStateException Si l'element ne peut pas être converti en boolean
- * @return
- */
- public boolean toBoolean() {
- if(this.isBoolean()) {
- LispBoolean lb = (LispBoolean) this.value;
- return lb.value();
- }
- throw new IllegalStateException("Not a Boolean");
- }
-
- /**
- * Retourne la valeur d'un element sous forme de string
- *
- * @throws IllegalStateException Si l'element ne peut pas être converti en String
- * @return
- */
- public String toStr() {
- if(this.isStr()) {
- return (String) this.value;
- }
- throw new IllegalStateException("Not a String");
- }
-
- /**
- * Retourne la valeur d'un element sous forme d'une liste
- *
- * @throws IllegalStateException
- * @return
- */
- public LispList toList() {
- if(this.isList()) {
- return (LispList) this.value;
- }
- throw new IllegalStateException("Not a List");
- }
-
- /**
- * Retourne la valeur d'un element sous forme d'une cons
- *
- * @throws IllegalStateException
- * @return
- */
- public Cons<?, ?> toCons() {
- if(this.isCons()) {
- return (Cons<?, ?>) this.value;
- }
- throw new IllegalStateException("Not a Cons");
- }
-
- /**
- * Indique si l'element est un entier
- * @return
- */
- public boolean isInt() {
- return this.value.getClass() == BigInteger.class;
- }
-
- /**
- * Indique si l'element est nombre (BigInteger ou Double)
- * @return
- */
- public boolean isNumber() {
- return this.isInt() || (this.value.getClass() == Double.class);
- }
-
- /**
- * Indique si l'element est boolean
- * @return
- */
- public boolean isBoolean() {
- return this.value.getClass() == LispBoolean.class;
- }
-
- /**
- * Indique si l'element est un String
- * @return
- */
- public boolean isStr() {
- return this.value.getClass() == String.class;
- }
-
- /**
- * Indique si l'element est une liste
- * @return
- */
- public boolean isList() {
- return this.value.getClass() == LispList.class;
- }
-
- /**
- * Indique si l'element est une Cons
- * @return
- */
- public boolean isCons() {
- return this.value.getClass() == Cons.class;
- }
- @Override
- public int hashCode() {
- return this.value.hashCode();
- }
- @Override
- public boolean equals(Object obj) {
- if(obj == null) {
- return false;
- } else if(this == obj) {
- return true;
- } else if(obj instanceof LispElement) {
- LispElement other = (LispElement) obj;
- return this.value.equals(other.value);
- }
- return false;
- }
- @Override
- public String toString() {
- return this.value.toString();
- }
-
- /**
- * Indique le nombre actuel d'element en cache
- * @return
- */
- public static int getCacheSize() {
- return cache.size();
- }
-
- /**
- * Supprime le cache
- */
- public static void clear() {
- cache.clear();
- }
- /**
- * Parse un element
- *
- * @param elt L'element à parser
- * @return Un LispElement contenant la valeur extraite
- */
- public static LispElement valueOf(String elt) {
- try {
- return generate(new BigInteger(elt));
- } catch(NumberFormatException ex) {
- //Rien
- }
- try {
- return generate(Double.valueOf(elt));
- } catch(NumberFormatException ex) {
- //Rien
- }
- try {
- return generate(LispBoolean.valueOf(elt));
- } catch(IllegalArgumentException ex) {
- //Rien
- }
- return generate(elt);
- }
-
- /**
- * Genere un LispElement correspondant à l'objet
- *
- * @param elt
- * @return
- */
- public static LispElement generate(Object elt) {
- if(elt == null) {
- return new LispElement(null);
- }
- else if(elt.getClass() == LispElement.class) {
- return (LispElement) elt;
- }
- else if(elt.getClass() == Integer.class) {
- elt = BigInteger.valueOf((Integer) elt);
- }
- else if(elt.getClass() == Boolean.class) {
- elt = LispBoolean.valueOf((boolean) elt);
- }
- else if(elt.getClass() == Long.class) {
- elt = BigInteger.valueOf((long) elt);
- }
- else if(
- elt.getClass() != BigInteger.class
- && elt.getClass() != Double.class
- && elt.getClass() != LispBoolean.class
- && elt.getClass() != String.class
- && elt.getClass() != LispList.class
- && elt.getClass() != Cons.class
- ) {
- throw new IllegalArgumentException("Object class is not a Lisp element");
- }
- if(cache.containsKey(elt)) {
- return cache.get(elt);
- }
- return new LispElement(elt);
- }
- }
|