{-# LANGUAGE DeriveGeneric #-} module PropertyInterp ( interpProps ) where import Ast import Invalid import Text.PrettyPrint.GenericPretty -- In the lists index 0 is used for predifined variables: Title, Total, MaxPoints -- This should refactored to real monadic programming data PropertyValue = StrVal String | DoubVal Double deriving (Eq, Show, Generic) instance Out PropertyValue interpProps :: Judgement -> Either Invalid Judgement interpProps j = case (interpJudgement j) of Right (jnew, _) -> Right jnew Left invalid -> Left invalid interpJudgement :: Judgement -> Either Invalid (Judgement, [(String, PropertyValue)]) interpJudgement (j @ (Judgement (h, prop, cs, js))) = do updlist <- mapM interpJudgement js let (jupdates, jsPropVals) = unzip updlist predef <- generatePredefinedValues h propVals <- mapM (bindProp j (predef:jsPropVals)) (addPredifinedProps prop) let newProps = map propValToProperties propVals pure (Judgement (h, newProps, cs, jupdates), propVals) interpJudgement j @ (Bonus (v, _)) = pure (j, [("Bonus", DoubVal v)]) propValToProperties :: (String, PropertyValue) -> Property propValToProperties (str, StrVal string) = Property (str, Value string) propValToProperties (str, DoubVal double) = Property (str, Num double) addPredifinedProps :: [Property] -> [Property] addPredifinedProps p = Property("Title", Lookup (0, "Title")) : Property("Total", Lookup (0, "Total")) : Property("MaxPoints", Lookup (0, "MaxPoints")) : p generatePredefinedValues :: Header -> Either Invalid [(String, PropertyValue)] generatePredefinedValues (Header (t, p, maxP)) = pure [("Title", StrVal t), ("Total", DoubVal p), ("MaxPoints", DoubVal maxP)] bindProp :: Judgement -> [[(String, PropertyValue)]] -> Property -> Either Invalid (String, PropertyValue) bindProp rj propEnv (Property (name, propExp)) = case (evalPropExp rj propExp propEnv) of Right (val) -> pure (name, val) Left invalid -> Left invalid evalPropExp :: Judgement -> PropertyExp -> [[(String, PropertyValue)]] -> Either Invalid PropertyValue evalPropExp _ (Value s) _ = pure $ StrVal s evalPropExp _ (Num n) _ = pure $ DoubVal n evalPropExp rj (Lookup (i, p)) propEnv = case (lookup p (propEnv !! (i))) of Nothing -> Left $ PropertyNotFound p rj (Just s) -> pure s