1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
{- |
     Author  : Kai-Oliver Prott
     Version : August 2018

     Datatype and operations to handle SpanInfos.
-}





module Curry.SpanInfo where

import Curry.Span
import Curry.Position

data SpanInfo = SpanInfo Span [Span] -- ^ Span for the whole entity
                                     -- and a list of minor sub-spans,
                                     -- e.g. keywords.
              | NoSpanInfo
  deriving (Eq, Show, Read)

-- | A class for easy access to SpanInfos
class HasSpanInfo a where
  getSpanInfo  :: a -> SpanInfo
  setSpanInfo  :: SpanInfo -> a -> a
  updateEndPos :: a -> a
  updateEndPos = id

instance HasSpanInfo SpanInfo where
  getSpanInfo  = id
  setSpanInfo  = const

instance HasSpanInfo a => HasSpanInfo [a] where
  getSpanInfo = fromSpanInfoList . map getSpanInfo
  setSpanInfo _ = id

fromSpanInfoList :: [SpanInfo] -> SpanInfo
fromSpanInfoList []       = NoSpanInfo
fromSpanInfoList xs@(s:_) = SpanInfo sp sps
  where
    sp  = Span (getStartPosition s) (getEndPosition (last xs))
    sps = concatMap getSrcInfoPoints xs
    last []           = error "Empty list"
    last [x]          = x
    last (_:xs'@(_:_)) = last xs'

fromSrcSpan :: Span -> SpanInfo
fromSrcSpan sp = SpanInfo sp []

fromSrcSpanBoth :: Span -> SpanInfo
fromSrcSpanBoth sp = SpanInfo sp [sp]

getSrcSpan :: HasSpanInfo a => a -> Span
getSrcSpan a = case getSpanInfo a of
  NoSpanInfo   -> NoSpan
  SpanInfo s _ -> s

setSrcSpan :: HasSpanInfo a => Span -> a -> a
setSrcSpan s a = case getSpanInfo a of
  NoSpanInfo     -> setSpanInfo (SpanInfo s [])  a
  SpanInfo _ inf -> setSpanInfo (SpanInfo s inf) a

fromSrcInfoPoints :: [Span] -> SpanInfo
fromSrcInfoPoints = SpanInfo NoSpan

getSrcInfoPoints :: HasSpanInfo a => a -> [Span]
getSrcInfoPoints a = case getSpanInfo a of
  NoSpanInfo    -> []
  SpanInfo _ xs -> xs

setSrcInfoPoints :: HasSpanInfo a => [Span] -> a -> a
setSrcInfoPoints inf a = case getSpanInfo a of
  NoSpanInfo   -> setSpanInfo (SpanInfo NoSpan inf) a
  SpanInfo s _ -> setSpanInfo (SpanInfo s      inf) a

getStartPosition :: HasSpanInfo a => a -> Position
getStartPosition a =  case getSrcSpan a of
  NoSpan   -> NoPos
  Span s _ -> s

getEndPosition :: HasSpanInfo a => a -> Position
getEndPosition = getSrcSpanEnd

getSrcSpanEnd :: HasSpanInfo a => a -> Position
getSrcSpanEnd a = case getSpanInfo a of
  NoSpanInfo   -> NoPos
  SpanInfo s _ -> end s

setStartPosition :: HasSpanInfo a => Position -> a -> a
setStartPosition p a = case getSrcSpan a of
  NoSpan   -> setSrcSpan (Span p NoPos) a
  Span _ e -> setSrcSpan (Span p     e) a

setEndPosition :: HasSpanInfo a => Position -> a -> a
setEndPosition e a = case getSrcSpan a of
  NoSpan   -> setSrcSpan (Span NoPos e) a
  Span p _ -> setSrcSpan (Span p     e) a

spanInfo2Pos :: HasSpanInfo a => a -> Position
spanInfo2Pos = getStartPosition