semver
Semantic Versioning 2.0.0 + npm-style range matching.
Reference specs (locked in 2026-05-26) :
- https://semver.org/spec/v2.0.0.html: version-string grammar + precedence rules §1–§12. Ranges are NOT part of this spec.
- https://github.com/npm/node-semver: de-facto reference for the
^/~/||/-/ x-range syntax we adopt.
Public surface :
Versioncarries the parsedmajor.minor.patch[-prerelease][+build].VersionRangecarries the parsed range expression.parse/parse_rangeare the entry points ; both return an explicitT | ParseErrorunion, carryingParseError(fromstd/string) on malformed input.Versionplugs intostd/core::Display,Equals,Comparable: call sites usea.compare(b),a < b,a == b,${v}(interp).VersionRangeplugs intostd/core::Contains<Version>: call sites use the infixinoperator :v in rdesugars tor.contains(v).
Build metadata is excluded from precedence per §10. Range pre-release
matching follows node-semver's strict default : a version with a
pre-release tag only satisfies a clause containing a comparator with
the same [major, minor, patch] tuple AND a pre-release tag.
Types
Version :: struct A parsed SemVer 2.0.0 version. The prerelease and build strings
hold the dot-separated identifiers verbatim (without the leading
- / + separators) ; they default to "" when absent, so a
simple Version { .major = 1, .minor = 2, .patch = 3 } literal is
the canonical way to build a no-pre-release / no-build version.
Use parse for the full grammar.
Fields
major: i32 minor: i32 patch: i32 prerelease: string = "" build: string = "" VersionRange :: struct A parsed range expression: a disjunction of conjunctions of terms,
matching the npm || (OR) / whitespace (AND) grammar. Construct via
parse_range only ; the internal RangeClause / RangeTerm types
are not exported.
Functions
parse :: fn(s: string) -> Version | ParseError Parse s into a Version per SemVer 2.0.0 §2/§9/§10.
Strict : rejects leading zeros on any numeric identifier, empty
identifiers, non-[0-9A-Za-z-] characters in pre-release / build,
missing components.
Parameters
| s | string | the version string (no leading v). |
Returns
Version | ParseError the parsed Version on success.Errors
ParseErrorcarrying a one-line description.
Example
match parsed :: parse("1.2.3-rc.1") {
is Version -> println("${parsed}")
is ParseError -> eprintln(parsed.message())
}parse_range :: fn(s: string) -> VersionRange | ParseError Parse s into a VersionRange per the npm range grammar : ^,
~, primitive comparators (=, <, <=, >, >=), whitespace
for AND, || for OR, hyphen ranges A - B, x-ranges (1.2.x,
1.x, *), and partial versions.
Upper bounds derived from ^ / ~ / x-range carry a -0
pre-release tag so no pre-release of the bumped major / minor can
slip through (matches node-semver).
Parameters
| s | string | the range expression. |
Returns
VersionRange | ParseError the parsed VersionRange on success.Errors
ParseErrorcarrying a one-line description.
Example
r :: parse_range("^1.2.3 || >=2.0.0")