sourcecode:
|
{- |
Author : Kai-Oliver Prott
Version : October 2024
Datatype and operations to handle Spans.
-}
{-# OPTIONS_FRONTEND -Wno-incomplete-patterns #-}
module Curry.Span (
Span(..), start, end,
-- * Transformer,
isSpan, isNoSpan, fromPosition, stripStart, span2Pos, combineSpans, addSpan,
-- * Distance management
vertDist, isAfter, isBefore, isBeforeList, spanLength
) where
import Curry.Position
data Span
= Span Position Position
| NoSpan
deriving (Eq, Show, Read)
start :: Span -> Position
start (Span x _) = x
end :: Span -> Position
end (Span _ y) = y
isSpan :: Span -> Bool
isSpan (Span {}) = True
isSpan NoSpan = False
isNoSpan :: Span -> Bool
isNoSpan (Span {}) = False
isNoSpan NoSpan = True
-- | Create a Span with the given Position as start and end
fromPosition :: Position -> Span
fromPosition NoPos = NoSpan
fromPosition p@(Position _ _) = Span p p
-- | Sets the start position of a Span to its end position
stripStart :: Span -> Span
stripStart = fromPosition . end
-- | Computes a "vertical distance" between two spans.
-- It is either the row distance of the start end end positions or
-- zero, if the spans overlap.
vertDist :: Span -> Span -> Int
vertDist NoSpan NoSpan = 0
vertDist NoSpan (Span {}) = 0
vertDist (Span {}) NoSpan = 0
vertDist (Span s1 e1) (Span s2 e2) =
case rowDist e1 s2 of
x | x >= 0 -> x
| e1 <= e2 -> 0 -- they overlap
| otherwise -> - (rowDist e2 s1)
-- | Checks if the first span is completely after the second span.
isAfter :: Span -> Span -> Bool
isAfter NoSpan NoSpan = False
isAfter (Span {}) NoSpan = False
isAfter NoSpan (Span {}) = False
isAfter (Span s _) (Span _ e) = s >= e
-- | Checks if the first span is completely before the second span.
isBefore :: Span -> Span -> Bool
isBefore NoSpan NoSpan = False
isBefore (Span {}) NoSpan = False
isBefore NoSpan (Span {}) = False
isBefore (Span _ e) (Span s _) = e <= s
-- | Checks if the first span is completely
-- before the first span of a list.
-- Reurns `True` if the list is empty
isBeforeList :: Span -> [Span] -> Bool
isBeforeList _ [] = True
isBeforeList sp1 (sp2:_) = isBefore sp1 sp2
span2Pos :: Span -> Position
span2Pos (Span p _) = p
span2Pos NoSpan = NoPos
combineSpans :: Span -> Span -> Span
combineSpans sp1 sp2 = Span s e
where s = start sp1
e = end sp2
addSpan :: Span -> (a, [Span]) -> (a, [Span])
addSpan sp (a, ss) = (a, sp:ss)
spanLength :: Span -> (Int, Int)
spanLength sp = case sp of
Span (Position x1 y1) (Position x2 y2)
-> (x2-x1, y2-y1)
_ -> (0, 0)
|