Renamer done.
It renames bound variables to numbers, converts let to lambda, and removes all variables from binds
This commit is contained in:
parent
53314551f5
commit
6218efac20
9 changed files with 158 additions and 175 deletions
|
|
@ -14,12 +14,12 @@ EAbs. Exp ::= "\\" Ident "." Exp ;
|
||||||
CInt. Const ::= Integer ;
|
CInt. Const ::= Integer ;
|
||||||
CStr. Const ::= String ;
|
CStr. Const ::= String ;
|
||||||
|
|
||||||
TMono. Type1 ::= UIdent ;
|
TMono. Type ::= "Mono" Ident ;
|
||||||
TPoly. Type1 ::= LIdent ;
|
TPoly. Type ::= "Poly" Ident ;
|
||||||
TArrow. Type ::= Type "->" Type1 ;
|
TArrow. Type ::= Type "->" Type1 ;
|
||||||
|
|
||||||
token UIdent (upper (letter | digit | '_')*) ;
|
-- token Upper (upper (letter | digit | '_')*) ;
|
||||||
token LIdent (lower (letter | digit | '_')*) ;
|
-- token Lower (lower (letter | digit | '_')*) ;
|
||||||
|
|
||||||
separator Bind ";" ;
|
separator Bind ";" ;
|
||||||
separator Ident " ";
|
separator Ident " ";
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,10 @@ executable language
|
||||||
Grammar.Print
|
Grammar.Print
|
||||||
Grammar.Skel
|
Grammar.Skel
|
||||||
Grammar.ErrM
|
Grammar.ErrM
|
||||||
-- LambdaLifter
|
|
||||||
TypeChecker.TypeChecker
|
TypeChecker.TypeChecker
|
||||||
TypeChecker.TypeCheckerIr
|
TypeChecker.TypeCheckerIr
|
||||||
-- Renamer.Renamer
|
Renamer.Renamer
|
||||||
-- Renamer.RenamerIr
|
Renamer.RenamerIr
|
||||||
-- Interpreter
|
|
||||||
|
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
add x = \y. x+y;
|
add x = \y. x+y;
|
||||||
|
|
||||||
main = (\z. z+z) ((add 4) 6);
|
main = (\z. z+z) ((add 4) 6);
|
||||||
|
|
||||||
|
|
|
||||||
10
src/Main.hs
10
src/Main.hs
|
|
@ -6,6 +6,7 @@ import Grammar.Print (printTree)
|
||||||
import System.Environment (getArgs)
|
import System.Environment (getArgs)
|
||||||
import System.Exit (exitFailure, exitSuccess)
|
import System.Exit (exitFailure, exitSuccess)
|
||||||
import TypeChecker.TypeChecker (typecheck)
|
import TypeChecker.TypeChecker (typecheck)
|
||||||
|
import Renamer.Renamer (rename)
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = getArgs >>= \case
|
main = getArgs >>= \case
|
||||||
|
|
@ -17,12 +18,11 @@ main = getArgs >>= \case
|
||||||
putStrLn "SYNTAX ERROR"
|
putStrLn "SYNTAX ERROR"
|
||||||
putStrLn err
|
putStrLn err
|
||||||
exitFailure
|
exitFailure
|
||||||
Right prg -> case typecheck prg of
|
Right prg -> case rename prg of
|
||||||
Right prg -> do
|
Right prg -> do
|
||||||
putStrLn "TYPE CHECK SUCCESSFUL"
|
putStrLn "RENAME SUCCESSFUL"
|
||||||
putStrLn . show $ prg
|
putStrLn $ printTree prg
|
||||||
Left err -> do
|
Left err -> do
|
||||||
putStrLn "TYPE CHECK ERROR"
|
putStrLn "FAILED RENAMING"
|
||||||
putStrLn . show $ err
|
putStrLn . show $ err
|
||||||
exitFailure
|
exitFailure
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,90 +1,101 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase, OverloadedRecordDot, OverloadedStrings #-}
|
||||||
{-# LANGUAGE OverloadedRecordDot #-}
|
|
||||||
|
|
||||||
module Renamer.Renamer (rename) where
|
module Renamer.Renamer (rename) where
|
||||||
|
|
||||||
import Control.Applicative (Applicative (liftA2))
|
import Renamer.RenamerIr
|
||||||
import Control.Monad.Except (MonadError (throwError))
|
import Control.Monad.State
|
||||||
import Control.Monad.RWS (MonadState, gets, modify)
|
import Control.Monad.Except
|
||||||
import Control.Monad.State (StateT, evalStateT)
|
import Control.Monad.Reader
|
||||||
|
import Data.Functor.Identity (Identity, runIdentity)
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as S
|
||||||
import Grammar.Abs
|
import Data.Map (Map)
|
||||||
import Grammar.ErrM (Err)
|
import qualified Data.Map as M
|
||||||
import Grammar.Print (printTree)
|
|
||||||
import qualified Renamer.RenamerIr as R
|
|
||||||
|
|
||||||
|
import Renamer.RenamerIr
|
||||||
|
import qualified Grammar.Abs as Old
|
||||||
|
|
||||||
data Cxt = Cxt
|
type Rename = StateT Ctx (ExceptT Error Identity)
|
||||||
{ uniques :: [(Ident, R.Unique)]
|
|
||||||
, nextUnique :: R.Unique
|
data Ctx = Ctx { count :: Integer
|
||||||
, sig :: Set Ident
|
, sig :: Set Ident
|
||||||
}
|
, env :: Map Ident Integer}
|
||||||
|
|
||||||
initCxt :: Cxt
|
run :: Rename a -> Either Error a
|
||||||
initCxt = Cxt
|
run = runIdentity . runExceptT . flip evalStateT initCtx
|
||||||
{ uniques = []
|
|
||||||
, nextUnique = R.Unique 0
|
initCtx :: Ctx
|
||||||
|
initCtx = Ctx { count = 0
|
||||||
, sig = mempty
|
, sig = mempty
|
||||||
}
|
, env = mempty }
|
||||||
|
|
||||||
newtype Rn a = Rn { runRn :: StateT Cxt Err a }
|
rename :: Old.Program -> Either Error RProgram
|
||||||
deriving (Functor, Applicative, Monad, MonadState Cxt, MonadError String)
|
rename = run . renamePrg
|
||||||
|
|
||||||
rename :: Program -> Err R.Program
|
renamePrg :: Old.Program -> Rename RProgram
|
||||||
rename p = evalStateT (runRn $ renameProgram p) initCxt
|
renamePrg (Old.Program xs) = do
|
||||||
|
xs' <- mapM renameBind xs
|
||||||
|
return $ RProgram xs'
|
||||||
|
|
||||||
renameProgram :: Program -> Rn R.Program
|
renameBind :: Old.Bind -> Rename RBind
|
||||||
renameProgram (Program ds (Main e)) = do
|
renameBind (Old.Bind i args e) = do
|
||||||
ds' <- mapM renameDef ds
|
insertSig i
|
||||||
e' <- renameExp e
|
e' <- renameExp (makeLambda (reverse args) e)
|
||||||
pure $ R.Program ds' (R.Main e')
|
return $ RBind i e'
|
||||||
|
where
|
||||||
|
makeLambda :: [Ident] -> Old.Exp -> Old.Exp
|
||||||
|
makeLambda [] e = e
|
||||||
|
makeLambda (x:xs) e = makeLambda xs (Old.EAbs x e)
|
||||||
|
|
||||||
renameDef :: Def -> Rn R.Def
|
renameExp :: Old.Exp -> Rename RExp
|
||||||
renameDef = \case
|
|
||||||
DExp x t _ xs e -> do
|
|
||||||
newSig x
|
|
||||||
xs' <- mapM newUnique xs
|
|
||||||
e' <- renameExp e
|
|
||||||
let e'' = foldr ($) e' . zipWith R.EAbs xs' $ fromTree t
|
|
||||||
pure . R.DBind $ R.Bind x t e''
|
|
||||||
|
|
||||||
renameExp :: Exp -> Rn R.Exp
|
|
||||||
renameExp = \case
|
renameExp = \case
|
||||||
EId x -> R.EId <$> findBind x
|
|
||||||
EInt i -> pure $ R.EInt i
|
|
||||||
EApp e e1 -> liftA2 R.EApp (renameExp e) $ renameExp e1
|
|
||||||
EAdd e e1 -> liftA2 R.EAdd (renameExp e) $ renameExp e1
|
|
||||||
EAbs x t e -> do
|
|
||||||
x' <- newUnique x
|
|
||||||
e' <- renameExp e
|
|
||||||
pure $ R.EAbs x' t e'
|
|
||||||
|
|
||||||
findBind :: Ident -> Rn R.Name
|
Old.EId i -> do
|
||||||
findBind x = lookupUnique x >>= \case
|
st <- get
|
||||||
Just u -> pure $ R.Nu u
|
case M.lookup i st.env of
|
||||||
Nothing -> gets (Set.member x . sig) >>= \case
|
Just n -> return $ RBound n i
|
||||||
False -> throwError ("Unbound variable " ++ printTree x)
|
Nothing -> case S.member i st.sig of
|
||||||
True -> pure $ R.Ni x
|
True -> return $ RFree i
|
||||||
|
False -> throwError $ UnboundVar (show i)
|
||||||
|
|
||||||
newUnique :: Ident -> Rn R.Unique
|
Old.EConst c -> return $ RConst c
|
||||||
newUnique x = do
|
|
||||||
u <- gets nextUnique
|
|
||||||
modify $ \env -> env { nextUnique = succ u
|
|
||||||
, uniques = (x, u) : env.uniques
|
|
||||||
}
|
|
||||||
pure u
|
|
||||||
|
|
||||||
newSig :: Ident -> Rn ()
|
Old.EAnn e t -> flip RAnn t <$> renameExp e
|
||||||
newSig x = modify $ \cxt -> cxt { sig = Set.insert x cxt.sig}
|
|
||||||
|
|
||||||
lookupUnique :: Ident -> Rn (Maybe R.Unique)
|
Old.EApp e1 e2 -> RApp <$> renameExp e1 <*> renameExp e2
|
||||||
lookupUnique x = lookup x <$> gets uniques
|
|
||||||
|
|
||||||
fromTree :: Type -> [Type]
|
Old.EAdd e1 e2 -> RAdd <$> renameExp e1 <*> renameExp e2
|
||||||
fromTree = fromTree' []
|
|
||||||
|
|
||||||
fromTree' :: [Type] -> Type -> [Type]
|
-- Convert let-expressions to lambdas
|
||||||
fromTree' acc = \case
|
Old.ELet i e1 e2 -> renameExp (Old.EApp (Old.EAbs i e2) e1)
|
||||||
TFun t t1 -> acc ++ [t] ++ fromTree t1
|
|
||||||
other -> other : acc
|
Old.EAbs i e -> do
|
||||||
|
n <- cnt
|
||||||
|
ctx <- get
|
||||||
|
insertEnv i n
|
||||||
|
re <- renameExp e
|
||||||
|
return $ RAbs n i re
|
||||||
|
|
||||||
|
-- | Get current count and increase it by one
|
||||||
|
cnt :: Rename Integer
|
||||||
|
cnt = do
|
||||||
|
st <- get
|
||||||
|
put (Ctx { count = succ st.count
|
||||||
|
, sig = st.sig
|
||||||
|
, env = st.env })
|
||||||
|
return st.count
|
||||||
|
|
||||||
|
insertEnv :: Ident -> Integer -> Rename ()
|
||||||
|
insertEnv i n = do
|
||||||
|
c <- get
|
||||||
|
put ( Ctx { env = M.insert i n c.env , sig = c.sig , count = c.count} )
|
||||||
|
|
||||||
|
insertSig :: Ident -> Rename ()
|
||||||
|
insertSig i = do
|
||||||
|
c <- get
|
||||||
|
put ( Ctx { sig = S.insert i c.sig , env = c.env , count = c.count } )
|
||||||
|
|
||||||
|
data Error = UnboundVar String
|
||||||
|
|
||||||
|
instance Show Error where
|
||||||
|
show (UnboundVar str) = "Unbound variable: " <> str
|
||||||
|
|
|
||||||
|
|
@ -1,84 +1,51 @@
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
|
||||||
module Renamer.RenamerIr where
|
module Renamer.RenamerIr (module Grammar.Abs, RExp (..), RBind (..), RProgram (..)) where
|
||||||
|
|
||||||
import Grammar.Abs (Ident, Type (..))
|
import Grammar.Abs (
|
||||||
|
Bind (..),
|
||||||
|
Const (..),
|
||||||
|
Ident (..),
|
||||||
|
Program (..),
|
||||||
|
Type (..),
|
||||||
|
)
|
||||||
import Grammar.Print
|
import Grammar.Print
|
||||||
|
|
||||||
|
data RProgram = RProgram [RBind]
|
||||||
|
deriving (Eq, Show, Read, Ord)
|
||||||
|
|
||||||
data Program = Program [Def] Main
|
data RBind = RBind Ident RExp
|
||||||
|
deriving (Eq, Show, Read, Ord)
|
||||||
|
|
||||||
|
data RExp
|
||||||
|
= RAnn RExp Type
|
||||||
|
| RBound Integer Ident
|
||||||
|
| RFree Ident
|
||||||
|
| RConst Const
|
||||||
|
| RApp RExp RExp
|
||||||
|
| RAdd RExp RExp
|
||||||
|
| RAbs Integer Ident RExp
|
||||||
deriving (Eq, Ord, Show, Read)
|
deriving (Eq, Ord, Show, Read)
|
||||||
|
|
||||||
newtype Main = Main Exp
|
instance Print RProgram where
|
||||||
deriving (Eq, Ord, Show, Read)
|
|
||||||
|
|
||||||
|
|
||||||
newtype Def = DBind Bind
|
|
||||||
deriving (Eq, Ord, Show, Read)
|
|
||||||
|
|
||||||
data Name = Nu Unique | Ni Ident deriving (Ord, Show, Eq, Read)
|
|
||||||
|
|
||||||
newtype Unique = Unique Int deriving (Enum, Eq, Read, Ord)
|
|
||||||
instance Show Unique where show (Unique i) = "x" ++ show i
|
|
||||||
|
|
||||||
data Exp
|
|
||||||
= EId Name
|
|
||||||
| EInt Integer
|
|
||||||
| EApp Exp Exp
|
|
||||||
| EAdd Exp Exp
|
|
||||||
| EAbs Unique Type Exp
|
|
||||||
deriving (Eq, Ord, Show, Read)
|
|
||||||
|
|
||||||
|
|
||||||
data Bind = Bind Ident Type Exp
|
|
||||||
deriving (Eq, Ord, Show, Read)
|
|
||||||
|
|
||||||
|
|
||||||
instance Print Program where
|
|
||||||
prt i = \case
|
prt i = \case
|
||||||
Program defs main -> prPrec i 0 (concatD [prt 0 defs, prt 0 main])
|
RProgram defs -> prPrec i 0 (concatD [prt 0 defs])
|
||||||
|
|
||||||
|
instance Print RBind where
|
||||||
instance Print Def where
|
|
||||||
prt i (DBind b) = prPrec i 0 $ concatD [prt 0 b, doc (showString ";")]
|
|
||||||
|
|
||||||
instance Print Bind where
|
|
||||||
prt i = \case
|
prt i = \case
|
||||||
Bind x t e -> prPrec i 0 $ concatD
|
RBind x e ->
|
||||||
|
prPrec i 0 $
|
||||||
|
concatD
|
||||||
[ prt 0 x
|
[ prt 0 x
|
||||||
, doc (showString ":")
|
|
||||||
, prt 0 t
|
|
||||||
, doc (showString "=")
|
, doc (showString "=")
|
||||||
, prt 0 e]
|
, prt 0 e
|
||||||
|
|
||||||
instance Print [Def] where
|
|
||||||
prt _ [] = concatD []
|
|
||||||
prt _ (x:xs) = concatD [prt 0 x, prt 0 xs]
|
|
||||||
|
|
||||||
|
|
||||||
instance Print Main where
|
|
||||||
prt i = \case
|
|
||||||
Main exp -> prPrec i 0 $ concatD
|
|
||||||
[ doc (showString "main")
|
|
||||||
, doc (showString "=")
|
|
||||||
, prt 0 exp
|
|
||||||
, doc (showString ";")
|
|
||||||
]
|
]
|
||||||
|
|
||||||
instance Print Exp where
|
instance Print RExp where
|
||||||
prt i = \case
|
prt i = \case
|
||||||
EId u -> prPrec i 3 (concatD [prt 0 u])
|
RBound n _ -> prPrec i 3 (concatD [prt 0 ("var" ++ show n)])
|
||||||
EInt n -> prPrec i 3 (concatD [prt 0 n])
|
RFree id -> prPrec i 3 (concatD [prt 0 id])
|
||||||
EApp e e1 -> prPrec i 2 (concatD [prt 2 e, prt 3 e1])
|
RConst n -> prPrec i 3 (concatD [prt 0 n])
|
||||||
EAdd e e1 -> prPrec i 1 (concatD [prt 1 e, doc (showString "+"), prt 2 e1])
|
RApp e e1 -> prPrec i 2 (concatD [prt 2 e, prt 3 e1])
|
||||||
EAbs u t e -> prPrec i 0 (concatD [doc (showString "\\"), prt 0 u, doc (showString ":"), prt 0 t, doc (showString "."), prt 0 e])
|
RAdd e e1 -> prPrec i 1 (concatD [prt 1 e, doc (showString "+"), prt 2 e1])
|
||||||
|
RAbs u id e -> prPrec i 0 (concatD [doc (showString "\\"), prt 0 ("var" ++ show u), doc (showString "."), prt 0 e])
|
||||||
|
|
||||||
instance Print Name where
|
|
||||||
prt _ = \case
|
|
||||||
Ni i -> prt 0 i
|
|
||||||
Nu u -> prt 0 u
|
|
||||||
|
|
||||||
instance Print Unique where
|
|
||||||
prt _ = doc . showString . show
|
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ inferExp = \case
|
||||||
return infT
|
return infT
|
||||||
|
|
||||||
Old.EConst c -> case c of
|
Old.EConst c -> case c of
|
||||||
(Old.CInt i) -> return (TMono $ UIdent "Int")
|
(Old.CInt i) -> return (TMono "Int")
|
||||||
(Old.CStr s) -> return (TMono $ UIdent "String")
|
(Old.CStr s) -> return (TMono "String")
|
||||||
|
|
||||||
Old.EAdd e1 e2 -> do
|
Old.EAdd e1 e2 -> do
|
||||||
let int = TMono "Int"
|
let int = TMono "Int"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
|
||||||
module TypeChecker.TypeCheckerIr (module Grammar.Abs, Exp) where
|
module TypeChecker.TypeCheckerIr where
|
||||||
|
|
||||||
import Grammar.Abs (Program(..), Ident(..), Bind(..), Const(..), Type(..), UIdent(..), LIdent(..))
|
import Renamer.RenamerIr
|
||||||
|
|
||||||
data Exp
|
data TProgram = TProgram [TBind]
|
||||||
= EAnn Exp Type
|
|
||||||
| EId Ident Type
|
data TBind = TBind Ident Type TExp
|
||||||
| EConst Const Type
|
|
||||||
| EApp Exp Exp Type
|
data TExp
|
||||||
| EAdd Exp Exp Type
|
= TAnn TExp Type
|
||||||
| EAbs Ident Exp Type
|
| TBound Integer Ident Type
|
||||||
|
| TFree Ident Type
|
||||||
|
| TConst Const Type
|
||||||
|
| TApp TExp TExp Type
|
||||||
|
| TAdd TExp TExp Type
|
||||||
|
| TAbs Integer Ident TExp Type
|
||||||
deriving (Eq, Ord, Show, Read)
|
deriving (Eq, Ord, Show, Read)
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
main = 3;
|
letters = let x = 1
|
||||||
|
in let y = 2
|
||||||
|
in let z = 3
|
||||||
|
in x + y + z
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue