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

module Compiler.ResolveLabels.ResolveLabelsHelpers (
    checkInt32Range,
    computeOffset,
    sizeOfJumpInst,
    sizeOfJumpIfFalseInst,
    sizeOfJumpIfTrueInst,
    sizeOfCallInst,
    sizeOfTailCallInst,
    ) where

import Data.Text (Text)
import qualified Data.Text as T
import Data.Int (Int64, Int32)

import Compiler.Instruction (Instruction(..), instructionSize)

sizeOfJumpInst :: Int
sizeOfJumpInst :: Int
sizeOfJumpInst = Instruction -> Int
instructionSize (Int -> Instruction
Jump Int
0)
sizeOfJumpIfFalseInst :: Int
sizeOfJumpIfFalseInst :: Int
sizeOfJumpIfFalseInst = Instruction -> Int
instructionSize (Int -> Instruction
JumpIfFalse Int
0)
sizeOfJumpIfTrueInst :: Int
sizeOfJumpIfTrueInst :: Int
sizeOfJumpIfTrueInst = Instruction -> Int
instructionSize (Int -> Instruction
JumpIfTrue Int
0)
sizeOfCallInst :: Int
sizeOfCallInst :: Int
sizeOfCallInst = Instruction -> Int
instructionSize (Int -> Instruction
Call Int
0)
sizeOfTailCallInst :: Int
sizeOfTailCallInst :: Int
sizeOfTailCallInst = Instruction -> Int
instructionSize (Int -> Instruction
Call Int
0)

computeOffset :: Int -> Int -> Int64
computeOffset :: Int -> Int -> Int64
computeOffset Int
target Int
idx = Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
target Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
idx

checkInt32Range :: Int64 -> Either Text Int32
checkInt32Range :: Int64 -> Either Text Int32
checkInt32Range Int64
off =
    case Int64
off Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int32
forall a. Bounded a => a
minBound :: Int32)
        Bool -> Bool -> Bool
|| Int64
off Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int32
forall a. Bounded a => a
maxBound :: Int32) of
        Bool
True  -> Text -> Either Text Int32
forall a b. a -> Either a b
Left (String -> Text
T.pack String
"Offset out of range")
        Bool
False -> Int32 -> Either Text Int32
forall a b. b -> Either a b
Right (Int64 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
off)