|
| 1 | +{-# LANGUAGE FlexibleInstances, FlexibleContexts, OverloadedStrings #-} |
| 2 | +{-# LANGUAGE DataKinds, MonadComprehensions, GADTs #-} |
| 3 | +-- | Converting the LambdaBox AST to s-expressions |
| 4 | +module SExpr (ToSexp, prettySexp) where |
| 5 | + |
| 6 | +import Data.Bifunctor(bimap) |
| 7 | +import Data.List(intercalate) |
| 8 | + |
| 9 | +import Agda.Syntax.Common.Pretty |
| 10 | +import LambdaBox |
| 11 | +import Agda.Utils.Function (applyWhen) |
| 12 | +import Agda2Lambox.Compile.Target |
| 13 | +import Data.SExpresso.SExpr |
| 14 | +import Data.SExpresso.Print.Lazy |
| 15 | +import Data.Text (Text, pack) |
| 16 | +import Data.Text.Lazy qualified as LText |
| 17 | + |
| 18 | +type Exp = Sexp Atom |
| 19 | + |
| 20 | +data Sexpable t = forall a. ToSexp t a => S a |
| 21 | + |
| 22 | +-- | SExpr atoms. |
| 23 | +data Atom |
| 24 | + = ANode Text -- ^ An AST node (i.e a constructor name) |
| 25 | + | AInt Int -- ^ A literal integer |
| 26 | + | ABool Bool -- ^ A literal boolean |
| 27 | + | AString String -- ^ A literal bytestring |
| 28 | + |
| 29 | + |
| 30 | +-- | Convert to S-expression (rendered as lazy 'Data.Lazy.Text'). |
| 31 | +prettySexp :: ToSexp t a => Target t -> a -> LText.Text |
| 32 | +prettySexp t = flatPrint printer . toSexp t |
| 33 | + where |
| 34 | + printer :: SExprPrinter () Atom |
| 35 | + printer = mkPrinter \case |
| 36 | + ANode kw -> kw |
| 37 | + AInt i -> pack $ show i |
| 38 | + ABool b -> if b then "true" else "false" |
| 39 | + AString str -> pack $ show str |
| 40 | + |
| 41 | + |
| 42 | +class ToSexp t a where |
| 43 | + toSexp :: Target t -> a -> Exp |
| 44 | + |
| 45 | +instance ToSexp t (Sexpable t) where |
| 46 | + toSexp t (S x) = toSexp t x |
| 47 | + |
| 48 | +ctor :: Target t -> Text -> [Sexpable t] -> Exp |
| 49 | +ctor t n [] = SAtom (ANode n) |
| 50 | +ctor t n xs = SList () (SAtom (ANode n) : map (toSexp t) xs) |
| 51 | + |
| 52 | +instance ToSexp t (Sexp Atom) where toSexp _ d = d |
| 53 | +instance ToSexp t Int where toSexp _ s = SAtom (AInt s) |
| 54 | +instance ToSexp t Bool where toSexp _ s = SAtom (ABool s) |
| 55 | + |
| 56 | +instance {-# OVERLAPPING #-} ToSexp t String where |
| 57 | + toSexp _ s = SAtom (AString s) |
| 58 | + |
| 59 | +instance ToSexp t a => ToSexp t (Maybe a) where |
| 60 | + toSexp t x = case x of |
| 61 | + Nothing -> ctor t "None" [] |
| 62 | + Just y -> ctor t "Some" [S y] |
| 63 | + |
| 64 | +instance ToSexp t a => ToSexp t [a] where |
| 65 | + toSexp t xs = SList () $ map (toSexp t) xs |
| 66 | + |
| 67 | +instance (ToSexp t a, ToSexp t b) => ToSexp t (a, b) where |
| 68 | + toSexp t (a, b) = SList () [toSexp t a, toSexp t b] |
| 69 | + |
| 70 | +instance ToSexp t Name where |
| 71 | + toSexp t n = case n of |
| 72 | + Anon -> ctor t "nAnon" [] |
| 73 | + Named i -> ctor t "nNamed" [S i] |
| 74 | + |
| 75 | +instance ToSexp t ModPath where |
| 76 | + toSexp t = \case |
| 77 | + MPFile dp -> ctor t "MPfile" [S dp] |
| 78 | + MPBound dp id i -> ctor t "MPbound" [S dp, S id, S i] |
| 79 | + MPDot mp id -> ctor t "MPdot" [S mp, S id] |
| 80 | + |
| 81 | +instance ToSexp t KerName where |
| 82 | + toSexp t KerName{..} = toSexp t (kerModPath, kerName) |
| 83 | + |
| 84 | +instance ToSexp t Inductive where |
| 85 | + toSexp t Inductive{..} = ctor t "inductive" [S indMInd, S indInd] |
| 86 | + |
| 87 | +instance ToSexp t d => ToSexp t (Def d) where |
| 88 | + toSexp t Def{..} = ctor t "def" [S dName, S dBody, S dArgs] |
| 89 | + |
| 90 | +instance ToSexp t Term where |
| 91 | + toSexp t = \case |
| 92 | + LBox -> ctor t "tBox" [] |
| 93 | + LRel k -> ctor t "tRel" [S k] |
| 94 | + LLambda n u -> ctor t "tLambda" [S n, S u] |
| 95 | + LLetIn n u v -> ctor t "tLetIn" [S n, S u, S v] |
| 96 | + LApp u v -> ctor t "tApp" [S u, S v] |
| 97 | + LConst c -> ctor t "tConst" [S c] |
| 98 | + LConstruct ind i es -> ctor t "tConstruct" [S ind, S i, S es] |
| 99 | + LCase ind n u bs -> ctor t "tCase" [S (ind, n), S u, S bs] |
| 100 | + LFix mf i -> ctor t "tFix" [S mf, S i] |
| 101 | + |
| 102 | +instance ToSexp t Type where |
| 103 | + toSexp t = \case |
| 104 | + TBox -> ctor t "TBox" [] |
| 105 | + TAny -> ctor t "TAny" [] |
| 106 | + TArr a b -> ctor t "TArr" [S a, S b] |
| 107 | + TApp a b -> ctor t "TApp" [S a, S b] |
| 108 | + TVar k -> ctor t "TVar" [S k] |
| 109 | + TInd ind -> ctor t "TInd" [S ind] |
| 110 | + TConst kn -> ctor t "TConst" [S kn] |
| 111 | + |
| 112 | +instance ToSexp t RecursivityKind where |
| 113 | + toSexp t = \case |
| 114 | + Finite -> ctor t "Finite" [] |
| 115 | + CoFinite -> ctor t "CoFinite" [] |
| 116 | + BiFinite -> ctor t "BiFinite" [] |
| 117 | + |
| 118 | +instance ToSexp t AllowedElims where |
| 119 | + toSexp t = \case |
| 120 | + IntoSProp -> ctor t "IntoSProp" [] |
| 121 | + IntoPropSProp -> ctor t "IntoPropSProp" [] |
| 122 | + IntoSetPropSProp -> ctor t "IntoSetPropSProp" [] |
| 123 | + IntoAny -> ctor t "IntoAny" [] |
| 124 | + |
| 125 | +instance ToSexp t (ConstructorBody t) where |
| 126 | + toSexp t@ToUntyped Constructor{..} = |
| 127 | + ctor t "constructor_body" [S cstrName, S cstrArgs] |
| 128 | + |
| 129 | + toSexp t@ToTyped Constructor{..} = |
| 130 | + toSexp t ((cstrName, getTyped cstrTypes), cstrArgs) |
| 131 | + |
| 132 | +instance ToSexp t (ProjectionBody t) where |
| 133 | + toSexp t@ToUntyped Projection{..} = ctor t "projection_body" [S projName] |
| 134 | + toSexp t@ToTyped Projection{..} = toSexp t (projName, getTyped projType) |
| 135 | + |
| 136 | +instance ToSexp t TypeVarInfo where |
| 137 | + toSexp t TypeVarInfo{..} = |
| 138 | + ctor t "type_var_info" |
| 139 | + [ S tvarName |
| 140 | + , S tvarIsLogical |
| 141 | + , S tvarIsArity |
| 142 | + , S tvarIsSort |
| 143 | + ] |
| 144 | + |
| 145 | +instance ToSexp t (OneInductiveBody t) where |
| 146 | + toSexp t OneInductive{..} = |
| 147 | + ctor t "one_inductive_body" $ |
| 148 | + [ S indName |
| 149 | + , S indPropositional |
| 150 | + , S indKElim |
| 151 | + ] |
| 152 | + ++ -- NOTE(flupe): in the SExp format, order is important |
| 153 | + case t of |
| 154 | + ToUntyped -> [] |
| 155 | + ToTyped -> [S $ getTyped indTypeVars] |
| 156 | + ++ |
| 157 | + [ S indCtors |
| 158 | + , S indProjs |
| 159 | + ] |
| 160 | + |
| 161 | +instance ToSexp t (MutualInductiveBody t) where |
| 162 | + toSexp t MutualInductive{..} = |
| 163 | + ctor t "mutual_inductive_body" |
| 164 | + [ S indFinite |
| 165 | + , S indPars |
| 166 | + , S indBodies |
| 167 | + ] |
| 168 | + |
| 169 | +instance ToSexp t (ConstantBody t) where |
| 170 | + toSexp t ConstantBody{..} = |
| 171 | + ctor t "constant_body" $ |
| 172 | + case t of |
| 173 | + ToUntyped -> [] |
| 174 | + ToTyped -> [S $ getTyped cstType] |
| 175 | + ++ [S cstBody] |
| 176 | + |
| 177 | +instance ToSexp t (GlobalDecl t) where |
| 178 | + toSexp t = \case |
| 179 | + ConstantDecl body -> ctor t "ConstantDecl" [S body] |
| 180 | + InductiveDecl minds -> ctor t "InductiveDecl" [S minds] |
| 181 | + TypeAliasDecl typ -> ctor t "TypeAliasDecl" [S typ] |
| 182 | + |
| 183 | +instance ToSexp t (GlobalEnv t) where |
| 184 | + toSexp t@ToUntyped (GlobalEnv env) = toSexp t env |
| 185 | + toSexp t@ToTyped (GlobalEnv env) = toSexp t $ flip map env \(kn, decl) -> ((kn, True), decl) |
| 186 | + |
| 187 | +-- TODO(flupe): handle programs |
| 188 | +instance ToSexp t (CoqModule t) where |
| 189 | + toSexp t@ToUntyped CoqModule{..} = toSexp t coqEnv |
| 190 | + toSexp t@ToTyped CoqModule{..} = toSexp t coqEnv |
0 commit comments