packages feed

elm-repl-0.2.1: src/Environment.hs

{-# LANGUAGE OverloadedStrings #-}
module Environment where

import Data.ByteString (ByteString)
import Data.Monoid     ((<>))
import qualified Data.ByteString.Char8 as BS
-- | TODO: Switch to a Char-based trie.
import Data.Trie       (Trie)
import qualified Data.Trie             as Trie

import Action (Term, Def(..))

data Repl = Repl
    { compilerPath :: FilePath
    , flags :: [String]
    , imports :: Trie String
    , adts :: Trie String
    , defs :: Trie String
    } deriving Show

empty :: FilePath -> Repl
empty compilerPath =
    Repl compilerPath [] Trie.empty Trie.empty (Trie.singleton firstVar (BS.unpack firstVar <> " = ()"))

firstVar :: ByteString
firstVar = "tsol"

lastVar :: ByteString
lastVar = "deltron3030"

toElm :: Repl -> String
toElm env = unlines $ "module Repl where" : decls
    where decls = concatMap Trie.elems [ imports env, adts env, defs env ]

insert :: Term -> Repl -> Repl
insert (src, def) env = case def of
  Nothing -> display src env
  Just (Import mport) -> noDisplay $ env { imports = Trie.insert (BS.pack mport) src (imports env) }
  Just (DataDef def)  -> noDisplay $ env { adts    = Trie.insert (BS.pack def)   src (adts env) }
  Just (VarDef var)   -> define (BS.pack var) src . display var $ env

define :: ByteString -> String -> Repl -> Repl
define name body env = env { defs = Trie.insert name body (defs env) }

display :: String -> Repl -> Repl
display = define lastVar . format
  where format body = (BS.unpack lastVar) ++ " =" ++ concatMap ("\n  "++) (lines body)

noDisplay :: Repl -> Repl
noDisplay env = env { defs = Trie.delete lastVar (defs env) }