{- | Code generation (codegen) stage of the compiler pipeline.

This module exposes some options for configuring what C code is generated and
how it is represented.
-}
module Codegen where

import qualified Common.Compiler as Compiler
import Common.Default (Default (..))

import qualified IR.IR as I

import qualified Text.PrettyPrint.Mainland as C
import qualified Text.PrettyPrint.Mainland.Class as C

import Codegen.Codegen (genProgram)
import System.Console.GetOpt (
  ArgDescr (..),
  OptDescr (..),
 )


-- | Operation modes for the codegen compiler stage.
data Mode = Continue
  deriving (Mode -> Mode -> Bool
(Mode -> Mode -> Bool) -> (Mode -> Mode -> Bool) -> Eq Mode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mode -> Mode -> Bool
$c/= :: Mode -> Mode -> Bool
== :: Mode -> Mode -> Bool
$c== :: Mode -> Mode -> Bool
Eq, Int -> Mode -> ShowS
[Mode] -> ShowS
Mode -> String
(Int -> Mode -> ShowS)
-> (Mode -> String) -> ([Mode] -> ShowS) -> Show Mode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Mode] -> ShowS
$cshowList :: [Mode] -> ShowS
show :: Mode -> String
$cshow :: Mode -> String
showsPrec :: Int -> Mode -> ShowS
$cshowsPrec :: Int -> Mode -> ShowS
Show)


-- | Compiler options for the codegen compiler stage.
data Options = Options
  { Options -> Mode
mode :: Mode
  , Options -> Int
textWidth :: Int
  }
  deriving (Options -> Options -> Bool
(Options -> Options -> Bool)
-> (Options -> Options -> Bool) -> Eq Options
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Options -> Options -> Bool
$c/= :: Options -> Options -> Bool
== :: Options -> Options -> Bool
$c== :: Options -> Options -> Bool
Eq, Int -> Options -> ShowS
[Options] -> ShowS
Options -> String
(Int -> Options -> ShowS)
-> (Options -> String) -> ([Options] -> ShowS) -> Show Options
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Options] -> ShowS
$cshowList :: [Options] -> ShowS
show :: Options -> String
$cshow :: Options -> String
showsPrec :: Int -> Options -> ShowS
$cshowsPrec :: Int -> Options -> ShowS
Show)


instance Default Options where
  def :: Options
def = Options :: Mode -> Int -> Options
Options{mode :: Mode
mode = Mode
Continue, textWidth :: Int
textWidth = Int
120}


-- | CLI options for the codegen compiler stage.
options :: [OptDescr (Options -> Options)]
options :: [OptDescr (Options -> Options)]
options =
  [ String
-> [String]
-> ArgDescr (Options -> Options)
-> String
-> OptDescr (Options -> Options)
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option
      String
""
      [String
"codegen-textwidth"]
      ((String -> Options -> Options)
-> String -> ArgDescr (Options -> Options)
forall a. (String -> a) -> String -> ArgDescr a
ReqArg (\String
tw Options
o -> Options
o{textWidth :: Int
textWidth = String -> Int
forall a. Read a => String -> a
read String
tw}) String
"<textwidth>")
      String
"Line width for pretty-printing the generated C code."
  ]


-- | Codegen compiler stage.
run :: Options -> I.Program I.Type -> Compiler.Pass String
run :: Options -> Program Type -> Pass String
run Options
opt Program Type
ir = do
  [Definition]
cdefs <- Program Type -> Pass [Definition]
genProgram Program Type
ir
  String -> Pass String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> Pass String) -> String -> Pass String
forall a b. (a -> b) -> a -> b
$ Int -> Doc -> String
C.pretty (Options -> Int
textWidth Options
opt) (Doc -> String) -> Doc -> String
forall a b. (a -> b) -> a -> b
$ [Definition] -> Doc
forall a. Pretty a => [a] -> Doc
C.pprList [Definition]
cdefs