module Main where

import LISS.Parser
import LISS.PrettyPrinter
import LISS.Semantics
import LISS.Checker
import LISS.Analyzer
import Why.PrettyPrinterFlattened

import UU.Parsing
import UU.Parsing.CharParser
import UU.Scanner
import UU.Pretty

import System.Directory
import System.IO
import System.Environment
import Control.Monad (when, liftM)

examplesDir = "examples"

scanFile fp =
     do contents <- readFile fp
     	return (scan keywordsText keywordsOps specialChars opChars noPos contents)

parseFile fp =
     do scanned <- Main.scanFile fp
     	parseIO pLiss scanned

runError (Left e) = error e
runError (Right x) = x

runFile fp = Main.parseFile fp >>= evalLiss . runError . LISS.Checker.check

check :: FilePath -> String -> Bool -> IO Bool
check fp s f = do 
  let scanned = scan keywordsText keywordsOps specialChars opChars noPos s
  tree <- parseIO pLiss scanned
  let prog = disp (pp tree) 0 ""
  let scanned2 = scan keywordsText keywordsOps specialChars opChars noPos prog
  tree2 <- parseIO pLiss scanned2
  when f (writeFile (examplesDir ++ "/" ++ fp ++ ".pp") prog)
  return (tree == tree2)

analyzeFile f = (Main.parseFile f >>= analyzeLiss) >>= writeFile (f++".mlw") . show . ppWhy

typeFile f = (Main.parseFile f) >>= print . LISS.Checker.check

execute _ checked "-r" = putStrLn "Evaluating..." >> evalLiss checked
execute _ checked "-d" = putStrLn "Evaluating (debug)..." >> (evalLissDebug checked >>= print)
execute fp checked "-a" = putStrLn "Analyzing..." >> (analyzeLiss checked >>= writeFile (fp++".mlw") . show . ppWhy)
	>> putStrLn ("Output Why file generated to "++fp++".mlw")
execute _ checked "-pp" = print $ pp checked
execute _ _ op = putStrLn ("Unknown option: "++op)

printUsage = (getProgName >>= putStr . ("Usage:\n\t"++)) >> putStrLn " <filepath> [ <option> ]\n"
	>> putStrLn "Possible options are:"
	>> putStrLn "\t-r\tRun."
	>> putStrLn "\t-d\tRun in debug mode (shows the final environment of the program)."
	>> putStrLn "\t-a\tAnalyze (convert to Why input code)."
	>> putStrLn "\t-pp\tPretty-print the parsed file."

main = do
	args <- getArgs
	if length args == 0 then printUsage else
	     do let fp = head args
		putStrLn "Parsing..."
		parsed <- Main.parseFile fp
		putStrLn "Checking..."
		let checked = runError $ LISS.Checker.check parsed
		if null (tail args) then print checked else mapM_ (execute fp checked) $ tail args

