{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
module BNFC.TypeChecker
(
runTypeChecker
, checkDefinitions
, checkDefinition'
, buildSignature, buildContext, ctxTokens, isToken
, ListConstructors(..)
) where
import Control.Monad
import Control.Monad.Except (MonadError(..))
import Control.Monad.Reader
import Data.Bifunctor
import Data.Char
import Data.Either (partitionEithers)
import qualified Data.Map as Map
import qualified Data.Set as Set
import BNFC.CF
import BNFC.PrettyPrint
type TCError = WithPosition String
newtype Err a = Err { forall a. Err a -> ReaderT Position (Either TCError) a
unErr :: ReaderT Position (Either TCError) a }
deriving ((forall a b. (a -> b) -> Err a -> Err b)
-> (forall a b. a -> Err b -> Err a) -> Functor Err
forall a b. a -> Err b -> Err a
forall a b. (a -> b) -> Err a -> Err b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Err b -> Err a
$c<$ :: forall a b. a -> Err b -> Err a
fmap :: forall a b. (a -> b) -> Err a -> Err b
$cfmap :: forall a b. (a -> b) -> Err a -> Err b
Functor, Functor Err
Functor Err
-> (forall a. a -> Err a)
-> (forall a b. Err (a -> b) -> Err a -> Err b)
-> (forall a b c. (a -> b -> c) -> Err a -> Err b -> Err c)
-> (forall a b. Err a -> Err b -> Err b)
-> (forall a b. Err a -> Err b -> Err a)
-> Applicative Err
forall a. a -> Err a
forall a b. Err a -> Err b -> Err a
forall a b. Err a -> Err b -> Err b
forall a b. Err (a -> b) -> Err a -> Err b
forall a b c. (a -> b -> c) -> Err a -> Err b -> Err c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: forall a b. Err a -> Err b -> Err a
$c<* :: forall a b. Err a -> Err b -> Err a
*> :: forall a b. Err a -> Err b -> Err b
$c*> :: forall a b. Err a -> Err b -> Err b
liftA2 :: forall a b c. (a -> b -> c) -> Err a -> Err b -> Err c
$cliftA2 :: forall a b c. (a -> b -> c) -> Err a -> Err b -> Err c
<*> :: forall a b. Err (a -> b) -> Err a -> Err b
$c<*> :: forall a b. Err (a -> b) -> Err a -> Err b
pure :: forall a. a -> Err a
$cpure :: forall a. a -> Err a
Applicative, Applicative Err
Applicative Err
-> (forall a b. Err a -> (a -> Err b) -> Err b)
-> (forall a b. Err a -> Err b -> Err b)
-> (forall a. a -> Err a)
-> Monad Err
forall a. a -> Err a
forall a b. Err a -> Err b -> Err b
forall a b. Err a -> (a -> Err b) -> Err b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> Err a
$creturn :: forall a. a -> Err a
>> :: forall a b. Err a -> Err b -> Err b
$c>> :: forall a b. Err a -> Err b -> Err b
>>= :: forall a b. Err a -> (a -> Err b) -> Err b
$c>>= :: forall a b. Err a -> (a -> Err b) -> Err b
Monad, MonadReader Position)
instance MonadError String Err where
throwError :: forall a. String -> Err a
throwError String
msg = ReaderT Position (Either TCError) a -> Err a
forall a. ReaderT Position (Either TCError) a -> Err a
Err (ReaderT Position (Either TCError) a -> Err a)
-> ReaderT Position (Either TCError) a -> Err a
forall a b. (a -> b) -> a -> b
$ do
Position
pos <- ReaderT Position (Either TCError) Position
forall r (m :: * -> *). MonadReader r m => m r
ask
TCError -> ReaderT Position (Either TCError) a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (TCError -> ReaderT Position (Either TCError) a)
-> TCError -> ReaderT Position (Either TCError) a
forall a b. (a -> b) -> a -> b
$ Position -> String -> TCError
forall a. Position -> a -> WithPosition a
WithPosition Position
pos String
msg
catchError :: forall a. Err a -> (String -> Err a) -> Err a
catchError Err a
m String -> Err a
h = ReaderT Position (Either TCError) a -> Err a
forall a. ReaderT Position (Either TCError) a -> Err a
Err (ReaderT Position (Either TCError) a -> Err a)
-> ReaderT Position (Either TCError) a -> Err a
forall a b. (a -> b) -> a -> b
$ do
Err a -> ReaderT Position (Either TCError) a
forall a. Err a -> ReaderT Position (Either TCError) a
unErr Err a
m ReaderT Position (Either TCError) a
-> (TCError -> ReaderT Position (Either TCError) a)
-> ReaderT Position (Either TCError) a
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` \ (WithPosition Position
_ String
msg) -> Err a -> ReaderT Position (Either TCError) a
forall a. Err a -> ReaderT Position (Either TCError) a
unErr (String -> Err a
h String
msg)
withPosition :: Position -> Err a -> Err a
withPosition :: forall a. Position -> Err a -> Err a
withPosition Position
pos = (Position -> Position) -> Err a -> Err a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (Position -> Position -> Position
forall a b. a -> b -> a
const Position
pos)
runTypeChecker :: Err a -> Either String a
runTypeChecker :: forall a. Err a -> Either String a
runTypeChecker Err a
m = (TCError -> String) -> Either TCError a -> Either String a
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first TCError -> String
blendInPosition (Either TCError a -> Either String a)
-> Either TCError a -> Either String a
forall a b. (a -> b) -> a -> b
$ Err a -> ReaderT Position (Either TCError) a
forall a. Err a -> ReaderT Position (Either TCError) a
unErr Err a
m ReaderT Position (Either TCError) a -> Position -> Either TCError a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
`runReaderT` Position
NoPosition
data Context = Ctx
{ Context -> Signature
ctxLabels :: Signature
, Context -> [String]
ctxTokens :: [String]
, Context -> Telescope
ctxLocals :: Telescope
}
data ListConstructors = LC
{ ListConstructors -> Base -> (String, Type)
nil :: Base -> (String, Type)
, ListConstructors -> Base -> (String, Type)
cons :: Base -> (String, Type)
}
dummyConstructors :: ListConstructors
dummyConstructors :: ListConstructors
dummyConstructors = LC
{ nil :: Base -> (String, Type)
nil = \ Base
b -> (String
"[]" , [Base] -> Base -> Type
FunT [] (Base -> Base
forall a. Base' a -> Base' a
ListT Base
b))
, cons :: Base -> (String, Type)
cons = \ Base
b -> (String
"(:)", [Base] -> Base -> Type
FunT [Base
b, Base -> Base
forall a. Base' a -> Base' a
ListT Base
b] (Base -> Base
forall a. Base' a -> Base' a
ListT Base
b))
}
checkDefinitions :: CF -> Err CF
checkDefinitions :: CF -> Err CF
checkDefinitions CF
cf = do
let ctx :: Context
ctx = CF -> Context
buildContext CF
cf
let ([Pragma]
pragmas, [Define]
defs0) = [Either Pragma Define] -> ([Pragma], [Define])
forall a b. [Either a b] -> ([a], [b])
partitionEithers ([Either Pragma Define] -> ([Pragma], [Define]))
-> [Either Pragma Define] -> ([Pragma], [Define])
forall a b. (a -> b) -> a -> b
$ (Pragma -> Either Pragma Define)
-> [Pragma] -> [Either Pragma Define]
forall a b. (a -> b) -> [a] -> [b]
map Pragma -> Either Pragma Define
isFunDef ([Pragma] -> [Either Pragma Define])
-> [Pragma] -> [Either Pragma Define]
forall a b. (a -> b) -> a -> b
$ CF -> [Pragma]
forall function. CFG function -> [Pragma]
cfgPragmas CF
cf
[Define]
defs <- (Define -> Err Define) -> [Define] -> Err [Define]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Context -> Define -> Err Define
checkDefinition Context
ctx) [Define]
defs0
CF -> Err CF
forall (m :: * -> *) a. Monad m => a -> m a
return CF
cf { cfgPragmas :: [Pragma]
cfgPragmas = [Pragma]
pragmas [Pragma] -> [Pragma] -> [Pragma]
forall a. [a] -> [a] -> [a]
++ (Define -> Pragma) -> [Define] -> [Pragma]
forall a b. (a -> b) -> [a] -> [b]
map Define -> Pragma
FunDef [Define]
defs }
checkDefinition :: Context -> Define -> Err Define
checkDefinition :: Context -> Define -> Err Define
checkDefinition Context
ctx (Define TCError
f Telescope
args Exp
e0 Base
_) = do
let xs :: [String]
xs = ((String, Base) -> String) -> Telescope -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Base) -> String
forall a b. (a, b) -> a
fst Telescope
args
(Telescope
tel, (Exp
e, Base
b)) <- ListConstructors
-> Context
-> TCError
-> [String]
-> Exp
-> Err (Telescope, (Exp, Base))
checkDefinition' ListConstructors
dummyConstructors Context
ctx TCError
f [String]
xs Exp
e0
Define -> Err Define
forall (m :: * -> *) a. Monad m => a -> m a
return (Define -> Err Define) -> Define -> Err Define
forall a b. (a -> b) -> a -> b
$ TCError -> Telescope -> Exp -> Base -> Define
Define TCError
f Telescope
tel Exp
e Base
b
checkDefinition'
:: ListConstructors
-> Context
-> RFun
-> [String]
-> Exp
-> Err (Telescope, (Exp, Base))
checkDefinition' :: ListConstructors
-> Context
-> TCError
-> [String]
-> Exp
-> Err (Telescope, (Exp, Base))
checkDefinition' ListConstructors
list Context
ctx TCError
ident [String]
xs Exp
e =
Position
-> Err (Telescope, (Exp, Base)) -> Err (Telescope, (Exp, Base))
forall a. Position -> Err a -> Err a
withPosition (TCError -> Position
forall a. WithPosition a -> Position
wpPosition TCError
ident) (Err (Telescope, (Exp, Base)) -> Err (Telescope, (Exp, Base)))
-> Err (Telescope, (Exp, Base)) -> Err (Telescope, (Exp, Base))
forall a b. (a -> b) -> a -> b
$
do Bool -> Err () -> Err ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Char -> Bool
isLower (Char -> Bool) -> Char -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Char
forall a. [a] -> a
head String
f) (Err () -> Err ()) -> Err () -> Err ()
forall a b. (a -> b) -> a -> b
$ String -> Err ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err ()) -> String -> Err ()
forall a b. (a -> b) -> a -> b
$
String
"Defined functions must start with a lowercase letter."
t :: Type
t@(FunT [Base]
ts Base
t') <- String -> Context -> Err Type
lookupCtx String
f Context
ctx Err Type -> (String -> Err Type) -> Err Type
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` \String
_ ->
String -> Err Type
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err Type) -> String -> Err Type
forall a b. (a -> b) -> a -> b
$ String
"'" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' must be used in a rule."
let expect :: Int
expect = [Base] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Base]
ts
given :: Int
given = [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
xs
Bool -> Err () -> Err ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
expect Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
given) (Err () -> Err ()) -> Err () -> Err ()
forall a b. (a -> b) -> a -> b
$ String -> Err ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err ()) -> String -> Err ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
"'", String
f, String
"' is used with type ", Type -> String
forall a. Show a => a -> String
show Type
t
, String
" but defined with ", Int -> String
forall a. Show a => a -> String
show Int
given, String
" argument", Int -> String
forall {a} {a}. (Eq a, Num a, IsString a) => a -> a
plural Int
given String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
]
Exp
e' <- ListConstructors -> Context -> Exp -> Base -> Err Exp
checkExp ListConstructors
list (Context -> Telescope -> Context
setLocals Context
ctx (Telescope -> Context) -> Telescope -> Context
forall a b. (a -> b) -> a -> b
$ [String] -> [Base] -> Telescope
forall a b. [a] -> [b] -> [(a, b)]
zip [String]
xs [Base]
ts) Exp
e Base
t'
(Telescope, (Exp, Base)) -> Err (Telescope, (Exp, Base))
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> [Base] -> Telescope
forall a b. [a] -> [b] -> [(a, b)]
zip [String]
xs [Base]
ts, (Exp
e', Base
t'))
Err (Telescope, (Exp, Base))
-> (String -> Err (Telescope, (Exp, Base)))
-> Err (Telescope, (Exp, Base))
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` \ String
err -> String -> Err (Telescope, (Exp, Base))
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err (Telescope, (Exp, Base)))
-> String -> Err (Telescope, (Exp, Base))
forall a b. (a -> b) -> a -> b
$
String
"In the definition " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords (String
f String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
xs [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
"=", Exp -> String
forall a. Pretty a => a -> String
prettyShow Exp
e, String
";"]) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\n " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
err
where
f :: String
f = TCError -> String
forall a. WithPosition a -> a
wpThing TCError
ident
plural :: a -> a
plural a
1 = a
""
plural a
_ = a
"s"
checkExp :: ListConstructors -> Context -> Exp -> Base -> Err Exp
checkExp :: ListConstructors -> Context -> Exp -> Base -> Err Exp
checkExp ListConstructors
list Context
ctx = ((Exp, Base) -> Err Exp) -> Exp -> Base -> Err Exp
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (((Exp, Base) -> Err Exp) -> Exp -> Base -> Err Exp)
-> ((Exp, Base) -> Err Exp) -> Exp -> Base -> Err Exp
forall a b. (a -> b) -> a -> b
$ \case
(App String
"[]" Type
_ [] , ListT Base
t ) -> Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return ((String -> Type -> [Exp] -> Exp) -> (String, Type) -> [Exp] -> Exp
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry String -> Type -> [Exp] -> Exp
forall f. f -> Type -> [Exp' f] -> Exp' f
App (ListConstructors -> Base -> (String, Type)
nil ListConstructors
list Base
t) [])
(App String
"[]" Type
_ [Exp]
_ , Base
_ ) -> String -> Err Exp
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err Exp) -> String -> Err Exp
forall a b. (a -> b) -> a -> b
$
String
"[] is applied to too many arguments."
(App String
"(:)" Type
_ [Exp
e,Exp
es], ListT Base
t ) -> do
Exp
e' <- ListConstructors -> Context -> Exp -> Base -> Err Exp
checkExp ListConstructors
list Context
ctx Exp
e Base
t
Exp
es' <- ListConstructors -> Context -> Exp -> Base -> Err Exp
checkExp ListConstructors
list Context
ctx Exp
es (Base -> Base
forall a. Base' a -> Base' a
ListT Base
t)
Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return (Exp -> Err Exp) -> Exp -> Err Exp
forall a b. (a -> b) -> a -> b
$ (String -> Type -> [Exp] -> Exp) -> (String, Type) -> [Exp] -> Exp
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry String -> Type -> [Exp] -> Exp
forall f. f -> Type -> [Exp' f] -> Exp' f
App (ListConstructors -> Base -> (String, Type)
cons ListConstructors
list Base
t) [Exp
e',Exp
es']
(App String
"(:)" Type
_ [Exp]
es , Base
_ ) -> String -> Err Exp
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err Exp) -> String -> Err Exp
forall a b. (a -> b) -> a -> b
$
String
"(:) takes 2 arguments, but has been given " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show ([Exp] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Exp]
es) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
(e :: Exp
e@(App String
x Type
_ [Exp]
es) , Base
t ) -> Exp -> String -> [Exp] -> Base -> Err Exp
forall {a}. Pretty a => a -> String -> [Exp] -> Base -> Err Exp
checkApp Exp
e String
x [Exp]
es Base
t
(e :: Exp
e@(Var String
x) , Base
t ) -> Exp
e Exp -> Err Exp -> Err Exp
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Exp -> String -> [Exp] -> Base -> Err Exp
forall {a}. Pretty a => a -> String -> [Exp] -> Base -> Err Exp
checkApp Exp
e String
x [] Base
t
(e :: Exp
e@LitInt{} , BaseT String
"Integer") -> Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return Exp
e
(e :: Exp
e@LitDouble{} , BaseT String
"Double" ) -> Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return Exp
e
(e :: Exp
e@LitChar{} , BaseT String
"Char" ) -> Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return Exp
e
(e :: Exp
e@LitString{} , BaseT String
"String" ) -> Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return Exp
e
(Exp
e , Base
t ) -> String -> Err Exp
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err Exp) -> String -> Err Exp
forall a b. (a -> b) -> a -> b
$
Exp -> String
forall a. Pretty a => a -> String
prettyShow Exp
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" does not have type " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Base -> String
forall a. Show a => a -> String
show Base
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
where
checkApp :: a -> String -> [Exp] -> Base -> Err Exp
checkApp a
e String
x [Exp]
es Base
t = do
ft :: Type
ft@(FunT [Base]
ts Base
t') <- String -> Context -> Err Type
lookupCtx String
x Context
ctx
[Exp]
es' <- [Base] -> Err [Exp]
matchArgs [Base]
ts
Bool -> Err () -> Err ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Base
t Base -> Base -> Bool
forall a. Eq a => a -> a -> Bool
== Base
t') (Err () -> Err ()) -> Err () -> Err ()
forall a b. (a -> b) -> a -> b
$ String -> Err ()
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err ()) -> String -> Err ()
forall a b. (a -> b) -> a -> b
$ a -> String
forall a. Pretty a => a -> String
prettyShow a
e String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" has type " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Base -> String
forall a. Show a => a -> String
show Base
t' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", but something of type " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Base -> String
forall a. Show a => a -> String
show Base
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" was expected."
Exp -> Err Exp
forall (m :: * -> *) a. Monad m => a -> m a
return (Exp -> Err Exp) -> Exp -> Err Exp
forall a b. (a -> b) -> a -> b
$ String -> Type -> [Exp] -> Exp
forall f. f -> Type -> [Exp' f] -> Exp' f
App String
x Type
ft [Exp]
es'
where
matchArgs :: [Base] -> Err [Exp]
matchArgs [Base]
ts
| Int
expect Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
given = String -> Err [Exp]
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err [Exp]) -> String -> Err [Exp]
forall a b. (a -> b) -> a -> b
$ String
"'" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' takes " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
expect String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" arguments, but has been given " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
given String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"."
| Bool
otherwise = (Exp -> Base -> Err Exp) -> [Exp] -> [Base] -> Err [Exp]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (ListConstructors -> Context -> Exp -> Base -> Err Exp
checkExp ListConstructors
list Context
ctx) [Exp]
es [Base]
ts
where
expect :: Int
expect = [Base] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Base]
ts
given :: Int
given = [Exp] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Exp]
es
buildSignature :: [Rule] -> Err Signature
buildSignature :: [Rule] -> Err Signature
buildSignature [Rule]
rules = do
let sig0 :: Map String (Set (WithPosition Type))
sig0 = (Set (WithPosition Type)
-> Set (WithPosition Type) -> Set (WithPosition Type))
-> [(String, Set (WithPosition Type))]
-> Map String (Set (WithPosition Type))
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Set (WithPosition Type)
-> Set (WithPosition Type) -> Set (WithPosition Type)
forall a. Monoid a => a -> a -> a
mappend ([(String, Set (WithPosition Type))]
-> Map String (Set (WithPosition Type)))
-> [(String, Set (WithPosition Type))]
-> Map String (Set (WithPosition Type))
forall a b. (a -> b) -> a -> b
$ ((String, WithPosition Type) -> (String, Set (WithPosition Type)))
-> [(String, WithPosition Type)]
-> [(String, Set (WithPosition Type))]
forall a b. (a -> b) -> [a] -> [b]
map ((WithPosition Type -> Set (WithPosition Type))
-> (String, WithPosition Type) -> (String, Set (WithPosition Type))
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second WithPosition Type -> Set (WithPosition Type)
forall a. a -> Set a
Set.singleton) [(String, WithPosition Type)]
labels
[(String, WithPosition Type)]
sig <- [(String, Set (WithPosition Type))]
-> ((String, Set (WithPosition Type))
-> Err (String, WithPosition Type))
-> Err [(String, WithPosition Type)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (Map String (Set (WithPosition Type))
-> [(String, Set (WithPosition Type))]
forall k a. Map k a -> [(k, a)]
Map.toAscList Map String (Set (WithPosition Type))
sig0) (((String, Set (WithPosition Type))
-> Err (String, WithPosition Type))
-> Err [(String, WithPosition Type)])
-> ((String, Set (WithPosition Type))
-> Err (String, WithPosition Type))
-> Err [(String, WithPosition Type)]
forall a b. (a -> b) -> a -> b
$ \ (String
f,Set (WithPosition Type)
ts) ->
case Set (WithPosition Type) -> [WithPosition Type]
forall a. Set a -> [a]
Set.toList Set (WithPosition Type)
ts of
[] -> Err (String, WithPosition Type)
forall a. HasCallStack => a
undefined
[WithPosition Type
t] -> (String, WithPosition Type) -> Err (String, WithPosition Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (String
f,WithPosition Type
t)
[WithPosition Type]
ts' -> String -> Err (String, WithPosition Type)
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err (String, WithPosition Type))
-> String -> Err (String, WithPosition Type)
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ String
"The label '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"' is used at conflicting types:" ]
, (WithPosition Type -> String) -> [WithPosition Type] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++) (String -> String)
-> (WithPosition Type -> String) -> WithPosition Type -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TCError -> String
blendInPosition (TCError -> String)
-> (WithPosition Type -> TCError) -> WithPosition Type -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Type -> String) -> WithPosition Type -> TCError
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Type -> String
forall a. Show a => a -> String
show) [WithPosition Type]
ts'
]
Signature -> Err Signature
forall (m :: * -> *) a. Monad m => a -> m a
return (Signature -> Err Signature) -> Signature -> Err Signature
forall a b. (a -> b) -> a -> b
$ [(String, WithPosition Type)] -> Signature
forall k a. Eq k => [(k, a)] -> Map k a
Map.fromAscList [(String, WithPosition Type)]
sig
where
mkType :: Cat -> [Either Cat b] -> Type
mkType Cat
cat [Either Cat b]
args = [Base] -> Base -> Type
FunT [ Cat -> Base
mkBase Cat
t | Left Cat
t <- [Either Cat b]
args ]
(Cat -> Base
mkBase Cat
cat)
mkBase :: Cat -> Base
mkBase Cat
t
| Cat -> Bool
isList Cat
t = Base -> Base
forall a. Base' a -> Base' a
ListT (Base -> Base) -> Base -> Base
forall a b. (a -> b) -> a -> b
$ Cat -> Base
mkBase (Cat -> Base) -> Cat -> Base
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCatOfList Cat
t
| Bool
otherwise = String -> Base
forall a. a -> Base' a
BaseT (String -> Base) -> String -> Base
forall a b. (a -> b) -> a -> b
$ Cat -> String
catToStr (Cat -> String) -> Cat -> String
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
t
labels :: [(String, WithPosition Type)]
labels =
[ (String
x, Position -> Type -> WithPosition Type
forall a. Position -> a -> WithPosition a
WithPosition Position
pos (Type -> WithPosition Type) -> Type -> WithPosition Type
forall a b. (a -> b) -> a -> b
$ Cat -> [Either Cat String] -> Type
forall {b}. Cat -> [Either Cat b] -> Type
mkType (WithPosition Cat -> Cat
forall a. WithPosition a -> a
wpThing WithPosition Cat
cat) [Either Cat String]
args)
| Rule f :: TCError
f@(WithPosition Position
pos String
x) WithPosition Cat
cat [Either Cat String]
args InternalRule
_ <- [Rule]
rules
, Bool -> Bool
not (TCError -> Bool
forall a. IsFun a => a -> Bool
isCoercion TCError
f)
, Bool -> Bool
not (TCError -> Bool
forall a. IsFun a => a -> Bool
isNilCons TCError
f)
]
buildContext :: CF -> Context
buildContext :: CF -> Context
buildContext CF
cf = Ctx
{ ctxLabels :: Signature
ctxLabels = CF -> Signature
forall function. CFG function -> Signature
cfgSignature CF
cf
, ctxTokens :: [String]
ctxTokens = (String
"Ident" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: CF -> [String]
forall f. CFG f -> [String]
tokenNames CF
cf)
, ctxLocals :: Telescope
ctxLocals = []
}
isToken :: String -> Context -> Bool
isToken :: String -> Context -> Bool
isToken String
x Context
ctx = String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem String
x ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ Context -> [String]
ctxTokens Context
ctx
setLocals :: Context -> [(String,Base)] -> Context
setLocals :: Context -> Telescope -> Context
setLocals Context
ctx Telescope
xs = Context
ctx { ctxLocals :: Telescope
ctxLocals = Telescope
xs }
lookupCtx :: String -> Context -> Err Type
lookupCtx :: String -> Context -> Err Type
lookupCtx String
x Context
ctx
| String -> Context -> Bool
isToken String
x Context
ctx = Type -> Err Type
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Err Type) -> Type -> Err Type
forall a b. (a -> b) -> a -> b
$ [Base] -> Base -> Type
FunT [String -> Base
forall a. a -> Base' a
BaseT String
"String"] (String -> Base
forall a. a -> Base' a
BaseT String
x)
| Bool
otherwise = do
case String -> Telescope -> Maybe Base
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
x (Telescope -> Maybe Base) -> Telescope -> Maybe Base
forall a b. (a -> b) -> a -> b
$ Context -> Telescope
ctxLocals Context
ctx of
Just Base
b -> Type -> Err Type
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Err Type) -> Type -> Err Type
forall a b. (a -> b) -> a -> b
$ [Base] -> Base -> Type
FunT [] Base
b
Maybe Base
Nothing -> do
case String -> Signature -> Maybe (WithPosition Type)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
x (Signature -> Maybe (WithPosition Type))
-> Signature -> Maybe (WithPosition Type)
forall a b. (a -> b) -> a -> b
$ Context -> Signature
ctxLabels Context
ctx of
Maybe (WithPosition Type)
Nothing -> String -> Err Type
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> Err Type) -> String -> Err Type
forall a b. (a -> b) -> a -> b
$ String
"Undefined symbol '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"'."
Just WithPosition Type
t -> Type -> Err Type
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Err Type) -> Type -> Err Type
forall a b. (a -> b) -> a -> b
$ WithPosition Type -> Type
forall a. WithPosition a -> a
wpThing WithPosition Type
t