function isSameReference(left, right) {
	if (left.type !== right.type) {
		// Handle `a.b` and `a?.b` are samely.
		if (left.type === 'ChainExpression') {
			return isSameReference(left.expression, right);
		}

		if (right.type === 'ChainExpression') {
			return isSameReference(left, right.expression);
		}

		return false;
	}

	switch (left.type) {
		case 'Super':
		case 'ThisExpression': {
			return true;
		}

		case 'Identifier':
		case 'PrivateIdentifier': {
			return left.name === right.name;
		}

		case 'Literal': {
			return equalLiteralValue(left, right);
		}

		case 'ChainExpression': {
			return isSameReference(left.expression, right.expression);
		}

		case 'MemberExpression': {
			const nameA = getStaticPropertyName(left);

			// `x.y = x["y"]`
			if (nameA !== undefined) {
				return (
					isSameReference(left.object, right.object)
					&& nameA === getStaticPropertyName(right)
				);
			}

			/*
			`x[0] = x[0]`
			`x[y] = x[y]`
			`x.y = x.y`
			*/
			return (
				left.computed === right.computed
				&& isSameReference(left.object, right.object)
				&& isSameReference(left.property, right.property)
			);
		}

		default: {
			return false;
		}
	}
}
Check if two expressions reference the same value. For example:
	a = a
	a.b = a.b
	a[0] = a[0]
	a['b'] = a['b']
@param {ASTNode} left The left side of the comparison.
@param {ASTNode} right The right side of the comparison.
@returns {boolean} `true` if both sides match and reference the same value.