module sets
// Laurens Kuijper, s4467299
// Camil Staps, s4498062
import StdBool
import StdEnum
from StdFunc import const, id, o
import StdInt
import StdList
import StdOverloaded
import StdString
import Data.Error
from Data.Functor import class Functor(fmap)
import Data.List
import qualified Data.Map as M
import Data.Maybe
import Data.Tuple
from Text import class Text(concat), instance Text String
:: Ident :== String
:: Expr = Expr
:: Upd = Upd
:: Stmt = Stmt
:: In a b = (In) infix 0 a b
:: Do a b = (Do) infix 0 a b
class isExpr a :: a -> Bool
instance isExpr Expr where isExpr _ = True
instance isExpr Upd where isExpr _ = True
class Type t | toString, TC t
where
type :: t -> String
instance Type () where type _ = "()"
instance Type Int where type _ = "Int"
instance Type Char where type _ = "Char"
instance Type Bool where type _ = "Bool"
class DSL v | AExpr, BExpr, Compare, SetExpr, Var, Stmt v
class AExpr v
where
lit :: a -> v a Expr | Type a
(+.) infixl 6 :: (v t p) (v t q) -> v t Expr | Type, + t
(-.) infixl 6 :: (v t p) (v t q) -> v t Expr | Type, - t
(*.) infixl 7 :: (v t p) (v t q) -> v t Expr | Type, * t
(!~) :: (v t p) -> v t Expr | Type, ~ t
class BExpr v
where
(&&.) infixr 3 :: (v Bool p) (v Bool q) -> v Bool Expr
(||.) infixr 2 :: (v Bool p) (v Bool q) -> v Bool Expr
class Compare v
where
(==.) infix 4 :: (v t p) (v t q) -> v Bool Expr | Type, == t
(<.) infix 4 :: (v t p) (v t q) -> v Bool Expr | Type, < t
class SetExpr v
where
set :: [a] -> v [a] Expr | Type a
(:+) infix 5 :: (v t p) (v [t] q) -> v [t] Expr | Type, Eq t
(+:) infix 5 :: (v [t] p) (v t q) -> v [t] Expr | Type, Eq t
(-:) infix 5 :: (v [t] p) (v t q) -> v [t] Expr | Type, Eq t
(:+:) infixl 6 :: (v [t] p) (v [t] q) -> v [t] Expr | Type, Eq t
(:-:) infixl 6 :: (v [t] p) (v [t] q) -> v [t] Expr | Type, Eq t
(:*:) infixl 7 :: (v [t] p) (v [t] q) -> v [t] Expr | Type, Eq t
class Var v
where
var :: ((v t Upd) -> In t (v a p)) -> v a p | Type t
(=.) infixr 2 :: (v t Upd) (v t p) -> v t p | Type t & isExpr p
class Stmt v
where
If :: (v Bool p) (v t q) (v u r) -> v () Stmt
For :: ((v t Upd) -> Do (v [t] Expr) (v u a)) -> v () Stmt | Type t
(:.) infixl 1 :: (v t p) (v u q) -> v u Stmt
:: Show t s = Show (ShowState -> ShowState)
:: ShowState =
{ output :: [String]
, fresh :: Int
}
print :: (Show s t) -> String
print (Show s) = concat (s {output=[], fresh=1}).output
(<<) infixr 9 //:: (Show a p) (Show b q) -> Show c r
(<<) (Show f) (Show g) :== Show (f o g)
(-<) infixr 9; (-<) s f :== show s << f
show :: a -> Show b c | toString a
show x = Show \st -> {st & output=[toString x:st.output]}
between :: a b (Show t u) -> Show p q | toString a & toString b
between x y s = x -< s << show y
par :: (Show a p) -> Show b q
par s = between "(" ")" s
brace :: (Show a p) -> Show b q
brace s = between "{ " " }" s
showsperse :: a [Show b p] -> Show c q | toString a
showsperse _ [] = Show id
showsperse _ [Show x] = Show x
showsperse g [x:xs] = x << g -< showsperse g xs
instance AExpr Show
where
lit x = show x
(+.) x y = par (x << " +. " -< y)
(-.) x y = par (x << " -. " -< y)
(*.) x y = par (x << " *. " -< y)
(!~) x = "!~" -< par x
instance BExpr Show
where
(&&.) x y = par (x << " &&. " -< y)
(||.) x y = par (x << " ||. " -< y)
instance Compare Show
where
(==.) x y = par (x << " ==. " -< y)
(<.) x y = par (x << " <. " -< y)
instance SetExpr Show
where
set xs = between "[" "]" (showsperse "," (map show xs))
(:+) xs x = par (xs << " :+ " -< x)
(+:) x xs = par (x << " +: " -< xs)
(-:) xs x = par (xs << " -: " -< x)
(:+:) xs ys = par (xs << " :+: " -< ys)
(:-:) xs ys = par (xs << " :-: " -< ys)
(:*:) xs ys = par (xs << " :*: " -< ys)
instance Var Show
where
var x = Show \st -> let v = show ("v" +++ toString st.fresh) in case x v of
In x f -> case "var " -< v << " = " -< x -< " :.\n" -< f of
Show f -> f {st & fresh=st.fresh+1}
(=.) v x = v << " =. " -< x
instance Stmt Show
where
If b t e = "If " -< par b << " " -< brace t << " " -< brace e
For x = Show \st -> let v = show ("v" +++ toString st.fresh) in case x v of
Do s f -> case "For " -< v << " in " -< s << " do " -< brace f of
Show f -> f {st & fresh=st.fresh+1}
(:.) s t = s << " :.\n" -< t
:: Eval t s = Eval ((RW t) EvalState -> MaybeError String (t, EvalState))
:: RW t = R | W t
:: EvalState =
{ vars :: 'M'.Map Int Dynamic
, next :: Int
}
eval :: (Eval t s) -> MaybeError String (t, EvalState)
eval (Eval x) = x R {vars='M'.newMap, next=1}
(<$>) infixl 4 // :: (a -> b) (v t a) -> v u b
(<$>) f (Eval x) = Eval \_ st -> fmap (appFst f) (x R st)
pure :: a -> Eval a t
pure x = Eval \_ st -> Ok (x,st)
liftA2 :: (a b -> c) (Eval a t) (Eval b u) -> Eval c v
liftA2 f (Eval x) (Eval y) = Eval \_ st -> case x R st of
Ok (x0,st) -> case y R st of
Ok (y,st) -> Ok (f x0 y, st)
Error e -> Error e
Error e -> Error e
instance AExpr Eval
where
lit x = pure x
(+.) x y = liftA2 (+) x y
(-.) x y = liftA2 (-) x y
(*.) x y = liftA2 (*) x y
(!~) x = (~) <$> x
instance BExpr Eval
where
(&&.) x y = liftA2 (&&) x y
(||.) x y = liftA2 (||) x y
instance Compare Eval
where
(==.) x y = liftA2 (==) x y
(<.) x y = liftA2 (<) x y
addElem :: a [a] -> [a] | Eq a; addElem x xs = if (isMember x xs) xs [x:xs]
delElem :== removeMember
instance SetExpr Eval
where
set xs = pure xs
(:+) x xs = liftA2 addElem x xs
(+:) xs x = liftA2 addElem x xs
(-:) xs x = liftA2 delElem x xs
(:+:) xs ys = liftA2 union xs ys
(:*:) xs ys = liftA2 intersect xs ys
(:-:) xs ys = liftA2 difference xs ys
rwvar :: Int (RW a) (EvalState) -> MaybeError String (a, EvalState) | TC a
rwvar i R st = case 'M'.get i st.vars of
Just (v :: a^) -> Ok (v,st)
Just _ -> Error "Wrong type"
Nothing -> Error "Undefined variable"
rwvar i (W x) st = Ok (x, {st & vars='M'.put i (dynamic x) st.vars})
instance Var Eval
where
(=.) (Eval v) (Eval e) = Eval \_ st -> case e R st of
Ok (e,st) -> v (W e) st
Error e -> Error e
var f = Eval \_ st -> let (x In (Eval r)) = f (Eval (rwvar st.next)) in
r R {st & next=st.next+1, vars='M'.put st.next (dynamic x) st.vars}
instance Stmt Eval
where
If (Eval b) (Eval t) (Eval e) = Eval \_ st -> case b R st of
Ok (True, st) -> fmap (appFst (const ())) (t R st)
Ok (False,st) -> fmap (appFst (const ())) (e R st)
Error e -> Error e
For f = Eval \_ st -> let (xs Do b) = f (Eval (rwvar st.next)) in
let (Eval e) = for st.next xs b in e R {st & next=st.next+1}
where
for :: Int (Eval [a] Expr) (Eval b t) -> Eval () Stmt | TC a
for i (Eval s) (Eval b) = Eval \_ st -> case s R st of
Ok (xs,st) -> loop xs st
Error e -> Error e
where
loop :: [a] EvalState -> MaybeError String ((), EvalState) | TC a
loop [] st = Ok ((), st)
loop [x:xs] st = case b R {st & vars='M'.put i (dynamic x) st.vars} of
Ok (_,st) -> loop xs st
Error e -> Error e
(:.) (Eval s) (Eval t) = Eval \_ st -> case s R st of
Ok (s,st) -> t R st
Error e -> Error e
Start = (print stmt, '\n', eval stmt)
where
stmt :: v Int Stmt | DSL v
stmt =
var \y = 1 In (
For \x . set [1..10] Do
y =. y *. x
):.
y