{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecursiveDo #-}

module CodeGen.RiscV.AsmGen (ppRiscVAsm) where

import CodeGen.Module (Module (..))
import qualified CodeGen.RiscV.Lib as Rv
import Control.Monad.State (MonadState, State, evalState, gets, modify)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (Text)
import qualified Data.Text as Txt
import Foreign (fromBool)
import MonadUtils (locally)
import qualified StdLib
import Transformations.Anf.Anf
import Trees.Common

ppRiscVAsm :: Module -> Text
ppRiscVAsm :: Module -> Identifier
ppRiscVAsm Module
m = [CodeLine] -> Identifier
Rv.ppCodeLines ([CodeLine] -> Identifier) -> [CodeLine] -> Identifier
forall a b. (a -> b) -> a -> b
$ Module -> [CodeLine]
genModule Module
m

-- The Code

type CodeGenM = Rv.AsmBuilderT (State Env)

data Env = Env
  { Env -> Map Identifier' Operand
locVars :: Map Identifier' Rv.Operand,
    Env -> Map Identifier' Operand
globVars :: Map Identifier' Rv.Operand,
    Env -> Map Identifier' (Operand, Arity)
funs :: Map Identifier' (Rv.Operand, Arity)
  }

genModule :: Module -> [Rv.CodeLine]
genModule :: Module -> [CodeLine]
genModule (Module (Program [GlobalDeclaration]
decls)) = (State Env [CodeLine] -> Env -> [CodeLine])
-> Env -> State Env [CodeLine] -> [CodeLine]
forall a b c. (a -> b -> c) -> b -> a -> c
flip State Env [CodeLine] -> Env -> [CodeLine]
forall s a. State s a -> s -> a
evalState (Map Identifier' Operand
-> Map Identifier' Operand
-> Map Identifier' (Operand, Arity)
-> Env
Env Map Identifier' Operand
forall k a. Map k a
Map.empty Map Identifier' Operand
forall k a. Map k a
Map.empty Map Identifier' (Operand, Arity)
forall k a. Map k a
Map.empty) (State Env [CodeLine] -> [CodeLine])
-> State Env [CodeLine] -> [CodeLine]
forall a b. (a -> b) -> a -> b
$
  AsmBuilderT (State Env) () -> State Env [CodeLine]
forall (m :: * -> *) a. Monad m => AsmBuilderT m a -> m [CodeLine]
Rv.compileT (AsmBuilderT (State Env) () -> State Env [CodeLine])
-> AsmBuilderT (State Env) () -> State Env [CodeLine]
forall a b. (a -> b) -> a -> b
$ do
    (DeclarationWithArity -> AsmBuilderT (State Env) ())
-> [DeclarationWithArity] -> AsmBuilderT (State Env) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ DeclarationWithArity -> AsmBuilderT (State Env) ()
genStdLibDecl [DeclarationWithArity]
StdLib.allDeclsWithArity
    (GlobalDeclaration -> AsmBuilderT (State Env) ())
-> [GlobalDeclaration] -> AsmBuilderT (State Env) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ GlobalDeclaration -> AsmBuilderT (State Env) ()
genGlobDecl [GlobalDeclaration]
decls

    -- In the `main` we define our global variables.
    (() -> AsmBuilderT (State Env) ()) -> AsmBuilderT (State Env) ()
forall (m :: * -> *). MonadAsmBuilder m => (() -> m ()) -> m ()
Rv.mainFunction ((() -> AsmBuilderT (State Env) ()) -> AsmBuilderT (State Env) ())
-> (() -> AsmBuilderT (State Env) ()) -> AsmBuilderT (State Env) ()
forall a b. (a -> b) -> a -> b
$ \()
_ -> (GlobalDeclaration -> AsmBuilderT (State Env) ())
-> [GlobalDeclaration] -> AsmBuilderT (State Env) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ GlobalDeclaration -> AsmBuilderT (State Env) ()
gVarDef [GlobalDeclaration]
decls
  where
    gVarDef :: GlobalDeclaration -> CodeGenM ()
    gVarDef :: GlobalDeclaration -> AsmBuilderT (State Env) ()
gVarDef = \case
      GlobVarDecl Identifier'
ident Expression
value -> do
        Operand
addr <- Identifier' -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadState Env m => Identifier' -> m Operand
findGlobVar Identifier'
ident
        Operand
value' <- Expression -> AsmBuilderT (State Env) Operand
genExpr Expression
value
        Operand -> Operand -> AsmBuilderT (State Env) ()
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m ()
Rv.storeToLabeledAddr Operand
addr Operand
value'
      GlobalDeclaration
_ -> () -> AsmBuilderT (State Env) ()
forall a. a -> AsmBuilderT (State Env) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

genStdLibDecl :: StdLib.DeclarationWithArity -> CodeGenM ()
genStdLibDecl :: DeclarationWithArity -> AsmBuilderT (State Env) ()
genStdLibDecl DeclarationWithArity
decl = DeclarationWithArity -> AsmBuilderT (State Env) Operand
declareAsExtern DeclarationWithArity
decl AsmBuilderT (State Env) Operand
-> (Operand -> AsmBuilderT (State Env) ())
-> AsmBuilderT (State Env) ()
forall a b.
AsmBuilderT (State Env) a
-> (a -> AsmBuilderT (State Env) b) -> AsmBuilderT (State Env) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DeclarationWithArity -> Operand -> AsmBuilderT (State Env) ()
register DeclarationWithArity
decl
  where
    declareAsExtern :: StdLib.DeclarationWithArity -> CodeGenM Rv.Operand
    declareAsExtern :: DeclarationWithArity -> AsmBuilderT (State Env) Operand
declareAsExtern (Identifier
ident, Arity
_) = Identifier -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Identifier -> m Operand
Rv.externFunction Identifier
ident

    register :: StdLib.DeclarationWithArity -> Rv.Operand -> CodeGenM ()
    register :: DeclarationWithArity -> Operand -> AsmBuilderT (State Env) ()
register (Identifier
ident, Arity
arity) Operand
fun = Identifier' -> Operand -> Arity -> AsmBuilderT (State Env) ()
forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> Arity -> m ()
regFun (Identifier -> Identifier'
Txt Identifier
ident) Operand
fun Arity
arity

genGlobDecl :: GlobalDeclaration -> CodeGenM ()
genGlobDecl :: GlobalDeclaration -> AsmBuilderT (State Env) ()
genGlobDecl = \case
  GlobVarDecl Identifier'
ident Expression
_ -> do
    Operand
var <- Identifier -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Identifier -> m Operand
Rv.globalVar (String -> Identifier
Txt.pack (String -> Identifier) -> String -> Identifier
forall a b. (a -> b) -> a -> b
$ Identifier' -> String
genId Identifier'
ident)
    Identifier' -> Operand -> AsmBuilderT (State Env) ()
forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> m ()
regGlobVar Identifier'
ident Operand
var
  GlobFunDecl Identifier'
ident [Identifier']
params Expression
body -> mdo
    Identifier' -> Operand -> Arity -> AsmBuilderT (State Env) ()
forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> Arity -> m ()
regFun Identifier'
ident Operand
fun ([Identifier'] -> Arity
forall a. [a] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Identifier']
params)
    Operand
fun <- AsmBuilderT (State Env) Operand -> AsmBuilderT (State Env) Operand
forall s (m :: * -> *) a. MonadState s m => m a -> m a
locally (AsmBuilderT (State Env) Operand
 -> AsmBuilderT (State Env) Operand)
-> AsmBuilderT (State Env) Operand
-> AsmBuilderT (State Env) Operand
forall a b. (a -> b) -> a -> b
$ do
      Identifier
-> Int64
-> ([Operand] -> AsmBuilderT (State Env) Operand)
-> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Identifier -> Int64 -> ([Operand] -> m Operand) -> m Operand
Rv.function
        (String -> Identifier
Txt.pack (String -> Identifier) -> String -> Identifier
forall a b. (a -> b) -> a -> b
$ Identifier' -> String
genId Identifier'
ident)
        (Arity -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Arity -> Int64) -> Arity -> Int64
forall a b. (a -> b) -> a -> b
$ [Identifier'] -> Arity
forall a. [a] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Identifier']
params)
        (([Operand] -> AsmBuilderT (State Env) Operand)
 -> AsmBuilderT (State Env) Operand)
-> ([Operand] -> AsmBuilderT (State Env) Operand)
-> AsmBuilderT (State Env) Operand
forall a b. (a -> b) -> a -> b
$ \[Operand]
args -> do
          ((Identifier', Operand) -> AsmBuilderT (State Env) ())
-> [(Identifier', Operand)] -> AsmBuilderT (State Env) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((Identifier' -> Operand -> AsmBuilderT (State Env) ())
-> (Identifier', Operand) -> AsmBuilderT (State Env) ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Identifier' -> Operand -> AsmBuilderT (State Env) ()
forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> m ()
regLocVar) ([Identifier']
params [Identifier'] -> [Operand] -> [(Identifier', Operand)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Operand]
args)
          Expression -> AsmBuilderT (State Env) Operand
genExpr Expression
body
    () -> AsmBuilderT (State Env) ()
forall a. a -> AsmBuilderT (State Env) a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

genId :: Identifier' -> String
genId :: Identifier' -> String
genId = \case
  Txt Identifier
txt -> Identifier -> String
Txt.unpack Identifier
txt
  Gen IdCnt
n Identifier
txt -> Identifier -> String
Txt.unpack Identifier
txt String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"_" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> IdCnt -> String
forall a. Show a => a -> String
show IdCnt
n

genExpr :: Expression -> CodeGenM Rv.Operand
genExpr :: Expression -> AsmBuilderT (State Env) Operand
genExpr = \case
  ExprAtom AtomicExpression
atom -> AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom AtomicExpression
atom
  ExprComp ComplexExpression
ce -> ComplexExpression -> AsmBuilderT (State Env) Operand
genComp ComplexExpression
ce
  ExprLetIn (Identifier'
ident, Expression
val) Expression
expr -> do
    Operand
val' <- Expression -> AsmBuilderT (State Env) Operand
genExpr Expression
val
    Identifier' -> Operand -> AsmBuilderT (State Env) ()
forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> m ()
regLocVar Identifier'
ident Operand
val'
    Expression -> AsmBuilderT (State Env) Operand
genExpr Expression
expr

genAtom :: AtomicExpression -> CodeGenM Rv.Operand
genAtom :: AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom = \case
  AtomId Identifier'
ident -> Identifier' -> AsmBuilderT (State Env) Operand
findAny Identifier'
ident
  AtomicExpression
AtomUnit -> Int64 -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Int64 -> m Operand
Rv.immediate Int64
0
  AtomBool Bool
bool -> Int64 -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Int64 -> m Operand
Rv.immediate (Int64 -> AsmBuilderT (State Env) Operand)
-> Int64 -> AsmBuilderT (State Env) Operand
forall a b. (a -> b) -> a -> b
$ Bool -> Int64
forall a. Num a => Bool -> a
fromBool Bool
bool
  AtomInt Int64
int -> Int64 -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Int64 -> m Operand
Rv.immediate Int64
int

genComp :: ComplexExpression -> CodeGenM Rv.Operand
genComp :: ComplexExpression -> AsmBuilderT (State Env) Operand
genComp = \case
  CompApp Identifier'
f AtomicExpression
arg -> do
    Operand
f' <- Identifier' -> AsmBuilderT (State Env) Operand
findAny Identifier'
f
    Operand
arg' <- AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom AtomicExpression
arg
    Operand
applyF <- Identifier' -> AsmBuilderT (State Env) Operand
findFun (Identifier -> Identifier'
Txt Identifier
"miniml_apply")
    Operand -> [Operand] -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> [Operand] -> m Operand
Rv.call Operand
applyF [Operand
f', Operand
arg']
  CompIte AtomicExpression
c Expression
t Expression
e -> do
    Operand
c' <- AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom AtomicExpression
c
    Operand
-> (() -> AsmBuilderT (State Env) Operand)
-> (() -> AsmBuilderT (State Env) Operand)
-> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> (() -> m Operand) -> (() -> m Operand) -> m Operand
Rv.ite Operand
c' (\()
_ -> Expression -> AsmBuilderT (State Env) Operand
genExpr Expression
t) (\()
_ -> Expression -> AsmBuilderT (State Env) Operand
genExpr Expression
e)
  CompBinOp BinaryOperator
op AtomicExpression
lhs AtomicExpression
rhs -> do
    Operand
lhs' <- AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom AtomicExpression
lhs
    Operand
rhs' <- AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom AtomicExpression
rhs
    let opF :: Operand -> Operand -> AsmBuilderT (State Env) Operand
opF = case BinaryOperator
op of
          BoolOp BooleanOperator
AndOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.and
          BoolOp BooleanOperator
OrOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.or
          ArithOp ArithmeticOperator
PlusOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.add
          ArithOp ArithmeticOperator
MinusOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.sub
          ArithOp ArithmeticOperator
MulOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.mul
          ArithOp ArithmeticOperator
DivOp ->
            ( \Operand
lhs'' Operand
rhs'' -> do
                Operand
divF <- Identifier' -> AsmBuilderT (State Env) Operand
findFun (Identifier -> Identifier'
Txt Identifier
"miniml_div")
                Operand -> [Operand] -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> [Operand] -> m Operand
Rv.call Operand
divF [Operand
lhs'', Operand
rhs'']
            )
          CompOp ComparisonOperator
EqOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.eq
          CompOp ComparisonOperator
NeOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.ne
          CompOp ComparisonOperator
LtOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.lt
          CompOp ComparisonOperator
LeOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.le
          CompOp ComparisonOperator
GtOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.gt
          CompOp ComparisonOperator
GeOp -> Operand -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> Operand -> m Operand
Rv.ge
    Operand -> Operand -> AsmBuilderT (State Env) Operand
opF Operand
lhs' Operand
rhs'
  CompUnOp UnaryOperator
op AtomicExpression
x -> do
    Operand
x' <- AtomicExpression -> AsmBuilderT (State Env) Operand
genAtom AtomicExpression
x
    let opF :: Operand -> AsmBuilderT (State Env) Operand
opF = case UnaryOperator
op of
          UnaryOperator
UnMinusOp -> Operand -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Operand -> m Operand
Rv.neg
    Operand -> AsmBuilderT (State Env) Operand
opF Operand
x'

-- Vars & Funs

findAny :: Identifier' -> CodeGenM Rv.Operand
findAny :: Identifier' -> AsmBuilderT (State Env) Operand
findAny Identifier'
ident = do
  Maybe Operand
maybeLocVar <- (Env -> Maybe Operand) -> AsmBuilderT (State Env) (Maybe Operand)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Map Identifier' Operand -> Identifier' -> Maybe Operand
forall k a. Ord k => Map k a -> k -> Maybe a
Map.!? Identifier'
ident) (Map Identifier' Operand -> Maybe Operand)
-> (Env -> Map Identifier' Operand) -> Env -> Maybe Operand
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env -> Map Identifier' Operand
locVars)
  case Maybe Operand
maybeLocVar of
    Just Operand
locVar -> Operand -> AsmBuilderT (State Env) Operand
forall a. a -> AsmBuilderT (State Env) a
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
locVar
    Maybe Operand
Nothing -> do
      Maybe (Operand, Arity)
maybeFun <- (Env -> Maybe (Operand, Arity))
-> AsmBuilderT (State Env) (Maybe (Operand, Arity))
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Map Identifier' (Operand, Arity)
-> Identifier' -> Maybe (Operand, Arity)
forall k a. Ord k => Map k a -> k -> Maybe a
Map.!? Identifier'
ident) (Map Identifier' (Operand, Arity) -> Maybe (Operand, Arity))
-> (Env -> Map Identifier' (Operand, Arity))
-> Env
-> Maybe (Operand, Arity)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env -> Map Identifier' (Operand, Arity)
funs)
      case Maybe (Operand, Arity)
maybeFun of
        Just (Operand
fun, Arity
arity) -> do
          Operand
funToPafF <- Identifier' -> AsmBuilderT (State Env) Operand
findFun (Identifier -> Identifier'
Txt Identifier
"miniml_fun_to_paf")
          Operand
arity' <- Int64 -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadAsmBuilder m => Int64 -> m Operand
Rv.immediate (Int64 -> AsmBuilderT (State Env) Operand)
-> Int64 -> AsmBuilderT (State Env) Operand
forall a b. (a -> b) -> a -> b
$ Arity -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Arity
arity
          Operand -> [Operand] -> AsmBuilderT (State Env) Operand
forall (m :: * -> *).
MonadAsmBuilder m =>
Operand -> [Operand] -> m Operand
Rv.call Operand
funToPafF [Operand
fun, Operand
arity']
        Maybe (Operand, Arity)
Nothing -> Identifier' -> AsmBuilderT (State Env) Operand
forall (m :: * -> *). MonadState Env m => Identifier' -> m Operand
findGlobVar Identifier'
ident

findGlobVar :: (MonadState Env m) => Identifier' -> m Rv.Operand
findGlobVar :: forall (m :: * -> *). MonadState Env m => Identifier' -> m Operand
findGlobVar Identifier'
ident = (Env -> Operand) -> m Operand
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Map Identifier' Operand -> Identifier' -> Operand
forall k a. Ord k => Map k a -> k -> a
Map.! Identifier'
ident) (Map Identifier' Operand -> Operand)
-> (Env -> Map Identifier' Operand) -> Env -> Operand
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env -> Map Identifier' Operand
globVars)

findFun :: Identifier' -> CodeGenM Rv.Operand
findFun :: Identifier' -> AsmBuilderT (State Env) Operand
findFun Identifier'
ident = (Env -> Operand) -> AsmBuilderT (State Env) Operand
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Operand, Arity) -> Operand
forall a b. (a, b) -> a
fst ((Operand, Arity) -> Operand)
-> (Env -> (Operand, Arity)) -> Env -> Operand
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Identifier' (Operand, Arity) -> Identifier' -> (Operand, Arity)
forall k a. Ord k => Map k a -> k -> a
Map.! Identifier'
ident) (Map Identifier' (Operand, Arity) -> (Operand, Arity))
-> (Env -> Map Identifier' (Operand, Arity))
-> Env
-> (Operand, Arity)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Env -> Map Identifier' (Operand, Arity)
funs)

regLocVar :: (MonadState Env m) => Identifier' -> Rv.Operand -> m ()
regLocVar :: forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> m ()
regLocVar Identifier'
ident Operand
var = (Env -> Env) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Env -> Env) -> m ()) -> (Env -> Env) -> m ()
forall a b. (a -> b) -> a -> b
$
  \Env
env -> Env
env {locVars :: Map Identifier' Operand
locVars = Identifier'
-> Operand -> Map Identifier' Operand -> Map Identifier' Operand
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Identifier'
ident Operand
var (Env -> Map Identifier' Operand
locVars Env
env)}

regGlobVar :: (MonadState Env m) => Identifier' -> Rv.Operand -> m ()
regGlobVar :: forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> m ()
regGlobVar Identifier'
ident Operand
gVar = (Env -> Env) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Env -> Env) -> m ()) -> (Env -> Env) -> m ()
forall a b. (a -> b) -> a -> b
$
  \Env
env -> Env
env {globVars :: Map Identifier' Operand
globVars = Identifier'
-> Operand -> Map Identifier' Operand -> Map Identifier' Operand
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Identifier'
ident Operand
gVar (Env -> Map Identifier' Operand
globVars Env
env)}

regFun :: (MonadState Env m) => Identifier' -> Rv.Operand -> Arity -> m ()
regFun :: forall (m :: * -> *).
MonadState Env m =>
Identifier' -> Operand -> Arity -> m ()
regFun Identifier'
ident Operand
fun Arity
paramsCnt = (Env -> Env) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Env -> Env) -> m ()) -> (Env -> Env) -> m ()
forall a b. (a -> b) -> a -> b
$
  \Env
env -> Env
env {funs :: Map Identifier' (Operand, Arity)
funs = Identifier'
-> (Operand, Arity)
-> Map Identifier' (Operand, Arity)
-> Map Identifier' (Operand, Arity)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Identifier'
ident (Operand
fun, Arity
paramsCnt) (Env -> Map Identifier' (Operand, Arity)
funs Env
env)}