module Csound.Dynamic.Build (
  -- * Expression tree
  -- | Working with expression tree
  toExp, onExp,

  -- * Rates
  -- * Queries
  getRates, isMultiOutSignature, getPrimUnsafe,

  -- * Constructors
  -- | Basic constructors
  prim, opcPrefix, oprPrefix, oprInfix,
  numExp1,
  tfm, tfmNoInlineArgs, pn, withInits,
  double, int, str, verbatim, instrIdE,
  inlineVar, gInit, gInitDouble,

  -- ** Opcodes constructors
  Spec1, spec1, opcs, opcsNoInlineArgs, opr1, opr1k, infOpr, oprBy,
  Specs, specs, MultiOut, mopcs, mo,

  -- * Global init statements
  setSr, setKsmps, setNchnls, setNchnls_i, setKr, setZeroDbfs,

  -- * Arrays
  opcsArr, infOprArr, initPureArr, readPureArr
) where

import qualified Data.Map as M(fromList, toList)
import Data.Serialize qualified as Cereal

import Data.List(transpose)
import Data.Fix(Fix(..))

import Csound.Dynamic.Types.Exp
import Csound.Dynamic.Types.Dep
import Data.Text (Text)
import Data.Text qualified as Text

------------------------------------------------
-- basic constructors

prim :: Prim -> E
prim :: Prim -> E
prim = Exp E -> E
noRate (Exp E -> E) -> (Prim -> Exp E) -> Prim -> E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Prim -> Exp E
forall a. Prim -> MainExp a
ExpPrim

opcPrefix :: Name -> Signature -> Info
opcPrefix :: Name -> Signature -> Info
opcPrefix Name
name Signature
signature = Name -> Signature -> OpcFixity -> Info
Info Name
name Signature
signature OpcFixity
Opcode

oprPrefix :: Name -> Signature -> Info
oprPrefix :: Name -> Signature -> Info
oprPrefix Name
name Signature
signature = Name -> Signature -> OpcFixity -> Info
Info Name
name Signature
signature OpcFixity
Prefix

oprInfix :: Name -> Signature -> Info
oprInfix :: Name -> Signature -> Info
oprInfix Name
name Signature
signature = Name -> Signature -> OpcFixity -> Info
Info Name
name Signature
signature OpcFixity
Infix

toArgs :: [Rate] -> [E] -> [PrimOr E]
toArgs :: [Rate] -> [E] -> [PrimOr E]
toArgs = (Rate -> E -> PrimOr E) -> [Rate] -> [E] -> [PrimOr E]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Rate -> E -> PrimOr E
toPrimOrTfm

tfm :: Info -> [E] -> E
tfm :: Info -> [E] -> E
tfm Info
info [E]
args = Exp E -> E
noRate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ Info -> [PrimOr E] -> Exp E
forall a. Info -> [a] -> MainExp a
Tfm Info
info ([PrimOr E] -> Exp E) -> [PrimOr E] -> Exp E
forall a b. (a -> b) -> a -> b
$ [Rate] -> [E] -> [PrimOr E]
toArgs (Info -> [Rate]
getInfoRates Info
info) [E]
args

tfmArr :: Monad m => IsArrInit -> Var -> Info -> [E] -> DepT m ()
tfmArr :: forall (m :: * -> *).
Monad m =>
IsArrInit -> Var -> Info -> [E] -> DepT m ()
tfmArr IsArrInit
isArrInit Var
var Info
info [E]
args = E -> DepT m ()
forall (m :: * -> *). Monad m => E -> DepT m ()
depT_ (E -> DepT m ()) -> E -> DepT m ()
forall a b. (a -> b) -> a -> b
$ Exp E -> E
noRate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ IsArrInit -> Var -> Info -> [PrimOr E] -> Exp E
forall a. IsArrInit -> Var -> Info -> [a] -> MainExp a
TfmArr IsArrInit
isArrInit Var
var Info
info ([PrimOr E] -> Exp E) -> [PrimOr E] -> Exp E
forall a b. (a -> b) -> a -> b
$ [Rate] -> [E] -> [PrimOr E]
toArgs (Info -> [Rate]
getInfoRates Info
info) [E]
args

getInfoRates :: Info -> [Rate]
getInfoRates :: Info -> [Rate]
getInfoRates Info
a = Signature -> [Rate]
getInRates (Signature -> [Rate]) -> Signature -> [Rate]
forall a b. (a -> b) -> a -> b
$ Info -> Signature
infoSignature Info
a
  where
    getInRates :: Signature -> [Rate]
getInRates Signature
x =
      case Signature
x of
        SingleRate Map Rate [Rate]
m    -> ([Rate] -> Rate) -> [[Rate]] -> [Rate]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Rate] -> Rate
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([[Rate]] -> [Rate]) -> [[Rate]] -> [Rate]
forall a b. (a -> b) -> a -> b
$ [[Rate]] -> [[Rate]]
forall a. [[a]] -> [[a]]
transpose ([[Rate]] -> [[Rate]]) -> [[Rate]] -> [[Rate]]
forall a b. (a -> b) -> a -> b
$ ((Rate, [Rate]) -> [Rate]) -> [(Rate, [Rate])] -> [[Rate]]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Rate, [Rate]) -> [Rate]
forall a b. (a, b) -> b
snd ([(Rate, [Rate])] -> [[Rate]]) -> [(Rate, [Rate])] -> [[Rate]]
forall a b. (a -> b) -> a -> b
$ Map Rate [Rate] -> [(Rate, [Rate])]
forall k a. Map k a -> [(k, a)]
M.toList Map Rate [Rate]
m
        MultiRate [Rate]
_ [Rate]
ins -> [Rate]
ins

tfmNoInlineArgs :: Info -> [E] -> E
tfmNoInlineArgs :: Info -> [E] -> E
tfmNoInlineArgs Info
info [E]
args = Exp E -> E
noRate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ Info -> [PrimOr E] -> Exp E
forall a. Info -> [a] -> MainExp a
Tfm Info
info ([PrimOr E] -> Exp E) -> [PrimOr E] -> Exp E
forall a b. (a -> b) -> a -> b
$ (E -> PrimOr E) -> [E] -> [PrimOr E]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Either Prim E -> PrimOr E
forall a. Either Prim a -> PrimOr a
PrimOr (Either Prim E -> PrimOr E)
-> (E -> Either Prim E) -> E -> PrimOr E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. E -> Either Prim E
forall a b. b -> Either a b
Right) [E]
args

inlineVar :: Var -> E
inlineVar :: Var -> E
inlineVar Var
var = RatedExp E -> E
forall (f :: * -> *). f (Fix f) -> Fix f
Fix (RatedExp E -> E) -> RatedExp E -> E
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe Rate -> Maybe Int -> Exp E -> RatedExp E
forall a.
ByteString -> Maybe Rate -> Maybe Int -> Exp a -> RatedExp a
RatedExp ByteString
h Maybe Rate
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing (Exp E -> RatedExp E) -> Exp E -> RatedExp E
forall a b. (a -> b) -> a -> b
$ Var -> Exp E
forall a. Var -> MainExp a
ReadVar Var
var
  where
    h :: ByteString
h = Var -> ByteString
forall a. Serialize a => a -> ByteString
Cereal.encode Var
var

pn :: Int -> E
pn :: Int -> E
pn = Prim -> E
prim (Prim -> E) -> (Int -> Prim) -> Int -> E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Prim
P

withInits :: E -> [E] -> E
withInits :: E -> [E] -> E
withInits E
a [E]
es = (Exp E -> Exp E) -> E -> E
onExp Exp E -> Exp E
phi E
a
  where
    phi :: Exp E -> Exp E
phi = \case
      -- for opcodes with single output
      Tfm Info
t [PrimOr E]
xs -> Info -> [PrimOr E] -> Exp E
forall a. Info -> [a] -> MainExp a
Tfm Info
t ([PrimOr E]
xs [PrimOr E] -> [PrimOr E] -> [PrimOr E]
forall a. [a] -> [a] -> [a]
++ ((E -> PrimOr E) -> [E] -> [PrimOr E]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap E -> PrimOr E
toPrimOr [E]
es))
      -- for opcodes with multiple outputs
      Select Rate
r Int
n PrimOr E
expr -> Rate -> Int -> PrimOr E -> Exp E
forall a. Rate -> Int -> a -> MainExp a
Select Rate
r Int
n (PrimOr E -> Exp E) -> PrimOr E -> Exp E
forall a b. (a -> b) -> a -> b
$ (E -> E) -> PrimOr E -> PrimOr E
forall a b. (a -> b) -> PrimOr a -> PrimOr b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\E
t -> E -> [E] -> E
withInits E
t [E]
es) PrimOr E
expr
      Exp E
x        -> Exp E
x

-- | Converts Haskell's doubles to Csound's doubles
double :: Double -> E
double :: Double -> E
double = Prim -> E
prim (Prim -> E) -> (Double -> Prim) -> Double -> E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Prim
PrimDouble

-- | Converts Haskell's strings to Csound's strings
str :: String -> E
str :: String -> E
str = Prim -> E
prim (Prim -> E) -> (String -> Prim) -> String -> E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Prim
PrimString (Name -> Prim) -> (String -> Name) -> String -> Prim
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Name
Text.pack

-- | Converts Haskell's integers to Csound's doubles
int :: Int -> E
int :: Int -> E
int = Prim -> E
prim (Prim -> E) -> (Int -> Prim) -> Int -> E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Prim
PrimInt

verbatim :: Monad m => Text -> DepT m ()
verbatim :: forall (m :: * -> *). Monad m => Name -> DepT m ()
verbatim = Exp E -> DepT m ()
forall (m :: * -> *). Monad m => Exp E -> DepT m ()
stmtOnlyT (Exp E -> DepT m ()) -> (Name -> Exp E) -> Name -> DepT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Exp E
forall a. Name -> MainExp a
Verbatim

instrIdE :: InstrId -> E
instrIdE :: InstrId -> E
instrIdE InstrId
x =
  case InstrId
x of
    InstrId Maybe Int
Nothing  Int
m -> Int -> E
int Int
m
    InstrId (Just Int
_) Int
_ -> String -> E
forall a. HasCallStack => String -> a
error String
"instrId undefined for fractional InstrIds"
    InstrLabel Name
s -> Prim -> E
prim (Name -> Prim
PrimString Name
s)

----------------------------------------------------------------------
-- constructing opcodes

-- single output

-- User friendly type for single output type signatures
type Spec1 = [(Rate, [Rate])]

spec1 :: Spec1 -> Signature
spec1 :: [(Rate, [Rate])] -> Signature
spec1 = Map Rate [Rate] -> Signature
SingleRate (Map Rate [Rate] -> Signature)
-> ([(Rate, [Rate])] -> Map Rate [Rate])
-> [(Rate, [Rate])]
-> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Rate, [Rate])] -> Map Rate [Rate]
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList

opcs :: Name -> Spec1 -> [E] -> E
opcs :: Name -> [(Rate, [Rate])] -> [E] -> E
opcs Name
name [(Rate, [Rate])]
signature = Info -> [E] -> E
tfm (Name -> Signature -> Info
opcPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate, [Rate])]
signature)

opcsNoInlineArgs :: Name -> Spec1 -> [E] -> E
opcsNoInlineArgs :: Name -> [(Rate, [Rate])] -> [E] -> E
opcsNoInlineArgs Name
name [(Rate, [Rate])]
signature = Info -> [E] -> E
tfmNoInlineArgs (Name -> Signature -> Info
opcPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate, [Rate])]
signature)

opr1 :: Name -> E -> E
opr1 :: Name -> E -> E
opr1 Name
name E
a = Info -> [E] -> E
tfm (Name -> Signature -> Info
oprPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate
Ar, [Rate
Ar]), (Rate
Kr, [Rate
Kr]), (Rate
Ir, [Rate
Ir])]) [E
a]

oprBy :: Name -> Spec1 -> [E] -> E
oprBy :: Name -> [(Rate, [Rate])] -> [E] -> E
oprBy Name
name [(Rate, [Rate])]
signature = Info -> [E] -> E
tfm (Name -> Signature -> Info
oprPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate, [Rate])]
signature)

opr1k :: Name -> E -> E
opr1k :: Name -> E -> E
opr1k Name
name E
a = Info -> [E] -> E
tfm (Name -> Signature -> Info
oprPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate
Kr, [Rate
Kr]), (Rate
Ir, [Rate
Ir])]) [E
a]

infOpr :: Name -> E -> E -> E
infOpr :: Name -> E -> E -> E
infOpr Name
name E
a E
b = Info -> [E] -> E
tfm (Name -> Signature -> Info
oprInfix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate
Ar, [Rate
Ar, Rate
Ar]), (Rate
Kr, [Rate
Kr, Rate
Kr]), (Rate
Ir, [Rate
Ir, Rate
Ir])]) [E
a, E
b]

numExp1 :: NumOp -> E -> E
numExp1 :: NumOp -> E -> E
numExp1 NumOp
op E
x = Exp E -> E
noRate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ NumExp (PrimOr E) -> Exp E
forall a. NumExp a -> MainExp a
ExpNum (NumExp (PrimOr E) -> Exp E) -> NumExp (PrimOr E) -> Exp E
forall a b. (a -> b) -> a -> b
$ (E -> PrimOr E) -> PreInline NumOp E -> NumExp (PrimOr E)
forall a b. (a -> b) -> PreInline NumOp a -> PreInline NumOp b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap E -> PrimOr E
toPrimOr (PreInline NumOp E -> NumExp (PrimOr E))
-> PreInline NumOp E -> NumExp (PrimOr E)
forall a b. (a -> b) -> a -> b
$ NumOp -> [E] -> PreInline NumOp E
forall a b. a -> [b] -> PreInline a b
PreInline NumOp
op [E
x]

opcsArr :: Monad m => IsArrInit -> Var -> Name -> Spec1 -> [E] -> DepT m ()
opcsArr :: forall (m :: * -> *).
Monad m =>
IsArrInit -> Var -> Name -> [(Rate, [Rate])] -> [E] -> DepT m ()
opcsArr IsArrInit
isArrInit Var
out Name
name [(Rate, [Rate])]
signature = IsArrInit -> Var -> Info -> [E] -> DepT m ()
forall (m :: * -> *).
Monad m =>
IsArrInit -> Var -> Info -> [E] -> DepT m ()
tfmArr IsArrInit
isArrInit Var
out (Name -> Signature -> Info
opcPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate, [Rate])]
signature)

infOprArr :: Monad m => IsArrInit -> Var -> Name -> E -> E -> DepT m ()
infOprArr :: forall (m :: * -> *).
Monad m =>
IsArrInit -> Var -> Name -> E -> E -> DepT m ()
infOprArr IsArrInit
isArrInit Var
out Name
name E
a E
b = IsArrInit -> Var -> Info -> [E] -> DepT m ()
forall (m :: * -> *).
Monad m =>
IsArrInit -> Var -> Info -> [E] -> DepT m ()
tfmArr IsArrInit
isArrInit Var
out (Name -> Signature -> Info
oprInfix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ [(Rate, [Rate])] -> Signature
spec1 [(Rate
Ar, [Rate
Ar, Rate
Ar]), (Rate
Kr, [Rate
Kr, Rate
Kr]), (Rate
Ir, [Rate
Ir, Rate
Ir])]) [E
a, E
b]

initPureArr :: Rate -> IfRate -> [E] -> E
initPureArr :: Rate -> IfRate -> [E] -> E
initPureArr Rate
outRate IfRate
procRate [E]
initVals =
  Exp E -> E
noRate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ Rate -> IfRate -> [PrimOr E] -> Exp E
forall a. Rate -> IfRate -> [a] -> MainExp a
InitPureArr Rate
outRate IfRate
procRate ([PrimOr E] -> Exp E) -> [PrimOr E] -> Exp E
forall a b. (a -> b) -> a -> b
$ [Rate] -> [E] -> [PrimOr E]
toArgs (Rate -> [Rate]
forall a. a -> [a]
repeat Rate
initRate) [E]
initVals
  where
    initRate :: Rate
initRate = IfRate -> Rate
fromIfRate IfRate
procRate

readPureArr :: Rate -> IfRate -> E -> E -> E
readPureArr :: Rate -> IfRate -> E -> E -> E
readPureArr Rate
outRate IfRate
procRate E
arr E
index =
  Exp E -> E
noRate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ Rate -> IfRate -> PrimOr E -> PrimOr E -> Exp E
forall a. Rate -> IfRate -> a -> a -> MainExp a
ReadPureArr Rate
outRate IfRate
procRate (E -> PrimOr E
toPrimOr E
arr) (Rate -> E -> PrimOr E
toPrimOrTfm (IfRate -> Rate
fromIfRate IfRate
procRate) E
index)

-- multiple output

-- User friendly type for multiple outputs type signatures
type Specs = ([Rate], [Rate])

specs :: Specs -> Signature
specs :: Specs -> Signature
specs = ([Rate] -> [Rate] -> Signature) -> Specs -> Signature
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry [Rate] -> [Rate] -> Signature
MultiRate

mopcs :: Name -> Specs -> [E] -> MultiOut [E]
mopcs :: Name -> Specs -> [E] -> MultiOut [E]
mopcs Name
name Specs
signature [E]
as = \Int
numOfOuts -> Int -> E -> [E]
mo Int
numOfOuts (E -> [E]) -> E -> [E]
forall a b. (a -> b) -> a -> b
$ Info -> [E] -> E
tfm (Name -> Signature -> Info
opcPrefix Name
name (Signature -> Info) -> Signature -> Info
forall a b. (a -> b) -> a -> b
$ Specs -> Signature
specs Specs
signature) [E]
as

mo :: Int -> E -> [E]
mo :: Int -> E -> [E]
mo Int
n E
e = (Int -> Rate -> E) -> [Int] -> [Rate] -> [E]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
cellId Rate
r -> Int -> Rate -> E -> E
select Int
cellId Rate
r E
e') [Int
0 ..] [Rate]
outRates
  where
    outRates :: [Rate]
outRates = Int -> [Rate] -> [Rate]
forall a. Int -> [a] -> [a]
take Int
n ([Rate] -> [Rate]) -> [Rate] -> [Rate]
forall a b. (a -> b) -> a -> b
$ Exp E -> [Rate]
forall a. MainExp a -> [Rate]
getRates (Exp E -> [Rate]) -> Exp E -> [Rate]
forall a b. (a -> b) -> a -> b
$ E -> Exp E
toExp E
e
    e' :: E
e' = (Exp E -> Exp E) -> E -> E
onExp ([Rate] -> Exp E -> Exp E
forall {a}. [Rate] -> MainExp a -> MainExp a
setMultiRate [Rate]
outRates) E
e

    setMultiRate :: [Rate] -> MainExp a -> MainExp a
setMultiRate [Rate]
rates (Tfm Info
info [a]
xs) = Info -> [a] -> MainExp a
forall a. Info -> [a] -> MainExp a
Tfm (Info
info{ infoSignature = MultiRate rates ins }) [a]
xs
        where
          ins :: [Rate]
ins = case Info -> Signature
infoSignature Info
info of
              MultiRate [Rate]
_ [Rate]
a -> [Rate]
a
              Signature
_ -> String -> [Rate]
forall a. HasCallStack => String -> a
error String
"Tuple.hs: multiOutsSection -- should be multiOut expression"
    setMultiRate [Rate]
_ MainExp a
_ = String -> MainExp a
forall a. HasCallStack => String -> a
error String
"Tuple.hs: multiOutsSection -- argument should be Tfm-expression"

    select :: Int -> Rate -> E -> E
select Int
cellId Rate
rate E
expr = Rate -> Exp E -> E
withRate Rate
rate (Exp E -> E) -> Exp E -> E
forall a b. (a -> b) -> a -> b
$ Rate -> Int -> PrimOr E -> Exp E
forall a. Rate -> Int -> a -> MainExp a
Select Rate
rate Int
cellId (Either Prim E -> PrimOr E
forall a. Either Prim a -> PrimOr a
PrimOr (Either Prim E -> PrimOr E) -> Either Prim E -> PrimOr E
forall a b. (a -> b) -> a -> b
$ E -> Either Prim E
forall a b. b -> Either a b
Right E
expr)


getRates :: MainExp a -> [Rate]
getRates :: forall a. MainExp a -> [Rate]
getRates (Tfm Info
info [a]
_) =
  case Info -> Signature
infoSignature Info
info of
    MultiRate [Rate]
outs [Rate]
_ -> [Rate]
outs
    Signature
_ -> String -> [Rate]
forall a. HasCallStack => String -> a
error String
"Build.hs:getRates - argument should be multiOut"
getRates MainExp a
_ = String -> [Rate]
forall a. HasCallStack => String -> a
error String
"Build.hs:getRates - argument should be Tfm-expression"


isMultiOutSignature :: Signature -> Bool
isMultiOutSignature :: Signature -> IsArrInit
isMultiOutSignature Signature
x =
  case Signature
x of
    MultiRate [Rate]
_ [Rate]
_ -> IsArrInit
True
    Signature
_ -> IsArrInit
False

getPrimUnsafe :: E -> Prim
getPrimUnsafe :: E -> Prim
getPrimUnsafe E
x = case E -> Exp E
toExp E
x of
    ExpPrim Prim
a   -> Prim
a
    Exp E
_           -> String -> Prim
forall a. HasCallStack => String -> a
error String
"Csound.Dynamic.Build.getPrimUnsafe:Expression is not a primitive"

-- expression tree

toExp :: E -> Exp E
toExp :: E -> Exp E
toExp = RatedExp E -> Exp E
forall a. RatedExp a -> Exp a
ratedExpExp (RatedExp E -> Exp E) -> (E -> RatedExp E) -> E -> Exp E
forall b c a. (b -> c) -> (a -> b) -> a -> c
. E -> RatedExp E
forall (f :: * -> *). Fix f -> f (Fix f)
unFix

-- Lifts transformation of main expression
onExp :: (Exp E -> Exp E) -> E -> E
onExp :: (Exp E -> Exp E) -> E -> E
onExp Exp E -> Exp E
f E
x =
  case E -> RatedExp E
forall (f :: * -> *). Fix f -> f (Fix f)
unFix E
x of
    RatedExp E
a -> RatedExp E -> E
forall (f :: * -> *). f (Fix f) -> Fix f
Fix (RatedExp E -> E) -> RatedExp E -> E
forall a b. (a -> b) -> a -> b
$ RatedExp E
a{ ratedExpExp = f (ratedExpExp a) }

----------------------------------------------------------------
-- global inits

setSr, setKsmps, setNchnls, setNchnls_i, setKr :: Monad m => Int -> DepT m ()

setZeroDbfs :: Monad m => Double -> DepT m  ()

setGlobal :: (Monad m, Show a) => Text -> a -> DepT m  ()
setGlobal :: forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
name a
val = Name -> DepT m ()
forall (m :: * -> *). Monad m => Name -> DepT m ()
verbatim (Name -> DepT m ()) -> Name -> DepT m ()
forall a b. (a -> b) -> a -> b
$ [Name] -> Name
Text.unwords [Name
name, Name
"=", String -> Name
Text.pack (String -> Name) -> String -> Name
forall a b. (a -> b) -> a -> b
$ a -> String
forall a. Show a => a -> String
show a
val]

setSr :: forall (m :: * -> *). Monad m => Int -> DepT m ()
setSr       = Name -> Int -> DepT m ()
forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
"sr"
setKr :: forall (m :: * -> *). Monad m => Int -> DepT m ()
setKr       = Name -> Int -> DepT m ()
forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
"kr"
setNchnls :: forall (m :: * -> *). Monad m => Int -> DepT m ()
setNchnls   = Name -> Int -> DepT m ()
forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
"nchnls"
setNchnls_i :: forall (m :: * -> *). Monad m => Int -> DepT m ()
setNchnls_i = Name -> Int -> DepT m ()
forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
"nchnls_i"
setKsmps :: forall (m :: * -> *). Monad m => Int -> DepT m ()
setKsmps    = Name -> Int -> DepT m ()
forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
"ksmps"
setZeroDbfs :: forall (m :: * -> *). Monad m => Double -> DepT m ()
setZeroDbfs = Name -> Double -> DepT m ()
forall (m :: * -> *) a. (Monad m, Show a) => Name -> a -> DepT m ()
setGlobal Name
"0dbfs"

gInit :: Monad m => Text -> Int -> DepT m ()
gInit :: forall (m :: * -> *). Monad m => Name -> Int -> DepT m ()
gInit Name
name Int
val = Var -> E -> DepT m ()
forall (m :: * -> *). Monad m => Var -> E -> DepT m ()
writeVar (Rate -> Name -> Var
VarVerbatim Rate
Ir Name
name) (Int -> E
int Int
val)

gInitDouble :: Monad m => Text -> Double -> DepT m ()
gInitDouble :: forall (m :: * -> *). Monad m => Name -> Double -> DepT m ()
gInitDouble Name
name Double
val = Var -> E -> DepT m ()
forall (m :: * -> *). Monad m => Var -> E -> DepT m ()
writeVar (Rate -> Name -> Var
VarVerbatim Rate
Ir Name
name) (Double -> E
double Double
val)