packages feed

fltkhs-0.5.1.1: src/Fluid/Migrate.hs

module Fluid.Migrate where
import Numeric
import Graphics.UI.FLTK.LowLevel.Utils
import Fluid.Types
import Fluid.Lookup

import Data.List
import Data.Ord

-- Generate Haskell from an existing C++ Fluid file.
-- Tabling this for now.
addOffsets :: Path -> [a] -> [(Path,a)]
addOffsets pathSoFar =
  zip ((map ((++) pathSoFar) . (drop 1) . inits) (repeat D))

indexTree
  :: PathIndexedElements -> Path -> WidgetTree -> PathIndexedElements
indexTree accum pathSoFar wt =
  let newPath = pathSoFar ++ [I]
      addCurrent =
        (\e ->
           accum ++ [(newPath,(WidgetElement e))])
  in case wt of
       c@(Container _ _ _ innerWts) ->
         addCurrent c ++
         (concatMap (\(p,wt) -> indexTree [] p wt)
                    (addOffsets newPath innerWts))
       c@(Component _ _ _) -> addCurrent c
       _ -> accum

indexBlock
  :: PathIndexedElements -> Path -> FluidBlock -> PathIndexedElements
indexBlock accum pathSoFar fb =
  let newPath = pathSoFar ++ [I]
      addCurrent =
        (\e ->
           accum ++ [(newPath,(BlockElement e))])
  in case fb of
       c@(FluidClass (Class _ _ fbs)) ->
         addCurrent c ++ concatMap (indexBlock [] newPath) fbs
       f@(FluidFunction (Function _ _ _ wts)) ->
         addCurrent f ++ (concatMap (indexTree [] newPath) wts)
       _ -> accum

indexByPaths :: Fluid -> PathIndexedElements
indexByPaths fbs =
  concatMap (\(p,fb) -> indexBlock [] p fb)
            (addOffsets [] fbs)

replaceV :: (Eq a)
         => a -> b -> [(a,[b])] -> [(a,[b])]
replaceV k newV kvs =
  let (newKvs,found) =
        foldl (\(accum,found) (_k,_v) ->
                 if (_k == k)
                    then (accum ++ [(_k,_v ++ [newV])],True)
                    else (accum ++ [(_k,_v)],False))
              ([],False)
              kvs
  in if found
        then newKvs
        else newKvs ++ [(k,[newV])]

labelFromAttrs :: [Attribute] -> Maybe String
labelFromAttrs attrs =
  case (filter (\a ->
                  case a of
                    Label l -> True
                    _ -> False)
               attrs) of
    [] -> Nothing
    ((Label (UnbrokenString _l)):_) -> Just _l
    _ -> Nothing

elementName :: FluidElement -> HaskellIdentifier
elementName (BlockElement (FluidClass (Class n _ _))) = n
elementName (BlockElement (FluidFunction (Function n _ _ _))) = n
elementName (WidgetElement (Container _ n _ _)) = n
elementName (WidgetElement (Component _ n _)) = n
elementName _ = Unidentified

elementClass :: FluidElement -> Maybe Type
elementClass (BlockElement (FluidClass (Class _ _ _))) = Just "Class"
elementClass (BlockElement (FluidFunction (Function _ _ _ _))) = Just "Function"
elementClass (WidgetElement (Container t _ _ _)) = Just t
elementClass (WidgetElement (Component t _ _)) = Just t
elementClass _ = Nothing

elementLabel :: FluidElement -> Maybe String
elementLabel (BlockElement (FluidClass (Class n _ _))) = Nothing
elementLabel (BlockElement (FluidFunction (Function n _ _ _))) = Nothing
elementLabel (WidgetElement (Container _ _ attrs _)) = labelFromAttrs attrs
elementLabel (WidgetElement (Component _ _ attrs)) = labelFromAttrs attrs
elementLabel _ = Nothing

makeLookupTables
  :: PathIndexedElements
  -> LookupTables
makeLookupTables pathIndexed =
  let nameIndexed =
        map (\(p,e) -> (p,elementName e)) pathIndexed
      classIndexed =
        map (\(p,e) -> (p,elementClass e)) pathIndexed
      labelIndexed =
        map (\(p,e) -> (p,elementLabel e)) pathIndexed
      buildTable :: Eq a
                 => [(Path,a)] -> [(a,[Path])]
      buildTable =
        foldl (\accum (p,n) -> replaceV n p accum) []
  in (buildTable nameIndexed,buildTable classIndexed,buildTable labelIndexed)

lookupPaths
  :: Eq a
  => a -> [(a,[Path])] -> NameLookupResult
lookupPaths i indexedPaths =
  case (lookup i indexedPaths) of
    Nothing -> PathNotFound
    Just (_p:[]) -> FoundUniquePath _p
    Just ps@(_p:_ps) -> FoundMultiplePaths ps
    Just [] -> PathNotFound

uniqueNames :: Fluid -> IdentifierIndexedElements
uniqueNames fluidBlocks =
  let pathIndexed = indexByPaths fluidBlocks
      (idIndexed,classIndexed,labelIndexed) = makeLookupTables pathIndexed
      pathsInside path =
        filter (isPrefixOf path)
               (map fst pathIndexed)
      generateId =
        go pathIndexed idIndexed
  in undefined
  where go :: PathIndexedElements
           -> [(HaskellIdentifier,[Path])]
           -> PathIndexedElements
           -> IdentifierIndexedElements
           -> IdentifierIndexedElements
        go pathTable haskellIdTable [] accum = accum
        go pathTable haskellIdTable ((path,element):restOfElements) accum =
          let name = elementName element
              occurences =
                lookup name haskellIdTable
          in case occurences of
               Just (_:[]) ->
                 go pathTable
                    haskellIdTable
                    restOfElements
                    (accum ++ [([ElementName name],element)])
               Just paths ->
                 let withoutThisPath =
                       filter ((/=) path) paths
                     parentPath =
                       reverse . dropWhile ((==) D) . drop 1 . reverse
                     closestOccurencesAbove =
                       reverse (sortBy (comparing length)
                                       (filter (\p ->
                                                  let currParent = parentPath p
                                                  in (length currParent <
                                                      length (parentPath path)) &&
                                                     (currParent `isPrefixOf`
                                                      (parentPath path)))
                                               withoutThisPath))
                 in case closestOccurencesAbove of
                      [] -> undefined
                      _ -> undefined
               Nothing ->
                 go pathTable
                    haskellIdTable
                    restOfElements
                    (accum ++ [([ElementPath path],element)])