-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>
--
-- SPDX-License-Identifier: GPL-3.0-only

module Language.QBE.Simulator.Error (EvalError (..)) where

import Control.Monad.Catch (Exception)
import Language.QBE.Simulator.Memory (Address, showAddr)
import Language.QBE.Types qualified as QBE

-- TODO: Differentiate different typing errors.
data EvalError
  = TypingError
  | UnknownVariable String
  | EmptyStack
  | EncounteredHalt
  | InvalidReturnValue
  | UnknownBlock QBE.BlockIdent
  | InvalidMemoryLoad
  | UnknownFunction QBE.GlobalIdent
  | UnknownFunctionAddr Address
  | MissingFunctionReturn
  | FunctionReturnIgnored
  | AssignedVoidReturnValue
  | InvaldSubWordExtension
  | InvalidAddressType
  | OverlappingBlit Address Address
  | FuncArgsMismatch QBE.GlobalIdent
  | InvalidPhiPosition
  | MemoryError String
  deriving (EvalError -> EvalError -> Bool
(EvalError -> EvalError -> Bool)
-> (EvalError -> EvalError -> Bool) -> Eq EvalError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EvalError -> EvalError -> Bool
== :: EvalError -> EvalError -> Bool
$c/= :: EvalError -> EvalError -> Bool
/= :: EvalError -> EvalError -> Bool
Eq)

instance Show EvalError where
  show :: EvalError -> String
show EvalError
TypingError = String
"TypingError"
  show (UnknownVariable String
s) = String
"UnknownVariable: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show String
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'"
  show EvalError
EmptyStack = String
"EmptyStack"
  show EvalError
EncounteredHalt = String
"EncounteredHalt"
  show EvalError
InvalidReturnValue = String
"InvalidReturnValue"
  show (UnknownBlock BlockIdent
block) = String
"UnknownBlock: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ BlockIdent -> String
forall a. Show a => a -> String
show BlockIdent
block String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'"
  show EvalError
InvalidMemoryLoad = String
"InvalidMemoryLoad"
  show (UnknownFunction GlobalIdent
ident) = String
"UnknownFunction: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ GlobalIdent -> String
forall a. Show a => a -> String
show GlobalIdent
ident String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'"
  show (UnknownFunctionAddr Address
addr) = String
"UnknownFunctionAddr: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Address -> String
showAddr Address
addr String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'"
  show EvalError
MissingFunctionReturn = String
"MissingFunctionReturn"
  show EvalError
FunctionReturnIgnored = String
"FunctionReturnIgnored"
  show EvalError
AssignedVoidReturnValue = String
"AssignedVoidReturnValue"
  show EvalError
InvaldSubWordExtension = String
"InvaldSubWordExtension"
  show EvalError
InvalidAddressType = String
"InvalidAddressType"
  show (OverlappingBlit Address
a1 Address
a2) = String
"Addresses for Blit instruction overlap: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Address -> String
forall a. Show a => a -> String
show Address
a1 String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" and " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Address -> String
forall a. Show a => a -> String
show Address
a2
  show (FuncArgsMismatch GlobalIdent
ident) = String
"FuncArgsMismatch: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ GlobalIdent -> String
forall a. Show a => a -> String
show GlobalIdent
ident String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'"
  show EvalError
InvalidPhiPosition = String
"InvalidPhiPosition"
  show (MemoryError String
msg) = String
"MemoryError: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show String
msg

instance Exception EvalError