package function.builtin.math import error.LispException import function.ArgumentValidator import function.FunctionNames import function.LispFunction import sexpression.Cons import sexpression.LispNumber import sexpression.SExpression @FunctionNames("MOD", "MODULO", "%") class Modulo(name: String) : LispFunction() { private val argumentValidator = ArgumentValidator(name).apply { setExactNumberOfArguments(2) setEveryArgumentExpectedType(LispNumber::class.java) } override fun call(argumentList: Cons): SExpression { argumentValidator.validate(argumentList) val dividend = argumentList.first as LispNumber val divisor = (argumentList.rest as Cons).first as LispNumber try { return LispNumber(dividend.value.mod(divisor.value)) } catch (e: ArithmeticException) { throw ModulusNotPositiveException() } } class ModulusNotPositiveException : LispException() { override val message = "modulus not positive" } }