module VM.VMValue
( VMValue(..)
, getValueName
, castValue
, valueToString
, valueToInt
, eqValue
, stringToValue
, charToValue
) where
import Data.Word (Word8)
import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Data.Text as T
import Data.Text (Text)
import Data.Char (chr, ord)
import Common.Type.Integer (IntValue(..), intValueToInt)
data VMValue
= VInt IntValue
| VBool Bool
| VList (Vector VMValue)
| VStruct (Vector VMValue)
| VClosure Int (Vector VMValue)
| VFuncPtr Int
| VVoid
deriving (VMValue -> VMValue -> Bool
(VMValue -> VMValue -> Bool)
-> (VMValue -> VMValue -> Bool) -> Eq VMValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VMValue -> VMValue -> Bool
== :: VMValue -> VMValue -> Bool
$c/= :: VMValue -> VMValue -> Bool
/= :: VMValue -> VMValue -> Bool
Eq, Int -> VMValue -> ShowS
[VMValue] -> ShowS
VMValue -> String
(Int -> VMValue -> ShowS)
-> (VMValue -> String) -> ([VMValue] -> ShowS) -> Show VMValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> VMValue -> ShowS
showsPrec :: Int -> VMValue -> ShowS
$cshow :: VMValue -> String
show :: VMValue -> String
$cshowList :: [VMValue] -> ShowS
showList :: [VMValue] -> ShowS
Show)
getCharFromValue :: VMValue -> Maybe Char
getCharFromValue :: VMValue -> Maybe Char
getCharFromValue (VInt (IChar Int8
c)) = Char -> Maybe Char
forall a. a -> Maybe a
Just (Int -> Char
chr (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
c))
getCharFromValue (VInt (UIChar Word8
c)) = Char -> Maybe Char
forall a. a -> Maybe a
Just (Int -> Char
chr (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c))
getCharFromValue VMValue
_ = Maybe Char
forall a. Maybe a
Nothing
tryExtractString :: [VMValue] -> Maybe Text
[] = Maybe Text
forall a. Maybe a
Nothing
tryExtractString [VMValue]
vals = (String -> Text) -> Maybe String -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> Text
T.pack Maybe String
maybeChars
where maybeChars :: Maybe String
maybeChars = (VMValue -> Maybe Char) -> [VMValue] -> Maybe String
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM VMValue -> Maybe Char
getCharFromValue [VMValue]
vals
valueToString :: VMValue -> Text
valueToString :: VMValue -> Text
valueToString VMValue
VVoid = String -> Text
T.pack String
"void"
valueToString (VInt (IChar Int8
c)) = Char -> Text
T.singleton (Int -> Char
chr (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
c)
valueToString (VInt (UIChar Word8
c)) = Char -> Text
T.singleton (Int -> Char
chr (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c)
valueToString (VInt IntValue
i) = String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show (IntValue -> Int
intValueToInt IntValue
i))
valueToString (VBool Bool
True) = String -> Text
T.pack String
"True"
valueToString (VBool Bool
False) = String -> Text
T.pack String
"False"
valueToString (VClosure Int
addr Vector VMValue
caps) = String -> Text
T.pack String
"#<procedure @" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
addr) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
" captures:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show (Vector VMValue -> Int
forall a. Vector a -> Int
V.length Vector VMValue
caps)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
">"
valueToString (VFuncPtr Int
addr) = String -> Text
T.pack String
"#<function @" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
addr) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
">"
valueToString (VStruct Vector VMValue
v) = String -> Text
T.pack String
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text -> [Text] -> Text
T.intercalate (String -> Text
T.pack String
", ") ((VMValue -> Text) -> [VMValue] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map VMValue -> Text
valueToString (Vector VMValue -> [VMValue]
forall a. Vector a -> [a]
V.toList Vector VMValue
v)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
"}"
valueToString (VList Vector VMValue
v) = let elements :: [VMValue]
elements = Vector VMValue -> [VMValue]
forall a. Vector a -> [a]
V.toList Vector VMValue
v in
case [VMValue] -> Maybe Text
tryExtractString [VMValue]
elements of
Just Text
txt -> Text
txt
Maybe Text
Nothing -> String -> Text
T.pack String
"[" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (Text -> [Text] -> Text
T.intercalate (String -> Text
T.pack String
", ")
((VMValue -> Text) -> [VMValue] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map VMValue -> Text
valueToString [VMValue]
elements)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
"]"
charToValue :: Char -> VMValue
charToValue :: Char -> VMValue
charToValue Char
c = IntValue -> VMValue
VInt (Int8 -> IntValue
IChar (Int -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c)))
stringToValue :: Text -> VMValue
stringToValue :: Text -> VMValue
stringToValue Text
txt = Vector VMValue -> VMValue
VList ([VMValue] -> Vector VMValue
forall a. [a] -> Vector a
V.fromList ((Char -> VMValue) -> String -> [VMValue]
forall a b. (a -> b) -> [a] -> [b]
map Char -> VMValue
charToValue (Text -> String
T.unpack Text
txt)))
valueToInt :: VMValue -> Int
valueToInt :: VMValue -> Int
valueToInt (VInt IntValue
i) = IntValue -> Int
intValueToInt IntValue
i
valueToInt (VBool Bool
True) = Int
1
valueToInt (VBool Bool
False) = Int
0
valueToInt (VFuncPtr Int
addr) = Int
addr
valueToInt VMValue
_ = Int
0
getValueName :: VMValue -> Text
getValueName :: VMValue -> Text
getValueName VMValue
VVoid = String -> Text
T.pack String
"void"
getValueName (VBool Bool
_) = String -> Text
T.pack String
"bool"
getValueName (VClosure Int
_ Vector VMValue
_) = String -> Text
T.pack String
"function"
getValueName (VFuncPtr Int
_) = String -> Text
T.pack String
"function"
getValueName (VInt (IChar Int8
_)) = String -> Text
T.pack String
"char"
getValueName (VInt (UIChar Word8
_)) = String -> Text
T.pack String
"char"
getValueName (VInt IntValue
_) = String -> Text
T.pack String
"int"
getValueName (VStruct Vector VMValue
_) = String -> Text
T.pack String
"[struct]"
getValueName (VList Vector VMValue
v)
| Vector VMValue -> Bool
forall a. Vector a -> Bool
V.null Vector VMValue
v = String -> Text
T.pack String
"[void]"
| Bool
otherwise = String -> Text
T.pack String
"[" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> VMValue -> Text
getValueName (Vector VMValue -> VMValue
forall a. Vector a -> a
V.head Vector VMValue
v) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
"]"
castValue :: Word8 -> VMValue -> VMValue
castValue :: Word8 -> VMValue -> VMValue
castValue Word8
0x00 VMValue
v = Bool -> VMValue
VBool (VMValue -> Int
valueToInt VMValue
v Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0)
castValue Word8
0x01 VMValue
v = IntValue -> VMValue
VInt (Int8 -> IntValue
I8 (Int -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x02 VMValue
v = IntValue -> VMValue
VInt (Word8 -> IntValue
UI8 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x03 VMValue
v = IntValue -> VMValue
VInt (Int16 -> IntValue
I16 (Int -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x04 VMValue
v = IntValue -> VMValue
VInt (Word16 -> IntValue
UI16 (Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x05 VMValue
v = IntValue -> VMValue
VInt (Int32 -> IntValue
I32 (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x06 VMValue
v = IntValue -> VMValue
VInt (Word32 -> IntValue
UI32 (Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x07 VMValue
v = IntValue -> VMValue
VInt (Int64 -> IntValue
I64 (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x08 VMValue
v = IntValue -> VMValue
VInt (Word64 -> IntValue
UI64 (Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x09 VMValue
v = IntValue -> VMValue
VInt (Int8 -> IntValue
IChar (Int -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
0x10 VMValue
v = IntValue -> VMValue
VInt (Word8 -> IntValue
UIChar (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (VMValue -> Int
valueToInt VMValue
v)))
castValue Word8
_ VMValue
v = VMValue
v
checkVectorEq :: V.Vector VMValue -> V.Vector VMValue -> Bool
checkVectorEq :: Vector VMValue -> Vector VMValue -> Bool
checkVectorEq Vector VMValue
v1 Vector VMValue
v2 =
Vector VMValue -> Int
forall a. Vector a -> Int
V.length Vector VMValue
v1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Vector VMValue -> Int
forall a. Vector a -> Int
V.length Vector VMValue
v2 Bool -> Bool -> Bool
&& Vector Bool -> Bool
V.and ((VMValue -> VMValue -> Bool)
-> Vector VMValue -> Vector VMValue -> Vector Bool
forall a b c. (a -> b -> c) -> Vector a -> Vector b -> Vector c
V.zipWith VMValue -> VMValue -> Bool
eqValue Vector VMValue
v1 Vector VMValue
v2)
eqValue :: VMValue -> VMValue -> Bool
eqValue :: VMValue -> VMValue -> Bool
eqValue (VInt IntValue
a) (VInt IntValue
b) = IntValue -> Int
intValueToInt IntValue
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== IntValue -> Int
intValueToInt IntValue
b
eqValue (VBool Bool
a) (VBool Bool
b) = Bool
a Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
b
eqValue (VFuncPtr Int
a) (VFuncPtr Int
b) = Int
a Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
b
eqValue VMValue
VVoid VMValue
VVoid = Bool
True
eqValue (VList Vector VMValue
a) (VList Vector VMValue
b) = Vector VMValue -> Vector VMValue -> Bool
checkVectorEq Vector VMValue
a Vector VMValue
b
eqValue (VStruct Vector VMValue
a) (VStruct Vector VMValue
b) = Vector VMValue -> Vector VMValue -> Bool
checkVectorEq Vector VMValue
a Vector VMValue
b
eqValue VMValue
_ VMValue
_ = Bool
False