text:
{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE UndecidableInstances #-}

module Control.Search.Generator
  ( (<@>)
  , mmap
  , search
  , ($==)
  , ($/=)
  , ($<)
  , ($<=)
  , ($>)
  , ($>=)
  , (@>)
  , VarId(..)

  , mapE, Eval(..), inite, seqSwitch, VarInfoM(..), MkEval, Evalable
  , SeqPos(..), Search(..), (@.), (@$), (@>>>@)
  , ref_count, ref_countx, ref_count_type, commentEval, (@++@)
  , entry, numSwitch, SearchCombiner(..)
  , buildCombiner, extractCombiners
  , memo
  , memoLoop {- ,MemoWrapper, runMemoWrapper-}
  , rReaderT
#ifndef NOMEMO
  , cacheStatement
#endif
  , cloneBase
  , mkCopy, mkUpdate, rp, inits, mseqs
  , cachedCommit, cachedAbort, cachedClone
  , nextSame, nextDiff, pushLeft, pushRight, bodyE, addE, returnE, initE, failE, tryE, startTryE, tryE_, deleteE
  ) where

import Debug.Trace

import Text.PrettyPrint hiding (space)
import Prelude hiding ((<>))
import Data.List (sort, nub, sortBy)
import Data.List (intercalate)
import Data.Unique
import Unsafe.Coerce

import Control.Search.Language
import Control.Search.GeneratorInfo
#ifndef NOMEMO
import Control.Search.Memo
import Control.Search.MemoReader
#endif

import Control.Monatron.Monatron hiding (Abort, L, state, cont)
import Control.Monatron.Zipper hiding (i,r)
import Control.Monatron.MonadInfo
import Control.Monatron.IdT

import Data.Maybe (fromJust)
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.Semigroup as DS

import Control.Search.SStateT

modify :: StateM s f => (s -> s) -> f ()
modify f = get >>= put . f

newtype GenModeT m a = GenModeT { unGenModeT :: ReaderT GenMode m a }
  deriving (MonadT, ReaderM GenMode, FMonadT)

class Monad m => GenModeM m where
  getFlags :: m PrettyFlags
  getMode :: m GenMode
  getFlags = getMode >>= return . PrettyFlags

instance MonadInfoT GenModeT where
  tminfo x = miInc "GenModeT" $ minfo (runReaderT undefined (unGenModeT x))

instance Monad m => GenModeM (GenModeT m) where
  getMode = GenModeT ask

instance (GenModeM m, FMonadT t) => GenModeM (t m) where
  getMode = lift getMode

runGenModeT :: GenMode -> GenModeT m a -> m a
runGenModeT m (GenModeT r) = runReaderT m r

type TreeState = Value

newtype VarId = VarId Int
  deriving (Ord, Eq, Show)

type VarInfo = Map VarId Info

newtype VarInfoT m a = VarInfoT { unVarInfoT :: SStateT VarInfo m a }
  deriving (MonadT,StateM VarInfo, FMonadT)

instance MonadInfoT VarInfoT where
  tminfo x = miInc "VarInfoT" $ minfo (runSStateT undefined (unVarInfoT x))

class Monad m => VarInfoM m where
  lookupVarInfo :: VarId -> m Info
  setVarInfo :: VarId -> Info -> m ()

instance Monad m => VarInfoM (VarInfoT m) where
  lookupVarInfo var = VarInfoT $ get >>= return . fromJust . Map.lookup var
  setVarInfo var val = VarInfoT $ get >>= \tbl -> (put $ Map.insert var val tbl)

instance (VarInfoM m, FMonadT t) => VarInfoM (t m) where
  lookupVarInfo = lift . lookupVarInfo
  setVarInfo var val = lift (setVarInfo var val)

#ifdef NOMEMO
class (VarInfoM m, HookStatsM m, MonadInfo m, GenModeM m, Functor m) => Evalable m
instance (VarInfoM m, HookStatsM m, MonadInfo m, GenModeM m, Functor m) => Evalable m
#else
class (VarInfoM m, HookStatsM m, MonadInfo m, MemoM m, GenModeM m, Functor m) => Evalable m
instance (VarInfoM m, HookStatsM m, MonadInfo m, MemoM m, GenModeM m, Functor m) => Evalable m
#endif

data Eval m = Eval
                 { structs    :: ([Struct],[Struct])                        -- auxiliary type declarations
                 , treeState_ :: [(String,Type, Info -> m Statement)]        -- tree state fields (name, type, init)
                 , evalState_  :: [(String,Type, Info -> m Value)]
         , nextSameH   :: Info -> m Statement
         , nextDiffH   :: Info -> m Statement
                 , pushLeftH   :: Info -> m Statement
                 , pushRightH  :: Info -> m Statement
         , bodyH      :: Info -> m Statement
                 , initH      :: Info -> m Statement
                 , addH       :: Info -> m Statement
         , returnH    :: Info -> m Statement
             , failH      :: Info -> m Statement
                 , tryH       :: Info -> m Statement
                 , tryLH      :: Info -> m Statement
                 , startTryH  :: Info -> m Statement
                 , intArraysE :: [String]
                 , boolArraysE :: [String]
                 , intVarsE   :: [String]
          , -- Free heap allocated memory for search heuristic associated to this node
           -- because it is being abandoned.
           --
           -- BE CAREFUL: deallocate memory only once in case of multiple references.
           --
           -- Example use case: untilLoop
           deleteH    :: Info -> m Statement
                 , toString   :: String
                 , canBranch  :: m Bool
                 , complete   :: Info -> m Value
                 }

commentStatement :: (HookStatsM m) => String -> Eval m -> (Info -> m Statement) -> (Info -> m Statement)
#ifdef OUTPUTCOMMENTS
commentStatement c e f = \x -> (f x >>= \s -> return (DebugOutput ("begin: " ++ c ++ " @ " ++ toString e) >>> s >>> DebugOutput ("end:   " ++ c ++ " @ " ++ toString e)))
#else
commentStatement c e f = \x -> (f x >>= \s -> return (comment ("begin: " ++ c ++ " @ " ++ toString e) >>> s >>> comment ("end:   " ++ c ++ " @ " ++ toString e)))
#endif

commentEval :: Evalable m => Eval m -> Eval m
#ifdef COMMENTS
commentEval e =
          e    { treeState_ = map (\(a,b,c) -> (a,b,commentStatement "treeState" e c)) (treeState_ e)
               , nextSameH = commentStatement "nextSame" e (nextSame e)
               , nextDiffH = commentStatement "nextDiff" e (nextDiff e)
               , pushLeftH = commentStatement "pushLeft" e (pushLeft e)
               , pushRightH = commentStatement "pushRight" e (pushRight e)
               , bodyH = commentStatement "bodyE" e (bodyE e)
               , initH = commentStatement "initE" e (initE e)
               , addH = commentStatement "addE" e (addE e)
               , returnH = commentStatement "returnE" e (returnE e)
               , failH = commentStatement "failE" e (failE e)
               , tryH = commentStatement "tryE" e (tryE e)
               , tryLH = commentStatement "tryE_" e (tryE_ e)
               , deleteH = commentStatement "deleteE" e (deleteE e)
               , startTryH = commentStatement "startTryE" e (startTryE e)
               }
#else
commentEval = id
#endif

entry :: Monad m => (String,Type,Value -> Statement) -> (String,Type,Info -> m Statement)
entry (name,ty,up) = (name, ty, \i -> return (up $ (@->name) $ tstate i))

rootEntry :: Monad m => [(String,Type,Info -> m Statement)]
rootEntry = [ entry ("space",Pointer SpaceType,assign RootSpace)
            ]

inits :: Evalable m => Eval m -> Info -> m Statement
inits e i = initTreeState_ i e @>>>@ initH e i

inite :: Monad m => [(String,Info -> m Value)] -> Info -> m Statement
inite fs i = mseqs [init i >>= \ini -> return (estate i @=> f <== ini) | (f,init) <- fs]

mkCopy   i f   = (tstate i @-> f) <==   (tstate (old i) @-> f)
mkUpdate i f g = (tstate i @-> f) <== g (tstate (old i) @-> f)

mseqs lst = sequence lst >>= \s -> return (seqs s)

mapE :: (HookStatsM m, HookStatsM n) => (forall x. m x -> n x) -> Eval m -> Eval n
mapE x = mapE_ (const x)

data HookStat = HookStat { nCalls :: Integer }

newtype HookStatsT m a = HookStatsT { unHookStatsT :: StateT HookStat m a }
  deriving (Monad, StateM HookStat, FMonadT, MonadT)

runHookStatsT :: Monad m => HookStatsT m a -> m (a, Integer)
runHookStatsT m = do
  (a, s) <- runStateT (HookStat { nCalls = 0 }) $ unHookStatsT m
  return (a, nCalls s)

instance MonadInfoT HookStatsT where
  tminfo = miInc "HookStatsT" . minfo . runHookStatsT

class Monad m => HookStatsM m where
  hookCalled :: m ()

instance Monad m => HookStatsM (HookStatsT m) where
  hookCalled = modify (\st -> st { nCalls = 1 + nCalls st })

instance (MonadT t, HookStatsM m) => HookStatsM (t m) where
  hookCalled = lift hookCalled

callHook :: HookStatsM m => String -> Eval m -> Info -> m ()
callHook s e i = hookCalled

nextSame, nextDiff, pushLeft, pushRight, bodyE, addE, returnE, initE, failE, tryE, startTryE, tryE_, deleteE :: HookStatsM m => Eval m -> Info -> m Statement
nextSame e i = callHook "nextSame" e i >> nextSameH e i
nextDiff e i = callHook "nextDiff" e i >> nextDiffH e i
pushLeft e i = callHook "pushLeft" e i  >> pushLeftH e i
pushRight e i = callHook "pushRight" e i  >> pushRightH e i
bodyE e i = callHook "body" e i  >> bodyH e i
addE e i = callHook "add" e i  >> addH e i
returnE e i = callHook "return" e i  >> returnH e i
initE e i = callHook "init" e i >> initH e i
failE e i = callHook "fail" e i >> failH e i
tryE e i = callHook "try" e i >> tryH e i
startTryE e i = callHook "startTry" e i  >> startTryH e i
tryE_ e i = callHook "tryL" e i  >> tryLH e i
deleteE e i = callHook "deleteH" e i  >> deleteH e i

mapE_ :: (HookStatsM m, HookStatsM n) => (forall x. Maybe Info -> m x -> n x) -> Eval m -> Eval n
mapE_ f e =
  Eval { structs    = structs e
       , treeState_  = map (\(s,t,m) -> (s,t,\i -> f (Just i) (m i))) (treeState_ e)
       , evalState_ = map (\(s,t,m) -> (s,t,\i -> f (Just i) (m i))) (evalState_ e)
       , nextSameH  = \i -> f (Just i) (nextSame e i)
       , nextDiffH  = \i -> f (Just i) (nextDiff e i)
       , pushLeftH  = \i -> f (Just i) (pushLeft e i)
       , pushRightH = \i -> f (Just i) (pushRight e i)
       , bodyH      = \i -> f (Just i) (bodyE e i)
       , addH       = \i -> f (Just i) (addE e i)
       , returnH    = \i -> f (Just i) (returnE e i)
       , initH      = \i -> f (Just i) (initE e i)
       , failH      = \i -> f (Just i) (failE e i)
       , tryH       = \i -> f (Just i) (tryE e i)
       , startTryH  = \i -> f (Just i) (startTryE e i)
       , tryLH      = \i -> f (Just i) (tryE_ e i)
       , boolArraysE = boolArraysE e
       , intArraysE = intArraysE e
       , intVarsE   = intVarsE e
       , deleteH    = \i -> f (Just i) (deleteE e i)
       , toString   = toString e
       , canBranch  = f Nothing $ canBranch e
       , complete   = \i -> f (Just i) (complete e i)
       }

--------------------------------------------------------------------------------
-- SEARCH TRANSFORMERS
--------------------------------------------------------------------------------

#ifndef NOMEMO
buildMemoKey :: MemoM m => String -> Maybe (Eval m) -> Maybe Statement -> Info -> m MemoKey
buildMemoKey fn (Just e) _ i = do
  t <- getMemo
  return $ MemoKey { memoFn = fn, memoInfo = Just i , memoStack = Just (toString e), memoExtra = Just (memoRead t), memoStatement = Nothing, memoParams = map fst (stackField i) }
buildMemoKey fn Nothing (Just s) i = do
  return $ MemoKey { memoFn = fn, memoInfo = Nothing, memoStack = Nothing          , memoExtra = Nothing          , memoStatement = Just s , memoParams = map fst (stackField i)  }

lookupMemo :: Evalable m => String -> Maybe (Eval m) -> Maybe Statement -> Info -> m (Maybe MemoValue)
lookupMemo fn e s i =
  do t <- getMemo
     key <- buildMemoKey fn e s i
     let r = Map.lookup key $ memoMap t
     case r of
       Nothing -> return ()
       Just k -> setMemo $ t { memoMap = Map.adjust (\x -> x { memoUsed = memoUsed x + 1 }) key (memoMap t) }
     return r

insertMemo :: Evalable m => String -> Maybe (Eval m) -> Statement -> (Int -> ([(String,Type,Value)], m Statement)) -> Info -> m MemoValue
insertMemo fn e s sm i =
  do t <- getMemo
     fl <- getFlags
     let n = memoCount t
     let (lst,ss) = sm n
     let ni = i { stackField = stackField i ++ (map (\(n,t,v) -> (rpx 0 fl t, n)) lst) }
     key <- buildMemoKey fn e (Just s) ni
     s2 <- ss
     let val = MemoValue { memoId = n
                         , memoCode = s2
                         , memoUsed = 1
                         , memoFields = stackField ni
                         }
     setMemo $ t { memoMap = Map.insert key val $ memoMap t
                 , memoCount = n+1
                 }
     return val

invokeMemo :: Evalable m => String -> Eval m -> (Eval m -> (Info -> m Statement)) -> (Info -> m Statement)
invokeMemo fn e x i =
  do let def = x e
     r <- lookupMemo fn (Just e) Nothing i
     val <- case r of
              Nothing -> do val <- def i
                            case val of
                              Skip -> return Nothing
                              _ -> do num <- insertMemo fn (Just e) val (const ([],return val)) i
                                      return $ Just num
              Just val -> return $ Just val
     case val of
       Nothing -> return Skip
       Just x -> cacheCall (fn ++ show (memoId x)) (stackField i) []

-- cacheCall :: String -> Info -> Statement
cacheCall :: Evalable m => String -> [(String,String)] -> [Value] -> m Statement
cacheCall fn i lst = do
  fl@(PrettyFlags pf) <- getFlags
  return $ SHook (fn ++ "(" ++ intercalate "," (map snd (fixArgs pf) ++ (map snd i) ++ (map (rpx 0 fl) lst)) ++ ");")

cacheStatement_ :: Evalable m => String -> (Int -> ([(String,Type,Value)], m Statement)) -> Info -> m Statement
cacheStatement_ fn sm i =
  do let (olst,ss) = sm 0
     fl <- getFlags
     let ni = i { stackField = stackField i ++ (map (\(n,t,v) -> (rpx 0 fl t, n)) olst) }
     s <- ss
     x <- lookupMemo fn Nothing (Just s) ni
     val <- case x of
              Nothing -> do case s of
                              Skip -> return Nothing
                              _ -> do num <- insertMemo fn Nothing s sm i
                                      return $ Just num
              Just r -> return $ Just r
     case val of
       Nothing -> return Skip
       Just x -> do let (lst,_) = sm (memoId x)
                    cacheCall (fn ++ show (memoId x)) (stackField i) (map (\(n,t,v) -> v) lst)

cacheStatement :: Evalable m => String -> Statement -> Info -> m Statement
cacheStatement fn s i = cacheStatement_ fn (const ([],return s)) i

{-
newtype MemoWrapper m a = MemoWrapper { runMemoWrapper :: m a }

instance MonadT MemoWrapper where
  lift = MemoWrapper
  treturn = MemoWrapper . return
  tbind (MemoWrapper a) f = MemoWrapper (a >>= (\x -> runMemoWrapper (f x)))

instance FMonadT MemoWrapper where
  tmap' d1 _d2 g f       = MemoWrapper . f . fmapD d1 g . runMemoWrapper
-}

class Memoable m where
  memox :: String -> Info -> (Int -> ([(String,Type,Value)],m)) -> m

instance Memoable m => Memoable ((Type,Value) -> m) where
  memox name info f = \(typ,val) ->
    case typ of
      THook "void" -> memox name info (\n -> let (lst,m) = f n in (lst,m (typ,Var "WTF??")))
      _ ->            memox name info (\n -> let (lst,m) = f n in (((nam n lst,typ,val):lst),m (typ,Var $ nam n lst)))
   where nam n lst = "arg_" ++ name ++ "_" ++ show n ++ "_" ++ show (length lst)

{-
instance Memoable m => Memoable (Value -> m) where
  memox name info f = \val -> memox name info (\n -> let (lst,m) = f n in (((nam n lst,Pointer (THook "void"),val):lst),m (Var $ nam n lst)))
    where nam n lst = "arg_" ++ name ++ "_" ++ show n ++ "_" ++ show (length lst)
-}

instance Evalable m => Memoable (m Statement) where
  memox name info f = cacheStatement_ ("cached_" ++ name) f info

memo :: Memoable m => String -> Info -> m -> m
memo name info m = memox name info (const ([],m))
-- memo name info m = m

memoLoop super =
  super { startTryH = invokeMemo "startTry" super startTryE
        , bodyH = invokeMemo "body" super bodyE
        , failH = invokeMemo "fail" super failE
        , tryH = invokeMemo "try" super tryE
        , addH = invokeMemo "add" super addE
        , returnH = invokeMemo "ret" super returnE
        , tryLH = invokeMemo "try_" super tryE_
        , initH = invokeMemo "init" super initE
        , pushLeftH = invokeMemo "pushL" super pushLeft
        , pushRightH = invokeMemo "pushR" super pushRight
        , deleteH = invokeMemo "delete" super deleteE
        , nextSameH = invokeMemo "nextSame" super nextSame
        , nextDiffH = invokeMemo "nextDiff" super nextDiff
        }

cachedCommit :: Evalable m => Info -> m Statement
cachedCommit i = return (comment "begin commit") @>>>@ cacheStatement "commit" (commit i) i @>>>@ return (comment "end commit")

cachedAbort :: Evalable m => Info -> m Statement
cachedAbort i = return (comment "begin abort") @>>>@ cacheStatement "abort" (abort i) i @>>>@ return (comment "end abort")

-- cachedClone :: MemoM m => Info -> Info -> m Statement
cachedClone i j = return (comment "begin clone") @>>>@ cacheStatement "clone" (cloneIt i j) i @>>>@ return (comment "end clone")
-- cachedClone i j = return $ clone i j

rReaderT x m = runMemoReaderT x m
#else

cachedCommit x = return $ (comment "begin commit" >>> commit x >>> comment "end commit")
cachedAbort x = return $ (comment "begin abort" >>> abort x >>> comment "end abort")
cachedClone i j = return $ (comment "begin clone" >>> cloneIt i j >>> comment "end clone")
memo :: String -> Info -> m -> m
memo name info m = m
memoLoop = id
rReaderT = runReaderT
#endif
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
data SeqPos = OutS | FirstS | SecondS
  deriving (Show)

seqSwitch :: ReaderM SeqPos m => m a -> m a -> m a
seqSwitch l r =
                do flag <- ask
                   case flag  of
                     FirstS  -> l
                     SecondS -> r

numSwitch n =
              do flag <- ask
                 n flag

(l1,l2) @++@ (l3,l4) = (l1 ++ l3, l2 ++ l4)

ref_count = \i -> estate i @=> "ref_count"
ref_countx = \i s -> estate i @=> ("ref_count_" ++ s)
ref_count_type = THook "int"
--------------------------------------------------------------------------------

-- cloneBase i = resetClone $ info { baseTstate = estate i @=> "parent" }
cloneBase i = i { baseTstate = estate i @=> "parent" }

(@>>>@) :: Evalable m => m Statement -> m Statement -> m Statement
(@>>>@) x y = do s1 <- x
                 s2 <- y
                 return (s1 >>> s2)

f  @$ x = x >>= return . f
mf @. x = mf >>= \f -> f @$ x

--------------------------------------------------------------------------------
-- PRINTING
--------------------------------------------------------------------------------

-- printTreeStateType :: Monad m => Eval m -> String
printTreeStateType e =
  {- render $ pretty $-} Struct "TreeState" [ (ty,name) | (name,ty,_) <- treeState_ e ]

-- printEvalStateType :: Monad m => Eval m -> String
printEvalStateType e =
  {-render $ pretty $-} Struct "EvalState" [ (ty,name) | (name,ty,_) <- evalState_ e ]

-- initEvalState :: Monad m => Info -> Eval m -> Doc
initEvalState i e = mconcat $
--  {-vcat-} [SHook ((rp 0 ty) ++ " " ++ name ++ ";") | (name,ty,_) <- evalState_ e]
  [SHook "struct EvalState evalState;"]

initTreeState_ :: Monad m => Info -> Eval m -> m Statement
initTreeState_ i e = mseqs [ init i | (_,_,init) <- treeState_ e]

-- initIntArrays :: Eval m -> Doc
initIntArrays eval =
  mconcat [ doc arr | arr <- nub $ sort $ intArraysE eval]
  where doc arr
         | [(_,"")] <- reads arr :: [(Int,String)]
         = SHook ("vm->getSearchintVarArray(\"" ++ arr ++ "\", VAR_" ++ arr ++ ");")
         | otherwise
         = SHook ("vm->getintVarArray(\"" ++ arr ++ "\", VAR_" ++ arr ++ ");")

-- initBoolArrays :: Eval m -> Doc
initBoolArrays eval =
  mconcat [ doc arr | arr <- nub $ sort $ boolArraysE eval]
  where doc arr
         | [(_,"")] <- reads arr :: [(Int,String)]
         = SHook ("vm->getSearchboolVarArray(\"" ++ arr ++ "\", VAR_" ++ arr ++ ");")
         | otherwise
         = SHook ("vm->getboolVarArray(\"" ++ arr ++ "\", VAR_" ++ arr ++ ");")

-- declIntArrays :: Eval m -> Doc
declIntArrays eval =
  mconcat [ doc arr | arr <- nub $ sort $ intArraysE eval]
  where doc arr
         | [(_,"")] <- reads arr :: [(Int,String)]
         = SHook ("vector<int> VAR_" ++ arr ++ ";")
         | otherwise
         = SHook ("vector<int> VAR_" ++ arr ++ ";")

declBoolArrays eval =
  mconcat [ doc arr | arr <- nub $ sort $ boolArraysE eval]
  where doc arr
         | [(_,"")] <- reads arr :: [(Int,String)]
         = SHook ("vector<int> VAR_" ++ arr ++ ";")
         | otherwise
         = SHook ("vector<int> VAR_" ++ arr ++ ";")

-- initIntVars :: Eval m -> Doc
initIntVars eval =
  mconcat [ doc var | var <- nub $ sort $ intVarsE eval]
  where doc var = SHook ("vm->getintVarIndex(\"" ++ var ++ "\", VAR_" ++ var ++ ");")

-- declIntVars :: Eval m -> Doc
declIntVars eval =
  mconcat [ doc var | var <- nub $ sort $ intVarsE eval]
  where doc var = SHook ("int VAR_" ++ var ++ ";")

corefn :: (Evalable m, WriterM ProgramString m) => Eval m -> m Statement
corefn eval =
  do fl <- getFlags
     sInitE <- inite (map (\(a,_,b) -> (a,b)) (evalState_ eval)) info
     sInitS <- inits eval info
     sTry   <- startTryE eval info
     sNext  <- nextSame eval info
     sBody  <- bodyE eval info
     return $ seqs [ -- SHook $ "\n  status = " ++ rpx 0 fl RootSpace ++ "->status();"
                     SHook "\n"
                   , SHook "  st->queue = new std::vector<TreeState>();"
                   , sInitE
                   , sInitS
                   , sTry
                   , Block (SHook "  while (!st->queue->empty())") $ seqs
                     [ SHook "    /* pop first element */"
                     , SHook "    TreeState popped_estate = st->queue->back();"
                     , SHook "    st->queue->pop_back();"
                     , sNext
                     , SHook "    st->estate = popped_estate;"
                     , sBody
                     ]
                   ]

mainfn :: (Evalable m, WriterM ProgramString m) => Eval m -> m Statement
mainfn eval =
  do core <- corefn eval
     return $ seqs [ SHook ("\n\nvoid eval(" ++ spacetype ModeFZ ++ "* root, VarMap* vm, Printer* p) {")
                   , SHook "RootState rootState;"
                   , SHook "RootState *st = &rootState;"
                   , initIntVars eval
                   , initBoolArrays eval
                   , initIntArrays eval
                   , core
                   , SHook "}"
                   ]

cppfn :: (Evalable m, WriterM ProgramString m) => Eval m -> m Statement
cppfn eval =
  do core <- corefn eval
     return $ seqs [ SHook ("\n\nvoid eval(" ++ spacetype ModeGecode ++ "* root, Printer *p) {")
                   , SHook "RootState rootState;"
                   , SHook "RootState *st = &rootState;"
                   , SHook ("    mgr.root(*root);")
                   , core
                   , SHook "}"
                   ]

mcpfn :: (Evalable m, WriterM ProgramString m) => Eval m -> m Statement
mcpfn eval =
  do core <- corefn eval
     return $ seqs [ SHook ("\n\nvoid eval(" ++ spacetype ModeMCP ++ "* root) {")
                   , SHook "RootState rootState;"
                   , SHook "RootState *st = &rootState;"
                   , core
                   , SHook "}"
                   ]

typedecls :: Evalable m => Eval m -> m Statement
typedecls eval =
  do fl <- getFlags
     return $ seqs [ SHook ("struct EvalState;")
                   , SHook (render $ vcat $ [text "struct" <+> text name <> semi | Struct name _ <- fst $ structs eval])
                   , SHook (render $ vcat $ map (prettyX fl) $ snd $ structs eval)
                   , SHook (rpx 1 fl $ printTreeStateType eval)
                   , SHook (rpx 1 fl $ printEvalStateType eval)
                   , SHook (render $ vcat $ map (prettyX fl) $ fst $ structs eval)
                   ]

declRootState :: Eval m -> Statement
declRootState eval = seqs [ SHook "typedef struct {"
                          , SHook "  TreeState estate;"
                          , SHook "  std::vector<TreeState> *queue;"
                          , initEvalState info eval
                          , SHook "} RootState;"
                          ]

generate :: (Evalable m, WriterM ProgramString m) => Eval m -> m ()
generate eval_ =
  do fl <- getFlags
     types <- typedecls eval
     let header = seqs [ types
                       , declIntVars eval
                       , declBoolArrays eval
                       , declIntArrays eval
                       , declRootState eval
                       ]
     main <- mainfn eval
     tell $ mempty { main = Just main, header = header }
 where eval = commentEval $ eval_ { treeState_ = rootEntry ++ treeState_ eval_ }

generatemcp :: (Evalable m, WriterM ProgramString m) => Eval m -> m ()
generatemcp eval_ =
  do fl <- getFlags
     types <- typedecls eval
     let header = seqs [ types
                       , declRootState eval
                       ]
     main <- mcpfn eval
     tell $ mempty { main = Just main, header = header }
 where eval = commentEval $ eval_ { treeState_ = rootEntry ++ treeState_ eval_ }

generatecpp :: (Evalable m, WriterM ProgramString m) => Eval m -> m ()
generatecpp eval_ =
  do fl <- getFlags
     types <- typedecls eval
     let header = seqs [ SHook "#include \"statemgr/varaccessor.hh\""
                       , types
                       , declRootState eval
                       , SHook "StateMgr mgr;"
                       ]
     main <- cppfn eval
     tell $ mempty { main = Just main, header = header }
 where eval = commentEval $ eval_ { treeState_ = rootEntry ++ treeState_ eval_ }

rp n = render . nest n . pretty
rpx n s = render . nest n . prettyX s

--------------------------------------------------------------------------------
-- COMPOSITION COMBINATORS
--------------------------------------------------------------------------------

-- def vars = label vars lbV minV minD ($==)

type MkEval m = Evalable m => Eval m -> State Int (Eval m)

fixall :: Evalable m => MkEval m -> Eval m
fixall f = let this = fst $ runState 0 $ f this
           in this

data Search = forall t2. (FMonadT t2, MonadInfoT t2) =>
  Search { mkeval     :: forall m t1. (HookStatsM m, MonadInfoT t1, FMonadT t1, Evalable m) => MkEval ((t1 :> t2) m)
         , runsearch  :: forall m x. (Evalable m) => t2 m x -> m x
         }

#ifndef NOMEMO
memoize :: Search
memoize =
  Search { mkeval     = return . memoLoop
         , runsearch  = runIdT
         }
#endif

{-# RULES
      "L"                          L = unsafeCoerce
  #-}
{-  # RULES
        "runL"                       runL = unsafeCoerce
  #-}
{-# RULES
        "unsafeCoerce/unsafeCoerce"  unsafeCoerce . unsafeCoerce = unsafeCoerce
  #-}
{-# RULES
        "mmap/unsafeCoerce"          mmap unsafeCoerce = unsafeCoerce
  #-}
{-# RULES
        "mapE/unsafeCoerce"          mapE unsafeCoerce = unsafeCoerce
  #-}

(<@>)
  :: Search -> Search -> Search
s1 <@> s2 =
  case s1 of
    Search { mkeval = evals1, runsearch = runs1 } ->
      case s2 of
        Search { mkeval = evals2, runsearch = runs2 } ->
         Search {mkeval =
              \super -> do { s2' <- evals2 $ mapE (L . L . mmap runL . runL)  super
                           ; s1' <- evals1 (mapE runL s2')
                           ; return $ mapE (L . mmap L . runL) s1'
                           }
             , runsearch  = runs2 . runs1 . runL
             }

data SearchCombiner = forall t1 t2. (FMonadT t1, FMonadT t2, MonadInfoT t1, MonadInfoT t2) =>
  SearchCombiner { runner :: forall m x. Evalable m => ((t1 :> t2) m) x -> m x
                 , elems :: [SearchCombinerElem t1 t2]
                 }

data SearchCombinerElem t1 t2 =
  SearchCombinerElem { mapper :: forall t' m. (FMonadT t', MonadInfoT t', Evalable m) => Eval (t' ((t1 :> t2) m)) -> State Int (Eval (t' ((t1 :> t2) m)))
                     }

extractCombiners :: (Evalable m, FMonadT t', MonadInfoT t', FMonadT t1, MonadInfoT t1, FMonadT t2, MonadInfoT t2) => [SearchCombinerElem t1 t2] -> Eval (t' ((t1 :> t2) m)) -> State Int [(Eval (t' ((t1 :> t2) m)))]
extractCombiners [] _ = return []
extractCombiners (SearchCombinerElem { mapper=m }:b) super =
  do prev <- extractCombiners b super
     next <- m super
     return $ (next) : prev

buildCombiner [s] =
  case s of
    Search { mkeval = evals, runsearch = runs } ->
      SearchCombiner { runner = runIdT . runs . runL
                     , elems = [SearchCombinerElem { mapper = liftM (mapE (mmap L . runL)) . evals . mapE (L . mmap runL)
                                                   }]
                     }
buildCombiner (s:ss) =
  case s of
    Search { mkeval = evals, runsearch = runs } ->
      case buildCombiner ss of
        SearchCombiner { runner = runner, elems = elems } ->
          SearchCombiner { runner = runner . runs . runL
                         , elems = SearchCombinerElem { mapper = liftM (mapE (mmap L . runL)) . evals . mapE (L . mmap runL)
                                                      } : liftSearchCombinerElems elems
                         }

liftSearchCombinerElems :: (FMonadT t1, FMonadT t0, FMonadT t2, MonadInfoT t1, MonadInfoT t0, MonadInfoT t2) => [SearchCombinerElem t1 t2] -> [SearchCombinerElem t0 (t1 :> t2)]
liftSearchCombinerElems [] = []
liftSearchCombinerElems (s:ss) =
  case s of
    SearchCombinerElem { mapper = m } ->
      SearchCombinerElem { mapper = liftM (mapE (mmap L . runL)) . m . mapE (L . mmap runL)
                         } : liftSearchCombinerElems ss

mmap :: (FMonadT t, MonadInfoT t, Monad m, Monad n, MonadInfo m) => (forall x. m x -> n x) -> t m a -> t n a
mmap f x = tmap' mfunctor mfunctor id f x

mfunctor :: Monad m => FunctorD m
mfunctor = FunctorD { fmapD = \f m -> m >>= return . f }

evalSStateT m s = runSStateT m s >>= \t -> case t of { Tup2 a _ -> return a }

data FunctionDef = FunctionDef { funName :: String, funArgs :: [(Type,String)], funBody :: Statement }

genfun :: PrettyFlags -> FunctionDef -> String
genfun fl f = rpx 0 fl $
    Block
      (SHook ("void " ++ funName f ++ "(" ++ intercalate "," [ rpx 0 fl t ++ " " ++ an | (t,an) <- funArgs f ] ++ ")"))
      (funBody f)

data ProgramString = ProgramString { header :: Statement
                                   , functions :: [FunctionDef]
                                   , main :: Maybe Statement
                                   , pcomment :: [String]
                                   }

transformProgram fn p = p { header = inliner fn (header p), functions = map (\f -> f { funBody = inliner fn (funBody f) }) (functions p), main = maybe Nothing (Just . inliner fn) (main p) }

instance Monoid ProgramString where
  mempty = ProgramString { header = Skip, functions = [], main = Nothing, pcomment = [] }
  mappend p1 p2 = ProgramString { header = header p1 >>> header p2, functions = functions p1 ++ functions p2, main = maybe (main p2) Just (main p1), pcomment = pcomment p1 ++ pcomment p2 }

instance DS.Semigroup ProgramString where
  (<>) = mappend

genprog :: PrettyFlags -> ProgramString -> String
genprog fl p = concatMap (\x -> "// " ++ x ++ "\n\n") (pcomment p) ++ rpx 0 fl (header p) ++ concatMap (\x -> "\n" ++ genfun fl x ++ "\n") (functions p) ++ maybe "" (rpx 0 fl) (main p)

monadInfo :: MInfo -> (Int,Int,Int)
monadInfo (MInfo x) =
  let total = sum $ map snd $ Map.toList x
      identities = Map.findWithDefault 0 "Id" x + Map.findWithDefault 0 "IdT" x
      zippers = Map.findWithDefault 0 ":>" x
  in  (total - (identities+zippers),zippers,identities)

getgen :: (Evalable m, WriterM ProgramString m) => Eval m -> m ()
getgen x = do
  fl <- getFlags
  case genMode fl of
    ModeFZ -> generate x
    ModeMCP -> generatemcp x
    ModeGecode -> generatecpp x
    ModeUnk -> error "Unknown generator?"

search' :: GenMode -> Search -> ProgramString
#ifdef NOMEMO
search' fl s  =
  case s of
    Search { mkeval = evals, runsearch = runs } -> do
       let fevals = fixall $ evals
           in case runId $ runGenModeT fl $ runHookStatsT $ evalSStateT Map.empty $ unVarInfoT $ runs $ runWriterT $ getgen $ mapE runL $ fevals
                   of (((_,eval)),n) -> let cmt = show $ monadInfo $ minfo $ canBranch $ fevals
                                            in eval { pcomment = ["Combinator stats: " ++ cmt, "Hook calls: " ++ show n]}
#else
refType t n =
  case t of
    x | last x == '*' -> n
    "int" -> n
    "bool" -> n
    _ -> '&' : n

search' fl s  =
  case memoize <@> s of
    Search { mkeval = evals, runsearch = runs } -> do
       let fevals = fixall $ evals
           in case runId $ runGenModeT fl $ runHookStatsT $ runMemoT $ evalSStateT Map.empty $ unVarInfoT $ runs $ runWriterT $ getgen $ mapE runL $ fevals
                   of (((_,eval),t),n) -> let {- m = inlineMap t  -}
                                              p = {- transformProgram m -} (mempty { functions = map toFun (filter (not . needInline) t) } `mappend` eval)
                                              cmt = show $ monadInfo $ minfo $ canBranch $ fevals
                                          in p { pcomment = ["Combinator stats: " ++ cmt, "Hook calls: " ++ show n]}
  where toFun (key,val) = FunctionDef { funName = memoFn key ++ show (memoId val), funArgs = mm (map (\x -> (THook (fst x), refType (fst x) $ snd x)) (memoFields val)), funBody = simplify (memoCode val) }
        mm = ((fixArgs fl) ++)

fixArgs ModeMCP = [ -- (Pointer (THook "Gecode::SpaceStatus"), "status")
                    (Pointer (THook "RootState"), "st")
                  ]
fixArgs _       = [ -- (Pointer (THook "Gecode::SpaceStatus"), "status")
                    (Pointer (THook "RootState"), "st"),
                    (Pointer (THook "Printer"),"p")
                  ]

needInline (key,val) = False {- (memoUsed val <= 1) -}
{-needInline (key,val) =
  let code = simplify $ memoCode val
      res = (memoUsed val <= 1) || (case code of { Seq _ _ -> False; Block _ _ -> False; Skip -> True; _ -> True })
      in trace ("needInline? " ++ show code ++ " -> " ++ show res ++ "\n") res
-}
-- needInline _ = False

inlineMap fl fns = do
  lst <- mapM (\(key,val) -> cacheCall (memoFn key ++ show (memoId val)) (memoFields val) [] >>= \c -> return (c, memoCode val)) [ x | x <- fns, needInline x ]
  return $ Map.fromList lst

#endif

search :: Search -> String
search s = genprog (PrettyFlags ModeMCP) (search' ModeMCP s)


text:
(function (document) {
  /**
   * Monkberry.
   * @class
   */
  function Monkberry() {
    this.pool = new Pool();
    this.templates = {};
    this.filters = {};
    this.wrappers = {};
  }

  Monkberry.prototype.foreach = function (parent, node, map, template, data, array, options) {
    var i, j, len, keys, transform, arrayLength, childrenSize = map.length;

    if (Array.isArray(array)) {
      transform = transformArray;
      arrayLength = array.length;
    } else {
      transform = transformObject;
      keys = Object.keys(array);
      arrayLength = keys.length;
    }

    len = childrenSize - arrayLength;
    for (i in map.items) {
      if (len-- > 0) {
        map.items[i].remove();
      } else {
        break;
      }
    }

    j = 0;
    for (i in map.items) {
      map.items[i].update(transform(data, array, keys, j, options));
      j++;
    }

    for (j = childrenSize, len = arrayLength; j < len; j++) {
      // Render new view.
      var view = this._render(template);

      // Set view hierarchy.
      view.parent = parent;
      parent.nested.push(view);

      // Add nodes DOM.
      if (node.nodeType == 8) {
        view.insertBefore(node);
      } else {
        view.appendTo(node);
      }

      // Set view data (note what it must be after adding nodes to DOM).
      view.update(transform(data, array, keys, j, options));

      // Remember to remove from children map on view remove.
      i = map.push(view);
      view.onRemove = (function (i) {
        return function () {
          map.remove(i);
        };
      })(i);
    }
  };

  Monkberry.prototype.insert = function (parent, node, child/*.ref*/, template, data, test) {
    if (child.ref) {
      if (test) {
        child.ref.update(data);
      } else {
        child.ref.remove();
      }
    } else if (test) {
      // Render new view.
      var view = this._render(template);

      // Set view hierarchy.
      view.parent = parent;
      parent.nested.push(view);

      // Add nodes DOM.
      if (node.nodeType == 8) {
        view.insertBefore(node);
      } else {
        view.appendTo(node);
      }

      // Set view data (note what it must be after adding nodes to DOM).
      view.update(data);

      // Remember to remove child ref on remove of view.
      child.ref = view;
      view.onRemove = function () {
        child.ref = null;
      };
    }

    return test;
  };

  /**
   * Render template to view.
   * @param {string} name - Template name.
   * @param {Object} values - Data to update view.
   * @param {boolean} noCache - Do not take views from pool.
   * @return {Monkberry.View}
   */
  Monkberry.prototype.render = function (name, values, noCache) {
    return this._render(name, values, noCache);
  };

  /**
   * This method is used only for private rendering of views.
   * @private
   */
  Monkberry.prototype._render = function (name, values, noCache) {
    noCache = noCache || false;

    if (this.templates[name]) {
      var view;

      if (noCache) {
        view = this.templates[name]();
        view.name = name;
        view.pool = this.pool;
      } else {
        view = this.pool.pull(name);
        if (!view) {
          view = this.templates[name]();
          view.name = name;
          view.pool = this.pool;
        }
      }

      if (values !== undefined) {
        view.update(values);
      }

      if (view.onRender) {
        view.onRender();
      }

      if (this.wrappers[name] && !view.wrapped[name]) {
        view = this.wrappers[name](view);
        view.wrapped[name] = true;
      }

      return view;
    } else {
      throw new Error('Template with name "' + name + '" does not found.');
    }
  };

  /**
   * Prerepder view for future usage.
   * @param {string} name - Template name.
   * @param {number} times - Times of prerender.
   */
  Monkberry.prototype.prerender = function (name, times) {
    while (times--) {
      this.pool.push(name, this.render(name, undefined, true));
    }
  };

  /**
   * Mount template into monkberry.
   * @param {Object} templates
   */
  Monkberry.prototype.mount = function (templates) {
    var _this = this;

    // Some of templates mounts as factory which returns list of templates.
    if (typeof templates === 'function') {
      templates = templates(this, document);
    }

    Object.keys(templates).forEach(function (name) {
      _this.templates[name] = templates[name];
    });
  };

  /**
   * Create new Monkberry instance with separate pool, templates and wrappers.
   * Note what filters will be same.
   * @returns {Monkberry}
   */
  Monkberry.prototype.createPool = function () {
    var pool = new Monkberry();
    pool.filters = this.filters;
    return pool;
  };

  /**
   * Get info about prerendered templates.
   * @returns {Object}
   */
  Monkberry.prototype.getPoolInfo = function () {
    var name, info = {};
    for(name in this.pool.store) {
      info[name] = this.pool.store[name].length;
    }
    return info;
  };

  Monkberry.prototype.view = function () {
    return new Monkberry.View;
  };

  Monkberry.prototype.map = function () {
    return new Map;
  };

  /**
   * Main class for view.
   * @class
   */
  Monkberry.View = function View() {
    this.name = ''; // Name of template.
    this.parent = null; // Parent view.
    this.nested = []; // Nested views.
    this.nodes = []; // Root DOM nodes.
    this.wrapped = {}; // List of already applied wrappers.
    this.onRender = null; // Function to call on render.
    this.onRemove = null; // Function to call on remove.
  };

  /**
   * Updates view. You can specify only part of data what is needs to be updated.
   * @param {Object} data
   */
  Monkberry.View.prototype.update = function (data) {
    var _this = this;

    // Collect keys.
    var keys = typeof data === 'object' ? Object.keys(data) : [];

    // Clear cache to prevent double updating.
    if (_this.__cache__) {
      keys.forEach(function (key) {
        if (key in _this.__cache__) {
          delete _this.__cache__[key];
        }
      });
    }

    // Update view.
    if (_this.__update__) {
      keys.forEach(function (key) {
        if (_this.__update__.hasOwnProperty(key)) {
          _this.__update__[key](data, data[key]);
        }
      });
    }
  };

  /**
   * @param {Element} toNode
   */
  Monkberry.View.prototype.appendTo = function (toNode) {
    for (var i = 0, len = this.nodes.length; i < len; i++) {
      toNode.appendChild(this.nodes[i]);
    }
  };

  /**
   * @param {Element} toNode
   */
  Monkberry.View.prototype.insertBefore = function (toNode) {
    if (toNode.parentNode) {
      for (var i = 0, len = this.nodes.length; i < len; i++) {
        toNode.parentNode.insertBefore(this.nodes[i], toNode);
      }
    } else {
      throw new Error(
        "Can not insert child view into parent node. " +
        "You need append your view first and then update."
      );
    }
  };

  /**
   * Return rendered node, or DocumentFragment of rendered nodes if more then one root node in template.
   * @returns {Element|DocumentFragment}
   */
  Monkberry.View.prototype.createDocument = function () {
    if (this.nodes.length == 1) {
      return this.nodes[0];
    } else {
      var fragment = document.createDocumentFragment();
      for (var i = 0, len = this.nodes.length; i < len; i++) {
        fragment.appendChild(this.nodes[i]);
      }
      return fragment;
    }
  };

  /**
   * @deprecated since version 3.1.0. Use createDocument() instead.
   * @returns {Element|DocumentFragment}
   */
  Monkberry.View.prototype.dom = function () {
    return this.createDocument();
  };

  /**
   * Remove view from DOM.
   * @param {boolean} force - If true, do not put this view into pool.
   */
  Monkberry.View.prototype.remove = function (force) {
    force = force || false;
    // Remove appended nodes.
    var i = this.nodes.length;
    while (i--) {
      this.nodes[i].parentNode.removeChild(this.nodes[i]);
    }
    // Remove self from parent's children map or child ref.
    if (this.onRemove) {
      this.onRemove();
    }
    // Remove all nested views.
    i = this.nested.length;
    while (i--) {
      this.nested[i].remove(force);
    }
    // Remove this view from parent's nested views.
    if (this.parent) {
      i = this.parent.nested.indexOf(this);
      this.parent.nested.splice(i, 1);
    }
    // Store view in pool for reuse in future.
    if (!force) {
      this.pool.push(this.name, this);
    }
  };

  /**
   * @param {string} id
   * @returns {Element}
   * @deprecated Use querySelector instead of.
   */
  Monkberry.View.prototype.getElementById = function (id) {
    return this.querySelector('#' + id);
  };

  /**
   * @param {string} query
   * @returns {Element}
   */
  Monkberry.View.prototype.querySelector = function (query) {
    for (var i = 0; i < this.nodes.length; i++) {
      if (this.nodes[i].matches && this.nodes[i].matches(query)) {
        return this.nodes[i];
      }

      if (this.nodes[i].nodeType === 8) {
        throw 'Can not use querySelector with non-element nodes on first level.';
      }

      if (this.nodes[i].querySelector) {
        var element = this.nodes[i].querySelector(query);
        if (element) {
          return element;
        }
      }
    }
    return null;
  };

  /**
   * Pool stores pre rendered views for faster template
   * rendering and removed views for reuseing DOM nodes.
   */
  function Pool() {
    this.store = {};
  }

  Pool.prototype.push = function (name, view) {
    if (!this.store[name]) {
      this.store[name] = [];
    }
    this.store[name].push(view);
  };

  Pool.prototype.pull = function (name) {
    if (this.store[name]) {
      return this.store[name].pop();
    } else {
      return void 0;
    }
  };

  /**
   * Simple Map implementation with length property.
   */
  function Map() {
    this.items = Object.create(null);
    this.length = 0;
    this.next = 0;
  }

  Map.prototype.push = function (element) {
    this.items[this.next] = element;
    this.length += 1;
    this.next += 1;
    return this.next - 1;
  };

  Map.prototype.remove = function (i) {
    if (i in this.items) {
      delete this.items[i];
      this.length -= 1;
    } else {
      throw new Error('You are trying to delete not existing element "' + i + '" form map.');
    }
  };

  Map.prototype.forEach = function (callback) {
    for (var i in this.items) {
      callback(this.items[i]);
    }
  };

  //
  // Helper function for working with foreach loops data.
  // Will transform data for "key, value of array" constructions.
  //

  function transformArray(data, array, keys, i, options) {
    if (options) {
      var t = data;
      t[options.value] = array[i];

      if (options.key) {
        t[options.key] = i;
      }

      return t;
    } else {
      return array[i];
    }
  }

  function transformObject(data, array, keys, i, options) {
    if (options) {
      var t = data;
      t[options.value] = array[keys[i]];

      if (options.key) {
        t[options.key] = keys[i];
      }

      return t;
    } else {
      return array[keys[i]];
    }
  }

  if (typeof module !== "undefined") {
    module.exports = new Monkberry();
  } else {
    window.monkberry = new Monkberry();
  }
})(window.document);

redpajama_set_name: RedPajamaGithub


text:
describe('Untyped Property', function() {
  var t;

  beforeEach(function() {
    foam.CLASS({
      name: 'PropTest',
      package: 'test',
      properties: [
        {
          name: 'b'
        },
      ]
    });
    t = test.PropTest.create({}, foam.__context__);
  });
  afterEach(function() {
    t = null;
  });

  it('creates a Property by default', function() {
    expect(test.PropTest.B.cls_.name).toEqual('Property');
  });

});

describe('AbstractClass.getAxioms', function() {

  beforeEach(function() {
  });
  afterEach(function() {
  });

  it('coverage', function() {
    foam.core.Property.getAxioms();
    // Previous results cached.
    expect(foam.core.Property.getAxioms()).toBeDefined();
  });

});

describe('AbstractClass.toString', function() {

  beforeEach(function() {
  });
  afterEach(function() {
  });

  it('coverage', function() {
    expect(foam.core.Property.toString()).toBeDefined();
  });

});

describe('Property Getter and Setter', function() {
  var t;
  var p;

  beforeEach(function() {
    foam.CLASS({
      name: 'GetterSetterTest',
      package: 'test',
      properties: [
        {
          name: 'b',
          adapt: function(old, nu) {
            p += 'adapt'+nu;
            return nu;
          },
          preSet: function(old, nu) {
            p += 'preSet'+nu;
            return nu;
          },
          postSet: function(old, nu) {
            p += 'postSet'+nu;
          },
        },
        {
          name: 'a',
          getter: function()  { return this.b; },
          setter: function(a) { this.b = a; }
        }
      ]
    });
    t = test.GetterSetterTest.create({}, foam.__context__);
    p = "";
  });
  afterEach(function() {
    t = null;
    p = "";
  });

  it('sets a value and gets it back', function() {
    t.a = 42;
    expect(t.a).toEqual(42);
  });
  it('sets a value via custom setter', function() {
    t.a = 42;
    expect(t.b).toEqual(42);
  })
  it('reads a value via custom getter', function() {
    t.b = 42;
    expect(t.a).toEqual(42);
  })
  it('sets values repeatedly and gets them back', function() {
    t.a = 42;
    expect(t.a).toEqual(42);
    t.a = 'hello';
    expect(t.a).toEqual('hello');
    t.a = -3;
    expect(t.a).toEqual(-3);
  });
  it('gets undefined when not yet set', function() {
    expect(t.a).toBeUndefined();
  });
  it('Hits defined adapt/pre/postSet', function() {
    t.b = 4;
    expect(p).toEqual('adapt4preSet4postSet4');
  });
});

describe('Property Factory', function() {
  var t;

  beforeEach(function() {
    foam.CLASS({
      name: 'FactoryTest',
      package: 'test',
      properties: [
        {
          name: 'a',
          factory: function() { this.testCount++; return 42; }
        },
        {
          name: 'testCount',
          value: 0
        }
      ]
    });
    t = test.FactoryTest.create({}, foam.__context__);
  });
  afterEach(function() {
    t = null;
  });

  it('runs', function() {
    expect(t.testCount).toEqual(0); // factory not run on init
    expect(t.a).toEqual(42);
    expect(t.testCount).toEqual(1); // factory is run by getter
  });

  it('is overwritten by a set value', function() {
    expect(t.testCount).toEqual(0); // factory not run on init
    t.a = 84;
    expect(t.testCount).toEqual(0); // factory is not run by setter
    expect(t.a).toEqual(84); // setter overwrites factory value
    t.a = 96;
    expect(t.testCount).toEqual(0);
    expect(t.a).toEqual(96);
  });

});

describe('Property default comparators', function() {
  var c;

  beforeEach(function() {
    c = foam.core.Property.create().comparePropertyValues;
  });
  afterEach(function() {
    c = null;
  });

//         return o1.$UID.compareTo(o2.$UID);

  it('accepts ===', function() {
    var s = '';
    expect(c(s, s)).toBe(0);
  });
  it('accepts double falsey', function() {
    expect(c(false, false)).toBe(0);
    expect(c(NaN, NaN)).toBe(0);
    expect(c(0, 0)).toBe(0);
    expect(c('', '')).toBe(0);
  });
  it('accepts left falsey', function() {
    expect(c(false, 6)).toEqual(1);
    expect(c(NaN, 6)).toEqual(1); // Is this really what we expect?
    expect(c(0, 6)).toEqual(-1);
    expect(c('', 6)).toEqual(-1);
  });
  it('accepts right falsey', function() {
    expect(c(4, false)).toEqual(-1);
    expect(c(4, NaN)).toEqual(-1);
    expect(c(4, 0)).toEqual(1);
    expect(c(4, '')).toEqual(1);
  });
  it('falls back on $UID.compareTo', function() {
    var o1 = Object.create(null);
    o1.$UID = 26;
    var o2 = Object.create(null);
    o2.$UID = 27;
    expect(c(o1, o2)).toBe(-1);
    expect(c(o2, o1)).toBe(1);
  });
});

describe('Property default value', function() {
  var t;

  beforeEach(function() {
    foam.CLASS({
      name: 'DefaultValue',
      package: 'test',
      properties: [
        {
          name: 'a',
          value: 42
        }
      ]
    });
    t= test.DefaultValue.create({}, foam.__context__);
  });
  afterEach(function() {
    t = null;
  });

  it('provides the value when not set', function() {
    expect(t.a).toEqual(42);
  });

  it('is overwritten by a set value', function() {
    expect(t.a).toEqual(42);
    t.a = 84;
    expect(t.a).toEqual(84);
  });

  it('provides the value when cleared', function() {
    expect(t.a).toEqual(42);
    t.a = 84;
    expect(t.a).toEqual(84);
    t.clearProperty('a');
    expect(t.a).toEqual(42);
  });

});
describe('Final property', function() {
  beforeEach(function() {
    foam.CLASS({
      name: 'Abc',
      package: 'test',
      properties: [
        {
          name: 'a',
          final: true
        }
      ]
    });
  });

  it('create with final set', function() {
    var abc = test.Abc.create({ a: 1 }, foam.__context__);
    expect(abc.a).toBe(1);
    abc.a = 2;
    expect(abc.a).toBe(1);
  });
  it('create unset and set after', function() {
    var abc = test.Abc.create(undefined, foam.__context__);
    abc.a = 1;
    expect(abc.a).toBe(1);
    abc.a = 2;
    expect(abc.a).toBe(1);
  });
});

describe('Constants', function() {
  var t;
  var t2;

  beforeEach(function() {
    foam.CLASS({
      name: 'ConstantTest',
      package: 'test',
      constants: [
        {
          name: 'KEY',
          value: 'my_value'
        }
      ]
    });
    t = test.ConstantTest.create({}, foam.__context__);
    foam.CLASS({
      name: 'ConstantTest2',
      package: 'test',
      constants: {
        KEY: 'my_value',
        KEY2: 'my_value2',
      }

    });
    t2 = test.ConstantTest2.create({}, foam.__context__);
  });
  afterEach(function() {
    t = null;
    t2 = null;
  });

  it('are available on instances', function() {
    expect(t.KEY).not.toBeUndefined();
    expect(t.KEY).toEqual('my_value');
  });

  it('accepts short map syntax', function() {
    expect(t2.KEY).not.toBeUndefined();
    expect(t2.KEY).toEqual('my_value');
    expect(t2.KEY2).not.toBeUndefined();
    expect(t2.KEY2).toEqual('my_value2');
  });

});

describe('Model.extends inheritance, isInstance(), isSubClass(), getAxioms()', function() {
  var person;
  var employee;
  var personReq;

  beforeEach(function() {
    foam.CLASS({
      package: 'test',
      name: 'Person',
      constants: [
        {
          name: 'KEY',
          value: 'my_value'
        }
      ],

      properties: [
        {
          class: 'String',
          name: 'name'
        },
        'age',
        {
          name: 'result'
        }
      ],

      methods: [
        function init() { },
        {
          name: 'sayHello',
          code: function() { this.result = 'hello '+this.name; }
        },
        function sayGoodbye() { this.result = "bye "+this.name; }
      ]
    });
    person = test.Person.create({name: 'Adam', age: 0}, foam.__context__);

    foam.CLASS({
      package: 'test',
      name: 'Employee',
      extends: 'test.Person',
      properties: [
        {
          name: 'salary'
        }
      ],

      methods: [
        function toString() {
          return this.cls_.name + '(' + this.name + ', ' + this.age + ', ' + this.salary + ')';
        }
      ]
    });
    employee = test.Employee.create({name: 'Jane', age: 30, salary: 50000}, foam.__context__);

    foam.CLASS({
      package: 'test',
      name: 'PersonRequirer',
      requires: ['test.Person'],
      methods: [
        function checkIsPersonInstance(other) {
          // This checks for subclass checking problems introduced by the
          // 'require' decorating of this.Person
          return this.Person.isInstance(other);
        }
      ]
    });
    personReq = test.PersonRequirer.create(undefined, foam.__context__);
  });
  afterEach(function() {
    person = null;
    employee = null;
    personReq = null;
  });

  it('inherits methods', function() {
    person.sayHello();
    employee.sayHello();
    expect(person.result).toEqual('hello Adam');
    expect(employee.result).toEqual('hello Jane');
    expect(employee.sayGoodbye).not.toBeUndefined();
  });
  it('inherits constants', function() {
    expect(person.KEY).toEqual('my_value');
    expect(employee.KEY).toEqual('my_value');
  });

  it('reports correct subclass checks', function() {
    expect(test.Person.isSubClass(test.Employee)).toBe(true);
    expect(test.Employee.isSubClass(test.Person)).toBe(false);

    foam.CLASS({ name: 'Fake', package: 'test' });
    expect(test.Person.isSubClass(test.Fake)).toBe(false);
  });

  it('reports correct subclass checks', function() {
    expect(test.Person.isInstance(person)).toBe(true);
    expect(test.Employee.isInstance(person)).toBe(false);
    expect(test.Person.isInstance(employee)).toBe(true);

    foam.CLASS({ name: 'Fake', package: 'test' });
    expect(test.Person.isInstance(test.Fake.create({}, foam.__context__))).toBe(false);
  });

  it('reports correct subclass checks in required classes', function() {
    expect(personReq.checkIsPersonInstance(person)).toBe(true);
    expect(personReq.checkIsPersonInstance(employee)).toBe(true);
  });

  it('returns axioms correctly', function() {
    expect(test.Person.getAxiomByName('age')).toBe(test.Person.AGE);

    var axs = test.Person.getAxiomsByClass(foam.core.Property);
    expect(axs.length).toEqual(3);
    expect(axs[0]).toBe(test.Person.NAME);
    expect(axs[1]).toBe(test.Person.AGE);
    expect(axs[2]).toBe(test.Person.RESULT);
  });

});

describe('Model.implements', function() {
  var person;

  beforeEach(function() {
    foam.CLASS({
      package: 'test',
      name: 'HelloBase',
      methods: [
        {
          name: 'sayHello',
          code: function() { this.result = 'Base hello '; }
        },
        {
          name: 'sayGoodbye',
          code: function() { this.result = 'Base bye '; }
        },
      ]
    });

    foam.CLASS({
      package: 'test',
      name: 'SalariedI',
      properties: [
        {
          name: 'salary',
          value: 50000
        }
      ],

      methods: [
        {
          name: 'sayHello',
          code: function() { this.result = 'BIG HELLO '+this.name; }
        },
        {
          name: 'sayGoodbye',
          code: function() { this.result = 'BYE '+this.name; }
        },
      ]
    });

    foam.CLASS({
      name: 'Person',
      extends: 'test.HelloBase',
      implements: [ 'test.SalariedI' ],
      package: 'test',
      properties: [
        {
          class: 'String',
          name: 'name'
        },
        'age',
        {
          name: 'result'
        }
      ],

      methods: [
        {
          name: 'sayHello',
          code: function() { this.result = 'hello '+this.name; }
        },
      ]
    });
    person = test.Person.create(undefined, foam.__context__);
  });
  afterEach(function() {
    person = null;
  });

  it('inherits methods', function() {
    person.name = "Joe";
    person.sayHello();
    expect(person.result).toEqual("hello Joe"); // Person overrides everyone
    person.sayGoodbye();
    expect(person.result).toEqual("BYE Joe"); // SalariedI overrides HelloBase
  });

});

describe('Model.classes', function() {
  var innerSelf;

  beforeEach(function() {

    foam.CLASS({
      name: 'Person',
      package: 'test',
      classes: [
        {
          name: 'InnerSelf',
          properties: [
            'me','myself','i'
          ],
        }
      ],

      properties: [
        {
          class: 'String',
          name: 'name'
        },
        'age',
        {
          name: 'result'
        }
      ],

      methods: [
        {
          name: 'sayHello',
          code: function() { this.result = 'hello '+this.name; }
        },
      ]
    });

  });
  afterEach(function() {
    innerSelf = null;
  });

  it('installs models', function() {
    expect(test.Person.InnerSelf).not.toBeUndefined();
  });

  it('processes model properties', function() {
    innerSelf = test.Person.InnerSelf.create({
      me: 43,
      myself: 'hello',
      i: ''
    }, foam.__context__);
    expect(innerSelf.me).toEqual(43);
    expect(innerSelf.myself).toEqual('hello');
    expect(innerSelf.i).toEqual('');

  });

});

describe('FObject white box test', function() {
  beforeEach(function() {
    foam.CLASS({
      name: 'Person',
      package: 'test',
      properties: [
        {
          class: 'String',
          name: 'name'
        },
        {
          name: 'age'
        },
      ],
    });
  });
  afterEach(function() {
  });

  it('inits from null', function() {
    var o = test.Person.create(undefined, foam.__context__);
    expect(o.name).toEqual('');
  });
  it('inits from a POJSO', function() {
    var o = test.Person.create({ name: 'prop1' }, foam.__context__);

    expect(o.name).toEqual('prop1');
  });
  it('inits from another FObject', function() {
    var o = test.Person.create({ name: 'prop1' }, foam.__context__);
    var o2 = test.Person.create(o, foam.__context__);

    expect(o2.name).toEqual('prop1');
  });
  it('covers init from another FObject with no instance_', function() {
    var prot = { name: 'prop1' };
    var o = test.Person.create(Object.create(prot), foam.__context__);

    expect(o.name).toEqual('prop1');
  });
  it('toString()s nicely', function() {
    var o = test.Person.create(undefined, foam.__context__);
    o.toString();
  });

});

describe('Method overrides and SUPER', function() {
  var m;
  var s;

  beforeEach(function() {
    foam.CLASS({
      name: 'BaseClass',
      package: 'test',
      methods: [
        function base() {
          return 5;
        }
      ]
    });
    foam.CLASS({
      name: 'SubClass',
      extends: 'test.BaseClass',
      package: 'test',
      methods: [
        function base() {
          return this.SUPER() + 1;
        }
      ]
    });
    foam.CLASS({
      name: 'SubSubClass',
      extends: 'test.SubClass',
      package: 'test',
      methods: [
        function base() {
          return this.SUPER() + 2;
        }
      ]
    });
    m = test.SubClass.create(undefined, foam.__context__);
    s = test.SubSubClass.create(undefined, foam.__context__);
  });
  afterEach(function() {
    BaseClass = undefined;
    SubClass = undefined;
    SubSubClass = undefined;
    m = null;
    s = null;
  });

  it('SUPER is defined for overriden methods', function() {
    expect(function() { m.base(); }).not.toThrow();
    expect(m.base()).toEqual(6);
    m.base.toString();
  });
  it('SUPER slow path works', function() {
    expect(function() { s.base(); }).not.toThrow();
    expect(s.base()).toEqual(8);
  });

});

describe('Property Mlang interop', function() {
  var t;

  beforeEach(function() {
    foam.CLASS({
      name: 'MTest',
      package: 'test',
      properties: [
        {
          name: 'a',
          value: 45,
        },
      ]
    });
    t = test.MTest.create({}, foam.__context__);
  });
  afterEach(function() {
    t = null;
  });

  it('predicate support works', function() {
    expect(test.MTest.A.f(t)).toEqual(45); // extracts 'a' property of instance t
  });
  it('compare support works', function() {
    var t2 = test.MTest.create({ a: 45 }, foam.__context__);
    expect(test.MTest.A.compare(t, t2)).toBe(0);
    t2.a = 2;
    expect(test.MTest.A.compare(t, t2)).toEqual(1);
    t.a = 1;
    expect(test.MTest.A.compare(t, t2)).toEqual(-1);
  });
});

describe('Slots', function() {
  var t;
  var t2;

  beforeEach(function() {
    foam.CLASS({
      name: 'MTest',
      package: 'test',
      properties: [
        {
          name: 'a',
          value: 45,
        },
      ]
    });
    t = test.MTest.create(undefined, foam.__context__);
    t2 = test.MTest.create(undefined, foam.__context__);
  });
  afterEach(function() {
    t = null;
    t2 = null;
  });

  it('creates a slot for a property', function() {
    expect(t.a$).not.toBeUndefined();
    expect(t.a$.isDefined()).toBe(false);
    t.a = 4;
    expect(t.a$.isDefined()).toBe(true);
  });
  it('binds property slots', function() {
    t.a$ = t2.a$; // bind
    t.a = 999;
    expect(t2.a).toEqual(999);
  });
  it('allows links to be detached', function() {
    var b = t.a$.link(t2.a$);
    t.a = 999;

    b.detach();

    t.a = 4;
    expect(t.a).toEqual(4);
    expect(t2.a).toEqual(999);
  });
  it('allows follows to be detached', function() {
    var b = t2.a$.follow(t.a$);
    t.a = 999;

    b.detach();

    t.a = 4;
    expect(t.a).toEqual(4);
    expect(t2.a).toEqual(999);
  });
//   it('clears the property', function() {
//     var b = t2.a$.follow(t.a$);
//     t.a = 999;
//     expect(t2.a).toEqual(999);
//     t.a$.clear();
//     expect(t2.a).toEqual(45);
//   });
  it('subs manual listeners', function() {
    var last_args, last_value;
    var l = function() {
      last_args = Array.prototype.slice.call(arguments);
      last_value = last_args[3].get();
    };
    t.a$.sub(l);
    t.a = 999;
    expect(last_args).toBeDefined();
    expect(last_args[2]).toEqual('a');
    expect(last_value).toEqual(999);
  });
  it('unsubs manual listeners', function() {
    var last_args, last_value;
    var l = function() {
      last_args = Array.prototype.slice.call(arguments);
      last_value = last_args[3].get();
    };
    var s = t.a$.sub(l);
    t.a = 999;

    s.detach();
    t.a = 49;

    // same as the first time
    expect(last_args).toBeDefined();
    expect(last_args[2]).toEqual('a');
    expect(last_value).toEqual(999);
  });
});

describe('Listeners', function() {
  var t;

  beforeEach(function() {
    foam.CLASS({
      name: 'Sprinkler',
      package: 'test',
      listeners: [
        function onAlarm() {  },
        {
          name: 'onClear',
          isFramed: true,
          code: function() { }
        }
      ]
    });
    t = test.Sprinkler.create({}, foam.__context__);
  });
  afterEach(function() {
    t = null;
  });

  it('listeners are installed as method-alikes', function() {
    t.onAlarm();
    t.onClear();
    expect().nothing();
  });
});

describe('Bootstrap invariants', function() {
  it('Check that all recursive relationships are properly set', function() {
    expect(foam.core.Model.isInstance(foam.core.Model.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.FObject.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Property.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Method.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.String.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.FObjectArray.model_)).toBe(true);
  });

  it('Check that Class.model_ and Class.prototype.model_ are the same object', function() {
    expect(foam.core.Model.isInstance(foam.core.AxiomArray.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Constant.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Implements.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Slot.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.internal.PropertySlot.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Topic.model_)).toBe(true);
    expect(foam.core.Model.isInstance(foam.core.Boolean.model_)).toBe(true);
  });
})


text:
package dot.junit.opcodes.sput_object.d;

public class T_sput_object_14 extends T_sput_object_1{

    public void run() {
        T_sput_object_1.st_p1 = this;
    }

    public static Object getProtectedField(){
        return T_sput_object_1.st_p1;
    }

}


text:
package com.swfarm.biz.product.web;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import com.swfarm.biz.chain.bo.SaleChannelAccountGroup;
import com.swfarm.biz.chain.dto.SearchSaleChannelAccountGroupCriteria;
import com.swfarm.biz.chain.srv.ChainManagementService;
import com.swfarm.biz.chain.srv.ChainService;
import com.swfarm.biz.oa.bo.User;
import com.swfarm.biz.product.bo.StockKeepingUnitCube;
import com.swfarm.biz.product.dto.SearchStockKeepingUnitCubesCriteria;
import com.swfarm.biz.product.srv.ProductService;
import com.swfarm.pub.utils.DateUtils;

public class RefreshSkuCubeStatisticsController extends AbstractController {

	private ChainService chainService;

	private ProductService productService;

	private ChainManagementService chainManagementService;

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	public void setChainService(ChainService chainService) {
		this.chainService = chainService;
	}

	public void setChainManagementService(
			ChainManagementService chainManagementService) {
		this.chainManagementService = chainManagementService;
	}

	protected ModelAndView handleRequestInternal(HttpServletRequest req,
			HttpServletResponse res) throws Exception {
		String skuCubeIdStr = req.getParameter("skuCubeId");
		String refreshDateStr = req.getParameter("startDate");
		Date refreshDate = null;
		if (StringUtils.isNotEmpty(refreshDateStr)) {
			DateUtils.stringToDate(refreshDateStr, "yyyy/MM/dd");
		} else {
			refreshDate = new Date();
		}
		if (StringUtils.isNotEmpty(skuCubeIdStr)) {
			Long skuCubeId = new Long(skuCubeIdStr);
			StockKeepingUnitCube skuCube = this.productService
					.findStockKeepingUnitCube(skuCubeId);
			List accountNumbers = getAccountNumbers(skuCube);
			this.chainManagementService.refreshSkuCubeSaleQuantities(skuCubeId,
					accountNumbers, refreshDate);
			this.chainManagementService.refreshSkuCubeBonusPoints(skuCubeId,
					accountNumbers, refreshDate);
			Double[] cubeTurnOverInfo = this.chainManagementService
					.refreshSkuTurnOverRates(skuCube.getArticleNumberList(),
							refreshDate);
			Double totalThirtyDaysSaleAmount = cubeTurnOverInfo[0];
			Double totalAverageStockAmount = cubeTurnOverInfo[1];
			if (totalAverageStockAmount > 0) {
				Double turnOverRate = totalThirtyDaysSaleAmount
						/ totalAverageStockAmount;
				skuCube.setThirtyDaysSaleAmount(totalThirtyDaysSaleAmount);
				skuCube.setAverageStockAmount(totalAverageStockAmount);
				skuCube.setTurnOverRate(turnOverRate);
				this.productService.saveStockKeepingUnitCube(skuCube);
			}
			return new ModelAndView(
					"redirect:/product/search_stockkeepingunitcubes.shtml",
					"name", skuCube.getName());
		} else {
			SearchStockKeepingUnitCubesCriteria criteria = new SearchStockKeepingUnitCubesCriteria();
			List skuCubes = this.productService
					.searchStockKeepingUnitCubes(criteria);
			if (CollectionUtils.isNotEmpty(skuCubes)) {
				for (Iterator iter = skuCubes.iterator(); iter.hasNext();) {
					StockKeepingUnitCube skuCube = (StockKeepingUnitCube) iter
							.next();
					List accountNumbers = getAccountNumbers(skuCube);
					this.chainManagementService.refreshSkuCubeSaleQuantities(
							skuCube.getId(), accountNumbers, refreshDate);
					this.chainManagementService.refreshSkuCubeBonusPoints(
							skuCube.getId(), accountNumbers, refreshDate);
					Double[] cubeTurnOverInfo = this.chainManagementService
							.refreshSkuTurnOverRates(
									skuCube.getArticleNumberList(), refreshDate);
					Double totalThirtyDaysSaleAmount = cubeTurnOverInfo[0];
					Double totalAverageStockAmount = cubeTurnOverInfo[1];
					if (totalAverageStockAmount > 0) {
						Double turnOverRate = totalThirtyDaysSaleAmount
								/ totalAverageStockAmount;
						skuCube.setThirtyDaysSaleAmount(totalThirtyDaysSaleAmount);
						skuCube.setAverageStockAmount(totalAverageStockAmount);
						skuCube.setTurnOverRate(turnOverRate);
						this.productService.saveStockKeepingUnitCube(skuCube);
					}
				}
			}
			return new ModelAndView(
					"redirect:/product/search_stockkeepingunitcubes.shtml");
		}
	}

	private List getAccountNumbers(StockKeepingUnitCube skuCube) {
		List accountNumbers = new ArrayList();
		User cubeOwner = skuCube.getCubeOwner();
		if (cubeOwner != null) {
			SearchSaleChannelAccountGroupCriteria criteria = new SearchSaleChannelAccountGroupCriteria();
			criteria.setGroupOwnerId(cubeOwner.getId());
			List groups = this.chainService
					.searchSaleChannelAccountGroups(criteria);
			SaleChannelAccountGroup group = null;
			if (CollectionUtils.isNotEmpty(groups)) {
				group = (SaleChannelAccountGroup) groups.iterator().next();
			}
			if (group == null) {
				criteria = new SearchSaleChannelAccountGroupCriteria();
				criteria.setGroupMemberId(cubeOwner.getId());
				groups = this.chainService
						.searchSaleChannelAccountGroups(criteria);
				if (CollectionUtils.isNotEmpty(groups)) {
					group = (SaleChannelAccountGroup) groups.iterator().next();
				}
			}
			if (group != null) {
				accountNumbers.addAll(group.getAccountNumberList());
			}
		}
		return accountNumbers;
	}
}


text:
<?php

namespace Pofta\MainBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * complexitate
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Pofta\MainBundle\Entity\complexitateRepository")
 */
class complexitate
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="denumire", type="string", length=15)
     */
    private $denumire;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set denumire
     *
     * @param string $denumire
     * @return complexitate
     */
    public function setDenumire($denumire)
    {
        $this->denumire = $denumire;

        return $this;
    }

    /**
     * Get denumire
     *
     * @return string
     */
    public function getDenumire()
    {
        return $this->denumire;
    }
}


text:
require 'thor'
module Gurk
  class Cli < Thor::Group
    include Thor::Actions

    argument :name

    def self.source_root
      File.dirname(__FILE__)
    end

    def setup
      directory "../templates", name, recursive: true
    end

    def bundle_install
      system("cd #{name} && bundle install")
    end

  end
end


text:
function SRGView(){

}

SRGView.prototype = {
	constructor: SRGView,
	isSRGView: true
}


text:
package org.radarcns.management.service.mapper;

import org.mapstruct.Mapper;
import org.radarcns.management.domain.SourceData;
import org.radarcns.management.service.dto.SourceDataDTO;

import java.util.List;

/**
 * Mapper for the entity SourceData and its DTO SourceDataDTO.
 */
@Mapper(componentModel = "spring", uses = {SourceTypeMapper.class})
public interface SourceDataMapper {

    SourceDataDTO sourceDataToSourceDataDTO(SourceData sourceData);

    List<SourceDataDTO> sourceDataToSourceDataDTOs(List<SourceData> sourceData);

    SourceData sourceDataDTOToSourceData(SourceDataDTO sourceDataDto);

    List<SourceData> sourceDataDTOsToSourceData(List<SourceDataDTO> sourceDataDtos);

    /**
     * generating the fromId for all mappers if the databaseType is sql, as the class has
     * relationship to it might need it, instead of creating a new attribute to know if the entity
     * has any relationship from some other entity.
     *
     * @param id id of the entity
     * @return the entity instance
     */

    default SourceData sourceDataFromId(Long id) {
        if (id == null) {
            return null;
        }
        SourceData sourceData = new SourceData();
        sourceData.setId(id);
        return sourceData;
    }
}


text:
<!DOCTYPE html>

	<meta charset="UTF-8">
	<link rel="stylesheet" href="style.css">
	<title>Dialogue test</title>

		<button class="myButton" id="cngButton">Change Text</button>

Hold on... We're getting the content for you.


text: - Updated the Docker image to: *demisto/pcap-http-extractor:1.0.0.32113*.


text:
package com.lsoe.coolreader.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * TODO: Describe purpose and behavior of CoolData
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CoolData {

	String csvFileURI();

	Class<?>[] columns() default {};
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A-Index</title>
<meta name="date" content="2015-06-17">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Letter

Next Letter

Frames

No Frames

All Classes

A C G M

A

AlexaRank - Class in com.renangomes.alexarankcache

AlexaRank class that will generate (on class load) a rank with top 1M URLs on
 Alexa.

A C G M

Skip navigation links

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Letter

Next Letter

Frames

No Frames

All Classes


text:
import React, { Component } from 'react'
import connectToStores from 'alt-utils/lib/connectToStores'

import DateStore from '../stores/DateStore'
import PoemStore from '../stores/PoemStore'
import PoemActions from '../actions/PoemActions'
import PoemList from '../components/PoemList'
import PoemEditor from '../components/PoemEditor'

import PanelActions from '../actions/PanelActions'

import PoemEditModal from '../components/PoemEditModal'

class PoemContainer extends Component {
  static getStores() {
    return [DateStore, PoemStore]
  }

  static getPropsFromStores() {
    return {
      ...DateStore.getState(),
      ...PoemStore.getState(),
    }
  }

  constructor() {
    super()
    this.state = { text: '' }
  }

  componentDidMount() {
    PoemActions.sync(this.props.date)
  }

  handleChange = (value) => {
    this.setState({ text: value })
  }

  handleSubmit = () => {
    if (!this.state.text.trim()) {
      console.log('no text')
      return
    }
    PoemActions.add({
      user_id: 1,
      date: this.props.date,
      status: 'published',
      body: this.state.text,
    })
    this.setState({ text: ' ' })
  }

  render() {
    const modal = (this.props.is_modal) ? <PoemEditModal poem={this.props.edit_poem} actions={PoemActions} handleEditorChange={this.handleChange} handleEditorSubmit={this.handleSubmit} /> : false
    const expandCls = (this.props.is_expand) ? 'fa fa-angle-up' : 'fa fa-angle-down'
    const expandBodyCls = (this.props.is_expand) ? 'message-body open' : 'message-body close'
    return (

Poem

          <PoemEditor
            value={this.state.text}
            handleEditorChange={this.handleChange}
            handleEditorSubmit={this.handleSubmit}
          />
          <PoemList actions={PoemActions} poems={this.props.poems} />

        {modal}

    )
  }
}

export default connectToStores(PoemContainer)


text:
using System;

class CalculationProblem
{
    static void Main()
    {
        string[] letterNumbers = Console.ReadLine().Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);

        long sumLetters = 0;

        for (int i = 0; i < letterNumbers.Length; i++)
        {
            string currWord = letterNumbers[i];
            long currSum = 0;

            foreach (var symbol in currWord)
            {
                int digit = symbol - 'a';
                currSum = digit + currSum * 23;
            }

            sumLetters += currSum;
        }

        long result = sumLetters;
        string base23 = string.Empty;

        do
        {
            char letter = (char)(sumLetters % 23 + 'a');
            sumLetters /= 23;

            base23 = letter + base23;
        }
        while (sumLetters > 0);

        Console.WriteLine("{0} = {1}", base23, result);
    }
}


text:
module Spec
  # == Example Groups and Code Examples
  #
  # A Code Example is an executable example of how a bit of code is expected
  # to behave.
  #
  # An Example Group is a group of code examples.
  #
  # RSpec exposes a DSL to describe groups of examples.
  #
  #   describe Account do
  #     it "should have a balance of $0" do
  #       account = Account.new
  #       account.balance.should == Money.new(0, :dollars)
  #     end
  #   end
  #
  # == Before and After
  #
  # You can use the <tt>before()</tt> and <tt>after()</tt> methods to extract
  # common code within an Example Group. Both methods take an optional scope
  # argument so you can run the block before :each example or before :all
  # examples
  #
  #   describe "..." do
  #     before :all do
  #       ...
  #     end
  #
  #     before :each do
  #       ...
  #     end
  #
  #     it "should do something" do
  #       ...
  #     end
  #
  #     it "should do something else" do
  #       ...
  #     end
  #
  #     after :each do
  #       ...
  #     end
  #
  #     after :all do
  #       ...
  #     end
  #
  #   end
  #
  # The <tt>before :each</tt> block will run before each of the examples, once
  # for each example. Likewise, the <tt>after :each</tt> block will run after
  # each of the examples.
  #
  # It is also possible to specify a <tt>before :all</tt> and <tt>after
  # :all</tt> block that will run only once for each example group, before the
  # first before :each and after the last after
  # :each respectively. The use of these is generally discouraged,
  # because it introduces dependencies between the examples. Still, it might
  # prove useful for very expensive operations if you know what you are doing.
  #
  # == Local helper methods
  #
  # You can include local helper methods by simply expressing them within an
  # example group:
  #
  #   describe "..." do
  #
  #     it "..." do
  #       helper_method
  #     end
  #
  #     def helper_method
  #       ...
  #     end
  #
  #   end
  #
  # == Included helper methods
  #
  # You can include helper methods in multiple example groups by expressing
  # them within a module, and then including that module in your example
  # groups:
  #
  #   module AccountExampleHelperMethods
  #     def helper_method
  #       ...
  #     end
  #   end
  #
  #   describe "A new account" do
  #     include AccountExampleHelperMethods
  #     before do
  #       @account = Account.new
  #     end
  #
  #     it "should have a balance of $0" do
  #       helper_method
  #       @account.balance.should eql(Money.new(0, :dollars))
  #     end
  #   end
  #
  # == Shared Example Groups
  #
  # You can define a shared example group, that may be used on other groups
  #
  #  share_examples_for "All Editions" do
  #    it "all editions behaviour" ...
  #  end
  #
  #  describe SmallEdition do
  #    it_should_behave_like "All Editions"
  #
  #    it "should do small edition stuff" do
  #      ...
  #    end
  #  end
  #
  # You can also assign the shared group to a module and include that
  #
  #  share_as :AllEditions do
  #    it "should do all editions stuff" ...
  #  end
  #
  #  describe SmallEdition do
  #    it_should_behave_like AllEditions
  #
  #    it "should do small edition stuff" do
  #      ...
  #    end
  #  end
  #
  # And, for those of you who prefer to use something more like Ruby, you can
  # just include the module directly
  #
  #  describe SmallEdition do
  #    include AllEditions
  #
  #    it "should do small edition stuff" do
  #      ...
  #    end
  #  end
  module Example
    class << self
      def args_and_options(*args) # :nodoc:
        with_options_from(args) do |options|
          return args, options
        end
      end

      def scope_from(*args) # :nodoc:
        args[0] || :each
      end

      def scope_and_options(*args) # :nodoc:
        args, options = args_and_options(*args)
        return scope_from(*args), options
      end

      def set_location(args, location) # :nodoc:
        args << {} unless Hash === args.last
        args.last[:location] ||= location
      end

    private

      def with_options_from(args)
        yield Hash === args.last ? args.pop : {} if block_given?
      end
    end
  end
end

require 'timeout'
require 'spec/example/predicate_matchers'
require 'spec/example/example_group_proxy'
require 'spec/example/example_proxy'
require 'spec/example/subject'
require 'spec/example/before_and_after_hooks'
require 'spec/example/pending'
require 'spec/example/module_reopening_fix'
require 'spec/example/example_group_hierarchy'
require 'spec/example/example_group_methods'
require 'spec/example/example_methods'
require 'spec/example/example_group'
require 'spec/example/shared_example_group'
require 'spec/example/example_group_factory'
require 'spec/example/errors'
require 'spec/example/example_matcher'


text:
import format = require('pg-format');

const testDate = new Date(Date.UTC(2012, 11, 14, 13, 6, 43, 152));
const testArray = [ 'abc', 1, true, null, testDate ];
const testIdentArray = [ 'abc', 'AbC', 1, true, testDate ];
const testObject = { a: 1, b: 2 };
const testNestedArray = [ [1, 2], [3, 4], [5, 6] ];

format.config({
    pattern: {
        ident: 'V',
        literal: 'C',
        string: 't'
    }
});
format.config();

format('some %s thing %s', 'long', 'here');
format('%L', testNestedArray);

format.withArray('some %s thing %s', [ 'long', 'here' ]);
format.withArray('many %s %s', ['things', testNestedArray]);

format.string(undefined);
format.string(null);
format.string(true);
format.string(false);
format.string(0);
format.string(15);
format.string(-15);
format.string(45.13);
format.string(-45.13);
format.string('something');
format.string(testArray);
format.string(testNestedArray);
format.string(testDate);
format.string(testObject);

format.ident(true);
format.ident(false);
format.ident(0);
format.ident(15);
format.ident(-15);
format.ident(45.13);
format.ident(-45.13);
format.ident('something');
format.ident(testIdentArray);
format.ident(testNestedArray);
format.ident(testDate);

format.literal(null);
format.literal(undefined);
format.literal(true);
format.literal(false);
format.literal(0);
format.literal(15);
format.literal(-15);
format.literal(45.13);
format.literal(-45.13);
format.literal('something');
format.literal(testArray);
format.literal(testNestedArray);
format.literal(testDate);
format.literal(testObject);


text:
package org.apache.commons.logging.servlet;

import junit.framework.Test;
import junit.framework.TestCase;

import org.apache.commons.logging.PathableClassLoader;
import org.apache.commons.logging.PathableTestSuite;
import org.apache.commons.logging.impl.ServletContextCleaner;

/**
 * Tests for ServletContextCleaner utility class.
 */

public class BasicServletTestCase extends TestCase {

    /**
     * Return the tests included in this test suite.
     */
    public static Test suite() throws Exception {
        // LogFactory in parent
        // LogFactory in child (loads test)
        // LogFactory in tccl
        //
        // Having the test loaded via a loader above the tccl emulates the situation
        // where a web.xml file specifies ServletContextCleaner as a listener, and
        // that class is deployed via a shared classloader.

        final PathableClassLoader parent = new PathableClassLoader(null);
        parent.useExplicitLoader("junit.", Test.class.getClassLoader());
        parent.addLogicalLib("commons-logging");
        parent.addLogicalLib("servlet-api");

        final PathableClassLoader child = new PathableClassLoader(parent);
        child.setParentFirst(false);
        child.addLogicalLib("commons-logging");
        child.addLogicalLib("testclasses");

        final PathableClassLoader tccl = new PathableClassLoader(child);
        tccl.setParentFirst(false);
        tccl.addLogicalLib("commons-logging");

        final Class testClass = child.loadClass(BasicServletTestCase.class.getName());
        return new PathableTestSuite(testClass, tccl);
    }

    /**
     * Test that calling ServletContextCleaner.contextDestroyed doesn't crash.
     * Testing anything else is rather difficult...
     */
    public void testBasics() {
        final ServletContextCleaner scc = new ServletContextCleaner();
        scc.contextDestroyed(null);
    }
}


text:
FOUNDATION_EXPORT double Pods_PannablePickerView_Example_PannablePickerView_TestsVersionNumber;
FOUNDATION_EXPORT const unsigned char Pods_PannablePickerView_Example_PannablePickerView_TestsVersionString[];


text:
var addToUnscopables = require('../internals/add-to-unscopables');

// https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
addToUnscopables('flat');


text:
<?php
declare(strict_types=1);

namespace PhpMud\Enum;

use MyCLabs\Enum\Enum;

/**
 * @method static LIGHT()
 * @method static FINGER()
 * @method static NECK()
 * @method static TORSO()
 * @method static HEAD()
 * @method static LEGS()
 * @method static FEET()
 * @method static HANDS()
 * @method static ARMS()
 * @method static SHIELD()
 * @method static BODY()
 * @method static WAIST()
 * @method static WRIST()
 * @method static WIELDED()
 * @method static HELD()
 * @method static FLOATING()
 * @method static SECONDARY()
 */
class Position extends Enum
{
    const LIGHT = 'light';
    const FINGER = 'finger';
    const NECK = 'neck';
    const TORSO = 'torso';
    const HEAD = 'head';
    const LEGS = 'legs';
    const FEET = 'feet';
    const HANDS = 'hands';
    const ARMS = 'arms';
    const SHIELD = 'shield';
    const BODY = 'body';
    const WAIST = 'waist';
    const WRIST = 'wrist';
    const WIELDED = 'wielded';
    const HELD = 'held';
    const FLOATING = 'floating';
    const SECONDARY = 'secondary';

    public function getCount(): int
    {
        return
            $this->value === self::FINGER
            || $this->value === self::NECK
            || $this->value === self::WRIST
            ? 2 : 1;
    }
}


text:
{-# LANGUAGE DeriveFunctor #-}

module Ast
  ( showConstructs, uget, uset, ufield, ucall, unamed, uliteral
  , uif, usequence, toplevelName, ureturn, ucase, ulet, utuple, posToSpan
  , Ident(..), Type(..), Literal(..), Expression(..) , FuncDef(..)
  , AliasDef(..), Construct(..), IfExpr(..), UExpr(..), UFuncDef(..)
  , UConstruct(..), DataDef(..), TypePath(..), Path(..), CaseExpr(..)
  , Pattern(..), LetExpr(..), TypeKind(..), LiteralKind(..), ConstructKind(..)
  , ExpressionKind(..), PatternKind(..), Span(..), TypeIdent(..)
  , TypeConstructor(..), enclosingSpan, Spanable(..), IdentPath(..) ) where

import Data.Maybe
import Data.List
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Pos

import Span
import Annotation

--------------------------------------------------------------------------------
--                                    Utilities                               --
--------------------------------------------------------------------------------

type AnnExpr i = Fix (Ann i Expression)

-- Untyped AST:
type UExpr = Fix Expression
type UConstruct = Construct UExpr
type UFuncDef = FuncDef UExpr

uget f a s        = Fix $ Expression (EGet f a) s
uset a b s        = Fix $ Expression (ESet a b) s
ufield f s        = Fix $ Expression (EField f) s
ucall a b s       = Fix $ Expression (ECall a b) s
unamed n s        = Fix $ Expression (ENamed n) s
uliteral litr s   = Fix $ Expression (ELiteral litr) s
uif a s           = Fix $ Expression (EIf a) s
ureturn a s       = Fix $ Expression (EReturn a) s
ucase a s         = Fix $ Expression (ECase a) s
ulet a s          = Fix $ Expression (ELet a) s
usequence exprs s = Fix $ Expression (ESequence exprs) s
utuple a s        = Fix $ Expression (ETuple a) s

toplevelName p  = IdentPath (TypePath []) p

--------------------------------------------------------------------------------
--                                 Data structures                            --
--------------------------------------------------------------------------------

data Ident =
  Ident { identName :: String
        , identSpan  :: Span }
  deriving (Eq)

data TypeIdent =
  TypeIdent { tyIdentName :: String
            , tyIdentSpan  :: Span }
  deriving (Eq)

data TypePath = TypePath [(TypeIdent, [Type])]
  deriving (Eq)

data IdentPath =
  IdentPath { pathFragments  :: TypePath
            , pathIdent      :: Ident }
  deriving (Eq)

data Path = IPath IdentPath | CPath TypePath
  deriving (Eq)

data TypeKind =
  TNamed TypePath
  | TUnit
  | TFn [Type] Type
  | TParam Ident
  | TApply Type [Type]
  | TTuple [Type]
  | TUnknown
  deriving (Eq)

data Type =
  Type { typeKind :: TypeKind
       , typeSpan  :: Span }
  deriving (Eq)

data LiteralKind =
  LInt Integer
  | LChar Char
  | LString String
  | LFloat Double
  | LUnit
  deriving (Eq)

data Literal =
  Literal { literalKind :: LiteralKind
          , literalSpan  :: Span }
  deriving (Eq)

data IfExpr a =
  IfExpr { ifCond :: a
         , ifThen :: a
         , ifElse :: Maybe a
         , ifSpan  :: Span }
  deriving (Show, Functor, Eq)

data PatternKind =
  PWildcard
  | PBind Ident
  | PApply TypePath [Pattern]
  | PAt Ident Pattern
  | PValue Literal
  | PTuple [Pattern]
  deriving (Eq)

data Pattern =
  Pattern { patternKind :: PatternKind
          , patternSpan  :: Span }
  deriving (Eq)

data CaseExpr a =
  CaseExpr { caseSubject :: a
           , caseCases   :: [(Pattern, a)]
           , caseSpan    :: Span }
  deriving (Show, Functor, Eq)

data LetExpr a =
  LetExpr { letBinding :: [(Pattern, a)]
          , letExpr    :: Maybe a
          , letSpan    :: Span }
  deriving (Show, Functor, Eq)

data ExpressionKind a =
  ECall a [a]
  | ENamed Path
  | ELiteral Literal
  | EField Ident
  | EGet Ident a
  | ESet a a
  | EIf (IfExpr a)
  | EReturn a
  | ETuple [a]
  | ECase (CaseExpr a)
  | ELet (LetExpr a)
  | ESequence [a]
  deriving (Functor, Eq)

data Expression a =
  Expression { exprKind :: ExpressionKind a
             , exprSpan  :: Span }
  deriving (Functor, Eq)

data FuncDef a =
  FuncDef { funcDefName :: Ident
          , funcDefArgs :: [(Ident, Type)]
          , funcDefRet  :: Maybe Type
          , funcDefBody :: Maybe a
          , funcDefSpan  :: Span }
  deriving (Functor, Eq)

-- The list of types represents a sum-type
data TypeConstructor = TypeConstructor (TypeIdent, [Type])
  deriving (Eq)

-- The list of type constructures represents a product type
data DataDef =
  DataDef { dataDefName :: TypeIdent
          , dataDefArgs :: [Type]
          , dataDefBody :: [TypeConstructor]
          , dataDefSpan  :: Span }
  deriving (Eq)

data AliasDef =
  AliasDef { aliasDefName :: TypeIdent
           , aliasDefArgs :: [Type]
           , aliasDefBody :: Type
           , aliasDefSpan  :: Span }
    deriving (Eq)

data ConstructKind a =
  CFuncDef (FuncDef a)
  | CDataDef DataDef
  | CAliasDef AliasDef
  deriving (Functor, Eq)

data Construct a =
    Construct { constructKind :: ConstructKind a
              , constructSpan  :: Span }
  deriving (Functor, Eq)

--------------------------------------------------------------------------------
--                              Printing functions                            --
--------------------------------------------------------------------------------

instance Spanable Ident where
  spanOf = identSpan

instance Spanable TypeIdent where
  spanOf = tyIdentSpan

instance Spanable Type where
  spanOf = typeSpan

instance Spanable Literal where
  spanOf = literalSpan

instance Show a => Spanable (IfExpr a) where
  spanOf = ifSpan

instance Spanable Pattern where
  spanOf = patternSpan

instance Show a => Spanable (CaseExpr a) where
  spanOf = caseSpan

instance Show a => Spanable (LetExpr a) where
  spanOf = letSpan

instance Show a => Spanable (Expression a) where
  spanOf = exprSpan

instance Show a => Spanable (FuncDef a) where
  spanOf = funcDefSpan

instance Spanable DataDef where
  spanOf = dataDefSpan

instance Spanable AliasDef  where
  spanOf = aliasDefSpan

instance Show a => Spanable (Construct a) where
  spanOf = constructSpan

pres "" = ""
pres x  = ' ' : x
spans "" = ""
spans x  = x ++ " "

mlace sep [] = ""
mlace sep ts = intercalate sep ts

instance Show Ident where
  show (Ident v _) = v

instance Show TypeIdent where
  show (TypeIdent v _) = v

instance Show TypePath where
  show (TypePath elms) =
    mlace "::" $ map (\(n, aps) ->
      case aps of
        [] -> show n
        _  -> "(" ++ show n ++ pres (mlace " " $ map show aps) ++ ")" ) elms

instance Show IdentPath where
  show (IdentPath (TypePath []) n) = show n
  show (IdentPath tp n) = show tp ++ "::" ++ show n

instance Show Path where
  show (IPath i) = show i
  show (CPath c) = show c

instance Show Type where
  show (Type k _) = show k

instance Show TypeKind where
  show (TNamed n) = show n
  show TUnit = "()"
  show TUnknown = "_"
  show (TFn as r) =
    "(fn " ++ mlace " " (map show as) ++ "->" ++ show r ++ ")"
  show (TParam x) = show x
  show (TApply f xs) = "(" ++ show f ++ " " ++ mlace " " (map show xs) ++ ")"
  show (TTuple x) = "(" ++ mlace ", " (map show x) ++ ")"

instance Show Literal where
  show (Literal k _) = show k

instance Show LiteralKind where
  show (LInt x) = show x
  show LUnit = "()"
  show (LChar x) = "'" ++ x : "'"
  show (LString x) = "\"" ++ x ++ "\""
  show (LFloat x) = show x

instance Show e => Show (FuncDef e) where
  show (FuncDef nm as rt bd _) =
    "fn " ++ show nm ++ pres argst ++ rett ++ "= " ++ bodyt
    where
      argst = mlace ", " $ map (\(x, t) -> show x ++ " : " ++ show t) as
      rett = maybe " " (\x -> " -> " ++ show x ++ " ") rt
      bodyt = maybe "" show bd

instance Show DataDef where
  show (DataDef nm as bd _) =
    "data " ++ show nm ++ " " ++ argst ++ "= " ++ bodyt
    where
      argst = spans $ mlace " " $ map show as
      bodyt =
        mlace " | "
        $ map (\(TypeConstructor (ctor, elms)) ->
            show ctor ++ pres (mlace " " $ map show elms))
          bd

instance Show AliasDef where
  show (AliasDef nm as bd _) =
    "alias " ++ show nm ++ " " ++ argst ++ "= " ++ show bd
    where
       argst = spans $ mlace " " $ map show as

showConstructs cs = intercalate "\n" $ map show cs

instance Show Pattern where
  show (Pattern k _) = show k

instance Show PatternKind where
  show PWildcard = "_"
  show (PBind x) = show x
  show (PApply tp as) = show tp ++ pres (mlace " " (map show as))
  show (PValue x) = show x
  show (PAt n e) = show n ++ "@" ++ show e
  show (PTuple x) = "(" ++ mlace ", " (map show x) ++ ")"

instance Show e => Show (Construct e) where
  show (Construct v _) = show v

instance Show e => Show (ConstructKind e) where
  show (CFuncDef x)  = show x
  show (CDataDef x)  = show x
  show (CAliasDef x) = show x

instance Show a => Show (Expression a) where
  show (Expression k _) = show k

instance Show a => Show (ExpressionKind a) where
  show (ESequence elms) =
    intercalate "; " $ map show elms
  show (ECall f args) =
      '(' : show f ++ foldl (\acc x -> acc ++ (' ' : show x)) "" args ++ ")"
  show (ENamed x) = show x
  show (ELiteral x) = show x
  show (ESet x y) = show x ++ " = " ++ show y
  show (EGet x y) = show y ++ "." ++ show x
  show (EField x) = "." ++ show x
  show (EReturn x) = "return " ++ show x
  show (ECase (CaseExpr x es _)) =
    "case " ++ show x ++ " of " ++ l
    where
      l = mlace ", " (map (\(p, e) -> show p ++ " => " ++ show e) es)
  show (EIf (IfExpr c t e _)) =
    "if " ++ show c ++ " then " ++ show t ++ maybe "" ((" else " ++) . show) e
  show (ELet (LetExpr ds i _)) =
    "let " ++ defs ++ ins
    where
      defs = mlace ", " $ map (\(p, e) -> show p ++ " = " ++ show e) ds
      ins = maybe "" (\x -> " in (" ++ show x ++ ")") i
  show (ETuple x) = "(" ++ mlace ", " (map show x) ++ ")"