From a4fe88283583954cea83637d3c8808ad7c3b10af Mon Sep 17 00:00:00 2001 From: George Thomas Date: Wed, 22 Nov 2023 12:19:25 +0000 Subject: [PATCH] feat: Add flavor annotations to edges in API trees This will enable more detailed rendering by clients. We have opted to keep `EdgeFlavor` small, in order to make things easier for clients. We _might_ eventually want to separate e.g. type- and term-level analogues in to separate flavors, but hopefully what we have here is enough information, since we anticipate these only being used for simple labelling. Signed-off-by: George Thomas --- primer-api/primer-api.cabal | 1 + primer-api/src/Primer/API.hs | 66 +- primer-api/src/Primer/API/EdgeFlavor.hs | 34 + primer-api/src/Primer/API/RecordPair.hs | 2 + primer-api/test/outputs/APITree/Expr | 1234 +++++++++-------- primer-api/test/outputs/APITree/Type | 197 +-- primer-service/src/Primer/OpenAPI.hs | 2 + .../test/outputs/OpenAPI/openapi.json | 40 +- 8 files changed, 916 insertions(+), 660 deletions(-) create mode 100644 primer-api/src/Primer/API/EdgeFlavor.hs diff --git a/primer-api/primer-api.cabal b/primer-api/primer-api.cabal index 94c294cf7..3326c97e2 100644 --- a/primer-api/primer-api.cabal +++ b/primer-api/primer-api.cabal @@ -13,6 +13,7 @@ category: API library exposed-modules: Primer.API + Primer.API.EdgeFlavor Primer.API.NodeFlavor Primer.API.RecordPair diff --git a/primer-api/src/Primer/API.hs b/primer-api/src/Primer/API.hs index 897cad42f..b349106e6 100644 --- a/primer-api/src/Primer/API.hs +++ b/primer-api/src/Primer/API.hs @@ -116,8 +116,9 @@ import Optics ( (^.), _Just, ) +import Primer.API.EdgeFlavor qualified as EdgeFlavor import Primer.API.NodeFlavor qualified as Flavor -import Primer.API.RecordPair (RecordPair (RecordPair)) +import Primer.API.RecordPair (RecordPair (..)) import Primer.Action (ActionError (ParamNotFound), ProgAction, toProgActionInput, toProgActionNoInput) import Primer.Action.Available qualified as Available import Primer.Action.ProgError (ProgError (ActionError, NodeIDNotFound, TypeDefConFieldNotFound)) @@ -645,8 +646,8 @@ data Tree = Tree { nodeId :: Text -- ^ a unique identifier , body :: NodeBody - , childTrees :: [Tree] - , rightChild :: Maybe Tree + , childTrees :: [RecordPair EdgeFlavor.EdgeFlavor Tree] + , rightChild :: Maybe (RecordPair EdgeFlavor.EdgeFlavor Tree) -- ^ a special subtree to be rendered to the right, rather than below - useful for `case` branches } deriving stock (Show, Read, Eq, Generic) @@ -657,8 +658,8 @@ data Tree = Tree treeIds :: Traversal' Tree Text treeIds = #nodeId - `adjoin` (#childTrees % traversed % treeIds) - `adjoin` (#rightChild % traversed % treeIds) + `adjoin` (#childTrees % traversed % #snd % treeIds) + `adjoin` (#rightChild % traversed % #snd % treeIds) -- | A local or global name. -- Field names are intentionally the same as `GlobalName`, so that, unless `qualifiedModule` is `Nothing`, @@ -811,7 +812,7 @@ viewTreeExpr e0 = case e0 of Tree { nodeId , body = NoBody Flavor.Hole - , childTrees = [viewTreeExpr e] + , childTrees = [RecordPair EdgeFlavor.Hole $ viewTreeExpr e] , rightChild = Nothing } EmptyHole _ -> @@ -825,42 +826,42 @@ viewTreeExpr e0 = case e0 of Tree { nodeId , body = NoBody Flavor.Ann - , childTrees = [viewTreeExpr e, viewTreeType t] + , childTrees = [RecordPair EdgeFlavor.AnnTerm $ viewTreeExpr e, RecordPair EdgeFlavor.Ann $ viewTreeType t] , rightChild = Nothing } App _ e1 e2 -> Tree { nodeId , body = NoBody Flavor.App - , childTrees = [viewTreeExpr e1, viewTreeExpr e2] + , childTrees = [RecordPair EdgeFlavor.AppFun $ viewTreeExpr e1, RecordPair EdgeFlavor.AppArg $ viewTreeExpr e2] , rightChild = Nothing } APP _ e t -> Tree { nodeId , body = NoBody Flavor.APP - , childTrees = [viewTreeExpr e, viewTreeType t] + , childTrees = [RecordPair EdgeFlavor.AppArg $ viewTreeExpr e, RecordPair EdgeFlavor.AppArg $ viewTreeType t] , rightChild = Nothing } Con _ c tmApps -> Tree { nodeId , body = TextBody $ RecordPair Flavor.Con $ globalName c - , childTrees = map viewTreeExpr tmApps + , childTrees = map (RecordPair EdgeFlavor.ConField . viewTreeExpr) tmApps , rightChild = Nothing } Lam _ s e -> Tree { nodeId , body = TextBody $ RecordPair Flavor.Lam $ localName s - , childTrees = [viewTreeExpr e] + , childTrees = [RecordPair EdgeFlavor.Lam $ viewTreeExpr e] , rightChild = Nothing } LAM _ s e -> Tree { nodeId , body = TextBody $ RecordPair Flavor.LAM $ localName s - , childTrees = [viewTreeExpr e] + , childTrees = [RecordPair EdgeFlavor.Lam $ viewTreeExpr e] , rightChild = Nothing } Var _ ref -> @@ -876,21 +877,21 @@ viewTreeExpr e0 = case e0 of Tree { nodeId , body = TextBody $ RecordPair Flavor.Let $ localName s - , childTrees = [viewTreeExpr e1, viewTreeExpr e2] + , childTrees = [RecordPair EdgeFlavor.LetEqual $ viewTreeExpr e1, RecordPair EdgeFlavor.LetIn $ viewTreeExpr e2] , rightChild = Nothing } LetType _ s t e -> Tree { nodeId , body = TextBody $ RecordPair Flavor.LetType $ localName s - , childTrees = [viewTreeExpr e, viewTreeType t] + , childTrees = [RecordPair EdgeFlavor.LetEqual $ viewTreeExpr e, RecordPair EdgeFlavor.LetIn $ viewTreeType t] , rightChild = Nothing } Letrec _ s e1 t e2 -> Tree { nodeId , body = TextBody $ RecordPair Flavor.Letrec $ localName s - , childTrees = [viewTreeExpr e1, viewTreeType t, viewTreeExpr e2] + , childTrees = [RecordPair EdgeFlavor.LetEqual $ viewTreeExpr e1, RecordPair EdgeFlavor.Ann $ viewTreeType t, RecordPair EdgeFlavor.LetIn $ viewTreeExpr e2] , rightChild = Nothing } Case _ e bs fb -> @@ -902,12 +903,12 @@ viewTreeExpr e0 = case e0 of } where (childTrees, rightChild) = - ( [viewTreeExpr e] + ( [RecordPair EdgeFlavor.MatchInput $ viewTreeExpr e] , -- seeing as the inner function always returns a `Just`, -- this would only be `Nothing` if the list of branches were empty, -- which should only happen when matching on `Void` ifoldr - (\i b next -> Just $ (viewCaseBranch i b){rightChild = next}) + (\i b next -> Just $ RecordPair EdgeFlavor.Pattern $ (viewCaseBranch i b){rightChild = next}) viewFallback bs ) @@ -930,18 +931,20 @@ viewTreeExpr e0 = case e0 of , childTrees = map ( \(Bind m v) -> - Tree - { nodeId = show $ getID m - , body = TextBody $ RecordPair Flavor.PatternBind $ localName v - , childTrees = [] - , rightChild = Nothing - } + RecordPair + EdgeFlavor.ConField + Tree + { nodeId = show $ getID m + , body = TextBody $ RecordPair Flavor.PatternBind $ localName v + , childTrees = [] + , rightChild = Nothing + } ) binds , rightChild = Nothing } ) - , childTrees = [viewTreeExpr rhs] + , childTrees = [RecordPair EdgeFlavor.MatchOutput $ viewTreeExpr rhs] , rightChild = Nothing } viewFallback = case fb of @@ -955,6 +958,7 @@ viewTreeExpr e0 = case e0 of patternRootId = boxId <> "B" in Just + . RecordPair EdgeFlavor.Pattern $ Tree { nodeId = boxId , body = @@ -967,7 +971,7 @@ viewTreeExpr e0 = case e0 of , rightChild = Nothing } ) - , childTrees = [viewTreeExpr rhs] + , childTrees = [RecordPair EdgeFlavor.MatchOutput $ viewTreeExpr rhs] , rightChild = Nothing } pat = \case @@ -1002,7 +1006,7 @@ viewTreeType' t0 = case t0 of Tree { nodeId , body = NoBody Flavor.THole - , childTrees = [viewTreeType' t] + , childTrees = [RecordPair EdgeFlavor.Hole $ viewTreeType' t] , rightChild = Nothing } TCon _ n -> @@ -1016,7 +1020,7 @@ viewTreeType' t0 = case t0 of Tree { nodeId , body = NoBody Flavor.TFun - , childTrees = [viewTreeType' t1, viewTreeType' t2] + , childTrees = [RecordPair EdgeFlavor.FunIn $ viewTreeType' t1, RecordPair EdgeFlavor.FunOut $ viewTreeType' t2] , rightChild = Nothing } TVar _ n -> @@ -1030,21 +1034,21 @@ viewTreeType' t0 = case t0 of Tree { nodeId , body = NoBody Flavor.TApp - , childTrees = [viewTreeType' t1, viewTreeType' t2] + , childTrees = [RecordPair EdgeFlavor.AppFun $ viewTreeType' t1, RecordPair EdgeFlavor.AppArg $ viewTreeType' t2] , rightChild = Nothing } TForall _ n k t -> Tree { nodeId , body = TextBody $ RecordPair Flavor.TForall $ localName n - , childTrees = [viewTreeKind' k, viewTreeType' t] + , childTrees = [RecordPair EdgeFlavor.ForallKind $ viewTreeKind' k, RecordPair EdgeFlavor.Forall $ viewTreeType' t] , rightChild = Nothing } TLet _ n t b -> Tree { nodeId , body = TextBody $ RecordPair Flavor.TLet $ localName n - , childTrees = [viewTreeType' t, viewTreeType' b] + , childTrees = [RecordPair EdgeFlavor.LetEqual $ viewTreeType' t, RecordPair EdgeFlavor.LetIn $ viewTreeType' b] , rightChild = Nothing } where @@ -1075,7 +1079,7 @@ viewTreeKind' = \case Tree { nodeId , body = NoBody Flavor.KFun - , childTrees = [viewTreeKind' k1, viewTreeKind' k2] + , childTrees = [RecordPair EdgeFlavor.FunIn $ viewTreeKind' k1, RecordPair EdgeFlavor.FunOut $ viewTreeKind' k2] , rightChild = Nothing } diff --git a/primer-api/src/Primer/API/EdgeFlavor.hs b/primer-api/src/Primer/API/EdgeFlavor.hs new file mode 100644 index 000000000..c4aa94530 --- /dev/null +++ b/primer-api/src/Primer/API/EdgeFlavor.hs @@ -0,0 +1,34 @@ +-- | An indication of the meaning of an edge, which frontend may use for labelling, colour etc. +module Primer.API.EdgeFlavor ( + EdgeFlavor (..), +) where + +-- We split this module to increase parallelism in our build. +-- This module does not depend on much, but takes a long time +-- to build because of +-- https://gitlab.haskell.org/ghc/ghc/-/issues/5642 + +import Foreword + +import Primer.JSON (CustomJSON (..), FromJSON, PrimerJSON, ToJSON) + +data EdgeFlavor + = Hole + | AnnTerm + | Ann + | AppFun + | AppArg + | ConField + | Lam + | LetEqual + | LetIn + | MatchInput + | Pattern + | MatchOutput + | FunIn + | FunOut + | ForallKind + | Forall + deriving stock (Show, Read, Eq, Generic) + deriving (ToJSON, FromJSON) via PrimerJSON EdgeFlavor + deriving anyclass (NFData) diff --git a/primer-api/src/Primer/API/RecordPair.hs b/primer-api/src/Primer/API/RecordPair.hs index fae883821..7baea01d9 100644 --- a/primer-api/src/Primer/API/RecordPair.hs +++ b/primer-api/src/Primer/API/RecordPair.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE NoFieldSelectors #-} + module Primer.API.RecordPair ( RecordPair (..), ) where diff --git a/primer-api/test/outputs/APITree/Expr b/primer-api/test/outputs/APITree/Expr index 2af601a7f..bc71a4b50 100644 --- a/primer-api/test/outputs/APITree/Expr +++ b/primer-api/test/outputs/APITree/Expr @@ -10,638 +10,788 @@ Tree } ) , childTrees = - [ Tree - { nodeId = "11" - , body = NoBody Ann - , childTrees = - [ Tree - { nodeId = "12" - , body = TextBody - ( RecordPair - { fst = Con - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "True" - } + [ RecordPair + { fst = LetEqual + , snd = Tree + { nodeId = "11" + , body = NoBody Ann + , childTrees = + [ RecordPair + { fst = AnnTerm + , snd = Tree + { nodeId = "12" + , body = TextBody + ( RecordPair + { fst = Con + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "True" + } + } + ) + , childTrees = [] + , rightChild = Nothing } - ) - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "13" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Bool" - } + } + , RecordPair + { fst = Ann + , snd = Tree + { nodeId = "13" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Bool" + } + } + ) + , childTrees = [] + , rightChild = Nothing } - ) - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Nothing + } + ] + , rightChild = Nothing + } } - , Tree - { nodeId = "14" - , body = TextBody - ( RecordPair - { fst = Letrec - , snd = Name - { qualifiedModule = Nothing - , baseName = "y" + , RecordPair + { fst = LetIn + , snd = Tree + { nodeId = "14" + , body = TextBody + ( RecordPair + { fst = Letrec + , snd = Name + { qualifiedModule = Nothing + , baseName = "y" + } } - } - ) - , childTrees = - [ Tree - { nodeId = "15" - , body = NoBody App - , childTrees = - [ Tree - { nodeId = "16" - , body = NoBody Hole + ) + , childTrees = + [ RecordPair + { fst = LetEqual + , snd = Tree + { nodeId = "15" + , body = NoBody App , childTrees = - [ Tree - { nodeId = "17" - , body = NoBody Ann - , childTrees = - [ Tree - { nodeId = "18" - , body = TextBody - ( RecordPair - { fst = Con - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Just" - } - } - ) - , childTrees = - [ Tree - { nodeId = "19" - , body = NoBody EmptyHole - , childTrees = [] + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "16" + , body = NoBody Hole + , childTrees = + [ RecordPair + { fst = Hole + , snd = Tree + { nodeId = "17" + , body = NoBody Ann + , childTrees = + [ RecordPair + { fst = AnnTerm + , snd = Tree + { nodeId = "18" + , body = TextBody + ( RecordPair + { fst = Con + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Just" + } + } + ) + , childTrees = + [ RecordPair + { fst = ConField + , snd = Tree + { nodeId = "19" + , body = NoBody EmptyHole + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + , RecordPair + { fst = Ann + , snd = Tree + { nodeId = "20" + , body = NoBody TApp + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "21" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Maybe" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "22" + , body = NoBody TEmptyHole + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + ] , rightChild = Nothing } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "20" - , body = NoBody TApp - , childTrees = - [ Tree - { nodeId = "21" + } + ] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "23" + , body = NoBody Hole + , childTrees = + [ RecordPair + { fst = Hole + , snd = Tree + { nodeId = "24" , body = TextBody ( RecordPair - { fst = TCon + { fst = GlobalVar , snd = Name { qualifiedModule = Just ( ModuleName - { unModuleName = "Builtins" :| [] } + { unModuleName = "M" :| [] } ) - , baseName = "Maybe" + , baseName = "unboundName" } } ) , childTrees = [] , rightChild = Nothing } - , Tree - { nodeId = "22" - , body = NoBody TEmptyHole - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing + } + ] + , rightChild = Nothing + } } ] , rightChild = Nothing } - , Tree - { nodeId = "23" - , body = NoBody Hole + } + , RecordPair + { fst = Ann + , snd = Tree + { nodeId = "25" + , body = NoBody THole , childTrees = - [ Tree - { nodeId = "24" - , body = TextBody - ( RecordPair - { fst = GlobalVar - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "M" :| [] } - ) - , baseName = "unboundName" + [ RecordPair + { fst = Hole + , snd = Tree + { nodeId = "26" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Maybe" + } } - } - ) - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "25" - , body = NoBody THole - , childTrees = - [ Tree - { nodeId = "26" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } ) - , baseName = "Maybe" + , childTrees = [] + , rightChild = Nothing } } - ) - , childTrees = [] + ] , rightChild = Nothing } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "27" - , body = NoBody Ann - , childTrees = - [ Tree - { nodeId = "28" - , body = TextBody - ( RecordPair - { fst = Lam - , snd = Name - { qualifiedModule = Nothing - , baseName = "i" - } - } - ) + } + , RecordPair + { fst = LetIn + , snd = Tree + { nodeId = "27" + , body = NoBody Ann , childTrees = - [ Tree - { nodeId = "29" - , body = TextBody - ( RecordPair - { fst = LAM - , snd = Name - { qualifiedModule = Nothing - , baseName = "β" + [ RecordPair + { fst = AnnTerm + , snd = Tree + { nodeId = "28" + , body = TextBody + ( RecordPair + { fst = Lam + , snd = Name + { qualifiedModule = Nothing + , baseName = "i" + } } - } - ) - , childTrees = - [ Tree - { nodeId = "30" - , body = NoBody App - , childTrees = - [ Tree - { nodeId = "31" - , body = NoBody APP - , childTrees = - [ Tree - { nodeId = "32" - , body = TextBody - ( RecordPair - { fst = LetType - , snd = Name - { qualifiedModule = Nothing - , baseName = "b" - } - } - ) - , childTrees = - [ Tree - { nodeId = "34" - , body = TextBody - ( RecordPair - { fst = Con - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Left" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "33" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Bool" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "35" - , body = TextBody - ( RecordPair - { fst = TVar - , snd = Name - { qualifiedModule = Nothing - , baseName = "β" - } - } - ) - , childTrees = [] - , rightChild = Nothing + ) + , childTrees = + [ RecordPair + { fst = Lam + , snd = Tree + { nodeId = "29" + , body = TextBody + ( RecordPair + { fst = LAM + , snd = Name + { qualifiedModule = Nothing + , baseName = "β" + } } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "36" - , body = NoBody Case + ) , childTrees = - [ Tree - { nodeId = "37" - , body = TextBody - ( RecordPair - { fst = LocalVar - , snd = Name - { qualifiedModule = Nothing - , baseName = "i" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Just - ( Tree - { nodeId = "36P0" - , body = BoxBody - ( RecordPair - { fst = Pattern - , snd = Tree - { nodeId = "36P0B" - , body = TextBody - ( RecordPair - { fst = PatternCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Zero" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - } - ) - , childTrees = - [ Tree - { nodeId = "38" - , body = TextBody - ( RecordPair - { fst = Con - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "False" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Just - ( Tree - { nodeId = "36P1" - , body = BoxBody - ( RecordPair - { fst = Pattern - , snd = Tree - { nodeId = "36P1B" - , body = TextBody - ( RecordPair - { fst = PatternCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Succ" - } + [ RecordPair + { fst = Lam + , snd = Tree + { nodeId = "30" + , body = NoBody App + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "31" + , body = NoBody APP + , childTrees = + [ RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "32" + , body = TextBody + ( RecordPair + { fst = LetType + , snd = Name + { qualifiedModule = Nothing + , baseName = "b" + } + } + ) + , childTrees = + [ RecordPair + { fst = LetEqual + , snd = Tree + { nodeId = "34" + , body = TextBody + ( RecordPair + { fst = Con + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Left" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + , RecordPair + { fst = LetIn + , snd = Tree + { nodeId = "33" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Bool" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing } - ) - , childTrees = - [ Tree - { nodeId = "39" + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "35" , body = TextBody ( RecordPair - { fst = PatternBind + { fst = TVar , snd = Name { qualifiedModule = Nothing - , baseName = "n" + , baseName = "β" } } ) , childTrees = [] , rightChild = Nothing } - ] - , rightChild = Nothing - } + } + ] + , rightChild = Nothing } - ) - , childTrees = - [ Tree - { nodeId = "40" + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "36" , body = NoBody Case , childTrees = - [ Tree - { nodeId = "41" - , body = TextBody - ( RecordPair - { fst = LocalVar - , snd = Name - { qualifiedModule = Nothing - , baseName = "n" + [ RecordPair + { fst = MatchInput + , snd = Tree + { nodeId = "37" + , body = TextBody + ( RecordPair + { fst = LocalVar + , snd = Name + { qualifiedModule = Nothing + , baseName = "i" + } } - } - ) - , childTrees = [] - , rightChild = Nothing + ) + , childTrees = [] + , rightChild = Nothing + } } ] , rightChild = Just - ( Tree - { nodeId = "40P0" - , body = BoxBody - ( RecordPair - { fst = Pattern - , snd = Tree - { nodeId = "40P0B" - , body = TextBody - ( RecordPair - { fst = PatternCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Zero" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - } - ) - , childTrees = - [ Tree - { nodeId = "42" - , body = NoBody App - , childTrees = - [ Tree - { nodeId = "43" - , body = NoBody App - , childTrees = - [ Tree - { nodeId = "44" - , body = NoBody EmptyHole - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "45" - , body = TextBody - ( RecordPair - { fst = LocalVar - , snd = Name - { qualifiedModule = Nothing - , baseName = "x" - } - } - ) - , childTrees = [] - , rightChild = Nothing + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "36P0" + , body = BoxBody + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "36P0B" + , body = TextBody + ( RecordPair + { fst = PatternCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Zero" + } } - ] + ) + , childTrees = [] , rightChild = Nothing } - , Tree - { nodeId = "46" + } + ) + , childTrees = + [ RecordPair + { fst = MatchOutput + , snd = Tree + { nodeId = "38" , body = TextBody ( RecordPair - { fst = LocalVar + { fst = Con , snd = Name - { qualifiedModule = Nothing - , baseName = "y" + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "False" } } ) , childTrees = [] , rightChild = Nothing } - ] - , rightChild = Nothing - } - ] - , rightChild = Just - ( Tree - { nodeId = "40Pwild" - , body = BoxBody - ( RecordPair - { fst = Pattern - , snd = Tree - { nodeId = "40PwildB" - , body = NoBody PatternWildcard - , childTrees = [] - , rightChild = Nothing - } - } - ) - , childTrees = - [ Tree - { nodeId = "47" - , body = NoBody EmptyHole - , childTrees = [] + } + ] + , rightChild = Just + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "36P1" + , body = BoxBody + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "36P1B" + , body = TextBody + ( RecordPair + { fst = PatternCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Succ" + } + } + ) + , childTrees = + [ RecordPair + { fst = ConField + , snd = Tree + { nodeId = "39" + , body = TextBody + ( RecordPair + { fst = PatternBind + , snd = Name + { qualifiedModule = Nothing + , baseName = "n" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + ) + , childTrees = + [ RecordPair + { fst = MatchOutput + , snd = Tree + { nodeId = "40" + , body = NoBody Case + , childTrees = + [ RecordPair + { fst = MatchInput + , snd = Tree + { nodeId = "41" + , body = TextBody + ( RecordPair + { fst = LocalVar + , snd = Name + { qualifiedModule = Nothing + , baseName = "n" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Just + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "40P0" + , body = BoxBody + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "40P0B" + , body = TextBody + ( RecordPair + { fst = PatternCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Zero" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ) + , childTrees = + [ RecordPair + { fst = MatchOutput + , snd = Tree + { nodeId = "42" + , body = NoBody App + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "43" + , body = NoBody App + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "44" + , body = NoBody EmptyHole + , childTrees = [] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "45" + , body = TextBody + ( RecordPair + { fst = LocalVar + , snd = Name + { qualifiedModule = Nothing + , baseName = "x" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "46" + , body = TextBody + ( RecordPair + { fst = LocalVar + , snd = Name + { qualifiedModule = Nothing + , baseName = "y" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + ] + , rightChild = Just + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "40Pwild" + , body = BoxBody + ( RecordPair + { fst = Pattern + , snd = Tree + { nodeId = "40PwildB" + , body = NoBody PatternWildcard + , childTrees = [] + , rightChild = Nothing + } + } + ) + , childTrees = + [ RecordPair + { fst = MatchOutput + , snd = Tree + { nodeId = "47" + , body = NoBody EmptyHole + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + ) + } + } + ) + } + } + ] , rightChild = Nothing } - ] - , rightChild = Nothing - } - ) + } + ) + } } ) } - ] - , rightChild = Nothing - } - ) + } + ] + , rightChild = Nothing + } } - ) + ] + , rightChild = Nothing } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "48" - , body = NoBody TFun - , childTrees = - [ Tree - { nodeId = "49" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Nat" } - } - ) - , childTrees = [] - , rightChild = Nothing + ] + , rightChild = Nothing + } } - , Tree - { nodeId = "50" - , body = TextBody - ( RecordPair - { fst = TForall - , snd = Name - { qualifiedModule = Nothing - , baseName = "α" - } - } - ) - , childTrees = - [ Tree - { nodeId = "51" - , body = NoBody KType - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "52" - , body = NoBody TApp - , childTrees = - [ Tree - { nodeId = "53" - , body = NoBody TApp - , childTrees = - [ Tree - { nodeId = "54" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Either" - } - } - ) - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "55" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Bool" - } - } - ) - , childTrees = [] - , rightChild = Nothing + , RecordPair + { fst = Ann + , snd = Tree + { nodeId = "48" + , body = NoBody TFun + , childTrees = + [ RecordPair + { fst = FunIn + , snd = Tree + { nodeId = "49" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Nat" + } } - ] + ) + , childTrees = [] , rightChild = Nothing } - , Tree - { nodeId = "56" + } + , RecordPair + { fst = FunOut + , snd = Tree + { nodeId = "50" , body = TextBody ( RecordPair - { fst = TVar + { fst = TForall , snd = Name { qualifiedModule = Nothing , baseName = "α" } } ) - , childTrees = [] + , childTrees = + [ RecordPair + { fst = ForallKind + , snd = Tree + { nodeId = "51" + , body = NoBody KType + , childTrees = [] + , rightChild = Nothing + } + } + , RecordPair + { fst = Forall + , snd = Tree + { nodeId = "52" + , body = NoBody TApp + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "53" + , body = NoBody TApp + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "54" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Either" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "55" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Bool" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "56" + , body = TextBody + ( RecordPair + { fst = TVar + , snd = Name + { qualifiedModule = Nothing + , baseName = "α" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing + } + } + ] , rightChild = Nothing } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing + } + ] + , rightChild = Nothing + } } ] , rightChild = Nothing } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing + } + ] + , rightChild = Nothing + } } ] , rightChild = Nothing diff --git a/primer-api/test/outputs/APITree/Type b/primer-api/test/outputs/APITree/Type index 14c6e78ff..bf131c110 100644 --- a/primer-api/test/outputs/APITree/Type +++ b/primer-api/test/outputs/APITree/Type @@ -2,101 +2,128 @@ Tree { nodeId = "0" , body = NoBody TFun , childTrees = - [ Tree - { nodeId = "1" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "Nat" + [ RecordPair + { fst = FunIn + , snd = Tree + { nodeId = "1" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "Nat" + } } - } - ) - , childTrees = [] - , rightChild = Nothing + ) + , childTrees = [] + , rightChild = Nothing + } } - , Tree - { nodeId = "2" - , body = TextBody - ( RecordPair - { fst = TForall - , snd = Name - { qualifiedModule = Nothing - , baseName = "a" + , RecordPair + { fst = FunOut + , snd = Tree + { nodeId = "2" + , body = TextBody + ( RecordPair + { fst = TForall + , snd = Name + { qualifiedModule = Nothing + , baseName = "a" + } + } + ) + , childTrees = + [ RecordPair + { fst = ForallKind + , snd = Tree + { nodeId = "3" + , body = NoBody KType + , childTrees = [] + , rightChild = Nothing + } } - } - ) - , childTrees = - [ Tree - { nodeId = "3" - , body = NoBody KType - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "4" - , body = NoBody TApp - , childTrees = - [ Tree - { nodeId = "5" - , body = NoBody THole + , RecordPair + { fst = Forall + , snd = Tree + { nodeId = "4" + , body = NoBody TApp , childTrees = - [ Tree - { nodeId = "6" - , body = NoBody TApp - , childTrees = - [ Tree - { nodeId = "7" - , body = TextBody - ( RecordPair - { fst = TCon - , snd = Name - { qualifiedModule = Just - ( ModuleName - { unModuleName = "Builtins" :| [] } - ) - , baseName = "List" - } + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "5" + , body = NoBody THole + , childTrees = + [ RecordPair + { fst = Hole + , snd = Tree + { nodeId = "6" + , body = NoBody TApp + , childTrees = + [ RecordPair + { fst = AppFun + , snd = Tree + { nodeId = "7" + , body = TextBody + ( RecordPair + { fst = TCon + , snd = Name + { qualifiedModule = Just + ( ModuleName + { unModuleName = "Builtins" :| [] } + ) + , baseName = "List" + } + } + ) + , childTrees = [] + , rightChild = Nothing + } + } + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "8" + , body = NoBody TEmptyHole + , childTrees = [] + , rightChild = Nothing + } + } + ] + , rightChild = Nothing } - ) - , childTrees = [] - , rightChild = Nothing - } - , Tree - { nodeId = "8" - , body = NoBody TEmptyHole - , childTrees = [] - , rightChild = Nothing - } - ] - , rightChild = Nothing + } + ] + , rightChild = Nothing + } } - ] - , rightChild = Nothing - } - , Tree - { nodeId = "9" - , body = TextBody - ( RecordPair - { fst = TVar - , snd = Name - { qualifiedModule = Nothing - , baseName = "a" + , RecordPair + { fst = AppArg + , snd = Tree + { nodeId = "9" + , body = TextBody + ( RecordPair + { fst = TVar + , snd = Name + { qualifiedModule = Nothing + , baseName = "a" + } + } + ) + , childTrees = [] + , rightChild = Nothing } } - ) - , childTrees = [] + ] , rightChild = Nothing } - ] - , rightChild = Nothing - } - ] - , rightChild = Nothing + } + ] + , rightChild = Nothing + } } ] , rightChild = Nothing diff --git a/primer-service/src/Primer/OpenAPI.hs b/primer-service/src/Primer/OpenAPI.hs index 69aec73ff..7a6cddff7 100644 --- a/primer-service/src/Primer/OpenAPI.hs +++ b/primer-service/src/Primer/OpenAPI.hs @@ -59,6 +59,7 @@ import Primer.API ( ValCon, ) import Primer.API qualified as API +import Primer.API.EdgeFlavor (EdgeFlavor) import Primer.API.NodeFlavor ( NodeFlavorBoxBody, NodeFlavorNoBody, @@ -154,6 +155,7 @@ deriving via PrimerJSON (RecordPair a b) instance (ToSchema a, ToSchema b) => To deriving via PrimerJSON Tree instance ToSchema Tree deriving via PrimerJSON API.Name instance ToSchema API.Name deriving via PrimerJSON PrimCon instance ToSchema PrimCon +deriving via PrimerJSON EdgeFlavor instance ToSchema EdgeFlavor deriving via PrimerJSON NodeBody instance ToSchema NodeBody deriving via PrimerJSON NodeFlavorTextBody instance ToSchema NodeFlavorTextBody deriving via PrimerJSON NodeFlavorPrimBody instance ToSchema NodeFlavorPrimBody diff --git a/primer-service/test/outputs/OpenAPI/openapi.json b/primer-service/test/outputs/OpenAPI/openapi.json index c626c9a1e..779af0d89 100644 --- a/primer-service/test/outputs/OpenAPI/openapi.json +++ b/primer-service/test/outputs/OpenAPI/openapi.json @@ -114,6 +114,27 @@ ], "type": "object" }, + "EdgeFlavor": { + "enum": [ + "Hole", + "AnnTerm", + "Ann", + "AppFun", + "AppArg", + "ConField", + "Lam", + "LetEqual", + "LetIn", + "MatchInput", + "Pattern", + "MatchOutput", + "FunIn", + "FunOut", + "ForallKind", + "Forall" + ], + "type": "string" + }, "EvalFullResp": { "oneOf": [ { @@ -700,6 +721,21 @@ ], "type": "object" }, + "RecordPair_EdgeFlavor_Tree": { + "properties": { + "fst": { + "$ref": "#/components/schemas/EdgeFlavor" + }, + "snd": { + "$ref": "#/components/schemas/Tree" + } + }, + "required": [ + "fst", + "snd" + ], + "type": "object" + }, "RecordPair_NodeFlavorBoxBody_Tree": { "properties": { "fst": { @@ -814,7 +850,7 @@ }, "childTrees": { "items": { - "$ref": "#/components/schemas/Tree" + "$ref": "#/components/schemas/RecordPair_EdgeFlavor_Tree" }, "type": "array" }, @@ -822,7 +858,7 @@ "type": "string" }, "rightChild": { - "$ref": "#/components/schemas/Tree" + "$ref": "#/components/schemas/RecordPair_EdgeFlavor_Tree" } }, "required": [