packages feed

ntha-0.1.0: src/Value.hs

module Value where

import Ast
import Data.List (intercalate)
import Prelude hiding (lookup)
import qualified Data.Map as M

type ValueEnv = M.Map EName Value
type ParentScope = ValueScope

data ValueScope = ValueScope (Maybe ParentScope) ValueEnv

createEmptyScope :: ValueScope
createEmptyScope = ValueScope Nothing M.empty

createScopeWithParent :: ParentScope -> ValueScope
createScopeWithParent parent = ValueScope (Just parent) M.empty

createScope :: ParentScope -> ValueEnv -> ValueScope
createScope parent env = ValueScope (Just parent) env

insert :: EName -> Value -> ValueScope -> ValueScope
insert name t (ValueScope parent env) = ValueScope parent (M.insert name t env)

lookup :: EName -> ValueScope -> Maybe Value
lookup name (ValueScope parent env) = case M.lookup name env of
                                      Just t -> Just t
                                      Nothing -> case parent of
                                        Just p -> lookup name p
                                        Nothing -> Nothing

-- create a child type scope of current parent type scope
-- just to mock immutable scope, will remove later
child :: ParentScope -> ValueScope
child = createScopeWithParent

instance Show ValueScope where
  show (ValueScope parent env) = (show . M.toList) env ++ case parent of
                                              Just p -> " -> " ++ show p
                                              Nothing -> " -| "

type Tag = String
type FreeVal = Value

data Value = VNum Int
           | VChar Char
           | VBool Bool
           | VTuple [Value]
           | VRecord (M.Map EField Value)
           | VUnit
           | Adt Tag [Value]
           | Fn (Value -> ValueScope -> Value) -- or closure
           | FnApArgs (M.Map String Value)
           | DestrFnApArgs [PatVal] FreeVal
           | TConArgs [Value] Tag

data PatVal = PatVal Pattern Value
              deriving (Eq, Show, Ord)

nil :: Value
nil = Adt "Nil" []

cons :: Value -> Value -> Value
cons h t = Adt "Cons" [h, t]

makeList :: [Value] -> Value
makeList res = case res of
                [] -> nil
                x:xs -> cons x $ makeList xs

getElements :: Value -> [Value]
getElements l = case l of
                  Adt "Cons" [h, t] -> h : (getElements t)
                  _ -> []

reverseList :: Value -> Value
reverseList l = makeList . reverse . getElements $ l

strV :: String -> Value
strV s = makeList $ map (VChar) s

desugerStrV :: Value -> String
desugerStrV (Adt _ values) = case values of
                               [] -> ""
                               _ -> intercalate "" (map desugerStrV values)
desugerStrV v = show v

-- binary operator
binFn :: (Value -> Value -> Value) -> Value
binFn f = Fn (\arg1 _ -> Fn (\arg2 _ -> f arg1 arg2))

isString :: Value -> Bool
isString v = case v of
               Adt "Cons" [h, _] -> case h of
                                     VChar _ -> True
                                     _ -> False
               _ -> False

stringOfAdt :: Tag -> [Value] -> String
stringOfAdt tag values = case tag of
                           "Cons" -> case (head values) of
                                      VChar _ -> "\"" ++ intercalate "" (map show (getElements (Adt tag values))) ++ "\""
                                      _ -> "[" ++ intercalate ", " (map (\v -> case v of
                                                                               Adt "Nil" [] -> "[]"
                                                                               _ -> show v) (getElements (Adt tag values))) ++ "]"
                           "Nil" -> "[]"
                           _ -> tag ++ case values of
                                        []-> ""
                                        _ -> " " ++ intercalate " | " (map show values)

stringOfPairs :: M.Map String Value -> String
stringOfPairs pairs = "{" ++ intercalate "," (M.elems $ M.mapWithKey (\f v -> f ++ " : " ++ show v) pairs) ++ "}"

instance Show Value where
  show (VNum i) = show i
  show (VChar c) = [c]
  show (VBool b) = show b
  show (VTuple values) = "(" ++ intercalate "," (map show values) ++ ")"
  show (VRecord pairs) = stringOfPairs pairs
  show VUnit = "⊥"
  show (Adt tag values) = stringOfAdt tag values
  show (Fn _) = "<fun>"
  show (FnApArgs pairs) = "FnApArgs(" ++ stringOfPairs pairs ++ ")"
  show (DestrFnApArgs pats val) = "DestrFnApArgs(" ++ intercalate ", " (map show pats) ++ " * " ++ show val ++ ")"
  show (TConArgs values tag) = "TConArgs(" ++ stringOfAdt tag values ++ ")"

instance Eq Value where
  VNum int1 == VNum int2 = int1 == int2
  VChar char1 == VChar char2 = char1 == char2
  VBool bool1 == VBool bool2 = bool1 == bool2
  VTuple values1 == VTuple values2 = values1 == values2
  VRecord pairs1 == VRecord pairs2 = pairs1 == pairs2
  VUnit == VUnit = True
  Adt tag1 values1 == Adt tag2 values2 = tag1 == tag2 && values1 == values2
  FnApArgs pairs1 == FnApArgs pairs2 = pairs1 == pairs2
  DestrFnApArgs vals1 val1 == DestrFnApArgs vals2 val2 = vals1 == vals2 && val1 == val2
  TConArgs vals1 tag1 == TConArgs vals2 tag2 = vals1 == vals2 && tag1 == tag2
  _ == _ = False

instance Ord Value where
  VNum int1 <= VNum int2 = int1 <= int2
  VChar char1 <= VChar char2 = char1 <= char2
  VBool bool1 <= VBool bool2 = bool1 <= bool2
  VTuple values1 <= VTuple values2 = values1 <= values2
  VRecord pairs1 <= VRecord pairs2 = pairs1 <= pairs2
  VUnit <= VUnit = True
  Adt tag1 values1 <= Adt tag2 values2 = tag1 <= tag2 && values1 <= values2
  FnApArgs pairs1 <= FnApArgs pairs2 = pairs1 <= pairs2
  DestrFnApArgs vals1 val1 <= DestrFnApArgs vals2 val2 = vals1 <= vals2 && val1 <= val2
  TConArgs vals1 tag1 <= TConArgs vals2 tag2 = vals1 <= vals2 && tag1 <= tag2
  _ <= _ = False