package function.builtin; import java.math.BigInteger; import function.LispFunction; import sexpression.*; /** * LENGTH 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 list */ 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); } }