Fix interpreter
This commit is contained in:
parent
e212c79a44
commit
d67eddcf0f
5 changed files with 105 additions and 33 deletions
5
Makefile
5
Makefile
|
|
@ -28,5 +28,10 @@ test :
|
||||||
./language ./sample-programs/basic-3
|
./language ./sample-programs/basic-3
|
||||||
./language ./sample-programs/basic-4
|
./language ./sample-programs/basic-4
|
||||||
./language ./sample-programs/basic-5
|
./language ./sample-programs/basic-5
|
||||||
|
./language ./sample-programs/basic-5
|
||||||
|
./language ./sample-programs/basic-6
|
||||||
|
./language ./sample-programs/basic-7
|
||||||
|
./language ./sample-programs/basic-8
|
||||||
|
./language ./sample-programs/basic-9
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,10 @@ executable language
|
||||||
Grammar.Par
|
Grammar.Par
|
||||||
Grammar.Print
|
Grammar.Print
|
||||||
Grammar.Skel
|
Grammar.Skel
|
||||||
|
Grammar.ErrM
|
||||||
LambdaLifter
|
LambdaLifter
|
||||||
Auxiliary
|
Auxiliary
|
||||||
-- Interpreter
|
Interpreter
|
||||||
|
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
|
|
||||||
|
|
|
||||||
4
sample-programs/basic-9
Normal file
4
sample-programs/basic-9
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
main = (\f.\x.\y. f x + f y) (\x. x+x) ((\x. x+1) ((\x. x+3) 2)) 4
|
||||||
|
|
@ -1,38 +1,72 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
{-# LANGUAGE OverloadedRecordDot #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
module Interpreter where
|
module Interpreter where
|
||||||
|
|
||||||
|
import Auxiliary (maybeToRightM)
|
||||||
import Control.Applicative (Applicative)
|
import Control.Applicative (Applicative)
|
||||||
import Control.Monad.Except (Except, MonadError (throwError),
|
import Control.Monad.Except (Except, MonadError (throwError),
|
||||||
liftEither)
|
liftEither)
|
||||||
|
import Control.Monad.State (MonadState, StateT, evalStateT)
|
||||||
import Data.Either.Combinators (maybeToRight)
|
import Data.Either.Combinators (maybeToRight)
|
||||||
import Data.Map (Map)
|
import Data.Map (Map)
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
import Data.Maybe (maybe)
|
||||||
import Grammar.Abs
|
import Grammar.Abs
|
||||||
|
import Grammar.ErrM (Err)
|
||||||
import Grammar.Print (printTree)
|
import Grammar.Print (printTree)
|
||||||
|
|
||||||
interpret :: Program -> Except String Integer
|
interpret :: Program -> Err Integer
|
||||||
interpret (Program e) =
|
interpret (Program scs) = do
|
||||||
eval mempty e >>= \case
|
main <- findMain scs
|
||||||
|
eval (initCxt scs) main >>=
|
||||||
|
\case
|
||||||
VClosure {} -> throwError "main evaluated to a function"
|
VClosure {} -> throwError "main evaluated to a function"
|
||||||
VInt i -> pure i
|
VInt i -> pure i
|
||||||
|
|
||||||
|
|
||||||
|
initCxt :: [Bind] -> Cxt
|
||||||
|
initCxt scs =
|
||||||
|
Cxt { env = mempty
|
||||||
|
, sig = foldr insert mempty $ map expandLambdas scs
|
||||||
|
}
|
||||||
|
where insert (Bind name _ rhs) = Map.insert name rhs
|
||||||
|
|
||||||
|
expandLambdas :: Bind -> Bind
|
||||||
|
expandLambdas (Bind name parms rhs) = Bind name [] $ foldr EAbs rhs parms
|
||||||
|
|
||||||
|
|
||||||
|
findMain :: [Bind] -> Err Exp
|
||||||
|
findMain [] = throwError "No main!"
|
||||||
|
findMain (sc:scs) = case sc of
|
||||||
|
Bind "main" _ rhs -> pure rhs
|
||||||
|
_ -> findMain scs
|
||||||
|
|
||||||
data Val = VInt Integer
|
data Val = VInt Integer
|
||||||
| VClosure Cxt Ident Exp
|
| VClosure Env Ident Exp
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
type Cxt = Map Ident Val
|
type Env = Map Ident Val
|
||||||
|
type Sig = Map Ident Exp
|
||||||
|
|
||||||
eval :: Cxt -> Exp -> Except String Val
|
data Cxt = Cxt
|
||||||
|
{ env :: Map Ident Val
|
||||||
|
, sig :: Map Ident Exp
|
||||||
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
|
eval :: Cxt -> Exp -> Err Val
|
||||||
eval cxt = \case
|
eval cxt = \case
|
||||||
|
|
||||||
|
|
||||||
-- ------------ x ∈ γ
|
-- ------------ x ∈ γ
|
||||||
-- γ ⊢ x ⇓ γ(x)
|
-- γ ⊢ x ⇓ γ(x)
|
||||||
|
|
||||||
EId x ->
|
EId x -> do
|
||||||
maybeToRightM
|
case Map.lookup x cxt.env of
|
||||||
("Unbound variable:" ++ printTree x)
|
Just e -> pure e
|
||||||
$ Map.lookup x cxt
|
Nothing ->
|
||||||
|
case Map.lookup x cxt.sig of
|
||||||
|
Just e -> eval (emptyEnv cxt) e
|
||||||
|
Nothing -> throwError ("Unbound variable: " ++ printTree x)
|
||||||
|
|
||||||
-- ---------
|
-- ---------
|
||||||
-- γ ⊢ i ⇓ i
|
-- γ ⊢ i ⇓ i
|
||||||
|
|
@ -50,13 +84,15 @@ eval cxt = \case
|
||||||
VInt _ -> throwError "Not a function"
|
VInt _ -> throwError "Not a function"
|
||||||
VClosure delta x f -> do
|
VClosure delta x f -> do
|
||||||
v <- eval cxt e1
|
v <- eval cxt e1
|
||||||
eval (Map.insert x v delta) f
|
let cxt' = putEnv (Map.insert x v delta) cxt
|
||||||
|
eval cxt' f
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- -----------------------------
|
-- -----------------------------
|
||||||
-- γ ⊢ λx. f ⇓ let γ in λx. f
|
-- γ ⊢ λx. f ⇓ let γ in λx. f
|
||||||
|
|
||||||
EAbs x e -> pure $ VClosure cxt x e
|
EAbs par e -> pure $ VClosure cxt.env par e
|
||||||
|
|
||||||
|
|
||||||
-- γ ⊢ e ⇓ v
|
-- γ ⊢ e ⇓ v
|
||||||
|
|
@ -71,8 +107,11 @@ eval cxt = \case
|
||||||
(VInt i, VInt i1) -> pure $ VInt (i + i1)
|
(VInt i, VInt i1) -> pure $ VInt (i + i1)
|
||||||
_ -> throwError "Can't add a function"
|
_ -> throwError "Can't add a function"
|
||||||
|
|
||||||
|
ELet _ _ -> throwError "ELet pattern match should never occur!"
|
||||||
|
|
||||||
|
|
||||||
maybeToRightM :: MonadError l m => l -> Maybe r -> m r
|
emptyEnv :: Cxt -> Cxt
|
||||||
maybeToRightM err = liftEither . maybeToRight err
|
emptyEnv cxt = cxt { env = mempty }
|
||||||
|
|
||||||
|
putEnv :: Env -> Cxt -> Cxt
|
||||||
|
putEnv env cxt = cxt { env = env }
|
||||||
|
|
|
||||||
49
src/Main.hs
49
src/Main.hs
|
|
@ -1,8 +1,10 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
|
import Grammar.ErrM (Err)
|
||||||
import Grammar.Par (myLexer, pProgram)
|
import Grammar.Par (myLexer, pProgram)
|
||||||
import Grammar.Print (printTree)
|
import Grammar.Print (printTree)
|
||||||
|
import Interpreter (interpret)
|
||||||
import LambdaLifter (abstract, freeVars, lambdaLift)
|
import LambdaLifter (abstract, freeVars, lambdaLift)
|
||||||
import System.Environment (getArgs)
|
import System.Environment (getArgs)
|
||||||
import System.Exit (exitFailure, exitSuccess)
|
import System.Exit (exitFailure, exitSuccess)
|
||||||
|
|
@ -10,20 +12,41 @@ import System.Exit (exitFailure, exitSuccess)
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = getArgs >>= \case
|
main = getArgs >>= \case
|
||||||
[] -> print "Required file path missing"
|
[] -> print "Required file path missing"
|
||||||
(x:_) -> do
|
(s:_) -> main' s
|
||||||
file <- readFile x
|
|
||||||
case pProgram (myLexer file) of
|
main' :: String -> IO ()
|
||||||
Left err -> do
|
main' s = do
|
||||||
putStrLn "SYNTAX ERROR"
|
file <- readFile s
|
||||||
putStrLn err
|
|
||||||
exitFailure
|
putStrLn "\n-- parse"
|
||||||
Right prg -> do
|
parsed <- fromSyntaxErr . pProgram $ myLexer file
|
||||||
putStrLn "-- Parse"
|
putStrLn $ printTree parsed
|
||||||
putStrLn $ printTree prg
|
|
||||||
putStrLn "\n-- Lambda lifter"
|
putStrLn "\n-- Lambda Lifter"
|
||||||
putStrLn . printTree $ lambdaLift prg
|
let lifted = lambdaLift parsed
|
||||||
putStrLn ""
|
putStrLn $ printTree lifted
|
||||||
|
|
||||||
|
interpred <- fromInterpreterErr $ interpret lifted
|
||||||
|
putStrLn "\n-- interpret"
|
||||||
|
print interpred
|
||||||
|
|
||||||
exitSuccess
|
exitSuccess
|
||||||
|
|
||||||
|
|
||||||
|
fromSyntaxErr :: Err a -> IO a
|
||||||
|
fromSyntaxErr = either
|
||||||
|
(\err -> do
|
||||||
|
putStrLn "\nSYNTAX ERROR"
|
||||||
|
putStrLn err
|
||||||
|
exitFailure)
|
||||||
|
pure
|
||||||
|
|
||||||
|
fromInterpreterErr :: Err a -> IO a
|
||||||
|
fromInterpreterErr = either
|
||||||
|
(\err -> do
|
||||||
|
putStrLn "\nINTERPRETER ERROR"
|
||||||
|
putStrLn err
|
||||||
|
exitFailure)
|
||||||
|
pure
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue