--  Compiler Toolkit: some basic definitions used all over the place
--
--  Author : Manuel M. T. Chakravarty
--  Created: 16 February 95
--
--  Version $Revision: 1.44 $ from $Date: 2000/10/05 07:51:28 $
--
--  Copyright (c) [1995..2000] Manuel M. T. Chakravarty
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Library General Public
--  License as published by the Free Software Foundation; either
--  version 2 of the License, or (at your option) any later version.
--
--  This library is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
--  Library General Public License for more details.
--
--- DESCRIPTION ---------------------------------------------------------------
--
--  This module provides some definitions used throughout all modules of a
--  compiler.
--
--- DOCU ----------------------------------------------------------------------
--
--  language: Haskell 98
--
--  * May not import anything apart from `Config'.
--
--- TODO ----------------------------------------------------------------------
--

module Position (
  --
  -- source text positions
  --
  Position(Position), Pos (posOf),
  nopos, isNopos,
  dontCarePos,  isDontCarePos,
  builtinPos, isBuiltinPos,
  internalPos, isInternalPos,
  incPos, tabPos, retPos,
) where

import Binary      (Binary(..), putSharedString, getSharedString)

-- uniform representation of source file positions; the order of the arguments
-- is important as it leads to the desired ordering of source positions
-- (EXPORTED)
--
data Position = Position String         -- file name
        {-# UNPACK #-}   !Int           -- row
        {-# UNPACK #-}   !Int           -- column
  deriving (Eq, Ord)

instance Show Position where
  show (Position fname row col) = show (fname, row, col)

-- no position (for unknown position information) (EXPORTED)
--
nopos :: Position
nopos  = Position "<no file>" (-1) (-1)

isNopos :: Position -> Bool
isNopos (Position _ (-1) (-1)) = True
isNopos _                      = False

-- don't care position (to be used for invalid position information) (EXPORTED)
--
dontCarePos :: Position
dontCarePos = Position "<invalid>" (-2) (-2)

isDontCarePos  :: Position -> Bool
isDontCarePos (Position _ (-2) (-2)) = True
isDontCarePos _                      = False

-- position attached to objects that are hard-coded into the toolkit (EXPORTED)
--
builtinPos :: Position
builtinPos  = Position "<built into the compiler>" (-3) (-3)

isBuiltinPos :: Position -> Bool
isBuiltinPos (Position _ (-3) (-3)) = True
isBuiltinPos _                      = False

-- position used for internal errors (EXPORTED)
--
internalPos :: Position
internalPos = Position "<internal error>" (-4) (-4)

isInternalPos :: Position -> Bool
isInternalPos (Position _ (-4) (-4)) = True
isInternalPos _                      = False

-- instances of the class `Pos' are associated with some source text position
-- don't care position (to be used for invalid position information) (EXPORTED)
--
class Pos a where
  posOf :: a -> Position

-- advance column
--
incPos :: Position -> Int -> Position
incPos (Position fname row col) n = Position fname row (col + n)

-- advance column to next tab positions (tabs are at every 8th column)
--
tabPos :: Position -> Position
tabPos (Position fname row col) =
        Position fname row (col + 8 - (col - 1) `mod` 8)

-- advance to next line
--
retPos :: Position -> Position
retPos (Position fname row col) = Position fname (row + 1) 1


instance Binary Position where
  put_ bh (Position fname row col) = do
    putSharedString bh fname
--    put_ bh fname
    put_ bh row
    put_ bh col
  get bh = do
    fname <- getSharedString bh
--    aa <- get bh
    row <- get bh
    col <- get bh
    return (Position fname row col)