<commit_before>package jcats.generator.function

import java.util.List
import jcats.generator.Generator
import jcats.generator.InterfaceGenerator
import jcats.generator.Type
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor

import static extension com.google.common.collect.Iterables.concat
import jcats.generator.Constants

@FinalFieldsConstructor
class F2Generator implements InterfaceGenerator {
	val Type type1
	val Type type2
	val Type returnType

	def static List<Generator> generators() {
		(0 ..< Type.values.size).map[i1 |
			(0 ..< Type.values.size).map[i2 |
				Type.values.toList.map[resultType |
					new F2Generator(Type.values.get(i1), Type.values.get(i2), resultType) as Generator
		]]].concat.concat.toList
	}

	override className() { Constants.FUNCTION + "." + shortName }

	def String shortName() {
		if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
			if (returnType == Type.OBJECT) "F2" else returnType.typeName + "F2"
		} else {
			'''«type1.typeName»«type2.typeName»«returnType.typeName»F2'''
		}
	}

	def typeParams(boolean annotations) {
		val params =
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<@Contravariant A1, @Contravariant A2, @Covariant B>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				"<@Contravariant A, @Covariant B>"
			} else {
				"<@Covariant A>"
			}
		} else {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<@Contravariant A1, @Contravariant A2>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				"<@Contravariant A>"
			} else {
				""
			}
		}
		if (annotations) {
			params
		} else {
			params.replaceAll("@Contravariant ", "").replaceAll("@Covariant ", "")
		}
	}

	def variantName() {
		shortName + typeParams(true)
	}

	def genericName() {
		shortName + typeParams(false)
	}

	def paramGenericName() {
		val params = typeParams(false)
		if (params.empty) genericName else params + " " + genericName
	}

	def returnTypeGenericName() {
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT || type2 == Type.OBJECT) "B" else "A"
		} else {
			returnType.javaName
		}
	}

	def type1GenericName() {
		if (type1 == Type.OBJECT && type2 == Type.OBJECT) "A1"
		else if (type1 == Type.OBJECT) "A"
		else type1.javaName
	}

	def type2GenericName() {
		if (type1 == Type.OBJECT && type2 == Type.OBJECT) "A2"
		else if (type2 == Type.OBJECT) "A"
		else type2.javaName
	}

	def mapReturnType() {
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<C> F2<A1, A2, C>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				'''<C> «shortName»<A, C>'''
			} else {
				'''<B> «shortName»<B>'''
			}
		} else {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<B> F2<A1, A2, B>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				'''<B> «type1.typeName»«type2.typeName»«Type.OBJECT.typeName»F2<A, B>'''
			} else {
				'''<A> «type1.typeName»«type2.typeName»«Type.OBJECT.typeName»F2<A>'''
			}
		}
	}

	def mapFunction() {
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT || type2 == Type.OBJECT) "F<B, C>" else "F<A, B>"
		} else {
			if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				'''«returnType.typeName»ObjectF<B>'''
			} else {
				'''«returnType.typeName»ObjectF<A>'''
			}
		}
	}

	def alwaysName() {
		shortName.replaceAll("F2", "Always").firstToLowerCase
	}

	override sourceCode() { '''
		package «Constants.FUNCTION»;

		«IF type1 == Type.OBJECT && type2 == Type.OBJECT && returnType == Type.OBJECT»
			import java.util.function.BiFunction;
			import java.util.function.BinaryOperator;
		«ELSEIF type1 == Type.OBJECT && type2 == Type.OBJECT && returnType.javaUnboxedType»
			import java.util.function.To«returnType.typeName»BiFunction;
		«ELSEIF type1 == Type.OBJECT && type2 == Type.OBJECT && returnType == Type.BOOLEAN»
			import java.util.function.BiPredicate;
		«ELSEIF type1 == type2 && returnType == type2 && Type.javaUnboxedTypes.contains(returnType)»
			import java.util.function.«returnType.typeName»BinaryOperator;
		«ENDIF»

		import «Constants.JCATS».*;

		import static java.util.Objects.requireNonNull;

		@FunctionalInterface
		public interface «variantName» {

			«returnTypeGenericName» apply(«type1GenericName» value1, «type2GenericName» value2);

			default «mapReturnType» map(final «mapFunction» f) {
				requireNonNull(f);
				return (final «type1GenericName» value1, final «type2GenericName» value2) -> {
					«IF type1 == Type.OBJECT»
						requireNonNull(value1);
					«ENDIF»
					«IF type2 == Type.OBJECT»
						requireNonNull(value2);
					«ENDIF»
					«IF returnType == Type.OBJECT»
						final «returnTypeGenericName» value = requireNonNull(apply(value1, value2));
					«ELSE»
						final «returnTypeGenericName» value = apply(value1, value2);
					«ENDIF»
					return requireNonNull(f.apply(value));
				};
			}

			«IF returnType == Type.OBJECT»
				«IF type1 == Type.OBJECT && type2 == Type.OBJECT»
					default <C> F2<C, A2, B> contraMap1(final F<C, A1> f) {
						requireNonNull(f);
						return (final C value1, final A2 value2) -> {
							requireNonNull(value1);
							requireNonNull(value2);
							final A1 value = requireNonNull(f.apply(value1));
							return requireNonNull(apply(value, value2));
						};
					}

					default <C> F2<A1, C, B> contraMap2(final F<C, A2> f) {
						requireNonNull(f);
						return (final A1 value1, final C value2) -> {
							requireNonNull(value1);
							requireNonNull(value2);
							final A2 value = requireNonNull(f.apply(value2));
							return requireNonNull(apply(value1, value));
						};
					}
				«ELSEIF type1 == Type.OBJECT»
					default <C> Object«type2.typeName»ObjectF2<C, B> contraMap1(final F<C, A> f) {
						requireNonNull(f);
						return (final C value1, final «type2.javaName» value2) -> {
							requireNonNull(value1);
							final A value = requireNonNull(f.apply(value1));
							return requireNonNull(apply(value, value2));
						};
					}

					default <C> F2<A, C, B> contraMap2(final «type2.typeName»F<C> f) {<commit_msg>F2.mapToPrimitive<commit_after>package jcats.generator.function

import java.util.List
import jcats.generator.Generator
import jcats.generator.InterfaceGenerator
import jcats.generator.Type
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor

import static extension com.google.common.collect.Iterables.concat
import jcats.generator.Constants

@FinalFieldsConstructor
class F2Generator implements InterfaceGenerator {
	val Type type1
	val Type type2
	val Type returnType

	def static List<Generator> generators() {
		(0 ..< Type.values.size).map[i1 |
			(0 ..< Type.values.size).map[i2 |
				Type.values.toList.map[resultType |
					new F2Generator(Type.values.get(i1), Type.values.get(i2), resultType) as Generator
		]]].concat.concat.toList
	}

	override className() { Constants.FUNCTION + "." + shortName }

	def String shortName() {
		if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
			if (returnType == Type.OBJECT) "F2" else returnType.typeName + "F2"
		} else {
			'''«type1.typeName»«type2.typeName»«returnType.typeName»F2'''
		}
	}

	def typeParams(boolean annotations) {
		val params =
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<@Contravariant A1, @Contravariant A2, @Covariant B>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				"<@Contravariant A, @Covariant B>"
			} else {
				"<@Covariant A>"
			}
		} else {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<@Contravariant A1, @Contravariant A2>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				"<@Contravariant A>"
			} else {
				""
			}
		}
		if (annotations) {
			params
		} else {
			params.replaceAll("@Contravariant ", "").replaceAll("@Covariant ", "")
		}
	}

	def variantName() {
		shortName + typeParams(true)
	}

	def genericName() {
		shortName + typeParams(false)
	}

	def paramGenericName() {
		val params = typeParams(false)
		if (params.empty) genericName else params + " " + genericName
	}

	def returnTypeGenericName() {
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT || type2 == Type.OBJECT) "B" else "A"
		} else {
			returnType.javaName
		}
	}

	def type1GenericName() {
		if (type1 == Type.OBJECT && type2 == Type.OBJECT) "A1"
		else if (type1 == Type.OBJECT) "A"
		else type1.javaName
	}

	def type2GenericName() {
		if (type1 == Type.OBJECT && type2 == Type.OBJECT) "A2"
		else if (type2 == Type.OBJECT) "A"
		else type2.javaName
	}

	def mapReturnType() {
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<C> F2<A1, A2, C>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				'''<C> «shortName»<A, C>'''
			} else {
				'''<B> «shortName»<B>'''
			}
		} else {
			if (type1 == Type.OBJECT && type2 == Type.OBJECT) {
				"<B> F2<A1, A2, B>"
			} else if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				'''<B> «type1.typeName»«type2.typeName»«Type.OBJECT.typeName»F2<A, B>'''
			} else {
				'''<A> «type1.typeName»«type2.typeName»«Type.OBJECT.typeName»F2<A>'''
			}
		}
	}

	def mapFunction() {
		if (returnType == Type.OBJECT) {
			if (type1 == Type.OBJECT || type2 == Type.OBJECT) "F<B, C>" else "F<A, B>"
		} else {
			if (type1 == Type.OBJECT || type2 == Type.OBJECT) {
				'''«returnType.typeName»ObjectF<B>'''
			} else {
				'''«returnType.typeName»ObjectF<A>'''
			}
		}
	}

	def alwaysName() {
		shortName.replaceAll("F2", "Always").firstToLowerCase
	}

	override sourceCode() { '''
		package «Constants.FUNCTION»;

		«IF type1 == Type.OBJECT && type2 == Type.OBJECT && returnType == Type.OBJECT»
			import java.util.function.BiFunction;
			import java.util.function.BinaryOperator;
		«ELSEIF type1 == Type.OBJECT && type2 == Type.OBJECT && returnType.javaUnboxedType»
			import java.util.function.To«returnType.typeName»BiFunction;
		«ELSEIF type1 == Type.OBJECT && type2 == Type.OBJECT && returnType == Type.BOOLEAN»
			import java.util.function.BiPredicate;
		«ELSEIF type1 == type2 && returnType == type2 && Type.javaUnboxedTypes.contains(returnType)»
			import java.util.function.«returnType.typeName»BinaryOperator;
		«ENDIF»

		import «Constants.JCATS».*;

		import static java.util.Objects.requireNonNull;

		@FunctionalInterface
		public interface «variantName» {

			«returnTypeGenericName» apply(«type1GenericName» value1, «type2GenericName» value2);

			default «mapReturnType» map(final «mapFunction» f) {
				requireNonNull(f);
				return (final «type1GenericName» value1, final «type2GenericName» value2) -> {
					«IF type1 == Type.OBJECT»
						requireNonNull(value1);
					«ENDIF»
					«IF type2 == Type.OBJECT»
						requireNonNull(value2);
					«ENDIF»
					«IF returnType == Type.OBJECT»
						final «returnTypeGenericName» value = requireNonNull(apply(value1, value2));
					«ELSE»
						final «returnTypeGenericName» value = apply(value1, value2);
					«ENDIF»
					return requireNonNull(f.apply(value));
				};
			}

			«FOR primitive : Type.primitives»
				«IF returnType == Type.OBJECT»
					«IF type1 == Type.OBJECT && type2 == Type.OBJECT»
						default «primitive.typeName»F2<A1, A2> mapTo«primitive.typeName»(final «primitive.typeName»F<B> f) {
					«ELSEIF type1 == Type.OBJECT || type2 == Type.OBJECT»
						default «type1.typeName»«type2.typeName»«primitive.typeName»F2<A> mapTo«primitive.typeName»(final «primitive.typeName»F<B> f) {
					«ELSE»
						default «type1.typeName»«type2.typeName»«primitive.typeName»F2 mapTo«primitive.typeName»(final «primitive.typeName»F<A> f) {
					«ENDIF»
				«ELSE»
					«IF type1 == Type.OBJECT && type2 == Type.OBJECT»
						default «primitive.typeName»F2<A1, A2> mapTo«primitive.typeName»(final «returnType.typeName»«primitive.typeName»F f) {
					«ELSEIF type1 == Type.OBJECT || type2 == Type.OBJECT»
						default «type1.typeName»«type2.typeName»«primitive.typeName»F2<A> mapTo«primitive.typeName»(final «returnType.typeName»«primitive.typeName»F f) {
					«ELSE»
						default «type1.typeName»«type2.typeName»«primitive.typeName»F2 mapTo«primitive.typeName»(final «returnType.typeName»«primitive.typeName»F f) {
					«ENDIF»
				«ENDIF»
					requireNonNull(f);
					return (final «type1GenericName» value1, final «type2GenericName» value2) -> {
						«IF type1 == Type.OBJECT»
							requireNonNull(value1);
						«ENDIF»
						«IF type2 == Type.OBJECT»
							requireNonNull(value2);
						«ENDIF»
						«IF returnType == Type.OBJECT»
							final «returnTypeGenericName» value = requireNonNull(apply(value1, value2));
						«ELSE»
							final «returnTypeGenericName» value = apply(value1, value2);
						«ENDIF»
						return f.apply(value);
					};
				}

			«ENDFOR»
			«IF returnType == Type.OBJECT» 
				«IF type1 == Type.OBJECT && type2 == Type.OBJECT»
					default <C> F2<C, A2, B> contraMap1(final F<C, A1> f) {
						requireNonNull(f);
						return (final C value1, final A2 value2) -> {
							requireNonNull(value1);
							requireNonNull(value2);
							final A1 value = requireNonNull(f.apply(value1));
							return requireNonNull(apply(value, value2));
						};
					}

					default <C> F2<A1, C, B> contraMap2(final F<C, A2> f) {
						requireNonNull(f);
						return (final A1 value1, final C value2) -> {
							requireNonNull(value1);
							requireNonNull(value2);
							final A2 value = requireNonNull(f.apply(value2));
							return requireNonNull(apply(value1, value));
						};
					}
				«ELSEIF type1 == Type.OBJECT»
					default <C> Object«type2.typeName»ObjectF2<C, B> contraMap1(final F<C, A> f) {
						requireNonNull(f);
						return (final C value1, final «type2.javaName» value2) -> {
							requireNonNull(value1);
							final A value = requireNonNull(f.apply(value1));
							return requireNonNull(apply(value, value2));
						};
					}

					default <C> F2<A, C, B> contraMap2(final «type2.typeName»F<C> f) {
{'fraction_non_alphanumeric': 0.15381301163291686, 'fraction_numerical': 0.021757862990090478, 'mean_word_length': 3.4723827874116893, 'pattern_counts': {'":': 0, '<': 82, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3111277', 'n_tokens_mistral': 5865, 'n_tokens_neox': 4901, 'n_words': 1375}