summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2022-06-08 13:40:09 -0400
committerGitHub <noreply@github.com>2022-06-08 13:40:09 -0400
commitff2ae7e0c1b48fa222f14dc84f15d0178ed056a1 (patch)
treec4a3ab1e3441ec40267125086e511ef05342a547 /source/core
parent8e6e884eca5b33218a8cb2714266fb6ed4548d75 (diff)
Improvements around Visual Studio versions/matching versions (#2267)
* #include an absolute path didn't work - because paths were taken to always be relative. * Use TerminatedUnownedStringSlice for literals in output C++. * Remove Escape/Unescape functions used in slang-token-reader.cpp Add target type of 'host-cpp' etc to map to the target types. * Fix some corner cases around string encoding. * Added unit test for string escaping. Fixed some assorted escaping bugs. * Updated test output. * Added decode test. * Stop using hex output, to get around 'greedy' aspect. Use octal instead. * Added HostHostCallable Small changes to use ArtifactDesc/Info instead of large switches. * Fix C++ emit to handle arbitrary function export. * Add options handling for callable without an output being specified. * Can compile with COM interface. Added example using com interface. * Use the IR Ptr type instead of hack in C++ emit for interfaces. * Fix issue with outputting the COM call when ptr is used. * Fix crash issue on compilation failure. * Add support for __global. * Added `ActualGlobalRate` Added special handling around globals and COM interfaces. Tested out in cpu-com-example. * Fix typo in NodeBase. * Support for accessing globals by name working. * Check that actual global initialization is working. * Refactor the com replacement such that it doesn't need a cache or do anything special with GlobalVar. * Remove context. Only create replacement if needed. * Split out COM host-callable into a unit-test. * host-callable com testing on C++and llvm. * Comment around the COM ptr replacement. * Disable com test on vs 32 bit. Fix C++ prelude * Disable 32 bit targets testing com host-callable. * Use JSON parsing to locate VS version. * Need platform detection in C++prelude. * Fix com host callable test for LLVM. * WIP improments finding downstream compiler version. * Work around for not being able to include "targetConditionals.h" * Matching semantic versioning support. * DownstreamMatchVersion -> DownstreamCompilerMatchVersion Small improvements.
Diffstat (limited to 'source/core')
-rw-r--r--source/core/slang-semantic-version.cpp153
-rw-r--r--source/core/slang-semantic-version.h46
2 files changed, 199 insertions, 0 deletions
diff --git a/source/core/slang-semantic-version.cpp b/source/core/slang-semantic-version.cpp
index 7f603fd9c..cc631d292 100644
--- a/source/core/slang-semantic-version.cpp
+++ b/source/core/slang-semantic-version.cpp
@@ -7,6 +7,8 @@
namespace Slang {
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SemanticVersion !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
SlangResult SemanticVersion::parse(const UnownedStringSlice& value, char separatorChar, SemanticVersion& outVersion)
{
outVersion.reset();
@@ -52,4 +54,155 @@ void SemanticVersion::append(StringBuilder& buf) const
}
}
+/* static */SemanticVersion SemanticVersion::getEarliest(const ThisType* versions, Count count)
+{
+ if (count <= 0)
+ {
+ return SemanticVersion();
+ }
+
+ SemanticVersion bestVersion = versions[0];
+ for (const auto version : makeConstArrayView(versions + 1, count - 1))
+ {
+ if (version < bestVersion)
+ {
+ bestVersion = version;
+ }
+ }
+ return bestVersion;
+}
+
+/* static */SemanticVersion SemanticVersion::getLatest(const ThisType* versions, Count count)
+{
+ if (count <= 0)
+ {
+ return SemanticVersion();
+ }
+
+ SemanticVersion bestVersion = versions[0];
+ for (const auto version : makeConstArrayView(versions + 1, count - 1))
+ {
+ if (version > bestVersion)
+ {
+ bestVersion = version;
+ }
+ }
+ return bestVersion;
+}
+
+
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MatchSemanticVersion !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+/* static */SemanticVersion MatchSemanticVersion::findAnyBest(const SemanticVersion* versions, Count count, const ThisType& matchVersion)
+{
+ // If there aren't any we are done
+ if (count <= 0)
+ {
+ return SemanticVersion();
+ }
+
+ // If there is only one it must be the best
+ if (count == 1)
+ {
+ return versions[0];
+ }
+
+ // Define a version range [start, end)
+ SemanticVersion start, end;
+
+ switch (matchVersion.m_kind)
+ {
+ case Kind::Past:
+ {
+ return SemanticVersion::getEarliest(versions, count);
+ }
+ case Kind::Unknown:
+ case Kind::Future:
+ {
+ // If it's unknown, we just get the latest
+ return SemanticVersion::getLatest(versions, count);
+ }
+ case Kind::Major:
+ {
+ start = SemanticVersion(matchVersion.m_version.m_major, 0, 0);
+ end = SemanticVersion(matchVersion.m_version.m_major + 1, 0, 0);
+ break;
+ }
+ case Kind::MajorMinor:
+ {
+ start = SemanticVersion(matchVersion.m_version.m_major, matchVersion.m_version.m_minor, 0);
+ end = SemanticVersion(matchVersion.m_version.m_major, matchVersion.m_version.m_minor + 1, 0);
+ break;
+ }
+ case Kind::MajorMinorPatch:
+ {
+ start = SemanticVersion(matchVersion.m_version);
+ end = SemanticVersion(matchVersion.m_version.m_major, matchVersion.m_version.m_minor, matchVersion.m_version.m_patch + 1);
+ break;
+ }
+ default: break;
+ }
+
+ List<SemanticVersion> sortedVersions;
+ sortedVersions.addRange(versions, count);
+
+ // Sort into increasing values
+ sortedVersions.sort([&](const SemanticVersion& a, const SemanticVersion& b) -> bool { return a < b; });
+
+ Index startIndex = 0;
+ for (; startIndex < count && sortedVersions[startIndex] < start; ++startIndex);
+
+ Index endIndex = startIndex;
+ for (; endIndex < count && sortedVersions[endIndex] < end; ++endIndex);
+
+ // If we have a span of versions, get the last in the span
+ if (startIndex < endIndex)
+ {
+ // Get the last one
+ return sortedVersions[endIndex - 1];
+ }
+
+ // Get the next greatest if there is one
+ if (endIndex < count)
+ {
+ return sortedVersions[endIndex];
+ }
+
+ // Get the prior prior to the start
+ if (startIndex > 0)
+ {
+ return sortedVersions[startIndex - 1];
+ }
+
+ // All cases should be covered, but return the last one
+ return sortedVersions[count - 1];
+}
+
+void MatchSemanticVersion::append(StringBuilder& buf) const
+{
+ switch (m_kind)
+ {
+ default:
+ case Kind::Unknown: buf << "unknown"; break;
+ case Kind::Past: buf << "past"; break;
+ case Kind::Future: buf << "future"; break;
+ case Kind::Major:
+ {
+ buf << m_version.m_major;
+ break;
+ }
+ case Kind::MajorMinor:
+ {
+ buf << m_version.m_major << "." << m_version.m_minor;
+ break;
+ }
+ case Kind::MajorMinorPatch:
+ {
+ m_version.append(buf);
+ break;
+ }
+ }
+}
+
} // namespace Slang
diff --git a/source/core/slang-semantic-version.h b/source/core/slang-semantic-version.h
index d33116de6..4d64627c2 100644
--- a/source/core/slang-semantic-version.h
+++ b/source/core/slang-semantic-version.h
@@ -47,6 +47,9 @@ struct SemanticVersion
static SlangResult parse(const UnownedStringSlice& value, SemanticVersion& outVersion);
static SlangResult parse(const UnownedStringSlice& value, char separatorChar, SemanticVersion& outVersion);
+ static ThisType getEarliest(const ThisType* versions, Count count);
+ static ThisType getLatest(const ThisType* versions, Count count);
+
void append(StringBuilder& buf) const;
bool operator>(const ThisType& rhs) const { return toInteger() > rhs.toInteger(); }
@@ -63,5 +66,48 @@ struct SemanticVersion
uint16_t m_patch;
};
+/* Adds to the semantic versioning information for an incomplete version that can be matched */
+struct MatchSemanticVersion
+{
+ typedef MatchSemanticVersion ThisType;
+
+ enum class Kind
+ {
+ Unknown, ///< Not known
+ Past, ///< Some unknown past version
+ Future, ///< Some future unknown version
+ Major, ///< Major version is defined (minor is in effect undefined)
+ MajorMinor, ///< Major and minor version are defined
+ MajorMinorPatch, ///< All elements of semantic version are defined
+ };
+
+ /// True if has a complete version
+ bool hasCompleteVersion() const { return m_kind == Kind::MajorMinorPatch; }
+ /// True if has some version information
+ bool hasVersion() const { return Index(m_kind) >= Index(Kind::Major); }
+
+ void set(Index major) { m_kind = Kind::Major; m_version = SemanticVersion(int(major), 0, 0); }
+ void set(Index major, Index minor) { m_kind = Kind::MajorMinor; m_version = SemanticVersion(int(major), int(minor), 0); }
+ void set(Index major, Index minor, Index patch) { m_kind = Kind::MajorMinorPatch; m_version = SemanticVersion(int(major), int(minor), int(patch)); }
+
+ void append(StringBuilder& buf) const;
+
+ static MatchSemanticVersion makeFuture() { MatchSemanticVersion version; version.m_kind = Kind::Future; return version; }
+
+ /// Finds the 'best' version based on the versions passed.
+ /// Doesn't follow strict semantic rules as will attempt to return the closest 'any' in past or future
+ /// If none can be found, returns an empty semantic version
+ static SemanticVersion findAnyBest(const SemanticVersion* versions, Count count, const ThisType& matchVersion);
+
+ MatchSemanticVersion():m_kind(Kind::Unknown) {}
+ MatchSemanticVersion(Kind kind, const SemanticVersion& version):
+ m_kind(kind),
+ m_version(version)
+ {}
+
+ Kind m_kind;
+ SemanticVersion m_version;
+};
+
}
#endif