{-# LANGUAGE TemplateHaskell #-}
module Analyzer.Result where
import Analyzer.AnalyzedAst (Identifier)
import Analyzer.AnalyzedType (Type)
import Control.Lens (At (at), LensLike', ix, makeLenses)
import Control.Monad.Except (ExceptT)
import Control.Monad.State (State)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (unpack)
type Result a = ExceptT Err (State Env) a
type ResultValue = Either Err
data Err
=
NoMain
|
IdentifierNotFound Identifier
|
IdentifierRedeclaration Identifier
|
MismatchedTypes
|
NotInIntBounds
|
DivisionByZero
|
BreakOrContinueOutsideOfForScope
instance Show Err where
show :: Err -> String
show Err
NoMain = String
"panic: analysis error: no main"
show (IdentifierNotFound Identifier
name) = String
"panic: analysis error: identifier " forall a. [a] -> [a] -> [a]
++ Identifier -> String
unpack Identifier
name forall a. [a] -> [a] -> [a]
++ String
" not found"
show (IdentifierRedeclaration Identifier
name) = String
"panic: analysis error: identifier " forall a. [a] -> [a] -> [a]
++ Identifier -> String
unpack Identifier
name forall a. [a] -> [a] -> [a]
++ String
" redeclared"
show Err
MismatchedTypes = String
"panic: analysis error: mismatched types"
show Err
NotInIntBounds = String
"panic: analysis error: not in int bounds"
show Err
DivisionByZero = String
"panic: analysis error: integer divide by zero"
show Err
BreakOrContinueOutsideOfForScope = String
"panic: analysis error: break or continue is not in a loop"
newtype Env = Env {Env -> [Scope]
_scopes :: [Scope]}
deriving (Int -> Env -> ShowS
[Env] -> ShowS
Env -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Env] -> ShowS
$cshowList :: [Env] -> ShowS
show :: Env -> String
$cshow :: Env -> String
showsPrec :: Int -> Env -> ShowS
$cshowsPrec :: Int -> Env -> ShowS
Show)
emptyEnv :: Env
emptyEnv :: Env
emptyEnv = [Scope] -> Env
Env []
data Scope = Scope
{ Scope -> ScopeType
_scopeType :: ScopeType,
Scope -> Map Identifier Type
_vars :: Map Identifier Type
}
deriving (Int -> Scope -> ShowS
[Scope] -> ShowS
Scope -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Scope] -> ShowS
$cshowList :: [Scope] -> ShowS
show :: Scope -> String
$cshow :: Scope -> String
showsPrec :: Int -> Scope -> ShowS
$cshowsPrec :: Int -> Scope -> ShowS
Show)
data ScopeType = ForScope | OrdinaryScope
deriving (Int -> ScopeType -> ShowS
[ScopeType] -> ShowS
ScopeType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ScopeType] -> ShowS
$cshowList :: [ScopeType] -> ShowS
show :: ScopeType -> String
$cshow :: ScopeType -> String
showsPrec :: Int -> ScopeType -> ShowS
$cshowsPrec :: Int -> ScopeType -> ShowS
Show, ScopeType -> ScopeType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ScopeType -> ScopeType -> Bool
$c/= :: ScopeType -> ScopeType -> Bool
== :: ScopeType -> ScopeType -> Bool
$c== :: ScopeType -> ScopeType -> Bool
Eq)
scope :: ScopeType -> [(Identifier, Type)] -> Scope
scope :: ScopeType -> [(Identifier, Type)] -> Scope
scope ScopeType
t [(Identifier, Type)]
elements = ScopeType -> Map Identifier Type -> Scope
Scope ScopeType
t (forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Identifier, Type)]
elements)
emptyScope :: ScopeType -> Scope
emptyScope :: ScopeType -> Scope
emptyScope ScopeType
t = ScopeType -> [(Identifier, Type)] -> Scope
scope ScopeType
t []
makeLenses ''Env
makeLenses ''Scope
makeLenses ''ScopeType
var :: Applicative f => Int -> Identifier -> LensLike' f Env (Maybe Type)
var :: forall (f :: * -> *).
Applicative f =>
Int -> Identifier -> LensLike' f Env (Maybe Type)
var Int
i Identifier
name = Iso' Env [Scope]
scopes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Int
i forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens' Scope (Map Identifier Type)
vars forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall m. At m => Index m -> Lens' m (Maybe (IxValue m))
at Identifier
name