diff options
-rw-r--r-- | lambdacube-compiler.cabal | 6 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/CGExp.hs | 276 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/CoreToGLSL.hs | 357 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/CoreToIR.hs | 611 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/Driver.hs | 11 | ||||
-rw-r--r-- | test/runTests.hs | 1 |
6 files changed, 612 insertions, 650 deletions
diff --git a/lambdacube-compiler.cabal b/lambdacube-compiler.cabal index 4c43bf99..aa5ac44d 100644 --- a/lambdacube-compiler.cabal +++ b/lambdacube-compiler.cabal | |||
@@ -19,13 +19,11 @@ Flag profiling | |||
19 | library | 19 | library |
20 | exposed-modules: | 20 | exposed-modules: |
21 | -- Compiler | 21 | -- Compiler |
22 | LambdaCube.Compiler.Token | ||
22 | LambdaCube.Compiler.Pretty | 23 | LambdaCube.Compiler.Pretty |
23 | LambdaCube.Compiler.CoreToIR | ||
24 | LambdaCube.Compiler.CoreToGLSL | ||
25 | LambdaCube.Compiler.Infer | 24 | LambdaCube.Compiler.Infer |
26 | LambdaCube.Compiler.CGExp | 25 | LambdaCube.Compiler.CoreToIR |
27 | LambdaCube.Compiler.Driver | 26 | LambdaCube.Compiler.Driver |
28 | LambdaCube.Compiler.Token | ||
29 | other-extensions: | 27 | other-extensions: |
30 | LambdaCase | 28 | LambdaCase |
31 | PatternSynonyms | 29 | PatternSynonyms |
diff --git a/src/LambdaCube/Compiler/CGExp.hs b/src/LambdaCube/Compiler/CGExp.hs deleted file mode 100644 index b2f19c9f..00000000 --- a/src/LambdaCube/Compiler/CGExp.hs +++ /dev/null | |||
@@ -1,276 +0,0 @@ | |||
1 | {-# LANGUAGE LambdaCase #-} | ||
2 | {-# LANGUAGE ViewPatterns #-} | ||
3 | {-# LANGUAGE PatternSynonyms #-} | ||
4 | {-# LANGUAGE FlexibleContexts #-} | ||
5 | {-# LANGUAGE FlexibleInstances #-} | ||
6 | {-# LANGUAGE NoMonomorphismRestriction #-} | ||
7 | {-# LANGUAGE DeriveFunctor #-} | ||
8 | {-# LANGUAGE DeriveFoldable #-} | ||
9 | {-# LANGUAGE DeriveTraversable #-} | ||
10 | {-# LANGUAGE RecursiveDo #-} | ||
11 | module LambdaCube.Compiler.CGExp where | ||
12 | |||
13 | import Control.Monad.Reader | ||
14 | import Control.Monad.State | ||
15 | import Control.Monad.Except | ||
16 | import Control.Monad.Identity | ||
17 | import Control.Monad.Writer | ||
18 | import Control.Arrow | ||
19 | import qualified Data.Set as S | ||
20 | import qualified Data.Map as M | ||
21 | import Text.Parsec.Pos | ||
22 | import Debug.Trace | ||
23 | |||
24 | import LambdaCube.Compiler.Pretty | ||
25 | import qualified LambdaCube.Compiler.Infer as I | ||
26 | import LambdaCube.Compiler.Infer (SName, Lit(..), Visibility(..)) | ||
27 | |||
28 | -------------------------------------------------------------------------------- | ||
29 | |||
30 | data Exp_ a | ||
31 | = Pi_ Visibility SName a a | ||
32 | | Lam_ Visibility Pat a a | ||
33 | | Con_ (SName, a) [a] | ||
34 | | ELit_ Lit | ||
35 | | Fun_ (SName, a) [a] | ||
36 | | App_ a a | ||
37 | | Var_ SName a | ||
38 | | TType_ | ||
39 | | Let_ Pat a a | ||
40 | deriving (Show, Eq, Functor, Foldable, Traversable) | ||
41 | |||
42 | instance PShow Exp where pShowPrec p = text . show | ||
43 | |||
44 | pattern Pi h n a b = Exp (Pi_ h n a b) | ||
45 | pattern Lam h n a b = Exp (Lam_ h n a b) | ||
46 | pattern Con a b = Exp (Con_ a b) | ||
47 | pattern ELit a = Exp (ELit_ a) | ||
48 | pattern Fun a b = Exp (Fun_ a b) | ||
49 | pattern EApp a b = Exp (App_ a b) | ||
50 | pattern Var a b = Exp (Var_ a b) | ||
51 | pattern TType = Exp TType_ | ||
52 | pattern ELet a b c = Exp (Let_ a b c) | ||
53 | |||
54 | pattern EString s = ELit (LString s) | ||
55 | pattern EFloat s = ELit (LFloat s) | ||
56 | pattern EInt s = ELit (LInt s) | ||
57 | |||
58 | newtype Exp = Exp (Exp_ Exp) | ||
59 | deriving (Show, Eq) | ||
60 | |||
61 | toExp :: I.Exp -> Exp | ||
62 | toExp = flip runReader [] . flip evalStateT freshTypeVars . f | ||
63 | where | ||
64 | freshTypeVars = (flip (:) <$> map show [0..] <*> ['a'..'z']) | ||
65 | newName = gets head <* modify tail | ||
66 | f = \case | ||
67 | I.Var i -> asks (!!! i) | ||
68 | I.Pi b x (I.downE 0 -> Just y) -> Pi b "" <$> f x <*> f y | ||
69 | I.Pi b x y -> newName >>= \n -> do | ||
70 | t <- f x | ||
71 | Pi b n t <$> local (Var n t:) (f y) | ||
72 | I.Lam b x y -> newName >>= \n -> do | ||
73 | t <- f x | ||
74 | Lam b (PVar t n) t <$> local (Var n t:) (f y) | ||
75 | I.Con (I.ConName s _ _ t) xs -> con s <$> f t <*> mapM f xs | ||
76 | I.TyCon (I.TyConName s _ _ t _ _) xs -> con s <$> f t <*> mapM f xs | ||
77 | I.ELit l -> pure $ ELit l | ||
78 | I.Fun (I.FunName s _ t) xs -> fun s <$> f t <*> mapM f xs | ||
79 | I.CaseFun x@(I.CaseFunName _ t _) xs -> fun (show x) <$> f t <*> mapM f xs | ||
80 | I.App a b -> app' <$> f a <*> f b | ||
81 | I.PMLabel x _ -> f x | ||
82 | I.FixLabel _ x -> f x | ||
83 | I.TType -> pure TType | ||
84 | I.LabelEnd x -> f x | ||
85 | z -> error $ "toExp: " ++ show z | ||
86 | |||
87 | xs !!! i | i < 0 || i >= length xs = error $ show xs ++ " !! " ++ show i | ||
88 | xs !!! i = xs !! i | ||
89 | |||
90 | untick ('\'': s) = s | ||
91 | untick s = s | ||
92 | |||
93 | fun s t xs = Fun (untick s, t) xs | ||
94 | con s t xs = Con (untick s, t) xs | ||
95 | |||
96 | freeVars :: Exp -> S.Set SName | ||
97 | freeVars = \case | ||
98 | Var n _ -> S.singleton n | ||
99 | Con _ xs -> S.unions $ map freeVars xs | ||
100 | ELit _ -> mempty | ||
101 | Fun _ xs -> S.unions $ map freeVars xs | ||
102 | EApp a b -> freeVars a `S.union` freeVars b | ||
103 | Pi _ n a b -> freeVars a `S.union` (S.delete n $ freeVars b) | ||
104 | Lam _ n a b -> freeVars a `S.union` (foldr S.delete (freeVars b) (patVars n)) | ||
105 | TType -> mempty | ||
106 | ELet n a b -> freeVars a `S.union` (foldr S.delete (freeVars b) (patVars n)) | ||
107 | |||
108 | type Ty = Exp | ||
109 | |||
110 | tyOf :: Exp -> Ty | ||
111 | tyOf = \case | ||
112 | Lam h (PVar _ n) t x -> Pi h n t $ tyOf x | ||
113 | EApp f x -> app (tyOf f) x | ||
114 | Var _ t -> t | ||
115 | Pi{} -> TType | ||
116 | Con (_, t) xs -> foldl app t xs | ||
117 | Fun (_, t) xs -> foldl app t xs | ||
118 | ELit l -> toExp $ I.litType l | ||
119 | TType -> TType | ||
120 | ELet a b c -> tyOf $ EApp (ELam a c) b | ||
121 | x -> error $ "tyOf: " ++ show x | ||
122 | where | ||
123 | app (Pi _ n a b) x = substE n x b | ||
124 | |||
125 | substE n x = \case | ||
126 | z@(Var n' _) | n' == n -> x | ||
127 | | otherwise -> z | ||
128 | Pi h n' a b | n == n' -> Pi h n' (substE n x a) b | ||
129 | Pi h n' a b -> Pi h n' (substE n x a) (substE n x b) | ||
130 | Lam h n' a b -> Lam h n' (substE n x a) $ if n `elem` patVars n' then b else substE n x b | ||
131 | Con cn xs -> Con cn (map (substE n x) xs) | ||
132 | Fun cn xs -> Fun cn (map (substE n x) xs) | ||
133 | TType -> TType | ||
134 | EApp a b -> app' (substE n x a) (substE n x b) | ||
135 | z -> error $ "substE: " ++ show z | ||
136 | |||
137 | app' (Lam _ (PVar _ n) _ x) b = substE n b x | ||
138 | app' a b = EApp a b | ||
139 | |||
140 | -------------------------------------------------------------------------------- | ||
141 | |||
142 | data Pat | ||
143 | = PVar Exp SName | ||
144 | | PTuple [Pat] | ||
145 | deriving (Eq, Show) | ||
146 | |||
147 | instance PShow Pat where pShowPrec p = text . show | ||
148 | |||
149 | patVars (PVar _ n) = [n] | ||
150 | patVars (PTuple ps) = concatMap patVars ps | ||
151 | |||
152 | patTy (PVar t _) = t | ||
153 | patTy (PTuple ps) = Con ("Tuple" ++ show (length ps), tupTy $ length ps) $ map patTy ps | ||
154 | |||
155 | tupTy n = foldr (:~>) TType $ replicate n TType | ||
156 | |||
157 | -- workaround for backward compatibility | ||
158 | etaRed (ELam (PVar _ n) (EApp f (EVar n'))) | n == n' && n `S.notMember` freeVars f = f | ||
159 | etaRed (ELam (PVar _ n) (Prim3 (tupCaseName -> Just k) _ x (EVar n'))) | n == n' && n `S.notMember` freeVars x = uncurry (\ps e -> ELam (PTuple ps) e) $ getPats k x | ||
160 | etaRed x = x | ||
161 | |||
162 | tupCaseName "Tuple2Case" = Just 2 | ||
163 | tupCaseName "Tuple3Case" = Just 3 | ||
164 | tupCaseName "Tuple4Case" = Just 4 | ||
165 | tupCaseName "Tuple5Case" = Just 5 | ||
166 | tupCaseName "Tuple6Case" = Just 6 | ||
167 | tupCaseName "Tuple7Case" = Just 7 | ||
168 | tupCaseName _ = Nothing | ||
169 | |||
170 | getPats 0 e = ([], e) | ||
171 | getPats i (ELam p e) = (p:) *** id $ getPats (i-1) e | ||
172 | |||
173 | ------------- | ||
174 | |||
175 | pattern EVar n <- Var n _ | ||
176 | pattern TVar t n = Var n t | ||
177 | |||
178 | pattern ELam n b <- Lam Visible n _ b where ELam n b = Lam Visible n (patTy n) b | ||
179 | |||
180 | pattern a :~> b = Pi Visible "" a b | ||
181 | infixr 1 :~> | ||
182 | |||
183 | pattern PrimN n xs <- Fun (n, t) (filterRelevant (n, 0) t -> xs) where PrimN n xs = Fun (n, builtinType n) xs | ||
184 | pattern Prim1 n a = PrimN n [a] | ||
185 | pattern Prim2 n a b = PrimN n [a, b] | ||
186 | pattern Prim3 n a b c <- PrimN n [a, b, c] | ||
187 | pattern Prim4 n a b c d <- PrimN n [a, b, c, d] | ||
188 | pattern Prim5 n a b c d e <- PrimN n [a, b, c, d, e] | ||
189 | |||
190 | builtinType = \case | ||
191 | "Output" -> TType | ||
192 | "Bool" -> TType | ||
193 | "Float" -> TType | ||
194 | "Nat" -> TType | ||
195 | "Zero" -> TNat | ||
196 | "Succ" -> TNat :~> TNat | ||
197 | "String" -> TType | ||
198 | "Sampler" -> TType | ||
199 | "VecS" -> TType :~> TNat :~> TType | ||
200 | n -> error $ "type of " ++ show n | ||
201 | |||
202 | filterRelevant _ _ [] = [] | ||
203 | filterRelevant i (Pi h n t t') (x: xs) = (if h == Visible then (x:) else id) $ filterRelevant (id *** (+1) $ i) (substE n x t') xs | ||
204 | |||
205 | pattern AN n xs <- Con (n, t) (filterRelevant (n, 0) t -> xs) where AN n xs = Con (n, builtinType n) xs | ||
206 | pattern A0 n = AN n [] | ||
207 | pattern A1 n a = AN n [a] | ||
208 | pattern A2 n a b = AN n [a, b] | ||
209 | pattern A3 n a b c <- AN n [a, b, c] | ||
210 | pattern A4 n a b c d <- AN n [a, b, c, d] | ||
211 | pattern A5 n a b c d e <- AN n [a, b, c, d, e] | ||
212 | |||
213 | pattern TCon0 n = A0 n | ||
214 | pattern TCon t n = Con (n, t) [] | ||
215 | |||
216 | pattern TUnit <- A0 "Tuple0" | ||
217 | pattern TBool = A0 "Bool" | ||
218 | pattern TWord <- A0 "Word" | ||
219 | pattern TInt <- A0 "Int" | ||
220 | pattern TNat = A0 "Nat" | ||
221 | pattern TFloat = A0 "Float" | ||
222 | pattern TString = A0 "String" | ||
223 | |||
224 | pattern Uniform n <- Prim1 "Uniform" n | ||
225 | |||
226 | pattern Zero = A0 "Zero" | ||
227 | pattern Succ n = A1 "Succ" n | ||
228 | |||
229 | pattern TVec n a = A2 "VecS" a (Nat n) | ||
230 | pattern TMat i j a <- A3 "Mat" (Nat i) (Nat j) a | ||
231 | |||
232 | pattern Nat n <- (fromNat -> Just n) where Nat = toNat | ||
233 | |||
234 | toNat :: Int -> Exp | ||
235 | toNat 0 = Zero | ||
236 | toNat n = Succ (toNat $ n-1) | ||
237 | |||
238 | fromNat :: Exp -> Maybe Int | ||
239 | fromNat Zero = Just 0 | ||
240 | fromNat (Succ n) = (1 +) <$> fromNat n | ||
241 | fromNat _ = Nothing | ||
242 | |||
243 | pattern TTuple xs <- (getTuple -> Just xs) | ||
244 | pattern ETuple xs <- (getTuple -> Just xs) | ||
245 | |||
246 | getTuple (AN (tupName -> Just n) xs) | length xs == n = Just xs | ||
247 | getTuple _ = Nothing | ||
248 | |||
249 | tupName = \case | ||
250 | "Tuple0" -> Just 0 | ||
251 | "Tuple2" -> Just 2 | ||
252 | "Tuple3" -> Just 3 | ||
253 | "Tuple4" -> Just 4 | ||
254 | "Tuple5" -> Just 5 | ||
255 | "Tuple6" -> Just 6 | ||
256 | "Tuple7" -> Just 7 | ||
257 | _ -> Nothing | ||
258 | |||
259 | pattern SwizzProj a b <- (getSwizzProj -> Just (a, b)) | ||
260 | |||
261 | getSwizzProj = \case | ||
262 | Prim2 "swizzscalar" e (getSwizzChar -> Just s) -> Just (e, [s]) | ||
263 | Prim2 "swizzvector" e (AN ((`elem` ["V2","V3","V4"]) -> True) (traverse getSwizzChar -> Just s)) -> Just (e, s) | ||
264 | _ -> Nothing | ||
265 | |||
266 | getSwizzChar = \case | ||
267 | A0 "Sx" -> Just 'x' | ||
268 | A0 "Sy" -> Just 'y' | ||
269 | A0 "Sz" -> Just 'z' | ||
270 | A0 "Sw" -> Just 'w' | ||
271 | _ -> Nothing | ||
272 | |||
273 | outputType = TCon0 "Output" | ||
274 | boolType = TBool | ||
275 | trueExp = TCon TBool "True" | ||
276 | |||
diff --git a/src/LambdaCube/Compiler/CoreToGLSL.hs b/src/LambdaCube/Compiler/CoreToGLSL.hs deleted file mode 100644 index 9247db17..00000000 --- a/src/LambdaCube/Compiler/CoreToGLSL.hs +++ /dev/null | |||
@@ -1,357 +0,0 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | ||
2 | {-# LANGUAGE PatternSynonyms #-} | ||
3 | {-# LANGUAGE ViewPatterns #-} | ||
4 | {-# LANGUAGE PackageImports #-} | ||
5 | {-# LANGUAGE FlexibleContexts #-} | ||
6 | {-# LANGUAGE LambdaCase #-} | ||
7 | module LambdaCube.Compiler.CoreToGLSL | ||
8 | ( genVertexGLSL | ||
9 | , genFragmentGLSL | ||
10 | ) where | ||
11 | |||
12 | import Debug.Trace | ||
13 | |||
14 | import Data.Char | ||
15 | import Data.List | ||
16 | import Data.Maybe | ||
17 | import Data.Set (Set) | ||
18 | import qualified Data.Set as Set | ||
19 | import Data.Map (Map) | ||
20 | import qualified Data.Map as Map | ||
21 | |||
22 | import Control.Arrow hiding ((<+>)) | ||
23 | import Control.Monad.Writer | ||
24 | |||
25 | import LambdaCube.Compiler.Pretty hiding (parens) | ||
26 | import LambdaCube.Compiler.CGExp | ||
27 | import IR(Backend(..)) | ||
28 | {- | ||
29 | mangleIdent :: String -> String | ||
30 | mangleIdent n = '_': concatMap encodeChar n | ||
31 | where | ||
32 | encodeChar = \case | ||
33 | c | isAlphaNum c -> [c] | ||
34 | '_' -> "__" | ||
35 | '.' -> "_dot" | ||
36 | '$' -> "_dollar" | ||
37 | '~' -> "_tilde" | ||
38 | '=' -> "_eq" | ||
39 | '<' -> "_less" | ||
40 | '>' -> "_greater" | ||
41 | '!' -> "_bang" | ||
42 | '#' -> "_hash" | ||
43 | '%' -> "_percent" | ||
44 | '^' -> "_up" | ||
45 | '&' -> "_amp" | ||
46 | '|' -> "_bar" | ||
47 | '*' -> "_times" | ||
48 | '/' -> "_div" | ||
49 | '+' -> "_plus" | ||
50 | '-' -> "_minus" | ||
51 | ':' -> "_colon" | ||
52 | '\\' -> "_bslash" | ||
53 | '?' -> "_qmark" | ||
54 | '@' -> "_at" | ||
55 | '\'' -> "_prime" | ||
56 | c -> '$' : show (ord c) | ||
57 | -} | ||
58 | |||
59 | genUniforms :: Exp -> Set [String] | ||
60 | genUniforms e = case e of | ||
61 | Uniform (EString s) -> Set.singleton [unwords ["uniform",toGLSLType "1" $ tyOf e,s,";"]] | ||
62 | ELet (PVar _ _) (A3 "Sampler" _ _ (A1 "Texture2DSlot" (EString n))) _ -> Set.singleton [unwords ["uniform","sampler2D",n,";"]] | ||
63 | ELet (PVar _ n) (A3 "Sampler" _ _ (A2 "Texture2D" _ _)) _ -> Set.singleton [unwords ["uniform","sampler2D",n,";"]] | ||
64 | Exp e -> foldMap genUniforms e | ||
65 | |||
66 | type GLSL = Writer [String] | ||
67 | |||
68 | genStreamInput :: Backend -> Pat -> GLSL [String] | ||
69 | genStreamInput backend i = fmap concat $ mapM input $ case i of | ||
70 | PTuple l -> l | ||
71 | x -> [x] | ||
72 | where | ||
73 | input (PVar t n) = tell [unwords [inputDef,toGLSLType (n ++ "\n") t,n,";"]] >> return [n] | ||
74 | input a = error $ "genStreamInput " ++ ppShow a | ||
75 | inputDef = case backend of | ||
76 | OpenGL33 -> "in" | ||
77 | WebGL1 -> "attribute" | ||
78 | |||
79 | genStreamOutput :: Backend -> Exp -> GLSL [(String, String, String)] | ||
80 | genStreamOutput backend (eTuple -> l) = fmap concat $ zipWithM go (map (("v" ++) . show) [0..]) l | ||
81 | where | ||
82 | go var (A1 (f -> i) (toGLSLType "3" . tyOf -> t)) = do | ||
83 | tell $ case backend of | ||
84 | WebGL1 -> [unwords ["varying",t,var,";"]] | ||
85 | OpenGL33 -> [unwords [i,"out",t,var,";"]] | ||
86 | return [(i,t,var)] | ||
87 | f "Smooth" = "smooth" | ||
88 | f "Flat" = "flat" | ||
89 | f "NoPerspective" = "noperspective" | ||
90 | |||
91 | eTuple (ETuple l) = l | ||
92 | eTuple x = [x] | ||
93 | |||
94 | genFragmentInput :: Backend -> [(String, String, String)] -> GLSL () | ||
95 | genFragmentInput OpenGL33 s = tell [unwords [i,"in",t,n,";"] | (i,t,n) <- s] | ||
96 | genFragmentInput WebGL1 s = tell [unwords ["varying",t,n,";"] | (i,t,n) <- s] | ||
97 | genFragmentOutput backend (tyOf -> a@(toGLSLType "4" -> t)) = case a of | ||
98 | TUnit -> return False | ||
99 | _ -> case backend of | ||
100 | OpenGL33 -> tell [unwords ["out",t,"f0",";"]] >> return True | ||
101 | WebGL1 -> return True | ||
102 | |||
103 | genVertexGLSL :: Backend -> Exp -> (([String],[(String,String,String)]),String) | ||
104 | genVertexGLSL backend e@(etaRed -> ELam i (A4 "VertexOut" p s c o)) = id *** unlines $ runWriter $ do | ||
105 | case backend of | ||
106 | OpenGL33 -> do | ||
107 | tell ["#version 330 core"] | ||
108 | tell ["vec4 texture2D(sampler2D s, vec2 uv){return texture(s,uv);}"] | ||
109 | WebGL1 -> do | ||
110 | tell ["#version 100"] | ||
111 | tell ["precision highp float;"] | ||
112 | tell ["precision highp int;"] | ||
113 | mapM_ tell $ genUniforms e | ||
114 | input <- genStreamInput backend i | ||
115 | out <- genStreamOutput backend o | ||
116 | tell ["void main() {"] | ||
117 | unless (null out) $ sequence_ [tell $ [var <> " = " <> genGLSL x <> ";"] | ((_,_,var),x) <- zip out $ eTuple o] | ||
118 | tell ["gl_Position = " <> genGLSL p <> ";"] | ||
119 | tell ["gl_PointSize = " <> genGLSL s <> ";"] | ||
120 | tell ["}"] | ||
121 | return (input,out) | ||
122 | genVertexGLSL _ e = error $ "genVertexGLSL: " ++ ppShow e | ||
123 | |||
124 | genGLSL :: Exp -> String | ||
125 | genGLSL e = show $ genGLSLSubst mempty e | ||
126 | |||
127 | genFragmentGLSL :: Backend -> [(String,String,String)] -> Exp -> Exp -> String | ||
128 | genFragmentGLSL backend s e@(etaRed -> ELam i fragOut) ffilter{-TODO-} = unlines $ execWriter $ do | ||
129 | case backend of | ||
130 | OpenGL33 -> do | ||
131 | tell ["#version 330 core"] | ||
132 | tell ["vec4 texture2D(sampler2D s, vec2 uv){return texture(s,uv);}"] | ||
133 | WebGL1 -> do | ||
134 | tell ["#version 100"] | ||
135 | tell ["precision highp float;"] | ||
136 | tell ["precision highp int;"] | ||
137 | mapM_ tell $ genUniforms e | ||
138 | genFragmentInput backend s | ||
139 | let o = case fragOut of | ||
140 | A1 "FragmentOutRastDepth" o -> o | ||
141 | A1 "FragmentOut" o -> o | ||
142 | _ -> error $ "genFragmentGLSL fragOut " ++ ppShow fragOut | ||
143 | hasOutput <- genFragmentOutput backend o | ||
144 | tell ["void main() {"] | ||
145 | case ffilter of | ||
146 | A0 "PassAll" -> return () | ||
147 | A1 "Filter" (etaRed -> ELam i o) -> tell ["if (!(" <> show (genGLSLSubst (makeSubst i s) o) <> ")) discard;"] | ||
148 | when hasOutput $ case backend of | ||
149 | OpenGL33 -> tell ["f0 = " <> show (genGLSLSubst (makeSubst i s) o) <> ";"] | ||
150 | WebGL1 -> tell ["gl_FragColor = " <> show (genGLSLSubst (makeSubst i s) o) <> ";"] | ||
151 | tell ["}"] | ||
152 | genFragmentGLSL _ _ e ff = error $ "genFragmentGLSL: " ++ ppShow e ++ ppShow ff | ||
153 | |||
154 | makeSubst (PVar _ x) [(_,_,n)] = Map.singleton x n | ||
155 | makeSubst (PTuple l) x = Map.fromList $ go l x where | ||
156 | go [] [] = [] | ||
157 | go (PVar _ x: al) ((_,_,n):bl) = (x,n) : go al bl | ||
158 | go i s = error $ "genFragmentGLSL illegal input " ++ ppShow i ++ " " ++ show s | ||
159 | |||
160 | parens a = "(" <+> a <+> ")" | ||
161 | |||
162 | -- todo: (on hold) name mangling to prevent name collisions | ||
163 | -- todo: reader monad | ||
164 | genGLSLSubst :: Map String String -> Exp -> Doc | ||
165 | genGLSLSubst s e = case e of | ||
166 | ELit a -> text $ show a | ||
167 | EVar a -> text $ Map.findWithDefault a a s | ||
168 | Uniform (EString s) -> text s | ||
169 | -- texturing | ||
170 | A3 "Sampler" _ _ _ -> error $ "sampler GLSL codegen is not supported" | ||
171 | PrimN "texture2D" xs -> functionCall "texture2D" xs | ||
172 | -- interpolation | ||
173 | A1 "Smooth" a -> gen a | ||
174 | A1 "Flat" a -> gen a | ||
175 | A1 "NoPerspecitve" a -> gen a | ||
176 | |||
177 | -- temp builtins FIXME: get rid of these | ||
178 | Prim1 "primIntToWord" a -> error $ "WebGL 1 does not support uint types: " ++ ppShow e | ||
179 | Prim1 "primIntToFloat" a -> gen a -- FIXME: does GLSL support implicit int to float cast??? | ||
180 | Prim2 "primCompareInt" a b -> error $ "GLSL codegen does not support: " ++ ppShow e | ||
181 | Prim2 "primCompareWord" a b -> error $ "GLSL codegen does not support: " ++ ppShow e | ||
182 | Prim2 "primCompareFloat" a b -> error $ "GLSL codegen does not support: " ++ ppShow e | ||
183 | Prim1 "primNegateInt" a -> text "-" <+> parens (gen a) | ||
184 | Prim1 "primNegateWord" a -> error $ "WebGL 1 does not support uint types: " ++ ppShow e | ||
185 | Prim1 "primNegateFloat" a -> text "-" <+> parens (gen a) | ||
186 | |||
187 | -- vectors | ||
188 | AN n xs | n `elem` ["V2", "V3", "V4"], Just s <- vecConName $ tyOf e -> functionCall s xs | ||
189 | -- bool | ||
190 | A0 "True" -> text "true" | ||
191 | A0 "False" -> text "false" | ||
192 | -- matrices | ||
193 | AN "M22F" xs -> functionCall "mat2" xs | ||
194 | AN "M23F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
195 | AN "M24F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
196 | AN "M32F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
197 | AN "M33F" xs -> functionCall "mat3" xs | ||
198 | AN "M34F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
199 | AN "M42F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
200 | AN "M43F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
201 | AN "M44F" xs -> functionCall "mat4" xs -- where gen = gen | ||
202 | |||
203 | Prim3 "primIfThenElse" a b c -> gen a <+> "?" <+> gen b <+> ":" <+> gen c | ||
204 | -- TODO: Texture Lookup Functions | ||
205 | SwizzProj a x -> "(" <+> gen a <+> (")." <> text x) | ||
206 | ELam _ _ -> error "GLSL codegen for lambda function is not supported yet" | ||
207 | ELet (PVar _ _) (A3 "Sampler" _ _ (A1 "Texture2DSlot" (EString n))) _ -> text n | ||
208 | ELet (PVar _ n) (A3 "Sampler" _ _ (A2 "Texture2D" _ _)) _ -> text n | ||
209 | ELet _ _ _ -> error "GLSL codegen for let is not supported yet" | ||
210 | ETuple _ -> error "GLSL codegen for tuple is not supported yet" | ||
211 | |||
212 | -- Primitive Functions | ||
213 | PrimN ('P':'r':'i':'m':n) xs | n'@(_:_) <- trName (dropS n) -> case n' of | ||
214 | (c:_) | isAlpha c -> functionCall n' xs | ||
215 | [op, '_'] -> prefixOp [op] xs | ||
216 | n' -> binOp n' xs | ||
217 | where | ||
218 | ifType p a b = if all (p . tyOf) xs then a else b | ||
219 | |||
220 | dropS n | ||
221 | | last n == 'S' && init n `elem` ["Add", "Sub", "Div", "Mod", "BAnd", "BOr", "BXor", "BShiftL", "BShiftR", "Min", "Max", "Clamp", "Mix", "Step", "SmoothStep"] = init n | ||
222 | | otherwise = n | ||
223 | |||
224 | trName = \case | ||
225 | |||
226 | -- Arithmetic Functions | ||
227 | "Add" -> "+" | ||
228 | "Sub" -> "-" | ||
229 | "Neg" -> "-_" | ||
230 | "Mul" -> ifType isMatrix "matrixCompMult" "*" | ||
231 | "MulS" -> "*" | ||
232 | "Div" -> "/" | ||
233 | "Mod" -> ifType isIntegral "%" "mod" | ||
234 | |||
235 | -- Bit-wise Functions | ||
236 | "BAnd" -> "&" | ||
237 | "BOr" -> "|" | ||
238 | "BXor" -> "^" | ||
239 | "BNot" -> "~_" | ||
240 | "BShiftL" -> "<<" | ||
241 | "BShiftR" -> ">>" | ||
242 | |||
243 | -- Logic Functions | ||
244 | "And" -> "&&" | ||
245 | "Or" -> "||" | ||
246 | "Xor" -> "^" | ||
247 | "Not" -> ifType isScalar "!_" "not" | ||
248 | |||
249 | -- Integer/Float Conversion Functions | ||
250 | "FloatBitsToInt" -> "floatBitsToInt" | ||
251 | "FloatBitsToUInt" -> "floatBitsToUint" | ||
252 | "IntBitsToFloat" -> "intBitsToFloat" | ||
253 | "UIntBitsToFloat" -> "uintBitsToFloat" | ||
254 | |||
255 | -- Matrix Functions | ||
256 | "OuterProduct" -> "outerProduct" | ||
257 | "MulMatVec" -> "*" | ||
258 | "MulVecMat" -> "*" | ||
259 | "MulMatMat" -> "*" | ||
260 | |||
261 | -- Fragment Processing Functions | ||
262 | "DFdx" -> "dFdx" | ||
263 | "DFdy" -> "dFdy" | ||
264 | |||
265 | -- Vector and Scalar Relational Functions | ||
266 | "LessThan" -> ifType isScalarNum "<" "lessThan" | ||
267 | "LessThanEqual" -> ifType isScalarNum "<=" "lessThanEqual" | ||
268 | "GreaterThan" -> ifType isScalarNum ">" "greaterThan" | ||
269 | "GreaterThanEqual" -> ifType isScalarNum ">=" "greaterThanEqual" | ||
270 | "Equal" -> "==" | ||
271 | "EqualV" -> ifType isScalar "==" "equal" | ||
272 | "NotEqual" -> "!=" | ||
273 | "NotEqualV" -> ifType isScalar "!=" "notEqual" | ||
274 | |||
275 | -- Angle and Trigonometry Functions | ||
276 | "ATan2" -> "atan" | ||
277 | -- Exponential Functions | ||
278 | "InvSqrt" -> "inversesqrt" | ||
279 | -- Common Functions | ||
280 | "RoundEven" -> "roundEven" | ||
281 | "ModF" -> error "PrimModF is not implemented yet!" -- TODO | ||
282 | "MixB" -> "mix" | ||
283 | |||
284 | n | n `elem` | ||
285 | -- Logic Functions | ||
286 | [ "Any", "All" | ||
287 | -- Angle and Trigonometry Functions | ||
288 | , "ACos", "ACosH", "ASin", "ASinH", "ATan", "ATanH", "Cos", "CosH", "Degrees", "Radians", "Sin", "SinH", "Tan", "TanH" | ||
289 | -- Exponential Functions | ||
290 | , "Pow", "Exp", "Exp2", "Log2", "Sqrt" | ||
291 | -- Common Functions | ||
292 | , "IsNan", "IsInf", "Abs", "Sign", "Floor", "Trunc", "Round", "Ceil", "Fract", "Min", "Max", "Mix", "Step", "SmoothStep" | ||
293 | -- Geometric Functions | ||
294 | , "Length", "Distance", "Dot", "Cross", "Normalize", "FaceForward", "Reflect", "Refract" | ||
295 | -- Matrix Functions | ||
296 | , "Transpose", "Determinant", "Inverse" | ||
297 | -- Fragment Processing Functions | ||
298 | , "FWidth" | ||
299 | -- Noise Functions | ||
300 | , "Noise1", "Noise2", "Noise3", "Noise4" | ||
301 | ] -> map toLower n | ||
302 | |||
303 | _ -> "" | ||
304 | |||
305 | x -> error $ "GLSL codegen - unsupported expression: " ++ ppShow x | ||
306 | where | ||
307 | prefixOp o [a] = text o <+> parens (gen a) | ||
308 | binOp o [a, b] = parens (gen a) <+> text o <+> parens (gen b) | ||
309 | functionCall f a = text f <+> parens (hcat $ intersperse "," $ map gen a) | ||
310 | |||
311 | gen = genGLSLSubst s | ||
312 | |||
313 | isMatrix :: Ty -> Bool | ||
314 | isMatrix (TMat{}) = True | ||
315 | isMatrix _ = False | ||
316 | |||
317 | isIntegral :: Ty -> Bool | ||
318 | isIntegral TWord = True | ||
319 | isIntegral TInt = True | ||
320 | isIntegral (TVec _ TWord) = True | ||
321 | isIntegral (TVec _ TInt) = True | ||
322 | isIntegral _ = False | ||
323 | |||
324 | isScalarNum :: Ty -> Bool | ||
325 | isScalarNum = \case | ||
326 | TInt -> True | ||
327 | TWord -> True | ||
328 | TFloat -> True | ||
329 | _ -> False | ||
330 | |||
331 | isScalar :: Ty -> Bool | ||
332 | isScalar = isJust . scalarType | ||
333 | |||
334 | scalarType = \case | ||
335 | TBool -> Just "b" | ||
336 | TWord -> Just "u" | ||
337 | TInt -> Just "i" | ||
338 | TFloat -> Just "" | ||
339 | _ -> Nothing | ||
340 | |||
341 | vecConName = \case | ||
342 | TVec n t | is234 n, Just s <- scalarType t -> Just $ s ++ "vec" ++ show n | ||
343 | t -> Nothing | ||
344 | |||
345 | toGLSLType msg = \case | ||
346 | TBool -> "bool" | ||
347 | TWord -> "uint" | ||
348 | TInt -> "int" | ||
349 | TFloat -> "float" | ||
350 | x@(TVec n t) | Just s <- vecConName x -> s | ||
351 | TMat i j TFloat | is234 i && is234 j -> "mat" ++ if i == j then show i else show i ++ "x" ++ show j | ||
352 | TTuple [] -> "void" | ||
353 | t -> error $ "toGLSLType: " ++ msg ++ " " ++ ppShow t | ||
354 | |||
355 | is234 = (`elem` [2,3,4]) | ||
356 | |||
357 | |||
diff --git a/src/LambdaCube/Compiler/CoreToIR.hs b/src/LambdaCube/Compiler/CoreToIR.hs index 66624afa..f37f13e5 100644 --- a/src/LambdaCube/Compiler/CoreToIR.hs +++ b/src/LambdaCube/Compiler/CoreToIR.hs | |||
@@ -4,13 +4,17 @@ | |||
4 | {-# LANGUAGE FlexibleContexts #-} | 4 | {-# LANGUAGE FlexibleContexts #-} |
5 | {-# LANGUAGE LambdaCase #-} | 5 | {-# LANGUAGE LambdaCase #-} |
6 | {-# LANGUAGE PackageImports #-} | 6 | {-# LANGUAGE PackageImports #-} |
7 | {-# LANGUAGE DeriveFunctor #-} | ||
8 | {-# LANGUAGE DeriveFoldable #-} | ||
9 | {-# LANGUAGE DeriveTraversable #-} | ||
7 | module LambdaCube.Compiler.CoreToIR | 10 | module LambdaCube.Compiler.CoreToIR |
8 | ( compilePipeline | 11 | ( compilePipeline |
12 | , Exp, toExp, tyOf, outputType, boolType, trueExp | ||
9 | ) where | 13 | ) where |
10 | 14 | ||
11 | import Debug.Trace | 15 | import Data.Char |
12 | import Control.Applicative | 16 | import Data.List |
13 | import Control.Monad.State | 17 | import Data.Maybe |
14 | import Data.Monoid | 18 | import Data.Monoid |
15 | import Data.Set (Set) | 19 | import Data.Set (Set) |
16 | import qualified Data.Set as Set | 20 | import qualified Data.Set as Set |
@@ -18,13 +22,26 @@ import Data.Map (Map) | |||
18 | import qualified Data.Map as Map | 22 | import qualified Data.Map as Map |
19 | import Data.Vector (Vector,(!)) | 23 | import Data.Vector (Vector,(!)) |
20 | import qualified Data.Vector as Vector | 24 | import qualified Data.Vector as Vector |
25 | import Control.Applicative | ||
26 | import Control.Arrow hiding ((<+>)) | ||
27 | import Control.Monad.Writer | ||
28 | import Control.Monad.State | ||
29 | import Control.Monad.Reader | ||
30 | import Control.Monad.Except | ||
31 | import Control.Monad.Identity | ||
32 | import Text.Parsec.Pos | ||
33 | import Debug.Trace | ||
21 | 34 | ||
22 | import LambdaCube.Compiler.Pretty | 35 | import IR(Backend(..)) |
23 | import LambdaCube.Compiler.CGExp | ||
24 | import LambdaCube.Compiler.CoreToGLSL | ||
25 | import qualified IR as IR | 36 | import qualified IR as IR |
26 | import qualified "lambdacube-ir" Linear as IR | 37 | import qualified "lambdacube-ir" Linear as IR |
27 | 38 | ||
39 | import LambdaCube.Compiler.Pretty hiding (parens) | ||
40 | import qualified LambdaCube.Compiler.Infer as I | ||
41 | import LambdaCube.Compiler.Infer (SName, Lit(..), Visibility(..)) | ||
42 | |||
43 | -------------------------------------------------------------------------- | ||
44 | |||
28 | type CG = State IR.Pipeline | 45 | type CG = State IR.Pipeline |
29 | 46 | ||
30 | pattern TFrameBuffer a b <- A2 "FrameBuffer" a b | 47 | pattern TFrameBuffer a b <- A2 "FrameBuffer" a b |
@@ -449,3 +466,585 @@ compPV x = case x of | |||
449 | A0 "FirstVertex" -> IR.FirstVertex | 466 | A0 "FirstVertex" -> IR.FirstVertex |
450 | A0 "LastVertex" -> IR.LastVertex | 467 | A0 "LastVertex" -> IR.LastVertex |
451 | x -> error $ "compPV " ++ ppShow x | 468 | x -> error $ "compPV " ++ ppShow x |
469 | |||
470 | --------------------------------------------------------------- GLSL generation | ||
471 | |||
472 | {- | ||
473 | mangleIdent :: String -> String | ||
474 | mangleIdent n = '_': concatMap encodeChar n | ||
475 | where | ||
476 | encodeChar = \case | ||
477 | c | isAlphaNum c -> [c] | ||
478 | '_' -> "__" | ||
479 | '.' -> "_dot" | ||
480 | '$' -> "_dollar" | ||
481 | '~' -> "_tilde" | ||
482 | '=' -> "_eq" | ||
483 | '<' -> "_less" | ||
484 | '>' -> "_greater" | ||
485 | '!' -> "_bang" | ||
486 | '#' -> "_hash" | ||
487 | '%' -> "_percent" | ||
488 | '^' -> "_up" | ||
489 | '&' -> "_amp" | ||
490 | '|' -> "_bar" | ||
491 | '*' -> "_times" | ||
492 | '/' -> "_div" | ||
493 | '+' -> "_plus" | ||
494 | '-' -> "_minus" | ||
495 | ':' -> "_colon" | ||
496 | '\\' -> "_bslash" | ||
497 | '?' -> "_qmark" | ||
498 | '@' -> "_at" | ||
499 | '\'' -> "_prime" | ||
500 | c -> '$' : show (ord c) | ||
501 | -} | ||
502 | |||
503 | genUniforms :: Exp -> Set [String] | ||
504 | genUniforms e = case e of | ||
505 | Uniform (EString s) -> Set.singleton [unwords ["uniform",toGLSLType "1" $ tyOf e,s,";"]] | ||
506 | ELet (PVar _ _) (A3 "Sampler" _ _ (A1 "Texture2DSlot" (EString n))) _ -> Set.singleton [unwords ["uniform","sampler2D",n,";"]] | ||
507 | ELet (PVar _ n) (A3 "Sampler" _ _ (A2 "Texture2D" _ _)) _ -> Set.singleton [unwords ["uniform","sampler2D",n,";"]] | ||
508 | Exp e -> foldMap genUniforms e | ||
509 | |||
510 | type GLSL = Writer [String] | ||
511 | |||
512 | genStreamInput :: Backend -> Pat -> GLSL [String] | ||
513 | genStreamInput backend i = fmap concat $ mapM input $ case i of | ||
514 | PTuple l -> l | ||
515 | x -> [x] | ||
516 | where | ||
517 | input (PVar t n) = tell [unwords [inputDef,toGLSLType (n ++ "\n") t,n,";"]] >> return [n] | ||
518 | input a = error $ "genStreamInput " ++ ppShow a | ||
519 | inputDef = case backend of | ||
520 | OpenGL33 -> "in" | ||
521 | WebGL1 -> "attribute" | ||
522 | |||
523 | genStreamOutput :: Backend -> Exp -> GLSL [(String, String, String)] | ||
524 | genStreamOutput backend (eTuple -> l) = fmap concat $ zipWithM go (map (("v" ++) . show) [0..]) l | ||
525 | where | ||
526 | go var (A1 (f -> i) (toGLSLType "3" . tyOf -> t)) = do | ||
527 | tell $ case backend of | ||
528 | WebGL1 -> [unwords ["varying",t,var,";"]] | ||
529 | OpenGL33 -> [unwords [i,"out",t,var,";"]] | ||
530 | return [(i,t,var)] | ||
531 | f "Smooth" = "smooth" | ||
532 | f "Flat" = "flat" | ||
533 | f "NoPerspective" = "noperspective" | ||
534 | |||
535 | eTuple (ETuple l) = l | ||
536 | eTuple x = [x] | ||
537 | |||
538 | genFragmentInput :: Backend -> [(String, String, String)] -> GLSL () | ||
539 | genFragmentInput OpenGL33 s = tell [unwords [i,"in",t,n,";"] | (i,t,n) <- s] | ||
540 | genFragmentInput WebGL1 s = tell [unwords ["varying",t,n,";"] | (i,t,n) <- s] | ||
541 | genFragmentOutput backend (tyOf -> a@(toGLSLType "4" -> t)) = case a of | ||
542 | TUnit -> return False | ||
543 | _ -> case backend of | ||
544 | OpenGL33 -> tell [unwords ["out",t,"f0",";"]] >> return True | ||
545 | WebGL1 -> return True | ||
546 | |||
547 | genVertexGLSL :: Backend -> Exp -> (([String],[(String,String,String)]),String) | ||
548 | genVertexGLSL backend e@(etaRed -> ELam i (A4 "VertexOut" p s c o)) = id *** unlines $ runWriter $ do | ||
549 | case backend of | ||
550 | OpenGL33 -> do | ||
551 | tell ["#version 330 core"] | ||
552 | tell ["vec4 texture2D(sampler2D s, vec2 uv){return texture(s,uv);}"] | ||
553 | WebGL1 -> do | ||
554 | tell ["#version 100"] | ||
555 | tell ["precision highp float;"] | ||
556 | tell ["precision highp int;"] | ||
557 | mapM_ tell $ genUniforms e | ||
558 | input <- genStreamInput backend i | ||
559 | out <- genStreamOutput backend o | ||
560 | tell ["void main() {"] | ||
561 | unless (null out) $ sequence_ [tell $ [var <> " = " <> genGLSL x <> ";"] | ((_,_,var),x) <- zip out $ eTuple o] | ||
562 | tell ["gl_Position = " <> genGLSL p <> ";"] | ||
563 | tell ["gl_PointSize = " <> genGLSL s <> ";"] | ||
564 | tell ["}"] | ||
565 | return (input,out) | ||
566 | genVertexGLSL _ e = error $ "genVertexGLSL: " ++ ppShow e | ||
567 | |||
568 | genGLSL :: Exp -> String | ||
569 | genGLSL e = show $ genGLSLSubst mempty e | ||
570 | |||
571 | genFragmentGLSL :: Backend -> [(String,String,String)] -> Exp -> Exp -> String | ||
572 | genFragmentGLSL backend s e@(etaRed -> ELam i fragOut) ffilter{-TODO-} = unlines $ execWriter $ do | ||
573 | case backend of | ||
574 | OpenGL33 -> do | ||
575 | tell ["#version 330 core"] | ||
576 | tell ["vec4 texture2D(sampler2D s, vec2 uv){return texture(s,uv);}"] | ||
577 | WebGL1 -> do | ||
578 | tell ["#version 100"] | ||
579 | tell ["precision highp float;"] | ||
580 | tell ["precision highp int;"] | ||
581 | mapM_ tell $ genUniforms e | ||
582 | genFragmentInput backend s | ||
583 | let o = case fragOut of | ||
584 | A1 "FragmentOutRastDepth" o -> o | ||
585 | A1 "FragmentOut" o -> o | ||
586 | _ -> error $ "genFragmentGLSL fragOut " ++ ppShow fragOut | ||
587 | hasOutput <- genFragmentOutput backend o | ||
588 | tell ["void main() {"] | ||
589 | case ffilter of | ||
590 | A0 "PassAll" -> return () | ||
591 | A1 "Filter" (etaRed -> ELam i o) -> tell ["if (!(" <> show (genGLSLSubst (makeSubst i s) o) <> ")) discard;"] | ||
592 | when hasOutput $ case backend of | ||
593 | OpenGL33 -> tell ["f0 = " <> show (genGLSLSubst (makeSubst i s) o) <> ";"] | ||
594 | WebGL1 -> tell ["gl_FragColor = " <> show (genGLSLSubst (makeSubst i s) o) <> ";"] | ||
595 | tell ["}"] | ||
596 | genFragmentGLSL _ _ e ff = error $ "genFragmentGLSL: " ++ ppShow e ++ ppShow ff | ||
597 | |||
598 | makeSubst (PVar _ x) [(_,_,n)] = Map.singleton x n | ||
599 | makeSubst (PTuple l) x = Map.fromList $ go l x where | ||
600 | go [] [] = [] | ||
601 | go (PVar _ x: al) ((_,_,n):bl) = (x,n) : go al bl | ||
602 | go i s = error $ "genFragmentGLSL illegal input " ++ ppShow i ++ " " ++ show s | ||
603 | |||
604 | parens a = "(" <+> a <+> ")" | ||
605 | |||
606 | -- todo: (on hold) name mangling to prevent name collisions | ||
607 | -- todo: reader monad | ||
608 | genGLSLSubst :: Map String String -> Exp -> Doc | ||
609 | genGLSLSubst s e = case e of | ||
610 | ELit a -> text $ show a | ||
611 | EVar a -> text $ Map.findWithDefault a a s | ||
612 | Uniform (EString s) -> text s | ||
613 | -- texturing | ||
614 | A3 "Sampler" _ _ _ -> error $ "sampler GLSL codegen is not supported" | ||
615 | PrimN "texture2D" xs -> functionCall "texture2D" xs | ||
616 | -- interpolation | ||
617 | A1 "Smooth" a -> gen a | ||
618 | A1 "Flat" a -> gen a | ||
619 | A1 "NoPerspecitve" a -> gen a | ||
620 | |||
621 | -- temp builtins FIXME: get rid of these | ||
622 | Prim1 "primIntToWord" a -> error $ "WebGL 1 does not support uint types: " ++ ppShow e | ||
623 | Prim1 "primIntToFloat" a -> gen a -- FIXME: does GLSL support implicit int to float cast??? | ||
624 | Prim2 "primCompareInt" a b -> error $ "GLSL codegen does not support: " ++ ppShow e | ||
625 | Prim2 "primCompareWord" a b -> error $ "GLSL codegen does not support: " ++ ppShow e | ||
626 | Prim2 "primCompareFloat" a b -> error $ "GLSL codegen does not support: " ++ ppShow e | ||
627 | Prim1 "primNegateInt" a -> text "-" <+> parens (gen a) | ||
628 | Prim1 "primNegateWord" a -> error $ "WebGL 1 does not support uint types: " ++ ppShow e | ||
629 | Prim1 "primNegateFloat" a -> text "-" <+> parens (gen a) | ||
630 | |||
631 | -- vectors | ||
632 | AN n xs | n `elem` ["V2", "V3", "V4"], Just s <- vecConName $ tyOf e -> functionCall s xs | ||
633 | -- bool | ||
634 | A0 "True" -> text "true" | ||
635 | A0 "False" -> text "false" | ||
636 | -- matrices | ||
637 | AN "M22F" xs -> functionCall "mat2" xs | ||
638 | AN "M23F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
639 | AN "M24F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
640 | AN "M32F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
641 | AN "M33F" xs -> functionCall "mat3" xs | ||
642 | AN "M34F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
643 | AN "M42F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
644 | AN "M43F" xs -> error "WebGL 1 does not support matrices with this dimension" | ||
645 | AN "M44F" xs -> functionCall "mat4" xs -- where gen = gen | ||
646 | |||
647 | Prim3 "primIfThenElse" a b c -> gen a <+> "?" <+> gen b <+> ":" <+> gen c | ||
648 | -- TODO: Texture Lookup Functions | ||
649 | SwizzProj a x -> "(" <+> gen a <+> (")." <> text x) | ||
650 | ELam _ _ -> error "GLSL codegen for lambda function is not supported yet" | ||
651 | ELet (PVar _ _) (A3 "Sampler" _ _ (A1 "Texture2DSlot" (EString n))) _ -> text n | ||
652 | ELet (PVar _ n) (A3 "Sampler" _ _ (A2 "Texture2D" _ _)) _ -> text n | ||
653 | ELet _ _ _ -> error "GLSL codegen for let is not supported yet" | ||
654 | ETuple _ -> error "GLSL codegen for tuple is not supported yet" | ||
655 | |||
656 | -- Primitive Functions | ||
657 | PrimN ('P':'r':'i':'m':n) xs | n'@(_:_) <- trName (dropS n) -> case n' of | ||
658 | (c:_) | isAlpha c -> functionCall n' xs | ||
659 | [op, '_'] -> prefixOp [op] xs | ||
660 | n' -> binOp n' xs | ||
661 | where | ||
662 | ifType p a b = if all (p . tyOf) xs then a else b | ||
663 | |||
664 | dropS n | ||
665 | | last n == 'S' && init n `elem` ["Add", "Sub", "Div", "Mod", "BAnd", "BOr", "BXor", "BShiftL", "BShiftR", "Min", "Max", "Clamp", "Mix", "Step", "SmoothStep"] = init n | ||
666 | | otherwise = n | ||
667 | |||
668 | trName = \case | ||
669 | |||
670 | -- Arithmetic Functions | ||
671 | "Add" -> "+" | ||
672 | "Sub" -> "-" | ||
673 | "Neg" -> "-_" | ||
674 | "Mul" -> ifType isMatrix "matrixCompMult" "*" | ||
675 | "MulS" -> "*" | ||
676 | "Div" -> "/" | ||
677 | "Mod" -> ifType isIntegral "%" "mod" | ||
678 | |||
679 | -- Bit-wise Functions | ||
680 | "BAnd" -> "&" | ||
681 | "BOr" -> "|" | ||
682 | "BXor" -> "^" | ||
683 | "BNot" -> "~_" | ||
684 | "BShiftL" -> "<<" | ||
685 | "BShiftR" -> ">>" | ||
686 | |||
687 | -- Logic Functions | ||
688 | "And" -> "&&" | ||
689 | "Or" -> "||" | ||
690 | "Xor" -> "^" | ||
691 | "Not" -> ifType isScalar "!_" "not" | ||
692 | |||
693 | -- Integer/Float Conversion Functions | ||
694 | "FloatBitsToInt" -> "floatBitsToInt" | ||
695 | "FloatBitsToUInt" -> "floatBitsToUint" | ||
696 | "IntBitsToFloat" -> "intBitsToFloat" | ||
697 | "UIntBitsToFloat" -> "uintBitsToFloat" | ||
698 | |||
699 | -- Matrix Functions | ||
700 | "OuterProduct" -> "outerProduct" | ||
701 | "MulMatVec" -> "*" | ||
702 | "MulVecMat" -> "*" | ||
703 | "MulMatMat" -> "*" | ||
704 | |||
705 | -- Fragment Processing Functions | ||
706 | "DFdx" -> "dFdx" | ||
707 | "DFdy" -> "dFdy" | ||
708 | |||
709 | -- Vector and Scalar Relational Functions | ||
710 | "LessThan" -> ifType isScalarNum "<" "lessThan" | ||
711 | "LessThanEqual" -> ifType isScalarNum "<=" "lessThanEqual" | ||
712 | "GreaterThan" -> ifType isScalarNum ">" "greaterThan" | ||
713 | "GreaterThanEqual" -> ifType isScalarNum ">=" "greaterThanEqual" | ||
714 | "Equal" -> "==" | ||
715 | "EqualV" -> ifType isScalar "==" "equal" | ||
716 | "NotEqual" -> "!=" | ||
717 | "NotEqualV" -> ifType isScalar "!=" "notEqual" | ||
718 | |||
719 | -- Angle and Trigonometry Functions | ||
720 | "ATan2" -> "atan" | ||
721 | -- Exponential Functions | ||
722 | "InvSqrt" -> "inversesqrt" | ||
723 | -- Common Functions | ||
724 | "RoundEven" -> "roundEven" | ||
725 | "ModF" -> error "PrimModF is not implemented yet!" -- TODO | ||
726 | "MixB" -> "mix" | ||
727 | |||
728 | n | n `elem` | ||
729 | -- Logic Functions | ||
730 | [ "Any", "All" | ||
731 | -- Angle and Trigonometry Functions | ||
732 | , "ACos", "ACosH", "ASin", "ASinH", "ATan", "ATanH", "Cos", "CosH", "Degrees", "Radians", "Sin", "SinH", "Tan", "TanH" | ||
733 | -- Exponential Functions | ||
734 | , "Pow", "Exp", "Exp2", "Log2", "Sqrt" | ||
735 | -- Common Functions | ||
736 | , "IsNan", "IsInf", "Abs", "Sign", "Floor", "Trunc", "Round", "Ceil", "Fract", "Min", "Max", "Mix", "Step", "SmoothStep" | ||
737 | -- Geometric Functions | ||
738 | , "Length", "Distance", "Dot", "Cross", "Normalize", "FaceForward", "Reflect", "Refract" | ||
739 | -- Matrix Functions | ||
740 | , "Transpose", "Determinant", "Inverse" | ||
741 | -- Fragment Processing Functions | ||
742 | , "FWidth" | ||
743 | -- Noise Functions | ||
744 | , "Noise1", "Noise2", "Noise3", "Noise4" | ||
745 | ] -> map toLower n | ||
746 | |||
747 | _ -> "" | ||
748 | |||
749 | x -> error $ "GLSL codegen - unsupported expression: " ++ ppShow x | ||
750 | where | ||
751 | prefixOp o [a] = text o <+> parens (gen a) | ||
752 | binOp o [a, b] = parens (gen a) <+> text o <+> parens (gen b) | ||
753 | functionCall f a = text f <+> parens (hcat $ intersperse "," $ map gen a) | ||
754 | |||
755 | gen = genGLSLSubst s | ||
756 | |||
757 | isMatrix :: Ty -> Bool | ||
758 | isMatrix (TMat{}) = True | ||
759 | isMatrix _ = False | ||
760 | |||
761 | isIntegral :: Ty -> Bool | ||
762 | isIntegral TWord = True | ||
763 | isIntegral TInt = True | ||
764 | isIntegral (TVec _ TWord) = True | ||
765 | isIntegral (TVec _ TInt) = True | ||
766 | isIntegral _ = False | ||
767 | |||
768 | isScalarNum :: Ty -> Bool | ||
769 | isScalarNum = \case | ||
770 | TInt -> True | ||
771 | TWord -> True | ||
772 | TFloat -> True | ||
773 | _ -> False | ||
774 | |||
775 | isScalar :: Ty -> Bool | ||
776 | isScalar = isJust . scalarType | ||
777 | |||
778 | scalarType = \case | ||
779 | TBool -> Just "b" | ||
780 | TWord -> Just "u" | ||
781 | TInt -> Just "i" | ||
782 | TFloat -> Just "" | ||
783 | _ -> Nothing | ||
784 | |||
785 | vecConName = \case | ||
786 | TVec n t | is234 n, Just s <- scalarType t -> Just $ s ++ "vec" ++ show n | ||
787 | t -> Nothing | ||
788 | |||
789 | toGLSLType msg = \case | ||
790 | TBool -> "bool" | ||
791 | TWord -> "uint" | ||
792 | TInt -> "int" | ||
793 | TFloat -> "float" | ||
794 | x@(TVec n t) | Just s <- vecConName x -> s | ||
795 | TMat i j TFloat | is234 i && is234 j -> "mat" ++ if i == j then show i else show i ++ "x" ++ show j | ||
796 | TTuple [] -> "void" | ||
797 | t -> error $ "toGLSLType: " ++ msg ++ " " ++ ppShow t | ||
798 | |||
799 | is234 = (`elem` [2,3,4]) | ||
800 | |||
801 | |||
802 | -------------------------------------------------------------------------------- | ||
803 | |||
804 | data Exp_ a | ||
805 | = Pi_ Visibility SName a a | ||
806 | | Lam_ Visibility Pat a a | ||
807 | | Con_ (SName, a) [a] | ||
808 | | ELit_ Lit | ||
809 | | Fun_ (SName, a) [a] | ||
810 | | App_ a a | ||
811 | | Var_ SName a | ||
812 | | TType_ | ||
813 | | Let_ Pat a a | ||
814 | deriving (Show, Eq, Functor, Foldable, Traversable) | ||
815 | |||
816 | instance PShow Exp where pShowPrec p = text . show | ||
817 | |||
818 | pattern Pi h n a b = Exp (Pi_ h n a b) | ||
819 | pattern Lam h n a b = Exp (Lam_ h n a b) | ||
820 | pattern Con a b = Exp (Con_ a b) | ||
821 | pattern ELit a = Exp (ELit_ a) | ||
822 | pattern Fun a b = Exp (Fun_ a b) | ||
823 | pattern EApp a b = Exp (App_ a b) | ||
824 | pattern Var a b = Exp (Var_ a b) | ||
825 | pattern TType = Exp TType_ | ||
826 | pattern ELet a b c = Exp (Let_ a b c) | ||
827 | |||
828 | pattern EString s = ELit (LString s) | ||
829 | pattern EFloat s = ELit (LFloat s) | ||
830 | pattern EInt s = ELit (LInt s) | ||
831 | |||
832 | newtype Exp = Exp (Exp_ Exp) | ||
833 | deriving (Show, Eq) | ||
834 | |||
835 | toExp :: I.Exp -> Exp | ||
836 | toExp = flip runReader [] . flip evalStateT freshTypeVars . f | ||
837 | where | ||
838 | freshTypeVars = (flip (:) <$> map show [0..] <*> ['a'..'z']) | ||
839 | newName = gets head <* modify tail | ||
840 | f = \case | ||
841 | I.Var i -> asks (!!! i) | ||
842 | I.Pi b x (I.downE 0 -> Just y) -> Pi b "" <$> f x <*> f y | ||
843 | I.Pi b x y -> newName >>= \n -> do | ||
844 | t <- f x | ||
845 | Pi b n t <$> local (Var n t:) (f y) | ||
846 | I.Lam b x y -> newName >>= \n -> do | ||
847 | t <- f x | ||
848 | Lam b (PVar t n) t <$> local (Var n t:) (f y) | ||
849 | I.Con (I.ConName s _ _ t) xs -> con s <$> f t <*> mapM f xs | ||
850 | I.TyCon (I.TyConName s _ _ t _ _) xs -> con s <$> f t <*> mapM f xs | ||
851 | I.ELit l -> pure $ ELit l | ||
852 | I.Fun (I.FunName s _ t) xs -> fun s <$> f t <*> mapM f xs | ||
853 | I.CaseFun x@(I.CaseFunName _ t _) xs -> fun (show x) <$> f t <*> mapM f xs | ||
854 | I.App a b -> app' <$> f a <*> f b | ||
855 | I.PMLabel x _ -> f x | ||
856 | I.FixLabel _ x -> f x | ||
857 | I.TType -> pure TType | ||
858 | I.LabelEnd x -> f x | ||
859 | z -> error $ "toExp: " ++ show z | ||
860 | |||
861 | xs !!! i | i < 0 || i >= length xs = error $ show xs ++ " !! " ++ show i | ||
862 | xs !!! i = xs !! i | ||
863 | |||
864 | untick ('\'': s) = s | ||
865 | untick s = s | ||
866 | |||
867 | fun s t xs = Fun (untick s, t) xs | ||
868 | con s t xs = Con (untick s, t) xs | ||
869 | |||
870 | freeVars :: Exp -> Set.Set SName | ||
871 | freeVars = \case | ||
872 | Var n _ -> Set.singleton n | ||
873 | Con _ xs -> Set.unions $ map freeVars xs | ||
874 | ELit _ -> mempty | ||
875 | Fun _ xs -> Set.unions $ map freeVars xs | ||
876 | EApp a b -> freeVars a `Set.union` freeVars b | ||
877 | Pi _ n a b -> freeVars a `Set.union` (Set.delete n $ freeVars b) | ||
878 | Lam _ n a b -> freeVars a `Set.union` (foldr Set.delete (freeVars b) (patVars n)) | ||
879 | TType -> mempty | ||
880 | ELet n a b -> freeVars a `Set.union` (foldr Set.delete (freeVars b) (patVars n)) | ||
881 | |||
882 | type Ty = Exp | ||
883 | |||
884 | tyOf :: Exp -> Ty | ||
885 | tyOf = \case | ||
886 | Lam h (PVar _ n) t x -> Pi h n t $ tyOf x | ||
887 | EApp f x -> app (tyOf f) x | ||
888 | Var _ t -> t | ||
889 | Pi{} -> TType | ||
890 | Con (_, t) xs -> foldl app t xs | ||
891 | Fun (_, t) xs -> foldl app t xs | ||
892 | ELit l -> toExp $ I.litType l | ||
893 | TType -> TType | ||
894 | ELet a b c -> tyOf $ EApp (ELam a c) b | ||
895 | x -> error $ "tyOf: " ++ show x | ||
896 | where | ||
897 | app (Pi _ n a b) x = substE n x b | ||
898 | |||
899 | substE n x = \case | ||
900 | z@(Var n' _) | n' == n -> x | ||
901 | | otherwise -> z | ||
902 | Pi h n' a b | n == n' -> Pi h n' (substE n x a) b | ||
903 | Pi h n' a b -> Pi h n' (substE n x a) (substE n x b) | ||
904 | Lam h n' a b -> Lam h n' (substE n x a) $ if n `elem` patVars n' then b else substE n x b | ||
905 | Con cn xs -> Con cn (map (substE n x) xs) | ||
906 | Fun cn xs -> Fun cn (map (substE n x) xs) | ||
907 | TType -> TType | ||
908 | EApp a b -> app' (substE n x a) (substE n x b) | ||
909 | z -> error $ "substE: " ++ show z | ||
910 | |||
911 | app' (Lam _ (PVar _ n) _ x) b = substE n b x | ||
912 | app' a b = EApp a b | ||
913 | |||
914 | -------------------------------------------------------------------------------- Exp conversion -- TODO: remove | ||
915 | |||
916 | data Pat | ||
917 | = PVar Exp SName | ||
918 | | PTuple [Pat] | ||
919 | deriving (Eq, Show) | ||
920 | |||
921 | instance PShow Pat where pShowPrec p = text . show | ||
922 | |||
923 | patVars (PVar _ n) = [n] | ||
924 | patVars (PTuple ps) = concatMap patVars ps | ||
925 | |||
926 | patTy (PVar t _) = t | ||
927 | patTy (PTuple ps) = Con ("Tuple" ++ show (length ps), tupTy $ length ps) $ map patTy ps | ||
928 | |||
929 | tupTy n = foldr (:~>) TType $ replicate n TType | ||
930 | |||
931 | -- workaround for backward compatibility | ||
932 | etaRed (ELam (PVar _ n) (EApp f (EVar n'))) | n == n' && n `Set.notMember` freeVars f = f | ||
933 | etaRed (ELam (PVar _ n) (Prim3 (tupCaseName -> Just k) _ x (EVar n'))) | n == n' && n `Set.notMember` freeVars x = uncurry (\ps e -> ELam (PTuple ps) e) $ getPats k x | ||
934 | etaRed x = x | ||
935 | |||
936 | tupCaseName "Tuple2Case" = Just 2 | ||
937 | tupCaseName "Tuple3Case" = Just 3 | ||
938 | tupCaseName "Tuple4Case" = Just 4 | ||
939 | tupCaseName "Tuple5Case" = Just 5 | ||
940 | tupCaseName "Tuple6Case" = Just 6 | ||
941 | tupCaseName "Tuple7Case" = Just 7 | ||
942 | tupCaseName _ = Nothing | ||
943 | |||
944 | getPats 0 e = ([], e) | ||
945 | getPats i (ELam p e) = (p:) *** id $ getPats (i-1) e | ||
946 | |||
947 | ------------- | ||
948 | |||
949 | pattern EVar n <- Var n _ | ||
950 | pattern TVar t n = Var n t | ||
951 | |||
952 | pattern ELam n b <- Lam Visible n _ b where ELam n b = Lam Visible n (patTy n) b | ||
953 | |||
954 | pattern a :~> b = Pi Visible "" a b | ||
955 | infixr 1 :~> | ||
956 | |||
957 | pattern PrimN n xs <- Fun (n, t) (filterRelevant (n, 0) t -> xs) where PrimN n xs = Fun (n, builtinType n) xs | ||
958 | pattern Prim1 n a = PrimN n [a] | ||
959 | pattern Prim2 n a b = PrimN n [a, b] | ||
960 | pattern Prim3 n a b c <- PrimN n [a, b, c] | ||
961 | pattern Prim4 n a b c d <- PrimN n [a, b, c, d] | ||
962 | pattern Prim5 n a b c d e <- PrimN n [a, b, c, d, e] | ||
963 | |||
964 | builtinType = \case | ||
965 | "Output" -> TType | ||
966 | "Bool" -> TType | ||
967 | "Float" -> TType | ||
968 | "Nat" -> TType | ||
969 | "Zero" -> TNat | ||
970 | "Succ" -> TNat :~> TNat | ||
971 | "String" -> TType | ||
972 | "Sampler" -> TType | ||
973 | "VecS" -> TType :~> TNat :~> TType | ||
974 | n -> error $ "type of " ++ show n | ||
975 | |||
976 | filterRelevant _ _ [] = [] | ||
977 | filterRelevant i (Pi h n t t') (x: xs) = (if h == Visible then (x:) else id) $ filterRelevant (id *** (+1) $ i) (substE n x t') xs | ||
978 | |||
979 | pattern AN n xs <- Con (n, t) (filterRelevant (n, 0) t -> xs) where AN n xs = Con (n, builtinType n) xs | ||
980 | pattern A0 n = AN n [] | ||
981 | pattern A1 n a = AN n [a] | ||
982 | pattern A2 n a b = AN n [a, b] | ||
983 | pattern A3 n a b c <- AN n [a, b, c] | ||
984 | pattern A4 n a b c d <- AN n [a, b, c, d] | ||
985 | pattern A5 n a b c d e <- AN n [a, b, c, d, e] | ||
986 | |||
987 | pattern TCon0 n = A0 n | ||
988 | pattern TCon t n = Con (n, t) [] | ||
989 | |||
990 | pattern TUnit <- A0 "Tuple0" | ||
991 | pattern TBool = A0 "Bool" | ||
992 | pattern TWord <- A0 "Word" | ||
993 | pattern TInt <- A0 "Int" | ||
994 | pattern TNat = A0 "Nat" | ||
995 | pattern TFloat = A0 "Float" | ||
996 | pattern TString = A0 "String" | ||
997 | |||
998 | pattern Uniform n <- Prim1 "Uniform" n | ||
999 | |||
1000 | pattern Zero = A0 "Zero" | ||
1001 | pattern Succ n = A1 "Succ" n | ||
1002 | |||
1003 | pattern TVec n a = A2 "VecS" a (Nat n) | ||
1004 | pattern TMat i j a <- A3 "Mat" (Nat i) (Nat j) a | ||
1005 | |||
1006 | pattern Nat n <- (fromNat -> Just n) where Nat = toNat | ||
1007 | |||
1008 | toNat :: Int -> Exp | ||
1009 | toNat 0 = Zero | ||
1010 | toNat n = Succ (toNat $ n-1) | ||
1011 | |||
1012 | fromNat :: Exp -> Maybe Int | ||
1013 | fromNat Zero = Just 0 | ||
1014 | fromNat (Succ n) = (1 +) <$> fromNat n | ||
1015 | fromNat _ = Nothing | ||
1016 | |||
1017 | pattern TTuple xs <- (getTuple -> Just xs) | ||
1018 | pattern ETuple xs <- (getTuple -> Just xs) | ||
1019 | |||
1020 | getTuple (AN (tupName -> Just n) xs) | length xs == n = Just xs | ||
1021 | getTuple _ = Nothing | ||
1022 | |||
1023 | tupName = \case | ||
1024 | "Tuple0" -> Just 0 | ||
1025 | "Tuple2" -> Just 2 | ||
1026 | "Tuple3" -> Just 3 | ||
1027 | "Tuple4" -> Just 4 | ||
1028 | "Tuple5" -> Just 5 | ||
1029 | "Tuple6" -> Just 6 | ||
1030 | "Tuple7" -> Just 7 | ||
1031 | _ -> Nothing | ||
1032 | |||
1033 | pattern SwizzProj a b <- (getSwizzProj -> Just (a, b)) | ||
1034 | |||
1035 | getSwizzProj = \case | ||
1036 | Prim2 "swizzscalar" e (getSwizzChar -> Just s) -> Just (e, [s]) | ||
1037 | Prim2 "swizzvector" e (AN ((`elem` ["V2","V3","V4"]) -> True) (traverse getSwizzChar -> Just s)) -> Just (e, s) | ||
1038 | _ -> Nothing | ||
1039 | |||
1040 | getSwizzChar = \case | ||
1041 | A0 "Sx" -> Just 'x' | ||
1042 | A0 "Sy" -> Just 'y' | ||
1043 | A0 "Sz" -> Just 'z' | ||
1044 | A0 "Sw" -> Just 'w' | ||
1045 | _ -> Nothing | ||
1046 | |||
1047 | outputType = TCon0 "Output" | ||
1048 | boolType = TBool | ||
1049 | trueExp = TCon TBool "True" | ||
1050 | |||
diff --git a/src/LambdaCube/Compiler/Driver.hs b/src/LambdaCube/Compiler/Driver.hs index 68ec34dd..6beca81a 100644 --- a/src/LambdaCube/Compiler/Driver.hs +++ b/src/LambdaCube/Compiler/Driver.hs | |||
@@ -11,7 +11,7 @@ module LambdaCube.Compiler.Driver | |||
11 | , Infos | 11 | , Infos |
12 | , showRange | 12 | , showRange |
13 | , ErrorMsg(..) | 13 | , ErrorMsg(..) |
14 | , Exp | 14 | , Exp, toExp, tyOf, outputType, boolType, trueExp |
15 | ) where | 15 | ) where |
16 | 16 | ||
17 | import Data.List | 17 | import Data.List |
@@ -31,11 +31,10 @@ import System.Directory | |||
31 | import System.FilePath | 31 | import System.FilePath |
32 | import Debug.Trace | 32 | import Debug.Trace |
33 | 33 | ||
34 | import IR | ||
34 | import LambdaCube.Compiler.Pretty hiding ((</>)) | 35 | import LambdaCube.Compiler.Pretty hiding ((</>)) |
35 | import LambdaCube.Compiler.Infer (Info, Infos, ErrorMsg(..), showRange, PolyEnv(..), Export(..), ModuleR(..), ErrorT, throwErrorTCM, parseLC, joinPolyEnvs, inference_) | 36 | import LambdaCube.Compiler.Infer (Info, Infos, ErrorMsg(..), showRange, PolyEnv(..), Export(..), ModuleR(..), ErrorT, throwErrorTCM, parseLC, joinPolyEnvs, inference_) |
36 | import LambdaCube.Compiler.CGExp (Exp, toExp, outputType) | 37 | import LambdaCube.Compiler.CoreToIR |
37 | import IR | ||
38 | import qualified LambdaCube.Compiler.CoreToIR as IR | ||
39 | 38 | ||
40 | type EName = String | 39 | type EName = String |
41 | type MName = String | 40 | type MName = String |
@@ -153,11 +152,11 @@ parseAndToCoreMain m = either (throwErrorTCM . text) return . (\(e, i) -> flip ( | |||
153 | compileMain_ :: MonadMask m => PolyEnv -> ModuleFetcher (MMT m) -> IR.Backend -> FilePath -> MName -> m (Err (IR.Pipeline, Infos)) | 152 | compileMain_ :: MonadMask m => PolyEnv -> ModuleFetcher (MMT m) -> IR.Backend -> FilePath -> MName -> m (Err (IR.Pipeline, Infos)) |
154 | compileMain_ prelude fetch backend path fname = runMM fetch $ do | 153 | compileMain_ prelude fetch backend path fname = runMM fetch $ do |
155 | modify $ Map.insert (path </> "Prelude.lc") $ Right prelude | 154 | modify $ Map.insert (path </> "Prelude.lc") $ Right prelude |
156 | (IR.compilePipeline True backend *** id) <$> parseAndToCoreMain fname | 155 | (compilePipeline True backend *** id) <$> parseAndToCoreMain fname |
157 | 156 | ||
158 | -- | most commonly used interface for end users | 157 | -- | most commonly used interface for end users |
159 | compileMain :: [FilePath] -> IR.Backend -> MName -> IO (Either String IR.Pipeline) | 158 | compileMain :: [FilePath] -> IR.Backend -> MName -> IO (Either String IR.Pipeline) |
160 | compileMain path backend fname = fmap ((show +++ fst) . fst) $ runMM (ioFetch path) $ (IR.compilePipeline True backend *** id) <$> parseAndToCoreMain fname | 159 | compileMain path backend fname = fmap ((show +++ fst) . fst) $ runMM (ioFetch path) $ (compilePipeline True backend *** id) <$> parseAndToCoreMain fname |
161 | 160 | ||
162 | compileMain' :: MonadMask m => PolyEnv -> IR.Backend -> String -> m (Err (IR.Pipeline, Infos)) | 161 | compileMain' :: MonadMask m => PolyEnv -> IR.Backend -> String -> m (Err (IR.Pipeline, Infos)) |
163 | compileMain' prelude backend src = compileMain_ prelude fetch backend "." "Main" | 162 | compileMain' prelude backend src = compileMain_ prelude fetch backend "." "Main" |
diff --git a/test/runTests.hs b/test/runTests.hs index b84181bd..5e1939e5 100644 --- a/test/runTests.hs +++ b/test/runTests.hs | |||
@@ -22,7 +22,6 @@ import Control.DeepSeq | |||
22 | import qualified Data.Set as Set | 22 | import qualified Data.Set as Set |
23 | 23 | ||
24 | import LambdaCube.Compiler.Pretty hiding ((</>)) | 24 | import LambdaCube.Compiler.Pretty hiding ((</>)) |
25 | import LambdaCube.Compiler.CGExp (tyOf, outputType, boolType, trueExp) | ||
26 | import LambdaCube.Compiler.Driver | 25 | import LambdaCube.Compiler.Driver |
27 | import LambdaCube.Compiler.CoreToIR | 26 | import LambdaCube.Compiler.CoreToIR |
28 | import IR (Backend(..)) | 27 | import IR (Backend(..)) |