// Path: app/src/main/java/com/annimon/hotarufx/exceptions/ArgumentsMismatchException.java
// public class ArgumentsMismatchException extends HotaruRuntimeException {
// 
//     public ArgumentsMismatchException(String message) {
//         super(message);
//     }
// 
//     public ArgumentsMismatchException(String message, SourcePosition start, SourcePosition end) {
//         super(message, start, end);
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/exceptions/TypeException.java
// public class TypeException extends HotaruRuntimeException {
// 
//     public TypeException(String message) {
//         super(message);
//     }
// 
//     public TypeException(String message, SourcePosition start, SourcePosition end) {
//         super(message, start, end);
//     }
// }


import com.annimon.hotarufx.exceptions.ArgumentsMismatchException;
import com.annimon.hotarufx.exceptions.TypeException;
    public Validator check(int expected) {
        if (args.length != expected) throw new ArgumentsMismatchException(String.format(
                "%d %s expected, got %d", expected, pluralize(expected), args.length));
        return this;
    }

    public Validator checkAtLeast(int expected) {
        if (args.length < expected) throw new ArgumentsMismatchException(String.format(
                "At least %d %s expected, got %d", expected, pluralize(expected), args.length));
        return this;
    }

    public Validator checkOrOr(int expectedOne, int expectedTwo) {
        if (expectedOne != args.length && expectedTwo != args.length)
            throw new ArgumentsMismatchException(String.format(
                    "%d or %d arguments expected, got %d", expectedOne, expectedTwo, args.length));
        return this;
    }

    public Validator checkRange(int from, int to) {
        if (from > args.length || args.length > to)
            throw new ArgumentsMismatchException(String.format(
                    "From %d to %d arguments expected, got %d", from, to, args.length));
        return this;
    }

    public ArrayValue requireArrayAt(int index) {
        checkAtLeast(index + 1);
        final var value = args[index];
        if (value.type() != Types.ARRAY) {
// Path: app/src/main/java/com/annimon/hotarufx/exceptions/ArgumentsMismatchException.java
// public class ArgumentsMismatchException extends HotaruRuntimeException {
// 
//     public ArgumentsMismatchException(String message) {
//         super(message);
//     }
// 
//     public ArgumentsMismatchException(String message, SourcePosition start, SourcePosition end) {
//         super(message, start, end);
//     }
// }
// 
// Path: app/src/main/java/com/annimon/hotarufx/exceptions/TypeException.java
// public class TypeException extends HotaruRuntimeException {
// 
//     public TypeException(String message) {
//         super(message);
//     }
// 
//     public TypeException(String message, SourcePosition start, SourcePosition end) {
//         super(message, start, end);
//     }
// }


// Path: app/src/main/java/com/annimon/hotarufx/lib/Validator.java
import com.annimon.hotarufx.exceptions.ArgumentsMismatchException;
import com.annimon.hotarufx.exceptions.TypeException;

    public Validator check(int expected) {
        if (args.length != expected) throw new ArgumentsMismatchException(String.format(
                "%d %s expected, got %d", expected, pluralize(expected), args.length));
        return this;
    }

    public Validator checkAtLeast(int expected) {
        if (args.length < expected) throw new ArgumentsMismatchException(String.format(
                "At least %d %s expected, got %d", expected, pluralize(expected), args.length));
        return this;
    }

    public Validator checkOrOr(int expectedOne, int expectedTwo) {
        if (expectedOne != args.length && expectedTwo != args.length)
            throw new ArgumentsMismatchException(String.format(
                    "%d or %d arguments expected, got %d", expectedOne, expectedTwo, args.length));
        return this;
    }

    public Validator checkRange(int from, int to) {
        if (from > args.length || args.length > to)
            throw new ArgumentsMismatchException(String.format(
                    "From %d to %d arguments expected, got %d", from, to, args.length));
        return this;
    }

    public ArrayValue requireArrayAt(int index) {
        checkAtLeast(index + 1);
        final var value = args[index];
        if (value.type() != Types.ARRAY) {
            throw new TypeException(String.format("Array required at %d argument", index));