module Statement(T, toString, fromString, exec, parse) where
import Prelude hiding (return, fail)
import Parser hiding (T)
import qualified Dictionary
import qualified Expr
type T = Statement
data Statement =
    Assignment String Expr.T |
    Skip |
    Scope [Statement] |
    Read String |
    Write Expr.T |
    While Expr.T Statement |
    Repeat Statement Expr.T |
    If Expr.T Statement Statement
    deriving Show

assignment = word #- accept ":=" # Expr.parse #- require ";" >-> buildAss
buildAss (v, e) = Assignment v e

skip = accept "skip" # require ";" >-> buildSkip
buildSkip (_, _) = Skip

read' = accept "read" -# word #- require ";" >-> buildRead
buildRead = Read

write' = accept "write" -# Expr.parse #- require ";" >-> buildWrite
buildWrite = Write

scope = accept "begin" -# rec #- require "end" >-> buildScope
buildScope = Scope

ifs = accept "if" -# Expr.parse # require "then" -# parse # require "else" -# parse >-> buildIf
buildIf ((e, s1), s2) = If e s1 s2

whl = accept "while" -# Expr.parse # require "do" -# parse >-> buildWhile
buildWhile (e, s) = While e s

rpt = accept "repeat" -# parse # require "until" -# Expr.parse #- require ";" >-> buildRepeat
buildRepeat (s, e) = Repeat s e

exec :: [T] -> Dictionary.T String Integer -> [Integer] -> [Integer]
exec (If cond thenStmts elseStmts: stmts) dict input = 
    if (Expr.value cond dict)>0 
    then exec (thenStmts: stmts) dict input
    else exec (elseStmts: stmts) dict input
exec (Skip : stmts) dict input = exec stmts dict input
-- May be wrong order of (var, i) below
exec (Read var: stmts) dict (i:is) =
    exec stmts (Dictionary.insert (var,i) dict) is
exec (Write var: stmts) dict input = (Expr.value var dict) : exec stmts dict input
exec (Assignment var val: stmts) dict input =
    exec stmts (Dictionary.insert (var, (Expr.value val dict)) dict) input
exec (Scope xs: stmts) dict input = exec (xs ++ stmts) dict input
exec (While cond doStmt: stmts) dict input =
    if (Expr.value cond dict)>0
    then exec (doStmt: While cond doStmt: stmts) dict input
    else exec stmts dict input
exec (Repeat repeatStmt cond: stmts) dict input =
    exec (Scope (
            repeatStmt : [
            If cond
                Skip (
                Repeat repeatStmt cond)] ) :
        stmts) dict input
exec [] dict input = []

str (Assignment var val) = (show var) ++ ":=" ++ (Expr.toString val) ++ "\n"
str (Skip) = "skip\n"
str (Read var) = "read " ++ (show var) ++ "\n"
str (Write e) = "write " ++ (Expr.toString e) ++ "\n"
str (Scope xs) = (foldl (++) "begin\n" (map toString xs)) ++ "end\n"
str (If cond thenStm elseStm) = "if " ++ (Expr.toString cond) ++
                                " then\n" ++ (toString thenStm) ++
                                "else\n" ++ (toString elseStm)
str (While cond doStm) = "while " ++ (Expr.toString cond) ++
                         " do\n" ++ (toString doStm) ++ "\n"
str (Repeat repStm cond) = "repeat\n" ++ (toString repStm) ++
                           "until " ++ (Expr.toString cond) ++ "\n"

instance Parse Statement where
  parse = assignment ! skip ! read' ! write' ! scope ! ifs ! whl ! rpt
  toString = str
