renamed stuff
This commit is contained in:
parent
3f618e77f9
commit
ce3971cf75
9 changed files with 414 additions and 409 deletions
|
|
@ -24,7 +24,7 @@ Bind. Bind ::= LIdent [LIdent] "=" Exp ;
|
|||
TLit. Type2 ::= UIdent ;
|
||||
TVar. Type2 ::= TVar ;
|
||||
TAll. Type1 ::= "forall" TVar "." Type ;
|
||||
TIndexed. Type1 ::= Indexed ;
|
||||
TData. Type1 ::= UIdent "(" [Type] ")" ;
|
||||
internal TEVar. Type1 ::= TEVar ;
|
||||
TFun. Type ::= Type1 "->" Type ;
|
||||
|
||||
|
|
@ -37,9 +37,7 @@ internal MkTEVar. TEVar ::= LIdent ;
|
|||
|
||||
Constructor. Constructor ::= UIdent ":" Type ;
|
||||
|
||||
Indexed. Indexed ::= UIdent "(" [Type] ")" ;
|
||||
|
||||
Data. Data ::= "data" Indexed "where" "{" [Constructor] "}" ;
|
||||
Data. Data ::= "data" Type "where" "{" [Constructor] "}" ;
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- * EXPRESSIONS
|
||||
|
|
|
|||
|
|
@ -1,22 +1,9 @@
|
|||
{-# LANGUAGE LambdaCase #-}
|
||||
{-# LANGUAGE LambdaCase #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
|
||||
module Codegen.Codegen (generateCode) where
|
||||
module Codegen.Codegen where
|
||||
|
||||
import Auxiliary (snoc)
|
||||
import Codegen.LlvmIr as LIR
|
||||
import Control.Applicative ((<|>))
|
||||
import Control.Monad.State (StateT, execStateT, foldM_,
|
||||
gets, modify)
|
||||
import qualified Data.Bifunctor as BI
|
||||
import Data.Coerce (coerce)
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Map as Map
|
||||
import Data.Maybe (fromJust, fromMaybe)
|
||||
import Data.Tuple.Extra (dupe, first, second)
|
||||
import qualified Grammar.Abs as GA
|
||||
import Grammar.ErrM (Err)
|
||||
import Monomorphizer.MonomorphizerIr as MIR
|
||||
-- module Codegen.Codegen (generateCode) where
|
||||
|
||||
-- | The record used as the code generator state
|
||||
data CodeGenerator = CodeGenerator
|
||||
|
|
@ -27,42 +14,45 @@ data CodeGenerator = CodeGenerator
|
|||
, labelCount :: Integer
|
||||
}
|
||||
|
||||
-- | A state type synonym
|
||||
type CompilerState a = StateT CodeGenerator Err a
|
||||
---- | The record used as the code generator state
|
||||
-- data CodeGenerator = CodeGenerator
|
||||
-- { instructions :: [LLVMIr]
|
||||
-- , functions :: Map MIR.Id FunctionInfo
|
||||
-- , constructors :: Map Ident ConstructorInfo
|
||||
-- , variableCount :: Integer
|
||||
-- , labelCount :: Integer
|
||||
-- }
|
||||
|
||||
data FunctionInfo = FunctionInfo
|
||||
{ numArgs :: Int
|
||||
, arguments :: [Id]
|
||||
}
|
||||
deriving (Show)
|
||||
data ConstructorInfo = ConstructorInfo
|
||||
{ numArgsCI :: Int
|
||||
, argumentsCI :: [Id]
|
||||
, numCI :: Integer
|
||||
}
|
||||
deriving (Show)
|
||||
---- | A state type synonym
|
||||
-- type CompilerState a = StateT CodeGenerator Err a
|
||||
|
||||
-- | Adds a instruction to the CodeGenerator state
|
||||
emit :: LLVMIr -> CompilerState ()
|
||||
emit l = modify $ \t -> t{instructions = Auxiliary.snoc l $ instructions t}
|
||||
-- data FunctionInfo = FunctionInfo
|
||||
-- { numArgs :: Int
|
||||
-- , arguments :: [Id]
|
||||
-- }
|
||||
-- deriving (Show)
|
||||
-- data ConstructorInfo = ConstructorInfo
|
||||
-- { numArgsCI :: Int
|
||||
-- , argumentsCI :: [Id]
|
||||
-- , numCI :: Integer
|
||||
-- }
|
||||
-- deriving (Show)
|
||||
|
||||
-- | Increases the variable counter in the CodeGenerator state
|
||||
increaseVarCount :: CompilerState ()
|
||||
increaseVarCount = modify $ \t -> t{variableCount = variableCount t + 1}
|
||||
---- | Adds a instruction to the CodeGenerator state
|
||||
-- emit :: LLVMIr -> CompilerState ()
|
||||
-- emit l = modify $ \t -> t{instructions = Auxiliary.snoc l $ instructions t}
|
||||
|
||||
-- | Returns the variable count from the CodeGenerator state
|
||||
getVarCount :: CompilerState Integer
|
||||
getVarCount = gets variableCount
|
||||
---- | Increases the variable counter in the CodeGenerator state
|
||||
-- increaseVarCount :: CompilerState ()
|
||||
-- increaseVarCount = modify $ \t -> t{variableCount = variableCount t + 1}
|
||||
|
||||
-- | Increases the variable count and returns it from the CodeGenerator state
|
||||
getNewVar :: CompilerState GA.Ident
|
||||
getNewVar = (GA.Ident . show) <$> (increaseVarCount >> getVarCount)
|
||||
---- | Returns the variable count from the CodeGenerator state
|
||||
-- getVarCount :: CompilerState Integer
|
||||
-- getVarCount = gets variableCount
|
||||
|
||||
-- | Increses the label count and returns a label from the CodeGenerator state
|
||||
getNewLabel :: CompilerState Integer
|
||||
getNewLabel = do
|
||||
modify (\t -> t{labelCount = labelCount t + 1})
|
||||
gets labelCount
|
||||
---- | Increases the variable count and returns it from the CodeGenerator state
|
||||
-- getNewVar :: CompilerState GA.Ident
|
||||
-- getNewVar = (GA.Ident . show) <$> (increaseVarCount >> getVarCount)
|
||||
|
||||
{- | Produces a map of functions infos from a list of binds,
|
||||
which contains useful data for code generation.
|
||||
|
|
@ -87,8 +77,28 @@ getFunctions bs = Map.fromList $ go bs
|
|||
cons
|
||||
<> go xs
|
||||
|
||||
createArgs :: [MIR.Type] -> [Id]
|
||||
createArgs xs = fst $ foldl (\(acc, l) t -> (acc ++ [(GA.Ident ("arg_" <> show l), t)], l + 1)) ([], 0) xs
|
||||
-- {- | Produces a map of functions infos from a list of binds,
|
||||
-- which contains useful data for code generation.
|
||||
---}
|
||||
-- getFunctions :: [MIR.Def] -> Map Id FunctionInfo
|
||||
-- getFunctions bs = Map.fromList $ go bs
|
||||
-- where
|
||||
-- go [] = []
|
||||
-- go (MIR.DBind (MIR.Bind id args _) : xs) =
|
||||
-- (id, FunctionInfo{numArgs = length args, arguments = args})
|
||||
-- : go xs
|
||||
-- go (MIR.DData (MIR.Constructor n cons) : xs) = undefined
|
||||
-- {-do map
|
||||
-- ( \(Constructor id xs) ->
|
||||
-- ( (id, MIR.TLit n)
|
||||
-- , FunctionInfo
|
||||
-- { numArgs = length xs
|
||||
-- , arguments = createArgs xs
|
||||
-- }
|
||||
-- )
|
||||
-- )
|
||||
-- cons
|
||||
-- <> go xs-}
|
||||
|
||||
{- | Produces a map of functions infos from a list of binds,
|
||||
which contains useful data for code generation.
|
||||
|
|
@ -119,66 +129,53 @@ getConstructors bs = Map.fromList $ go bs
|
|||
<> go xs
|
||||
go (_ : xs) = go xs
|
||||
|
||||
initCodeGenerator :: [MIR.Def] -> CodeGenerator
|
||||
initCodeGenerator scs =
|
||||
CodeGenerator
|
||||
{ instructions = defaultStart
|
||||
, functions = getFunctions scs
|
||||
, constructors = getConstructors scs
|
||||
, variableCount = 0
|
||||
, labelCount = 0
|
||||
}
|
||||
-- {- | Produces a map of functions infos from a list of binds,
|
||||
-- which contains useful data for code generation.
|
||||
---}
|
||||
-- getConstructors :: [MIR.Def] -> Map Ident ConstructorInfo
|
||||
-- getConstructors bs = Map.fromList $ go bs
|
||||
-- where
|
||||
-- go [] = []
|
||||
-- go (MIR.DData (MIR.Constructor n cons) : xs) = undefined
|
||||
-- {-do
|
||||
-- fst
|
||||
-- ( foldl
|
||||
-- ( \(acc, i) (GA.Constructor (GA.Ident id) xs) ->
|
||||
-- ( ( (GA.Ident (n <> "_" <> id), MIR.TLit (GA.Ident n))
|
||||
-- , ConstructorInfo
|
||||
-- { numArgsCI = length xs
|
||||
-- , argumentsCI = createArgs xs
|
||||
-- , numCI = i
|
||||
-- }
|
||||
-- )
|
||||
-- : acc
|
||||
-- , i + 1
|
||||
-- )
|
||||
-- )
|
||||
-- ([], 0)
|
||||
-- cons
|
||||
-- )
|
||||
-- <> go xs-}
|
||||
-- go (_ : xs) = go xs
|
||||
|
||||
{-
|
||||
run :: Err String -> IO ()
|
||||
run s = do
|
||||
let s' = case s of
|
||||
Right s -> s
|
||||
Left _ -> error "yo"
|
||||
writeFile "output/llvm.ll" s'
|
||||
putStrLn . trim =<< readCreateProcess (shell "lli") s'
|
||||
-- initCodeGenerator :: [MIR.Def] -> CodeGenerator
|
||||
-- initCodeGenerator scs =
|
||||
-- CodeGenerator
|
||||
-- { instructions = defaultStart
|
||||
-- , functions = getFunctions scs
|
||||
-- , constructors = getConstructors scs
|
||||
-- , variableCount = 0
|
||||
-- , labelCount = 0
|
||||
-- }
|
||||
|
||||
test :: Integer -> Program
|
||||
test v =
|
||||
Program
|
||||
[ DataType
|
||||
(GA.Ident "Craig")
|
||||
[ Constructor (GA.Ident "Bob") [MIR.Type (GA.Ident "_Int")]
|
||||
, Constructor (GA.Ident "Betty") [MIR.Type (GA.Ident "_Int")]
|
||||
]
|
||||
, DataType
|
||||
(GA.Ident "Alice")
|
||||
[ Constructor (GA.Ident "Eve") [MIR.Type (GA.Ident "_Int")] -- ,
|
||||
-- (GA.Ident "Alice", [TInt, TInt])
|
||||
]
|
||||
, Bind (GA.Ident "fibonacci", MIR.Type (GA.Ident "_Int")) [(GA.Ident "x", MIR.Type (GA.Ident "_Int"))] (EId ("x", MIR.Type (GA.Ident "Craig")), MIR.Type (GA.Ident "Craig"))
|
||||
, Bind (GA.Ident "main", MIR.Type (GA.Ident "_Int")) []
|
||||
-- (EApp (MIR.Type (GA.Ident "Craig")) (EId (GA.Ident "Craig_Bob", MIR.Type (GA.Ident "Craig")), MIR.Type (GA.Ident "Craig")) (ELit (LInt v), MIR.Type (GA.Ident "_Int")), MIR.Type (GA.Ident "Craig"))-- (EInt 92)
|
||||
$
|
||||
eCaseInt
|
||||
(EApp (MIR.TLit (GA.Ident "Craig")) (EId (GA.Ident "Craig_Bob", MIR.TLit (GA.Ident "Craig")), MIR.TLit (GA.Ident "Craig")) (ELit (LInt v), MIR.Type (GA.Ident "_Int")), MIR.Type (GA.Ident "Craig"))
|
||||
[ injectionCons "Craig_Bob" "Craig" [CIdent (GA.Ident "x")] (EId (GA.Ident "x", MIR.Type (GA.Ident "_Int")), MIR.Type (GA.Ident "_Int"))
|
||||
, injectionCons "Craig_Betty" "Craig" [CLit (LInt 5)] (int 2)
|
||||
, Injection (CIdent (GA.Ident "z")) (int 3)
|
||||
, -- , injectionInt 5 (int 6)
|
||||
injectionCatchAll (int 10)
|
||||
]
|
||||
]
|
||||
where
|
||||
injectionCons x y xs = Injection (CCons (GA.Ident x, MIR.Type (GA.Ident y)) xs)
|
||||
injectionInt x = Injection (CLit (LInt x))
|
||||
injectionCatchAll = Injection CatchAll
|
||||
eCaseInt x xs = (ECase (MIR.TLit (MIR.Ident "_Int")) x xs, MIR.TLit (MIR.Ident "_Int"))
|
||||
int x = (ELit (LInt x), MIR.TLit (MIR.Ident "_Int"))
|
||||
-}
|
||||
{- | Compiles an AST and produces a LLVM Ir string.
|
||||
An easy way to actually "compile" this output is to
|
||||
Simply pipe it to LLI
|
||||
-}
|
||||
generateCode :: MIR.Program -> Err String
|
||||
generateCode (MIR.Program scs) = do
|
||||
let codegen = initCodeGenerator scs
|
||||
llvmIrToString . instructions <$> execStateT (compileScs scs) codegen
|
||||
-- {-
|
||||
-- run :: Err String -> IO ()
|
||||
-- run s = do
|
||||
-- let s' = case s of
|
||||
-- Right s -> s
|
||||
-- Left _ -> error "yo"
|
||||
-- writeFile "output/llvm.ll" s'
|
||||
-- putStrLn . trim =<< readCreateProcess (shell "lli") s'
|
||||
|
||||
compileScs :: [MIR.Def] -> CompilerState ()
|
||||
compileScs [] = do
|
||||
|
|
@ -270,50 +267,50 @@ compileScs (MIR.DData (MIR.Constructor (GA.UIdent outer_id) ts) : xs) = do
|
|||
types
|
||||
compileScs xs
|
||||
|
||||
mainContent :: LLVMValue -> [LLVMIr]
|
||||
mainContent var =
|
||||
[ UnsafeRaw $
|
||||
-- "%2 = alloca %Craig\n" <>
|
||||
-- " store %Craig %1, ptr %2\n" <>
|
||||
-- " %3 = bitcast %Craig* %2 to i72*\n" <>
|
||||
-- " %4 = load i72, ptr %3\n" <>
|
||||
-- " call i32 (ptr, ...) @printf(ptr noundef @.str, i72 noundef %4)\n"
|
||||
"call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef " <> toIr var <> ")\n"
|
||||
, -- , SetVariable (GA.Ident "p") (Icmp LLEq I64 (VInteger 2) (VInteger 2))
|
||||
-- , BrCond (VIdent (GA.Ident "p")) (GA.Ident "b_1") (GA.Ident "b_2")
|
||||
-- , Label (GA.Ident "b_1")
|
||||
-- , UnsafeRaw
|
||||
-- "call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef 1)\n"
|
||||
-- , Br (GA.Ident "end")
|
||||
-- , Label (GA.Ident "b_2")
|
||||
-- , UnsafeRaw
|
||||
-- "call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef 2)\n"
|
||||
-- , Br (GA.Ident "end")
|
||||
-- , Label (GA.Ident "end")
|
||||
Ret I64 (VInteger 0)
|
||||
]
|
||||
-- mainContent :: LLVMValue -> [LLVMIr]
|
||||
-- mainContent var =
|
||||
-- [ UnsafeRaw $
|
||||
-- -- "%2 = alloca %Craig\n" <>
|
||||
-- -- " store %Craig %1, ptr %2\n" <>
|
||||
-- -- " %3 = bitcast %Craig* %2 to i72*\n" <>
|
||||
-- -- " %4 = load i72, ptr %3\n" <>
|
||||
-- -- " call i32 (ptr, ...) @printf(ptr noundef @.str, i72 noundef %4)\n"
|
||||
-- "call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef " <> toIr var <> ")\n"
|
||||
-- , -- , SetVariable (GA.Ident "p") (Icmp LLEq I64 (VInteger 2) (VInteger 2))
|
||||
-- -- , BrCond (VIdent (GA.Ident "p")) (GA.Ident "b_1") (GA.Ident "b_2")
|
||||
-- -- , Label (GA.Ident "b_1")
|
||||
-- -- , UnsafeRaw
|
||||
-- -- "call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef 1)\n"
|
||||
-- -- , Br (GA.Ident "end")
|
||||
-- -- , Label (GA.Ident "b_2")
|
||||
-- -- , UnsafeRaw
|
||||
-- -- "call i32 (ptr, ...) @printf(ptr noundef @.str, i64 noundef 2)\n"
|
||||
-- -- , Br (GA.Ident "end")
|
||||
-- -- , Label (GA.Ident "end")
|
||||
-- Ret I64 (VInteger 0)
|
||||
-- ]
|
||||
|
||||
defaultStart :: [LLVMIr]
|
||||
defaultStart =
|
||||
[ UnsafeRaw "target triple = \"x86_64-pc-linux-gnu\"\n"
|
||||
, UnsafeRaw "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
|
||||
, UnsafeRaw "@.str = private unnamed_addr constant [3 x i8] c\"%x\n\", align 1\n"
|
||||
, UnsafeRaw "declare i32 @printf(ptr noalias nocapture, ...)\n"
|
||||
]
|
||||
-- defaultStart :: [LLVMIr]
|
||||
-- defaultStart =
|
||||
-- [ UnsafeRaw "target triple = \"x86_64-pc-linux-gnu\"\n"
|
||||
-- , UnsafeRaw "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"
|
||||
-- , UnsafeRaw "@.str = private unnamed_addr constant [3 x i8] c\"%x\n\", align 1\n"
|
||||
-- , UnsafeRaw "declare i32 @printf(ptr noalias nocapture, ...)\n"
|
||||
-- ]
|
||||
|
||||
compileExp :: ExpT -> CompilerState ()
|
||||
compileExp (MIR.ELit lit,t) = emitLit lit
|
||||
compileExp (MIR.EAdd e1 e2,t) = emitAdd t e1 e2
|
||||
-- compileExp (ESub t e1 e2) = emitSub t e1 e2
|
||||
compileExp (MIR.EId name,t) = emitIdent name
|
||||
compileExp (MIR.EApp e1 e2,t) = emitApp t e1 e2
|
||||
-- compileExp (EAbs t ti e) = emitAbs t ti e
|
||||
compileExp (MIR.ELet binds e,t) = undefined -- emitLet binds (fst e)
|
||||
compileExp (MIR.ECase e cs,t) = emitECased t e (map (t,) cs)
|
||||
-- compileExp :: ExpT -> CompilerState ()
|
||||
-- compileExp (MIR.ELit lit,t) = emitLit lit
|
||||
-- compileExp (MIR.EAdd e1 e2,t) = emitAdd t e1 e2
|
||||
---- compileExp (ESub t e1 e2) = emitSub t e1 e2
|
||||
-- compileExp (MIR.EId name,t) = emitIdent name
|
||||
-- compileExp (MIR.EApp e1 e2,t) = emitApp t e1 e2
|
||||
---- compileExp (EAbs t ti e) = emitAbs t ti e
|
||||
-- compileExp (MIR.ELet binds e,t) = undefined -- emitLet binds (fst e)
|
||||
-- compileExp (MIR.ECase e cs,t) = emitECased t e (map (t,) cs)
|
||||
|
||||
-- go (EMul e1 e2) = emitMul e1 e2
|
||||
-- go (EDiv e1 e2) = emitDiv e1 e2
|
||||
-- go (EMod e1 e2) = emitMod e1 e2
|
||||
---- go (EMul e1 e2) = emitMul e1 e2
|
||||
---- go (EDiv e1 e2) = emitDiv e1 e2
|
||||
---- go (EMod e1 e2) = emitMod e1 e2
|
||||
|
||||
--- aux functions ---
|
||||
emitECased :: MIR.Type -> ExpT -> [(MIR.Type, Injection)] -> CompilerState ()
|
||||
|
|
@ -336,89 +333,89 @@ emitECased t e cases = do
|
|||
cons <- gets constructors
|
||||
let r = fromJust $ Map.lookup (coerce consId, t) cons
|
||||
|
||||
lbl_failPos <- (\x -> GA.Ident $ "failed_" <> show x) <$> getNewLabel
|
||||
lbl_succPos <- (\x -> GA.Ident $ "success_" <> show x) <$> getNewLabel
|
||||
-- lbl_failPos <- (\x -> GA.Ident $ "failed_" <> show x) <$> getNewLabel
|
||||
-- lbl_succPos <- (\x -> GA.Ident $ "success_" <> show x) <$> getNewLabel
|
||||
|
||||
consVal <- getNewVar
|
||||
emit $ SetVariable consVal (ExtractValue rt vs 0)
|
||||
-- consVal <- getNewVar
|
||||
-- emit $ SetVariable consVal (ExtractValue rt vs 0)
|
||||
|
||||
consCheck <- getNewVar
|
||||
emit $ SetVariable consCheck (Icmp LLEq I8 (VIdent consVal I8) (VInteger $ numCI r))
|
||||
emit $ BrCond (VIdent consCheck ty) lbl_succPos lbl_failPos
|
||||
emit $ Label lbl_succPos
|
||||
-- consCheck <- getNewVar
|
||||
-- emit $ SetVariable consCheck (Icmp LLEq I8 (VIdent consVal I8) (VInteger $ numCI r))
|
||||
-- emit $ BrCond (VIdent consCheck ty) lbl_succPos lbl_failPos
|
||||
-- emit $ Label lbl_succPos
|
||||
|
||||
castPtr <- getNewVar
|
||||
castedPtr <- getNewVar
|
||||
casted <- getNewVar
|
||||
emit $ SetVariable castPtr (Alloca rt)
|
||||
emit $ Store rt vs Ptr castPtr
|
||||
emit $ SetVariable castedPtr (Bitcast Ptr (VIdent castPtr Ptr) Ptr)
|
||||
emit $ SetVariable casted (Load (CustomType (coerce consId)) Ptr castedPtr)
|
||||
-- castPtr <- getNewVar
|
||||
-- castedPtr <- getNewVar
|
||||
-- casted <- getNewVar
|
||||
-- emit $ SetVariable castPtr (Alloca rt)
|
||||
-- emit $ Store rt vs Ptr castPtr
|
||||
-- emit $ SetVariable castedPtr (Bitcast Ptr (VIdent castPtr Ptr) Ptr)
|
||||
-- emit $ SetVariable casted (Load (CustomType (coerce consId)) Ptr castedPtr)
|
||||
|
||||
val <- exprToValue exp
|
||||
-- enumerateOneM_
|
||||
-- (\i c -> do
|
||||
-- case c of
|
||||
-- CIdent x -> do
|
||||
-- emit . Comment $ "ident " <> show x
|
||||
-- emit $ SetVariable x (ExtractValue (CustomType (fst consId)) (VIdent casted Ptr) i)
|
||||
-- emit $ Store ty val Ptr stackPtr
|
||||
-- CCons x cs -> error "nested constructor"
|
||||
-- CLit l -> do
|
||||
-- testVar <- getNewVar
|
||||
-- emit $ SetVariable testVar (ExtractValue (CustomType (fst consId)) (VIdent casted Ptr) i)
|
||||
-- case l of
|
||||
-- LInt l -> emit $ Icmp LLEq I64 (VIdent testVar Ptr) (VInteger l)
|
||||
-- LChar c -> emit $ Icmp LLEq I8 (VIdent testVar Ptr) (VChar c)
|
||||
-- CCatch -> emit . Comment $ "Catch all"
|
||||
-- emit . Comment $ "return this " <> toIr val
|
||||
-- emit . Comment . show $ c
|
||||
-- emit . Comment . show $ i
|
||||
-- )
|
||||
-- cs
|
||||
-- emit $ Store ty val Ptr stackPtr
|
||||
emit $ Br label
|
||||
emit $ Label lbl_failPos
|
||||
emitCases rt ty label stackPtr vs (Injection (MIR.InitLit i, _) exp) = do
|
||||
let i' = case i of
|
||||
GA.LInt i -> VInteger i
|
||||
GA.LChar i -> VChar i
|
||||
ns <- getNewVar
|
||||
lbl_failPos <- (\x -> GA.Ident $ "failed_" <> show x) <$> getNewLabel
|
||||
lbl_succPos <- (\x -> GA.Ident $ "success_" <> show x) <$> getNewLabel
|
||||
emit $ SetVariable ns (Icmp LLEq ty vs i')
|
||||
emit $ BrCond (VIdent ns ty) lbl_succPos lbl_failPos
|
||||
emit $ Label lbl_succPos
|
||||
val <- exprToValue exp
|
||||
emit $ Store ty val Ptr stackPtr
|
||||
emit $ Br label
|
||||
emit $ Label lbl_failPos
|
||||
-- emitCases rt ty label stackPtr vs (Injection (MIR.CIdent id) exp) = do
|
||||
-- -- //TODO this is pretty disgusting and would heavily benefit from a rewrite
|
||||
-- valPtr <- getNewVar
|
||||
-- emit $ SetVariable valPtr (Alloca rt)
|
||||
-- emit $ Store rt vs Ptr valPtr
|
||||
-- emit $ SetVariable id (Load rt Ptr valPtr)
|
||||
-- increaseVarCount
|
||||
-- val <- exprToValue (fst exp)
|
||||
-- emit $ Store ty val Ptr stackPtr
|
||||
-- emit $ Br label
|
||||
emitCases _ ty label stackPtr _ (Injection (MIR.InitCatch, _) exp) = do
|
||||
val <- exprToValue exp
|
||||
emit $ Store ty val Ptr stackPtr
|
||||
emit $ Br label
|
||||
-- val <- exprToValue exp
|
||||
-- -- enumerateOneM_
|
||||
-- -- (\i c -> do
|
||||
-- -- case c of
|
||||
-- -- CIdent x -> do
|
||||
-- -- emit . Comment $ "ident " <> show x
|
||||
-- -- emit $ SetVariable x (ExtractValue (CustomType (fst consId)) (VIdent casted Ptr) i)
|
||||
-- -- emit $ Store ty val Ptr stackPtr
|
||||
-- -- CCons x cs -> error "nested constructor"
|
||||
-- -- CLit l -> do
|
||||
-- -- testVar <- getNewVar
|
||||
-- -- emit $ SetVariable testVar (ExtractValue (CustomType (fst consId)) (VIdent casted Ptr) i)
|
||||
-- -- case l of
|
||||
-- -- LInt l -> emit $ Icmp LLEq I64 (VIdent testVar Ptr) (VInteger l)
|
||||
-- -- LChar c -> emit $ Icmp LLEq I8 (VIdent testVar Ptr) (VChar c)
|
||||
-- -- CCatch -> emit . Comment $ "Catch all"
|
||||
-- -- emit . Comment $ "return this " <> toIr val
|
||||
-- -- emit . Comment . show $ c
|
||||
-- -- emit . Comment . show $ i
|
||||
-- -- )
|
||||
-- -- cs
|
||||
-- -- emit $ Store ty val Ptr stackPtr
|
||||
-- emit $ Br label
|
||||
-- emit $ Label lbl_failPos
|
||||
-- emitCases rt ty label stackPtr vs (Injection (MIR.InitLit i, _) exp) = do
|
||||
-- let i' = case i of
|
||||
-- GA.LInt i -> VInteger i
|
||||
-- GA.LChar i -> VChar i
|
||||
-- ns <- getNewVar
|
||||
-- lbl_failPos <- (\x -> GA.Ident $ "failed_" <> show x) <$> getNewLabel
|
||||
-- lbl_succPos <- (\x -> GA.Ident $ "success_" <> show x) <$> getNewLabel
|
||||
-- emit $ SetVariable ns (Icmp LLEq ty vs i')
|
||||
-- emit $ BrCond (VIdent ns ty) lbl_succPos lbl_failPos
|
||||
-- emit $ Label lbl_succPos
|
||||
-- val <- exprToValue exp
|
||||
-- emit $ Store ty val Ptr stackPtr
|
||||
-- emit $ Br label
|
||||
-- emit $ Label lbl_failPos
|
||||
---- emitCases rt ty label stackPtr vs (Injection (MIR.CIdent id) exp) = do
|
||||
---- -- //TODO this is pretty disgusting and would heavily benefit from a rewrite
|
||||
---- valPtr <- getNewVar
|
||||
---- emit $ SetVariable valPtr (Alloca rt)
|
||||
---- emit $ Store rt vs Ptr valPtr
|
||||
---- emit $ SetVariable id (Load rt Ptr valPtr)
|
||||
---- increaseVarCount
|
||||
---- val <- exprToValue (fst exp)
|
||||
---- emit $ Store ty val Ptr stackPtr
|
||||
---- emit $ Br label
|
||||
-- emitCases _ ty label stackPtr _ (Injection (MIR.InitCatch, _) exp) = do
|
||||
-- val <- exprToValue exp
|
||||
-- emit $ Store ty val Ptr stackPtr
|
||||
-- emit $ Br label
|
||||
|
||||
--emitLet :: Bind -> Exp -> CompilerState ()
|
||||
emitLet xs e = do
|
||||
emit $
|
||||
Comment $
|
||||
concat
|
||||
[ "ELet ("
|
||||
, show xs
|
||||
, " = "
|
||||
, show e
|
||||
, ") is not implemented!"
|
||||
]
|
||||
----emitLet :: Bind -> Exp -> CompilerState ()
|
||||
-- emitLet xs e = do
|
||||
-- emit $
|
||||
-- Comment $
|
||||
-- concat
|
||||
-- [ "ELet ("
|
||||
-- , show xs
|
||||
-- , " = "
|
||||
-- , show e
|
||||
-- , ") is not implemented!"
|
||||
-- ]
|
||||
|
||||
emitApp :: MIR.Type -> ExpT -> ExpT -> CompilerState ()
|
||||
emitApp t e1 e2 = appEmitter e1 e2 []
|
||||
|
|
@ -443,60 +440,60 @@ emitApp t e1 e2 = appEmitter e1 e2 []
|
|||
emit $ SetVariable vs call
|
||||
x -> error $ "The unspeakable happened: " <> show x
|
||||
|
||||
emitIdent :: GA.Ident -> CompilerState ()
|
||||
emitIdent id = do
|
||||
-- !!this should never happen!!
|
||||
emit $ Comment "This should not have happened!"
|
||||
emit $ Variable id
|
||||
emit $ UnsafeRaw "\n"
|
||||
-- emitIdent :: GA.Ident -> CompilerState ()
|
||||
-- emitIdent id = do
|
||||
-- -- !!this should never happen!!
|
||||
-- emit $ Comment "This should not have happened!"
|
||||
-- emit $ Variable id
|
||||
-- emit $ UnsafeRaw "\n"
|
||||
|
||||
emitLit :: MIR.Lit -> CompilerState ()
|
||||
emitLit i = do
|
||||
-- !!this should never happen!!
|
||||
let (i', t) = case i of
|
||||
(MIR.LInt i'') -> (VInteger i'', I64)
|
||||
(MIR.LChar i'') -> (VChar i'', I8)
|
||||
varCount <- getNewVar
|
||||
emit $ Comment "This should not have happened!"
|
||||
emit $ SetVariable (GA.Ident (show varCount)) (Add t i' (VInteger 0))
|
||||
-- emitLit :: MIR.Lit -> CompilerState ()
|
||||
-- emitLit i = do
|
||||
-- -- !!this should never happen!!
|
||||
-- let (i', t) = case i of
|
||||
-- (MIR.LInt i'') -> (VInteger i'', I64)
|
||||
-- (MIR.LChar i'') -> (VChar i'', I8)
|
||||
-- varCount <- getNewVar
|
||||
-- emit $ Comment "This should not have happened!"
|
||||
-- emit $ SetVariable (GA.Ident (show varCount)) (Add t i' (VInteger 0))
|
||||
|
||||
emitAdd :: MIR.Type -> ExpT -> ExpT -> CompilerState ()
|
||||
emitAdd t e1 e2 = do
|
||||
v1 <- exprToValue e1
|
||||
v2 <- exprToValue e2
|
||||
v <- getNewVar
|
||||
emit $ SetVariable (GA.Ident $ show v) (Add (type2LlvmType t) v1 v2)
|
||||
-- emitAdd :: MIR.Type -> ExpT -> ExpT -> CompilerState ()
|
||||
-- emitAdd t e1 e2 = do
|
||||
-- v1 <- exprToValue e1
|
||||
-- v2 <- exprToValue e2
|
||||
-- v <- getNewVar
|
||||
-- emit $ SetVariable (GA.Ident $ show v) (Add (type2LlvmType t) v1 v2)
|
||||
|
||||
emitSub :: MIR.Type -> ExpT -> ExpT -> CompilerState ()
|
||||
emitSub t e1 e2 = do
|
||||
v1 <- exprToValue e1
|
||||
v2 <- exprToValue e2
|
||||
v <- getNewVar
|
||||
emit $ SetVariable v (Sub (type2LlvmType t) v1 v2)
|
||||
-- emitSub :: MIR.Type -> ExpT -> ExpT -> CompilerState ()
|
||||
-- emitSub t e1 e2 = do
|
||||
-- v1 <- exprToValue e1
|
||||
-- v2 <- exprToValue e2
|
||||
-- v <- getNewVar
|
||||
-- emit $ SetVariable v (Sub (type2LlvmType t) v1 v2)
|
||||
|
||||
exprToValue :: ExpT -> CompilerState LLVMValue
|
||||
exprToValue = \case
|
||||
(MIR.ELit i, t) -> pure $ case i of
|
||||
(MIR.LInt i) -> VInteger i
|
||||
(MIR.LChar i) -> VChar i
|
||||
(MIR.EId name, t) -> do
|
||||
funcs <- gets functions
|
||||
case Map.lookup (name, t) funcs of
|
||||
Just fi -> do
|
||||
if numArgs fi == 0
|
||||
then do
|
||||
vc <- getNewVar
|
||||
emit $
|
||||
SetVariable
|
||||
vc
|
||||
(Call FastCC (type2LlvmType t) Global name [])
|
||||
pure $ VIdent vc (type2LlvmType t)
|
||||
else pure $ VFunction name Global (type2LlvmType t)
|
||||
Nothing -> pure $ VIdent name (type2LlvmType t)
|
||||
e -> do
|
||||
compileExp e
|
||||
v <- getVarCount
|
||||
pure $ VIdent (GA.Ident $ show v) (getType e)
|
||||
-- exprToValue :: ExpT -> CompilerState LLVMValue
|
||||
-- exprToValue = \case
|
||||
-- (MIR.ELit i, t) -> pure $ case i of
|
||||
-- (MIR.LInt i) -> VInteger i
|
||||
-- (MIR.LChar i) -> VChar i
|
||||
-- (MIR.EId name, t) -> do
|
||||
-- funcs <- gets functions
|
||||
-- case Map.lookup (name, t) funcs of
|
||||
-- Just fi -> do
|
||||
-- if numArgs fi == 0
|
||||
-- then do
|
||||
-- vc <- getNewVar
|
||||
-- emit $
|
||||
-- SetVariable
|
||||
-- vc
|
||||
-- (Call FastCC (type2LlvmType t) Global name [])
|
||||
-- pure $ VIdent vc (type2LlvmType t)
|
||||
-- else pure $ VFunction name Global (type2LlvmType t)
|
||||
-- Nothing -> pure $ VIdent name (type2LlvmType t)
|
||||
-- e -> do
|
||||
-- compileExp e
|
||||
-- v <- getVarCount
|
||||
-- pure $ VIdent (GA.Ident $ show v) (getType e)
|
||||
|
||||
type2LlvmType :: MIR.Type -> LLVMType
|
||||
type2LlvmType (MIR.TLit id@(Ident name)) = case name of
|
||||
|
|
@ -510,26 +507,26 @@ type2LlvmType (MIR.TFun t xs) = do
|
|||
function2LLVMType (TFun t xs) s = function2LLVMType xs (type2LlvmType t : s)
|
||||
function2LLVMType x s = (type2LlvmType x, s)
|
||||
|
||||
getType :: ExpT -> LLVMType
|
||||
getType (_, t) = type2LlvmType t
|
||||
-- getType :: ExpT -> LLVMType
|
||||
-- getType (_, t) = type2LlvmType t
|
||||
|
||||
valueGetType :: LLVMValue -> LLVMType
|
||||
valueGetType (VInteger _) = I64
|
||||
valueGetType (VChar _) = I8
|
||||
valueGetType (VIdent _ t) = t
|
||||
valueGetType (VConstant s) = Array (fromIntegral $ length s) I8
|
||||
valueGetType (VFunction _ _ t) = t
|
||||
-- valueGetType :: LLVMValue -> LLVMType
|
||||
-- valueGetType (VInteger _) = I64
|
||||
-- valueGetType (VChar _) = I8
|
||||
-- valueGetType (VIdent _ t) = t
|
||||
-- valueGetType (VConstant s) = Array (fromIntegral $ length s) I8
|
||||
-- valueGetType (VFunction _ _ t) = t
|
||||
|
||||
typeByteSize :: LLVMType -> Integer
|
||||
typeByteSize I1 = 1
|
||||
typeByteSize I8 = 1
|
||||
typeByteSize I32 = 4
|
||||
typeByteSize I64 = 8
|
||||
typeByteSize Ptr = 8
|
||||
typeByteSize (Ref _) = 8
|
||||
typeByteSize (Function _ _) = 8
|
||||
typeByteSize (Array n t) = n * typeByteSize t
|
||||
typeByteSize (CustomType _) = 8
|
||||
-- typeByteSize :: LLVMType -> Integer
|
||||
-- typeByteSize I1 = 1
|
||||
-- typeByteSize I8 = 1
|
||||
-- typeByteSize I32 = 4
|
||||
-- typeByteSize I64 = 8
|
||||
-- typeByteSize Ptr = 8
|
||||
-- typeByteSize (Ref _) = 8
|
||||
-- typeByteSize (Function _ _) = 8
|
||||
-- typeByteSize (Array n t) = n * typeByteSize t
|
||||
-- typeByteSize (CustomType _) = 8
|
||||
|
||||
enumerateOneM_ :: Monad m => (Integer -> a -> m b) -> [a] -> m ()
|
||||
enumerateOneM_ f = foldM_ (\i a -> f i a >> pure (i + 1)) 1
|
||||
-- enumerateOneM_ :: Monad m => (Integer -> a -> m b) -> [a] -> m ()
|
||||
-- enumerateOneM_ f = foldM_ (\i a -> f i a >> pure (i + 1)) 1
|
||||
|
|
|
|||
45
src/Main.hs
45
src/Main.hs
|
|
@ -2,26 +2,29 @@
|
|||
|
||||
module Main where
|
||||
|
||||
import Codegen.Codegen (generateCode)
|
||||
import GHC.IO.Handle.Text (hPutStrLn)
|
||||
import Grammar.ErrM (Err)
|
||||
import Grammar.Par (myLexer, pProgram)
|
||||
import Grammar.Print (printTree)
|
||||
import Monomorphizer.Monomorphizer (monomorphize)
|
||||
-- import Codegen.Codegen (generateCode)
|
||||
import GHC.IO.Handle.Text (hPutStrLn)
|
||||
import Grammar.ErrM (Err)
|
||||
import Grammar.Par (myLexer, pProgram)
|
||||
import Grammar.Print (printTree)
|
||||
import Monomorphizer.Monomorphizer (monomorphize)
|
||||
|
||||
import Control.Monad (when)
|
||||
import Data.List.Extra (isSuffixOf)
|
||||
import Control.Monad (when)
|
||||
import Data.List.Extra (isSuffixOf)
|
||||
|
||||
import Renamer.Renamer (rename)
|
||||
import System.Directory (createDirectory, doesPathExist,
|
||||
getDirectoryContents,
|
||||
removeDirectoryRecursive,
|
||||
setCurrentDirectory)
|
||||
import System.Environment (getArgs)
|
||||
import System.Exit (exitFailure, exitSuccess)
|
||||
import System.IO (stderr)
|
||||
import System.Process.Extra (spawnCommand, waitForProcess)
|
||||
import TypeChecker.TypeChecker (typecheck)
|
||||
import Renamer.Renamer (rename)
|
||||
import System.Directory (
|
||||
createDirectory,
|
||||
doesPathExist,
|
||||
getDirectoryContents,
|
||||
removeDirectoryRecursive,
|
||||
setCurrentDirectory,
|
||||
)
|
||||
import System.Environment (getArgs)
|
||||
import System.Exit (exitFailure, exitSuccess)
|
||||
import System.IO (stderr)
|
||||
import System.Process.Extra (spawnCommand, waitForProcess)
|
||||
import TypeChecker.TypeChecker (typecheck)
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
|
|
@ -50,9 +53,9 @@ main' debug s = do
|
|||
-- let lifted = lambdaLift typechecked
|
||||
-- printToErr $ printTree lifted
|
||||
--
|
||||
printToErr "\n -- Printing compiler output to stdout --"
|
||||
compiled <- fromCompilerErr $ generateCode (monomorphize typechecked)
|
||||
putStrLn compiled
|
||||
-- printToErr "\n -- Printing compiler output to stdout --"
|
||||
-- compiled <- fromCompilerErr $ generateCode (monomorphize typechecked)
|
||||
-- putStrLn compiled
|
||||
|
||||
-- check <- doesPathExist "output"
|
||||
-- when check (removeDirectoryRecursive "output")
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
module Monomorphizer.Monomorphizer (monomorphize) where
|
||||
|
||||
import Data.Coerce (coerce)
|
||||
import Grammar.Abs (Constructor (..), Ident (..),
|
||||
Indexed (..))
|
||||
import qualified Grammar.Abs as GA
|
||||
import qualified Monomorphizer.MonomorphizerIr as M
|
||||
import qualified TypeChecker.TypeCheckerIr as T
|
||||
import Data.Coerce (coerce)
|
||||
import Grammar.Abs (Constructor (..), Ident (..))
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
|
||||
import Grammar.Abs qualified as GA
|
||||
import Monomorphizer.MonomorphizerIr qualified as M
|
||||
import TypeChecker.TypeCheckerIr qualified as T
|
||||
|
||||
monomorphize :: T.Program -> M.Program
|
||||
monomorphize (T.Program ds) = M.Program $ monoDefs ds
|
||||
|
|
@ -17,14 +18,11 @@ monoDefs = map monoDef
|
|||
|
||||
monoDef :: T.Def -> M.Def
|
||||
monoDef (T.DBind bind) = M.DBind $ monoBind bind
|
||||
monoDef (T.DData d) = M.DData $ monoData d
|
||||
monoDef (T.DData d) = M.DData $ unsafeCoerce d
|
||||
|
||||
monoBind :: T.Bind -> M.Bind
|
||||
monoBind (T.Bind name args (e, t)) = M.Bind (monoId name) (map monoId args) (monoExpr e, monoType t)
|
||||
|
||||
monoData :: T.Data -> M.Constructor
|
||||
monoData (T.Data (Indexed n _) cons) = M.Constructor n (map (\(Constructor n t) -> (n, monoAbsType t)) cons)
|
||||
|
||||
monoExpr :: T.Exp -> M.Exp
|
||||
monoExpr = \case
|
||||
T.EId (Ident i) -> M.EId (Ident i)
|
||||
|
|
@ -36,29 +34,28 @@ monoExpr = \case
|
|||
T.ECase expt injs -> M.ECase (monoexpt expt) (monoInjs injs)
|
||||
|
||||
monoAbsType :: GA.Type -> M.Type
|
||||
monoAbsType (GA.TLit u) = M.TLit (coerce u)
|
||||
monoAbsType (GA.TVar _v) = error "NOT POLYMORHPIC TYPES"
|
||||
monoAbsType (GA.TAll _v _t) = error "NOT ALL TYPES"
|
||||
monoAbsType (GA.TIndexed _i) = error "NOT INDEXED TYPES"
|
||||
monoAbsType (GA.TEVar _v) = error "I DONT KNOW WHAT THIS IS"
|
||||
monoAbsType (GA.TFun t1 t2) = M.TFun (monoAbsType t1) (monoAbsType t2)
|
||||
|
||||
monoAbsType (GA.TLit u) = M.TLit (coerce u)
|
||||
monoAbsType (GA.TVar _v) = error "NOT POLYMORHPIC TYPES"
|
||||
monoAbsType (GA.TAll _v _t) = error "NOT ALL TYPES"
|
||||
monoAbsType (GA.TData _ i) = error "NOT INDEXED TYPES"
|
||||
monoAbsType (GA.TEVar _v) = error "I DONT KNOW WHAT THIS IS"
|
||||
monoAbsType (GA.TFun t1 t2) = M.TFun (monoAbsType t1) (monoAbsType t2)
|
||||
|
||||
monoType :: T.Type -> M.Type
|
||||
monoType (T.TAll _ t) = monoType t
|
||||
monoType (T.TAll _ t) = monoType t
|
||||
monoType (T.TVar (T.MkTVar i)) = error "NOT POLYMORPHIC TYPES"
|
||||
monoType (T.TLit i) = M.TLit i
|
||||
monoType (T.TFun t1 t2) = M.TFun (monoType t1) (monoType t2)
|
||||
monoType (T.TIndexed _) = error "Not sure what this is"
|
||||
monoType (T.TLit i) = M.TLit i
|
||||
monoType (T.TFun t1 t2) = M.TFun (monoType t1) (monoType t2)
|
||||
monoType (T.TData _ _) = error "Not sure what this is"
|
||||
|
||||
monoexpt :: T.ExpT -> M.ExpT
|
||||
monoexpt (e, t) = (monoExpr e, monoType t)
|
||||
|
||||
monoId :: T.Id -> M.Id
|
||||
monoId (n,t) = (n, monoType t)
|
||||
monoId (n, t) = (n, monoType t)
|
||||
|
||||
monoLit :: T.Lit -> M.Lit
|
||||
monoLit (T.LInt i) = M.LInt i
|
||||
monoLit (T.LInt i) = M.LInt i
|
||||
monoLit (T.LChar c) = M.LChar c
|
||||
|
||||
monoInjs :: [T.Inj] -> [M.Injection]
|
||||
|
|
@ -69,4 +66,3 @@ monoInj (T.Inj (init, t) expt) = M.Injection (monoInit init, monoType t) (monoex
|
|||
|
||||
monoInit :: T.Init -> M.Init
|
||||
monoInit = id
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
module Monomorphizer.MonomorphizerIr (module Monomorphizer.MonomorphizerIr, module RE, module GA) where
|
||||
|
||||
import Grammar.Abs (Ident (..), Init (..), UIdent)
|
||||
import qualified Grammar.Abs as GA (Ident (..), Init (..))
|
||||
import qualified TypeChecker.TypeCheckerIr as RE (Indexed)
|
||||
import TypeChecker.TypeCheckerIr (Indexed)
|
||||
import Grammar.Abs (Ident (..), Init (..), UIdent)
|
||||
import Grammar.Abs qualified as GA (Ident (..), Init (..))
|
||||
import TypeChecker.TypeCheckerIr qualified as RE
|
||||
|
||||
type Id = (Ident, Type)
|
||||
|
||||
newtype Program = Program [Def]
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
data Def = DBind Bind | DData Constructor
|
||||
data Def = DBind Bind | DData Data
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
data Data = Data Type Constructor
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
data Bind = Bind Id [Id] ExpT
|
||||
|
|
@ -43,4 +45,4 @@ data Type = TLit Ident | TFun Type Type
|
|||
|
||||
flattenType :: Type -> [Type]
|
||||
flattenType (TFun t1 t2) = t1 : flattenType t2
|
||||
flattenType x = [x]
|
||||
flattenType x = [x]
|
||||
|
|
|
|||
|
|
@ -37,22 +37,23 @@ renameDefs defs = runIdentity $ runExceptT $ evalStateT (runRn $ mapM renameDef
|
|||
renameDef = \case
|
||||
DSig (Sig name typ) -> DSig . Sig name <$> renameTVars typ
|
||||
DBind bind -> DBind . snd <$> renameBind initNames bind
|
||||
DData (Data (Indexed cname types) constrs) -> do
|
||||
DData (Data (TData cname types) constrs) -> do
|
||||
tvars_ <- tvars
|
||||
tvars' <- mapM nextNameTVar tvars_
|
||||
let tvars_lt = zip tvars_ tvars'
|
||||
typ' = map (substituteTVar tvars_lt) types
|
||||
constrs' = map (renameConstr tvars_lt) constrs
|
||||
pure . DData $ Data (Indexed cname typ') constrs'
|
||||
pure . DData $ Data (TData cname typ') constrs'
|
||||
where
|
||||
tvars = concat <$> mapM (collectTVars []) types
|
||||
collectTVars :: [TVar] -> Type -> Rn [TVar]
|
||||
collectTVars tvars = \case
|
||||
TAll tvar t -> collectTVars (tvar : tvars) t
|
||||
TIndexed _ -> return tvars
|
||||
TData _ _ -> return tvars
|
||||
-- Should be monad error
|
||||
TVar v -> return [v]
|
||||
_ -> throwError ("Bad data type definition: " ++ show types)
|
||||
DData (Data types _) -> throwError ("Bad data type definition: " ++ show types)
|
||||
|
||||
renameConstr :: [(TVar, TVar)] -> Constructor -> Constructor
|
||||
renameConstr new_types (Constructor name typ) =
|
||||
|
|
@ -78,7 +79,7 @@ substituteTVar new_names typ = case typ of
|
|||
TAll tvar' $ substitute' t
|
||||
| otherwise ->
|
||||
TAll tvar $ substitute' t
|
||||
TIndexed (Indexed name typs) -> TIndexed . Indexed name $ map substitute' typs
|
||||
TData name typs -> TData name $ map substitute' typs
|
||||
_ -> error ("Impossible " ++ show typ)
|
||||
where
|
||||
substitute' = substituteTVar new_names
|
||||
|
|
@ -169,7 +170,7 @@ substitute tvar1 tvar2 typ = case typ of
|
|||
| otherwise -> typ
|
||||
TFun t1 t2 -> on TFun substitute' t1 t2
|
||||
TAll tvar t -> TAll tvar $ substitute' t
|
||||
TIndexed (Indexed name typs) -> TIndexed . Indexed name $ map substitute' typs
|
||||
TData name typs -> TData name $ map substitute' typs
|
||||
_ -> error "Impossible"
|
||||
where
|
||||
substitute' = substitute tvar1 tvar2
|
||||
|
|
|
|||
|
|
@ -48,13 +48,13 @@ typecheck = run . checkPrg
|
|||
checkData :: Data -> Infer ()
|
||||
checkData d = do
|
||||
case d of
|
||||
(Data typ@(Indexed name ts) constrs) -> do
|
||||
(Data typ@(TData name ts) constrs) -> do
|
||||
unless
|
||||
(all isPoly ts)
|
||||
(throwError $ unwords ["Data type incorrectly declared"])
|
||||
traverse_
|
||||
( \(Constructor name' t') ->
|
||||
if TIndexed typ == retType t'
|
||||
if typ == retType t'
|
||||
then insertConstr (coerce name') (toNew t')
|
||||
else
|
||||
throwError $
|
||||
|
|
@ -68,6 +68,7 @@ checkData d = do
|
|||
]
|
||||
)
|
||||
constrs
|
||||
_ -> throwError $ "incorrectly declared data type '" ++ printTree d ++ "'"
|
||||
|
||||
retType :: Type -> Type
|
||||
retType (TFun _ t2) = retType t2
|
||||
|
|
@ -86,7 +87,14 @@ checkPrg (Program bs) = do
|
|||
preRun [] = return ()
|
||||
preRun (x : xs) = case x of
|
||||
DSig (Sig n t) -> do
|
||||
gets (M.member (coerce n) . sigs) >>= flip when (throwError $ "Duplicate signatures for function '" ++ printTree n ++ "'")
|
||||
gets (M.member (coerce n) . sigs)
|
||||
>>= flip
|
||||
when
|
||||
( throwError $
|
||||
"Duplicate signatures for function '"
|
||||
++ printTree n
|
||||
++ "'"
|
||||
)
|
||||
insertSig (coerce n) (Just $ toNew t) >> preRun xs
|
||||
DBind (Bind n _ _) -> do
|
||||
s <- gets sigs
|
||||
|
|
@ -140,7 +148,7 @@ isMoreSpecificOrEq :: T.Type -> T.Type -> Bool
|
|||
isMoreSpecificOrEq _ (T.TAll _ _) = True
|
||||
isMoreSpecificOrEq (T.TFun a b) (T.TFun c d) =
|
||||
isMoreSpecificOrEq a c && isMoreSpecificOrEq b d
|
||||
isMoreSpecificOrEq (T.TIndexed (T.Indexed n1 ts1)) (T.TIndexed (T.Indexed n2 ts2)) =
|
||||
isMoreSpecificOrEq (T.TData n1 ts1) (T.TData n2 ts2) =
|
||||
n1 == n2
|
||||
&& length ts1 == length ts2
|
||||
&& and (zipWith isMoreSpecificOrEq ts1 ts2)
|
||||
|
|
@ -169,11 +177,11 @@ instance NewType Type T.Type where
|
|||
TVar v -> T.TVar $ toNew v
|
||||
TFun t1 t2 -> T.TFun (toNew t1) (toNew t2)
|
||||
TAll b t -> T.TAll (toNew b) (toNew t)
|
||||
TIndexed i -> T.TIndexed (toNew i)
|
||||
TData i ts -> T.TData (coerce i) (map toNew ts)
|
||||
TEVar _ -> error "Should not exist after typechecker"
|
||||
|
||||
instance NewType Indexed T.Indexed where
|
||||
toNew (Indexed name vars) = T.Indexed (coerce name) (map toNew vars)
|
||||
-- instance NewType Indexed T.TData where
|
||||
-- toNew (Indexed name vars) = T.TData (coerce name) (map toNew vars)
|
||||
|
||||
instance NewType TVar T.TVar where
|
||||
toNew (MkTVar i) = T.MkTVar $ coerce i
|
||||
|
|
@ -181,8 +189,8 @@ instance NewType TVar T.TVar where
|
|||
algoW :: Exp -> Infer (Subst, T.ExpT)
|
||||
algoW = \case
|
||||
-- \| TODO: More testing need to be done. Unsure of the correctness of this
|
||||
EAnn e t -> do
|
||||
(s1, (e', t')) <- algoW e
|
||||
err@(EAnn e t) -> do
|
||||
(s1, (e', t')) <- exprErr (algoW e) err
|
||||
unless
|
||||
(toNew t `isMoreSpecificOrEq` t')
|
||||
( throwError $
|
||||
|
|
@ -194,16 +202,14 @@ algoW = \case
|
|||
]
|
||||
)
|
||||
applySt s1 $ do
|
||||
s2 <- unify (toNew t) t'
|
||||
s2 <- exprErr (unify (toNew t) t') err
|
||||
let comp = s2 `compose` s1
|
||||
return (comp, apply comp (e', toNew t))
|
||||
|
||||
-- \| ------------------
|
||||
-- \| Γ ⊢ i : Int, ∅
|
||||
|
||||
ELit lit ->
|
||||
let lt = litType lit
|
||||
in return (nullSubst, (T.ELit lit, lt))
|
||||
ELit lit -> return (nullSubst, (T.ELit lit, litType lit))
|
||||
-- \| x : σ ∈ Γ τ = inst(σ)
|
||||
-- \| ----------------------
|
||||
-- \| Γ ⊢ x : τ, ∅
|
||||
|
|
@ -227,13 +233,16 @@ algoW = \case
|
|||
-- \| ---------------------------------
|
||||
-- \| Γ ⊢ w λx. e : Sτ → τ', S
|
||||
|
||||
EAbs name e -> do
|
||||
err@(EAbs name e) -> do
|
||||
fr <- fresh
|
||||
withBinding (coerce name) fr $ do
|
||||
(s1, (e', t')) <- algoW e
|
||||
let varType = apply s1 fr
|
||||
let newArr = T.TFun varType t'
|
||||
return (s1, apply s1 (T.EAbs (coerce name) (e', t'), newArr))
|
||||
exprErr
|
||||
( withBinding (coerce name) fr $ do
|
||||
(s1, (e', t')) <- exprErr (algoW e) err
|
||||
let varType = apply s1 fr
|
||||
let newArr = T.TFun varType t'
|
||||
return (s1, apply s1 (T.EAbs (coerce name) (e', t'), newArr))
|
||||
)
|
||||
err
|
||||
|
||||
-- \| Γ ⊢ e₀ : τ₀, S₀ S₀Γ ⊢ e₁ : τ₁, S₁
|
||||
-- \| s₂ = mgu(s₁τ₀, Int) s₃ = mgu(s₂τ₁, Int)
|
||||
|
|
@ -241,13 +250,13 @@ algoW = \case
|
|||
-- \| Γ ⊢ e₀ + e₁ : Int, S₃S₂S₁S₀
|
||||
-- This might be wrong
|
||||
|
||||
EAdd e0 e1 -> do
|
||||
err@(EAdd e0 e1) -> do
|
||||
(s1, (e0', t0)) <- algoW e0
|
||||
applySt s1 $ do
|
||||
(s2, (e1', t1)) <- algoW e1
|
||||
-- applySt s2 $ do
|
||||
s3 <- unify (apply s2 t0) int
|
||||
s4 <- unify (apply s3 t1) int
|
||||
s3 <- exprErr (unify (apply s2 t0) int) err
|
||||
s4 <- exprErr (unify (apply s3 t1) int) err
|
||||
let comp = s4 `compose` s3 `compose` s2 `compose` s1
|
||||
return
|
||||
( comp
|
||||
|
|
@ -259,12 +268,12 @@ algoW = \case
|
|||
-- \| --------------------------------------
|
||||
-- \| Γ ⊢ e₀ e₁ : S₂τ', S₂S₁S₀
|
||||
|
||||
EApp e0 e1 -> do
|
||||
err@(EApp e0 e1) -> do
|
||||
fr <- fresh
|
||||
(s0, (e0', t0)) <- algoW e0
|
||||
(s0, (e0', t0)) <- exprErr (algoW e0) err
|
||||
applySt s0 $ do
|
||||
(s1, (e1', t1)) <- algoW e1
|
||||
s2 <- unify (apply s1 t0) (T.TFun t1 fr)
|
||||
(s1, (e1', t1)) <- exprErr (algoW e1) err
|
||||
s2 <- exprErr (unify (apply s1 t0) (T.TFun t1 fr)) err
|
||||
let t = apply s2 fr
|
||||
let comp = s2 `compose` s1 `compose` s0
|
||||
return (comp, apply comp (T.EApp (e0', t0) (e1', t1), t))
|
||||
|
|
@ -275,9 +284,9 @@ algoW = \case
|
|||
|
||||
-- The bar over S₀ and Γ means "generalize"
|
||||
|
||||
ELet b@(Bind name args e) e1 -> do
|
||||
(s1, (_, t0)) <- algoW (makeLambda e (coerce args))
|
||||
bind' <- checkBind b
|
||||
err@(ELet b@(Bind name args e) e1) -> do
|
||||
(s1, (_, t0)) <- exprErr (algoW (makeLambda e (coerce args))) err
|
||||
bind' <- exprErr (checkBind b) err
|
||||
env <- asks vars
|
||||
let t' = generalize (apply s1 env) t0
|
||||
withBinding (coerce name) t' $ do
|
||||
|
|
@ -311,7 +320,7 @@ unify t0 t1 = do
|
|||
(a, T.TAll _ t) -> unify a t
|
||||
(T.TLit a, T.TLit b) ->
|
||||
if a == b then return M.empty else throwError . unwords $ ["Can not unify", "'" ++ printTree (T.TLit a) ++ "'", "with", "'" ++ printTree (T.TLit b) ++ "'"]
|
||||
(T.TIndexed (T.Indexed name t), T.TIndexed (T.Indexed name' t')) ->
|
||||
(T.TData name t, T.TData name' t') ->
|
||||
if name == name' && length t == length t'
|
||||
then do
|
||||
xs <- zipWithM unify t t'
|
||||
|
|
@ -399,7 +408,7 @@ instance FreeVars T.Type where
|
|||
free (T.TLit _) = mempty
|
||||
free (T.TFun a b) = free a `S.union` free b
|
||||
-- \| Not guaranteed to be correct
|
||||
free (T.TIndexed (T.Indexed _ a)) =
|
||||
free (T.TData _ a) =
|
||||
foldl' (\acc x -> free x `S.union` acc) S.empty a
|
||||
|
||||
apply :: Subst -> T.Type -> T.Type
|
||||
|
|
@ -413,7 +422,7 @@ instance FreeVars T.Type where
|
|||
Nothing -> T.TAll (T.MkTVar i) (apply sub t)
|
||||
Just _ -> apply sub t
|
||||
T.TFun a b -> T.TFun (apply sub a) (apply sub b)
|
||||
T.TIndexed (T.Indexed name a) -> T.TIndexed (T.Indexed name (map (apply sub) a))
|
||||
T.TData name a -> T.TData name (map (apply sub) a)
|
||||
|
||||
instance FreeVars (Map Ident T.Type) where
|
||||
free :: Map Ident T.Type -> Set Ident
|
||||
|
|
@ -548,3 +557,6 @@ partitionType = go []
|
|||
TAll tvar t' -> second (TAll tvar) $ go acc i t'
|
||||
TFun t1 t2 -> go (acc ++ [t1]) (i - 1) t2
|
||||
_ -> error "Number of parameters and type doesn't match"
|
||||
|
||||
exprErr :: Infer a -> Exp -> Infer a
|
||||
exprErr ma exp = catchError ma (\x -> throwError $ x ++ " on expression: " ++ printTree exp)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ data Type
|
|||
| TVar TVar
|
||||
| TFun Type Type
|
||||
| TAll TVar Type
|
||||
| TIndexed Indexed
|
||||
| TData Ident [Type]
|
||||
deriving (Show, Eq, Ord, Read)
|
||||
|
||||
data Exp
|
||||
|
|
@ -67,9 +67,6 @@ data Exp
|
|||
|
||||
type ExpT = (Exp, Type)
|
||||
|
||||
data Indexed = Indexed Ident [Type]
|
||||
deriving (Show, Read, Ord, Eq)
|
||||
|
||||
data Inj = Inj (Init, Type) ExpT
|
||||
deriving (C.Eq, C.Ord, C.Read, C.Show)
|
||||
|
||||
|
|
@ -205,8 +202,5 @@ instance Print Type where
|
|||
TLit uident -> prPrec i 2 (concatD [prt 0 uident])
|
||||
TVar tvar -> prPrec i 2 (concatD [prt 0 tvar])
|
||||
TAll tvar type_ -> prPrec i 1 (concatD [doc (showString "forall"), prt 0 tvar, doc (showString "."), prt 0 type_])
|
||||
TIndexed indexed -> prPrec i 1 (concatD [prt 0 indexed])
|
||||
TData ident types -> prPrec i 1 (concatD [prt 0 ident, prt 0 types])
|
||||
TFun type_1 type_2 -> prPrec i 0 (concatD [prt 1 type_1, doc (showString "->"), prt 0 type_2])
|
||||
|
||||
instance Print Indexed where
|
||||
prt i (Indexed u ts) = concatD [prt i u, prt i ts]
|
||||
|
|
|
|||
30
test_program
30
test_program
|
|
@ -8,18 +8,18 @@ data Bool () where {
|
|||
False : Bool ()
|
||||
};
|
||||
|
||||
-- hello_world = Cons 'h' (Cons 'e' (Cons 'l' (Cons 'l' (Cons 'o' (Cons ' ' (Cons 'w' (Cons 'o' (Cons 'r' (Cons 'l' (Cons 'd' Nil)))))))))) ;
|
||||
hello_world = Cons 'h' (Cons 'e' (Cons 'l' (Cons 'l' (Cons 'o' (Cons ' ' (Cons 'w' (Cons 'o' (Cons 'r' (Cons 'l' (Cons 'd' Nil)))))))))) ;
|
||||
|
||||
-- length : List (a) -> Int ;
|
||||
-- length xs = case xs of {
|
||||
-- Nil => 0 ;
|
||||
-- Cons x xs => length xs
|
||||
-- };
|
||||
length : List (a) -> Int ;
|
||||
length xs = case xs of {
|
||||
Nil => 0 ;
|
||||
Cons x xs => length xs
|
||||
};
|
||||
|
||||
-- head : List (a) -> a ;
|
||||
-- head xs = case xs of {
|
||||
-- Cons x xs => x
|
||||
-- };
|
||||
head : List (a) -> a ;
|
||||
head xs = case xs of {
|
||||
Cons x xs => x
|
||||
};
|
||||
|
||||
firstIsOne : List (Int) -> Bool () ;
|
||||
firstIsOne : List (Int) -> Bool () ;
|
||||
|
|
@ -34,9 +34,11 @@ firstIsOne xs = case xs of {
|
|||
_ => False
|
||||
};
|
||||
|
||||
-- firstIsOne :: [Int] -> Bool
|
||||
-- firstIsOne xs = case xs of
|
||||
-- (1 : xs) -> True
|
||||
-- _ -> False
|
||||
firstIsOne :: [Int] -> Bool
|
||||
firstIsOne xs = case xs of
|
||||
(1 : xs) -> True
|
||||
_ -> False
|
||||
|
||||
main = firstIsOne (Cons 'a' Nil)
|
||||
|
||||
data a -> b where
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue