{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RecursiveDo #-}
module Codegen.ExprGen.ControlFlow where
import qualified Ast.Types as AT
import qualified Codegen.Errors as CC
import qualified Codegen.ExprGen.Cast as CC
import {-# SOURCE #-} qualified Codegen.ExprGen.ExprGen as EG
import qualified Codegen.State as CS
import qualified Codegen.Utils as U
import qualified Control.Monad as CM
import qualified Control.Monad.Except as E
import qualified Control.Monad.State as S
import qualified LLVM.AST as AST
import qualified LLVM.AST.Constant as C
import qualified LLVM.AST.IntegerPredicate as IP
import qualified LLVM.AST.Type as T
import qualified LLVM.IRBuilder.Instruction as I
import qualified LLVM.IRBuilder.Monad as IRM
import qualified Shared.Utils as SU
generateIf :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateIf :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateIf (AT.If SrcLoc
_ Expr
cond Expr
thenExpr Maybe Expr
elseExpr) = mdo
Operand
condVal <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
cond
Operand
condTest <- IntegerPredicate -> Operand -> Operand -> m Operand
forall (m :: * -> *).
MonadIRBuilder m =>
IntegerPredicate -> Operand -> Operand -> m Operand
I.icmp IntegerPredicate
IP.NE Operand
condVal (Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer -> Constant
C.Int Word32
1 Integer
0)
Operand -> Name -> Name -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Name -> Name -> m ()
I.condBr Operand
condTest Name
thenBlock Name
elseBlock
Name
thenBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"if.then"
Operand
thenVal <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
thenExpr
Bool
thenTerminated <- m Bool
forall (m :: * -> *). MonadIRBuilder m => m Bool
IRM.hasTerminator
()
_ <- Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
S.unless Bool
thenTerminated (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
mergeBlock
Name
thenBlockName <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.currentBlock
Name
elseBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"if.else"
Operand
elseVal <- case Maybe Expr
elseExpr of
Just Expr
e -> Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
e
Maybe Expr
Nothing -> Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Undef Type
T.void)
Bool
elseTerminated <- m Bool
forall (m :: * -> *). MonadIRBuilder m => m Bool
IRM.hasTerminator
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
S.unless Bool
elseTerminated (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
mergeBlock
Name
elseBlockName <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.currentBlock
Name
mergeBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"if.merge"
let validBrs :: [(Operand, Name)]
validBrs =
[(Operand
thenVal, Name
thenBlockName) | Bool -> Bool
not Bool
thenTerminated]
[(Operand, Name)] -> [(Operand, Name)] -> [(Operand, Name)]
forall a. [a] -> [a] -> [a]
++ [(Operand
elseVal, Name
elseBlockName) | Bool -> Bool
not Bool
elseTerminated]
case [(Operand, Name)]
validBrs of
[] -> Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Type -> Constant
C.Undef Type
T.void)
[(Operand
v, Name
_)] -> Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Operand
v
[(Operand, Name)]
_ -> [(Operand, Name)] -> m Operand
forall (m :: * -> *).
MonadIRBuilder m =>
[(Operand, Name)] -> m Operand
I.phi [(Operand, Name)]
validBrs
generateIf Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedDefinition Expr
expr
generateFromLoop :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateFromLoop :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateFromLoop (AT.From SrcLoc
loc Expr
_ Expr
endExpr Expr
stepExpr declExpr :: Expr
declExpr@(AT.Declaration SrcLoc
_ String
varName Type
varType Maybe Expr
_) Expr
bodyExpr) = mdo
Operand
_ <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
declExpr
Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
condBlock
Name
condBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"for.cond"
Operand
condVal <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr (Expr -> m Operand) -> Expr -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> Operation -> Expr -> Expr -> Expr
AT.Op SrcLoc
loc Operation
AT.Gt Expr
endExpr Expr
zeroExpr
Operand
boolCondVal <- SrcLoc -> Operand -> m Operand
forall (m :: * -> *).
MonadCodegen m =>
SrcLoc -> Operand -> m Operand
CC.toBool SrcLoc
loc Operand
condVal
Operand -> Name -> Name -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Name -> Name -> m ()
I.condBr Operand
boolCondVal Name
forwardBlock Name
backwardBlock
Name
forwardBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"for.cond.forward"
Operand
forwardVal <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr (Expr -> m Operand) -> Expr -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> Operation -> Expr -> Expr -> Expr
AT.Op SrcLoc
loc Operation
AT.Lt Expr
varExpr Expr
endExpr
Operand
boolForwardVal <- SrcLoc -> Operand -> m Operand
forall (m :: * -> *).
MonadCodegen m =>
SrcLoc -> Operand -> m Operand
CC.toBool SrcLoc
loc Operand
forwardVal
Operand -> Name -> Name -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Name -> Name -> m ()
I.condBr Operand
boolForwardVal Name
bodyBlock Name
exitBlock
Name
backwardBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"for.cond.backward"
Operand
backwardVal <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr (Expr -> m Operand) -> Expr -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> Operation -> Expr -> Expr -> Expr
AT.Op SrcLoc
loc Operation
AT.Gt Expr
varExpr Expr
endExpr
Operand
boolBackwardVal <- SrcLoc -> Operand -> m Operand
forall (m :: * -> *).
MonadCodegen m =>
SrcLoc -> Operand -> m Operand
CC.toBool SrcLoc
loc Operand
backwardVal
Operand -> Name -> Name -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Name -> Name -> m ()
I.condBr Operand
boolBackwardVal Name
bodyBlock Name
exitBlock
Name
bodyBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"for.body"
LoopState
oldLoopState <- (CodegenState -> LoopState) -> m LoopState
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
S.gets CodegenState -> LoopState
CS.loopState
(CodegenState -> CodegenState) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
S.modify (\CodegenState
s -> CodegenState
s {loopState :: LoopState
CS.loopState = (Name, Name) -> LoopState
forall a. a -> Maybe a
Just (Name
stepBlock, Name
exitBlock)})
Operand
_ <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
bodyExpr
(CodegenState -> CodegenState) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
S.modify (\CodegenState
s -> CodegenState
s {loopState :: LoopState
CS.loopState = LoopState
oldLoopState})
Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
stepBlock
Name
stepBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"for.step"
Operand
_ <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
stepExpr
Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
condBlock
Name
exitBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"for.exit"
Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Null Type
T.i8
where
varExpr :: Expr
varExpr = SrcLoc -> String -> Type -> Expr
AT.Var SrcLoc
loc String
varName Type
varType
zeroExpr :: Expr
zeroExpr = SrcLoc -> Literal -> Expr
AT.Lit SrcLoc
loc (Integer -> Literal
AT.LInt Integer
0)
generateFromLoop Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedForDefinition Expr
expr
generateWhileLoop :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateWhileLoop :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateWhileLoop (AT.While SrcLoc
loc Expr
condExpr Expr
bodyExpr) = mdo
Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
condBlock
Name
condBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"while.cond"
Operand
condVal <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
condExpr
Operand
boolCondVal <- SrcLoc -> Operand -> m Operand
forall (m :: * -> *).
MonadCodegen m =>
SrcLoc -> Operand -> m Operand
CC.toBool SrcLoc
loc Operand
condVal
Operand -> Name -> Name -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Name -> Name -> m ()
I.condBr Operand
boolCondVal Name
bodyBlock Name
exitBlock
Name
bodyBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"while.body"
LoopState
oldLoopState <- (CodegenState -> LoopState) -> m LoopState
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
S.gets CodegenState -> LoopState
CS.loopState
(CodegenState -> CodegenState) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
S.modify (\CodegenState
s -> CodegenState
s {loopState :: LoopState
CS.loopState = (Name, Name) -> LoopState
forall a. a -> Maybe a
Just (Name
condBlock, Name
exitBlock)})
Operand
_ <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
bodyExpr
(CodegenState -> CodegenState) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
S.modify (\CodegenState
s -> CodegenState
s {loopState :: LoopState
CS.loopState = LoopState
oldLoopState})
Bool
bodyTerminated <- m Bool
forall (m :: * -> *). MonadIRBuilder m => m Bool
IRM.hasTerminator
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
CM.unless Bool
bodyTerminated (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
condBlock
Name
exitBlock <- m Name
forall (m :: * -> *). MonadIRBuilder m => m Name
IRM.block m Name -> ShortByteString -> m Name
forall (m :: * -> *) r.
MonadIRBuilder m =>
m r -> ShortByteString -> m r
`IRM.named` String -> ShortByteString
U.stringToByteString String
"while.exit"
Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Null Type
T.i8
generateWhileLoop Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedWhileDefinition Expr
expr
generateBreak :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateBreak :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateBreak (AT.Break SrcLoc
loc) = do
CodegenState
state <- m CodegenState
forall s (m :: * -> *). MonadState s m => m s
S.get
case CodegenState -> LoopState
CS.loopState CodegenState
state of
Just (Name
_, Name
breakBlock) -> do
Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
breakBlock
Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Undef Type
T.void
LoopState
Nothing -> CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError SrcLoc
loc CodegenErrorType
CC.BreakOutsideLoop
generateBreak Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedDefinition Expr
expr
generateContinue :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateContinue :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateContinue (AT.Continue SrcLoc
loc) = do
CodegenState
state <- m CodegenState
forall s (m :: * -> *). MonadState s m => m s
S.get
case CodegenState -> LoopState
CS.loopState CodegenState
state of
Just (Name
continueBlock, Name
_) -> do
Name -> m ()
forall (m :: * -> *). MonadIRBuilder m => Name -> m ()
I.br Name
continueBlock
Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Undef Type
T.void
LoopState
Nothing -> CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError SrcLoc
loc CodegenErrorType
CC.ContinueOutsideLoop
generateContinue Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedDefinition Expr
expr
generateReturn :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateReturn :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateReturn (AT.Return SrcLoc
_ Maybe Expr
mExpr) = do
case Maybe Expr
mExpr of
Just Expr
expr -> do
Operand
result <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
expr
Operand -> m ()
forall (m :: * -> *). MonadIRBuilder m => Operand -> m ()
I.ret Operand
result
Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Operand
result
Maybe Expr
Nothing -> do
m ()
forall (m :: * -> *). MonadIRBuilder m => m ()
I.retVoid
Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Undef Type
T.void
generateReturn Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedDefinition Expr
expr
generateBlock :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateBlock :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateBlock (AT.Block []) = Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Operand -> m Operand) -> Operand -> m Operand
forall a b. (a -> b) -> a -> b
$ Constant -> Operand
AST.ConstantOperand (Constant -> Operand) -> Constant -> Operand
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Undef Type
T.void
generateBlock (AT.Block [Expr]
exprs) = do
[Operand] -> Operand
forall a. HasCallStack => [a] -> a
last ([Operand] -> Operand) -> m [Operand] -> m Operand
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Expr -> m Operand) -> [Expr] -> m [Operand]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr [Expr]
exprs
generateBlock Expr
expr =
CodegenError -> m Operand
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Operand) -> CodegenError -> m Operand
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Expr -> CodegenErrorType
CC.UnsupportedDefinition Expr
expr