packages feed

kempe 0.1.0.2 → 0.1.1.0

raw patch · 64 files changed

+773/−190 lines, 64 filesdep ~basedep ~composition-preludePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, composition-prelude

API changes (from Hackage documentation)

- Kempe.AST: type Module a c b = [KempeDecl a c b]
- Kempe.File: parsedFp :: FilePath -> IO (Int, Module AlexPosn AlexPosn AlexPosn)
+ Data.Foldable.Ext: foldMapA :: (Applicative f, Traversable t, Monoid m) => (a -> f m) -> t a -> f m
+ Data.Foldable.Ext: foldMapAlternative :: (Traversable t, Alternative f) => (a -> f b) -> t a -> f b
+ Kempe.AST: Module :: [ByteString] -> [KempeDecl a c b] -> Module a c b
+ Kempe.AST: [body] :: Module a c b -> [KempeDecl a c b]
+ Kempe.AST: [importFps] :: Module a c b -> [ByteString]
+ Kempe.AST: cSize :: Size -> Int64
+ Kempe.AST: data Module a c b
+ Kempe.AST: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData b, Control.DeepSeq.NFData c) => Control.DeepSeq.NFData (Kempe.AST.Module a c b)
+ Kempe.AST: instance GHC.Generics.Generic (Kempe.AST.Module a c b)
+ Kempe.AST: size' :: SizeEnv -> KempeTy a -> Int64
+ Kempe.AST: type Declarations a c b = [KempeDecl a c b]
+ Kempe.AST: type Size = [Int64] -> Int64
+ Kempe.Asm.X86.Type: AH :: X86Reg
+ Kempe.Asm.X86.Type: AL :: X86Reg
+ Kempe.Asm.X86.Type: AddAC :: a -> Addr reg -> Int64 -> X86 reg a
+ Kempe.Asm.X86.Type: AddRC :: a -> reg -> Int64 -> X86 reg a
+ Kempe.Asm.X86.Type: AddRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: AddrRCMinus :: reg -> Int64 -> Addr reg
+ Kempe.Asm.X86.Type: AddrRCPlus :: reg -> Int64 -> Addr reg
+ Kempe.Asm.X86.Type: AddrRRPlus :: reg -> reg -> Addr reg
+ Kempe.Asm.X86.Type: AddrRRScale :: reg -> reg -> Int64 -> Addr reg
+ Kempe.Asm.X86.Type: AllocReg64 :: !Int -> AbsReg
+ Kempe.Asm.X86.Type: AllocReg8 :: !Int -> AbsReg
+ Kempe.Asm.X86.Type: AndRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: BSLabel :: a -> ByteString -> X86 reg a
+ Kempe.Asm.X86.Type: CArg1 :: AbsReg
+ Kempe.Asm.X86.Type: CArg2 :: AbsReg
+ Kempe.Asm.X86.Type: CArg3 :: AbsReg
+ Kempe.Asm.X86.Type: CArg4 :: AbsReg
+ Kempe.Asm.X86.Type: CArg5 :: AbsReg
+ Kempe.Asm.X86.Type: CArg6 :: AbsReg
+ Kempe.Asm.X86.Type: CH :: X86Reg
+ Kempe.Asm.X86.Type: CL :: X86Reg
+ Kempe.Asm.X86.Type: CRet :: AbsReg
+ Kempe.Asm.X86.Type: Call :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: CallBS :: a -> ByteString -> X86 reg a
+ Kempe.Asm.X86.Type: CmpAddrBool :: a -> Addr reg -> Word8 -> X86 reg a
+ Kempe.Asm.X86.Type: CmpAddrReg :: a -> Addr reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: CmpRegBool :: a -> reg -> Word8 -> X86 reg a
+ Kempe.Asm.X86.Type: CmpRegReg :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: ControlAnn :: !Int -> [Int] -> Set AbsReg -> Set AbsReg -> ControlAnn
+ Kempe.Asm.X86.Type: Cqo :: a -> X86 reg a
+ Kempe.Asm.X86.Type: DH :: X86Reg
+ Kempe.Asm.X86.Type: DL :: X86Reg
+ Kempe.Asm.X86.Type: DataPointer :: AbsReg
+ Kempe.Asm.X86.Type: Dil :: X86Reg
+ Kempe.Asm.X86.Type: DivR :: a -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: IdivR :: a -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: ImulRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: Je :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Jg :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Jge :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Jl :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Jle :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Jne :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Jump :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Label :: a -> Label -> X86 reg a
+ Kempe.Asm.X86.Type: Liveness :: !Set AbsReg -> !Set AbsReg -> Liveness
+ Kempe.Asm.X86.Type: MovABool :: a -> Addr reg -> Word8 -> X86 reg a
+ Kempe.Asm.X86.Type: MovAC :: a -> Addr reg -> Int64 -> X86 reg a
+ Kempe.Asm.X86.Type: MovACTag :: a -> Addr reg -> Word8 -> X86 reg a
+ Kempe.Asm.X86.Type: MovACi8 :: a -> Addr reg -> Int8 -> X86 reg a
+ Kempe.Asm.X86.Type: MovAR :: a -> Addr reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: MovRA :: a -> reg -> Addr reg -> X86 reg a
+ Kempe.Asm.X86.Type: MovRC :: a -> reg -> Int64 -> X86 reg a
+ Kempe.Asm.X86.Type: MovRCBool :: a -> reg -> Word8 -> X86 reg a
+ Kempe.Asm.X86.Type: MovRCTag :: a -> reg -> Word8 -> X86 reg a
+ Kempe.Asm.X86.Type: MovRCi8 :: a -> reg -> Int8 -> X86 reg a
+ Kempe.Asm.X86.Type: MovRL :: a -> reg -> ByteString -> X86 reg a
+ Kempe.Asm.X86.Type: MovRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: MovRWord :: a -> reg -> Word -> X86 reg a
+ Kempe.Asm.X86.Type: NasmMacro0 :: a -> ByteString -> X86 reg a
+ Kempe.Asm.X86.Type: NegR :: a -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: OrRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: PopMem :: a -> Addr reg -> X86 reg a
+ Kempe.Asm.X86.Type: PopReg :: a -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: PopcountRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: PushConst :: a -> Int64 -> X86 reg a
+ Kempe.Asm.X86.Type: PushMem :: a -> Addr reg -> X86 reg a
+ Kempe.Asm.X86.Type: PushReg :: a -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: QuotRes :: AbsReg
+ Kempe.Asm.X86.Type: R10 :: X86Reg
+ Kempe.Asm.X86.Type: R10b :: X86Reg
+ Kempe.Asm.X86.Type: R11 :: X86Reg
+ Kempe.Asm.X86.Type: R11b :: X86Reg
+ Kempe.Asm.X86.Type: R12 :: X86Reg
+ Kempe.Asm.X86.Type: R12b :: X86Reg
+ Kempe.Asm.X86.Type: R13 :: X86Reg
+ Kempe.Asm.X86.Type: R13b :: X86Reg
+ Kempe.Asm.X86.Type: R14 :: X86Reg
+ Kempe.Asm.X86.Type: R14b :: X86Reg
+ Kempe.Asm.X86.Type: R15 :: X86Reg
+ Kempe.Asm.X86.Type: R15b :: X86Reg
+ Kempe.Asm.X86.Type: R8 :: X86Reg
+ Kempe.Asm.X86.Type: R8b :: X86Reg
+ Kempe.Asm.X86.Type: R9 :: X86Reg
+ Kempe.Asm.X86.Type: R9b :: X86Reg
+ Kempe.Asm.X86.Type: Rax :: X86Reg
+ Kempe.Asm.X86.Type: Rbp :: X86Reg
+ Kempe.Asm.X86.Type: Rbx :: X86Reg
+ Kempe.Asm.X86.Type: Rcx :: X86Reg
+ Kempe.Asm.X86.Type: Rdi :: X86Reg
+ Kempe.Asm.X86.Type: Rdx :: X86Reg
+ Kempe.Asm.X86.Type: Reg :: reg -> Addr reg
+ Kempe.Asm.X86.Type: RemRes :: AbsReg
+ Kempe.Asm.X86.Type: Ret :: a -> X86 reg a
+ Kempe.Asm.X86.Type: Rsi :: X86Reg
+ Kempe.Asm.X86.Type: Rsp :: X86Reg
+ Kempe.Asm.X86.Type: ShiftExponent :: AbsReg
+ Kempe.Asm.X86.Type: ShiftLRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: ShiftRRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: Sil :: X86Reg
+ Kempe.Asm.X86.Type: SubRC :: a -> reg -> Int64 -> X86 reg a
+ Kempe.Asm.X86.Type: SubRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: XorRR :: a -> reg -> reg -> X86 reg a
+ Kempe.Asm.X86.Type: [addrAdd1] :: X86 reg a -> Addr reg
+ Kempe.Asm.X86.Type: [addrCmp] :: X86 reg a -> Addr reg
+ Kempe.Asm.X86.Type: [addrDest] :: X86 reg a -> Addr reg
+ Kempe.Asm.X86.Type: [addrSrc] :: X86 reg a -> Addr reg
+ Kempe.Asm.X86.Type: [addr] :: X86 reg a -> Addr reg
+ Kempe.Asm.X86.Type: [ann] :: X86 reg a -> a
+ Kempe.Asm.X86.Type: [bCmp] :: X86 reg a -> Word8
+ Kempe.Asm.X86.Type: [boolSrc] :: X86 reg a -> Word8
+ Kempe.Asm.X86.Type: [bsLabel] :: X86 reg a -> ByteString
+ Kempe.Asm.X86.Type: [bslLabel] :: X86 reg a -> ByteString
+ Kempe.Asm.X86.Type: [conn] :: ControlAnn -> [Int]
+ Kempe.Asm.X86.Type: [defsNode] :: ControlAnn -> Set AbsReg
+ Kempe.Asm.X86.Type: [i8Src] :: X86 reg a -> Int8
+ Kempe.Asm.X86.Type: [iAdd2] :: X86 reg a -> Int64
+ Kempe.Asm.X86.Type: [iSrc] :: X86 reg a -> Int64
+ Kempe.Asm.X86.Type: [iSub2] :: X86 reg a -> Int64
+ Kempe.Asm.X86.Type: [ins] :: Liveness -> !Set AbsReg
+ Kempe.Asm.X86.Type: [jLabel] :: X86 reg a -> Label
+ Kempe.Asm.X86.Type: [label] :: X86 reg a -> Label
+ Kempe.Asm.X86.Type: [macroName] :: X86 reg a -> ByteString
+ Kempe.Asm.X86.Type: [node] :: ControlAnn -> !Int
+ Kempe.Asm.X86.Type: [out] :: Liveness -> !Set AbsReg
+ Kempe.Asm.X86.Type: [rAdd1] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rAdd2] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rCmp'] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rCmp] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rDest] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rDiv] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rMul1] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rMul2] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rSrc] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rSub1] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rSub2] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rXor1] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [rXor2] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [reg] :: X86 reg a -> reg
+ Kempe.Asm.X86.Type: [tagSrc] :: X86 reg a -> Word8
+ Kempe.Asm.X86.Type: [usesNode] :: ControlAnn -> Set AbsReg
+ Kempe.Asm.X86.Type: [wSrc] :: X86 reg a -> Word
+ Kempe.Asm.X86.Type: data AbsReg
+ Kempe.Asm.X86.Type: data Addr reg
+ Kempe.Asm.X86.Type: data ControlAnn
+ Kempe.Asm.X86.Type: data Liveness
+ Kempe.Asm.X86.Type: data X86 reg a
+ Kempe.Asm.X86.Type: data X86Reg
+ Kempe.Asm.X86.Type: instance (Control.DeepSeq.NFData a, Control.DeepSeq.NFData reg) => Control.DeepSeq.NFData (Kempe.Asm.X86.Type.X86 reg a)
+ Kempe.Asm.X86.Type: instance Control.DeepSeq.NFData Kempe.Asm.X86.Type.AbsReg
+ Kempe.Asm.X86.Type: instance Control.DeepSeq.NFData Kempe.Asm.X86.Type.ControlAnn
+ Kempe.Asm.X86.Type: instance Control.DeepSeq.NFData Kempe.Asm.X86.Type.Liveness
+ Kempe.Asm.X86.Type: instance Control.DeepSeq.NFData Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance Control.DeepSeq.NFData reg => Control.DeepSeq.NFData (Kempe.Asm.X86.Type.Addr reg)
+ Kempe.Asm.X86.Type: instance GHC.Base.Functor (Kempe.Asm.X86.Type.X86 reg)
+ Kempe.Asm.X86.Type: instance GHC.Classes.Eq Kempe.Asm.X86.Type.AbsReg
+ Kempe.Asm.X86.Type: instance GHC.Classes.Eq Kempe.Asm.X86.Type.Liveness
+ Kempe.Asm.X86.Type: instance GHC.Classes.Eq Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance GHC.Classes.Ord Kempe.Asm.X86.Type.AbsReg
+ Kempe.Asm.X86.Type: instance GHC.Classes.Ord Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance GHC.Enum.Bounded Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance GHC.Enum.Enum Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance GHC.Generics.Generic (Kempe.Asm.X86.Type.Addr reg)
+ Kempe.Asm.X86.Type: instance GHC.Generics.Generic (Kempe.Asm.X86.Type.X86 reg a)
+ Kempe.Asm.X86.Type: instance GHC.Generics.Generic Kempe.Asm.X86.Type.AbsReg
+ Kempe.Asm.X86.Type: instance GHC.Generics.Generic Kempe.Asm.X86.Type.ControlAnn
+ Kempe.Asm.X86.Type: instance GHC.Generics.Generic Kempe.Asm.X86.Type.Liveness
+ Kempe.Asm.X86.Type: instance GHC.Generics.Generic Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance Prettyprinter.Internal.Pretty Kempe.Asm.X86.Type.AbsReg
+ Kempe.Asm.X86.Type: instance Prettyprinter.Internal.Pretty Kempe.Asm.X86.Type.Liveness
+ Kempe.Asm.X86.Type: instance Prettyprinter.Internal.Pretty Kempe.Asm.X86.Type.X86Reg
+ Kempe.Asm.X86.Type: instance Prettyprinter.Internal.Pretty reg => Prettyprinter.Internal.Pretty (Kempe.Asm.X86.Type.Addr reg)
+ Kempe.Asm.X86.Type: instance Prettyprinter.Internal.Pretty reg => Prettyprinter.Internal.Pretty (Kempe.Asm.X86.Type.X86 reg a)
+ Kempe.Asm.X86.Type: prettyAsm :: Pretty reg => [X86 reg a] -> Doc ann
+ Kempe.Asm.X86.Type: prettyDebugAsm :: Pretty reg => [X86 reg Liveness] -> Doc ann
+ Kempe.Asm.X86.Type: type Label = Word
+ Kempe.Check.Restrict: restrictConstructors :: Declarations a c b -> Maybe (Error a)
+ Kempe.Check.TopLevel: data Warning a
+ Kempe.Check.TopLevel: instance (Prettyprinter.Internal.Pretty a, Data.Typeable.Internal.Typeable a) => GHC.Exception.Type.Exception (Kempe.Check.TopLevel.Warning a)
+ Kempe.Check.TopLevel: instance Prettyprinter.Internal.Pretty a => GHC.Show.Show (Kempe.Check.TopLevel.Warning a)
+ Kempe.Check.TopLevel: instance Prettyprinter.Internal.Pretty a => Prettyprinter.Internal.Pretty (Kempe.Check.TopLevel.Warning a)
+ Kempe.Check.TopLevel: topLevelCheck :: Declarations a c a -> Maybe (Warning a)
+ Kempe.Error: BadType :: a -> Error a
+ Kempe.Error: FatSumType :: a -> TyName a -> Error a
+ Kempe.Error: IllKinded :: a -> KempeTy a -> Error a
+ Kempe.Error: InexhaustiveMatch :: a -> Error a
+ Kempe.Error: InvalidCExport :: a -> Name a -> Error a
+ Kempe.Error: InvalidCImport :: a -> Name a -> Error a
+ Kempe.Error: LessGeneral :: a -> StackType a -> StackType a -> Error a
+ Kempe.Error: MismatchedLengths :: a -> StackType a -> StackType a -> Error a
+ Kempe.Error: MonoFailed :: a -> Error a
+ Kempe.Error: PoorScope :: a -> Name a -> Error a
+ Kempe.Error: TyVarExt :: a -> Name a -> Error a
+ Kempe.Error: UnificationFailed :: a -> KempeTy a -> KempeTy a -> Error a
+ Kempe.Error: data Error a
+ Kempe.Error: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Kempe.Error.Error a)
+ Kempe.Error: instance Data.Typeable.Internal.Typeable a => GHC.Exception.Type.Exception (Kempe.Error.Error a)
+ Kempe.Error: instance GHC.Generics.Generic (Kempe.Error.Error a)
+ Kempe.Error: instance GHC.Show.Show (Kempe.Error.Error a)
+ Kempe.Error: instance Prettyprinter.Internal.Pretty (Kempe.Error.Error a)
+ Kempe.Error: mErr :: Maybe (Error ()) -> Either (Error ()) ()
+ Kempe.File: dumpIR :: Typeable a => Int -> Declarations a c b -> Doc ann
+ Kempe.File: warnFile :: FilePath -> IO (Maybe (Warning AlexPosn))
+ Kempe.Lexer: TokModuleStr :: a -> ByteString -> Token a
+ Kempe.Lexer: [moduleFp] :: Token a -> ByteString
+ Kempe.Lexer: alexInitUserState :: AlexUserState
+ Kempe.Lexer: instance GHC.Classes.Ord Kempe.Lexer.AlexPosn
+ Kempe.Lexer: withAlexSt :: ByteString -> AlexUserState -> Alex a -> Either String (AlexUserState, a)
+ Kempe.Module: parseProcess :: FilePath -> IO (Int, Declarations AlexPosn AlexPosn AlexPosn)
+ Kempe.Name: Name :: Text -> !Unique -> a -> Name a
+ Kempe.Name: [loc] :: Name a -> a
+ Kempe.Name: [name] :: Name a -> Text
+ Kempe.Name: [unique] :: Name a -> !Unique
+ Kempe.Name: data Name a
+ Kempe.Name: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Kempe.Name.Name a)
+ Kempe.Name: instance Data.Foldable.Foldable Kempe.Name.Name
+ Kempe.Name: instance Data.Traversable.Traversable Kempe.Name.Name
+ Kempe.Name: instance GHC.Base.Functor Kempe.Name.Name
+ Kempe.Name: instance GHC.Classes.Eq (Kempe.Name.Name a)
+ Kempe.Name: instance GHC.Classes.Ord (Kempe.Name.Name a)
+ Kempe.Name: instance Prettyprinter.Internal.Pretty (Kempe.Name.Name a)
+ Kempe.Name: type TyName = Name
+ Kempe.Parser: parseWithCtx :: ByteString -> AlexUserState -> Either (ParseError AlexPosn) (AlexUserState, Module AlexPosn AlexPosn AlexPosn)
+ Kempe.Parser: parseWithInitCtx :: ByteString -> Either (ParseError AlexPosn) (AlexUserState, Module AlexPosn AlexPosn AlexPosn)
+ Kempe.Proc.Nasm: writeO :: Doc ann -> FilePath -> Bool -> IO ()
+ Kempe.Unique: Unique :: Int -> Unique
+ Kempe.Unique: [unUnique] :: Unique -> Int
+ Kempe.Unique: instance GHC.Classes.Eq Kempe.Unique.Unique
+ Kempe.Unique: instance GHC.Classes.Ord Kempe.Unique.Unique
+ Kempe.Unique: instance Prettyprinter.Internal.Pretty Kempe.Unique.Unique
+ Kempe.Unique: newtype Unique
+ Prettyprinter.Ext: (<##>) :: Doc a -> Doc a -> Doc a
+ Prettyprinter.Ext: (<#>) :: Doc a -> Doc a -> Doc a
+ Prettyprinter.Ext: infixr 6 <##>
+ Prettyprinter.Ext: prettyHex :: (Integral a, Show a) => a -> Doc ann
+ Prettyprinter.Ext: prettyLines :: [Doc ann] -> Doc ann
+ Prettyprinter.Ext: sepDecls :: [Doc ann] -> Doc ann
- Kempe.AST: prettyFancyModule :: Module () (ConsAnn (StackType ())) (StackType ()) -> Doc ann
+ Kempe.AST: prettyFancyModule :: Declarations () (ConsAnn (StackType ())) (StackType ()) -> Doc ann
- Kempe.AST: prettyTypedModule :: Module () (StackType ()) (StackType ()) -> Doc ann
+ Kempe.AST: prettyTypedModule :: Declarations () (StackType ()) (StackType ()) -> Doc ann
- Kempe.AST: size :: SizeEnv -> KempeTy a -> Int64
+ Kempe.AST: size :: SizeEnv -> KempeTy a -> Size
- Kempe.AST: type SizeEnv = IntMap Int64
+ Kempe.AST: type SizeEnv = IntMap Size
- Kempe.Check.Pattern: checkModuleExhaustive :: Module a c b -> Maybe (Error b)
+ Kempe.Check.Pattern: checkModuleExhaustive :: Declarations a c b -> Maybe (Error b)
- Kempe.File: dumpX86 :: Int -> Module a c b -> Doc ann
+ Kempe.File: dumpX86 :: Typeable a => Int -> Declarations a c b -> Doc ann
- Kempe.IR: size :: SizeEnv -> KempeTy a -> Int64
+ Kempe.IR: size :: SizeEnv -> KempeTy a -> Size
- Kempe.IR: writeModule :: SizeEnv -> Module () (ConsAnn MonoStackType) MonoStackType -> TempM [Stmt]
+ Kempe.IR: writeModule :: SizeEnv -> Declarations () (ConsAnn MonoStackType) MonoStackType -> TempM [Stmt]
- Kempe.Inline: inline :: Module a c b -> Module a c b
+ Kempe.Inline: inline :: Declarations a c b -> Declarations a c b
- Kempe.Monomorphize: closedModule :: Module () (StackType ()) (StackType ()) -> MonoM (Module () (StackType ()) (StackType ()))
+ Kempe.Monomorphize: closedModule :: Declarations () (StackType ()) (StackType ()) -> MonoM (Declarations () (StackType ()) (StackType ()))
- Kempe.Monomorphize: closure :: Ord b => (Module a b b, ModuleMap a b b) -> Set (Name b, b)
+ Kempe.Monomorphize: closure :: Ord b => (Declarations a b b, ModuleMap a b b) -> Set (Name b, b)
- Kempe.Monomorphize: flattenModule :: Module () (StackType ()) (StackType ()) -> MonoM (Module () (ConsAnn MonoStackType) (StackType ()))
+ Kempe.Monomorphize: flattenModule :: Declarations () (StackType ()) (StackType ()) -> MonoM (Declarations () (ConsAnn MonoStackType) (StackType ()))
- Kempe.Monomorphize: mkModuleMap :: Module a c b -> ModuleMap a c b
+ Kempe.Monomorphize: mkModuleMap :: Declarations a c b -> ModuleMap a c b
- Kempe.Pipeline: irGen :: Int -> Module a c b -> ([Stmt], WriteSt, SizeEnv)
+ Kempe.Pipeline: irGen :: Typeable a => Int -> Declarations a c b -> ([Stmt], WriteSt, SizeEnv)
- Kempe.Pipeline: x86Alloc :: Int -> Module a c b -> [X86 X86Reg ()]
+ Kempe.Pipeline: x86Alloc :: Typeable a => Int -> Declarations a c b -> [X86 X86Reg ()]
- Kempe.Pipeline: x86Parsed :: Int -> Module a c b -> [X86 AbsReg ()]
+ Kempe.Pipeline: x86Parsed :: Typeable a => Int -> Declarations a c b -> [X86 AbsReg ()]
- Kempe.Shuttle: monomorphize :: Int -> Module a c b -> Either (Error ()) (Module () (ConsAnn MonoStackType) MonoStackType, SizeEnv)
+ Kempe.Shuttle: monomorphize :: Int -> Declarations a c b -> Either (Error ()) (Declarations () (ConsAnn MonoStackType) MonoStackType, SizeEnv)
- Kempe.TyAssign: assignModule :: Module a c b -> TypeM () (Module () (StackType ()) (StackType ()))
+ Kempe.TyAssign: assignModule :: Declarations a c b -> TypeM () (Declarations () (StackType ()) (StackType ()))
- Kempe.TyAssign: checkModule :: Module a c b -> TypeM () ()
+ Kempe.TyAssign: checkModule :: Declarations a c b -> TypeM () ()

Files

CHANGELOG.md view
@@ -1,5 +1,16 @@ # kempe +## 0.1.1.0++  * Fix internal pretty-printer (exposed as hidden `fmt` subcommand)+  * Optimize IR cases+  * Fix padding+  * Fix bug in lexer (for C foreign calls)+  * Support down to GHC 8.0.2+  * Unification no longer takes pathologically long time+  * Add test files so source distribution passes+  * Some sort of imports now supported.+ ## 0.1.0.2    * Add optimizations (simplify code so that liveness analysis is quicker)
README.md view
@@ -25,11 +25,14 @@  ## Defects -  * Unification takes too long   * Errors don't have position information   * Monomorphization fails on recursive polymorphic functions++    Hopefully this isn't too sinful; I can't think of any examples of recursive+    polymorphic functions   * Can't export or call C functions with more than 6 arguments; can't call or     export large arguments (i.e. structs) passed by value.      This is less of an impediment than it sounds like.-  * Sizing for ADTs is not rigorous in places+  * Cyclic module imports are not detected+  * Modules (imports) are kind of defective
bench/Bench.hs view
@@ -1,6 +1,6 @@ module Main (main) where -import           Control.Exception         (Exception, throw, throwIO)+import           Control.Exception         (throw) import           Criterion.Main import           Data.Bifunctor            (Bifunctor, bimap) import qualified Data.ByteString.Lazy      as BSL@@ -15,6 +15,7 @@ import           Kempe.IR.Opt import           Kempe.Inline import           Kempe.Lexer+import           Kempe.Module import           Kempe.Monomorphize import           Kempe.Parser import           Kempe.Pipeline@@ -95,15 +96,16 @@                         , bench "Generate assembly (lib/numbertheory.kmp)" $ nfIO (writeAsm "lib/numbertheory.kmp")                         , bench "Object file (examples/factorial.kmp)" $ nfIO (compile "examples/factorial.kmp" "/tmp/factorial.o" False)                         , bench "Object file (lib/numbertheory.kmp)" $ nfIO (compile "lib/numbertheory.kmp" "/tmp/numbertheory.o" False)+                        , bench "Object file (examples/splitmix.kmp)" $ nfIO (compile "examples/splitmix.kmp" "/tmp/splitmix.o" False)                         ]                 ]-    where parsedM = yeetIO . parseWithMax =<< BSL.readFile "test/data/ty.kmp"-          splitmix = yeetIO . parseWithMax =<< BSL.readFile "examples/splitmix.kmp"-          fac = yeetIO . parseWithMax =<< BSL.readFile "examples/factorial.kmp"-          num = yeetIO . parseWithMax =<< BSL.readFile "lib/numbertheory.kmp"-          eitherMod = yeetIO . parse =<< BSL.readFile "lib/either.kmp"+    where parsedM = parseProcess "test/data/ty.kmp"+          splitmix = parseProcess "examples/splitmix.kmp"+          fac = parseProcess "examples/factorial.kmp"+          num = parseProcess "lib/numbertheory.kmp"+          eitherMod = snd <$> parseProcess "lib/either.kmp"           parsedInteresting = (,) <$> fac <*> num-          prelude = yeetIO . parseWithMax =<< BSL.readFile "prelude/fn.kmp"+          prelude = parseProcess "prelude/fn.kmp"           forTyEnv = (,,) <$> parsedM <*> splitmix <*> prelude           runCheck (maxU, m) = runTypeM maxU (checkModule m)           runAssign (maxU, m) = runTypeM maxU (assignModule m)@@ -134,13 +136,9 @@           -- not even gonna justify this           yrrucnu f (y, x) = f x y -yeetIO :: Exception e => Either e a -> IO a-yeetIO = either throwIO pure- writeAsm :: FilePath          -> IO T.Text writeAsm fp = do-    contents <- BSL.readFile fp-    res <- yeetIO $ parseWithMax contents+    res <- parseProcess fp     pure $ renderText $ uncurry dumpX86 res     where renderText = renderStrict . layoutPretty defaultLayoutOptions
docs/manual.pdf view

binary file changed (212387 → 213705 bytes)

+ examples/factorial.kmp view
@@ -0,0 +1,21 @@+loop : Int Int -- Int+     =: [ swap dup 0 =+          if( drop+            , dup 1 - dip(*) swap loop )+        ]++; tail recursive factorial+;+; see C example: https://wiki.c2.com/?TailRecursion+fac_tailrec : Int -- Int+            =: [ 1 loop ]++; naïve factorial+fac : Int -- Int+    =: [ dup 0 =+         if( drop 1+           , dup 1 - fac * )+       ]++%foreign cabi fac+%foreign cabi fac_tailrec
+ examples/hamming.kmp view
@@ -0,0 +1,2 @@+hamming : Word Word -- Int+        =: [ xoru popcount ]
+ examples/splitmix.kmp view
@@ -0,0 +1,11 @@+; from here: http://prng.di.unimi.it/splitmix64.c++; given a seed, return a random value and the new seed+next : Word -- Word Word+     =: [ 0x9e3779b97f4a7c15u +~ dup+          dup 30i8 >>~ xoru 0xbf58476d1ce4e5b9u *~+          dup 27i8 >>~ xoru 0x94d049bb133111ebu *~+          dup 31i8 >>~ xoru+        ]++%foreign kabi next
kempe.cabal view
@@ -1,6 +1,6 @@ cabal-version:   3.0 name:            kempe-version:         0.1.0.2+version:         0.1.1.0 license:         BSD-3-Clause license-file:    LICENSE copyright:       Copyright: (c) 2020 Vanessa McHale@@ -12,6 +12,12 @@ build-type:      Simple data-files:     test/data/*.kmp+    test/err/*.kmp+    test/examples/*.kmp+    test/golden/*.out+    test/golden/*.ir+    test/harness/*.c+    examples/*.kmp     prelude/*.kmp     lib/*.kmp     docs/manual.pdf@@ -40,6 +46,7 @@         Kempe.Pipeline         Kempe.Shuttle         Kempe.Inline+        Kempe.Module         Kempe.Check.Pattern         Kempe.IR         Kempe.IR.Opt@@ -51,6 +58,7 @@     hs-source-dirs:   src     other-modules:         Kempe.Check.Restrict+        Kempe.Check.TopLevel         Kempe.Unique         Kempe.Name         Kempe.Error@@ -65,9 +73,9 @@         FlexibleContexts GeneralizedNewtypeDeriving OverloadedStrings         StandaloneDeriving TupleSections DeriveAnyClass -    ghc-options:      -Wall -O2+    ghc-options:      -Wall     build-depends:-        base >=4.11 && <5,+        base >=4.9 && <5,         array -any,         bytestring -any,         containers >=0.6.0.0,@@ -76,9 +84,9 @@         mtl -any,         microlens -any,         transformers -any,-        extra -any,+        extra >=1.7.4,         prettyprinter >=1.7.0,-        composition-prelude >=1.1.0.1,+        composition-prelude >=2.0.2.0,         microlens-mtl -any,         process >=1.2.3.0,         temporary -any@@ -111,7 +119,8 @@         base -any,         optparse-applicative -any,         kempe-modules -any,-        prettyprinter >=1.7.0+        prettyprinter >=1.7.0,+        bytestring -any      if impl(ghc >=8.0)         ghc-options:@@ -135,6 +144,7 @@         Parser         Type         Backend+        Abi      default-language: Haskell2010     ghc-options:      -threaded -rtsopts "-with-rtsopts=-N -K1K" -Wall@@ -145,7 +155,10 @@         tasty-hunit -any,         bytestring -any,         prettyprinter >=1.7.0,-        deepseq -any+        deepseq -any,+        tasty-golden -any,+        text -any,+        composition-prelude -any      if impl(ghc >=8.0)         ghc-options:
+ lib/libc.kmp view
@@ -0,0 +1,7 @@+; bindings to libc (x86_64 guess)++rand : -- Int+     =: $cfun"rand"++exit : Int --+     =: $cfun"exit"
lib/numbertheory.kmp view
@@ -1,15 +1,11 @@+import "prelude/fn.kmp"+ ; tail recursive! gcd : Int Int -- Int     =: [ dup 0 =          if( drop            , dup dip(%) swap gcd )        ]--over : a b -- a b a-     =: [ dip(dup) swap ]--dup2 : a b -- a b a b-     =: [ over over ]  square : Int -- Int        =: [ dup * ]
+ lib/tuple.kmp view
@@ -0,0 +1,12 @@+import "prelude/fn.kmp"++type Pair a b { Pair a b }++unPair : ((Pair a) b) -- a b+       =: [ { case | Pair -> } ]++fst : ((Pair a) b) -- a+    =: [ unPair drop ]++snd : ((Pair a) b) -- b+    =: [ unPair nip ]
run/Main.hs view
@@ -1,10 +1,14 @@ module Main (main) where -import           Control.Exception         (throwIO)+import           Control.Exception         (Exception, throwIO) import           Control.Monad             ((<=<))+import qualified Data.ByteString.Lazy      as BSL+import           Data.Semigroup            ((<>)) import qualified Data.Version              as V import           Kempe.AST import           Kempe.File+import           Kempe.Lexer+import           Kempe.Parser import           Options.Applicative import qualified Paths_kempe               as P import           Prettyprinter             (LayoutOptions (LayoutOptions), PageWidth (AvailablePerLine), hardline, layoutSmart)@@ -15,14 +19,24 @@ data Command = TypeCheck !FilePath              | Compile !FilePath !(Maybe FilePath) !Bool !Bool !Bool -- TODO: take arch on cli              | Format !FilePath+             | Lint !FilePath  fmt :: FilePath -> IO ()-fmt = renderIO stdout <=< fmap (render . (<> hardline) . prettyModule . snd) . parsedFp+fmt = renderIO stdout <=< fmap (render . (<> hardline) . prettyModule) . parsedFp     where render = layoutSmart settings           settings = LayoutOptions $ AvailablePerLine 80 0.5 +parsedFp :: FilePath -> IO (Module AlexPosn AlexPosn AlexPosn)+parsedFp fp = do+     contents <- BSL.readFile fp+     yeetIO $ parse contents++yeetIO :: Exception e => Either e a -> IO a+yeetIO = either throwIO pure+ run :: Command -> IO () run (TypeCheck fp)                        = either throwIO pure =<< tcFile fp+run (Lint fp)                             = maybe (pure ()) throwIO =<< warnFile fp run (Compile _ Nothing _ False False)     = putStrLn "No output file specified!" run (Compile fp (Just o) dbg False False) = compile fp o dbg run (Compile fp Nothing False True False) = irFile fp@@ -39,6 +53,9 @@ fmtP :: Parser Command fmtP = Format <$> kmpFile +lintP :: Parser Command+lintP = Lint <$> kmpFile+ debugSwitch :: Parser Bool debugSwitch = switch     (long "debug"@@ -65,7 +82,8 @@  commandP :: Parser Command commandP = hsubparser-    (command "typecheck" (info tcP (progDesc "Type-check module contents")))+    (command "typecheck" (info tcP (progDesc "Type-check module contents"))+    <> command "lint" (info lintP (progDesc "Lint a file")))     <|> hsubparser (command "fmt" (info fmtP (progDesc "Pretty-print a Kempe file")) <> internal)     <|> compileP     where
src/Kempe/AST.hs view
@@ -15,12 +15,16 @@                  , KempeDecl (..)                  , Pattern (..)                  , ABI (..)-                 , Module+                 , Declarations+                 , Module (..)                  , freeVars                  , MonoStackType                  , SizeEnv+                 , Size                  , size                  , sizeStack+                 , size'+                 , cSize                  , prettyMonoStackType                  , prettyTyped                  , prettyTypedModule@@ -41,6 +45,7 @@ import           Data.List.NonEmpty      (NonEmpty) import qualified Data.List.NonEmpty      as NE import           Data.Monoid             (Sum (..))+import           Data.Semigroup          ((<>)) import qualified Data.Set                as S import           Data.Text.Lazy.Encoding (decodeUtf8) import           Data.Word               (Word8)@@ -48,7 +53,7 @@ import           Kempe.Name import           Kempe.Unique import           Numeric.Natural-import           Prettyprinter           (Doc, Pretty (pretty), align, braces, brackets, colon, concatWith, fillSep, hsep, parens, pipe, sep, vsep, (<+>))+import           Prettyprinter           (Doc, Pretty (pretty), align, braces, brackets, colon, concatWith, dquotes, fillSep, hsep, parens, pipe, sep, vsep, (<+>)) import           Prettyprinter.Ext  data BuiltinTy = TyInt@@ -152,7 +157,7 @@ prettyTyped (BoolLit _ b)    = pretty b prettyTyped (Int8Lit _ i)    = pretty i <> "i8" prettyTyped (WordLit _ n)    = pretty n <> "u"-prettyTyped (Case _ ls)      = "case" <+> braces (vsep (toList $ fmap (uncurry prettyTypedLeaf) ls))+prettyTyped (Case _ ls)      = braces ("case" <+> vsep (toList $ fmap (uncurry prettyTypedLeaf) ls))  data Atom c b = AtName b (Name b)               | Case b (NonEmpty (Pattern c b, [Atom c b]))@@ -256,7 +261,7 @@ prettyKempeDecl :: (Atom c b -> Doc ann) -> KempeDecl a c b -> Doc ann prettyKempeDecl atomizer (FunDecl _ n is os as) = pretty n <+> align (":" <+> sep (fmap pretty is) <+> "--" <+> sep (fmap pretty os) <#> "=:" <+> brackets (align (fillSep (atomizer <$> as)))) prettyKempeDecl _ (Export _ abi n)              = "%foreign" <+> pretty abi <+> pretty n-prettyKempeDecl _ (ExtFnDecl _ n is os b)       = pretty n <+> align (":" <+> sep (fmap pretty is) <+> "--" <+> sep (fmap pretty os) <#> "=:" <+> "$cfun" <> pretty (decodeUtf8 b))+prettyKempeDecl _ (ExtFnDecl _ n is os b)       = pretty n <+> align (":" <+> sep (fmap pretty is) <+> "--" <+> sep (fmap pretty os) <#> "=:" <+> "$cfun" <> dquotes (pretty (decodeUtf8 b))) prettyKempeDecl _ (TyDecl _ tn ns ls)           = "type" <+> pretty tn <+> hsep (fmap pretty ns) <+> braces (concatWith (\x y -> x <+> pipe <+> y) $ fmap (uncurry prettyTyLeaf) ls)  instance Pretty (KempeDecl a b c) where@@ -279,20 +284,31 @@     first _ (Export l abi n)           = Export l abi n     second = fmap +prettyDeclarationsGeneral :: (Atom c b -> Doc ann) -> Declarations a c b -> Doc ann+prettyDeclarationsGeneral atomizer = sepDecls . fmap (prettyKempeDecl atomizer)++prettyImport :: BSL.ByteString -> Doc ann+prettyImport b = "import" <+> dquotes (pretty (decodeUtf8 b))+ prettyModuleGeneral :: (Atom c b -> Doc ann) -> Module a c b -> Doc ann-prettyModuleGeneral atomizer = sep . fmap (prettyKempeDecl atomizer)+prettyModuleGeneral atomizer (Module [] ds) = prettyDeclarationsGeneral atomizer ds+prettyModuleGeneral atomizer (Module is ds) = prettyLines (fmap prettyImport is) <##> prettyDeclarationsGeneral atomizer ds -prettyFancyModule :: Module () (ConsAnn (StackType ())) (StackType ()) -> Doc ann+prettyFancyModule :: Declarations () (ConsAnn (StackType ())) (StackType ()) -> Doc ann prettyFancyModule = prettyTypedModule . fmap (first consTy) -prettyTypedModule :: Module () (StackType ()) (StackType ()) -> Doc ann-prettyTypedModule = prettyModuleGeneral prettyTyped+prettyTypedModule :: Declarations () (StackType ()) (StackType ()) -> Doc ann+prettyTypedModule = prettyDeclarationsGeneral prettyTyped  prettyModule :: Module a c b -> Doc ann prettyModule = prettyModuleGeneral pretty -type Module a c b = [KempeDecl a c b]+type Declarations a c b = [KempeDecl a c b] +data Module a c b = Module { importFps :: [BSL.ByteString]+                           , body      :: [KempeDecl a c b]+                           } deriving (Generic, NFData)+ extrVars :: KempeTy a -> [Name a] extrVars TyBuiltin{}      = [] extrVars TyNamed{}        = []@@ -302,22 +318,32 @@ freeVars :: [KempeTy a] -> S.Set (Name a) freeVars tys = S.fromList (concatMap extrVars tys) -type SizeEnv = IM.IntMap Int64+-- machinery for assigning a constructor to a function of its concrete types+-- (and then curry forward...) --- the kempe sizing system is kind of fucked (it works tho)+type Size = [Int64] -> Int64+type SizeEnv = IM.IntMap Size +-- the kempe sizing system is kind of fucked (it mostly works tho)+ -- | Don't call this on ill-kinded types; it won't throw any error.-size :: SizeEnv -> KempeTy a -> Int64-size _ (TyBuiltin _ TyInt)                 = 8 -- since we're only targeting x86_64 and aarch64 we have 64-bit 'Int's-size _ (TyBuiltin _ TyBool)                = 1-size _ (TyBuiltin _ TyInt8)                = 1-size _ (TyBuiltin _ TyWord)                = 8+size :: SizeEnv -> KempeTy a -> Size+size _ (TyBuiltin _ TyInt)                 = const 8+size _ (TyBuiltin _ TyBool)                = const 1+size _ (TyBuiltin _ TyInt8)                = const 1+size _ (TyBuiltin _ TyWord)                = const 8 size _ TyVar{}                             = error "Internal error: type variables should not be present at this stage." size env (TyNamed _ (Name _ (Unique k) _)) = IM.findWithDefault (error "Size not in map!") k env-size env (TyApp _ ty ty')                  = size env ty + size env ty'+size env (TyApp _ ty ty')                  = \tys -> size env ty (size env ty' [] : tys) +cSize :: Size -> Int64+cSize = ($ [])++size' :: SizeEnv -> KempeTy a -> Int64+size' env = cSize . size env+ sizeStack :: SizeEnv -> [KempeTy a] -> Int64-sizeStack env = getSum . foldMap (Sum . size env)+sizeStack env = getSum . foldMap (Sum . size' env)  -- | Used in "Kempe.Monomorphize" for patterns flipStackType :: StackType () -> StackType ()
src/Kempe/Asm/X86.hs view
@@ -139,16 +139,16 @@     pure [ SubRC () (toAbsReg r1) i ] irEmit _ (IR.MovTemp r1 (IR.ExprIntBinOp IR.IntPlusIR (IR.Reg r2) (IR.ConstInt i))) | r1 == r2 = do     pure [ AddRC () (toAbsReg r1) i ]-irEmit env (IR.CCall (is, []) b) | all (\i -> size env i <= 8) is && length is <= 6 =+irEmit env (IR.CCall (is, []) b) | all (\i -> size' env i <= 8) is && length is <= 6 =     pure [NasmMacro0 () "callersave", CallBS () b, NasmMacro0 () "callerrestore"]-irEmit env (IR.CCall (is, [o]) b) | all (\i -> size env i <= 8) is && size env o <= 8 && length is <= 6 =+irEmit env (IR.CCall (is, [o]) b) | all (\i -> size' env i <= 8) is && size' env o <= 8 && length is <= 6 =     pure [NasmMacro0 () "callersave", CallBS () b, NasmMacro0 () "callerrestore"] -- For 128-bit returns we'd have to use rax and rdx-irEmit env (IR.WrapKCall Cabi (is, [o]) n l) | all (\i -> size env i <= 8) is && size env o <= 8 && length is <= 6 = do-    { let offs = scanl' (+) 0 (fmap (size env) is)+irEmit env (IR.WrapKCall Cabi (is, [o]) n l) | all (\i -> size' env i <= 8) is && size' env o <= 8 && length is <= 6 = do+    { let offs = scanl' (+) 0 (fmap (size' env) is)     ; let totalSize = sizeStack env is     ; let argRegs = [CArg1, CArg2, CArg3, CArg4, CArg5, CArg6]-    ; pure $ [BSLabel () n, MovRL () DataPointer "kempe_data", NasmMacro0 () "calleesave"] ++ zipWith (\r i-> MovAR () (AddrRCPlus DataPointer i) r) argRegs offs ++ [AddRC () DataPointer totalSize, Call () l, MovRA () CRet (AddrRCMinus DataPointer (size env o)), NasmMacro0 () "calleerestore", Ret ()] -- TODO: bytes on the stack eh+    ; pure $ [BSLabel () n, MovRL () DataPointer "kempe_data", NasmMacro0 () "calleesave"] ++ zipWith (\r i-> MovAR () (AddrRCPlus DataPointer i) r) argRegs offs ++ [AddRC () DataPointer totalSize, Call () l, MovRA () CRet (AddrRCMinus DataPointer (size' env o)), NasmMacro0 () "calleerestore", Ret ()] -- TODO: bytes on the stack eh     } irEmit _ (IR.WrapKCall Kabi (_, _) n l) =     pure [BSLabel () n, Call () l, Ret ()]
src/Kempe/Asm/X86/ControlFlow.hs view
@@ -7,6 +7,7 @@ import           Data.Bifunctor             (first, second) import           Data.Functor               (($>)) import qualified Data.Map                   as M+import           Data.Semigroup             ((<>)) import qualified Data.Set                   as S import           Kempe.Asm.X86.Type 
src/Kempe/Asm/X86/Linear.hs view
@@ -11,6 +11,7 @@ import           Data.Foldable              (traverse_) import qualified Data.Map                   as M import           Data.Maybe                 (fromMaybe)+import           Data.Semigroup             ((<>)) import qualified Data.Set                   as S import           Kempe.Asm.X86.Type import           Lens.Micro                 (Lens')
src/Kempe/Asm/X86/Liveness.hs view
@@ -8,6 +8,7 @@ import           Control.Composition (thread) -- this seems to be faster import qualified Data.IntMap.Lazy    as IM+import           Data.Semigroup      ((<>)) import qualified Data.Set            as S import           Kempe.Asm.X86.Type 
src/Kempe/Asm/X86/Type.hs view
@@ -19,6 +19,7 @@ import qualified Data.ByteString.Lazy    as BSL import           Data.Foldable           (toList) import           Data.Int                (Int64, Int8)+import           Data.Semigroup          ((<>)) import qualified Data.Set                as S import           Data.Text.Encoding      (decodeUtf8) import qualified Data.Text.Lazy.Encoding as TL@@ -281,9 +282,6 @@     pretty (MovRCTag _ r b)     = i4 ("mov" <+> pretty r <> "," <+> pretty b)     pretty (NasmMacro0 _ b)     = i4 (pretty (decodeUtf8 b))     pretty (CallBS _ b)         = i4 ("call" <+> pretty (TL.decodeUtf8 b))--prettyLines :: [Doc ann] -> Doc ann-prettyLines = concatWith (<#>)  prettyAsm :: Pretty reg => [X86 reg a] -> Doc ann prettyAsm = ((prolegomena <#> macros <#> "section .text" <> hardline) <>) . prettyLines . fmap pretty
src/Kempe/Check/Pattern.hs view
@@ -34,10 +34,10 @@ checkDecl env (FunDecl _ _ _ _ as) = foldMapAlternative (checkAtom env) as checkDecl _ _                      = Nothing -checkModule :: PatternEnv -> Module a c b -> Maybe (Error b)+checkModule :: PatternEnv -> Declarations a c b -> Maybe (Error b) checkModule env = foldMapAlternative (checkDecl env) -checkModuleExhaustive :: Module a c b -> Maybe (Error b)+checkModuleExhaustive :: Declarations a c b -> Maybe (Error b) checkModuleExhaustive m =     let env = runPatternM $ patternEnvDecls m         in checkModule env m@@ -54,7 +54,7 @@  type PatternM = State PatternEnv -patternEnvDecls :: Module a c b -> PatternM ()+patternEnvDecls :: Declarations a c b -> PatternM () patternEnvDecls = traverse_ declAdd  declAdd :: KempeDecl a c b -> PatternM ()
src/Kempe/Check/Restrict.hs view
@@ -6,7 +6,7 @@ import           Kempe.AST import           Kempe.Error       (Error (FatSumType)) -restrictConstructors :: Module a c b -> Maybe (Error a)+restrictConstructors :: Declarations a c b -> Maybe (Error a) restrictConstructors = foldMapAlternative restrictDecl  restrictDecl :: KempeDecl a c b -> Maybe (Error a)
+ src/Kempe/Check/TopLevel.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}++module Kempe.Check.TopLevel ( topLevelCheck+                            , Warning+                            ) where++import           Control.Applicative ((<|>))+import           Control.Exception   (Exception)+import           Data.Foldable       (toList)+import           Data.Foldable.Ext+import           Data.List           (group, sort)+import           Data.Maybe          (mapMaybe)+import           Data.Semigroup      ((<>))+import           Data.Typeable       (Typeable)+import           Kempe.AST+import           Kempe.Name+import           Prettyprinter       (Pretty (pretty))++data Warning a = NameClash a (Name a)++instance Pretty a => Pretty (Warning a) where+    pretty (NameClash l x) = pretty l <> " '" <> pretty x <> "' is defined more than once."++topLevelCheck :: Declarations a c a -> Maybe (Warning a)+topLevelCheck ds =+        checkNames (collectNames ds)+    <|> checkNames (collectCons ds)++-- | Just checks function names and type names. Doesn't check constructors.+collectNames :: Declarations a c a -> [Name a]+collectNames = mapMaybe collectDeclNames where+    collectDeclNames (FunDecl _ n _ _ _)   = Just n+    collectDeclNames (ExtFnDecl _ n _ _ _) = Just n+    collectDeclNames Export{}              = Nothing+    collectDeclNames (TyDecl _ tn _ _)     = Just tn++collectCons :: Declarations a c b-> [Name b]+collectCons = concatMap collectDeclNames where+    collectDeclNames (TyDecl _ _ _ ls) = toList (fst <$> ls)+    collectDeclNames _                 = []++checkNames :: [Name a] -> Maybe (Warning a)+checkNames ns = foldMapAlternative announce (group $ sort ns) -- maybe could be better idk+    where announce (_:y:_) = Just $ NameClash (loc y) y+          announce _       = Nothing++instance (Pretty a) => Show (Warning a) where+    show = show . pretty++instance (Pretty a, Typeable a) => Exception (Warning a)
src/Kempe/Error.hs view
@@ -8,6 +8,7 @@  import           Control.DeepSeq   (NFData) import           Control.Exception (Exception)+import           Data.Semigroup    ((<>)) import           Data.Typeable     (Typeable) import           GHC.Generics      (Generic) import           Kempe.AST@@ -33,7 +34,7 @@ mErr Nothing    = Right () mErr (Just err) = Left err -instance (Pretty a) => Show (Error a) where+instance Show (Error a) where     show = show . pretty  instance Pretty (Error a) where@@ -50,4 +51,4 @@     pretty (FatSumType _ tn)             = "Sum type" <+> pretty tn <+> "has too many constructors! Sum types are limited to 256 constructors in Kempe."     pretty InexhaustiveMatch{}           = "Inexhaustive pattern match." -instance (Pretty a, Typeable a) => Exception (Error a)+instance (Typeable a) => Exception (Error a)
src/Kempe/File.hs view
@@ -1,28 +1,31 @@ module Kempe.File ( tcFile+                  , warnFile                   , dumpMono                   , dumpTyped                   , irFile                   , x86File                   , dumpX86                   , compile-                  , parsedFp+                  , dumpIR                   ) where  -- common b/w test suite and exec, repl utils import           Control.Composition       ((.*)) import           Control.Exception         (Exception, throwIO) import           Data.Bifunctor            (bimap)-import qualified Data.ByteString.Lazy      as BSL import           Data.Functor              (void)+import           Data.Semigroup            ((<>)) import qualified Data.Set                  as S import           Data.Tuple.Extra          (fst3)+import           Data.Typeable             (Typeable) import           Kempe.AST import           Kempe.Asm.X86.Type import           Kempe.Check.Pattern+import           Kempe.Check.TopLevel import           Kempe.Error import           Kempe.IR import           Kempe.Lexer-import           Kempe.Parser+import           Kempe.Module import           Kempe.Pipeline import           Kempe.Proc.Nasm import           Kempe.Shuttle@@ -32,48 +35,47 @@  tcFile :: FilePath -> IO (Either (Error ()) ()) tcFile fp = do-    contents <- BSL.readFile fp-    (maxU, m) <- yeetIO $ parseWithMax contents+    (maxU, m) <- parseProcess fp     pure $ do         void $ runTypeM maxU (checkModule m)         mErr $ checkModuleExhaustive (void <$> m) +warnFile :: FilePath -> IO (Maybe (Warning AlexPosn))+warnFile fp = do+    (_, m) <- parseProcess fp+    pure $ topLevelCheck m+ yeetIO :: Exception e => Either e a -> IO a yeetIO = either throwIO pure  dumpTyped :: FilePath -> IO () dumpTyped fp = do-    (i, m) <- parsedFp fp+    (i, m) <- parseProcess fp     (mTyped, _) <- yeetIO $ runTypeM i (assignModule m)     putDoc $ prettyTypedModule mTyped  dumpMono :: FilePath -> IO () dumpMono fp = do-    (i, m) <- parsedFp fp+    (i, m) <- parseProcess fp     (mMono, _) <- yeetIO $ monomorphize i m     putDoc $ prettyTypedModule (fmap (bimap fromMonoConsAnn fromMono) mMono)     where fromMono (is, os) = StackType S.empty is os           fromMonoConsAnn (ConsAnn _ _ ty) = fromMono ty -dumpIR :: Int -> Module a c b -> Doc ann+dumpIR :: Typeable a => Int -> Declarations a c b -> Doc ann dumpIR = prettyIR . fst3 .* irGen -dumpX86 :: Int -> Module a c b -> Doc ann+dumpX86 :: Typeable a => Int -> Declarations a c b -> Doc ann dumpX86 = prettyAsm .* x86Alloc  irFile :: FilePath -> IO () irFile fp = do-    res <- parsedFp fp+    res <- parseProcess fp     putDoc $ uncurry dumpIR res <> hardline -parsedFp :: FilePath -> IO (Int, Module AlexPosn AlexPosn AlexPosn)-parsedFp fp = do-    contents <- BSL.readFile fp-    yeetIO $ parseWithMax contents- x86File :: FilePath -> IO () x86File fp = do-    res <- parsedFp fp+    res <- parseProcess fp     putDoc $ uncurry dumpX86 res <> hardline  compile :: FilePath@@ -81,6 +83,5 @@         -> Bool -- ^ Debug symbols?         -> IO () compile fp o dbg = do-    contents <- BSL.readFile fp-    res <- yeetIO $ parseWithMax contents+    res <- parseProcess fp     writeO (uncurry dumpX86 res) o dbg
src/Kempe/IR.hs view
@@ -30,6 +30,7 @@ import           Data.Foldable.Ext import           Data.Int                   (Int64, Int8) import qualified Data.IntMap                as IM+import           Data.Semigroup             ((<>)) import           Data.Text.Encoding         (decodeUtf8, encodeUtf8) import           Data.Word                  (Word8) import           GHC.Generics               (Generic)@@ -38,7 +39,7 @@ import           Kempe.Unique import           Lens.Micro                 (Lens') import           Lens.Micro.Mtl             (modifying)-import           Prettyprinter              (Doc, Pretty (pretty), braces, brackets, colon, concatWith, hardline, parens, (<+>))+import           Prettyprinter              (Doc, Pretty (pretty), braces, brackets, colon, hardline, parens, (<+>)) import           Prettyprinter.Ext  type Label = Word@@ -103,7 +104,7 @@         (IM.findWithDefault (error "Internal error in IR phase: could not look find label for name") i . atLabels)  prettyIR :: [Stmt] -> Doc ann-prettyIR = concatWith (\x y -> x <> hardline <> y) . fmap pretty+prettyIR = prettyLines . fmap pretty  prettyLabel :: Label -> Doc ann prettyLabel l = "kmp" <> pretty l@@ -216,7 +217,7 @@     pretty WordModIR    = "%~"     pretty WordDivIR    = "/~" -writeModule :: SizeEnv -> Module () (ConsAnn MonoStackType) MonoStackType -> TempM [Stmt]+writeModule :: SizeEnv -> Declarations () (ConsAnn MonoStackType) MonoStackType -> TempM [Stmt] writeModule env m = traverse_ assignName m *> foldMapA (writeDecl env) m  -- optimize tail-recursion, if possible@@ -353,10 +354,10 @@ writeAtom _ _ (AtBuiltin _ IntNeg)      = intNeg writeAtom _ _ (AtBuiltin _ Popcount)    = wordCount writeAtom env _ (AtBuiltin (is, _) Drop)  =-    let sz = size env (last is) in+    let sz = size' env (last is) in         pure [ dataPointerDec sz ] writeAtom env _ (AtBuiltin (is, _) Dup)   =-    let sz = size env (last is) in+    let sz = size' env (last is) in         pure $              copyBytes 0 (-sz) sz                 ++ [ dataPointerInc sz ] -- move data pointer over sz bytes@@ -369,11 +370,11 @@     l2 <- newLabel     pure $ dataPointerDec 1 : ifIR : (Labeled l0 : asIR ++ [Jump l2]) ++ (Labeled l1 : asIR') ++ [Labeled l2] writeAtom env _ (Dip (is, _) as) =-    let sz = size env (last is)+    let sz = size' env (last is)     in foldMapA (dipify env sz) as writeAtom env _ (AtBuiltin ([i0, i1], _) Swap) =-    let sz0 = size env i0-        sz1 = size env i1+    let sz0 = size' env i0+        sz1 = size' env i1     in         pure $             copyBytes 0 (-sz0 - sz1) sz0 -- copy i0 to end of the stack@@ -385,7 +386,7 @@ writeAtom _ _ (Case ([], _) _) = error "Internal error: Ill-typed case statement?!" writeAtom env l (Case (is, _) ls) =     let (ps, ass) = NE.unzip ls-        decSz = size env (last is)+        decSz = size' env (last is)         in do             leaves <- zipWithM (mkLeaf env l) ps ass             let (switches, meat) = NE.unzip leaves@@ -422,14 +423,14 @@ dipify :: SizeEnv -> Int64 -> Atom (ConsAnn MonoStackType) MonoStackType -> TempM [Stmt] dipify _ _ (AtBuiltin ([], _) Drop) = error "Internal error: Ill-typed drop!" dipify env sz (AtBuiltin (is, _) Drop) =-    let sz' = size env (last is)+    let sz' = size' env (last is)         shift = dataPointerDec sz' -- shift data pointer over by sz' bytes         -- copy sz bytes over (-sz') bytes from the data pointer         copyBytes' = copyBytes (-sz - sz') (-sz) sz         in pure $ copyBytes' ++ [shift] dipify env sz (AtBuiltin ([i0, i1], _) Swap) =-    let sz0 = size env i0-        sz1 = size env i1+    let sz0 = size' env i0+        sz1 = size' env i1     in         pure $             copyBytes 0 (-sz - sz0 - sz1) sz0 -- copy i0 to end of the stack@@ -437,7 +438,7 @@                 ++ copyBytes (-sz - sz0) 0 sz0 -- copy i0 at end of stack to its new place dipify _ _ (Dip ([], _) _) = error "Internal error: Ill-typed dip()!" dipify env sz (Dip (is, _) as) =-    let sz' = size env (last is)+    let sz' = size' env (last is)         in foldMapA (dipify env (sz + sz')) as dipify _ _ (AtBuiltin _ Swap)        = error "Internal error: Ill-typed swap!" dipify _ sz (AtBuiltin _ IntTimes)   = dipOp sz IntTimesIR@@ -469,7 +470,7 @@ dipify _ sz (AtBuiltin _ WordMod)    = dipOp sz WordModIR dipify _ _ (AtBuiltin ([], _) Dup) = error "Internal error: Ill-typed dup!" dipify env sz (AtBuiltin (is, _) Dup) = do-    let sz' = size env (last is) in+    let sz' = size' env (last is) in         pure $              copyBytes 0 (-sz) sz -- copy sz bytes over to the end of the stack                 ++ copyBytes (-sz) (-sz - sz') sz' -- copy sz' bytes over (duplicate)@@ -555,6 +556,7 @@     | b `mod` 8 == 0 =         let is = fmap (8*) [0..(b `div` 8 - 1)] in             [ MovMem (dataPointerPlus (i + off1)) 8 (Mem 8 $ dataPointerPlus (i + off2)) | i <- is ]+    -- TODO: 4 byte chunks, &c. (would require more registers).     | otherwise =         [ MovMem (dataPointerPlus (i + off1)) 1 (Mem 1 $ dataPointerPlus (i + off2)) | i <- [0..(b-1)] ] 
src/Kempe/IR/Opt.hs view
@@ -63,5 +63,7 @@ removeNop :: [Stmt] -> [Stmt] removeNop = filter (not . isNop)     where+        isNop (MovTemp e (ExprIntBinOp IntPlusIR (Reg e') (ConstInt 0))) | e == e' = True+        isNop (MovTemp e (ExprIntBinOp IntMinusIR (Reg e') (ConstInt 0))) | e == e' = True         isNop (MovMem e _ (Mem _ e')) | e == e' = True -- the Eq on Exp is kinda weird, but if the syntax trees are the same then they're certainly equivalent semantically         isNop _ = False
src/Kempe/Inline.hs view
@@ -8,6 +8,7 @@ import qualified Data.IntMap        as IM import qualified Data.List.NonEmpty as NE import           Data.Maybe         (fromMaybe, mapMaybe)+import           Data.Semigroup     ((<>)) import           Data.Tuple.Extra   (third3) import           Kempe.AST import           Kempe.Name@@ -17,7 +18,7 @@ -- a given 'Name' type FnModuleMap c b = IM.IntMap (Maybe [Atom c b]) -inline :: Module a c b -> Module a c b+inline :: Declarations a c b -> Declarations a c b inline m = fmap inlineDecl m     where inlineDecl (FunDecl l n ty ty' as) = FunDecl l n ty ty' (inlineAtoms n as)           inlineDecl d                       = d@@ -44,7 +45,7 @@  -- | Given a module, make a map telling which top-level names are recursive or -- cannot be inlined-graphRecursiveMap :: Module a c b -> (Graph, Name b -> Vertex) -> IM.IntMap Bool+graphRecursiveMap :: Declarations a c b -> (Graph, Name b -> Vertex) -> IM.IntMap Bool graphRecursiveMap m (graph, nLookup) = IM.fromList $ mapMaybe fnRecursive m     where fnRecursive (FunDecl _ n@(Name _ (Unique i) _) _ _ as) | n `elem` namesInAtoms as = Just (i, True) -- if it calls iteself                                                                  | anyReachable n as = Just (i, True)@@ -55,18 +56,18 @@             any (\nA -> path graph (nLookup nA) (nLookup n)) (namesInAtoms as) -- TODO: lift let-binding (nLookup?)  -kempeGraph :: Module a c b -> (Graph, Vertex -> (KempeDecl a c b, Name b, [Name b]), Name b -> Vertex)+kempeGraph :: Declarations a c b -> (Graph, Vertex -> (KempeDecl a c b, Name b, [Name b]), Name b -> Vertex) kempeGraph = third3 (findVtx .) . graphFromEdges . kempePreGraph     where findVtx = fromMaybe (error "Internal error: bad name lookup!") -kempePreGraph :: Module a c b -> [(KempeDecl a c b, Name b, [Name b])]+kempePreGraph :: Declarations a c b -> [(KempeDecl a c b, Name b, [Name b])] kempePreGraph = mapMaybe kempeDeclToGraph     where kempeDeclToGraph :: KempeDecl a c b -> Maybe (KempeDecl a c b, Name b, [Name b])           kempeDeclToGraph d@(FunDecl _ n _ _ as)  = Just (d, n, foldMap namesInAtom as)           kempeDeclToGraph d@(ExtFnDecl _ n _ _ _) = Just (d, n, [])           kempeDeclToGraph _                       = Nothing -mkFnModuleMap :: Module a c b -> FnModuleMap c b+mkFnModuleMap :: Declarations a c b -> FnModuleMap c b mkFnModuleMap = IM.fromList . mapMaybe toInt where     toInt (FunDecl _ (Name _ (Unique i) _) _ _ as)  = Just (i, Just as)     toInt (ExtFnDecl _ (Name _ (Unique i) _) _ _ _) = Just (i, Nothing)
src/Kempe/Lexer.x view
@@ -4,8 +4,10 @@     {-# LANGUAGE OverloadedStrings #-}     {-# LANGUAGE StandaloneDeriving #-}     module Kempe.Lexer ( alexMonadScan+                       , alexInitUserState                        , runAlex                        , runAlexSt+                       , withAlexSt                        , lexKempe                        , AlexPosn (..)                        , Alex (..)@@ -25,6 +27,7 @@ import Data.Int (Int8) import qualified Data.IntMap as IM import qualified Data.Map as M+import Data.Semigroup ((<>)) import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8) import GHC.Generics (Generic)@@ -51,6 +54,8 @@  @foreign = \" $latin @follow_char* \" +@module_str = \" [^\"]+ \"+ tokens :-      <0> {@@ -119,6 +124,7 @@         False                    { mkBuiltin (BuiltinBoolLit False) }         dup                      { mkBuiltin BuiltinDup }         drop                     { mkBuiltin BuiltinDrop }+         swap                     { mkBuiltin BuiltinSwap }         xori                     { mkBuiltin BuiltinIntXor }         xoru                     { mkBuiltin BuiltinWordXor }@@ -135,12 +141,17 @@          @name                    { tok (\p s -> TokName p <$> newIdentAlex p (mkText s)) }         @tyname                  { tok (\p s -> TokTyName p <$> newIdentAlex p (mkText s)) }-        @foreign                 { tok (\p s -> alex $ TokForeign p s) }+        @foreign                 { tok (\p s -> alex $ TokForeign p (dropQuotes s)) } +        @module_str              { tok (\p s -> alex $ TokModuleStr p (dropQuotes s)) }+     }  { +dropQuotes :: BSL.ByteString -> BSL.ByteString+dropQuotes = BSL.init . BSL.tail+ readHex' :: (Eq a, Num a) => BSL.ByteString -> Alex a readHex' bs =     case readHex (ASCII.unpack bs) of@@ -166,6 +177,8 @@ instance Pretty AlexPosn where     pretty (AlexPn _ line col) = pretty line <> colon <> pretty col +deriving instance Ord AlexPosn+ deriving instance Generic AlexPosn  deriving instance NFData AlexPosn@@ -328,20 +341,22 @@              | TokInt8 { loc :: a, int8 :: Int8 }              | TokWord { loc :: a, word :: Natural }              | TokForeign { loc :: a, ident :: BSL.ByteString }+             | TokModuleStr { loc :: a, moduleFp :: BSL.ByteString }              | TokBuiltin { loc :: a, builtin :: Builtin }              deriving (Generic, NFData)  instance Pretty (Token a) where-    pretty EOF{}             = "(eof)"-    pretty (TokSym _ s)      = "symbol" <+> squotes (pretty s)-    pretty (TokName _ n)     = "identifier" <+> squotes (pretty n)-    pretty (TokTyName _ tn)  = "identifier" <+> squotes (pretty tn)-    pretty (TokKeyword _ kw) = "keyword" <+> squotes (pretty kw)-    pretty (TokInt _ i)      = pretty i-    pretty (TokWord _ n)     = pretty n <> "u"-    pretty (TokInt8 _ i)     = pretty i <> "i8"-    pretty (TokForeign _ fn) = dquotes (pretty $ mkText fn)-    pretty (TokBuiltin _ b)  = pretty b+    pretty EOF{}              = "(eof)"+    pretty (TokSym _ s)       = "symbol" <+> squotes (pretty s)+    pretty (TokName _ n)      = "identifier" <+> squotes (pretty n)+    pretty (TokTyName _ tn)   = "identifier" <+> squotes (pretty tn)+    pretty (TokKeyword _ kw)  = "keyword" <+> squotes (pretty kw)+    pretty (TokInt _ i)       = pretty i+    pretty (TokWord _ n)      = pretty n <> "u"+    pretty (TokInt8 _ i)      = pretty i <> "i8"+    pretty (TokForeign _ fn)  = dquotes (pretty $ mkText fn)+    pretty (TokModuleStr _ m) = dquotes (pretty $ mkText m)+    pretty (TokBuiltin _ b)   = pretty b  newIdentAlex :: AlexPosn -> T.Text -> Alex (Name AlexPosn) newIdentAlex pos t = do
+ src/Kempe/Module.hs view
@@ -0,0 +1,42 @@+-- | Pretty easy since doesn't need renaming.+--+-- Just thread lexer state through, remove duplicates.+module Kempe.Module ( parseProcess+                    ) where++import           Control.Exception          (Exception, throwIO)+import qualified Data.ByteString.Lazy       as BSL+import qualified Data.ByteString.Lazy.Char8 as ASCII+import qualified Data.Set                   as S+import           Data.Tuple.Extra           (fst3, third3)+import           Kempe.AST+import           Kempe.Lexer+import           Kempe.Parser+++parseProcess :: FilePath -> IO (Int, Declarations AlexPosn AlexPosn AlexPosn)+parseProcess fp = do+    (st, [], ds) <- loopFps [fp] alexInitUserState+    pure (fst3 st, {-# SCC "dedup" #-} dedup ds)++yeetIO :: Exception e => Either e a -> IO a+yeetIO = either throwIO pure++loopFps :: [FilePath] -> AlexUserState -> IO (AlexUserState, [FilePath], Declarations AlexPosn AlexPosn AlexPosn)+loopFps [] st = pure (st, [], [])+loopFps (fp:fps) st = do+    (st', Module is ds) <- parseStep fp st+    third3 (++ ds) <$> loopFps (fmap ASCII.unpack (reverse is) ++ fps) st'++parseStep :: FilePath -> AlexUserState -> IO (AlexUserState, Module AlexPosn AlexPosn AlexPosn)+parseStep fp st = do+    contents <- BSL.readFile fp+    yeetIO $ parseWithCtx contents st++dedup :: Ord a => [a] -> [a]+dedup = loop S.empty+    where loop _ [] = []+          loop acc (x:xs) =+            if S.member x acc+                then loop acc xs+                else x : loop (S.insert x acc) xs
src/Kempe/Monomorphize.hs view
@@ -24,11 +24,11 @@ import           Data.Foldable              (traverse_) import           Data.Function              (on) import           Data.Functor               (($>))-import           Data.Int                   (Int64) import qualified Data.IntMap                as IM-import           Data.List                  (find, groupBy, partition)+import           Data.List                  (elemIndex, find, groupBy, partition) import qualified Data.Map                   as M import           Data.Maybe                 (fromMaybe, mapMaybe)+import           Data.Semigroup             ((<>)) import qualified Data.Set                   as S import qualified Data.Text                  as T import           Data.Tuple                 (swap)@@ -80,7 +80,7 @@ -- a given 'Name' type ModuleMap a c b = IM.IntMap (KempeDecl a c b) -mkModuleMap :: Module a c b -> ModuleMap a c b+mkModuleMap :: Declarations a c b -> ModuleMap a c b mkModuleMap = IM.fromList . concatMap toInt where     toInt d@(FunDecl _ (Name _ (Unique i) _) _ _ _)   = [(i, d)]     toInt d@(ExtFnDecl _ (Name _ (Unique i) _) _ _ _) = [(i, d)]@@ -145,11 +145,11 @@ renameDecl (TyDecl l n vars ls)       = pure $ TyDecl l n vars ls  -- | Call 'closedModule' and perform any necessary renamings-flattenModule :: Module () (StackType ()) (StackType ()) -> MonoM (Module () (ConsAnn MonoStackType) (StackType ()))+flattenModule :: Declarations () (StackType ()) (StackType ()) -> MonoM (Declarations () (ConsAnn MonoStackType) (StackType ())) flattenModule = renameMonoM <=< closedModule  -- | To be called after 'closedModule'-renameMonoM :: Module () (StackType ()) (StackType ()) -> MonoM (Module () (ConsAnn MonoStackType) (StackType ()))+renameMonoM :: Declarations () (StackType ()) (StackType ()) -> MonoM (Declarations () (ConsAnn MonoStackType) (StackType ())) renameMonoM = traverse renameDecl  -- | Filter so that only the 'KempeDecl's necessary for exports are there, and@@ -158,7 +158,7 @@ -- This will throw an exception on ill-typed programs. -- -- The 'Module' returned will have to be renamed.-closedModule :: Module () (StackType ()) (StackType ()) -> MonoM (Module () (StackType ()) (StackType ()))+closedModule :: Declarations () (StackType ()) (StackType ()) -> MonoM (Declarations () (StackType ()) (StackType ())) closedModule m = addExports <$> do     { fn' <- traverse (uncurry specializeDecl . drop1) fnDecls     ; traverse_ insTyDecl $ nubOrd (snd3 <$> tyDecls)@@ -190,15 +190,31 @@ isTyVar TyVar{} = True isTyVar _       = False -sizeLeaf :: [KempeTy a] -> MonoM Int64-sizeLeaf tys =-    sizeStack <$> gets szEnv <*> pure (filter (not . isTyVar) tys)+extrNames :: KempeTy a -> Name a+extrNames (TyVar _ n) = n+extrNames _           = error "Internal error!" +sizeLeaf :: [Name a] -- ^ Type variables as declared+         -> [KempeTy a]+         -> MonoM Size+sizeLeaf fv tys = do+    { let (tvs, conc) = partition isTyVar tys+    ; pad <- sizeStack <$> gets szEnv <*> pure conc+    ; let tvPrecompose = fmap (forVar . extrNames) tvs+    ; let tvComposed = foldr compose (const pad) tvPrecompose+    ; pure tvComposed+    }+  where+    findIx x = fromMaybe (error "Internal error: can't find index of type variable.") $ elemIndex x fv+    forVar n =+        let i = findIx n+            in (!! i)+    compose sz sz' = \tys' -> sz tys' + sz' tys'+ insTyDecl :: KempeDecl a c b -> MonoM ()-insTyDecl (TyDecl _ (Name _ (Unique k) _) _ leaves) = do-    leafSizes <- traverse sizeLeaf (fmap snd leaves)-    -- this is kinda sketch because it takes max w/o tyvars-    let consSz = 1 + maximum leafSizes -- for the tag+insTyDecl (TyDecl _ (Name _ (Unique k) _) fv leaves) = do+    leafSizes <- traverse (sizeLeaf fv) (fmap snd leaves)+    let consSz = \tys -> 1 + maximum (($tys) <$> leafSizes) -- for the tag     modifying szEnvLens (IM.insert k consSz) insTyDecl _ = error "Shouldn't happen." @@ -210,7 +226,7 @@     where indexAt p xs = fst $ fromMaybe (error "Internal error.") $ find (\(_, x) -> p x) (zip [0..] xs)           getTag (Name _ u _) = indexAt (== u) preIxes           preIxes = fmap (unique . fst) preConstrs-          szType env (_, [o]) = size env o+          szType env (_, [o]) = size' env o           szType _ _          = error "Internal error: ill-typed constructor." mkTyDecl _ _ = error "Shouldn't happen." @@ -241,7 +257,7 @@     modifying fnEnvLens (M.insert (i, newStackType) j)     pure (Name t' j newStackType) -closure :: Ord b => (Module a b b, ModuleMap a b b) -> S.Set (Name b, b)+closure :: Ord b => (Declarations a b b, ModuleMap a b b) -> S.Set (Name b, b) closure (m, key) = loop roots S.empty     where roots = S.fromList (exports m)           loop ns avoid =@@ -272,10 +288,10 @@ namesInAtom WordLit{}                  = S.empty namesInAtom (Case _ as)                = foldMap namesInAtom (foldMap snd as) -- FIXME: patterns too -exports :: Module a c b -> [(Name b, b)]+exports :: Declarations a c b -> [(Name b, b)] exports = mapMaybe exportsDecl -exportsOnly :: Module a c b -> Module a c b+exportsOnly :: Declarations a c b -> Declarations a c b exportsOnly = mapMaybe getExport where     getExport d@Export{} = Just d     getExport _          = Nothing
src/Kempe/Name.hs view
@@ -8,6 +8,7 @@                   ) where  import           Control.DeepSeq (NFData (..))+import           Data.Semigroup  ((<>)) import qualified Data.Text       as T import           Kempe.Unique import           Prettyprinter   (Pretty (pretty))
src/Kempe/Parser.y view
@@ -4,6 +4,8 @@     {-# LANGUAGE OverloadedStrings #-}     module Kempe.Parser ( parse                         , parseWithMax+                        , parseWithCtx+                        , parseWithInitCtx                         , ParseError (..)                         ) where @@ -74,6 +76,7 @@     name { TokName _ $$ }     tyName { TokTyName  _ $$ }     foreignName { TokForeign _ $$ }+    moduleFile { TokModuleStr _ $$ }      intLit { $$@(TokInt _ _) }     wordLit { $$@(TokWord _ _) }@@ -86,6 +89,7 @@     foreign { TokKeyword $$ KwForeign }     cabi { TokKeyword $$ KwCabi }     kabi { TokKeyword $$ KwKabi }+    import { TokKeyword $$ KwImport }      dip { TokBuiltin $$ BuiltinDip }     boolLit { $$@(TokBuiltin _ (BuiltinBoolLit _)) }@@ -124,8 +128,14 @@     : lparen p rparen { $2 }  Module :: { Module AlexPosn AlexPosn AlexPosn }-       : many(Decl) { (reverse $1) }+       : many(Import) Declarations { Module (reverse $1) $2 } +Declarations :: { Declarations AlexPosn AlexPosn AlexPosn }+             : many(Decl) { (reverse $1) }++Import :: { BSL.ByteString }+       : import moduleFile { $2 }+ ABI :: { ABI }     : cabi { Cabi }     | kabi { Kabi }@@ -236,10 +246,22 @@ parse = fmap snd . parseWithMax  parseWithMax :: BSL.ByteString -> Either (ParseError AlexPosn) (Int, Module AlexPosn AlexPosn AlexPosn)-parseWithMax = fmap (first fst3) . runParse parseModule+parseWithMax = fmap (first fst3) . parseWithInitCtx +parseWithInitCtx :: BSL.ByteString -> Either (ParseError AlexPosn) (AlexUserState, Module AlexPosn AlexPosn AlexPosn)+parseWithInitCtx bsl = parseWithCtx bsl alexInitUserState++parseWithCtx :: BSL.ByteString -> AlexUserState -> Either (ParseError AlexPosn) (AlexUserState, Module AlexPosn AlexPosn AlexPosn)+parseWithCtx = parseWithInitSt parseModule+ runParse :: Parse a -> BSL.ByteString -> Either (ParseError AlexPosn) (AlexUserState, a) runParse parser str = liftErr $ runAlexSt str (runExceptT parser)++parseWithInitSt :: Parse a -> BSL.ByteString -> AlexUserState -> Either (ParseError AlexPosn) (AlexUserState, a)+parseWithInitSt parser str st = liftErr $ withAlexSt str st (runExceptT parser)+    where liftErr (Left err)            = Left (LexErr err)+          liftErr (Right (_, Left err)) = Left err+          liftErr (Right (i, Right x))  = Right (i, x)  liftErr :: Either String (b, Either (ParseError a) c) -> Either (ParseError a) (b, c) liftErr (Left err)            = Left (LexErr err)
src/Kempe/Pipeline.hs view
@@ -6,24 +6,28 @@ import           Control.Composition       ((.*)) import           Control.Exception         (throw) import           Data.Bifunctor            (first)+import           Data.Typeable             (Typeable) import           Kempe.AST import           Kempe.Asm.X86 import           Kempe.Asm.X86.ControlFlow import           Kempe.Asm.X86.Linear import           Kempe.Asm.X86.Liveness import           Kempe.Asm.X86.Type+import           Kempe.Check.Restrict import           Kempe.IR import           Kempe.IR.Opt import           Kempe.Shuttle -irGen :: Int -- ^ Thread uniques through-      -> Module a c b -> ([Stmt], WriteSt, SizeEnv)+irGen :: Typeable a+      => Int -- ^ Thread uniques through+      -> Declarations a c b -> ([Stmt], WriteSt, SizeEnv) irGen i m = adjEnv $ first optimize $ runTempM (writeModule env tAnnMod)-    where (tAnnMod, env) = either throw id $ monomorphize i m+    where (tAnnMod, env) = either throw id $ monomorphize i mOk+          mOk = maybe m throw (restrictConstructors m)           adjEnv (x, y) = (x, y, env) -x86Parsed :: Int -> Module a c b -> [X86 AbsReg ()]+x86Parsed :: Typeable a => Int -> Declarations a c b -> [X86 AbsReg ()] x86Parsed i m = let (ir, u, env) = irGen i m in irToX86 env u ir -x86Alloc :: Int -> Module a c b -> [X86 X86Reg ()]+x86Alloc :: Typeable a => Int -> Declarations a c b -> [X86 X86Reg ()] x86Alloc = allocRegs . reconstruct . mkControlFlow .* x86Parsed
src/Kempe/Shuttle.hs view
@@ -12,8 +12,8 @@ import           Kempe.TyAssign  inlineAssignFlatten :: Int-                    -> Module a c b-                    -> Either (Error ()) (Module () (ConsAnn MonoStackType) (StackType ()), (Int, SizeEnv))+                    -> Declarations a c b+                    -> Either (Error ()) (Declarations () (ConsAnn MonoStackType) (StackType ()), (Int, SizeEnv)) inlineAssignFlatten ctx m = do     -- check before inlining otherwise users would get weird errors     void $ do@@ -23,8 +23,8 @@     runMonoM i (flattenModule mTy)  monomorphize :: Int-             -> Module a c b-             -> Either (Error ()) (Module () (ConsAnn MonoStackType) MonoStackType, SizeEnv)+             -> Declarations a c b+             -> Either (Error ()) (Declarations () (ConsAnn MonoStackType) MonoStackType, SizeEnv) monomorphize ctx m = do     (flat, (_, env)) <- inlineAssignFlatten ctx m     let flatFn' = filter (not . isTyDecl) flat
src/Kempe/TyAssign.hs view
@@ -18,6 +18,7 @@ import qualified Data.IntMap                as IM import           Data.List                  (foldl') import           Data.List.NonEmpty         (NonEmpty (..))+import           Data.Semigroup             ((<>)) import qualified Data.Set                   as S import qualified Data.Text                  as T import           Data.Tuple.Extra           (fst3)@@ -97,39 +98,53 @@  type TypeM a = StateT (TyState a) (Either (Error a)) -onType :: (Int, KempeTy a) -> KempeTy a -> KempeTy a-onType _ ty'@TyBuiltin{} = ty'-onType _ ty'@TyNamed{}   = ty'-onType (k, ty) ty'@(TyVar _ (Name _ (Unique i) _)) | i == k = ty-                                                   | otherwise = ty'-onType (k, ty) (TyApp l ty' ty'') = TyApp l (onType (k, ty) ty') (onType (k, ty) ty'') -- I think this is right+type UnifyMap = IM.IntMap (KempeTy ()) -renameForward :: (Int, KempeTy a) -> [(KempeTy a, KempeTy a)] -> [(KempeTy a, KempeTy a)]-renameForward _ []                      = []-renameForward (k, ty) ((ty', ty''):tys) = (onType (k, ty) ty', onType (k, ty) ty'') : renameForward (k, ty) tys+inContext :: UnifyMap -> KempeTy () -> KempeTy ()+inContext um ty'@(TyVar _ (Name _ (Unique i) _)) =+    case IM.lookup i um of+        Just ty@TyVar{} -> inContext (IM.delete i um) ty -- prevent cyclic lookups+        Just ty         -> ty+        Nothing         -> ty'+inContext _ ty'@TyBuiltin{} = ty'+inContext _ ty'@TyNamed{} = ty'+inContext um (TyApp l ty ty') = TyApp l (inContext um ty) (inContext um ty') -unify :: [(KempeTy a, KempeTy a)] -> Either (Error ()) (IM.IntMap (KempeTy ()))-unify []                                                             = Right mempty-unify ((ty@(TyBuiltin _ b0), ty'@(TyBuiltin _ b1)):tys) | b0 == b1   = unify tys-                                                        | otherwise  = Left (UnificationFailed () (void ty) (void ty'))-unify ((ty@(TyNamed _ n0), ty'@(TyNamed _ n1)):tys) | n0 == n1       = unify tys+-- | Perform substitutions before handing off to 'unifyMatch'+unifyPrep :: UnifyMap+           -> [(KempeTy (), KempeTy ())]+           -> Either (Error ()) (IM.IntMap (KempeTy ()))+unifyPrep _ [] = Right mempty+unifyPrep um ((ty, ty'):tys) =+    let ty'' = inContext um ty+        ty''' = inContext um ty'+    in unifyMatch um $ (ty'', ty'''):tys++unifyMatch :: UnifyMap -> [(KempeTy (), KempeTy ())] -> Either (Error ()) (IM.IntMap (KempeTy ()))+unifyMatch _ []                                                             = Right mempty+unifyMatch um ((ty@(TyBuiltin _ b0), ty'@(TyBuiltin _ b1)):tys) | b0 == b1   = unifyPrep um tys+                                                                | otherwise  = Left (UnificationFailed () ty ty')+unifyMatch um ((ty@(TyNamed _ n0), ty'@(TyNamed _ n1)):tys) | n0 == n1       = unifyPrep um tys                                                     | otherwise      = Left (UnificationFailed () (void ty) (void ty'))-unify ((ty@(TyNamed _ _), TyVar  _ (Name _ (Unique k) _)):tys)       = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys) -- is this O(n^2) or something bad?-unify ((TyVar _ (Name _ (Unique k) _), ty@(TyNamed _ _)):tys)        = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys) -- FIXME: is renameForward enough?-unify ((ty@(TyBuiltin _ _), TyVar  _ (Name _ (Unique k) _)):tys)     = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys)-unify ((TyVar _ (Name _ (Unique k) _), ty@(TyBuiltin _ _)):tys)      = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys)-unify ((TyVar _ (Name _ (Unique k) _), ty@(TyVar _ _)):tys)          = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys)-unify ((ty@TyBuiltin{}, ty'@TyNamed{}):_)                            = Left (UnificationFailed () (void ty) (void ty'))-unify ((ty@TyNamed{}, ty'@TyBuiltin{}):_)                            = Left (UnificationFailed () (void ty) (void ty'))-unify ((ty@TyBuiltin{}, ty'@TyApp{}):_)                              = Left (UnificationFailed () (void ty) (void ty'))-unify ((ty@TyNamed{}, ty'@TyApp{}):_)                                = Left (UnificationFailed () (void ty) (void ty'))-unify ((ty@TyApp{}, ty'@TyBuiltin{}):_)                              = Left (UnificationFailed () (void ty) (void ty'))-unify ((TyVar _ (Name _ (Unique k) _), ty@TyApp{}):tys)              = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys)-unify ((ty@TyApp{}, TyVar  _ (Name _ (Unique k) _)):tys)             = IM.insert k (void ty) <$> unify (renameForward (k, ty) tys)-unify ((TyApp _ ty ty', TyApp _ ty'' ty'''):tys)                     = unify ((ty, ty'') : (ty', ty''') : tys) -- TODO: I think this is right?-unify ((ty@TyApp{}, ty'@TyNamed{}):_)                                = Left (UnificationFailed () (void ty) (void ty'))+unifyMatch um ((ty@(TyNamed _ _), TyVar  _ (Name _ (Unique k) _)):tys)       = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch um ((TyVar _ (Name _ (Unique k) _), ty@(TyNamed _ _)):tys)        = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch um ((ty@TyBuiltin{}, TyVar  _ (Name _ (Unique k) _)):tys)         = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch um ((TyVar _ (Name _ (Unique k) _), ty@(TyBuiltin _ _)):tys)      = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch um ((TyVar _ (Name _ (Unique k) _), ty@(TyVar _ _)):tys)          = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch _ ((ty@TyBuiltin{}, ty'@TyNamed{}):_)                             = Left (UnificationFailed () ty ty')+unifyMatch _ ((ty@TyNamed{}, ty'@TyBuiltin{}):_)                             = Left (UnificationFailed () ty ty')+unifyMatch _ ((ty@TyBuiltin{}, ty'@TyApp{}):_)                               = Left (UnificationFailed () ty ty')+unifyMatch _ ((ty@TyNamed{}, ty'@TyApp{}):_)                                 = Left (UnificationFailed () ty ty')+unifyMatch _ ((ty@TyApp{}, ty'@TyBuiltin{}):_)                               = Left (UnificationFailed () ty ty')+unifyMatch um ((TyVar _ (Name _ (Unique k) _), ty@TyApp{}):tys)              = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch um ((ty@TyApp{}, TyVar  _ (Name _ (Unique k) _)):tys)             = IM.insert k ty <$> unifyPrep (IM.insert k ty um) tys+unifyMatch um ((TyApp _ ty ty', TyApp _ ty'' ty'''):tys)                     = unifyMatch um ((ty, ty'') : (ty', ty''') : tys) -- TODO: I think this is right?+unifyMatch _ ((ty@TyApp{}, ty'@TyNamed{}):_)                                 = Left (UnificationFailed () (void ty) (void ty')) -unifyM :: S.Set (KempeTy a, KempeTy a) -> TypeM () (IM.IntMap (KempeTy ()))+unify :: [(KempeTy (), KempeTy ())] -> Either (Error ()) (IM.IntMap (KempeTy ()))+unify = unifyPrep IM.empty++unifyM :: S.Set (KempeTy (), KempeTy ()) -> TypeM () (IM.IntMap (KempeTy ())) unifyM s =     case {-# SCC "unify" #-} unify (S.toList s) of         Right x  -> pure x@@ -409,13 +424,13 @@ tyInsert ExtFnDecl{} = pure () -- TODO: kind-check tyInsert Export{} = pure () -tyModule :: Module a c b -> TypeM () ()+tyModule :: Declarations a c b -> TypeM () () tyModule m = traverse_ tyHeader m *> traverse_ tyInsert m -checkModule :: Module a c b -> TypeM () ()+checkModule :: Declarations a c b -> TypeM () () checkModule m = tyModule m <* (unifyM =<< gets constraints) -assignModule :: Module a c b -> TypeM () (Module () (StackType ()) (StackType ()))+assignModule :: Declarations a c b -> TypeM () (Declarations () (StackType ()) (StackType ())) assignModule m = {-# SCC "assignModule" #-} do     traverse_ tyHeader m     m' <- traverse assignDecl m
src/Prettyprinter/Ext.hs view
@@ -1,16 +1,29 @@ {-# LANGUAGE OverloadedStrings #-}  module Prettyprinter.Ext ( (<#>)+                         , (<##>)                          , prettyHex+                         , prettyLines+                         , sepDecls                          ) where  import           Numeric       (showHex) import           Prettyprinter  infixr 6 <#>+infixr 6 <##>  (<#>) :: Doc a -> Doc a -> Doc a (<#>) x y = x <> hardline <> y +(<##>) :: Doc a -> Doc a -> Doc a+(<##>) x y = x <> hardline <> hardline <> y+ prettyHex :: (Integral a, Show a) => a -> Doc ann prettyHex x = "0x" <> pretty (showHex x mempty)++prettyLines :: [Doc ann] -> Doc ann+prettyLines = concatWith (<#>)++sepDecls :: [Doc ann] -> Doc ann+sepDecls = concatWith (<##>)
+ test/Abi.hs view
@@ -0,0 +1,36 @@+-- | This is to ensure consistency in the ABI.+module Abi ( backendGolden+           ) where++import           Control.Composition       ((.*))+import qualified Data.Text.Lazy            as TL+import           Data.Text.Lazy.Encoding   (encodeUtf8)+import           Data.Typeable             (Typeable)+import           Kempe.AST+import           Kempe.File+import           Kempe.Module+import           Prettyprinter             (defaultLayoutOptions, layoutPretty)+import           Prettyprinter.Render.Text (renderLazy)+import           Test.Tasty+import           Test.Tasty.Golden         (goldenVsString)++backendGolden :: TestTree+backendGolden =+    testGroup "IR goldens"+        [ goldenIR "test/data/abi.kmp" "test/golden/abi.ir"+        , goldenIR "lib/gaussian.kmp" "test/golden/gaussian.ir"+        -- not for ABI, to test it imports the right thing (transitively)+        , goldenIR "test/data/diamond/a.kmp" "test/golden/a.ir"+        ]++dumpIRLazyText :: Typeable a => Int -> Declarations a c b -> TL.Text+dumpIRLazyText = renderLazy . layoutPretty defaultLayoutOptions .* dumpIR++goldenIR :: FilePath+         -> FilePath+         -> TestTree+goldenIR fp out =+    goldenVsString fp out $+        do+            res <- parseProcess fp+            pure $ encodeUtf8 $ uncurry dumpIRLazyText res
test/Backend.hs view
@@ -4,8 +4,8 @@ import           Control.DeepSeq           (deepseq) import           Kempe.Asm.X86.ControlFlow import           Kempe.Asm.X86.Liveness-import           Kempe.File import           Kempe.Inline+import           Kempe.Module import           Kempe.Monomorphize import           Kempe.Pipeline import           Kempe.Shuttle@@ -46,32 +46,32 @@  codegen :: FilePath -> TestTree codegen fp = testCase ("Generates code without throwing an exception (" ++ fp ++ ")") $ do-    parsed <- parsedFp fp+    parsed <- parseProcess fp     let code = uncurry x86Alloc parsed     assertBool "Doesn't fail" (code `deepseq` True)  liveness :: FilePath -> TestTree liveness fp = testCase ("Liveness analysis terminates (" ++ fp ++ ")") $ do-    parsed <- parsedFp fp+    parsed <- parseProcess fp     let x86 = uncurry x86Parsed parsed         cf = mkControlFlow x86     assertBool "Doesn't bottom" (reconstruct cf `deepseq` True)  controlFlowGraph :: FilePath -> TestTree controlFlowGraph fp = testCase ("Doesn't crash while creating control flow graph for " ++ fp) $ do-    parsed <- parsedFp fp+    parsed <- parseProcess fp     let x86 = uncurry x86Parsed parsed     assertBool "Worked without exception" (mkControlFlow x86 `deepseq` True)  x86NoYeet :: FilePath -> TestTree x86NoYeet fp = testCase ("Selects instructions for " ++ fp) $ do-    parsed <- parsedFp fp+    parsed <- parseProcess fp     let x86 = uncurry x86Parsed parsed     assertBool "Worked without exception" (x86 `deepseq` True)  irNoYeet :: FilePath -> TestTree irNoYeet fp = testCase ("Generates IR without throwing an exception (" ++ fp ++ ")") $ do-    (i, m) <- parsedFp fp+    (i, m) <- parseProcess fp     let (res, _, _) = irGen i m     assertBool "Worked without failure" (res `deepseq` True) @@ -80,7 +80,7 @@  inlineFile :: FilePath -> Assertion inlineFile fp = do-    (_, m) <- parsedFp fp+    (_, m) <- parseProcess fp     let res = inline m     assertBool "Doesn't bottom when inlining" (res `deepseq` True) @@ -95,7 +95,7 @@  pipelineWorks :: FilePath -> TestTree pipelineWorks fp = testCase ("Functions in " ++ fp ++ " can be specialized") $ do-    (maxU, m) <- parsedFp fp+    (maxU, m) <- parseProcess fp     let res = monomorphize maxU m     case res of         Left err -> assertFailure (show $ pretty err)
test/Spec.hs view
@@ -2,6 +2,7 @@  module Main (main) where +import           Abi import           Backend import           Parser import           Test.Tasty@@ -13,4 +14,5 @@         [ parserTests         , typeTests         , backendTests+        , backendGolden         ]
test/Type.hs view
@@ -7,6 +7,7 @@ import           Control.Exception (Exception, throwIO) import           Kempe.AST import           Kempe.File+import           Kempe.Module import           Kempe.TyAssign import           Prettyprinter     (pretty) import           Test.Tasty@@ -24,9 +25,13 @@         , tyInfer "lib/bool.kmp"         , tyInfer "examples/hamming.kmp"         , tyInfer "lib/gaussian.kmp"+        , tyInfer "test/data/transitive.kmp"+        , tyInfer "lib/tuple.kmp"         , badType "test/err/merge.kmp" "Type a_5 -- Int a_4 is not as general as type a_3 -- a_3 a_3"         , badType "test/err/kind.kmp" "Ill-kinded type: '(Maybe_1 Maybe_1)'. Note that type variables have kind \11089 in Kempe."         , badType "test/err/patternMatch.kmp" "Inexhaustive pattern match."+        , detectsWarn "test/err/stupid.kmp" "4:1 'rand_1' is defined more than once."+        , detectsWarn "test/err/questionable.kmp" "3:19 'Some_3' is defined more than once."         , testAssignment "test/data/ty.kmp"         , testAssignment "lib/either.kmp"         , testAssignment "prelude/fn.kmp"@@ -36,9 +41,9 @@ yeetIO :: Exception e => Either e a -> IO a yeetIO = either throwIO pure -assignTypes :: FilePath -> IO (Module () (StackType ()) (StackType ()), Int)+assignTypes :: FilePath -> IO (Declarations () (StackType ()) (StackType ()), Int) assignTypes fp = do-    (maxU, m) <- parsedFp fp+    (maxU, m) <- parseProcess fp     yeetIO $ runTypeM maxU (assignModule m)  testAssignment :: FilePath -> TestTree@@ -52,6 +57,13 @@     case res of         Left err -> assertFailure (show $ pretty err)         Right{}  -> assertBool "Doesn't fail type-checking" True++detectsWarn :: FilePath -> String -> TestTree+detectsWarn fp msg = testCase ("Warns (" ++ fp ++ ")") $ do+    res <- warnFile fp+    case res of+        Just err -> show (pretty err) @?= msg+        Nothing  -> assertFailure "Failed to warn!"  badType :: FilePath -> String -> TestTree badType fp msg = testCase ("Detects error (" ++ fp ++ ")") $ do
+ test/data/abi.kmp view
@@ -0,0 +1,10 @@+type Param a b c+    { C a b b+    | D a b c+    }++; this should have 7 bytes of padding before the D, so as to match a C constructor+mkConcrete : -- (((Param Int8) Int) Int8)+      =: [ 0i8 0 0i8 D ]++%foreign kabi mkConcrete
test/data/multiConstruct.kmp view
@@ -1,6 +1,5 @@-type Either a b { Left a | Right b }--type Maybe a { Just a | Nothing }+import "lib/maybe.kmp"+import "lib/either.kmp"  mkJustRight : Int -- ((Either Int) (Maybe Int))             =: [ Just Right ]
test/data/mutual.kmp view
@@ -1,10 +1,4 @@-not : Bool -- Bool-    =: [-    { case-        | True -> False-        | _    -> True-    }-]+import "lib/bool.kmp"  odd : Int -- Bool     =: [ dup 0 =
+ test/data/transitive.kmp view
@@ -0,0 +1,6 @@+import "lib/tuple.kmp"++enTuple : Int Int -- ((Pair Int) Int)+        =: [ Pair ]++%foreign kabi enTuple
+ test/err/kind.kmp view
@@ -0,0 +1,4 @@+type Maybe a { Just a | Nothing }++poorlyKinded : (Maybe Maybe) --+             =: [ drop ]
+ test/err/merge.kmp view
@@ -0,0 +1,2 @@+dup0 : a -- a a+     =: [ dip(3) ]
+ test/err/patternMatch.kmp view
@@ -0,0 +1,6 @@+not : Bool -- Bool+    =: [+    { case+        | True  -> False+    }+]
+ test/err/questionable.kmp view
@@ -0,0 +1,3 @@+type Option a { Some a | None }++type Optional a { Some a | None }
+ test/err/stupid.kmp view
@@ -0,0 +1,5 @@+rand : -- Int+     =: [ 3 ]++rand : -- Int+     =: $cfun"rand"
+ test/examples/bool.kmp view
@@ -0,0 +1,19 @@+not : Bool -- Bool+    =: [+    { case+        | True  -> False+        | False -> True+    }+]++eq : Bool Bool -- Bool+   =: [ xor not ]++nand : Bool Bool -- Bool+     =: [ & not ]++nor : Bool Bool -- Bool+    =: [ || not ]++%foreign cabi not+%foreign cabi eq
+ test/examples/hamming.kmp view
@@ -0,0 +1,4 @@+hamming : Word Word -- Int+        =: [ xoru popcount ]++%foreign cabi hamming
+ test/examples/splitmix.kmp view
@@ -0,0 +1,11 @@+next : Word -- Word Word+     =: [ 0x9e3779b97f4a7c15u +~ dup+          dup 30i8 >>~ xoru 0xbf58476d1ce4e5b9u *~+          dup 27i8 >>~ xoru 0x94d049bb133111ebu *~+          dup 31i8 >>~ xoru+        ]++from_seed : Word -- Word+          =: [ next dip(drop) ]++%foreign cabi from_seed
+ test/golden/a.ir view
@@ -0,0 +1,19 @@++kmp1:+(movmem (reg datapointer) (int 17))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (reg datapointer) (int 1))+(movtemp t_1 (mem [8] (reg datapointer)))+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_2 (mem [8] (reg datapointer)))+(movmem (reg datapointer) (+ (reg t_2) (reg t_1)))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (reg datapointer) (int 2))+(movtemp t_3 (mem [8] (reg datapointer)))+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_4 (mem [8] (reg datapointer)))+(movmem (reg datapointer) (* (reg t_4) (reg t_3)))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(ret)++export forExport { -- Int} kmp1
+ test/golden/abi.ir view
@@ -0,0 +1,13 @@++kmp1:+(movmem (reg datapointer) (int8 0))+(movtemp datapointer (+ (reg datapointer) (int 1)))+(movmem (reg datapointer) (int 0))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (reg datapointer) (int8 0))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (reg datapointer) (tag 0x1))+(movtemp datapointer (+ (reg datapointer) (int 1)))+(ret)++export mkConcrete { -- (((Param_1 Int8) Int) Int8)} kmp1
+ test/golden/bool.out view
@@ -0,0 +1,3 @@+0+1+0
+ test/golden/factorial.out view
@@ -0,0 +1,2 @@+6+6
+ test/golden/gaussian.ir view
@@ -0,0 +1,76 @@++kmp1:+(movtemp datapointer (- (reg datapointer) (int 17)))+(mjump (=b (mem [1] (+ (reg datapointer) (int 0))) (tag 0x0)) kmp4)++kmp4:+(j kmp5)++kmp5:+(ret)++kmp2:+(movtemp datapointer (- (reg datapointer) (int 17)))+(call kmp1)+(movmem (- (reg datapointer) (int 0)) (mem [1] (+ (reg datapointer) (int 17))))+(movmem (+ (reg datapointer) (int 1)) (mem [1] (+ (reg datapointer) (int 18))))+(movmem (+ (reg datapointer) (int 2)) (mem [1] (+ (reg datapointer) (int 19))))+(movmem (+ (reg datapointer) (int 3)) (mem [1] (+ (reg datapointer) (int 20))))+(movmem (+ (reg datapointer) (int 4)) (mem [1] (+ (reg datapointer) (int 21))))+(movmem (+ (reg datapointer) (int 5)) (mem [1] (+ (reg datapointer) (int 22))))+(movmem (+ (reg datapointer) (int 6)) (mem [1] (+ (reg datapointer) (int 23))))+(movmem (+ (reg datapointer) (int 7)) (mem [1] (+ (reg datapointer) (int 24))))+(movmem (+ (reg datapointer) (int 8)) (mem [1] (+ (reg datapointer) (int 25))))+(movmem (+ (reg datapointer) (int 9)) (mem [1] (+ (reg datapointer) (int 26))))+(movmem (+ (reg datapointer) (int 10)) (mem [1] (+ (reg datapointer) (int 27))))+(movmem (+ (reg datapointer) (int 11)) (mem [1] (+ (reg datapointer) (int 28))))+(movmem (+ (reg datapointer) (int 12)) (mem [1] (+ (reg datapointer) (int 29))))+(movmem (+ (reg datapointer) (int 13)) (mem [1] (+ (reg datapointer) (int 30))))+(movmem (+ (reg datapointer) (int 14)) (mem [1] (+ (reg datapointer) (int 31))))+(movmem (+ (reg datapointer) (int 15)) (mem [1] (+ (reg datapointer) (int 32))))+(movmem (+ (reg datapointer) (int 16)) (mem [1] (+ (reg datapointer) (int 33))))+(mjump (=b (mem [1] (+ (reg datapointer) (int 0))) (tag 0x0)) kmp6)++kmp6:+(j kmp7)++kmp7:+(movmem (- (reg datapointer) (int 0)) (mem [8] (- (reg datapointer) (int 24))))+(movmem (- (reg datapointer) (int 24)) (mem [8] (- (reg datapointer) (int 16))))+(movmem (- (reg datapointer) (int 16)) (mem [8] (- (reg datapointer) (int 0))))+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_1 (mem [8] (reg datapointer)))+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_2 (mem [8] (reg datapointer)))+(movmem (reg datapointer) (+ (reg t_2) (reg t_1)))+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_3 (mem [8] (reg datapointer)))+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_4 (mem [8] (reg datapointer)))+(movmem (reg datapointer) (+ (reg t_4) (reg t_3)))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (- (reg datapointer) (int 0)) (mem [8] (+ (reg datapointer) (int 8))))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (reg datapointer) (tag 0x0))+(movtemp datapointer (+ (reg datapointer) (int 1)))+(ret)++kmp3:+(movtemp datapointer (- (reg datapointer) (int 17)))+(mjump (=b (mem [1] (+ (reg datapointer) (int 0))) (tag 0x0)) kmp8)++kmp8:+(j kmp9)++kmp9:+(movtemp datapointer (- (reg datapointer) (int 8)))+(movtemp t_5 (mem [8] (reg datapointer)))+(movmem (reg datapointer) (~ (reg t_5)))+(movtemp datapointer (+ (reg datapointer) (int 8)))+(movmem (reg datapointer) (tag 0x0))+(movtemp datapointer (+ (reg datapointer) (int 1)))+(ret)++export add {Gaussian_1 Gaussian_1 -- Gaussian_1} kmp2++export conjugate {Gaussian_1 -- Gaussian_1} kmp3
+ test/golden/hamming.out view
@@ -0,0 +1,1 @@+2
+ test/golden/numbertheory.out view
@@ -0,0 +1,3 @@+1+0+7
+ test/golden/splitmix.out view
@@ -0,0 +1,1 @@+3631356771
+ test/harness/bool.c view
@@ -0,0 +1,12 @@+#include <stdbool.h>+#include <stdio.h>++extern bool not(bool);+extern bool eq(bool, bool);++int main(int argc, char *argv[]) {+    printf("%d\n", not(true));+    printf("%d\n", not(false));+    printf("%d", eq(true, false));+}+
+ test/harness/factorial.c view
@@ -0,0 +1,9 @@+#include <stdio.h>++extern int fac_tailrec(int);+extern int fac(int);++int main(int argc, char *argv[]) {+    printf("%d\n", fac_tailrec(3));+    printf("%d", fac(3));+}
+ test/harness/hamming.c view
@@ -0,0 +1,8 @@+#include <stdint.h>+#include <stdio.h>++extern int hamming(uint64_t, uint64_t);++int main(int argc, char *argv[]) {+    printf("%d", hamming(5, 3));+}
+ test/harness/numbertheory.c view
@@ -0,0 +1,11 @@+#include <stdbool.h>+#include <stdio.h>++extern int k_gcd(int, int);+extern bool is_prime(int);++int main(int argc, char *argv[]) {+    printf("%d\n", is_prime(37));+    printf("%d\n", is_prime(36));+    printf("%d", k_gcd(21, 35));+}
+ test/harness/splitmix.c view
@@ -0,0 +1,8 @@+#include <stdint.h>+#include <stdio.h>++extern uint64_t from_seed(uint64_t);++int main(int argc, char *argv[]) {+    printf("%u", (unsigned int) from_seed(3012512025));+}