{-# LANGUAGE LambdaCase #-}

-- | Conversions of high level descriptor types to their low level textual representations.
module H2JVM.Internal.Convert.Type (
    fieldTypeDescriptor,
    classInfoTypeDescriptor,
    baseTypeDescriptor,
    convertMethodDescriptor,
)
where

import Data.Text (Text)

import H2JVM.Descriptor
import H2JVM.Name (toInternalName)

import H2JVM.Type qualified as Abs

-- | Get the internal descriptor text of a 'Abs.PrimitiveType'.
baseTypeDescriptor :: Abs.PrimitiveType -> Text
baseTypeDescriptor :: PrimitiveType -> Text
baseTypeDescriptor = \case
    PrimitiveType
Abs.JByte -> Text
"B"
    PrimitiveType
Abs.JChar -> Text
"C"
    PrimitiveType
Abs.JDouble -> Text
"D"
    PrimitiveType
Abs.JFloat -> Text
"F"
    PrimitiveType
Abs.JInt -> Text
"I"
    PrimitiveType
Abs.JLong -> Text
"J"
    PrimitiveType
Abs.JShort -> Text
"S"
    PrimitiveType
Abs.JBoolean -> Text
"Z"

-- | Get the internal textual descriptor of a 'Abs.FieldType'.
fieldTypeDescriptor :: Abs.FieldType -> Text
fieldTypeDescriptor :: FieldType -> Text
fieldTypeDescriptor = \case
    Abs.PrimitiveFieldType PrimitiveType
base -> PrimitiveType -> Text
baseTypeDescriptor PrimitiveType
base
    Abs.ObjectFieldType QualifiedClassName
name -> Text
"L" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> QualifiedClassName -> Text
toInternalName QualifiedClassName
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";"
    Abs.ArrayFieldType FieldType
fieldType -> Text
"[" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FieldType -> Text
fieldTypeDescriptor FieldType
fieldType

-- | Get the internal textual descriptor of a 'Abs.ClassInfoType'.
classInfoTypeDescriptor :: Abs.ClassInfoType -> Text
classInfoTypeDescriptor :: ClassInfoType -> Text
classInfoTypeDescriptor = \case
    Abs.ClassInfoType QualifiedClassName
name -> QualifiedClassName -> Text
toInternalName QualifiedClassName
name
    arrayType :: ClassInfoType
arrayType@(Abs.ArrayClassInfoType ClassInfoType
_) ->
        FieldType -> Text
fieldTypeDescriptor (ClassInfoType -> FieldType
Abs.classInfoTypeToFieldType ClassInfoType
arrayType)
    Abs.PrimitiveClassInfoType PrimitiveType
base -> PrimitiveType -> Text
baseTypeDescriptor PrimitiveType
base

-- | Convert a 'MethodDescriptor' to its low level textual representation.
convertMethodDescriptor :: MethodDescriptor -> Text
convertMethodDescriptor :: MethodDescriptor -> Text
convertMethodDescriptor (MethodDescriptor [FieldType]
params ReturnDescriptor
ret) =
    let params' :: [Text]
params' = (FieldType -> Text) -> [FieldType] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map FieldType -> Text
fieldTypeDescriptor [FieldType]
params
        ret' :: Text
ret' = case ReturnDescriptor
ret of
            ReturnDescriptor
VoidReturn -> Text
"V"
            TypeReturn FieldType
t -> FieldType -> Text
fieldTypeDescriptor FieldType
t
     in Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [Text]
params' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
ret'