module Camfort.Specification.Stencils.Synthesis where
import Data.List
import Data.Maybe
import qualified Data.Map as M
import Camfort.Specification.Stencils.Syntax
import Camfort.Analysis.Annotations
import qualified Language.Fortran.AST as F
import qualified Language.Fortran.Analysis as FA
import qualified Language.Fortran.Analysis.Renaming as FAR
import qualified Language.Fortran.Util.Position as FU
import Language.Fortran.Util.Position
formatSpec ::
    Maybe String
 -> FAR.NameMap
 -> (FU.SrcSpan, Either [([Variable], Specification)] (String,Variable))
 -> String
formatSpec prefix nm (span, Right (evalInfo,name)) =
     prefix'
  ++ evalInfo
  ++ (if name /= "" then " :: " ++ realName name else "") ++ "\n"
  where
    realName v = v `fromMaybe` (v `M.lookup` nm)
    prefix' = case prefix of
                Nothing -> show span ++ "    "
                Just pr -> pr
formatSpec _ _ (_, Left []) = ""
formatSpec prefix nm (span, Left specs) =
  (intercalate "\n" $ map (\s -> prefix' ++ doSpec s) specs)
    where
      prefix' = case prefix of
                   Nothing -> show span ++ "    "
                   Just pr -> pr
      commaSep                 = intercalate ", "
      doSpec (arrayVar, spec)  =
             show (fixSpec spec) ++ " :: " ++ commaSep (map realName arrayVar)
      realName v               = v `fromMaybe` (v `M.lookup` nm)
      fixSpec s                = s
a = (head $ FA.initAnalysis [unitAnnotation]) { FA.insLabel = Just 0 }
s = SrcSpan (Position 0 0 0) (Position 0 0 0)
offsetToIx :: F.Name -> Int -> F.Index (FA.Analysis A)
offsetToIx v o
  | o == absoluteRep
              = F.IxSingle a s Nothing (F.ExpValue a s (F.ValInteger "0"))
  | o == 0    = F.IxSingle a s Nothing (F.ExpValue a s (F.ValVariable v))
  | o  > 0    = F.IxSingle a s Nothing (F.ExpBinary a s F.Addition
                                 (F.ExpValue a s (F.ValVariable v))
                                 (F.ExpValue a s (F.ValInteger $ show o)))
  | otherwise = F.IxSingle a s Nothing (F.ExpBinary a s F.Subtraction
                                 (F.ExpValue a s (F.ValVariable v))
                                 (F.ExpValue a s (F.ValInteger $ show (abs o))))