things
[clean-tests.git] / dsl / dsl.icl
diff --git a/dsl/dsl.icl b/dsl/dsl.icl
new file mode 100644 (file)
index 0000000..d8dd42e
--- /dev/null
@@ -0,0 +1,164 @@
+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)