module L05B where
-- Week 5 
-- Recursive data types. 
-- Part 1: The expression game × 
-- dave@chalmers.se
-- 2016-09-29

import Test.QuickCheck
------------------------------------------------------
xx = undefined -- for incomplete code

data Expr = Num Integer
          | Add Expr Expr
          | Mul Expr Expr         
 deriving Eq -- ,Show)

instance Show Expr where
  show = showExpr


-- (1+2)*4
ex1 = Mul (Add (Num 1) (Num 2)) (Num 4)

-- 1 + 2 * 4
ex2 = Add (Num 1) (Mul (Num 2) (Num 4) )



eval :: Expr -> Integer
eval (Num n)     = n
eval (Add e1 e2) = eval e1 + eval e2 
eval (Mul e1 e2) = eval e1 * eval e2 

showExpr :: Expr -> String
showExpr (Num n)     = show n
showExpr (Add e1 e2) = showExpr e1 ++ " + " ++ showExpr e2 
showExpr (Mul e1 e2) = showFactor e1 ++ " * " ++ showFactor e2
  where showFactor (Add e1 e2) = "(" ++ showExpr (Add e1 e2) ++ ")"
        showFactor e           = showExpr e
{- 
1 + (2 + 3)
1 + (2 * 3)
1 * (2 + 3)
-}

instance Arbitrary Expr
  where arbitrary = sized rExp 
  
rExp :: Int -> Gen Expr
rExp s = frequency [(1,rNum),(s,rBin)]
  where 
  rNum = do
     n <- arbitrary
     return $ Num n
   
  rBin = do
     op <- elements [Add,Mul]
     e1 <- rExp s'
     e2 <- rExp s'
     return $ op e1 e2
  s' = s `div` 2 



-----------------------------------------------

difficulty = 3
main :: IO()
main = do
   -- let q = "1+1"
   qs <- sample' (rExp difficulty)
   let q = last qs
   let a = show $ eval q
   putStrLn $ "What is the value of " ++ show q
   ans <- getLine   
   putStrLn $ if (ans == a)
                 then "Correct!"
                 else "Fail! Correct answer was: " ++ show a
   main
----------------------------------------------------------------
-- * Reading Expressions