on fddebca help sign in
Idris-dev/src/IRTS/Lang.hs
234 lines 9.8 kB history raw
1module IRTS.Lang where
3import Control.Monad.State hiding (lift)
4import Core.TT
5import Data.List
6import Debug.Trace
8data LVar = Loc Int | Glob Name
9 deriving (Show, Eq)
11data LExp = LV LVar
12 | LApp Bool LExp [LExp] -- True = tail call
13 | LLazyApp Name [LExp] -- True = tail call
14 | LLazyExp LExp
15 | LForce LExp -- make sure Exp is evaluted
16 | LLet Name LExp LExp -- name just for pretty printing
17 | LLam [Name] LExp -- lambda, lifted out before compiling
18 | LProj LExp Int -- projection
19 | LCon Int Name [LExp]
20 | LCase LExp [LAlt]
21 | LConst Const
22 | LForeign FLang FType String [(FType, LExp)]
23 | LOp PrimFn [LExp]
24 | LNothing
25 | LError String
26 deriving Eq
28-- Primitive operators. Backends are not *required* to implement all
29-- of these, but should report an error if they are unable
31data PrimFn = LPlus ArithTy | LMinus ArithTy | LTimes ArithTy
32 | LUDiv IntTy | LSDiv ArithTy | LURem IntTy | LSRem ArithTy
33 | LAnd IntTy | LOr IntTy | LXOr IntTy | LCompl IntTy
34 | LSHL IntTy | LLSHR IntTy | LASHR IntTy
35 | LEq ArithTy | LLt IntTy | LLe IntTy | LGt IntTy | LGe IntTy
36 | LSLt ArithTy | LSLe ArithTy | LSGt ArithTy | LSGe ArithTy
37 | LSExt IntTy IntTy | LZExt IntTy IntTy | LTrunc IntTy IntTy
38 | LStrConcat | LStrLt | LStrEq | LStrLen
39 | LIntFloat IntTy | LFloatInt IntTy | LIntStr IntTy | LStrInt IntTy
40 | LFloatStr | LStrFloat | LChInt IntTy | LIntCh IntTy
41 | LPrintNum | LPrintStr | LReadStr
42 | LBitCast ArithTy ArithTy -- Only for values of equal width
44 | LFExp | LFLog | LFSin | LFCos | LFTan | LFASin | LFACos | LFATan
45 | LFSqrt | LFFloor | LFCeil
47 -- construction element extraction element insertion
48 | LMkVec NativeTy Int | LIdxVec NativeTy Int | LUpdateVec NativeTy Int
50 | LStrHead | LStrTail | LStrCons | LStrIndex | LStrRev
51 | LStdIn | LStdOut | LStdErr
53 | LFork
54 | LPar -- evaluate argument anywhere, possibly on another
55 -- core or another machine. 'id' is a valid implementation
56 | LVMPtr
57 | LNoOp
58 deriving (Show, Eq)
60-- Supported target languages for foreign calls
62data FCallType = FStatic | FObject | FConstructor
63 deriving (Show, Eq)
65data FLang = LANG_C | LANG_JAVA FCallType
66 deriving (Show, Eq)
68data FType = FArith ArithTy
69 | FFunction
70 | FFunctionIO
71 | FString
72 | FUnit
73 | FPtr
74 | FAny
75 deriving (Show, Eq)
77data LAlt = LConCase Int Name [Name] LExp
78 | LConstCase Const LExp
79 | LDefaultCase LExp
80 deriving (Show, Eq)
82data LDecl = LFun [LOpt] Name [Name] LExp -- options, name, arg names, def
83 | LConstructor Name Int Int -- constructor name, tag, arity
84 deriving (Show, Eq)
86type LDefs = Ctxt LDecl
88data LOpt = Inline | NoInline
89 deriving (Show, Eq)
91addTags :: Int -> [(Name, LDecl)] -> (Int, [(Name, LDecl)])
92addTags i ds = tag i ds []
93 where tag i ((n, LConstructor n' (-1) a) : as) acc
94 = tag (i + 1) as ((n, LConstructor n' i a) : acc)
95 tag i ((n, LConstructor n' t a) : as) acc
96 = tag i as ((n, LConstructor n' t a) : acc)
97 tag i (x : as) acc = tag i as (x : acc)
98 tag i [] acc = (i, reverse acc)
100data LiftState = LS Name Int [(Name, LDecl)]
102lname (NS n x) i = NS (lname n i) x
103lname (UN n) i = MN i n
104lname x i = MN i (show x)
106liftAll :: [(Name, LDecl)] -> [(Name, LDecl)]
107liftAll xs = concatMap (\ (x, d) -> lambdaLift x d) xs
109lambdaLift :: Name -> LDecl -> [(Name, LDecl)]
110lambdaLift n (LFun _ _ args e)
111 = let (e', (LS _ _ decls)) = runState (lift args e) (LS n 0 []) in
112 (n, LFun [] n args e') : decls
113lambdaLift n x = [(n, x)]
115getNextName :: State LiftState Name
116getNextName = do LS n i ds <- get
117 put (LS n (i + 1) ds)
118 return (lname n i)
120addFn :: Name -> LDecl -> State LiftState ()
121addFn fn d = do LS n i ds <- get
122 put (LS n i ((fn, d) : ds))
124lift :: [Name] -> LExp -> State LiftState LExp
125lift env (LV v) = return (LV v) -- Lifting happens before these can exist...
126lift env (LApp tc (LV (Glob n)) args) = do args' <- mapM (lift env) args
127 return (LApp tc (LV (Glob n)) args')
128lift env (LApp tc f args) = do f' <- lift env f
129 fn <- getNextName
130 addFn fn (LFun [Inline] fn env f')
131 args' <- mapM (lift env) args
132 return (LApp tc (LV (Glob fn)) (map (LV . Glob) env ++ args'))
133lift env (LLazyApp n args) = do args' <- mapM (lift env) args
134 return (LLazyApp n args')
135lift env (LLazyExp (LConst c)) = return (LConst c)
136-- lift env (LLazyExp (LApp tc (LV (Glob f)) args))
137-- = lift env (LLazyApp f args)
138lift env (LLazyExp e) = do e' <- lift env e
139 let usedArgs = nub $ usedIn env e'
140 fn <- getNextName
141 addFn fn (LFun [NoInline] fn usedArgs e')
142 return (LLazyApp fn (map (LV . Glob) usedArgs))
143lift env (LForce e) = do e' <- lift env e
144 return (LForce e')
145lift env (LLet n v e) = do v' <- lift env v
146 e' <- lift (env ++ [n]) e
147 return (LLet n v' e')
148lift env (LLam args e) = do e' <- lift (env ++ args) e
149 let usedArgs = nub $ usedIn env e'
150 fn <- getNextName
151 addFn fn (LFun [Inline] fn (usedArgs ++ args) e')
152 return (LApp False (LV (Glob fn)) (map (LV . Glob) usedArgs))
153lift env (LProj t i) = do t' <- lift env t
154 return (LProj t' i)
155lift env (LCon i n args) = do args' <- mapM (lift env) args
156 return (LCon i n args')
157lift env (LCase e alts) = do alts' <- mapM liftA alts
158 e' <- lift env e
159 return (LCase e' alts')
160 where
161 liftA (LConCase i n args e) = do e' <- lift (env ++ args) e
162 return (LConCase i n args e')
163 liftA (LConstCase c e) = do e' <- lift env e
164 return (LConstCase c e')
165 liftA (LDefaultCase e) = do e' <- lift env e
166 return (LDefaultCase e')
167lift env (LConst c) = return (LConst c)
168lift env (LForeign l t s args) = do args' <- mapM (liftF env) args
169 return (LForeign l t s args')
170 where
171 liftF env (t, e) = do e' <- lift env e
172 return (t, e')
173lift env (LOp f args) = do args' <- mapM (lift env) args
174 return (LOp f args')
175lift env (LError str) = return $ LError str
176lift env LNothing = return $ LNothing
178-- Return variables in list which are used in the expression
180usedArg env n | n `elem` env = [n]
181 | otherwise = []
183usedIn :: [Name] -> LExp -> [Name]
184usedIn env (LV (Glob n)) = usedArg env n
185usedIn env (LApp _ e args) = usedIn env e ++ concatMap (usedIn env) args
186usedIn env (LLazyApp n args) = concatMap (usedIn env) args ++ usedArg env n
187usedIn env (LLazyExp e) = usedIn env e
188usedIn env (LForce e) = usedIn env e
189usedIn env (LLet n v e) = usedIn env v ++ usedIn (env \\ [n]) e
190usedIn env (LLam ns e) = usedIn (env \\ ns) e
191usedIn env (LCon i n args) = concatMap (usedIn env) args
192usedIn env (LProj t i) = usedIn env t
193usedIn env (LCase e alts) = usedIn env e ++ concatMap (usedInA env) alts
194 where usedInA env (LConCase i n ns e) = usedIn env e
195 usedInA env (LConstCase c e) = usedIn env e
196 usedInA env (LDefaultCase e) = usedIn env e
197usedIn env (LForeign _ _ _ args) = concatMap (usedIn env) (map snd args)
198usedIn env (LOp f args) = concatMap (usedIn env) args
199usedIn env _ = []
201instance Show LExp where
202 show e = show' [] e where
203 show' env (LV (Loc i)) = env!!i
204 show' env (LV (Glob n)) = show n
205 show' env (LLazyApp e args) = show e ++ "|(" ++
206 showSep ", " (map (show' env) args) ++")"
207 show' env (LApp _ e args) = show' env e ++ "(" ++
208 showSep ", " (map (show' env) args) ++")"
209 show' env (LLazyExp e) = "%lazy(" ++ show' env e ++ ")"
210 show' env (LForce e) = "%force(" ++ show' env e ++ ")"
211 show' env (LLet n v e) = "let " ++ show n ++ " = " ++ show' env v ++ " in " ++
212 show' (env ++ [show n]) e
213 show' env (LLam args e) = "\\ " ++ showSep "," (map show args) ++ " => " ++
214 show' (env ++ (map show args)) e
215 show' env (LProj t i) = show t ++ "!" ++ show i
216 show' env (LCon i n args) = show n ++ ")" ++ showSep ", " (map (show' env) args) ++ ")"
217 show' env (LCase e alts) = "case " ++ show' env e ++ " of {\n\t" ++
218 showSep "\n\t| " (map (showAlt env) alts)
219 show' env (LConst c) = show c
220 show' env (LForeign lang ty n args)
221 = "foreign " ++ n ++ "(" ++ showSep ", " (map (show' env) (map snd args)) ++ ")"
222 show' env (LOp f args) = show f ++ "(" ++ showSep ", " (map (show' env) args) ++ ")"
223 show' env (LError str) = "error " ++ show str
224 show' env LNothing = "____"
226 showAlt env (LConCase _ n args e)
227 = show n ++ "(" ++ showSep ", " (map show args) ++ ") => "
228 ++ show' env e
229 showAlt env (LConstCase c e) = show c ++ " => " ++ show' env e
230 showAlt env (LDefaultCase e) = "_ => " ++ show' env e