]> hydra-www.ietfng.org Git - dyna2/commitdiff
Some initial progress towards a K3 backend: AST, renderer, and examples
authorNathaniel Wesley Filardo <nwf@pf.priv.oc.ietfng.org>
Sat, 22 Sep 2012 03:11:45 +0000 (23:11 -0400)
committerNathaniel Wesley Filardo <nwf@pf.priv.oc.ietfng.org>
Sat, 22 Sep 2012 03:11:45 +0000 (23:11 -0400)
src/Dyna/BackendK3/AST.hs [new file with mode: 0644]
src/Dyna/BackendK3/Examples.hs [new file with mode: 0644]
src/Dyna/BackendK3/Render.hs [new file with mode: 0644]

diff --git a/src/Dyna/BackendK3/AST.hs b/src/Dyna/BackendK3/AST.hs
new file mode 100644 (file)
index 0000000..16a9c91
--- /dev/null
@@ -0,0 +1,347 @@
+---------------------------------------------------------------------------
+-- Header material
+------------------------------------------------------------------------{{{
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+
+  -- | An AST for K3.
+  --
+  -- To as large of an extent as possible, we wish to capture the static 
+  -- semantics of K3 in the Haskell type system.
+module Dyna.BackendK3.AST where
+
+import           Data.Word
+import           GHC.Prim (Constraint)
+
+------------------------------------------------------------------------}}}
+-- Preliminaries
+------------------------------------------------------------------------{{{
+
+newtype VarIx  = Var String
+newtype AddrIx = Addr (String,Int)
+
+data Ann = Ann [String]
+
+------------------------------------------------------------------------}}}
+-- Collections
+------------------------------------------------------------------------{{{
+
+data CKind = CSet | CBag | CList
+
+data CTE (c :: CKind) e
+
+data CollTy c where
+  CTSet  :: CollTy CSet
+  CTBag  :: CollTy CBag
+  CTList :: CollTy CList
+
+------------------------------------------------------------------------}}}
+-- Effectables (XXX TODO)
+------------------------------------------------------------------------{{{
+
+{-
+data MKind = MKImmut | MKMut
+
+data MTy m where
+  MTImmut :: MTy MKImmut
+  MTMut   :: MTy MKMut
+
+data VKind = VKIsol | VKCont
+
+data VTy v where
+  VTIsol :: VTy VKIsol
+  VTCont :: VTy VKCont
+-}
+
+------------------------------------------------------------------------}}}
+-- Type System
+------------------------------------------------------------------------{{{
+
+  -- | Data level representation of K3 types, indexed by equivalent type in
+  -- Haskell.
+class K3Ty (r :: * -> *) where
+    -- | Attach an annotation to a type
+  tAnn    :: Ann -> r a -> r a
+
+  tBool   :: r Bool
+  tByte   :: r Word8
+  tFloat  :: r Float
+  tInt    :: r Int
+  tString :: r String
+  tUnit   :: r ()
+  tUnk    :: r a
+
+{- TAddress | TTarget BaseTy -}
+
+  tPair   :: r a -> r b -> r (a,b)
+
+  tMaybe  :: r a -> r (Maybe a)
+
+  tColl   :: CollTy c -> r a -> r (CTE c a)
+
+  tFun    :: r a -> r b -> r (a -> b)
+
+  -- | Existential typeclass wrapper for K3Ty
+newtype ExTyRepr (a :: *) = ETR { unETR :: forall r . (K3Ty r) => r a }
+instance K3Ty ExTyRepr where
+  tAnn   s (ETR t)               = ETR$tAnn s t
+  tBool                          = ETR tBool
+  tByte                          = ETR tByte
+  tFloat                         = ETR tFloat
+  tInt                           = ETR tInt
+  tString                        = ETR tString
+  tUnit                          = ETR tUnit
+  tUnk                           = ETR tUnk
+
+  tPair  (ETR a) (ETR b) = ETR$tPair a b
+  tMaybe (ETR a)         = ETR$tMaybe a
+  tColl  c (ETR a)       = ETR$tColl c a
+  tFun   (ETR a) (ETR b) = ETR$tFun a b
+
+------------------------------------------------------------------------}}}
+-- Pattern System
+------------------------------------------------------------------------{{{
+
+  -- | Kinds of patterns permitted in K3
+data PKind where
+  PKVar  :: k -> PKind
+  PKJust :: PKind -> PKind
+  PKPair :: PKind -> PKind -> PKind
+
+  -- | Provides witnesses that certain types may be used
+  --   as arguments to K3 lambdas.  Useful when building
+  --   up type signatures and pattern matches in lambdas.
+  --
+  --   Note that this is a closed class using the promoted
+  --   data PKind.
+class Pat (w :: PKind) where
+    -- | Any data this witness needs to carry around
+  data PatDa w :: *
+    -- | The type this witness witnesses?
+  type PatTy w :: *
+    -- | The type of this pattern.
+  type PatReprFn w (r :: * -> *) :: *
+    -- | Produce a data-level type representation for this witness
+  patAsRepr :: PatDa w -> ExTyRepr (PatTy w)
+
+instance Pat (PKVar (a :: *)) where
+  -- | Pattern variables may be of any type, but we have to
+  --   have a representation builder for it.
+  data PatDa (PKVar a) = PVar { unPVar :: ExTyRepr a }
+  type PatTy (PKVar a) = a
+  type PatReprFn (PKVar a) r = r a
+
+  patAsRepr = unPVar
+
+instance (Pat w) => Pat (PKJust w) where
+  -- | Just patterns (fail on Nothing)
+  --
+  -- Note the distinction between PatTy and PatReprFn here!
+  -- This pattern witnesses a type "Maybe a" but binds a variable of type
+  -- "a".  This will in general be true of any variant (i.e. sum) pattern.
+  data PatDa (PKJust w)       = PJust (PatDa w)
+  type PatTy (PKJust w)       = Maybe (PatTy w)
+  type PatReprFn (PKJust w) r = PatReprFn w r
+
+  patAsRepr (PJust w') = ETR $ tMaybe $ unETR $ patAsRepr w'
+
+instance (Pat wa, Pat wb) => Pat (PKPair wa wb) where
+  -- | Pair patterns
+  --
+  -- Product patterns, on the other hand, have PatTy and PatReprFn both
+  -- producing tuples.
+  data PatDa (PKPair wa wb)       = PPair (PatDa wa) (PatDa wb)
+  type PatTy (PKPair wa wb)       = (PatTy wa, PatTy wb)
+  type PatReprFn (PKPair wa wb) r = (PatReprFn wa r, PatReprFn wb r)
+
+  patAsRepr (PPair wa wb) = ETR $ tPair (unETR $ patAsRepr wa)
+                                        (unETR $ patAsRepr wb)
+
+------------------------------------------------------------------------}}}
+-- Slice System
+------------------------------------------------------------------------{{{
+
+  -- | Kinds of slices permitted in K3
+data SKind where
+  SKVar  :: k -> SKind
+  SKJust :: SKind -> SKind
+  SKPair :: SKind -> SKind -> SKind
+
+  -- | Witness of slice well-formedness
+class Slice (w :: SKind) where
+  data SliceDa w :: *
+  type SliceTy w :: *
+  sliceAsRepr :: SliceDa w -> ExTyRepr (SliceTy w)
+
+  -- Slice variables are VarIx and representation of K3 type
+instance Slice (SKVar (a :: *)) where
+  data SliceDa (SKVar a) = SVar VarIx (ExTyRepr a)
+  type SliceTy (SKVar a) = a
+  sliceAsRepr (SVar _ ea) = ea
+
+instance (Slice s) => Slice (SKJust s) where
+  data SliceDa (SKJust s) = SJust (SliceDa s)
+  type SliceTy (SKJust s) = Maybe (SliceTy s)
+  sliceAsRepr (SJust a) = ETR $ tMaybe $ unETR $ sliceAsRepr a
+
+instance (Slice sa, Slice sb) => Slice (SKPair sa sb) where
+  data SliceDa (SKPair sa sb) = SPair (SliceDa sa) (SliceDa sb)
+  type SliceTy (SKPair sa sb) = (SliceTy sa, SliceTy sb)
+  sliceAsRepr (SPair a b) = ETR $ tPair (unETR $ sliceAsRepr a)
+                                        (unETR $ sliceAsRepr b)
+
+------------------------------------------------------------------------}}}
+-- Numeric Autocasting
+------------------------------------------------------------------------{{{
+
+  -- | Unary numerics
+class UnNum a where unneg :: a -> a
+instance UnNum Bool  where unneg = not
+instance UnNum Int   where unneg x = (-x)
+instance UnNum Float where unneg x = (-x)
+
+  -- | Binary numerics
+class BiNum a b where 
+  type BNTF a b :: *
+  biadd :: a -> b -> BNTF a b
+  bimul :: a -> b -> BNTF a b
+
+instance BiNum Bool Bool where 
+  type BNTF Bool Bool = Bool
+  biadd = (||)
+  bimul = (&&)
+
+instance BiNum Int Int where 
+  type BNTF Int Int = Int
+  biadd = (+)
+  bimul = (*)
+
+instance BiNum Float Float where
+  type BNTF Float Float = Float
+  biadd = (+)
+  bimul = (*)
+
+  -- XXX More
+
+------------------------------------------------------------------------}}}
+-- Values and Expressions
+------------------------------------------------------------------------{{{
+
+class K3 (r :: * -> *) where
+    -- | A representation-specific constraint for collections, on functions
+    -- which need to dispatch on a type-tag in the output.
+  type K3AST_Coll_C r (c :: CKind) :: Constraint
+
+    -- | A representation-specific constraint on handling patterns, on any
+    -- function which uses patterns.
+  type K3AST_Pat_C r (w :: PKind) :: Constraint
+
+    -- | A representation-specific constraint for slices, on eSlice.
+  type K3AST_Slice_C r (w :: SKind) :: Constraint
+
+    -- | Add a comment to some part of the AST
+  cComment  :: String -> r a -> r a
+    -- | Add some annotations to some part of the AST
+  cAnn      :: Ann -> r a -> r a
+
+    -- XXX An escape hatch
+  cUnk      :: r a 
+
+    -- XXX cAddress  :: AddrIx -> r AddrIx
+  cBool     :: Bool -> r Bool
+  cByte     :: Word8 -> r Word8
+  cFloat    :: Float -> r Float
+  cInt      :: Int -> r Int
+  cNothing  :: r (Maybe a)
+  cString   :: String -> r String
+  cUnit     :: r ()
+
+    -- XXX polymorphic type because the expression might be
+    -- well-formed; we'll have to resolve it later.
+  eVar      :: VarIx -> r a
+
+  ePair     :: r a -> r b -> r (a,b)
+  eJust     :: r a -> r (Maybe t)
+
+  eEmpty    :: (K3AST_Coll_C r c) => r (CTE c e)
+  eSing     :: (K3AST_Coll_C r c) => r e -> r (CTE c e)
+  eComb     :: r (CTE c e) -> r (CTE c e) -> r (CTE c e)
+  eRange    :: r Int -> r Int -> r Int -> r (CTE c Int)
+
+  eAdd      :: (BiNum a b) => r a -> r b -> r (BNTF a b)
+  eMul      :: (BiNum a b) => r a -> r b -> r (BNTF a b)
+  eNeg      :: (UnNum a)   => r a -> r a 
+
+    -- XXX Constraints?
+  eEq       :: r a -> r a -> r Bool
+  eLt       :: r a -> r a -> r Bool
+  eLeq      :: r a -> r a -> r Bool
+  eNeq      :: r a -> r a -> r Bool
+
+    -- Unlike traditional lambdas, we require a witness
+    -- that the argument is admissible in K3.
+  eLam      :: (K3AST_Pat_C r w, Pat w)
+            => PatDa w -> (PatReprFn w r -> r b) -> r (PatTy w -> b)
+  eApp      :: r (a -> b) -> r a -> r b
+
+  eBlock    :: [r ()] -> r a -> r a
+
+  eIter     :: r (t -> ()) -> r (CTE c t) -> r ()
+
+  eITE      :: r Bool -> r a -> r a -> r a
+
+  eMap      :: r (t -> t') -> r (CTE c t) -> r (CTE c t')
+  eFiltMap  :: r (t -> Bool) -> r (t -> t') -> r (CTE c t) -> r (CTE c t')
+
+  eFlatten  :: r (CTE c (CTE c' t)) -> r (CTE c' t)
+
+    -- | Called Aggregate in K3's AST
+  eFold     :: r ((t', t) -> t') -> r t' -> r (CTE c t) -> r t'
+  eGBA      :: r (t -> t'') -> r ((t',t) -> t') -> r t' -> r (CTE c t) -> r (CTE c (t'',t'))
+
+  eSort     :: r (CTE c t) -> r ((t,t) -> Bool) -> r (CTE 'CList t)
+
+  ePeek     :: r (CTE c e) -> r e
+
+    -- | Slice out from a collection; the slice's type and
+    -- the type of elements of the collection must match.
+    --
+    -- Rather like lambdas, except that the witness is also
+    -- a mandatory part of the definition of "slice" :)
+  eSlice    :: (K3AST_Slice_C r w, Slice w, SliceTy w ~ t)
+            => SliceDa w -> r (CTE c t) -> r (CTE c t)
+
+  eInsert   :: r (CTE c t) -> r t -> r ()
+  eDelete   :: r (CTE c t) -> r t -> r ()
+  eUpdate   :: r (CTE c t) -> r t -> r t -> r ()
+
+  -- XXX eAssign
+  -- XXX eDeref
+  -- XXX eSend
+
+------------------------------------------------------------------------}}}
+-- Miscellanious
+------------------------------------------------------------------------{{{
+
+  -- XXX does not enumerate local variables
+data Decl tr r t = Decl VarIx (tr t) (Maybe (r t))
+
+  -- | A convenience function for setting the type of a collection.
+  --
+  -- Use as (eEmpty `asColl` CTSet)
+asColl :: r (CTE c t) -> CollTy c -> r (CTE c t)
+asColl = const
+
+------------------------------------------------------------------------}}}
+-- fin
+---------------------------------------------------------------------------
diff --git a/src/Dyna/BackendK3/Examples.hs b/src/Dyna/BackendK3/Examples.hs
new file mode 100644 (file)
index 0000000..209cc0f
--- /dev/null
@@ -0,0 +1,68 @@
+---------------------------------------------------------------------------
+-- Header material
+------------------------------------------------------------------------{{{
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE ExistentialQuantification #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+
+
+module Dyna.BackendK3.Examples where
+
+import           Dyna.BackendK3.AST
+import           Dyna.BackendK3.Render
+
+------------------------------------------------------------------------}}}
+-- Example cases
+------------------------------------------------------------------------{{{
+
+macro_caseMaybe :: (K3 r, K3AST_Pat_C r (PKJust (PKVar a)))
+                => ExTyRepr a
+                -> r (Maybe a)
+                -> r b
+                -> (r a -> r b)
+                -> r b
+macro_caseMaybe w m n b = eITE (eEq m cNothing)
+                                n
+                                (eApp (eLam (PJust (PVar w)) b) m)
+
+test_macroCM = Decl (Var "nocase")
+                    (tInt)
+                    $Just $ macro_caseMaybe tInt (eVar (Var "test")) (cInt 0) (id)
+
+testdecf = Decl (Var "f")
+                (tColl CTBag (tPair tInt tInt))
+                Nothing
+
+testmfn = Decl (Var "negAddOne")
+               (tFun tInt tInt)
+               $Just (eLam (PVar $ ETR tInt) (\a -> eNeg $ eAdd a $ cInt 1))
+
+booli = Decl (Var "booli")
+             (tFun tBool tInt)
+             $ Just (eLam (PVar (ETR tBool)) (\b -> eITE b (cInt 1) (cInt 0)))
+
+testcfn = Decl (Var "cfn")
+               (tFun tInt $ tColl CTSet tInt)
+               $Just (eLam (PVar tInt) (\x -> eSing x))
+
+
+testpairfn = Decl (Var "ibfst")
+                  (tFun (tPair tInt tBool) tInt)
+                  $Just (eLam (PPair (PVar tInt) (PVar tBool)) (\(a,b) -> a))
+
+exslice =  eSlice (SPair (SVar (Var "x") tInt)
+                         (SVar (Var "y") tInt))
+                  (eSing (ePair (cInt 3) (cInt 4)) `asColl` CTSet)
+
+------------------------------------------------------------------------}}}
+-- fin
+---------------------------------------------------------------------------
diff --git a/src/Dyna/BackendK3/Render.hs b/src/Dyna/BackendK3/Render.hs
new file mode 100644 (file)
index 0000000..e6ea815
--- /dev/null
@@ -0,0 +1,226 @@
+---------------------------------------------------------------------------
+-- Header material
+------------------------------------------------------------------------{{{
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+
+    -- | Provides the "AsK3" type and instances for the K3 AST.
+module Dyna.BackendK3.Render where
+
+import           Text.PrettyPrint.Free
+
+import           Dyna.BackendK3.AST
+
+
+------------------------------------------------------------------------}}}
+-- Type handling
+------------------------------------------------------------------------{{{
+
+    -- | Unlike AsK3 below, we don't need to thread a variable counter
+    --   around since K3 doesn't have tyvars
+newtype AsK3Ty e (a :: *) = AsK3Ty { unAsK3Ty :: Doc e }
+
+instance K3Ty (AsK3Ty e) where
+  tAnn (Ann anns) (AsK3Ty e) = AsK3Ty$ 
+       parens e <> " @ "
+    <> (encloseSep lbrace rbrace comma $ map text anns)
+
+  tBool   = AsK3Ty$ "bool"
+  tByte   = AsK3Ty$ "byte"
+  tFloat  = AsK3Ty$ "float"
+  tInt    = AsK3Ty$ "int"
+  tString = AsK3Ty$ "string"
+  tUnit   = AsK3Ty$ "unit"
+  tUnk    = AsK3Ty$ "_"
+
+  tPair (AsK3Ty ta) (AsK3Ty tb) = AsK3Ty$ tupled [ ta, tb ]
+
+  tMaybe (AsK3Ty ta) = AsK3Ty$ "Maybe " <> ta
+
+  tColl CTSet  (AsK3Ty ta) = AsK3Ty$ braces   ta
+  tColl CTBag  (AsK3Ty ta) = AsK3Ty$ encBag   ta
+  tColl CTList (AsK3Ty ta) = AsK3Ty$ brackets ta
+
+  tFun (AsK3Ty ta) (AsK3Ty tb) = AsK3Ty$ ta <> " -> " <> tb
+
+------------------------------------------------------------------------}}}
+-- Collection handling
+------------------------------------------------------------------------{{{
+
+class K3CFn (c :: CKind) where
+  k3cfn_empty :: AsK3 e (CTE c a)
+  k3cfn_sing  :: AsK3 e vma -> AsK3 e (CTE c vma)
+
+instance K3CFn CSet where
+  k3cfn_empty = AsK3$const$ "{ }"
+  k3cfn_sing (AsK3 e) = AsK3$ braces . e
+
+instance K3CFn CList where
+  k3cfn_empty = AsK3$const$ "[ ]"
+  k3cfn_sing (AsK3 e) = AsK3$ brackets . e
+
+instance K3CFn CBag where
+  k3cfn_empty = AsK3$const$ "{| |}"
+  k3cfn_sing (AsK3 e) = AsK3$ encBag . e
+
+------------------------------------------------------------------------}}}
+-- Pattern handling
+------------------------------------------------------------------------{{{
+
+class (Pat w) => K3PFn w where
+  k3pfn :: Int -> PatDa w -> (Int, Doc e, PatReprFn w (AsK3 e))
+
+instance K3PFn (PKVar (a :: *)) where
+  k3pfn n (PVar tr) = let sn = text $ "x" ++ show n in
+                      (n+1
+                      ,sn <> colon <> unAsK3Ty (unETR tr)
+                      ,AsK3$const$ sn)
+
+instance (K3PFn w) => K3PFn (PKJust w) where
+  k3pfn n (PJust w) = let (n', b, r) = k3pfn n w
+                      in (n', "Just " <> parens b, r)
+
+instance (K3PFn wa, K3PFn wb) => K3PFn (PKPair wa wb) where
+  k3pfn n (PPair wa wb) =
+    let (n', ba, ra) = k3pfn n wa
+        (n'', bb, rb) = k3pfn n' wb
+    in (n'', tupled [ ba, bb ], (ra,rb))
+
+------------------------------------------------------------------------}}}
+-- Slice handling
+------------------------------------------------------------------------{{{
+
+class (Slice w) => K3SFn w where
+  k3sfn :: SliceDa w -> Doc e
+
+instance K3SFn (SKVar (a :: *)) where
+  k3sfn (SVar (Var v) _) = text v
+
+instance (K3SFn s) => K3SFn (SKJust s) where
+  k3sfn (SJust s) = "Just" <> parens (k3sfn s)
+
+instance (K3SFn sa, K3SFn sb) => K3SFn (SKPair sa sb) where
+  k3sfn (SPair sa sb) = tupled [ k3sfn sa, k3sfn sb ]
+
+------------------------------------------------------------------------}}}
+-- Expression handling
+------------------------------------------------------------------------{{{
+
+newtype AsK3 e (a :: *) = AsK3 { unAsK3 :: Int -> Doc e }
+
+instance K3 (AsK3 e) where
+  type K3AST_Coll_C (AsK3 e) c = K3CFn c
+  type K3AST_Pat_C (AsK3 e) p = K3PFn p
+  type K3AST_Slice_C (AsK3 e) s = K3SFn s
+
+  cAnn (Ann anns) (AsK3 e) = AsK3$ \n ->
+       parens (e n) <> " @ "
+    <> (encloseSep lbrace rbrace comma $ map text anns)
+
+  cComment str (AsK3 a) = AsK3$ \n -> "\n// " <> text str <> "\n" <> a n
+
+  cBool   n     = AsK3$const$ text$ show n
+  cByte   n     = AsK3$const$ text$ show n
+  cFloat  n     = AsK3$const$ text$ show n
+  cInt    n     = AsK3$const$ text$ show n
+  cString n     = AsK3$const$ text$ show n
+  cNothing      = AsK3$const$ "nothing"
+  cUnit         = AsK3$const$ "unit"
+  cUnk          = AsK3$const$ "_"
+
+  eVar (Var v) = AsK3$const$text v
+
+
+  ePair (AsK3 a) (AsK3 b) = AsK3$ \n -> tupled [a n, b n]
+  eJust (AsK3 a)          = builtin "Just " [ a ]
+
+  eEmpty = k3cfn_empty
+  eSing  = k3cfn_sing
+  eComb (AsK3 a) (AsK3 b) = AsK3$ \n -> parens (a n) <> " ++ " <> parens (b n)
+  eRange (AsK3 f) (AsK3 l) (AsK3 s) = builtin "range" [ f, l, s ]
+  
+  eAdd (AsK3 a) (AsK3 b) = AsK3$ \n -> a n <> "+" <> b n
+  eMul (AsK3 a) (AsK3 b) = AsK3$ \n -> a n <> "*" <> b n
+  eNeg (AsK3 b) = AsK3$ \n -> "-" <> parens (b n)
+
+  eEq  = binop "=="
+  eLt  = binop "<"
+  eLeq = binop "<="
+  eNeq = binop "!="
+
+  eLam w f = AsK3$ \n -> let (n', pat, arg) = k3pfn n w
+                         in "\\" <> pat <> " -> " <> (unAsK3 (f arg) n')
+
+  eApp (AsK3 f) (AsK3 x) = AsK3$ \n ->
+    parens (parens (f n) <> space <> parens (x n))
+
+  eBlock ss (AsK3 r) = AsK3$ \n -> 
+    "do" <> (semiBraces (map ($ n) ((map unAsK3 ss) ++ [r])))
+
+  eIter (AsK3 f) (AsK3 c) = builtin "iterate" [ f, c ]
+
+  eITE (AsK3 b) (AsK3 t) (AsK3 e) = AsK3$ \n ->    "if "     <> parens (b n)
+                                                <> " then "  <> parens (t n)
+                                                <> " else "  <> parens (e n)
+
+  eMap     (AsK3 f) (AsK3 c)                   = builtin "map"       [ f, c    ]
+  eFiltMap (AsK3 f) (AsK3 m) (AsK3 c)          = builtin "filtermap" [ f, m, c ]
+  eFlatten (AsK3 c)                            = builtin "flatten"   [ c ]
+  eFold    (AsK3 f) (AsK3 z) (AsK3 c)          = builtin "fold"      [ f, z, c ]
+  eGBA     (AsK3 p) (AsK3 f) (AsK3 z) (AsK3 c) = builtin "groupby"   [ p, f, z, c ]
+  eSort    (AsK3 c) (AsK3 f)                   = builtin "sort"      [ c, f ]
+  ePeek    (AsK3 c)                            = builtin "peek"      [ c ]
+
+  eSlice w (AsK3 c) = AsK3$ \n -> c n <> brackets (k3sfn w)
+
+  eInsert (AsK3 c) (AsK3 e)          = builtin "insert" [ c, e ]
+  eDelete (AsK3 c) (AsK3 e)          = builtin "delete" [ c, e ]
+  eUpdate (AsK3 c) (AsK3 o) (AsK3 n) = builtin "update" [ c, o, n ]
+
+------------------------------------------------------------------------}}}
+-- Miscellany
+------------------------------------------------------------------------{{{
+
+encBag :: Doc e -> Doc e
+encBag = enclose "{|" "|}"
+
+    -- Overly polymorphic; use only when correct
+binop :: Doc e -> AsK3 e a -> AsK3 e a -> AsK3 e b
+binop o (AsK3 a) (AsK3 b) = AsK3$ \n -> parens (a n) <> o <> parens (b n)
+
+    -- Overly polymorphic; use only when correct
+builtin :: Doc e -> [ Int -> Doc e ] -> AsK3 e b
+builtin fn as = AsK3$ \n -> fn <> tupled (map ($ n) as)
+
+instance Show (AsK3 e a) where
+  show (AsK3 f) = show $ f 0
+
+sh :: AsK3 e a -> String
+sh = show
+
+instance Show (AsK3Ty e a) where
+  show (AsK3Ty f) = show f
+
+sht :: AsK3Ty e a -> String
+sht = show
+
+shd :: Decl (AsK3Ty e) (AsK3 e) t -> Doc e
+shd (Decl (Var name) tipe body) =
+     "declare "
+  <> text name
+  <> space <> colon <> space
+  <> unAsK3Ty tipe
+  <> case body of
+       Nothing -> empty
+       Just b  -> space <> equals <> space <> unAsK3 b 0
+  <> semi
+
+------------------------------------------------------------------------}}}
+-- fin
+---------------------------------------------------------------------------