text: //===--- Version.h - Swift Version Number -----------------------*- C++ -*-===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  ///
  /// \file
  /// Defines version macros and version-related utility functions
  /// for Swift.
  ///
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_BASIC_VERSION_H
  #define SWIFT_BASIC_VERSION_H
  
  
  #include "swift/Basic/LLVM.h"
  #include "llvm/ADT/Optional.h"
  #include "llvm/ADT/SmallVector.h"
  #include "llvm/ADT/StringRef.h"
  #include "llvm/Support/VersionTuple.h"
  #include <string>
  
  namespace swift {
  
  class DiagnosticEngine;
  class SourceLoc;
  
  namespace version {
  
  /// Represents an internal compiler version, represented as a tuple of
  /// integers, or "version components".
  ///
  /// For comparison, if a `CompilerVersion` contains more than one
  /// version component, the second one is ignored for comparison,
  /// as it represents a compiler variant with no defined ordering.
  ///
  /// A CompilerVersion must have no more than five components and must fit in a
  /// 64-bit unsigned integer representation.
  ///
  /// Assuming a maximal version component layout of X.Y.Z.a.b,
  /// X, Y, Z, a, b are integers with the following (inclusive) ranges:
  /// X: [0 - 9223371]
  /// Y: [0 - 999]
  /// Z: [0 - 999]
  /// a: [0 - 999]
  /// b: [0 - 999]
  class Version {
    SmallVector<unsigned, 5> Components;
  public:
    /// Create the empty compiler version - this always compares greater
    /// or equal to any other CompilerVersion, as in the case of building Swift
    /// from latest sources outside of a build/integration/release context.
    Version() = default;
  
    /// Create a literal version from a list of components.
    Version(std::initializer_list<unsigned> Values) : Components(Values) {}
  
    /// Create a version from a string in source code.
    ///
    /// Must include only groups of digits separated by a dot.
    Version(StringRef VersionString, SourceLoc Loc, DiagnosticEngine *Diags);
  
    /// Return a string to be used as an internal preprocessor define.
    ///
    /// The components of the version are multiplied element-wise by
    /// \p componentWeights, then added together (a dot product operation).
    /// If either array is longer than the other, the missing elements are
    /// treated as zero.
    ///
    /// The resulting string will have the form "-DMACRO_NAME=XYYZZ".
    /// The combined value must fit in a uint64_t.
    std::string preprocessorDefinition(StringRef macroName,
                                       ArrayRef<uint64_t> componentWeights) const;
  
    /// Return the ith version component.
    unsigned operator[](size_t i) const {
      return Components[i];
    }
  
    /// Return the number of version components.
    size_t size() const {
      return Components.size();
    }
  
    bool empty() const {
      return Components.empty();
    }
  
    /// Convert to a (maximum-4-element) llvm::VersionTuple, truncating
    /// away any 5th component that might be in this version.
    operator llvm::VersionTuple() const;
  
    /// Returns the concrete version to use when \e this version is provided as
    /// an argument to -swift-version.
    ///
    /// This is not the same as the set of Swift versions that have ever existed,
    /// just those that we are attempting to maintain backward-compatibility
    /// support for. It's also common for valid versions to produce a different
    /// result; for example "-swift-version 3" at one point instructed the
    /// compiler to act as if it is version 3.1.
    Optional<Version> getEffectiveLanguageVersion() const;
  
    /// Whether this version is greater than or equal to the given major version
    /// number.
    bool isVersionAtLeast(unsigned major, unsigned minor = 0) const {
      switch (size()) {
      case 0:
        return false;
      case 1:
        return ((Components[0] == major && 0 == minor) ||
                (Components[0] > major));
      default:
        return ((Components[0] == major && Components[1] >= minor) ||
                (Components[0] > major));
      }
    }
  
    /// Return this Version struct with minor and sub-minor components stripped
    Version asMajorVersion() const;
  
    /// Return this Version struct as the appropriate version string for APINotes.
    std::string asAPINotesVersionString() const;
  
    /// Parse a version in the form used by the _compiler_version \#if condition.
    static Optional<Version> parseCompilerVersionString(StringRef VersionString,
                                                        SourceLoc Loc,
                                                        DiagnosticEngine *Diags);
  
    /// Parse a generic version string of the format [0-9]+(.[0-9]+)*
    ///
    /// Version components can be any unsigned 64-bit number.
    static Optional<Version> parseVersionString(StringRef VersionString,
                                                SourceLoc Loc,
                                                DiagnosticEngine *Diags);
  
    /// Returns a version from the currently defined SWIFT_COMPILER_VERSION.
    ///
    /// If SWIFT_COMPILER_VERSION is undefined, this will return the empty
    /// compiler version.
    static Version getCurrentCompilerVersion();
  
    /// Returns a version from the currently defined SWIFT_VERSION_MAJOR and
    /// SWIFT_VERSION_MINOR.
    static Version getCurrentLanguageVersion();
  
    // List of backward-compatibility versions that we permit passing as
    // -swift-version <vers>
    static std::array<StringRef, 3> getValidEffectiveVersions() {
      return {{"4", "4.2", "5"}};
    };
  };
  
  bool operator>=(const Version &lhs, const Version &rhs);
  bool operator<(const Version &lhs, const Version &rhs);
  bool operator==(const Version &lhs, const Version &rhs);
  inline bool operator!=(const Version &lhs, const Version &rhs) {
    return !(lhs == rhs);
  }
  
  raw_ostream &operator<<(raw_ostream &os, const Version &version);
  
  /// Retrieves the numeric {major, minor} Swift version.
  ///
  /// Note that this is the underlying version of the language, ignoring any
  /// -swift-version flags that may have been used in a particular invocation of
  /// the compiler.
  std::pair<unsigned, unsigned> getSwiftNumericVersion();
  
  /// Retrieves a string representing the complete Swift version, which includes
  /// the Swift supported and effective version numbers, the repository version,
  /// and the vendor tag.
  std::string getSwiftFullVersion(Version effectiveLanguageVersion =
                                  Version::getCurrentLanguageVersion());
  
  /// Retrieves the repository revision number (or identifier) from which
  /// this Swift was built.
  StringRef getSwiftRevision();
  
  } // end namespace version
  } // end namespace swift
  
  #endif // SWIFT_BASIC_VERSION_H
  