diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 7f0d8dce1..cd8817ed0 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -40,6 +40,7 @@ library , Renderer.Summary , SES , Source + , SourceSpan , SplitDiff , Syntax , Term diff --git a/src/Info.hs b/src/Info.hs index 5c7b8223d..a4b5d7896 100644 --- a/src/Info.hs +++ b/src/Info.hs @@ -5,11 +5,18 @@ import Data.Record import Prologue import Category import Range +import SourceSpan import Test.QuickCheck newtype Cost = Cost { unCost :: Integer } deriving (Eq, Num, Ord, Show) +sourceSpan :: HasField fields SourceSpan => Record fields -> SourceSpan +sourceSpan = getField + +setSourceSpan :: HasField fields SourceSpan => Record fields -> SourceSpan -> Record fields +setSourceSpan = setField + characterRange :: HasField fields Range => Record fields -> Range characterRange = getField diff --git a/src/SourceSpan.hs b/src/SourceSpan.hs new file mode 100644 index 000000000..ba68d0b22 --- /dev/null +++ b/src/SourceSpan.hs @@ -0,0 +1,71 @@ +-- | +-- Source position and span information +-- +module SourceSpan where + +import Prologue +import Data.Aeson ((.=), (.:)) +import qualified Data.Aeson as A + +-- | +-- Source position information +-- +data SourcePos = SourcePos + { -- | + -- Line number + -- + line :: !Int + -- | + -- Column number + -- + , column :: !Int + } deriving (Show, Read, Eq, Ord) + +displaySourcePos :: SourcePos -> Text +displaySourcePos sp = + "line " <> show (line sp) <> ", column " <> show (column sp) + +instance A.ToJSON SourcePos where + toJSON SourcePos{..} = + A.toJSON [line, column] + +instance A.FromJSON SourcePos where + parseJSON arr = do + [line, col] <- A.parseJSON arr + pure $ SourcePos line col + +data SourceSpan = SourceSpan + { -- | + -- Source name + -- + spanName :: !Text + -- | + -- Start of the span + -- + , spanStart :: !SourcePos + -- End of the span + -- + , spanEnd :: !SourcePos + } deriving (Show, Read, Eq, Ord) + +displayStartEndPos :: SourceSpan -> Text +displayStartEndPos sp = + displaySourcePos (spanStart sp) <> " - " <> displaySourcePos (spanEnd sp) + +displaySourceSpan :: SourceSpan -> Text +displaySourceSpan sp = + spanName sp <> " " <> displayStartEndPos sp + +instance A.ToJSON SourceSpan where + toJSON SourceSpan{..} = + A.object [ "name" .= spanName + , "start" .= spanStart + , "end" .= spanEnd + ] + +instance A.FromJSON SourceSpan where + parseJSON = A.withObject "SourceSpan" $ \o -> + SourceSpan <$> + o .: "name" <*> + o .: "start" <*> + o .: "end"