300 lines
6.0 KiB
Java
300 lines
6.0 KiB
Java
/* :folding=explicit:collapseFolds=1: */
|
|
|
|
/*
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2003, 2004 Slava Pestov.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
package factor;
|
|
|
|
/**
|
|
* Used to build up linked lists.
|
|
*/
|
|
public class Cons implements PublicCloneable, FactorExternalizable
|
|
{
|
|
public static int COUNT;
|
|
|
|
public Object car;
|
|
public Object cdr;
|
|
|
|
//{{{ Cons constructor
|
|
public Cons(Object car, Object cdr)
|
|
{
|
|
this.car = car;
|
|
this.cdr = cdr;
|
|
|
|
COUNT++;
|
|
} //}}}
|
|
|
|
//{{{ car() method
|
|
public Object car(Class clas) throws Exception
|
|
{
|
|
return FactorJava.convertToJavaType(car,clas);
|
|
} //}}}
|
|
|
|
//{{{ cdr() method
|
|
public Object cdr(Class clas) throws Exception
|
|
{
|
|
return FactorJava.convertToJavaType(cdr,clas);
|
|
} //}}}
|
|
|
|
//{{{ next() method
|
|
public Cons next()
|
|
{
|
|
return (Cons)cdr;
|
|
} //}}}
|
|
|
|
//{{{ get() method
|
|
public Object get(int index)
|
|
{
|
|
return _get(index).car;
|
|
} //}}}
|
|
|
|
//{{{ _get() method
|
|
public Cons _get(int index)
|
|
{
|
|
Cons iter = this;
|
|
while(index != 0)
|
|
{
|
|
iter = (Cons)iter.cdr;
|
|
index--;
|
|
}
|
|
return iter;
|
|
} //}}}
|
|
|
|
//{{{ contains() method
|
|
public boolean contains(Object obj)
|
|
{
|
|
Cons iter = this;
|
|
while(iter != null)
|
|
{
|
|
if(FactorLib.objectsEqual(obj,iter.car))
|
|
return true;
|
|
iter = iter.next();
|
|
}
|
|
return false;
|
|
} //}}}
|
|
|
|
//{{{ contains() method
|
|
public static boolean contains(Cons list, Object obj)
|
|
{
|
|
if(list == null)
|
|
return false;
|
|
else
|
|
return list.contains(obj);
|
|
} //}}}
|
|
|
|
//{{{ length() method
|
|
public int length()
|
|
{
|
|
int size = 0;
|
|
Cons iter = this;
|
|
while(iter != null)
|
|
{
|
|
iter = (Cons)iter.cdr;
|
|
size++;
|
|
}
|
|
return size;
|
|
} //}}}
|
|
|
|
//{{{ nappend() method
|
|
public static Cons nappend(Cons l1, Cons l2)
|
|
{
|
|
if(l1 == null)
|
|
return l2;
|
|
if(l2 == null)
|
|
return l1;
|
|
Cons last = l1;
|
|
while(last.cdr != null)
|
|
last = last.next();
|
|
last.cdr = l2;
|
|
return l1;
|
|
} //}}}
|
|
|
|
//{{{ reverse() method
|
|
public static Cons reverse(Cons list)
|
|
{
|
|
Cons reversed = null;
|
|
while(list != null)
|
|
{
|
|
reversed = new Cons(list.car,reversed);
|
|
list = list.next();
|
|
}
|
|
return reversed;
|
|
} //}}}
|
|
|
|
//{{{ assoc() method
|
|
public static Object assoc(Cons assoc, Object key)
|
|
{
|
|
if(assoc == null)
|
|
return null;
|
|
else
|
|
{
|
|
Cons first = (Cons)assoc.car;
|
|
if(FactorLib.equal(first.car,key))
|
|
return first.cdr;
|
|
else
|
|
return assoc(assoc.next(),key);
|
|
}
|
|
} //}}}
|
|
|
|
//{{{ elementsToString() method
|
|
/**
|
|
* Returns a whitespace separated string of the unparseObject() of each
|
|
* item.
|
|
*/
|
|
public String elementsToString()
|
|
{
|
|
StringBuffer buf = new StringBuffer();
|
|
Cons iter = this;
|
|
while(iter != null)
|
|
{
|
|
buf.append(FactorReader.unparseObject(iter.car));
|
|
if(iter.cdr instanceof Cons)
|
|
{
|
|
buf.append(' ');
|
|
iter = (Cons)iter.cdr;
|
|
continue;
|
|
}
|
|
else if(iter.cdr == null)
|
|
break;
|
|
else
|
|
{
|
|
buf.append(" | ");
|
|
buf.append(FactorReader.unparseObject(iter.cdr));
|
|
iter = null;
|
|
}
|
|
}
|
|
|
|
return buf.toString();
|
|
} //}}}
|
|
|
|
//{{{ toString() method
|
|
/**
|
|
* Returns elementsToString() enclosed with [ and ].
|
|
*/
|
|
public String toString()
|
|
{
|
|
return "[ " + elementsToString() + " ]";
|
|
} //}}}
|
|
|
|
//{{{ toArray() method
|
|
/**
|
|
* Note that unlike Java list toArray(), the given array must already
|
|
* be the right size.
|
|
*/
|
|
public Object[] toArray(Object[] returnValue)
|
|
{
|
|
int i = 0;
|
|
Cons iter = this;
|
|
while(iter != null)
|
|
{
|
|
returnValue[i++] = iter.car;
|
|
iter = iter.next();
|
|
}
|
|
return returnValue;
|
|
} //}}}
|
|
|
|
//{{{ fromArray() method
|
|
public static Cons fromArray(Object[] array)
|
|
{
|
|
if(array == null || array.length == 0)
|
|
return null;
|
|
else
|
|
{
|
|
Cons first = new Cons(array[0],null);
|
|
Cons last = first;
|
|
for(int i = 1; i < array.length; i++)
|
|
{
|
|
Cons cons = new Cons(array[i],null);
|
|
last.cdr = cons;
|
|
last = cons;
|
|
}
|
|
return first;
|
|
}
|
|
} //}}}
|
|
|
|
//{{{ equals() method
|
|
public boolean equals(Object o)
|
|
{
|
|
if(o instanceof Cons)
|
|
{
|
|
Cons l = (Cons)o;
|
|
return FactorLib.objectsEqual(car,l.car)
|
|
&& FactorLib.objectsEqual(cdr,l.cdr);
|
|
}
|
|
else
|
|
return false;
|
|
} //}}}
|
|
|
|
//{{{ hashCode() method
|
|
public int hashCode()
|
|
{
|
|
if(car == null)
|
|
return 0;
|
|
else
|
|
return car.hashCode();
|
|
} //}}}
|
|
|
|
//{{{ clone() method
|
|
public Object clone()
|
|
{
|
|
if(cdr instanceof Cons)
|
|
return new Cons(car,((Cons)cdr).clone());
|
|
else
|
|
return new Cons(car,cdr);
|
|
} //}}}
|
|
|
|
//{{{ deepClone() method
|
|
public static Cons deepClone(Cons list)
|
|
{
|
|
if(list == null)
|
|
return null;
|
|
|
|
Object ccar;
|
|
if(list.car instanceof PublicCloneable)
|
|
ccar = ((PublicCloneable)list.car).clone();
|
|
else
|
|
ccar = list.car;
|
|
if(list.cdr instanceof Cons)
|
|
{
|
|
return new Cons(ccar,deepClone(list.next()));
|
|
}
|
|
else if(list.cdr == null)
|
|
{
|
|
return new Cons(ccar,null);
|
|
}
|
|
else
|
|
{
|
|
Object ccdr;
|
|
if(list.cdr instanceof PublicCloneable)
|
|
ccdr = ((PublicCloneable)list.cdr).clone();
|
|
else
|
|
ccdr = list.cdr;
|
|
return new Cons(ccar,ccdr);
|
|
}
|
|
} //}}}
|
|
}
|