packages feed

Elm-0.1.0: src/Initialize.hs

module Initialize (initialize) where

import Ast
import Control.Arrow (first)
import Control.Monad
import Data.Char (isAlpha)
import Data.Maybe (mapMaybe)
import Data.Either (rights)
import FreeVar
import Lexer
import Parser (toExpr,toDefs)
import Rename (rename)
import Replace
import System.IO.Unsafe

initialize str = do
   expr <- toDefs =<< tokenize str
--   let rexpr = rename expr
--   let init = simp_loop rexpr
--   return $ if depth init < depth rexpr then init else rexpr
   return $ rename expr
{--
simp_loop exp = if exp == exp' then exp' else simp_loop exp'
    where exp' = simp exp

simp expr =
    let f = simp in
    case expr of
      Range e1 e2 -> simp_range (f e1) (f e2)
      Binop op e1 e2 -> simp_binop op (f e1) (f e2)
      Lambda x e -> Lambda x (f e)
      App e1 e2 -> simp_app (f e1) (f e2)
      If e1 e2 e3 -> simp_if (f e1) (f e2) (f e3)
      Lift e es -> Lift (f e) $ map f es
      Fold e1 e2 e3 -> Fold (f e1) (f e2) (f e3)
      Async e -> Async (f e)
      Let x e1 e2 -> simp_let x (f e1) (f e2)
      Data name es -> Data name (map f es)
      Case e cases -> simp_case (f e) cases
      _ -> expr

data Status = NoMatch | Quit deriving (Show,Eq)

simp_case v cases =
    case v of
      Data _ _ -> case rights $ map (\(p,e) -> match p v e) cases of
                    { v:_ -> v; _ -> Case v cases }
      _ -> Case v cases

match p v hole =
    case p of PAnything -> return hole
              PVar x -> return $ Let x v hole
              PData pn ps ->
                  case v of
                    Data vn vs -> if pn /= vn then Left NoMatch else
                                      foldM (flip ($)) hole (zipWith match ps vs)
                    _ -> Left Quit

simp_let x e1 e2
    | not (x `freeIn` e2) = e2
    | isValue e1 = Let x e1 (replace x e1 e2)
    | otherwise  = Let x e1 e2

simp_app e1 e2 =
    case e1 of
      Let x s e -> if x `freeIn` e2 then error "Overlapping names!" else
                       Let x s (App e e2)
      Lambda x e -> Let x e2 e
{--
      Var "constant" -> App (Lambda "v" (Lift (Var "v") [])) e2
      Var "async" -> Async e2
      Var "foldp" -> Lambda "b" . Lambda "s" $ (Fold e2 (Var "b") (Var "s"))
      Var "lift"  -> Lambda "s" (Lift e2 [Var "s"])
      Var "lift2" -> Lambda "s1" . Lambda "s2" $ (Lift e2 [Var "s1",Var "s2"])
--}
      _ -> App e1 e2

simp_if (Boolean b) e2 e3 = if b then e2 else e3
simp_if a b c = If a b c

isValue expr =
    case expr of
      Number _ -> True
      Chr _ -> True
      Boolean _ -> True
      Range _ _ -> True
      Lambda _ _ -> True
      Data _ _ -> True
      Var _ -> True
      _ -> False

simp_range lo hi = toAST (parse code)
    where toAST = either (error "Compilation Failure") (\f -> App (App f lo) hi)
          parse str = toExpr =<< tokenize str
          code = "let range xs lo hi = \
                 \if hi < lo then xs else range (hi:xs) lo (hi-1) in\
                 \ \\x y -> range [] x y"

simp_binop "mod" (Number n) (Number m) = Number (mod n m)
simp_binop "mod" e1 e2 = Binop "mod" e1 e2
simp_binop str e1 e2
    | isAlpha (head str) || '_' == head str =
        App (App (Var str) e1) e2
    | otherwise = binop str e1 e2

binop op (Number n) (Number m) = f n m
    where f a b = case op of
                    { "+" -> Number $ (+) a b
                    ; "-" -> Number $ (-) a b
                    ; "*" -> Number $ (*) a b
                    --; "/" -> Number $ div a b
                    ; "<" -> Boolean $ a < b
                    ; ">" -> Boolean $ a < b
                    ; "<=" -> Boolean $ a <= b
                    ; ">=" -> Boolean $ a >= b
                    ; "==" -> Boolean $ a == b
                    ; "/=" -> Boolean $ a /= b
                    ;  _  -> Binop op (Number n) (Number m) }

binop "-" e (Number 0) = e
binop "+" (Number 0) e = e
binop "+" (Number n) (Binop "+" (Number m) e) = binop "+" (Number (n+m)) e
binop "+" (Number n) (Binop "+" e (Number m)) = binop "+" (Number (n+m)) e

binop "/" e (Number 1) = e
binop "*" (Number 0) e = Number 0
binop "*" (Number 1) e = e
binop "*" (Number n) (Binop "*" (Number m) e) = binop "*" (Number (n*m)) e
binop "*" (Number n) (Binop "*" e (Number m)) = binop "*" (Number (n*m)) e

binop "+" e (Number n) = binop "+" (Number n) e
binop "*" e (Number n) = binop "*" (Number n) e

binop op (Boolean n) (Boolean m) = f n m
    where f a b = case op of { "&&" -> Boolean $ (&&) n m
                             ; "||" -> Boolean $ (||) n m
                             ;  _  -> Binop op (Boolean n) (Boolean m) }

binop "&&" (Boolean  True) e = e
binop "&&" (Boolean False) e = Boolean False
binop "||" (Boolean  True) e = Boolean True
binop "||" (Boolean False) e = e

binop op e (Boolean n) = binop op (Boolean n) e

binop ":" h t = cons h t
binop "++" (Data "Nil" []) e = e
binop "++" e (Data "Nil" []) = e
binop "++" (Data "Cons" [h,t]) e = Data "Cons" [h, binop "++" t e]

binop "$" e1 e2 = App e1 e2

binop op e1 e2 = Binop op e1 e2
--}