- | insert a variable at this position. The expression value is inserted in the "where" section if it is not already
-- created. If the address of this object being parsed correspond with an address already parsed and
-- it is in the where section, then the same variable name is used
--   @runW showp (1::Int)                                -> "1"
--   runW (insertVar showp) (1::Int)                ->  v1 where { v1=1}
--   runW (insertVar showp) [(1::Int) ,1]        -> [v1.v1] where { v1=1}@
--   This is useful when the object is referenced many times

insertVar :: (a -> ST ()) -> a -> ST ()
insertVar parser x= ST(\(Stat(c,s,v))->
 let mf = trytofindEntireObject x c in
 case mf of
   Just  var ->  Right(Stat(c,s `append` " " `append` var,v),())
   Nothing ->
         let
            ST f= parser x
            Right (Stat (c',str,_), _) = f  (Stat(c,"",v))

         in Right(Stat(addc str c',s `append` (cons ' ' varname) ,v), ()))
 where
  addc str c= insert ( hash) (st,unsafeCoerce x,  str) c
  (hash,st) = hasht x
  varname=  pack$ "v" ++ show hash

  trytofindEntireObject x c=
         case Data.RefSerialize.Serialize.lookup  hash  c  of
           Nothing -> Nothing
           Just _  -> Just varname

-- | inform if the expression iwas already referenced and return @Right varname@
--  otherwise, add the expresion to the context and giive it a name and return  @Left varname@
-- The varname is not added to the serialized expression. The user must serialize it
-- This is usefu for expressions that admit different syntax depending or recursiviity, such are lists

insertVar :: (a -> ST ()) -> a -> ST ()
insertVar parser x= ST(\(Stat(c,s,v))->
 let mf = trytofindEntireObject x c in
 case mf of
   Just  var ->  Right(Stat(c,s `append` " " `append` var,v),())
   Nothing ->
         let
            ST f= parser x
            Right (Stat (c',str,_), _) = f  (Stat(c,"",v))

         in Right(Stat(addc str c',s `append` (cons ' ' varname) ,v), ()))
 where
  addc str c= insert ( hash) (st,unsafeCoerce x,  str) c
  (hash,st) = hasht x
  varname=  pack$ "v" ++ show hash

  trytofindEntireObject x c=
         case Data.RefSerialize.Serialize.lookup  hash  c  of
           Nothing -> Nothing
           Just _  -> Just varname

-- | inform if the expression iwas already referenced and return @Right varname@
--  otherwise, add the expresion to the context and giive it a name and return  @Left varname@
-- The varname is not added to the serialized expression. The user must serialize it
-- This is usefu for expressions that admit different syntax depending or recursiviity, such are lists
insertVar parser x= ST(\(Stat(c,s,v))->
 let mf = trytofindEntireObject x c in
 case mf of
   Just  var ->  Right(Stat(c,s `append` " " `append` var,v),())
   Nothing ->
         let
            ST f= parser x
            Right (Stat (c',str,_), _) = f  (Stat(c,"",v))

         in Right(Stat(addc str c',s `append` (cons ' ' varname) ,v), ()))
 where
  addc str c= insert ( hash) (st,unsafeCoerce x,  str) c
  (hash,st) = hasht x
  varname=  pack$ "v" ++ show hash

  trytofindEntireObject x c=
         case Data.RefSerialize.Serialize.lookup  hash  c  of
           Nothing -> Nothing
           Just _  -> Just varname

-- | inform if the expression iwas already referenced and return @Right varname@
--  otherwise, add the expresion to the context and giive it a name and return  @Left varname@
-- The varname is not added to the serialized expression. The user must serialize it
-- This is usefu for expressions that admit different syntax depending or recursiviity, such are lists