+module dsl
+
+import StdEnv
+
+import Data.Func => qualified app
+import Data.Functor
+import Data.Either
+import Data.GenEq
+import Data.Functor.Identity
+import Control.Applicative
+import Control.Monad => qualified join
+import Text
+
+import Text.Parsers.Simple.Core
+
+class Symantics v where
+ int :: Int -> v Int
+ bool :: Bool -> v Bool
+ lam :: ((v a) -> v b) -> v (a -> b)
+ app :: (v (a -> b)) (v a) -> v b
+ Fix :: ((v a) -> (v a)) -> v a
+ add :: (v a) (v a) -> v a | + a
+ mul :: (v a) (v a) -> v a | * a
+ leq :: (v a) (v a) -> v Bool | Ord a
+ If :: (v Bool) (v a) (v a) -> v a
+
+//Run the object
+:: Run a = Run a
+runRun (Run a) = a
+instance Functor Run where fmap f a = Run $ f $ runRun a
+instance pure Run where pure a = Run a
+instance <*> Run where <*> a b = Run $ runRun a $ runRun b
+instance Symantics Run where
+ int a = pure a
+ bool a = pure a
+ lam f = pure $ runRun o f o Run
+ app f a = f <*> a
+ Fix f = pure $ let x = runRun $ f $ pure x in x
+ add a b = (+) <$> a <*> b
+ mul a b = (*) <$> a <*> b
+ leq a b = (<=) <$> a <*> b
+ If i t e = if` <$> i <*> t <*> e
+
+//Length of the object
+:: Length a = Length Int
+runLength (Length i) = i
+(+.) infixl 6
+(+.) (Length a) (Length b) = Length $ a + b
+instance one (Length a) where one = Length 1
+instance zero (Length a) where zero = Length 0
+instance Symantics Length where
+ int _ = one
+ bool _ = one
+ lam f = f zero +. one
+ app f a = f +. a +. one
+ Fix f = f zero +. one
+ add a b = a +. b +. one
+ mul a b = a +. b +. one
+ leq a b = a +. b +. one
+ If i t e = i +. t +. e +. one
+
+//Print the object
+:: Print a = Print (Int [String] -> [String])
+runPrint (Print a) = a
+print a = concat $ runPrint a 0 []
+var i = "v" +++ toString i
+show a = Print \_ c->[toString a:c]
+binop op (Print a) (Print b) = Print \i c->["(":a i [op: b i [")":c]]]
+instance Symantics Print where
+ int a = show a
+ bool a = show a
+ lam f = Print \i c->["(\\", var i, ".":runPrint (f $ show $ var i) (i+1) [")":c]]
+ app f a = Print \i c->["(":runPrint f i [" ":runPrint a i [")":c]]]
+ Fix f = Print \i c->["fix (\\","self.":runPrint (f $ show "self") (i+1) [")":c]]
+ add a b = binop "+" a b
+ mul a b = binop "*" a b
+ leq a b = binop "<=" a b
+ If p t e = Print \i c->["if ":runPrint p i [" then ":runPrint t i [" else ":runPrint e i c]]]
+
+//Parsing
+:: Token = IntToken Int | BoolToken Bool | BrackOpenToken | BrackCloseToken | LeqToken | AddToken | MulToken | IfToken
+derive gEq Token
+instance == Token where == a b = a === b
+
+lex :: [Char] -> Either [String] [Token]
+lex [] = Right []
+lex [')':cs] = clex cs BrackCloseToken
+lex ['(':cs] = clex cs BrackOpenToken
+lex ['<=':cs] = clex cs LeqToken
+lex ['+':cs] = clex cs AddToken
+lex ['*':cs] = clex cs MulToken
+lex ['True':cs] = clex cs $ BoolToken True
+lex ['False':cs] = clex cs $ BoolToken False
+lex ['-',c:cs]
+ | isDigit c = lex [c:cs] >>= \v->case v of
+ [IntToken i:rest] = Right [IntToken (~i):rest]
+ x = pure x
+lex [c:cs]
+ | isSpace c = lex cs
+ | isDigit c
+ # (d, cs) = span isDigit [c:cs]
+ = clex cs $ IntToken $ toInt $ toString d
+ = Left ["Unexpected: " +++ toString c +++ " ord: " +++ toString (toInt c)]
+
+clex :: [Char] Token -> Either [String] [Token]
+clex cs t = (\ts->[t:ts]) <$> lex cs
+
+class parseSym a where
+ parseSym :: Parser Token (v a) | Symantics v
+instance parseSym Int where
+ parseSym
+ = flip pChainl1 (add <$ pToken AddToken)
+ $ flip pChainl1 (mul <$ pToken MulToken)
+ $ pToken BrackOpenToken *> parseSym <* pToken BrackCloseToken
+ <|> If <$ pToken IfToken <*> parseSym <*> parseSym <*> parseSym
+ <|> int <$> pInt
+ where
+ pInt = pSatisfy (\t->t=:(IntToken _)) >>= \(IntToken i)->pure i
+instance parseSym Bool where
+ parseSym
+ = leq <$> parseSymInt <* pToken LeqToken <*> parseSymInt
+ <|> If <$ pToken IfToken <*> parseSym <*> parseSym <*> parseSym
+ <|> pToken BrackOpenToken *> parseSym <* pToken BrackCloseToken
+ <|> bool <$> pBool
+ where
+ pBool = pSatisfy (\t->t=:(BoolToken _)) >>= \(BoolToken b)->pure b
+
+ parseSymInt :: Parser Token (v Int) | Symantics v
+ parseSymInt = parseSym
+
+Start = print <$> exp
+where
+ exp :: Either [String] (v Bool) | Symantics v
+ exp = lex (fromString inp) >>= parse parseSym
+
+ inp = "1+2*3 <= 42*42"
+//Start =
+// [ toString $ runRun fourtytwo
+// , print fourtytwo
+// , toString $ runRun true
+// , print true
+// , toString $ runRun powfix33
+// , print powfix33
+// , toString $ runRun factfix5
+// , print factfix5
+// ]
+
+fourtytwo :: v Int | Symantics v
+fourtytwo = add (int 38) (int 4)
+
+true :: v Bool | Symantics v
+true = app (lam (\x->x)) (bool True)
+
+powfix = lam \x->Fix \self->lam \n->
+ If (leq n (int 0)) (int 1)
+ (mul x (app self (add n (int -1))))
+
+powfix33 = app (app powfix (int 3)) (int 3)
+
+factfix = Fix \self->lam \n->
+ If (leq n (int 0)) (int 1)
+ (mul n (app self (add n (int -1))))
+
+factfix5 = app factfix (int 5)