2012-06-12 06:28:45 +00:00
|
|
|
module Optimize (optimize) where
|
|
|
|
|
|
|
|
import Ast
|
2013-05-29 23:20:38 +00:00
|
|
|
import Located
|
2012-06-12 06:28:45 +00:00
|
|
|
import Control.Arrow (second)
|
|
|
|
import Data.Char (isAlpha)
|
2012-09-14 04:31:34 +00:00
|
|
|
import Substitute
|
2012-06-12 06:28:45 +00:00
|
|
|
|
2012-08-01 23:37:37 +00:00
|
|
|
optimize (Module name ims exs stmts) =
|
|
|
|
Module name ims exs (map optimizeStmt stmts)
|
2012-06-12 06:28:45 +00:00
|
|
|
|
2012-08-01 23:37:37 +00:00
|
|
|
optimizeStmt stmt = if stmt == stmt' then stmt' else optimizeStmt stmt'
|
2012-11-23 03:48:54 +00:00
|
|
|
where stmt' = simp stmt
|
2012-08-01 23:37:37 +00:00
|
|
|
|
2012-11-23 03:48:54 +00:00
|
|
|
class Simplify a where
|
|
|
|
simp :: a -> a
|
|
|
|
|
|
|
|
instance Simplify Statement where
|
|
|
|
simp (Definition def) = Definition (simp def)
|
|
|
|
simp (ImportEvent js b elm t) = ImportEvent js (simp b) elm t
|
|
|
|
simp stmt = stmt
|
|
|
|
|
|
|
|
instance Simplify Def where
|
|
|
|
simp (FnDef func args e) = FnDef func args (simp e)
|
|
|
|
simp (OpDef op a1 a2 e) = OpDef op a1 a2 (simp e)
|
2013-06-03 07:44:45 +00:00
|
|
|
simp x = x
|
2012-12-25 08:39:18 +00:00
|
|
|
|
2013-05-29 23:20:38 +00:00
|
|
|
instance Simplify e => Simplify (Located e) where
|
|
|
|
simp (L t s e) = L t s (simp e)
|
2012-11-23 03:48:54 +00:00
|
|
|
|
|
|
|
instance Simplify Expr where
|
|
|
|
simp expr =
|
2012-06-12 06:28:45 +00:00
|
|
|
let f = simp in
|
|
|
|
case expr of
|
|
|
|
Range e1 e2 -> Range (f e1) (f e2)
|
|
|
|
Binop op e1 e2 -> simp_binop op (f e1) (f e2)
|
|
|
|
Lambda x e -> Lambda x (f e)
|
2012-12-25 08:39:18 +00:00
|
|
|
Record fs -> Record (map (\(f,as,e) -> (f, as, simp e)) fs)
|
2013-05-29 23:20:38 +00:00
|
|
|
App (L t s (Lambda x e1)) e2 ->
|
|
|
|
if isValue e2' then subst x e2' e1' else App (L t s (Lambda x ce1')) ce2'
|
|
|
|
where ce1'@(L _ _ e1') = f e1
|
|
|
|
ce2'@(L _ _ e2') = f e2
|
2012-06-12 06:28:45 +00:00
|
|
|
App e1 e2 -> App (f e1) (f e2)
|
|
|
|
If e1 e2 e3 -> simp_if (f e1) (f e2) (f e3)
|
2012-11-23 03:48:54 +00:00
|
|
|
Let defs e -> Let (map simp defs) (f e)
|
2012-06-12 06:28:45 +00:00
|
|
|
Data name es -> Data name (map f es)
|
|
|
|
Case e cases -> Case (f e) (map (second f) cases)
|
|
|
|
_ -> expr
|
|
|
|
|
2013-05-29 23:20:38 +00:00
|
|
|
simp_if (L _ _ (Boolean b)) (L _ _ e2) (L _ _ e3) = if b then e2 else e3
|
2012-06-12 06:28:45 +00:00
|
|
|
simp_if a b c = If a b c
|
|
|
|
|
2012-12-25 08:39:18 +00:00
|
|
|
isValue e =
|
|
|
|
case e of { IntNum _ -> True
|
|
|
|
; FloatNum _ -> True
|
|
|
|
; Chr _ -> True
|
|
|
|
; Str _ -> True
|
|
|
|
; Boolean _ -> True
|
|
|
|
; Var _ -> True
|
|
|
|
; Data _ _ -> True
|
|
|
|
; _ -> False }
|
2012-09-14 04:31:34 +00:00
|
|
|
|
2012-08-09 14:38:18 +00:00
|
|
|
simp_binop = binop
|
2012-06-12 06:28:45 +00:00
|
|
|
|
2013-05-29 23:20:38 +00:00
|
|
|
binop op ce1@(L t1 s1 e1) ce2@(L t2 s2 e2) =
|
|
|
|
let c1 = L t1 s1 in
|
|
|
|
let c2 = L t2 s2 in
|
2012-12-25 08:39:18 +00:00
|
|
|
case (op, e1, e2) of
|
|
|
|
(_, IntNum n, IntNum m) -> case op of
|
|
|
|
{ "+" -> IntNum $ (+) n m
|
|
|
|
; "-" -> IntNum $ (-) n m
|
|
|
|
; "*" -> IntNum $ (*) n m
|
|
|
|
; "^" -> IntNum $ n ^ m
|
|
|
|
; "div" -> IntNum $ div n m
|
|
|
|
; "mod" -> IntNum $ mod n m
|
|
|
|
; "<" -> Boolean $ n < m
|
|
|
|
; ">" -> Boolean $ n < m
|
|
|
|
; "<=" -> Boolean $ n <= m
|
|
|
|
; ">=" -> Boolean $ n >= m
|
|
|
|
; "==" -> Boolean $ n == m
|
|
|
|
; "/=" -> Boolean $ n /= m
|
|
|
|
; _ -> Binop op ce1 ce2 }
|
|
|
|
|
|
|
|
-- flip order to move lone integers to the left
|
|
|
|
("+", _, IntNum n) -> binop "+" ce2 ce1
|
|
|
|
("*", _, IntNum n) -> binop "*" ce2 ce1
|
|
|
|
|
|
|
|
("+", IntNum 0, _) -> e2
|
2013-05-29 23:20:38 +00:00
|
|
|
("+", IntNum n, Binop "+" (L _ _ (IntNum m)) ce) ->
|
2012-12-25 08:39:18 +00:00
|
|
|
binop "+" (c1 $ IntNum (n+m)) ce
|
2013-05-29 23:20:38 +00:00
|
|
|
("+", Binop "+" (L _ _ (IntNum n)) ce1'
|
|
|
|
, Binop "+" (L _ _ (IntNum m)) ce2') ->
|
|
|
|
binop "+" (notLocated $ IntNum (n+m)) (notLocated $ Binop "+" ce1' ce2')
|
2012-12-25 08:39:18 +00:00
|
|
|
|
|
|
|
("*", IntNum 0, _) -> e1
|
|
|
|
("*", IntNum 1, _) -> e2
|
2013-05-29 23:20:38 +00:00
|
|
|
("*", IntNum n, Binop "*" (L _ _ (IntNum m)) ce) ->
|
|
|
|
binop "*" (notLocated $ IntNum (n*m)) ce
|
|
|
|
("*", Binop "*" (L _ _ (IntNum n)) ce1'
|
|
|
|
, Binop "*" (L _ _ (IntNum m)) ce2') ->
|
|
|
|
binop "*" (notLocated $ IntNum (n*m)) (notLocated $ Binop "*" ce1' ce2')
|
2012-12-25 08:39:18 +00:00
|
|
|
|
|
|
|
("-", _, IntNum 0) -> e1
|
|
|
|
("/", _, IntNum 1) -> e1
|
|
|
|
("div", _, IntNum 1) -> e1
|
|
|
|
|
|
|
|
(_, Boolean n, Boolean m) -> case op of "&&" -> Boolean $ n && m
|
|
|
|
"||" -> Boolean $ n || m
|
|
|
|
_ -> Binop op ce1 ce2
|
|
|
|
|
|
|
|
("&&", Boolean True, _) -> e2
|
|
|
|
("&&", Boolean False, _) -> Boolean False
|
|
|
|
("||", Boolean True, _) -> Boolean True
|
|
|
|
("||", Boolean False, _) -> e2
|
|
|
|
|
2013-05-29 23:20:38 +00:00
|
|
|
("::", _, _) -> let (L _ _ e) = cons ce1 ce2 in e
|
2012-12-25 08:39:18 +00:00
|
|
|
|
|
|
|
("++", Str s1, Str s2) -> Str $ s1 ++ s2
|
2013-05-29 23:20:38 +00:00
|
|
|
("++", Str s1, Binop "++" (L _ _ (Str s2)) ce) ->
|
2012-12-25 08:39:18 +00:00
|
|
|
Binop "++" (c1 $ Str $ s1 ++ s2) ce
|
2013-05-29 23:20:38 +00:00
|
|
|
("++", Binop "++" e (L _ _ (Str s1)), Str s2) ->
|
2012-12-25 08:39:18 +00:00
|
|
|
Binop "++" e (c1 $ Str $ s1 ++ s2)
|
|
|
|
|
|
|
|
("++", Data "Nil" [], _) -> e2
|
|
|
|
("++", _, Data "Nil" []) -> e1
|
2013-05-29 23:20:38 +00:00
|
|
|
("++", Data "Cons" [h,t], _) -> Data "Cons" [h, notLocated $ binop "++" t ce2]
|
2012-12-25 08:39:18 +00:00
|
|
|
|
2013-05-21 20:09:08 +00:00
|
|
|
("|>", _, _) -> App ce2 ce1
|
|
|
|
("<|", _, _) -> App ce1 ce2
|
2012-12-25 08:39:18 +00:00
|
|
|
(".", _, _) ->
|
2013-05-29 23:20:38 +00:00
|
|
|
Lambda "x" (notLocated $
|
|
|
|
App ce1 (notLocated $ App ce2 (notLocated $ Var "x")))
|
2012-12-25 08:39:18 +00:00
|
|
|
|
|
|
|
_ | isAlpha (head op) || '_' == head op ->
|
2013-05-29 23:20:38 +00:00
|
|
|
App (notLocated $ App (notLocated $ Var op) ce1) ce2
|
2012-12-25 08:39:18 +00:00
|
|
|
| otherwise -> Binop op ce1 ce2
|