{-
-- EPITECH PROJECT, 2026
-- Glados
-- File description:
-- Builtins
-}

module Compiler.ASM.Builtins
    ( builtinMap
    , getInnerListType
    , getBuiltinReturnType
    ) where

import Data.Text (Text, pack)
import qualified Data.Text as T
import qualified Data.Map.Strict as Map

import Compiler.Instruction (Instruction(..))

builtinCastList :: [(Text, Instruction)]
builtinCastList :: [(Text, Instruction)]
builtinCastList =
    [ (String -> Text
pack String
"int8", Word8 -> Instruction
Cast Word8
0x01), (String -> Text
pack String
"uint8", Word8 -> Instruction
Cast Word8
0x02)
    , (String -> Text
pack String
"int16", Word8 -> Instruction
Cast Word8
0x03), (String -> Text
pack String
"uint16", Word8 -> Instruction
Cast Word8
0x04)
    , (String -> Text
pack String
"int32", Word8 -> Instruction
Cast Word8
0x05), (String -> Text
pack String
"uint32", Word8 -> Instruction
Cast Word8
0x06)
    , (String -> Text
pack String
"int64", Word8 -> Instruction
Cast Word8
0x07), (String -> Text
pack String
"uint64", Word8 -> Instruction
Cast Word8
0x08)
    , (String -> Text
pack String
"char", Word8 -> Instruction
Cast Word8
0x09), (String -> Text
pack String
"uchar", Word8 -> Instruction
Cast Word8
0x10) ]

builtinArithList :: [(Text, Instruction)]
builtinArithList :: [(Text, Instruction)]
builtinArithList =
    [ (String -> Text
pack String
"+", Instruction
Add), (String -> Text
pack String
"-", Instruction
Sub), (String -> Text
pack String
"*", Instruction
Mul)
    , (String -> Text
pack String
"div", Instruction
Div), (String -> Text
pack String
"mod", Instruction
Mod) ]

builtinStackList :: [(Text, Instruction)]
builtinStackList :: [(Text, Instruction)]
builtinStackList =
    [ (String -> Text
pack String
"cons", Instruction
Cons), (String -> Text
pack String
"head", Instruction
Head),
    (String -> Text
pack String
"tail", Instruction
Tail), (String -> Text
pack String
"nth", Instruction
Nth),
    (String -> Text
pack String
"nth_update", Instruction
NthUpdate), (String -> Text
pack String
"attr_update", Instruction
AttrUpdate) ]

builtinLogicList :: [(Text, Instruction)]
builtinLogicList :: [(Text, Instruction)]
builtinLogicList =
    [ (String -> Text
pack String
"eq?", Instruction
Eq), (String -> Text
pack String
"teq?", Instruction
TEq)
    , (String -> Text
pack String
"<", Instruction
Lt), (String -> Text
pack String
"<=", Instruction
Le)
    , (String -> Text
pack String
"&&", Instruction
And), (String -> Text
pack String
"||", Instruction
Or), (String -> Text
pack String
"!", Instruction
Not) ]

builtinIoList :: [(Text, Instruction)]
builtinIoList :: [(Text, Instruction)]
builtinIoList =
    [ (String -> Text
pack String
"open", Instruction
Open), (String -> Text
pack String
"read", Instruction
Read)
    , (String -> Text
pack String
"write", Instruction
Write), (String -> Text
pack String
"close", Instruction
Close)
    , (String -> Text
pack String
"input", Instruction
Input) ]

builtinSystemList :: [(Text, Instruction)]
builtinSystemList :: [(Text, Instruction)]
builtinSystemList =
    [ (String -> Text
pack String
"typeof", Instruction
TypeOf), (String -> Text
pack String
"sizeof", Instruction
SizeOf)
    , (String -> Text
pack String
"print", Instruction
Print), (String -> Text
pack String
"exit", Instruction
Exit) ]

builtinList :: [(Text, Instruction)]
builtinList :: [(Text, Instruction)]
builtinList = ([(Text, Instruction)]
builtinCastList
    [(Text, Instruction)]
-> [(Text, Instruction)] -> [(Text, Instruction)]
forall a. [a] -> [a] -> [a]
++ [(Text, Instruction)]
builtinArithList
    [(Text, Instruction)]
-> [(Text, Instruction)] -> [(Text, Instruction)]
forall a. [a] -> [a] -> [a]
++ [(Text, Instruction)]
builtinStackList
    [(Text, Instruction)]
-> [(Text, Instruction)] -> [(Text, Instruction)]
forall a. [a] -> [a] -> [a]
++ [(Text, Instruction)]
builtinLogicList
    [(Text, Instruction)]
-> [(Text, Instruction)] -> [(Text, Instruction)]
forall a. [a] -> [a] -> [a]
++ [(Text, Instruction)]
builtinIoList
    [(Text, Instruction)]
-> [(Text, Instruction)] -> [(Text, Instruction)]
forall a. [a] -> [a] -> [a]
++ [(Text, Instruction)]
builtinSystemList)

-- | Mapping of builtin operator names to their VM instructions.
--
builtinMap :: Map.Map Text Instruction
builtinMap :: Map Text Instruction
builtinMap = [(Text, Instruction)] -> Map Text Instruction
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Text, Instruction)]
builtinList

-- | Helper to transform "[int]" to "int" or "[Point]" to "Point"
--
getInnerListType :: Text -> Either Text Text
getInnerListType :: Text -> Either Text Text
getInnerListType Text
t
    | Text -> Int
T.length Text
t Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2 Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.head Text
t Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'[' Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.last Text
t Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
']' =
        Text -> Either Text Text
forall a b. b -> Either a b
Right (HasCallStack => Text -> Text
Text -> Text
T.tail (HasCallStack => Text -> Text
Text -> Text
T.init Text
t))
    | Bool
otherwise = Text -> Either Text Text
forall a b. a -> Either a b
Left (String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"Expected a list type [...], got: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
t)

-- | Returns the return type of a builtin based on its name and argument types.
--
getBuiltinReturnType :: String -> [Text] -> Either Text Text
getBuiltinReturnType :: String -> [Text] -> Either Text Text
getBuiltinReturnType String
"nth" [Text
listType, Text
_] = Text -> Either Text Text
getInnerListType Text
listType
getBuiltinReturnType String
"head" [Text
listType] = Text -> Either Text Text
getInnerListType Text
listType
getBuiltinReturnType String
"tail" [Text
listType] = Text -> Either Text Text
forall a b. b -> Either a b
Right Text
listType
getBuiltinReturnType String
"cons" [Text
_, Text
listType] = Text -> Either Text Text
forall a b. b -> Either a b
Right Text
listType

getBuiltinReturnType String
"+" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"-" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"*" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"/" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"%" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"div" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"mod" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")

getBuiltinReturnType String
"eq?" [Text]
_   = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"neq?" [Text]
_  = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"teq?" [Text]
_  = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"tneq?" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"<" [Text]
_     = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
">" [Text]
_     = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"<=" [Text]
_    = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
">=" [Text]
_    = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"!" [Text]
_     = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"&&" [Text]
_    = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"||" [Text]
_    = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")

getBuiltinReturnType String
"open" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"close" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"read" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"[char]")
getBuiltinReturnType String
"write" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")
getBuiltinReturnType String
"ffread" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"[[char]]")
getBuiltinReturnType String
"ffwrite" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"bool")
getBuiltinReturnType String
"typeof" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"[char]")
getBuiltinReturnType String
"sizeof" [Text]
_ = Text -> Either Text Text
forall a b. b -> Either a b
Right (String -> Text
pack String
"int")

getBuiltinReturnType String
name [Text]
_ = Text -> Either Text Text
forall a b. a -> Either a b
Left (
    String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
"Unknown builtin or invalid arguments for: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. Show a => a -> String
show String
name)