transcendental-lisp/src/function/builtin/LENGTH.java

64 lines
1.9 KiB
Java

package function.builtin;
import java.math.BigInteger;
import function.LispFunction;
import sexpression.*;
/**
* <code>LENGTH</code> represents the LENGTH function in Lisp.
*/
public class LENGTH extends LispFunction {
/**
* Returns the length of the given list.
*
* @param list
* the list to determine the length of
* @return the length of <code>list</code>
*/
public static int getLength(Cons list) {
LENGTH lengthFunction = new LENGTH();
LispNumber length = lengthFunction.call(LIST.makeList(list));
return length.getValue().intValue(); // TODO - return BigInteger when all built-ins use
// ArgumentValidator
}
public LispNumber call(Cons argList) {
// make sure we have received at least one argument
if (argList.nullp()) {
Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList);
throw new RuntimeException("too few arguments given to LENGTH: " + originalSExpr);
}
SExpression argCar = argList.getCar();
SExpression argCdr = argList.getCdr();
// make sure we have received only one argument
if (!argCdr.nullp()) {
Cons originalSExpr = new Cons(new Symbol("LENGTH"), argList);
throw new RuntimeException("too many arguments given to LENGTH: " + originalSExpr);
}
// make sure that the argument is a list
if (argCar.listp()) {
Cons arg = (Cons) argCar;
if (arg.nullp()) {
return new LispNumber(BigInteger.ZERO);
}
Cons cdr = LIST.makeList(arg.getCdr());
LispNumber cdrLength = call(cdr);
return new LispNumber(BigInteger.ONE.add(cdrLength.getValue()));
}
throw new RuntimeException("LENGTH: a proper list must not end with " + argCar);
}
}