<commit_before>//  Copyright © 2015 <NAME>. All rights reserved.

extension Term {
	public static func equate(left: Term, _ right: Term) -> Bool {
		return equate(left, right, [:]) != nil
	}

	public static func equate(left: Term, _ right: Term, _ environment: [Name:Term], var visited: Set<Term> = []) -> Term? {
		if left == right { return right }

		let (leftʹ, visitedLeft) = left.weakHeadNormalForm(environment, shouldRecur: false, visited: visited)
		let (rightʹ, visitedRight) = right.weakHeadNormalForm(environment, shouldRecur: false, visited: visited)
		visited.unionInPlace(visitedLeft)
		visited.unionInPlace(visitedRight)

		if leftʹ == rightʹ { return rightʹ }

		switch (leftʹ.out, rightʹ.out) {
		case (.Identity(.Implicit), _):
			return rightʹ

		case (_, .Identity(.Implicit)):
			return leftʹ

		case (.Identity(.Type), .Identity(.Type)):
			return rightʹ

		case let (.Identity(.Application(a1, a2)), .Identity(.Application(b1, b2))):
			guard let first = equate(a1, b1, environment, visited: visited), second = equate(a2, b2, environment, visited: visited) else { return nil }
			return .Application(first, second)

		case let (.Identity(.Lambda(a1, a2)), .Identity(.Lambda(b1, b2))):
			guard let type = equate(a1, b1, environment, visited: visited), body = equate(a2, b2, environment, visited: visited) else { return nil }
			return .Lambda(type, body)

		case let (.Identity(.Embedded(a1, _, t1)), .Identity(.Embedded(a2, eq, t2))):
			guard let t = equate(t1, t2, environment, visited: visited) where eq(a1, a2) else { return nil }
			return .Embedded(a2, eq, t)

		case let (.Abstraction(name1, scope1), .Abstraction(name2, scope2)):
			let fresh = Name.fresh(scope1.freeVariables.union(scope2.freeVariables))
			guard let scope = equate(scope1.rename(name1, fresh), scope2.rename(name2, fresh), environment, visited: visited) else { return nil }<commit_msg>Pick variables that aren’t shadowed, either.<commit_after>//  Copyright © 2015 <NAME>. All rights reserved.

extension Term {
	public static func equate(left: Term, _ right: Term) -> Bool {
		return equate(left, right, [:]) != nil
	}

	public static func equate(left: Term, _ right: Term, _ environment: [Name:Term], var visited: Set<Term> = []) -> Term? {
		if left == right { return right }

		let (leftʹ, visitedLeft) = left.weakHeadNormalForm(environment, shouldRecur: false, visited: visited)
		let (rightʹ, visitedRight) = right.weakHeadNormalForm(environment, shouldRecur: false, visited: visited)
		visited.unionInPlace(visitedLeft)
		visited.unionInPlace(visitedRight)

		if leftʹ == rightʹ { return rightʹ }

		switch (leftʹ.out, rightʹ.out) {
		case (.Identity(.Implicit), _):
			return rightʹ

		case (_, .Identity(.Implicit)):
			return leftʹ

		case (.Identity(.Type), .Identity(.Type)):
			return rightʹ

		case let (.Identity(.Application(a1, a2)), .Identity(.Application(b1, b2))):
			guard let first = equate(a1, b1, environment, visited: visited), second = equate(a2, b2, environment, visited: visited) else { return nil }
			return .Application(first, second)

		case let (.Identity(.Lambda(a1, a2)), .Identity(.Lambda(b1, b2))):
			guard let type = equate(a1, b1, environment, visited: visited), body = equate(a2, b2, environment, visited: visited) else { return nil }
			return .Lambda(type, body)

		case let (.Identity(.Embedded(a1, _, t1)), .Identity(.Embedded(a2, eq, t2))):
			guard let t = equate(t1, t2, environment, visited: visited) where eq(a1, a2) else { return nil }
			return .Embedded(a2, eq, t)

		case let (.Abstraction(name1, scope1), .Abstraction(name2, scope2)):
			let fresh = Name.fresh(scope1.freeVariables.union(scope1.boundVariables).union(scope2.freeVariables).union(scope2.boundVariables))
			guard let scope = equate(scope1.rename(name1, fresh), scope2.rename(name2, fresh), environment, visited: visited) else { return nil }
{'fraction_non_alphanumeric': 0.14433791137600416, 'fraction_numerical': 0.020730759264058048, 'mean_word_length': 4.61863173216885, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, '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': '398367', 'n_tokens_mistral': 1383, 'n_tokens_neox': 1261, 'n_words': 361}