// Path: matchers/src/main/java/jinsist/matchers/Arguments.java
// public class Arguments {
//     private List<ArgumentMatcher<?>> argumentMatchers;
// 
//     public Arguments(List<ArgumentMatcher<?>> argumentMatchers) {
//         this.argumentMatchers = argumentMatchers;
//     }
// 
//     public boolean matches(Object... arguments) {
//         int length = argumentMatchers.size();
//         if (length != arguments.length)
//             return false;
//         else
//             for (int i = 0; i < length; i++) {
//                 ArgumentMatcher matcher = argumentMatchers.get(i);
//                 @SuppressWarnings("unchecked")
//                 boolean matches = matcher.matches(arguments[i]);
//                 if (!matches) return false;
//             }
//         return true;
//     }
// 
//     public List<ArgumentMatcher<?>> getArgumentMatchers() {
//         return argumentMatchers;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Arguments arguments = (Arguments) o;
// 
//         return argumentMatchers.equals(arguments.argumentMatchers);
//     }
// 
//     @Override
//     public int hashCode() {
//         return argumentMatchers != null ? argumentMatchers.hashCode() : 0;
//     }
// }


import jinsist.matchers.Arguments;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
            Method method,
            Arguments arguments,
            ReturnType result
    ) {
        ExpectedInvocation<MockType> invocation = new ExpectedInvocation<>(classToMock, instance, method, arguments);
        expectations.add(new Expectation<>(invocation, result));
    }

    @Override
    public <MockType> Object execute(
            Class<MockType> classToMock,
            MockType instance,
            Method method,
            Object[] arguments
    ) {
        Invocation<MockType> invocation = new Invocation<>(classToMock, instance, method, arguments);
        if (expectations.isEmpty()) {
            throw new UnexpectedInvocation(invocation);
        }
        Expectation expectation = expectations.remove(0);

        verifyExpectationMatchesInvocation(expectation, invocation);

        return expectation.getResult();
    }

    private <MockType> void verifyExpectationMatchesInvocation(
            Expectation expectation,
            Invocation<MockType> invocation
    ) {
// Path: matchers/src/main/java/jinsist/matchers/Arguments.java
// public class Arguments {
//     private List<ArgumentMatcher<?>> argumentMatchers;
// 
//     public Arguments(List<ArgumentMatcher<?>> argumentMatchers) {
//         this.argumentMatchers = argumentMatchers;
//     }
// 
//     public boolean matches(Object... arguments) {
//         int length = argumentMatchers.size();
//         if (length != arguments.length)
//             return false;
//         else
//             for (int i = 0; i < length; i++) {
//                 ArgumentMatcher matcher = argumentMatchers.get(i);
//                 @SuppressWarnings("unchecked")
//                 boolean matches = matcher.matches(arguments[i]);
//                 if (!matches) return false;
//             }
//         return true;
//     }
// 
//     public List<ArgumentMatcher<?>> getArgumentMatchers() {
//         return argumentMatchers;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Arguments arguments = (Arguments) o;
// 
//         return argumentMatchers.equals(arguments.argumentMatchers);
//     }
// 
//     @Override
//     public int hashCode() {
//         return argumentMatchers != null ? argumentMatchers.hashCode() : 0;
//     }
// }


// Path: expectations/src/main/java/jinsist/expectations/OrderedExpectations.java
import jinsist.matchers.Arguments;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

            Method method,
            Arguments arguments,
            ReturnType result
    ) {
        ExpectedInvocation<MockType> invocation = new ExpectedInvocation<>(classToMock, instance, method, arguments);
        expectations.add(new Expectation<>(invocation, result));
    }

    @Override
    public <MockType> Object execute(
            Class<MockType> classToMock,
            MockType instance,
            Method method,
            Object[] arguments
    ) {
        Invocation<MockType> invocation = new Invocation<>(classToMock, instance, method, arguments);
        if (expectations.isEmpty()) {
            throw new UnexpectedInvocation(invocation);
        }
        Expectation expectation = expectations.remove(0);

        verifyExpectationMatchesInvocation(expectation, invocation);

        return expectation.getResult();
    }

    private <MockType> void verifyExpectationMatchesInvocation(
            Expectation expectation,
            Invocation<MockType> invocation
    ) {
        if (!expectation.isFor(invocation)) {