{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} {- | Source information is some form of description of where a Bricks expression or term /came from/. This information is used to tag 'Expression's and 'Term's so that our error messages can tell the user what parts of the Bricks source code are relevant to the problem. Overview of the types involved: - 'SourcePosition' - a line and column number - 'SourceRange' - a pair of 'SourcePosition's indicating the start and end of some expression - 'SourceName' - a description of where the top-level expression was parsed from, such as a file path or a part of a REPL session. - '()' can be used as the source information type in cases where we do not actually care to retain any source information. -} module Bricks.Source where -- Bricks internal import Bricks.Internal.Prelude import Bricks.Internal.Text (Text) import qualified Bricks.Internal.Text as Text -------------------------------------------------------------------------------- -- SourcePosition -------------------------------------------------------------------------------- {- | An endpoint of a 'SourceRange'. -} data SourcePosition = SourcePosition { sourcePosition'line :: Natural , sourcePosition'column :: Natural } deriving (Eq, Ord) instance Show SourcePosition where show = Text.unpack . show'sourcePosition show'sourcePosition :: SourcePosition -> Text show'sourcePosition (SourcePosition a b) = Text.show @Natural a <> ":" <> Text.show @Natural b -------------------------------------------------------------------------------- -- SourceRange -------------------------------------------------------------------------------- {- | Start and end points for a span of text. When we parse text into an 'Expression', we annotate it with source ranges so error messages that refer to specific expressions can tell the user where in their Bricks code those expressions are defined. -} data SourceRange = SourceRange { sourceRange'start :: SourcePosition , sourceRange'end :: SourcePosition } instance Show SourceRange where show = Text.unpack . show'sourceRange show'sourceRange :: SourceRange -> Text show'sourceRange (SourceRange a b) = show'sourcePosition a <> "-" <> show'sourcePosition b sourceRange'join :: SourceRange -> SourceRange -> SourceRange sourceRange'join (SourceRange a1 a2) (SourceRange b1 b2) = SourceRange (min a1 b1) (max a2 b2) instance Semigroup SourceRange where (<>) = sourceRange'join sourceRangeMaybe'join :: Maybe SourceRange -> Maybe SourceRange -> Maybe SourceRange sourceRangeMaybe'join (Just x) (Just y) = Just (sourceRange'join x y) sourceRangeMaybe'join _ _ = Nothing -------------------------------------------------------------------------------- -- SourceName -------------------------------------------------------------------------------- newtype SourceName a = SourceName a