module Flite.Compile (compile) where import Flite.Syntax import Flite.Flatten import Flite.CompileFrontend import Flite.CompileBackend import Data.List import Flite.Inline compile :: InlineFlag -> Prog -> String compile i p = program (addBool cs, p2) where p0 = frontend i p p1 = [(f, map getVar args, flatten rhs) | Func f args rhs <- p0] cs = nub $ concat [ctrs b | (_, _, bs) <- p1, b <- map snd bs] p2 = [ (funId f, length vs, [(v, map (toNode f p1) a) | (v, a) <- bs]) | (f, vs, bs) <- p1 ] addBool cs = insertIf (notDefined "False") false (insertIf (notDefined "True") true cs) where false = ("False", 0, 0) true = ("True", 0, 1) notDefined f cs = null [c | (c, _, _) <- cs, c == f] insertIf p x xs = if p xs then x:xs else xs toNode f p (Fun g) = case arities of [] -> FUN 2 (funId g) n:_ -> FUN n (funId g) where arities = [length args | (h, args, rhs) <- p, g == h] toNode f p (Var v) = case v `elemIndex` args of Nothing -> VAR v Just i -> ARG i where args = head [args | (g, args, rhs) <- p, f == g] toNode f p (Ctr c n i) = FUN (n+1) (funId c) toNode f p (Alts fs _) = FUN 0 (funId $ head fs) toNode f p (Int i) = INT i toNode f p Bottom = FUN 0 "_|_" funId f | '#' `elem` f = "ALT_" ++ map (tr '#' '_') f | otherwise = f tr :: Eq a => a -> a -> a -> a tr a b x = if a == x then b else x ctr :: Exp -> [Cons] ctr (Ctr c n i) = [(funId c, n, i)] ctr _ = [] ctrs :: [Exp] -> [Cons] ctrs = concatMap ctr getVar :: Exp -> String getVar (Var v) = v