797 lines
18 KiB
Haskell
Raw Normal View History

{-
The AST and auxillary types along with their pretty-printers.
TODO: Untangle pretty-printing mess into combinators.
TODO: Store offending text verbatim in Wrong*.
-}
module AST.Scope where
import Control.Lens hiding (Const, List)
import Control.Monad.State
import Data.Text (Text)
import Data.Traversable
import Data.Foldable
import Parser
import Range
import AST.Types
class UpdatableScopes a where
updateScopes :: HasRange r => (r -> ScopeM s) -> a r -> ScopeM (a s)
type ScopeM = State [Env]
newtype Env = Env
{ _eDecls :: [ScopedDecl]
}
deriving newtype (Semigroup, Monoid)
data ScopedDecl = ScopedDecl
{ _sdName :: Maybe Text
, _sdOrigin :: Maybe Range
, _sdBody :: Maybe Range
, _sdType :: Maybe (Either (Type ()) Kind)
}
data Kind = Star
block :: ScopeM a -> ScopeM a
block action = do
modify \(top : rest) -> top : top : rest -- inheriting outer scope
res <- action
modify tail -- dropping current frame
return res
define :: ScopedDecl -> ScopeM ()
define sd = do
modify \(Env top : rest) -> Env (sd : top) : rest
def
:: ( HasRange i
, Foldable g
, Stubbed (g i)
)
=> Name i
-> g i
-> Type j
-> ScopeM ()
def n b ty =
define $ ScopedDecl
(n^?raw)
(n^?folded.location)
(b^?treeRange)
(Just $ Left $ void ty)
defP
:: ( HasRange i
, Foldable g
, Stubbed (g i)
)
=> Name i
-> g i
-> Maybe (Type j)
-> ScopeM ()
defP n b mty =
define $ ScopedDecl
(n^?raw)
(n^?folded.location)
(b^?treeRange)
(fmap (Left . void) mty)
defParam
:: ( HasRange i
)
=> Name i
-> Type j
-> ScopeM ()
defParam n ty =
define $ ScopedDecl
(n^?raw)
(n^?folded.location)
Nothing
(Just $ Left $ void ty)
defI
:: ( HasRange i
)
=> Name i
-> ScopeM ()
defI n =
define $ ScopedDecl
(n^?raw)
(n^?folded.location)
Nothing
Nothing
defE
:: ( HasRange i
, Foldable f
, Stubbed (f i)
)
=> Name i
-> f i
-> ScopeM ()
defE n b =
define $ ScopedDecl
(n^?raw)
(n^?folded.location)
(b^?treeRange)
Nothing
defType
:: ( Foldable g
, HasRange i
, Stubbed (g i)
)
=> Name i
-> g i
-> Kind
-> ScopeM ()
defType n b ki =
define $ ScopedDecl
(n^?raw)
(n^?folded.location)
(b^?treeRange)
(Just (Right ki))
treeRange
:: ( Foldable f
, HasRange a
, Stubbed (f a)
)
=> Fold (f a) Range
treeRange = folded.location
instance UpdatableScopes Contract where
updateScopes update = \case
Contract i ds -> do
block do
Contract
<$> update i
<*> for ds (updateScopes update)
WrongContract e -> do
return $ WrongContract e
-- data Contract info
-- = Contract info [Declaration info]
-- | WrongContract Error
instance UpdatableScopes Declaration where
updateScopes update = \case
ValueDecl i bind -> do
ValueDecl
<$> update i
<*> updateScopes update bind
TypeDecl i n ty -> do
defType n ty Star
TypeDecl
<$> update i
<*> updateScopes update n
<*> updateScopes update ty
Action i expr -> do
Action
<$> update i
<*> updateScopes update expr
Include i s -> do
Include
<$> update i
<*> pure s
WrongDecl e -> do
return $ WrongDecl e
-- data Declaration info
-- = ValueDecl info (Binding info)
-- | TypeDecl info (Name info) (Type info)
-- | Action info (Expr info)
-- | Include info Text
-- | WrongDecl Error
instance UpdatableScopes Binding where
updateScopes update = \case
Irrefutable i p e -> do
res <- Irrefutable
<$> update i
<*> updateScopes update p
<*> updateScopes update e
for_ (p^..patternNames) \name -> do
defE name e
return res
Function i recur n params ty body -> do
let
returns = telescope ((void) <$> params)
defineHere = def n body (returns (void ty))
when recur do
defineHere
res <- block do
Function
<$> update i
<*> pure recur
<*> updateScopes update n
<*> traverse (updateScopes update) params
<*> updateScopes update ty
<*> updateScopes update body
unless recur do
defineHere
return res
Var i n ty e -> do
res <- Var
<$> update i
<*> updateScopes update n
<*> updateScopes update ty
<*> updateScopes update e
def n e ty
return res
Const i n ty e -> do
res <- Const
<$> update i
<*> updateScopes update n
<*> updateScopes update ty
<*> updateScopes update e
def n e ty
return res
WrongBinding e -> do
return $ WrongBinding e
telescope :: [VarDecl i] -> Type () -> Type ()
telescope = flip $ foldr \case
Decl _ _ _ ty -> TArrow () (void ty)
WrongVarDecl e -> TArrow () (WrongType e)
-- data Binding info
-- = Irrefutable info (Pattern info) (Expr info)
-- | Function info Bool (Name info) [VarDecl info] (Type info) (Expr info)
-- | Var info (Name info) (Type info) (Expr info)
-- | Const info (Name info) (Type info) (Expr info)
-- | WrongBinding Error
instance UpdatableScopes VarDecl where
updateScopes update = \case
Decl i mut n ty -> do
res <- Decl
<$> update i
<*> updateScopes update mut
<*> updateScopes update n
<*> updateScopes update ty
defParam n ty
return res
WrongVarDecl e -> do
return $ WrongVarDecl e
-- data VarDecl info
-- = Decl info (Mutable info) (Name info) (Type info)
-- | WrongVarDecl Error
instance UpdatableScopes Mutable where
updateScopes update = \case
Mutable i -> Mutable <$> update i
Immutable i -> Immutable <$> update i
WrongMutable e -> return $ WrongMutable e
-- data Mutable info
-- = Mutable info
-- | Immutable info
-- | WrongMutable Error
instance UpdatableScopes Type where
updateScopes update = \case
TArrow i cod dom -> do
TArrow
<$> update i
<*> updateScopes update cod
<*> updateScopes update dom
TRecord i fs -> do
TRecord
<$> update i
<*> traverse (updateScopes update) fs
TVar i n -> do
TVar
<$> update i
<*> updateScopes update n
TSum i vs -> do
TSum
<$> update i
<*> traverse (updateScopes update) vs
TProduct i es -> do
TProduct
<$> update i
<*> traverse (updateScopes update) es
TApply i f xs -> do
TApply
<$> update i
<*> updateScopes update f
<*> traverse (updateScopes update) xs
WrongType e -> do
return $ WrongType e
-- data Type info
-- = TArrow info (Type info) (Type info)
-- | TRecord info [TField info]
-- | TVar info (Name info)
-- | TSum info [Variant info]
-- | TProduct info [Type info]
-- | TApply info (Name info) [Type info]
-- | WrongType Error
instance UpdatableScopes Variant where
updateScopes update = \case
Variant i n mty -> do
res <- Variant
<$> update i
<*> updateScopes update n
<*> traverse (updateScopes update) mty
defParam n $ case mty of
Just it -> TArrow () (void it) (TVar () (Name () "unknown"))
Nothing -> TVar () (Name () "unknown")
return res
WrongVariant e -> do
return $ WrongVariant e
-- data Variant info
-- = Variant info (Name info) (Maybe (Type info))
-- | WrongVariant Error
instance UpdatableScopes TField where
updateScopes update = \case
TField i a b -> do
TField
<$> update i
<*> updateScopes update a
<*> updateScopes update b
WrongTField e -> do
return $ WrongTField e
-- data TField info
-- = TField info (Name info) (Type info)
-- | WrongTField Error
instance UpdatableScopes Expr where
updateScopes update = \case
Let i ds b -> do
s <- update i
block do
Let s
<$> traverse (updateScopes update) ds
<*> updateScopes update b
Apply i f xs ->
Apply
<$> update i
<*> updateScopes update f
<*> traverse (updateScopes update) xs
Constant i c ->
Constant
<$> update i
<*> updateScopes update c
Ident i qn -> do
Ident
<$> update i
<*> updateScopes update qn
BinOp i l op r -> do
BinOp
<$> update i
<*> updateScopes update l
<*> pure op
<*> updateScopes update r
UnOp i op r -> do
UnOp
<$> update i
<*> pure op
<*> updateScopes update r
Record i fs -> do
Record
<$> update i
<*> traverse (updateScopes update) fs
If i a b c -> do
If
<$> update i
<*> updateScopes update a
<*> updateScopes update b
<*> updateScopes update c
Assign i l r -> do
Assign
<$> update i
<*> updateScopes update l
<*> updateScopes update r
List i ls -> do
List
<$> update i
<*> traverse (updateScopes update) ls
Set i ls -> do
Set
<$> update i
<*> traverse (updateScopes update) ls
Tuple i ls -> do
Tuple
<$> update i
<*> traverse (updateScopes update) ls
Annot i e ty -> do
Annot
<$> update i
<*> updateScopes update e
<*> updateScopes update ty
Attrs i az -> do
Attrs
<$> update i
<*> pure az
BigMap i ms -> do
BigMap
<$> update i
<*> traverse (updateScopes update) ms
Map i ms -> do
Map
<$> update i
<*> traverse (updateScopes update) ms
MapRemove i e qn -> do
MapRemove
<$> update i
<*> updateScopes update e
<*> updateScopes update qn
SetRemove i e qn -> do
SetRemove
<$> update i
<*> updateScopes update e
<*> updateScopes update qn
Indexing i q e -> do
Indexing
<$> update i
<*> updateScopes update q
<*> updateScopes update e
Case i e az -> do
Case
<$> update i
<*> updateScopes update e
<*> traverse (updateScopes update) az
Skip i -> Skip <$> update i
ForLoop i n a b c -> do
block do
defI n
ForLoop
<$> update i
<*> updateScopes update n
<*> updateScopes update a
<*> updateScopes update b
<*> updateScopes update c
WhileLoop i a b -> do
WhileLoop
<$> update i
<*> updateScopes update a
<*> updateScopes update b
Seq i ds -> do
block do
Seq
<$> update i
<*> traverse (updateScopes update) ds
Lambda i ps ty b -> do
block do
Lambda
<$> update i
<*> traverse (updateScopes update) ps
<*> updateScopes update ty
<*> updateScopes update b
ForBox i a mb t e f -> do
block do
defI a
ForBox
<$> update i
<*> updateScopes update a
<*> traverse (updateScopes update) mb
<*> pure t
<*> updateScopes update e
<*> updateScopes update f
MapPatch i q bs -> do
MapPatch
<$> update i
<*> updateScopes update q
<*> traverse (updateScopes update) bs
SetPatch i q bs -> do
SetPatch
<$> update i
<*> updateScopes update q
<*> traverse (updateScopes update) bs
RecordUpd i q fs -> do
RecordUpd
<$> update i
<*> updateScopes update q
<*> traverse (updateScopes update) fs
WrongExpr e -> do
return $ WrongExpr e
-- data Expr info
-- = Let info [Declaration info] (Expr info)
-- | Apply info (Expr info) [Expr info]
-- | Constant info (Constant info)
-- | Ident info (QualifiedName info)
-- | BinOp info (Expr info) Text (Expr info)
-- | UnOp info Text (Expr info)
-- | Record info [Assignment info]
-- | If info (Expr info) (Expr info) (Expr info)
-- | Assign info (LHS info) (Expr info)
-- | List info [Expr info]
-- | Set info [Expr info]
-- | Tuple info [Expr info]
-- | Annot info (Expr info) (Type info)
-- | Attrs info [Text]
-- | BigMap info [MapBinding info]
-- | Map info [MapBinding info]
-- | MapRemove info (Expr info) (QualifiedName info)
-- | SetRemove info (Expr info) (QualifiedName info)
-- | Indexing info (QualifiedName info) (Expr info)
-- | Case info (Expr info) [Alt info]
-- | Skip info
-- | ForLoop info (Name info) (Expr info) (Expr info) (Expr info)
-- | WhileLoop info (Expr info) (Expr info)
-- | Seq info [Declaration info]
-- | Lambda info [VarDecl info] (Type info) (Expr info)
-- | ForBox info (Name info) (Maybe (Name info)) Text (Expr info) (Expr info)
-- | MapPatch info (QualifiedName info) [MapBinding info]
-- | SetPatch info (QualifiedName info) [Expr info]
-- | RecordUpd info (QualifiedName info) [FieldAssignment info]
-- | WrongExpr Error
instance UpdatableScopes Alt where
updateScopes update = \case
Alt i p e -> do
block do
s <- update i
p' <- updateScopes update p
for_ (p^..patternNames) \name -> do
defI name
Alt s p'
<$> updateScopes update e
WrongAlt e -> do
return $ WrongAlt e
-- data Alt info
-- = Alt info (Pattern info) (Expr info)
-- | WrongAlt Error
instance UpdatableScopes LHS where
updateScopes update = \case
LHS i q me -> do
LHS
<$> update i
<*> updateScopes update q
<*> traverse (updateScopes update) me
WrongLHS e -> do
return $ WrongLHS e
-- data LHS info
-- = LHS info (QualifiedName info) (Maybe (Expr info))
-- | WrongLHS Error
instance UpdatableScopes MapBinding where
updateScopes update = \case
MapBinding i e f -> do
MapBinding
<$> update i
<*> updateScopes update e
<*> updateScopes update f
WrongMapBinding e -> do
return $ WrongMapBinding e
-- data MapBinding info
-- = MapBinding info (Expr info) (Expr info)
-- | WrongMapBinding Error
instance UpdatableScopes Assignment where
updateScopes update = \case
Assignment i n e -> do
Assignment
<$> update i
<*> updateScopes update n
<*> updateScopes update e
WrongAssignment e -> do
return $ WrongAssignment e
-- data Assignment info
-- = Assignment info (Name info) (Expr info)
-- | WrongAssignment Error
instance UpdatableScopes FieldAssignment where
updateScopes update = \case
FieldAssignment i q e -> do
FieldAssignment
<$> update i
<*> updateScopes update q
<*> updateScopes update e
WrongFieldAssignment e -> do
return $ WrongFieldAssignment e
-- data FieldAssignment info
-- = FieldAssignment info (QualifiedName info) (Expr info)
-- | WrongFieldAssignment Error
instance UpdatableScopes Constant where
updateScopes update = \case
Int i t -> Int <$> update i <*> pure t
Nat i t -> Nat <$> update i <*> pure t
String i t -> String <$> update i <*> pure t
Float i t -> Float <$> update i <*> pure t
Bytes i t -> Bytes <$> update i <*> pure t
Tez i t -> Tez <$> update i <*> pure t
WrongConstant e -> return $ WrongConstant e
-- data Constant info
-- = Int info Text
-- | Nat info Text
-- | String info Text
-- | Float info Text
-- | Bytes info Text
-- | Tez info Text
-- | WrongConstant Error
patternNames :: Fold (Pattern i) (Name i)
patternNames act = go
where
go = \case
IsConstr i n p -> IsConstr i <$> act n <*> traverse go p
IsConstant i c -> pure $ IsConstant i c
IsVar i n -> IsVar i <$> act n
IsCons i h t -> IsCons i <$> go h <*> go t
IsWildcard i -> pure $ IsWildcard i
IsList i ps -> IsList i <$> traverse go ps
IsTuple i ps -> IsTuple i <$> traverse go ps
WrongPattern e -> pure $ WrongPattern e
instance UpdatableScopes Pattern where
updateScopes update = \case
IsConstr i n mp -> do
IsConstr
<$> update i
<*> updateScopes update n
<*> traverse (updateScopes update) mp
IsConstant i c -> do
IsConstant
<$> update i
<*> updateScopes update c
IsVar i n -> do
IsVar
<$> update i
<*> updateScopes update n
IsCons i h t ->
IsCons
<$> update i
<*> updateScopes update h
<*> updateScopes update t
IsWildcard i -> IsWildcard <$> update i
IsList i l ->
IsList
<$> update i
<*> traverse (updateScopes update) l
IsTuple i l ->
IsTuple
<$> update i
<*> traverse (updateScopes update) l
WrongPattern e -> do
return $ WrongPattern e
-- data Pattern info
-- = IsConstr info (Name info) (Maybe (Pattern info))
-- | IsConstant info (Constant info)
-- | IsVar info (Name info)
-- | IsCons info (Pattern info) (Pattern info)
-- | IsWildcard info
-- | IsList info [Pattern info]
-- | IsTuple info [Pattern info]
-- | WrongPattern Error
instance UpdatableScopes QualifiedName where
updateScopes update = \case
QualifiedName i n ps -> do
QualifiedName
<$> update i
<*> updateScopes update n
<*> traverse (updateScopes update) ps
WrongQualifiedName e -> do
return $ WrongQualifiedName e
-- data QualifiedName info
-- = QualifiedName
-- { qnInfo :: info
-- , qnSource :: Name info
-- , qnPath :: [Path info]
-- }
-- | WrongQualifiedName Error
instance UpdatableScopes Path where
updateScopes update = \case
At i n -> At <$> update i <*> updateScopes update n
Ix i n -> Ix <$> update i <*> pure n
WrongPath e -> return $ WrongPath e
-- data Path info
-- = At info (Name info)
-- | Ix info Text
-- | WrongPath Error
instance UpdatableScopes Name where
updateScopes update = \case
Name i r -> Name <$> update i <*> pure r
WrongName e -> do
return $ WrongName e
-- data Name info = Name
-- { info :: info
-- , raw :: Text
-- }
-- | WrongName Error