17 | module Compiler.Opts.Constructor
19 | import Core.CompileExpr
24 | data NextMN : Type where
27 | newMN : Ref NextMN Int => String -> Core Name
42 | data Magic : Type where
44 | Name -> (arity : Nat) ->
45 | (FC -> FC -> forall vars. Vect arity (CExp vars) -> CExp vars) ->
48 | magic : List Magic -> CExp vars -> Maybe (CExp vars)
49 | magic ms (CLam fc x exp) = CLam fc x <$> magic ms exp
50 | magic ms e = go ms e where
52 | fire : Magic -> CExp vars -> Maybe (CExp vars)
53 | fire (MagicCRef n arity f) (CApp fc (CRef fc' n') es) = do
55 | map (f fc fc') (toVect arity es)
58 | go : List Magic -> CExp vars -> Maybe (CExp vars)
60 | go (m :: ms) e = case fire m e of
64 | magic__integerToNat : FC -> FC -> forall vars. Vect 1 (CExp vars) -> CExp vars
65 | magic__integerToNat fc fc' [k]
66 | = CApp fc (CRef fc' (NS typesNS (UN $
Basic "prim__integerToNat"))) [k]
68 | magic__natMinus : FC -> FC -> forall vars. Vect 2 (CExp vars) -> CExp vars
69 | magic__natMinus fc fc' [m, n]
70 | = magic__integerToNat fc fc'
71 | [COp fc (Sub IntegerType) [m, n]]
75 | magic__natUnsuc : FC -> FC -> forall vars. Vect 1 (CExp vars) -> CExp vars
76 | magic__natUnsuc fc fc' [m]
77 | = COp fc (Sub IntegerType) [m, CPrimVal fc (BI 1)]
80 | natHack : List Magic
82 | [ MagicCRef (NS typesNS (UN $
Basic "natToInteger")) 1 (\ _, _, [k] => k)
83 | , MagicCRef (NS typesNS (UN $
Basic "integerToNat")) 1 magic__integerToNat
84 | , MagicCRef (NS typesNS (UN $
Basic "plus")) 2
85 | (\ fc, fc', [m,n] => COp fc (Add IntegerType) [m, n])
86 | , MagicCRef (NS typesNS (UN $
Basic "mult")) 2
87 | (\ fc, fc', [m,n] => COp fc (Mul IntegerType) [m, n])
88 | , MagicCRef (NS typesNS (UN $
Basic "minus")) 2 magic__natMinus
89 | , MagicCRef (NS typesNS (UN $
Basic "equalNat")) 2
90 | (\ fc, fc', [m,n] => COp fc (EQ IntegerType) [m, n])
91 | , MagicCRef (NS typesNS (UN $
Basic "compareNat")) 2
92 | (\ fc, fc', [m,n] => CApp fc (CRef fc' (NS eqOrdNS (UN $
Basic "compareInteger"))) [m, n])
96 | builtinMagic : forall vars. CExp vars -> Maybe (CExp vars)
97 | builtinMagic = magic natHack
99 | natBranch : CConAlt vars -> Bool
100 | natBranch (MkConAlt n ZERO _ _ _) = True
101 | natBranch (MkConAlt n SUCC _ _ _) = True
102 | natBranch _ = False
104 | trySBranch : CExp vars -> CConAlt vars -> Maybe (CExp vars)
105 | trySBranch n (MkConAlt nm SUCC _ [arg] sc)
106 | = Just (CLet (getFC n) arg YesInline (magic__natUnsuc (getFC n) (getFC n) [n]) sc)
107 | trySBranch _ _ = Nothing
109 | tryZBranch : CConAlt vars -> Maybe (CExp vars)
110 | tryZBranch (MkConAlt n ZERO _ [] sc) = Just sc
111 | tryZBranch _ = Nothing
113 | getSBranch : CExp vars -> List (CConAlt vars) -> Maybe (CExp vars)
114 | getSBranch n [] = Nothing
115 | getSBranch n (x :: xs) = trySBranch n x <|> getSBranch n xs
117 | getZBranch : List (CConAlt vars) -> Maybe (CExp vars)
118 | getZBranch [] = Nothing
119 | getZBranch (x :: xs) = tryZBranch x <|> getZBranch xs
122 | nat : {auto s : Ref NextMN Int} -> CExp vars -> Core (Maybe (CExp vars))
123 | nat (CCon fc _ ZERO _ []) = pure $
Just $
CPrimVal fc (BI 0)
124 | nat (CCon fc _ SUCC _ [x]) = pure $
Just $
COp fc (Add IntegerType) [CPrimVal fc (BI 1), x]
125 | nat (CConCase fc sc@(CLocal {}) alts def) =
126 | pure $
if any natBranch alts
128 | let defb = fromMaybe (CCrash fc "Nat case not covered") def
129 | salt = maybe defb id (getSBranch sc alts)
130 | zalt = maybe defb id (getZBranch alts)
131 | in Just (CConstCase fc sc [MkConstAlt (BI 0) zalt] (Just salt))
133 | nat (CConCase fc sc alts def) = do
135 | Just t <- nat (CConCase fc (CLocal fc First) (map weaken alts) (map weaken def))
136 | | Nothing => pure Nothing
137 | pure $
Just $
CLet fc x YesInline sc t
138 | nat _ = pure Nothing
146 | enumTag : Nat -> Int -> Constant
148 | if k <= 0xff then B8 (cast i)
149 | else if k <= 0xffff then B16 (cast i)
152 | enum : CExp vars -> Maybe (CExp vars)
153 | enum (CCon fc _ (ENUM n) (Just tag) []) = Just (CPrimVal fc (enumTag n tag))
154 | enum (CConCase fc sc alts def) = do
155 | alts' <- traverse toEnum alts
156 | Just $
CConstCase fc sc alts' def
158 | toEnum : CConAlt vars -> Maybe (CConstAlt vars)
159 | toEnum (MkConAlt nm (ENUM n) (Just tag) [] sc)
160 | = pure $
MkConstAlt (enumTag n tag) sc
170 | unitTree : Ref NextMN Int => CExp vars -> Core (Maybe (CExp vars))
171 | unitTree exp@(CConCase fc sc alts def) =
172 | let [MkConAlt _ UNIT _ [] e] = alts
173 | | _ => pure Nothing
175 | CLocal {} => pure $
Just e
176 | _ => pure $
Just $
CLet fc !(newMN "_unit") NotInline sc (weaken e)
177 | unitTree t = pure Nothing
185 | mkIntrinsicName : String -> Name
186 | mkIntrinsicName x = mkNamespacedName (Just intrinsicNS) (Basic x)
188 | intrinsicNS : Namespace
189 | intrinsicNS = mkNamespace "_builtin"
191 | conInfoNameTag : ConInfo -> Maybe (Name, Int)
192 | conInfoNameTag NIL = Just (mkIntrinsicName "NIL", 0)
193 | conInfoNameTag CONS = Just (mkIntrinsicName "CONS", 1)
194 | conInfoNameTag NOTHING = Just (mkIntrinsicName "NOTHING", 0)
195 | conInfoNameTag JUST = Just (mkIntrinsicName "JUST", 1)
196 | conInfoNameTag _ = Nothing
199 | intrinsicCons : List (Name, FC, CDef)
200 | intrinsicCons = process
207 | process : List (ConInfo, Nat) -> List (Name, FC, CDef)
208 | process = mapMaybe $
\(ci, ar) =>
209 | map (\(n, tag) => (n, (EmptyFC, MkCon (Just tag) ar Nothing))) $
conInfoNameTag ci
211 | tryIntrinsic : CExp vars -> Maybe (CExp vars)
212 | tryIntrinsic (CCon fc _ ci _ xs) =
213 | conInfoNameTag ci <&> \(n, tag) => CCon fc n ci (Just tag) xs
214 | tryIntrinsic (CConCase fc e alts def) =
216 | <&> \alts => CConCase fc e alts def
218 | go : CConAlt vars -> Maybe (CConAlt vars)
219 | go (MkConAlt _ ci _ as e) =
220 | conInfoNameTag ci <&> \(n, tag) => MkConAlt n ci (Just tag) as e
221 | tryIntrinsic _ = Nothing
223 | parameters (try : forall vars. CExp vars -> Core (CExp vars))
224 | rewriteCExp : CExp vars -> Core (CExp vars)
226 | rewriteSub : CExp vars -> Core (CExp vars)
228 | rewriteCConAlt : CConAlt vars -> Core (CConAlt vars)
229 | rewriteCConstAlt : CConstAlt vars -> Core (CConstAlt vars)
231 | rewriteCExp exp = do
232 | exp' <- rewriteSub exp
235 | rewriteSub (CLam fc x e) =
236 | CLam fc x <$> rewriteCExp e
237 | rewriteSub (CLet fc x inl e1 e2) =
238 | CLet fc x inl <$> rewriteCExp e1 <*> rewriteCExp e2
239 | rewriteSub (CApp fc f xs) =
240 | CApp fc <$> rewriteCExp f <*> traverse rewriteCExp xs
241 | rewriteSub (CCon fc n ci t xs) =
242 | CCon fc n ci t <$> traverse rewriteCExp xs
243 | rewriteSub (COp fc op xs) =
244 | COp fc op <$> traverseVect rewriteCExp xs
245 | rewriteSub (CExtPrim fc n xs) =
246 | CExtPrim fc n <$> traverse rewriteCExp xs
247 | rewriteSub (CForce fc lr e) =
248 | CForce fc lr <$> rewriteCExp e
249 | rewriteSub (CDelay fc lr e) =
250 | CDelay fc lr <$> rewriteCExp e
251 | rewriteSub (CConCase fc x alts def) =
254 | <*> traverse rewriteCConAlt alts
255 | <*> traverseOpt rewriteCExp def
256 | rewriteSub (CConstCase fc x alts def) =
259 | <*> traverse rewriteCConstAlt alts
260 | <*> traverseOpt rewriteCExp def
261 | rewriteSub e = pure e
263 | rewriteCConAlt (MkConAlt n ci t as e) = MkConAlt n ci t as <$> rewriteCExp e
264 | rewriteCConstAlt (MkConstAlt x e) = MkConstAlt x <$> rewriteCExp e
266 | sequence : List (forall vars. CExp vars -> Core (Maybe (CExp vars))) -> CExp vars -> Core (CExp vars)
267 | sequence [] e = pure e
268 | sequence (x :: xs) e = do
269 | e' <- fromMaybe e <$> x e
273 | constructorCExp : Ref NextMN Int => CExp vars -> Core (CExp vars)
274 | constructorCExp = rewriteCExp rw
276 | rw : forall vars. CExp vars -> Core (CExp vars)
278 | [ pure . builtinMagic
282 | , pure . tryIntrinsic
287 | constructorCDef : Ref NextMN Int => CDef -> Core CDef
288 | constructorCDef (MkFun args e) = MkFun args <$> constructorCExp e
289 | constructorCDef def = pure def