{-# LANGUAGE InstanceSigs #-}

module Codegen.Errors where

import qualified Ast.Types as AT
import qualified LLVM.AST.Type as T

-- | Error types for code generation.
data CodegenError = CodegenError
  { CodegenError -> SrcLoc
errorLoc :: AT.SrcLoc,
    CodegenError -> CodegenErrorType
errorType :: CodegenErrorType
  }
  deriving (CodegenError -> CodegenError -> Bool
(CodegenError -> CodegenError -> Bool)
-> (CodegenError -> CodegenError -> Bool) -> Eq CodegenError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CodegenError -> CodegenError -> Bool
== :: CodegenError -> CodegenError -> Bool
$c/= :: CodegenError -> CodegenError -> Bool
/= :: CodegenError -> CodegenError -> Bool
Eq)

-- | Error types for code generation.
data CodegenErrorType
  = UnsupportedTopLevel AT.Expr
  | UnsupportedOperator AT.Operation
  | UnsupportedUnaryOperator AT.UnaryOperation
  | UnsupportedLiteral AT.Literal
  | UnsupportedType AT.Type
  | UnsupportedGlobalVar AT.Literal
  | UnsupportedLocalVar AT.Literal
  | UnsupportedDefinition AT.Expr
  | UnsupportedForDefinition AT.Expr
  | UnsupportedWhileDefinition AT.Expr
  | VariableNotFound String
  | UnsupportedFunctionCall String
  | UnsupportedStructureAccess AT.Expr
  | StructureFieldNotFound String
  | ContinueOutsideLoop
  | BreakOutsideLoop
  | UnsupportedConversion T.Type T.Type
  | UnsupportedGlobalDeclaration AT.Expr
  deriving (CodegenErrorType -> CodegenErrorType -> Bool
(CodegenErrorType -> CodegenErrorType -> Bool)
-> (CodegenErrorType -> CodegenErrorType -> Bool)
-> Eq CodegenErrorType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CodegenErrorType -> CodegenErrorType -> Bool
== :: CodegenErrorType -> CodegenErrorType -> Bool
$c/= :: CodegenErrorType -> CodegenErrorType -> Bool
/= :: CodegenErrorType -> CodegenErrorType -> Bool
Eq, Int -> CodegenErrorType -> ShowS
[CodegenErrorType] -> ShowS
CodegenErrorType -> String
(Int -> CodegenErrorType -> ShowS)
-> (CodegenErrorType -> String)
-> ([CodegenErrorType] -> ShowS)
-> Show CodegenErrorType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CodegenErrorType -> ShowS
showsPrec :: Int -> CodegenErrorType -> ShowS
$cshow :: CodegenErrorType -> String
show :: CodegenErrorType -> String
$cshowList :: [CodegenErrorType] -> ShowS
showList :: [CodegenErrorType] -> ShowS
Show)

instance Show CodegenError where
  show :: CodegenError -> String
  show :: CodegenError -> String
show (CodegenError SrcLoc
loc CodegenErrorType
err) =
    SrcLoc -> String
AT.srcFile SrcLoc
loc
      String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":"
      String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (SrcLoc -> Int
AT.srcLine SrcLoc
loc)
      String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":"
      String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (SrcLoc -> Int
AT.srcCol SrcLoc
loc)
      String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
": "
      String -> ShowS
forall a. [a] -> [a] -> [a]
++ CodegenErrorType -> String
showErrorType CodegenErrorType
err

-- | Show error type as string.
showErrorType :: CodegenErrorType -> String
showErrorType :: CodegenErrorType -> String
showErrorType CodegenErrorType
err = case CodegenErrorType
err of
  UnsupportedTopLevel Expr
expr -> String
"Unsupported top-level expression: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. Show a => a -> String
show Expr
expr
  UnsupportedOperator Operation
op -> String
"Unsupported operator: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Operation -> String
forall a. Show a => a -> String
show Operation
op
  UnsupportedUnaryOperator UnaryOperation
op -> String
"Unsupported unary operator: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ UnaryOperation -> String
forall a. Show a => a -> String
show UnaryOperation
op
  UnsupportedLiteral Literal
lit -> String
"Unsupported literal: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Literal -> String
forall a. Show a => a -> String
show Literal
lit
  UnsupportedType Type
typ -> String
"Unsupported type: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Type -> String
forall a. Show a => a -> String
show Type
typ
  UnsupportedGlobalVar Literal
lit -> String
"Unsupported global variable: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Literal -> String
forall a. Show a => a -> String
show Literal
lit
  UnsupportedLocalVar Literal
lit -> String
"Unsupported local variable: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Literal -> String
forall a. Show a => a -> String
show Literal
lit
  UnsupportedDefinition Expr
expr -> String
"Unsupported definition: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. Show a => a -> String
show Expr
expr
  UnsupportedForDefinition Expr
expr -> String
"Invalid for loop: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. Show a => a -> String
show Expr
expr
  UnsupportedWhileDefinition Expr
expr -> String
"Invalid while loop: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. Show a => a -> String
show Expr
expr
  VariableNotFound String
name -> String
"Variable not found: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
  UnsupportedFunctionCall String
name -> String
"Invalid function call: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
  UnsupportedStructureAccess Expr
expr -> String
"Invalid structure access: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. Show a => a -> String
show Expr
expr
  StructureFieldNotFound String
name -> String
"Structure field not found: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name
  CodegenErrorType
ContinueOutsideLoop -> String
"Continue statement outside loop"
  CodegenErrorType
BreakOutsideLoop -> String
"Break statement outside loop"
  UnsupportedConversion Type
from Type
to -> String
"Unsupported conversion from " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Type -> String
forall a. Show a => a -> String
show Type
from String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" to " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Type -> String
forall a. Show a => a -> String
show Type
to
  UnsupportedGlobalDeclaration Expr
expr -> String
"Unsupported global declaration: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Expr -> String
forall a. Show a => a -> String
show Expr
expr