> module Edlib where

> import Type_defs

> import Core_datatype

> infixr 9 <:

> infixl 8 /// , />/ , /:>/ , /./ , /.>/, /.:>/, |||, |>|, |@|, |.|

> infixl 8 ..., ./., \\\

> infixl 1 `handle`, `ihandle`

>-- infixl 8 >>, >>>, *>>, *>>>, >>+, >>>+, *>>+, *>>>+, >>^, >>>^, *>>^, *>>>^





>-- type Xin = ( String , [Response] , [Int])
> type Xin = ( String , [Int] , [Int])

> type Xout = String
>-- type Xout = [Request]

> type Xio = ( Xin , Xout )

> type Xio_fn = Xin -> Xio

> type Xst a = ( Xin , a , Xout )

> type Xst_fn a = ( Xin , a ) -> ( Xin , a , Xout )


>--partain: id x = x




{- composition function to allow output fns to be written 'sequentially' -}

> (\\\) :: Xio -> Xio_fn -> Xio

> ( xin , xout ) \\\ g
>	= ( xin2 , xout ++ xout2 )
>         where
>	  ( xin2, xout2  ) = g xin
	

> (...) :: Xio_fn -> Xio_fn -> Xin -> Xio

> (...) f g xin
>	= f xin \\\ g


composition f - output fn, g - input fn with state (st)

> (./.) :: Xio_fn -> ( Xin -> Xst ( MayBe a b )) -> Xin -> Xst ( MayBe a b )

> (./.) f g xin
>	= ( xin2 , st, xout' ++ xout2 )
>         where
>         ( xin', xout' )  = f xin
>	  ( xin2, st, xout2  ) = g xin'


utility to apply a list of functions to a state

> app :: [ Xin -> Xio ] -> Xin -> Xio

> app ( fn : fns ) = fn ... app fns

> app [] =  \ xin -> ( xin , [] )




> --partain: (|||) :: MayBe a b -> ( a -> MayBe c d ) -> MayBe c d
> (|||) :: MayBe a b -> ( a -> MayBe c b ) -> MayBe c b

> ( Ok s ) ||| f
> 	= f s

> ( Bad mesg ) ||| f = Bad mesg






vanilla Maybe composed with IO fn

> s |.| f
> 	= case s of
>		Ok t    -> f t
>		Bad err -> return_err err






> ( Ok ( s , u )) |@| f
> 	= f s u

> ( Bad mesg ) |@| f = Bad mesg




> ( Ok ( s , u )) |>| f
>	= case f u of
>		Ok t    -> Ok (( s , t ) , u )
>		Bad err -> Bad err







> (///) :: Xst (MayBe a b) -> ( a -> Xin -> Xst (MayBe c b)) -> Xst (MayBe c b)

> x@( xin , st , xout ) /// f
>	= sendout x x'
>	  where
>	  x' = case st of
>	 	   Ok val   -> f val xin
>		   Bad mesg -> ( xin , Bad mesg , [] )




as above except second argument not fully evaluated

> (/./) :: (Xin -> Xst (MayBe a b)) -> ( a -> Xin -> Xst (MayBe c b))
>					           -> Xin -> Xst (MayBe c b)

> (/./) f g xin
>	= f xin /// g




> (/>/) :: Xst (MayBe a b) -> ( Xin -> Xst (MayBe c b)) -> Xst (MayBe (a,c) b)

> x1@( xin , st , xout ) />/ f
>	= sendout x1 x1'
>	  where
>	  x1' = case st of
>		  Ok val -> ( xin2, st2', xout2 )
>			    where
>			    st2' = case st2 of
>				    Ok val2  -> Ok ( val, val2 )
>				    Bad mesg -> Bad mesg
>		  Bad mesg -> ( xin, Bad mesg, [] )
>	  ( xin2, st2, xout2 ) = f xin





> (/.>/) :: (Xin -> Xst (MayBe a b)) -> ( Xin -> Xst (MayBe c b))
>					       -> Xin -> Xst (MayBe (a,c) b)

> (/.>/) f g xin
>	= f xin />/ g



as above except form list as state output rather than nested two tuples
(note, first read, first in list)


> x1@( xin , st , xout ) /:>/ f
>	= sendout x1 x1'
>	  where
>	  x1' = case st of
>		  Ok val -> ( xin2, st2', xout2 )
>			    where
>			    st2' = case st2 of
>				    Ok val2  -> Ok ( val : val2 )
>				    Bad mesg -> Bad mesg
>		  Bad mesg -> ( xin, Bad mesg, [] )
>	  ( xin2, st2, xout2 ) = f xin



> (/.:>/) :: (Xin -> Xst (MayBe a b)) -> ( Xin -> Xst (MayBe [a] b))
>					       -> Xin -> Xst (MayBe [a] b)

> (/.:>/) f g xin
>	= f xin /:>/ g


error handler

> handle f handler xin
>	= f xin `ihandle` handler

> ihandle x@( xin , st , _ ) handler
>	= sendout x x'
>	  where
>	  x' = case st of
>		  Ok val   -> ( xin, Ok val, [] )
>		  Bad mesg -> handler mesg xin






push non-MayBe Xio fn into valid MayBe result with unused non-xio
result

> mk_ok x_fn arg
>	= Ok ( x_fn arg )



split a list on a given element

> split :: ( Eq a ) => a -> [a] -> [[a]]

> split c ( a : x )
>	| a == c = [] : split c x
>	| a /= c = case split c x of
>			b : y -> ( a : b ) : y
>			[]    -> [[a]]

> split _ [] = []



append a character to the end of a list

> (<:) :: [a] -> a -> [a]

> l <: c = l ++ [c]






> sendout ( _, _, xout ) x
>	= ( xin, st, xout ++ xout2 )
>	  where
>	  ( xin, st, xout2 ) = x



> return_val st xin = ( xin , st , [] )

> return_err st xin = ( xin, Bad st , [] )

> reTurn st xin = ( xin, Ok st, [] )



> genuid ( ins , rsps , ( gno : gnoL ) )
>	= ( ( ins , rsps , gnoL ) , Ok ( show gno ) , [] )











parsing functions



>{-

> ( f >> g )
> 	= next_tk f /./ ( next_tk . g )

> ( f >>> g)
>	= next_tk f /:>/ next_tk g


> ( f *>> g )
>	= f >> ( g . discard_tk )

> ( f *>>> g)
>	= f >>> ( g . discard_tk )




> ( f >>+ g )
>	= ( \ tk -> f tk /./ pst_extend ) >> g

> ( f >>>+ g )
>	= ( \ tk -> f tk /./ pst_extend ) >>> g

> ( f *>>+ g )
>	= ( \ tk -> f tk /./ pst_extend ) *>> g

> ( f *>>>+ g )
>	= ( \ tk -> f tk /./ pst_extend ) *>>> g





> ( f >>^ g )
>	= f >> ( g . pst_retract )

> ( f >>>^ g )
>	= f >>> ( g . pst_retract )

> ( f *>>^ g )
>	= f *>> ( g . pst_retract )

> ( f *>>>^ g )
>	= f *>>> ( g . pst_retract )





> next_tk f ( tk : tkL, pst, xin )
>	= f tk ( tkL, pst, xin )

> next_tk _ st@( [] , _ , _ )
>	= return_err "Unexpected end of input" st






> discard_tk ( _ : tkL , pst , xin )
>	= ( tkL , pst , xin )

> discard_tk st@( [] , _ , _ ) = st





> pst_retract ( tkL , (tgL, Extend _ isg _ ), xin )
>	= ( tkL, (tgL, isg), xin )

> pst_retract _ = error "pst_retract on empty sg -- impossible"






> pst_extend resL st
>	= pst_extend' resL st ./.
>	  return resL




> pst_extend' ( Opnd ( Idec idc ) : _ ) ( tkL, ( tgL, isg ), xin )
>	= ( tkL, ( tgL, Extend idc isg [] ), xin )

> pst_extend' ( _ : resL )
>	= pst_extend' resL

> pst_extend' []
>	= return_err "No dc with which to extend sg"




>-}
