module Language.Lean.Internal.Expr
  ( 
    MacroDef
  , MacroDefPtr
  , OutMacroDefPtr
  , withMacroDef
    
  , Expr
  , ExprPtr
  , OutExprPtr
  , withExpr
  , exprLt
  , exprToString
  , BinderKind(..)
    
  , ListExpr
  , ListExprPtr
  , OutListExprPtr
  , withListExpr
  ) where
import Control.Lens (toListOf)
import Foreign
import Foreign.C
import System.IO.Unsafe
import Language.Lean.List
import Language.Lean.Internal.Exception
import Language.Lean.Internal.Exception.Unsafe
newtype MacroDef = MacroDef (ForeignPtr MacroDef)
withMacroDef :: MacroDef -> (Ptr MacroDef -> IO a) -> IO a
withMacroDef (MacroDef o) = withForeignPtr $! o
type MacroDefPtr = Ptr (MacroDef)
type OutMacroDefPtr = Ptr (MacroDefPtr)
instance IsLeanValue MacroDef (Ptr MacroDef) where
  mkLeanValue = fmap MacroDef . newForeignPtr lean_macro_def_del_ptr
foreign import ccall unsafe "&lean_macro_def_del"
  lean_macro_def_del_ptr :: FunPtr (MacroDefPtr -> IO ())
instance Eq MacroDef where
  (==) = error "Equality comparison with macro definitions is not yet implemented."
instance Show MacroDef where
  show = error "MacroDef.show not yet implement"
data BinderKind = BinderDefault
                | BinderImplicit
                | BinderStrictImplicit
                | BinderInstImplicit
                | BinderHidden
  deriving (Enum,Eq,Show)
newtype Expr = Expr (ForeignPtr Expr)
withExpr :: Expr -> (Ptr Expr -> IO a) -> IO a
withExpr (Expr o) = withForeignPtr $! o
type ExprPtr = Ptr (Expr)
type OutExprPtr = Ptr (ExprPtr)
instance IsLeanValue Expr (Ptr Expr) where
  mkLeanValue = fmap Expr . newForeignPtr lean_expr_del_ptr
foreign import ccall unsafe "&lean_expr_del"
  lean_expr_del_ptr :: FunPtr (ExprPtr -> IO ())
newtype instance List Expr = ListExpr (ForeignPtr (List Expr))
type ListExpr = List Expr
withListExpr :: List Expr -> (Ptr (List Expr) -> IO a) -> IO a
withListExpr (ListExpr p) = withForeignPtr $! p
type ListExprPtr = Ptr (ListExpr)
type OutListExprPtr = Ptr (ListExprPtr)
instance IsLeanValue (List Expr) (Ptr (List Expr)) where
  mkLeanValue = fmap ListExpr . newForeignPtr lean_list_expr_del_ptr
foreign import ccall unsafe "&lean_list_expr_del"
  lean_list_expr_del_ptr :: FunPtr (ListExprPtr -> IO ())
exprToString :: Expr -> String
exprToString x = tryGetLeanValue $ lean_expr_to_string x
instance Show Expr where
  show = show . exprToString
lean_expr_to_string :: (Expr) -> (Ptr CString) -> (OutExceptionPtr) -> IO ((Bool))
lean_expr_to_string a1 a2 a3 =
  (withExpr) a1 $ \a1' -> 
  let {a2' = id a2} in 
  let {a3' = id a3} in 
  lean_expr_to_string'_ a1' a2' a3' >>= \res ->
  let {res' = toBool res} in
  return (res')
instance Eq Expr where
  x == y = tryGetLeanValue $ lean_expr_eq x y
lean_expr_eq :: (Expr) -> (Expr) -> (Ptr CInt) -> (OutExceptionPtr) -> IO ((Bool))
lean_expr_eq a1 a2 a3 a4 =
  (withExpr) a1 $ \a1' -> 
  (withExpr) a2 $ \a2' -> 
  let {a3' = id a3} in 
  let {a4' = id a4} in 
  lean_expr_eq'_ a1' a2' a3' a4' >>= \res ->
  let {res' = toBool res} in
  return (res')
instance Ord Expr where
   x <= y = not $ tryGetLeanValue $ lean_expr_quick_lt y x
lean_expr_quick_lt :: (Expr) -> (Expr) -> (Ptr CInt) -> (OutExceptionPtr) -> IO ((Bool))
lean_expr_quick_lt a1 a2 a3 a4 =
  (withExpr) a1 $ \a1' -> 
  (withExpr) a2 $ \a2' -> 
  let {a3' = id a3} in 
  let {a4' = id a4} in 
  lean_expr_quick_lt'_ a1' a2' a3' a4' >>= \res ->
  let {res' = toBool res} in
  return (res')
exprLt :: Expr -> Expr -> Bool
exprLt x y = tryGetLeanValue $ lean_expr_lt x y
lean_expr_lt :: (Expr) -> (Expr) -> (Ptr CInt) -> (OutExceptionPtr) -> IO ((Bool))
lean_expr_lt a1 a2 a3 a4 =
  (withExpr) a1 $ \a1' -> 
  (withExpr) a2 $ \a2' -> 
  let {a3' = id a3} in 
  let {a4' = id a4} in 
  lean_expr_lt'_ a1' a2' a3' a4' >>= \res ->
  let {res' = toBool res} in
  return (res')
instance Eq (List Expr) where
  (==) = lean_list_expr_eq
lean_list_expr_eq :: (ListExpr) -> (ListExpr) -> (Bool)
lean_list_expr_eq a1 a2 =
  unsafePerformIO $
  (withListExpr) a1 $ \a1' -> 
  (withListExpr) a2 $ \a2' -> 
  let {res = lean_list_expr_eq'_ a1' a2'} in
  let {res' = toBool res} in
  return (res')
instance IsListIso (List Expr) where
  nil = tryGetLeanValue $ lean_list_expr_mk_nil
  h <| r = tryGetLeanValue $ lean_list_expr_mk_cons h r
  listView l =
    if lean_list_expr_is_cons l then
      tryGetLeanValue (lean_list_expr_head l)
        :< tryGetLeanValue (lean_list_expr_tail l)
    else
      Nil
lean_list_expr_mk_nil :: (OutListExprPtr) -> (OutExceptionPtr) -> IO ((Bool))
lean_list_expr_mk_nil a1 a2 =
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  lean_list_expr_mk_nil'_ a1' a2' >>= \res ->
  let {res' = toBool res} in
  return (res')
lean_list_expr_mk_cons :: (Expr) -> (ListExpr) -> (OutListExprPtr) -> (OutExceptionPtr) -> IO ((Bool))
lean_list_expr_mk_cons a1 a2 a3 a4 =
  (withExpr) a1 $ \a1' -> 
  (withListExpr) a2 $ \a2' -> 
  let {a3' = id a3} in 
  let {a4' = id a4} in 
  lean_list_expr_mk_cons'_ a1' a2' a3' a4' >>= \res ->
  let {res' = toBool res} in
  return (res')
lean_list_expr_is_cons :: (ListExpr) -> (Bool)
lean_list_expr_is_cons a1 =
  unsafePerformIO $
  (withListExpr) a1 $ \a1' -> 
  let {res = lean_list_expr_is_cons'_ a1'} in
  let {res' = toBool res} in
  return (res')
lean_list_expr_head :: (ListExpr) -> (OutExprPtr) -> (OutExceptionPtr) -> IO ((Bool))
lean_list_expr_head a1 a2 a3 =
  (withListExpr) a1 $ \a1' -> 
  let {a2' = id a2} in 
  let {a3' = id a3} in 
  lean_list_expr_head'_ a1' a2' a3' >>= \res ->
  let {res' = toBool res} in
  return (res')
lean_list_expr_tail :: (ListExpr) -> (OutListExprPtr) -> (OutExceptionPtr) -> IO ((Bool))
lean_list_expr_tail a1 a2 a3 =
  (withListExpr) a1 $ \a1' -> 
  let {a2' = id a2} in 
  let {a3' = id a3} in 
  lean_list_expr_tail'_ a1' a2' a3' >>= \res ->
  let {res' = toBool res} in
  return (res')
instance IsList (List Expr) where
  type Item ListExpr = Expr
  fromList = fromListDefault
  toList = toListOf traverseList
instance Show (List Expr) where
  showsPrec _ l = showList (toList l)
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_expr_to_string"
  lean_expr_to_string'_ :: ((ExprPtr) -> ((Ptr (Ptr CChar)) -> ((OutExceptionPtr) -> (IO CInt))))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_expr_eq"
  lean_expr_eq'_ :: ((ExprPtr) -> ((ExprPtr) -> ((Ptr CInt) -> ((OutExceptionPtr) -> (IO CInt)))))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_expr_quick_lt"
  lean_expr_quick_lt'_ :: ((ExprPtr) -> ((ExprPtr) -> ((Ptr CInt) -> ((OutExceptionPtr) -> (IO CInt)))))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_expr_lt"
  lean_expr_lt'_ :: ((ExprPtr) -> ((ExprPtr) -> ((Ptr CInt) -> ((OutExceptionPtr) -> (IO CInt)))))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_list_expr_eq"
  lean_list_expr_eq'_ :: ((ListExprPtr) -> ((ListExprPtr) -> CInt))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_list_expr_mk_nil"
  lean_list_expr_mk_nil'_ :: ((OutListExprPtr) -> ((OutExceptionPtr) -> (IO CInt)))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_list_expr_mk_cons"
  lean_list_expr_mk_cons'_ :: ((ExprPtr) -> ((ListExprPtr) -> ((OutListExprPtr) -> ((OutExceptionPtr) -> (IO CInt)))))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_list_expr_is_cons"
  lean_list_expr_is_cons'_ :: ((ListExprPtr) -> CInt)
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_list_expr_head"
  lean_list_expr_head'_ :: ((ListExprPtr) -> ((OutExprPtr) -> ((OutExceptionPtr) -> (IO CInt))))
foreign import ccall unsafe "Language/Lean/Internal/Expr.chs.h lean_list_expr_tail"
  lean_list_expr_tail'_ :: ((ListExprPtr) -> ((OutListExprPtr) -> ((OutExceptionPtr) -> (IO CInt))))