packages feed

yapb-0.1.0: app/polyrpc/Main.hs

{-# LANGUAGE DeriveGeneric #-}

module Main where

import CommonParserUtil

import Token
import Lexer
import Terminal
import Parser
import Type
import Expr
import qualified CSType as TT
import qualified CSExpr as TE
import TypeCheck
import Compile
import Verify
import Execute

import Text.JSON.Generic
import Text.JSON.Pretty
import Text.PrettyPrint
-- For aeson
--import qualified Data.ByteString.Lazy.Char8 as B
--import Data.Aeson.Encode.Pretty
import Data.Maybe
import System.IO 
import System.Environment (getArgs)

main :: IO ()
main = do
  args <- getArgs
  cmd  <- getCmd args
  
  let files = _files cmd
  
  mapM_ (doProcess cmd) files -- [ ((build cmd file), file) | file <- files ]

doProcess cmd file = do
  putStrLn $ "[Reading] " ++ file
  text <- readFile file

  putStrLn "[Lexing]"
  terminalList <- lexing lexerSpec text
  verbose (_flag_debug_lex cmd) $ mapM_ (putStrLn) (map terminalToString terminalList)


  putStrLn "[Parsing]"
  exprSeqAst <- parsing parserSpec terminalList
  
  verbose (_flag_debug_parse cmd) $ putStrLn "Dumping..."
  verbose (_flag_debug_parse cmd) $ putStrLn $ show $ fromASTTopLevelDeclSeq exprSeqAst
  
  let toplevelDecls = fromASTTopLevelDeclSeq exprSeqAst

  
  putStrLn "[Type checking]"
  (gti, elab_toplevelDecls) <- typeCheck toplevelDecls
  verbose (_flag_debug_typecheck cmd) $ putStrLn "Dumping..."
  verbose (_flag_debug_typecheck cmd) $ putStrLn $ show $ elab_toplevelDecls

  print_rpc cmd file elab_toplevelDecls


  putStrLn "[Compiling]"
  (t_gti, funStore, t_expr) <- compile gti elab_toplevelDecls
  verbose (_flag_debug_compile cmd) $ putStrLn "Dumping...\nGlobal type information:\n"
  verbose (_flag_debug_compile cmd) $ putStrLn $ (show t_gti ++ "\n\nFunction stores:")
  verbose (_flag_debug_compile cmd) $ putStrLn $ (show funStore ++ "\n\nMain expression:")
  verbose (_flag_debug_compile cmd) $ putStrLn $ (show t_expr ++ "\n")

  print_cs cmd file funStore t_expr

  putStrLn "[Verifying generated codes]"
  verify t_gti funStore t_expr
  verbose (_flag_debug_verify cmd) $ putStrLn "[Well-typed]"

  putStrLn "[Executing codes]"
  v <- execute (_flag_debug_run cmd) t_gti funStore t_expr
  verbose (_flag_debug_run cmd) $ putStrLn $ "[Result]\n" ++ show v

  putStrLn "[Success]"


--
print_rpc cmd file elab_toplevelDecls = do
  let jsonfile = prefixOf file ++ ".json"
  if _flag_print_rpc_json cmd
  then do putStrLn $ "Writing to " ++ jsonfile
          writeFile jsonfile $ render
             $ pp_value $ toJSON (elab_toplevelDecls :: [TopLevelDecl])
  else return ()

print_cs cmd file funStore t_expr = do
  let jsonfile = prefixOf file ++ "_cs.json"
  if _flag_print_cs_json cmd
  then do putStrLn $ "Writing to " ++ jsonfile
          writeFile jsonfile $ render
             $ pp_value $ toJSON (funStore :: TE.FunctionStore, t_expr :: TE.Expr)
  else return ()

prefixOf str = reverse (removeDot (dropWhile (/='.') (reverse str)))
  where removeDot []     = []
        removeDot (x:xs) = xs  -- x must be '.'

--
readline msg = do
  putStr msg
  hFlush stdout
  readline'

readline' = do
  ch <- getChar
  if ch == '\n' then
    return ""
  else
    do line <- readline'
       return (ch:line)

--
data Cmd =
  Cmd { _flag_print_rpc_json :: Bool
      , _flag_print_cs_json :: Bool
      , _flag_debug_lex :: Bool
      , _flag_debug_parse :: Bool
      , _flag_debug_typecheck :: Bool
      , _flag_debug_compile :: Bool
      , _flag_debug_verify :: Bool
      , _flag_debug_run :: Bool
      , _files :: [String]
      }

initCmd =
  Cmd { _flag_print_rpc_json = False
      , _flag_print_cs_json  = False
      , _flag_debug_lex = False
      , _flag_debug_parse = False
      , _flag_debug_typecheck = False
      , _flag_debug_compile = False
      , _flag_debug_verify = False
      , _flag_debug_run = False
      , _files = []
      }

getCmd :: Monad m => [String] -> m Cmd
getCmd args = collect initCmd args 

collect :: Monad m => Cmd -> [String] -> m Cmd
collect cmd [] = return cmd
collect cmd ("--output-json":args) = do
  let new_cmd = cmd { _flag_print_rpc_json = True }
  collect new_cmd args
  
collect cmd ("--output-rpc-json":args) = do  
  let new_cmd = cmd { _flag_print_rpc_json = True }
  collect new_cmd args
  
collect cmd ("--output-cs-json":args) = do  
  let new_cmd = cmd { _flag_print_cs_json = True }
  collect new_cmd args

collect cmd ("--debug-lex":args) = do    
  let new_cmd = cmd { _flag_debug_lex = True }
  collect new_cmd args
  
collect cmd ("--debug-parse":args) = do    
  let new_cmd = cmd { _flag_debug_parse = True }
  collect new_cmd args
  
collect cmd ("--debug-typecheck":args) = do    
  let new_cmd = cmd { _flag_debug_typecheck = True }
  collect new_cmd args
  
collect cmd ("--debug-compile":args) = do    
  let new_cmd = cmd { _flag_debug_compile = True }
  collect new_cmd args
  
collect cmd ("--debug-verify":args) = do    
  let new_cmd = cmd { _flag_debug_verify = True }
  collect new_cmd args
  
collect cmd ("--debug-run":args) = do    
  let new_cmd = cmd { _flag_debug_run = True }
  collect new_cmd args
  
collect cmd (arg:args) = do
  let old_files = _files cmd 
  let new_cmd = cmd { _files = old_files ++ [arg] }
  collect new_cmd args

  
verbose b action = if b then action else return ()