module ToC (toC) where
import Text.PrettyPrint.HughesPJ
import Graph
import TSort
import Control.Monad (liftM2)
import Control.Monad.Reader () -- Monad ((->) e)

t = text

toC::String->Graph->Doc
toC fnname graph =
    let is = inlets graph
        os = outlets graph in
    (case outlets graph of
       [o] -> t"double"<+>t fnname<>
              (parens.cat.punctuate (t", ").map t.
               map ("double "++)) is
       _ -> t"void"<+>t fnname<>
            (parens.cat.punctuate (t", ").map t)
            (map ("double "++) is ++ map ("double* _"++) os)
    ) <+>
    lbrace $+$
    nest 2 ((vcat.concat)
            [map statement (tsort (nodes graph) mustComeBefore)
            ,case outlets graph of
               [o] -> [t"return"<+>t o<>t";"]
               os -> map (\n->t"*_"<>t n<+>t"="<+>t n<>t";") os
            ]) $+$
    rbrace

binopL::[String]->String->String->Doc
binopL inputs op output =
    t"double"<+>t output<+>t"="<+>
    (cat.punctuate (t op).map t$inputs)<>
    t";"

statement::Node->Doc
statement (Node inputs Add [output]) = binopL inputs "+" output
statement (Node inputs Sub [output]) = binopL inputs "-" output
statement (Node inputs Mul [output]) = binopL inputs "*" output
statement (Node inputs Div [output]) = binopL inputs "/" output
statement (Node inputs (App fnname) [output]) =
    t"double"<+>t output<+>t "="<+>
    t fnname<>(parens.cat.punctuate (t ",").map t$inputs)<>
    t";"
statement (Node [input] (Put varname) []) =
    t"self"<>t"->"<>t varname<+>t"="<+>t input<>t";"
statement (Node [] (Get varname) [output]) =
    t"double"<+>t output<+>t"="<+>t"self"<>t"->"<>t varname<>t";"
