namespace NubLang.Code; public readonly struct SourceSpan : IEquatable { public static SourceSpan Zero => new(SourceLocation.Zero, SourceLocation.Zero); public static SourceSpan Merge(params IEnumerable spans) { var spanArray = spans as SourceSpan[] ?? spans.ToArray(); if (spanArray.Length == 0) { return Zero; } var minStart = spanArray.Min(s => s.Start); var maxEnd = spanArray.Max(s => s.End); return new SourceSpan(minStart, maxEnd); } public SourceSpan(SourceLocation start, SourceLocation end) { if (start > end) { throw new ArgumentException("Start location cannot be after end location"); } Start = start; End = end; } public SourceLocation Start { get; } public SourceLocation End { get; } public override string ToString() { if (Start == End) { return $"{Start}"; } if (Start.Line == End.Line) { return Start.Column == End.Column ? $"{Start}" : $"{Start.Line}:{Start.Column}-{End.Column}"; } return $"{Start}-{End}"; } public bool Equals(SourceSpan other) => Start == other.Start && End == other.End; public override bool Equals(object? obj) => obj is SourceSpan other && Equals(other); public override int GetHashCode() => HashCode.Combine(typeof(SourceSpan), Start, End); public static bool operator ==(SourceSpan left, SourceSpan right) => Equals(left, right); public static bool operator !=(SourceSpan left, SourceSpan right) => !Equals(left, right); }