{-# LANGUAGE FlexibleContexts #-}

module Codegen.ExprGen.Variable where

import qualified Ast.Types as AT
import qualified Codegen.Errors as CC
import qualified Codegen.ExprGen.Cast as EC
import qualified Codegen.ExprGen.DataValue as ED
import {-# SOURCE #-} qualified Codegen.ExprGen.ExprGen as EG
import qualified Codegen.ExprGen.Types as ET
import qualified Codegen.State as CS
import qualified Control.Monad.Except as E
import qualified Data.List as L
import qualified Data.Maybe as M
import qualified LLVM.AST as AST
import qualified LLVM.AST.AddrSpace as AS
import qualified LLVM.AST.Constant as C
import qualified LLVM.AST.Float as FF
import qualified LLVM.AST.Global as G
import qualified LLVM.AST.Linkage as LK
import qualified LLVM.AST.Type as T
import qualified LLVM.AST.Typed as TD
import qualified LLVM.AST.Visibility as V
import qualified LLVM.IRBuilder.Constant as IC
import qualified LLVM.IRBuilder.Instruction as I
import qualified LLVM.IRBuilder.Module as M
import qualified Shared.Utils as SU

-- | Generate LLVM code for declarations.
generateDeclaration :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateDeclaration :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateDeclaration (AT.Declaration SrcLoc
loc String
name Type
typ Maybe Expr
mInitExpr) = do
  Maybe Operand
maybeVar <- String -> m (Maybe Operand)
forall (m :: * -> *). VarBinding m => String -> m (Maybe Operand)
CS.getVar String
name
  case Maybe Operand
maybeVar of
    Just Operand
ptr -> do
      case Maybe Expr
mInitExpr of
        Just Expr
initExpr -> do
          Operand
initValue <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
initExpr
          Operand
initValue' <- SrcLoc -> Operand -> Type -> m Operand
forall (m :: * -> *).
MonadCodegen m =>
SrcLoc -> Operand -> Type -> m Operand
EC.ensureMatchingType SrcLoc
loc Operand
initValue (Type -> Type
forall a. ToLLVM a => a -> Type
ET.toLLVM Type
typ)
          Operand -> Word32 -> Operand -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> Operand -> m ()
I.store Operand
ptr Word32
0 Operand
initValue'
          Operand -> Word32 -> m Operand
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> m Operand
I.load Operand
ptr Word32
0
        Maybe Expr
Nothing -> Operand -> Word32 -> m Operand
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> m Operand
I.load Operand
ptr Word32
0
    Maybe Operand
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 -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ String -> CodegenErrorType
CC.VariableNotFound String
name
generateDeclaration 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

-- | Generate LLVM code for literals.
generateLiteral :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateLiteral :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateLiteral (AT.Lit SrcLoc
loc Literal
lit) = do
  Constant
constant <- Literal -> SrcLoc -> m Constant
forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Literal -> SrcLoc -> m Constant
generateConstant Literal
lit SrcLoc
loc
  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
constant
generateLiteral 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

-- | Generate LLVM code for constants.
generateConstant :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Literal -> AT.SrcLoc -> m C.Constant
generateConstant :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Literal -> SrcLoc -> m Constant
generateConstant Literal
lit SrcLoc
loc = case Literal
lit of
  AT.LInt Integer
n -> Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer -> Constant
C.Int Word32
32 (Integer -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n)
  AT.LChar Char
c -> Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer -> Constant
C.Int Word32
8 (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> Int -> Integer
forall a b. (a -> b) -> a -> b
$ Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
c)
  AT.LBool Bool
b -> Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ Word32 -> Integer -> Constant
C.Int Word32
1 (if Bool
b then Integer
1 else Integer
0)
  Literal
AT.LNull -> Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ Type -> Constant
C.Null Type
T.i8
  AT.LFloat Double
f -> Constant -> m Constant
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ SomeFloat -> Constant
C.Float (Float -> SomeFloat
FF.Single (Double -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac Double
f))
  AT.LDouble Double
f -> Constant -> m Constant
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ SomeFloat -> Constant
C.Float (Double -> SomeFloat
FF.Double (Double -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Double
f))
  AT.LArray [Literal]
elems -> do
    let (Literal
headElem, [Literal]
_) = Maybe (Literal, [Literal]) -> (Literal, [Literal])
forall a. HasCallStack => Maybe a -> a
M.fromJust (Maybe (Literal, [Literal]) -> (Literal, [Literal]))
-> Maybe (Literal, [Literal]) -> (Literal, [Literal])
forall a b. (a -> b) -> a -> b
$ [Literal] -> Maybe (Literal, [Literal])
forall a. [a] -> Maybe (a, [a])
L.uncons [Literal]
elems
    case Literal
headElem of
      AT.LChar Char
_ -> do
        Operand
strPtr <- String -> m Operand
forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
String -> m Operand
createGlobalString [Char
c | AT.LChar Char
c <- [Literal]
elems]
        case Operand
strPtr of
          AST.ConstantOperand Constant
c -> Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Constant
c
          Operand
_ -> CodegenError -> m Constant
forall a. CodegenError -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
E.throwError (CodegenError -> m Constant) -> CodegenError -> m Constant
forall a b. (a -> b) -> a -> b
$ SrcLoc -> CodegenErrorType -> CodegenError
CC.CodegenError SrcLoc
loc (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ Literal -> CodegenErrorType
CC.UnsupportedLiteral Literal
lit
      Literal
_ -> do
        [Constant]
constants <- (Literal -> m Constant) -> [Literal] -> m [Constant]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Literal -> SrcLoc -> m Constant
forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Literal -> SrcLoc -> m Constant
`generateConstant` SrcLoc
loc) [Literal]
elems
        Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ Type -> [Constant] -> Constant
C.Array (Constant -> Type
forall a. Typed a => a -> Type
TD.typeOf (Constant -> Type) -> Constant -> Type
forall a b. (a -> b) -> a -> b
$ [Constant] -> Constant
forall a. HasCallStack => [a] -> a
head [Constant]
constants) [Constant]
constants
  AT.LStruct [(String, Literal)]
fields -> do
    let ([String]
_, [Literal]
values) = [(String, Literal)] -> ([String], [Literal])
forall a b. [(a, b)] -> ([a], [b])
unzip [(String, Literal)]
fields
    [Constant]
constants <- (Literal -> m Constant) -> [Literal] -> m [Constant]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Literal -> SrcLoc -> m Constant
forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Literal -> SrcLoc -> m Constant
`generateConstant` SrcLoc
loc) [Literal]
values
    Constant -> m Constant
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Constant -> m Constant) -> Constant -> m Constant
forall a b. (a -> b) -> a -> b
$ Maybe Name -> Bool -> [Constant] -> Constant
C.Struct Maybe Name
forall a. Maybe a
Nothing Bool
False [Constant]
constants

-- | Generate LLVM code for global variables.
createGlobalString :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => String -> m AST.Operand
createGlobalString :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
String -> m Operand
createGlobalString String
str = do
  let strConst :: Constant
strConst =
        Type -> [Constant] -> Constant
C.Array
          (Word32 -> Type
T.IntegerType Word32
8)
          ((Char -> Constant) -> String -> [Constant]
forall a b. (a -> b) -> [a] -> [b]
map (Word32 -> Integer -> Constant
C.Int Word32
8 (Integer -> Constant) -> (Char -> Integer) -> Char -> Constant
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> (Char -> Int) -> Char -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
forall a. Enum a => a -> Int
fromEnum) (String
str String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\0"))
  let strType :: Type
strType = Word64 -> Type -> Type
T.ArrayType (Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word64) -> Int -> Word64
forall a b. (a -> b) -> a -> b
$ String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
str Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) (Word32 -> Type
T.IntegerType Word32
8)
  Name
name <- m Name
forall (m :: * -> *). MonadState CodegenState m => m Name
CS.fresh
  let global :: Global
global =
        AST.GlobalVariable
          { name :: Name
G.name = Name
name,
            linkage :: Linkage
G.linkage = Linkage
LK.Private,
            visibility :: Visibility
G.visibility = Visibility
V.Default,
            dllStorageClass :: Maybe StorageClass
G.dllStorageClass = Maybe StorageClass
forall a. Maybe a
Nothing,
            threadLocalMode :: Maybe Model
G.threadLocalMode = Maybe Model
forall a. Maybe a
Nothing,
            unnamedAddr :: Maybe UnnamedAddr
G.unnamedAddr = UnnamedAddr -> Maybe UnnamedAddr
forall a. a -> Maybe a
Just UnnamedAddr
AST.GlobalAddr,
            isConstant :: Bool
G.isConstant = Bool
True,
            type' :: Type
G.type' = Type
strType,
            addrSpace :: AddrSpace
G.addrSpace = Word32 -> AddrSpace
AS.AddrSpace Word32
0,
            initializer :: Maybe Constant
G.initializer = Constant -> Maybe Constant
forall a. a -> Maybe a
Just Constant
strConst,
            section :: Maybe ShortByteString
G.section = Maybe ShortByteString
forall a. Maybe a
Nothing,
            comdat :: Maybe ShortByteString
G.comdat = Maybe ShortByteString
forall a. Maybe a
Nothing,
            alignment :: Word32
G.alignment = Word32
1,
            metadata :: [(ShortByteString, MDRef MDNode)]
G.metadata = []
          }
  Definition -> m ()
forall (m :: * -> *). MonadModuleBuilder m => Definition -> m ()
M.emitDefn (Definition -> m ()) -> Definition -> m ()
forall a b. (a -> b) -> a -> b
$ Global -> Definition
AST.GlobalDefinition Global
global
  Operand -> m Operand
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (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
$
      Bool -> Constant -> [Constant] -> Constant
C.GetElementPtr
        Bool
True
        (Type -> Name -> Constant
C.GlobalReference (Type -> Type
T.ptr Type
strType) Name
name)
        [Word32 -> Integer -> Constant
C.Int Word32
64 Integer
0, Word32 -> Integer -> Constant
C.Int Word32
64 Integer
0]

-- | Generate LLVM code for variable references.
generateVar :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateVar :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateVar (AT.Var SrcLoc
loc String
name Type
type') = do
  Maybe Operand
maybeVar <- String -> m (Maybe Operand)
forall (m :: * -> *). VarBinding m => String -> m (Maybe Operand)
CS.getVar String
name
  case Maybe Operand
maybeVar of
    Maybe Operand
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 -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ String -> CodegenErrorType
CC.VariableNotFound String
name
    Just Operand
ptr -> do
      let varTy :: Type
varTy = Operand -> Type
forall a. Typed a => a -> Type
TD.typeOf Operand
ptr
          expectedType :: Type
expectedType = Type -> Type
forall a. ToLLVM a => a -> Type
ET.toLLVM Type
type'
      if Type
varTy Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Type
expectedType
        then Operand -> m Operand
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
ptr
        else case Type
varTy of
          T.PointerType (T.FunctionType {}) AddrSpace
_ -> Operand -> m Operand
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
ptr
          T.PointerType Type
_ AddrSpace
_ -> Operand -> Word32 -> m Operand
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> m Operand
I.load Operand
ptr Word32
0
          Type
_ -> Operand -> m Operand
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
ptr
generateVar 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

-- | Generate LLVM code for assignments.
generateAssignment :: (CS.MonadCodegen m, EG.ExprGen AT.Expr) => AT.Expr -> m AST.Operand
generateAssignment :: forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m Operand
generateAssignment (AT.Assignment SrcLoc
_ Expr
expr Expr
valueExpr) = do
  Operand
value <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
valueExpr
  case Expr
expr of
    AT.Var SrcLoc
_ String
name Type
_ -> do
      Maybe Operand
maybeVar <- String -> m (Maybe Operand)
forall (m :: * -> *). VarBinding m => String -> m (Maybe Operand)
CS.getVar String
name
      case Maybe Operand
maybeVar of
        Just Operand
ptr -> do
          Operand -> Word32 -> Operand -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> Operand -> m ()
I.store Operand
ptr Word32
0 Operand
value
          Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Operand
value
        Maybe Operand
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 (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ String -> CodegenErrorType
CC.VariableNotFound String
name
    AT.ArrayAccess SrcLoc
_ (AT.Var SrcLoc
_ String
name Type
_) Expr
indexExpr -> do
      Maybe Operand
maybeVar <- String -> m (Maybe Operand)
forall (m :: * -> *). VarBinding m => String -> m (Maybe Operand)
CS.getVar String
name
      Operand
ptr <- case Maybe Operand
maybeVar of
        Just Operand
arrayPtr -> Operand -> m Operand
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
arrayPtr
        Maybe Operand
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 (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ String -> CodegenErrorType
CC.VariableNotFound String
name
      Operand
index <- Expr -> m Operand
forall a (m :: * -> *).
(ExprGen a, MonadCodegen m) =>
a -> m Operand
forall (m :: * -> *). MonadCodegen m => Expr -> m Operand
EG.generateExpr Expr
indexExpr
      Operand
elementPtr <- Operand -> [Operand] -> m Operand
forall (m :: * -> *).
(MonadIRBuilder m, MonadModuleBuilder m) =>
Operand -> [Operand] -> m Operand
I.gep Operand
ptr [Integer -> Operand
IC.int32 Integer
0, Operand
index]
      Operand -> Word32 -> Operand -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> Operand -> m ()
I.store Operand
elementPtr Word32
0 Operand
value
      Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Operand
value
    AT.UnaryOp SrcLoc
_ UnaryOperation
AT.Deref (AT.Var SrcLoc
_ String
name Type
_) -> do
      Maybe Operand
maybeVar <- String -> m (Maybe Operand)
forall (m :: * -> *). VarBinding m => String -> m (Maybe Operand)
CS.getVar String
name
      case Maybe Operand
maybeVar of
        Just Operand
ptr -> do
          Operand
actualPtr <- Operand -> Word32 -> m Operand
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> m Operand
I.load Operand
ptr Word32
0
          Operand -> Word32 -> Operand -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> Operand -> m ()
I.store Operand
actualPtr Word32
0 Operand
value
          Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Operand
value
        Maybe Operand
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 (Expr -> SrcLoc
SU.getLoc Expr
expr) (CodegenErrorType -> CodegenError)
-> CodegenErrorType -> CodegenError
forall a b. (a -> b) -> a -> b
$ String -> CodegenErrorType
CC.VariableNotFound String
name
    AT.StructAccess {} -> do
      (Operand
fieldPtr, Type
_) <- Expr -> m (Operand, Type)
forall (m :: * -> *).
(MonadCodegen m, ExprGen Expr) =>
Expr -> m (Operand, Type)
ED.getStructFieldPointer Expr
expr
      Operand -> Word32 -> Operand -> m ()
forall (m :: * -> *).
MonadIRBuilder m =>
Operand -> Word32 -> Operand -> m ()
I.store Operand
fieldPtr Word32
0 Operand
value
      Operand -> m Operand
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Operand
value
    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
generateAssignment 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