{- | Module : $Header$ Description : Spans in a source file Copyright : (c) 2016 Jan Tikovsky 2016 Finn Teegen License : BSD-3-clause Maintainer : jrt@informatik.uni-kiel.de Stability : experimental Portability : portable This module implements a data type for span information in a source file and respective functions to operate on them. A source file span consists of a filename, a start position and an end position. In addition, the type 'SrcRef' identifies the path to an expression in the abstract syntax tree by argument positions, which is used for debugging purposes. -} {-# LANGUAGE CPP #-} module Curry.Base.Span where #if __GLASGOW_HASKELL__ >= 804 import Prelude hiding ((<>)) #endif import System.FilePath import Curry.Base.Position hiding (file) import Curry.Base.Pretty data Span -- |Normal source code span = Span { file :: FilePath -- ^ 'FilePath' of the source file , start :: Position -- ^ start position , end :: Position -- ^ end position } -- |no span | NoSpan deriving (Eq, Ord, Read, Show) instance Pretty Span where pPrint = ppSpan instance HasPosition Span where setPosition p NoSpan = Span "" p NoPos setPosition p (Span f _ e) = Span f p e getPosition NoSpan = NoPos getPosition (Span _ p _) = p -- |Show a 'Span' as a 'String' showSpan :: Span -> String showSpan = show . ppSpan -- |Pretty print a 'Span' ppSpan :: Span -> Doc ppSpan s@(Span f _ _) | null f = startEnd | otherwise = text (normalise f) <> comma <+> startEnd where startEnd = ppPositions s ppSpan _ = empty -- |Pretty print the start and end position of a 'Span' ppPositions :: Span -> Doc ppPositions (Span _ s e) = text "startPos:" <+> ppLine s <> comma <+> text "endPos:" <+> ppLine e ppPositions _ = empty fstSpan :: FilePath -> Span fstSpan fn = Span fn (first fn) (first fn) -- |Compute the column of the start position of a 'Span' startCol :: Span -> Int startCol (Span _ p _) = column p startCol _ = 0 nextSpan :: Span -> Span nextSpan sp = incrSpan sp 1 incrSpan :: Span -> Int -> Span incrSpan (Span fn s e) n = Span fn (incr s n) (incr e n) incrSpan sp _ = sp -- TODO: Rename to tab and nl as soon as positions are completely replaced by spans -- |Convert a span to a (start) position -- TODO: This function should be removed as soon as positions are completely replaced by spans -- in the frontend span2Pos :: Span -> Position span2Pos (Span _ p _) = p span2Pos NoSpan = NoPos combineSpans :: Span -> Span -> Span combineSpans sp1 sp2 = Span f s e where s = start sp1 e = end sp2 f = file sp1 -- |First position after the next tabulator tabSpan :: Span -> Span tabSpan (Span fn s e) = Span fn (tab s) (tab e) tabSpan sp = sp -- |First position of the next line nlSpan :: Span -> Span nlSpan (Span fn s e) = Span fn (nl s) (nl e) nlSpan sp = sp addSpan :: Span -> (a, [Span]) -> (a, [Span]) addSpan sp (a, ss) = (a, sp:ss) -- |Distance of a span, i.e. the line and column distance between start -- and end position type Distance = (Int, Int) -- |Set the distance of a span, i.e. update its end position setDistance :: Span -> Distance -> Span setDistance (Span fn p _) d = Span fn p (p `moveBy` d) setDistance s _ = s -- |Move position by given distance moveBy :: Position -> Distance -> Position moveBy (Position fn l c) (ld, cd) = Position fn (l + ld) (c + cd) moveBy p _ = p