From 7f895d42028ab64cc01a48030e144ad80fcd0e9e Mon Sep 17 00:00:00 2001 From: Dougal Date: Wed, 15 May 2024 12:03:28 -0400 Subject: [PATCH] Remove one-off type arguments from primops and make a result type uniformly available instead --- dex.cabal | 10 ++-- src/lib/Builder.hs | 54 +++++++++++++----- src/lib/CheapReduction.hs | 6 +- src/lib/DPS.hs | 4 +- src/lib/Imp.hs | 63 +++++++++++---------- src/lib/Inference.hs | 24 +++----- src/lib/QueryTypePure.hs | 59 ++++--------------- src/lib/Simplify.hs | 29 +++++----- src/lib/TopLevel.hs | 101 ++++++++++++++++++--------------- src/lib/Types/Core.hs | 115 +++++++++++++++++--------------------- 10 files changed, 220 insertions(+), 245 deletions(-) diff --git a/dex.cabal b/dex.cabal index 8fa762d71..3d5b074c2 100644 --- a/dex.cabal +++ b/dex.cabal @@ -44,7 +44,7 @@ library , Builder , CUDA , CheapReduction - , CheckType + -- , CheckType , ConcreteSyntax , Core , DPS @@ -56,9 +56,9 @@ library , Inference -- , Inline , IRVariants - , JAX.Concrete - , JAX.Rename - , JAX.ToSimp + -- , JAX.Concrete + -- , JAX.Rename + -- , JAX.ToSimp , LLVM.Link , LLVM.Compile , LLVM.CUDA @@ -75,7 +75,7 @@ library , PPrint , RawName , Runtime - , RuntimePrint + -- , RuntimePrint , Serialize , Simplify , Subst diff --git a/src/lib/Builder.hs b/src/lib/Builder.hs index 26b359d7b..b60ecae25 100644 --- a/src/lib/Builder.hs +++ b/src/lib/Builder.hs @@ -42,6 +42,18 @@ import Util (enumerate, transitiveClosureM, bindM2, toSnocList, popList) peepholeExpr :: a -> a peepholeExpr = id +-- === ToExpr === + +class ToExpr (e::E) (r::IR) | e -> r where + toExpr :: e n -> Expr r n + +instance ToExpr (Expr r) r where toExpr = id +instance ToExpr (Atom r) r where toExpr = Atom +instance ToExpr (Con r) r where toExpr = Atom . Con +instance ToExpr (AtomVar r) r where toExpr = toExpr . toAtom +instance IRRep r => ToExpr (MemOp r) r where toExpr op = PrimOp (getType op) (MemOp op) +instance ToExpr (TypedHof r) r where toExpr = Hof + -- === Ordinary (local) builder class === class (EnvReader m, Fallible1 m, IRRep r) @@ -81,6 +93,18 @@ emit e = case toExpr e of return $ toAtom v {-# INLINE emit #-} +emitUnOp :: (Builder r m, Emits n) => UnOp -> Atom r n -> m n (Atom r n) +emitUnOp op x = emit $ PrimOp resultTy $ UnOp op x + where resultTy = TyCon $ BaseType $ typeUnOp op $ getTypeBaseType x + + +emitBinOp :: (Builder r m, Emits n) => BinOp -> Atom r n -> Atom r n -> m n (Atom r n) +emitBinOp op x y = emit $ PrimOp resultTy $ BinOp op x y + where resultTy = TyCon $ BaseType $ typeBinOp op $ getTypeBaseType x + +emitRefOp :: (Builder r m, Emits n) => Atom r n -> RefOp r n -> m n (Atom r n) +emitRefOp ref op = undefined + emitToVar :: (Builder r m, ToExpr e r, Emits n) => e n -> m n (AtomVar r n) emitToVar expr = emit expr >>= \case Stuck _ (Var v) -> return v @@ -823,7 +847,7 @@ maybeTangentType' ty = case ty of addTangent :: (Emits n, SBuilder m) => SAtom n -> SAtom n -> m n (SAtom n) addTangent x y = do case getTyCon x of - BaseType (Scalar _) -> emit $ BinOp FAdd x y + BaseType (Scalar _) -> emitBinOp FAdd x y ProdType _ -> do xs <- getUnpacked x ys <- getUnpacked y @@ -855,22 +879,22 @@ symbolicTangentNonZero val = do -- === builder versions of common local ops === fadd :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) -fadd x y = emit $ BinOp FAdd x y +fadd x y = emitBinOp FAdd x y fsub :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) -fsub x y = emit $ BinOp FSub x y +fsub x y = emitBinOp FSub x y fmul :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) -fmul x y = emit $ BinOp FMul x y +fmul x y = emitBinOp FMul x y fdiv :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) -fdiv x y = emit $ BinOp FDiv x y +fdiv x y = emitBinOp FDiv x y iadd :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) -iadd x y = emit $ BinOp IAdd x y +iadd x y = emitBinOp IAdd x y imul :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) -imul x y = emit $ BinOp IMul x y +imul x y = emitBinOp IMul x y fLitLike :: Double -> SAtom n -> SAtom n fLitLike x t = case getTyCon t of @@ -893,7 +917,7 @@ getProjRef :: (Builder r m, Emits n) => Projection -> Atom r n -> m n (Atom r n) getProjRef i r = emit =<< mkProjRef r i newUninitializedRef :: (SBuilder m, Emits o) => SType o -> m o (SAtom o) -newUninitializedRef ty = emit $ NewRef ty +newUninitializedRef ty = emit $ PrimOp ty $ MiscOp NewRef -- XXX: getUnpacked must reduce its argument to enforce the invariant that -- ProjectElt atoms are always fully reduced (to avoid type errors between two @@ -1068,21 +1092,21 @@ naryIndexRef ref is = foldM indexRef ref is ptrOffset :: (Builder r m, Emits n) => Atom r n -> Atom r n -> m n (Atom r n) ptrOffset x (IdxRepVal 0) = return x -ptrOffset x i = emit $ MemOp $ PtrOffset x i +ptrOffset x i = emit $ PtrOffset x i {-# INLINE ptrOffset #-} unsafePtrLoad :: (Builder r m, Emits n) => Atom r n -> m n (Atom r n) -unsafePtrLoad x = emit . MemOp . PtrLoad =<< sinkM x +unsafePtrLoad x = emit . PtrLoad =<< sinkM x -mkIndexRef :: (EnvReader m, Fallible1 m, IRRep r) => Atom r n -> Atom r n -> m n (PrimOp r n) +mkIndexRef :: (EnvReader m, Fallible1 m, IRRep r) => Atom r n -> Atom r n -> m n (Expr r n) mkIndexRef ref i = do resultTy <- typeOfIndexRef (getType ref) i - return $ RefOp ref $ IndexRef resultTy i + return $ PrimOp resultTy $ RefOp ref $ IndexRef i -mkProjRef :: (EnvReader m, IRRep r) => Atom r n -> Projection -> m n (PrimOp r n) +mkProjRef :: (EnvReader m, IRRep r) => Atom r n -> Projection -> m n (Expr r n) mkProjRef ref i = do resultTy <- typeOfProjRef (getType ref) i - return $ RefOp ref $ ProjRef resultTy i + return $ PrimOp resultTy $ RefOp ref $ ProjRef i -- === index set type class === @@ -1127,7 +1151,7 @@ emitIf :: (Emits n, ScopableBuilder r m) -> (forall l. (Emits l, DExt n l) => m l (Atom r l)) -> m n (Atom r n) emitIf predicate resultTy trueCase falseCase = do - predicate' <- emit $ ToEnum (TyCon (SumType [UnitTy, UnitTy])) predicate + predicate' <- emit $ PrimOp (TyCon (SumType [UnitTy, UnitTy])) $ MiscOp (ToEnum predicate) buildCase predicate' resultTy \i _ -> case i of 0 -> falseCase diff --git a/src/lib/CheapReduction.hs b/src/lib/CheapReduction.hs index 40c3182b5..130597eb2 100644 --- a/src/lib/CheapReduction.hs +++ b/src/lib/CheapReduction.hs @@ -110,7 +110,7 @@ reduceExprM = \case withInstantiated def args \(PairE _ (InstanceBody _ methods)) -> do reduceApp (methods !! i) explicitArgs' _ -> empty - PrimOp (MiscOp (CastOp ty' val')) -> do + PrimOp ty' (MiscOp (CastOp val')) -> do ty <- substM ty' val <- substM val' case (ty, val) of @@ -124,7 +124,7 @@ reduceExprM = \case TopApp _ _ _ -> empty Case _ _ _ -> empty TabCon _ _ -> empty - PrimOp _ -> empty + PrimOp _ _ -> empty reduceApp :: CAtom i -> [CAtom o] -> ReducerM i o (CAtom o) reduceApp f xs = do @@ -392,7 +392,7 @@ instance IRRep r => VisitGeneric (Expr r) r where return $ Case x' alts' effTy' Atom x -> Atom <$> visitGeneric x TabCon t xs -> TabCon <$> visitGeneric t <*> mapM visitGeneric xs - PrimOp op -> PrimOp <$> visitGeneric op + PrimOp t op -> PrimOp <$> visitGeneric t <*> visitGeneric op App et fAtom xs -> App <$> visitGeneric et <*> visitGeneric fAtom <*> mapM visitGeneric xs ApplyMethod et m i xs -> ApplyMethod <$> visitGeneric et <*> visitGeneric m <*> pure i <*> mapM visitGeneric xs Project t i x -> Project <$> visitGeneric t <*> pure i <*> visitGeneric x diff --git a/src/lib/DPS.hs b/src/lib/DPS.hs index cc51897d8..af5f4f603 100644 --- a/src/lib/DPS.hs +++ b/src/lib/DPS.hs @@ -85,7 +85,7 @@ storeDest :: Emits o => Dest o -> SAtom o -> DestM i o () storeDest dest val = do RefTy (TyCon tycon) <- return $ getType dest case tycon of - BaseType _ -> void $ emit $ RefOp dest $ MPut val + BaseType _ -> undefined -- void $ emit $ RefOp dest $ MPut val -- The dps pass carries a non-type-preserving substitution in which arrays are -- replaced with refs to arrays. So it's incorrect to directly apply the @@ -121,7 +121,7 @@ dpsExpr maybeDest expr = case expr of return UnitVal Atom x -> lowerAtom x >>= returnResult TabCon _ _ -> undefined - PrimOp _ -> undefined + PrimOp _ _ -> undefined Project _ _ _ -> undefined where diff --git a/src/lib/Imp.hs b/src/lib/Imp.hs index e47de1171..e09298597 100644 --- a/src/lib/Imp.hs +++ b/src/lib/Imp.hs @@ -30,7 +30,7 @@ import qualified Control.Monad.State.Strict as MTL import Builder import CheapReduction -import CheckType (CheckableE (..)) +-- import CheckType (CheckableE (..)) import Core import Err import IRVariants @@ -289,7 +289,7 @@ translateExpr expr = confuseGHC >>= \_ -> case expr of results <- impCall f scalarArgs restructureScalarOrPairType resultTy results Atom x -> substM x - PrimOp op -> toImpOp op + PrimOp ty op -> toImpOp ty op Case e alts (EffTy _ unitResultTy) -> do e' <- substM e case unitResultTy of @@ -332,34 +332,38 @@ toImpRefOp refDest' m = do -- than to go through a general purpose atom. storeAtom dest =<< loadAtom refDest loadAtom dest - IndexRef _ i -> destToAtom <$> indexDest refDest i - ProjRef _ ~(ProjectProduct i) -> return $ destToAtom $ projectDest i refDest + IndexRef i -> destToAtom <$> indexDest refDest i + ProjRef ~(ProjectProduct i) -> return $ destToAtom $ projectDest i refDest -toImpOp :: forall i o . Emits o => PrimOp SimpIR i -> SubstImpM i o (SAtom o) -toImpOp op = case op of +toImpOp :: forall i o . Emits o => SType i -> PrimOp SimpIR i -> SubstImpM i o (SAtom o) +toImpOp resultTy op = case op of RefOp refDest eff -> toImpRefOp refDest eff BinOp binOp x y -> returnIExprVal =<< emitInstr =<< (IBinOp binOp <$> fsa x <*> fsa y) UnOp unOp x -> returnIExprVal =<< emitInstr =<< (IUnOp unOp <$> fsa x) MemOp op' -> toImpMemOp =<< substM op' - MiscOp op' -> toImpMiscOp =<< substM op' - VectorOp op' -> toImpVectorOp =<< substM op' + MiscOp op' -> do + resultTy' <- substM resultTy + toImpMiscOp resultTy' =<< substM op' + VectorOp op' -> do + resultTy' <- substM resultTy + toImpVectorOp resultTy' =<< substM op' where fsa x = substM x >>= fromScalarAtom returnIExprVal x = return $ toScalarAtom x -toImpVectorOp :: Emits o => VectorOp SimpIR o -> SubstImpM i o (SAtom o) -toImpVectorOp = \case - VectorBroadcast val vty -> do +toImpVectorOp :: Emits o => SType o -> VectorOp SimpIR o -> SubstImpM i o (SAtom o) +toImpVectorOp vty = \case + VectorBroadcast val -> do val' <- fromScalarAtom val emitInstr (IVectorBroadcast val' $ toIVectorType vty) >>= returnIExprVal - VectorIota vty -> emitInstr (IVectorIota $ toIVectorType vty) >>= returnIExprVal - VectorSubref ref i vty -> do + VectorIota -> emitInstr (IVectorIota $ toIVectorType vty) >>= returnIExprVal + VectorSubref ref i -> do refDest <- atomToDest ref refi <- destToAtom <$> indexDest refDest i refi' <- fromScalarAtom refi resultVal <- castPtrToVectorType refi' (toIVectorType vty) repValAtom $ RepVal (RefTy vty) (Leaf resultVal) - VectorIdx _ _ _ -> error "Unexpected VectorIdx in Imp pass" + VectorIdx _ _ -> error "Unexpected VectorIdx in Imp pass" where returnIExprVal x = return $ toScalarAtom x @@ -369,20 +373,20 @@ castPtrToVectorType ptr vty = do let PtrType (addrSpace, _) = getIType ptr cast ptr (PtrType (addrSpace, vty)) -toImpMiscOp :: forall i o . Emits o => MiscOp SimpIR o -> SubstImpM i o (SAtom o) -toImpMiscOp op = case op of - ThrowError resultTy -> do +toImpMiscOp :: forall i o . Emits o => SType o -> MiscOp SimpIR o -> SubstImpM i o (SAtom o) +toImpMiscOp resultTy op = case op of + ThrowError -> do emitStatement IThrowError buildGarbageVal resultTy - CastOp destTy x -> do + CastOp x -> do BaseTy _ <- return $ getType x - BaseTy bt <- return destTy + BaseTy bt <- return resultTy x' <- fsa x returnIExprVal =<< cast x' bt - BitcastOp destTy x -> do - BaseTy bt <- return destTy + BitcastOp x -> do + BaseTy bt <- return resultTy returnIExprVal =<< emitInstr =<< (IBitcastOp bt <$> fsa x) - UnsafeCoerce resultTy x -> do + UnsafeCoerce x -> do srcTy <- return $ getType x srcRep <- getRepBaseTypes srcTy destRep <- getRepBaseTypes resultTy @@ -390,8 +394,8 @@ toImpMiscOp op = case op of "representation types don't match: " ++ pprint srcRep ++ " != " ++ pprint destRep RepVal _ tree <- atomToRepVal x repValAtom (RepVal resultTy tree) - GarbageVal resultTy -> buildGarbageVal resultTy - NewRef _ -> error "not implemented" + GarbageVal -> buildGarbageVal resultTy + NewRef -> error "not implemented" Select p x y -> do BaseTy _ <- return $ getType x returnIExprVal =<< emitInstr =<< (ISelect <$> fsa p <*> fsa x <*> fsa y) @@ -401,15 +405,14 @@ toImpMiscOp op = case op of RepVal _ (Branch (tag:_)) <- return dRepVal return $ toAtom $ RepVal (TagRepTy :: SType o) tag _ -> error $ "Not a data constructor: " ++ pprint con - ToEnum ty i -> case ty of + ToEnum i -> case resultTy of TyCon (SumType cases) -> do i' <- fromScalarAtom i - return $ toAtom $ RepVal ty $ Branch $ Leaf i' : map (const (Branch [])) cases - _ -> error $ "Not an enum: " ++ pprint ty + return $ toAtom $ RepVal resultTy $ Branch $ Leaf i' : map (const (Branch [])) cases + _ -> error $ "Not an enum: " ++ pprint resultTy OutputStream -> returnIExprVal =<< emitInstr IOutputStream ShowAny _ -> error "Shouldn't have ShowAny in simplified IR" ShowScalar x -> do - resultTy <- return $ getType $ PrimOp $ MiscOp op Dest (PairTy sizeTy tabTy) (Branch [sizeTree, tabTree@(Leaf tabPtr)]) <- allocDest resultTy xScalar <- fromScalarAtom x size <- emitInstr $ IShowScalar tabPtr xScalar @@ -1234,8 +1237,8 @@ impInstrTypes instr = case instr of IShowScalar _ _ -> return [Scalar Word32Type] where hostPtrTy ty = PtrType (CPU, ty) -instance CheckableE SimpIR ImpFunction where - checkE = renameM -- TODO +-- instance CheckableE SimpIR ImpFunction where +-- checkE = renameM -- TODO -- TODO: Don't use Core Envs for Imp! instance BindsEnv ImpDecl where diff --git a/src/lib/Inference.hs b/src/lib/Inference.hs index ada21aa66..22a55b40b 100644 --- a/src/lib/Inference.hs +++ b/src/lib/Inference.hs @@ -29,7 +29,7 @@ import GHC.Generics (Generic (..)) import Builder import CheapReduction -import CheckType +-- import CheckType import Core import Err import IRVariants @@ -1037,12 +1037,12 @@ matchPrimApp = \case UCon con -> case con of P.ProdCon -> \xs -> return $ toAtom $ ProdCon xs P.SumCon _ -> error "not supported" - UMiscOp op -> \x -> emit =<< MiscOp <$> matchGenericOp op x - UMemOp op -> \x -> emit =<< MemOp <$> matchGenericOp op x - UBinOp op -> \case ~[x, y] -> emit $ BinOp op x y - UUnOp op -> \case ~[x] -> emit $ UnOp op x - UMGet -> \case ~[r] -> emit $ RefOp r MGet - UMPut -> \case ~[r, x] -> emit $ RefOp r $ MPut x + -- UMiscOp op -> \x -> emit =<< MiscOp <$> matchGenericOp op x + -- UMemOp op -> \x -> emit =<< MemOp <$> matchGenericOp op x + UBinOp op -> \case ~[x, y] -> emitBinOp op x y + UUnOp op -> \case ~[x] -> emitUnOp op x + UMGet -> \case ~[r] -> emitRefOp r MGet + UMPut -> \case ~[r, x] -> emitRefOp r $ MPut x UIndexRef -> \case ~[r, i] -> indexRef r i UApplyMethod i -> \case ~(d:args) -> emit =<< mkApplyMethod (fromJust $ toMaybeDict d) i args ULinearize -> \case ~[f, x] -> do f' <- lam1 f; emitHof $ Linearize f' x @@ -1116,7 +1116,7 @@ buildNthOrderedAlt alts _ resultTy i v = do case lookup i [(idx, alt) | IndexedAlt idx alt <- alts] of Nothing -> do resultTy' <- sinkM resultTy - emit $ ThrowError resultTy' + emit $ PrimOp resultTy' $ MiscOp ThrowError Just alt -> applyAbs alt (SubstVal v) >>= emit buildMonomorphicCase @@ -2213,14 +2213,6 @@ instance PrettyE e => Pretty (UDeclInferenceResult e l) where instance SinkableE e => SinkableE (UDeclInferenceResult e) where sinkingProofE = todoSinkableProof -instance (RenameE e, CheckableE CoreIR e) => CheckableE CoreIR (UDeclInferenceResult e) where - checkE = \case - UDeclResultDone e -> UDeclResultDone <$> checkE e - UDeclResultBindName ann block ab -> - UDeclResultBindName ann <$> checkE block <*> renameM ab -- TODO: check result - UDeclResultBindPattern hint block recon -> - UDeclResultBindPattern hint <$> checkE block <*> renameM recon -- TODO: check recon - instance GenericE SynthType where type RepE SynthType = EitherE2 DictType (PairE (LiftE [Explicitness]) (Abs (Nest CBinder) DictType)) fromE (SynthDictType d) = Case0 d diff --git a/src/lib/QueryTypePure.hs b/src/lib/QueryTypePure.hs index 43cc9b7ea..a2dfdf903 100644 --- a/src/lib/QueryTypePure.hs +++ b/src/lib/QueryTypePure.hs @@ -135,7 +135,7 @@ instance IRRep r => HasType r (Expr r) where Atom x -> getType x Block (EffTy _ ty) _ -> ty TabCon ty _ -> ty - PrimOp op -> getType op + PrimOp ty _ -> ty Case _ _ (EffTy _ resultTy) -> resultTy ApplyMethod (EffTy _ t) _ _ _ -> t Project t _ _ -> t @@ -145,21 +145,6 @@ instance IRRep r => HasType r (Expr r) where instance IRRep r => HasType r (RepVal r) where getType (RepVal ty _) = ty -instance IRRep r => HasType r (PrimOp r) where - getType primOp = case primOp of - BinOp op x _ -> TyCon $ BaseType $ typeBinOp op $ getTypeBaseType x - UnOp op x -> TyCon $ BaseType $ typeUnOp op $ getTypeBaseType x - MemOp op -> getType op - MiscOp op -> getType op - VectorOp op -> getType op - RefOp ref m -> case getType ref of - TyCon (RefType s) -> case m of - MGet -> s - MPut _ -> UnitTy - IndexRef t _ -> t - ProjRef t _ -> t - _ -> error "not a reference type" - getTypeBaseType :: (IRRep r, HasType r e) => e n -> BaseType getTypeBaseType e = case getType e of TyCon (BaseType b) -> b @@ -175,30 +160,6 @@ instance IRRep r => HasType r (MemOp r) where toType $ BaseType t PtrStore _ _ -> UnitTy -instance IRRep r => HasType r (VectorOp r) where - getType = \case - VectorBroadcast _ vty -> vty - VectorIota vty -> vty - VectorIdx _ _ vty -> vty - VectorSubref ref _ vty -> case getType ref of - TyCon (RefType _) -> TyCon $ RefType vty - ty -> error $ "Not a reference type: " ++ show ty - -instance IRRep r => HasType r (MiscOp r) where - getType = \case - Select _ x _ -> getType x - ThrowError t -> t - CastOp t _ -> t - BitcastOp t _ -> t - UnsafeCoerce t _ -> t - GarbageVal t -> t - SumTag _ -> TagRepTy - ToEnum t _ -> t - OutputStream -> toType $ BaseType $ hostPtrTy $ Scalar Word8Type - where hostPtrTy ty = PtrType (CPU, ty) - ShowAny _ -> rawStrType -- TODO: constrain `ShowAny` to have `HasCore r` - ShowScalar _ -> toType $ ProdType [IdxRepTy, rawFinTabType (IdxRepVal showStringBufferSize) CharRepTy] - rawStrType :: IRRep r => Type r n rawStrType = case newName "n" of Abs b v -> do @@ -255,7 +216,7 @@ instance IRRep r => HasEffects (Expr r) r where Case _ _ (EffTy effs _) -> effs TabCon _ _ -> Pure ApplyMethod (EffTy eff _) _ _ _ -> eff - PrimOp primOp -> getEffects primOp + PrimOp _ primOp -> getEffects primOp Project _ _ _ -> Pure Unwrap _ _ -> Pure Hof (TypedHof (EffTy eff _) _) -> eff @@ -277,19 +238,19 @@ instance IRRep r => HasEffects (PrimOp r) r where PtrOffset _ _ -> Pure MiscOp op -> case op of Select _ _ _ -> Pure - ThrowError _ -> Pure - CastOp _ _ -> Pure - UnsafeCoerce _ _ -> Pure - GarbageVal _ -> Pure - BitcastOp _ _ -> Pure + ThrowError -> Pure + CastOp _ -> Pure + UnsafeCoerce _ -> Pure + GarbageVal -> Pure + BitcastOp _ -> Pure SumTag _ -> Pure - ToEnum _ _ -> Pure + ToEnum _ -> Pure OutputStream -> Pure ShowAny _ -> Pure ShowScalar _ -> Pure RefOp _ m -> case m of MGet -> Effectful MPut _ -> Effectful - IndexRef _ _ -> Pure - ProjRef _ _ -> Pure + IndexRef _ -> Pure + ProjRef _ -> Pure {-# INLINE getEffects #-} diff --git a/src/lib/Simplify.hs b/src/lib/Simplify.hs index cc9e9d2f6..6359b1b98 100644 --- a/src/lib/Simplify.hs +++ b/src/lib/Simplify.hs @@ -24,7 +24,7 @@ import Name import Subst import PPrint import QueryType -import RuntimePrint +-- import RuntimePrint -- import Transpose import Types.Core import Types.Top @@ -221,7 +221,7 @@ simplifyExpr = \case f' <- toDataAtom f simplifyTabApp f' x' Atom x -> simplifyAtom x - PrimOp op -> simplifyOp op + PrimOp _ op -> simplifyOp op Hof (TypedHof (EffTy _ ty) hof) -> simplifyHof hof ApplyMethod (EffTy _ ty) dict i xs -> do xs' <- mapM simplifyAtom xs @@ -255,16 +255,16 @@ requireReduced expr = reduceExpr expr >>= \case simplifyRefOp :: Emits o => RefOp CoreIR i -> SAtom o -> SimplifyM i o (SAtom o) simplifyRefOp op ref = case op of - MGet -> emit $ RefOp ref MGet + MGet -> undefined -- emit $ RefOp ref MGet MPut x -> do x' <- toDataAtom x emitRefOp $ MPut x' - IndexRef _ x -> do + IndexRef x -> do x' <- toDataAtom x emit =<< mkIndexRef ref x' - ProjRef _ (ProjectProduct i) -> emit =<< mkProjRef ref (ProjectProduct i) - ProjRef _ UnwrapNewtype -> return ref - where emitRefOp op' = emit $ RefOp ref op' + ProjRef (ProjectProduct i) -> emit =<< mkProjRef ref (ProjectProduct i) + ProjRef UnwrapNewtype -> return ref + where emitRefOp op' = undefined -- emit $ RefOp ref op' simplifyApp :: Emits o => SimpVal o -> [SimpVal o] -> SimplifyM i o (SimpVal o) simplifyApp f xs = case f of @@ -410,22 +410,23 @@ simplifyLam (LamExpr bsTop body) = case bsTop of simplifyOp :: Emits o => PrimOp CoreIR i -> SimplifyM i o (SimpVal o) simplifyOp op = case op of MemOp op' -> simplifyGenericOp op' - VectorOp op' -> simplifyGenericOp op' + VectorOp op' -> undefined -- simplifyGenericOp op' RefOp ref eff -> do ref' <- toDataAtom ref SimpAtom <$> simplifyRefOp eff ref' BinOp binop x y -> do x' <- toDataAtom x y' <- toDataAtom y - SimpAtom <$> emit (BinOp binop x' y') + SimpAtom <$> emitBinOp binop x' y' UnOp unOp x -> do x' <- toDataAtom x - SimpAtom <$> emit (UnOp unOp x') + SimpAtom <$> emitUnOp unOp x' MiscOp op' -> case op' of - ShowAny x -> do - x' <- toDataAtom x - dropSubst $ showAny x' >>= simplifyExpr - _ -> simplifyGenericOp op' + ShowAny x -> undefined + -- ShowAny x -> do + -- x' <- toDataAtom x + -- dropSubst $ showAny x' >>= simplifyExpr + _ -> undefined -- simplifyGenericOp op' simplifyGenericOp :: (GenericOp op, ToExpr (op SimpIR) SimpIR, HasType CoreIR (op CoreIR), Emits o, diff --git a/src/lib/TopLevel.hs b/src/lib/TopLevel.hs index 2b351fdad..4710baf58 100644 --- a/src/lib/TopLevel.hs +++ b/src/lib/TopLevel.hs @@ -43,10 +43,10 @@ import qualified LLVM.AST import AbstractSyntax import Builder -import CheckType ( CheckableE (..), checkTypeIs) -#ifdef DEX_DEBUG -import CheckType (checkTypes) -#endif +-- import CheckType ( CheckableE (..), checkTypeIs) +-- #ifdef DEX_DEBUG +-- import CheckType (checkTypes) +-- #endif import Core import ConcreteSyntax import CheapReduction @@ -288,36 +288,37 @@ evalSourceBlock' mname block = case sbContents block of let desc = makeTopNameDescription mname block emitSourceMap $ SourceMap $ M.singleton dexName [ModuleVar desc (Just $ UAtomVar vCore)] - DeclareCustomLinearization fname zeros g -> do - expr <- parseExpr g - lookupSourceMap (withoutSrc fname) >>= \case - Nothing -> throw rootSrcId $ UnboundVarErr $ pprint fname - Just (UAtomVar fname') -> do - lookupCustomRules fname' >>= \case - Nothing -> return () - Just _ -> throwErr $ MiscErr $ MiscMiscErr - $ pprint fname ++ " already has a custom linearization" - lookupAtomName fname' >>= \case - NoinlineFun _ _ -> return () - _ -> throwErr $ MiscErr $ MiscMiscErr "Custom linearizations only apply to @noinline functions" - -- We do some special casing to avoid instantiating polymorphic functions. - impl <- case expr of - WithSrcE _ (UVar _) -> - renameSourceNamesUExpr expr >>= \case - WithSrcE _ (UVar (InternalName _ _ (UAtomVar v))) -> toAtom <$> toAtomVar v - _ -> error "Expected a variable" - _ -> evalUExpr expr - fType <- getType <$> toAtomVar fname' - (nimplicit, nexplicit, linFunTy) <- liftExceptEnvReaderM $ getLinearizationType zeros fType - liftEnvReaderT (impl `checkTypeIs` linFunTy) >>= \case - Failure _ -> do - let implTy = getType impl - throwErr $ MiscErr $ MiscMiscErr $ unlines - [ "Expected the custom linearization to have type:" , "" , pprint linFunTy , "" - , "but it has type:" , "" , pprint implTy] - Success () -> return () - updateTopEnv $ AddCustomRule fname' $ CustomLinearize nimplicit nexplicit zeros impl - Just _ -> throwErr $ MiscErr $ MiscMiscErr $ "Custom linearization can only be defined for functions" + DeclareCustomLinearization fname zeros g -> undefined + -- DeclareCustomLinearization fname zeros g -> do + -- expr <- parseExpr g + -- lookupSourceMap (withoutSrc fname) >>= \case + -- Nothing -> throw rootSrcId $ UnboundVarErr $ pprint fname + -- Just (UAtomVar fname') -> do + -- lookupCustomRules fname' >>= \case + -- Nothing -> return () + -- Just _ -> throwErr $ MiscErr $ MiscMiscErr + -- $ pprint fname ++ " already has a custom linearization" + -- lookupAtomName fname' >>= \case + -- NoinlineFun _ _ -> return () + -- _ -> throwErr $ MiscErr $ MiscMiscErr "Custom linearizations only apply to @noinline functions" + -- -- We do some special casing to avoid instantiating polymorphic functions. + -- impl <- case expr of + -- WithSrcE _ (UVar _) -> + -- renameSourceNamesUExpr expr >>= \case + -- WithSrcE _ (UVar (InternalName _ _ (UAtomVar v))) -> toAtom <$> toAtomVar v + -- _ -> error "Expected a variable" + -- _ -> evalUExpr expr + -- fType <- getType <$> toAtomVar fname' + -- (nimplicit, nexplicit, linFunTy) <- liftExceptEnvReaderM $ getLinearizationType zeros fType + -- liftEnvReaderT (impl `checkTypeIs` linFunTy) >>= \case + -- Failure _ -> do + -- let implTy = getType impl + -- throwErr $ MiscErr $ MiscMiscErr $ unlines + -- [ "Expected the custom linearization to have type:" , "" , pprint linFunTy , "" + -- , "but it has type:" , "" , pprint implTy] + -- Success () -> return () + -- updateTopEnv $ AddCustomRule fname' $ CustomLinearize nimplicit nexplicit zeros impl + -- Just _ -> throwErr $ MiscErr $ MiscMiscErr $ "Custom linearization can only be defined for functions" UnParseable _ s -> throwErr $ ParseErr $ MiscParseErr s Misc m -> case m of GetNameType v -> do @@ -596,10 +597,11 @@ compileTopLevelFun cc fSimp = do checkPass ImpPass $ toImpFunction cc flOpt printCodegen :: (Topper m, Mut n) => CAtom n -> m n String -printCodegen x = do - block <- liftBuilder $ buildBlock $ emit $ ShowAny $ sink x - (topBlock, _) <- asTopBlock block - getDexString =<< evalBlock topBlock +printCodegen x = undefined +-- printCodegen x = do +-- block <- liftBuilder $ buildBlock $ emit $ ShowAny $ sink x +-- (topBlock, _) <- asTopBlock block +-- getDexString =<< evalBlock topBlock loadObject :: (Topper m, Mut n) => FunObjCodeName n -> m n NativeFunction loadObject fname = @@ -674,20 +676,27 @@ funNameToObj v = do TopFunBinding (DexTopFun _ _ (Finished impl)) -> return $ topFunObjCode impl b -> error $ "couldn't find object cache entry for " ++ pprint v ++ "\ngot:\n" ++ pprint b -checkPass :: (Topper m, Pretty (e n), CheckableE r e) +checkPass :: (Topper m, Pretty (e n)) => PassName -> m n (e n) -> m n (e n) checkPass name cont = do result <- cont logPass name result -#ifdef DEX_DEBUG - logDebug $ return $ MiscLog $ "Running checks" - checkTypes result - logDebug $ return $ MiscLog $ "Checks passed" -#else - logDebug $ return $ MiscLog $ "Checks skipped (not a debug build)" -#endif return result +-- checkPass :: (Topper m, Pretty (e n), CheckableE r e) +-- => PassName -> m n (e n) -> m n (e n) +-- checkPass name cont = do +-- result <- cont +-- logPass name result +-- #ifdef DEX_DEBUG +-- logDebug $ return $ MiscLog $ "Running checks" +-- checkTypes result +-- logDebug $ return $ MiscLog $ "Checks passed" +-- #else +-- logDebug $ return $ MiscLog $ "Checks skipped (not a debug build)" +-- #endif +-- return result + logTop :: TopLogger m => Output -> m () logTop x = emitLog $ Outputs [x] diff --git a/src/lib/Types/Core.hs b/src/lib/Types/Core.hs index 04afee621..cb4ff668d 100644 --- a/src/lib/Types/Core.hs +++ b/src/lib/Types/Core.hs @@ -109,7 +109,7 @@ data Expr r n where Case :: Atom r n -> [Alt r n] -> EffTy r n -> Expr r n Atom :: Atom r n -> Expr r n TabCon :: Type r n -> [Atom r n] -> Expr r n - PrimOp :: PrimOp r n -> Expr r n + PrimOp :: Type r n -> PrimOp r n -> Expr r n Hof :: TypedHof r n -> Expr r n Project :: Type r n -> Int -> Atom r n -> Expr r n App :: EffTy CoreIR n -> CAtom n -> [CAtom n] -> Expr CoreIR n @@ -319,16 +319,16 @@ data MemOp (r::IR) (n::S) = data MiscOp (r::IR) (n::S) = Select (Atom r n) (Atom r n) (Atom r n) -- (3) predicate, val-if-true, val-if-false - | CastOp (Type r n) (Atom r n) -- (2) Type, then value. See CheckType.hs for valid coercions. - | BitcastOp (Type r n) (Atom r n) -- (2) Type, then value. See CheckType.hs for valid coercions. - | UnsafeCoerce (Type r n) (Atom r n) -- type, then value. Assumes runtime representation is the same. - | GarbageVal (Type r n) -- type of value (assume `Data` constraint) (TODO: redundant with NewRef) - | NewRef (Type r n) - | ThrowError (Type r n) -- (1) Hard error (parameterized by result type) + | CastOp (Atom r n) -- (2) See CheckType.hs for valid coercions. + | BitcastOp (Atom r n) -- (2) See CheckType.hs for valid coercions. + | UnsafeCoerce (Atom r n) -- type, then value. Assumes runtime representation is the same. + | GarbageVal -- (TODO: redundant with NewRef) + | NewRef + | ThrowError -- Tag of a sum type | SumTag (Atom r n) -- Create an enum (payload-free ADT) from a Word8 - | ToEnum (Type r n) (Atom r n) + | ToEnum (Atom r n) -- printing | OutputStream | ShowAny (Atom r n) -- implemented in Simplify @@ -341,10 +341,10 @@ showStringBufferSize :: Word32 showStringBufferSize = 32 data VectorOp r n = - VectorBroadcast (Atom r n) (Type r n) -- value, vector type - | VectorIota (Type r n) -- vector type - | VectorIdx (Atom r n) (Atom r n) (Type r n) -- table, base ix, vector type - | VectorSubref (Atom r n) (Atom r n) (Type r n) -- ref, base ix, vector type + VectorBroadcast (Atom r n) -- value, + | VectorIota + | VectorIdx (Atom r n) (Atom r n) -- table, base ix + | VectorSubref (Atom r n) (Atom r n) -- ref, base ix deriving (Show, Generic) data TypedHof r n = TypedHof (EffTy r n) (Hof r n) @@ -362,8 +362,8 @@ deriving via WrapE (Hof r) n instance IRRep r => Generic (Hof r n) data RefOp r n = MGet | MPut (Atom r n) - | IndexRef (Type r n) (Atom r n) - | ProjRef (Type r n) Projection + | IndexRef (Atom r n) + | ProjRef Projection deriving (Show, Generic) -- === IR variants === @@ -553,21 +553,6 @@ toMaybeDict = \case Con (DictConAtom d) -> Just $ DictCon d _ -> Nothing --- === ToExpr === - -class ToExpr (e::E) (r::IR) | e -> r where - toExpr :: e n -> Expr r n - -instance ToExpr (Expr r) r where toExpr = id -instance ToExpr (Atom r) r where toExpr = Atom -instance ToExpr (Con r) r where toExpr = Atom . Con -instance ToExpr (AtomVar r) r where toExpr = toExpr . toAtom -instance ToExpr (PrimOp r) r where toExpr = PrimOp -instance ToExpr (MiscOp r) r where toExpr = PrimOp . MiscOp -instance ToExpr (MemOp r) r where toExpr = PrimOp . MemOp -instance ToExpr (VectorOp r) r where toExpr = PrimOp . VectorOp -instance ToExpr (TypedHof r) r where toExpr = Hof - -- === Pattern synonyms === pattern IdxRepScalarBaseTy :: ScalarBaseType @@ -850,14 +835,14 @@ instance GenericOp RefOp where fromOp = \case MGet -> GenericOpRep P.MGet Nothing [] MPut x -> GenericOpRep P.MPut Nothing [x] - IndexRef t x -> GenericOpRep P.IndexRef (Just t) [x] - ProjRef t p -> GenericOpRep (P.ProjRef p) (Just t) [] + IndexRef x -> GenericOpRep P.IndexRef Nothing [x] + ProjRef p -> GenericOpRep (P.ProjRef p) Nothing [] {-# INLINE fromOp #-} toOp = \case GenericOpRep P.MGet Nothing [] -> Just $ MGet GenericOpRep P.MPut Nothing [x] -> Just $ MPut x - GenericOpRep P.IndexRef (Just t) [x] -> Just $ IndexRef t x - GenericOpRep (P.ProjRef p) (Just t) [] -> Just $ ProjRef t p + GenericOpRep P.IndexRef Nothing [x] -> Just $ IndexRef x + GenericOpRep (P.ProjRef p) Nothing [] -> Just $ ProjRef p _ -> Nothing {-# INLINE toOp #-} @@ -991,7 +976,7 @@ instance IRRep r => GenericE (Expr r) where ) ( EitherE6 {- TabCon -} (Type r `PairE` ListE (Atom r)) - {- PrimOp -} (PrimOp r) + {- PrimOp -} (Type r `PairE` PrimOp r) {- ApplyMethod -} (WhenCore r (EffTy r `PairE` Atom r `PairE` LiftE Int `PairE` ListE (Atom r))) {- Project -} (Type r `PairE` LiftE Int `PairE` Atom r) {- Unwrap -} (WhenCore r (CType `PairE` CAtom)) @@ -1004,7 +989,7 @@ instance IRRep r => GenericE (Expr r) where TopApp et f xs -> Case0 $ Case4 (WhenIRE (et `PairE` f `PairE` ListE xs)) Block et block -> Case0 $ Case5 (et `PairE` block) TabCon ty xs -> Case1 $ Case0 (ty `PairE` ListE xs) - PrimOp op -> Case1 $ Case1 op + PrimOp ty op -> Case1 $ Case1 (ty `PairE` op) ApplyMethod et d i xs -> Case1 $ Case2 (WhenIRE (et `PairE` d `PairE` LiftE i `PairE` ListE xs)) Project ty i x -> Case1 $ Case3 (ty `PairE` LiftE i `PairE` x) Unwrap t x -> Case1 $ Case4 (WhenIRE (t `PairE` x)) @@ -1021,7 +1006,7 @@ instance IRRep r => GenericE (Expr r) where _ -> error "impossible" Case1 case1 -> case case1 of Case0 (ty `PairE` ListE xs) -> TabCon ty xs - Case1 op -> PrimOp op + Case1 (ty `PairE` op) -> PrimOp ty op Case2 (WhenIRE (et `PairE` d `PairE` LiftE i `PairE` ListE xs)) -> ApplyMethod et d i xs Case3 (ty `PairE` LiftE i `PairE` x) -> Project ty i x Case4 (WhenIRE (t `PairE` x)) -> Unwrap t x @@ -1072,17 +1057,17 @@ instance IRRep r => RenameE (PrimOp r) instance GenericOp VectorOp where type OpConst VectorOp r = P.VectorOp fromOp = \case - VectorBroadcast x t -> GenericOpRep P.VectorBroadcast (Just t) [x] - VectorIota t -> GenericOpRep P.VectorIota (Just t) [] - VectorIdx x y t -> GenericOpRep P.VectorIdx (Just t) [x, y] - VectorSubref x y t -> GenericOpRep P.VectorSubref (Just t) [x, y] + VectorBroadcast x -> GenericOpRep P.VectorBroadcast Nothing [x] + VectorIota -> GenericOpRep P.VectorIota Nothing [] + VectorIdx x y -> GenericOpRep P.VectorIdx Nothing [x, y] + VectorSubref x y -> GenericOpRep P.VectorSubref Nothing [x, y] {-# INLINE fromOp #-} toOp = \case - GenericOpRep P.VectorBroadcast (Just t) [x] -> Just $ VectorBroadcast x t - GenericOpRep P.VectorIota (Just t) [] -> Just $ VectorIota t - GenericOpRep P.VectorIdx (Just t) [x, y] -> Just $ VectorIdx x y t - GenericOpRep P.VectorSubref (Just t) [x, y] -> Just $ VectorSubref x y t + GenericOpRep P.VectorBroadcast Nothing [x] -> Just $ VectorBroadcast x + GenericOpRep P.VectorIota Nothing [] -> Just $ VectorIota + GenericOpRep P.VectorIdx Nothing [x, y] -> Just $ VectorIdx x y + GenericOpRep P.VectorSubref Nothing [x, y] -> Just $ VectorSubref x y _ -> Nothing {-# INLINE toOp #-} @@ -1128,28 +1113,28 @@ instance GenericOp MiscOp where type OpConst MiscOp r = P.MiscOp fromOp = \case Select p x y -> GenericOpRep P.Select Nothing [p,x,y] - CastOp t x -> GenericOpRep P.CastOp (Just t) [x] - BitcastOp t x -> GenericOpRep P.BitcastOp (Just t) [x] - UnsafeCoerce t x -> GenericOpRep P.UnsafeCoerce (Just t) [x] - GarbageVal t -> GenericOpRep P.GarbageVal (Just t) [] - NewRef t -> GenericOpRep P.NewRef (Just t) [] - ThrowError t -> GenericOpRep P.ThrowError (Just t) [] + CastOp x -> GenericOpRep P.CastOp Nothing [x] + BitcastOp x -> GenericOpRep P.BitcastOp Nothing [x] + UnsafeCoerce x -> GenericOpRep P.UnsafeCoerce Nothing [x] + GarbageVal -> GenericOpRep P.GarbageVal Nothing [] + NewRef -> GenericOpRep P.NewRef Nothing [] + ThrowError -> GenericOpRep P.ThrowError Nothing [] SumTag x -> GenericOpRep P.SumTag Nothing [x] - ToEnum t x -> GenericOpRep P.ToEnum (Just t) [x] + ToEnum x -> GenericOpRep P.ToEnum Nothing [x] OutputStream -> GenericOpRep P.OutputStream Nothing [] ShowAny x -> GenericOpRep P.ShowAny Nothing [x] ShowScalar x -> GenericOpRep P.ShowScalar Nothing [x] {-# INLINE fromOp #-} toOp = \case GenericOpRep P.Select Nothing [p,x,y] -> Just $ Select p x y - GenericOpRep P.CastOp (Just t) [x] -> Just $ CastOp t x - GenericOpRep P.BitcastOp (Just t) [x] -> Just $ BitcastOp t x - GenericOpRep P.UnsafeCoerce (Just t) [x] -> Just $ UnsafeCoerce t x - GenericOpRep P.GarbageVal (Just t) [] -> Just $ GarbageVal t - GenericOpRep P.NewRef (Just t) [] -> Just $ NewRef t - GenericOpRep P.ThrowError (Just t) [] -> Just $ ThrowError t + GenericOpRep P.CastOp Nothing [x] -> Just $ CastOp x + GenericOpRep P.BitcastOp Nothing [x] -> Just $ BitcastOp x + GenericOpRep P.UnsafeCoerce Nothing [x] -> Just $ UnsafeCoerce x + GenericOpRep P.GarbageVal Nothing [] -> Just $ GarbageVal + GenericOpRep P.NewRef Nothing [] -> Just $ NewRef + GenericOpRep P.ThrowError Nothing [] -> Just $ ThrowError GenericOpRep P.SumTag Nothing [x] -> Just $ SumTag x - GenericOpRep P.ToEnum (Just t) [x] -> Just $ ToEnum t x + GenericOpRep P.ToEnum Nothing [x] -> Just $ ToEnum x GenericOpRep P.OutputStream Nothing [] -> Just $ OutputStream GenericOpRep P.ShowAny Nothing [x] -> Just $ ShowAny x GenericOpRep P.ShowScalar Nothing [x] -> Just $ ShowScalar x @@ -1706,8 +1691,8 @@ instance IRRep r => PrettyPrec (PrimOp r n) where RefOp ref eff -> atPrec LowestPrec case eff of MGet -> "get" <+> pApp ref MPut x -> pApp ref <+> ":=" <+> pApp x - IndexRef _ i -> pApp ref <+> "!" <+> pApp i - ProjRef _ i -> "proj_ref" <+> pApp ref <+> p i + IndexRef i -> pApp ref <+> "!" <+> pApp i + ProjRef i -> "proj_ref" <+> pApp ref <+> p i UnOp op x -> prettyOpDefault (UUnOp op) [x] BinOp op x y -> prettyOpDefault (UBinOp op) [x, y] MiscOp op -> prettyOpGeneric op @@ -1725,10 +1710,10 @@ instance IRRep r => PrettyPrec (MemOp r n) where instance IRRep r => Pretty (VectorOp r n) where pretty = prettyFromPrettyPrec instance IRRep r => PrettyPrec (VectorOp r n) where prettyPrec = \case - VectorBroadcast v vty -> atPrec LowestPrec $ "vbroadcast" <+> pApp v <+> pApp vty - VectorIota vty -> atPrec LowestPrec $ "viota" <+> pApp vty - VectorIdx tbl i vty -> atPrec LowestPrec $ "vslice" <+> pApp tbl <+> pApp i <+> pApp vty - VectorSubref ref i _ -> atPrec LowestPrec $ "vrefslice" <+> pApp ref <+> pApp i + VectorBroadcast v -> atPrec LowestPrec $ "vbroadcast" <+> pApp v + VectorIota -> atPrec LowestPrec $ "viota" + VectorIdx tbl i -> atPrec LowestPrec $ "vslice" <+> pApp tbl <+> pApp i + VectorSubref ref i -> atPrec LowestPrec $ "vrefslice" <+> pApp ref <+> pApp i prettyOpGeneric :: (IRRep r, GenericOp op, Show (OpConst op r)) => op r n -> DocPrec ann prettyOpGeneric op = case fromEGenericOpRep op of @@ -1772,7 +1757,7 @@ instance IRRep r => PrettyPrec (Expr r n) where TabApp _ f x -> atPrec AppPrec $ pApp f <> brackets (p x) Case e alts _ -> prettyPrecCase "case" e alts TabCon _ es -> atPrec ArgPrec $ list $ pApp <$> es - PrimOp op -> prettyPrec op + PrimOp _ op -> prettyPrec op ApplyMethod _ d i xs -> atPrec AppPrec $ "applyMethod" <+> p d <+> p i <+> p xs Project _ i x -> atPrec AppPrec $ "Project" <+> p i <+> p x Unwrap _ x -> atPrec AppPrec $ "Unwrap" <+> p x