Skip to main content

sva_engine/
lib.rs

1// Concern: resolves a graph into instances a caller can ask about, and keeps their buffers | Non-concern: parsing (sva-ast), CLI framing (sva-cli) | IO: (&Graph, root) -> Instances, Traced
2
3mod arguments;
4mod bindings;
5mod cache;
6mod cast;
7mod error;
8pub mod flops;
9pub mod instantiate;
10mod loops;
11mod lower;
12mod meaning;
13mod offset;
14pub mod overload;
15pub mod query;
16mod refs;
17mod release;
18pub mod render;
19mod schedule;
20mod trace;
21mod typing;
22mod vocabulary;
23
24pub use arguments::{Argument, Arguments, Called, Chosen};
25pub use bindings::Binding;
26pub use cache::{
27    Cache, CachePolicy, CacheStats, DEFAULT_CACHE_BYTES, Hash, Lookup, Outcome, PayloadKind,
28    PrunePolicy, buffer_key, symbolic_key,
29};
30pub use cast::Cast;
31pub use error::{BindingFault, Diagnostic, EngineError, Located, REGISTRY};
32pub use flops::{Row as FlopRow, Tree as FlopTree, Work};
33pub use loops::{Delay, Shift};
34pub use meaning::{Meaning, meaning};
35pub use offset::Offset;
36pub use query::{Answer, Ask, DEFAULT_FRAME_SECS, Output, Representation};
37pub use refs::{Read, identity, nodes_in, resolve, spectral_sum_of, symbolic_hash};
38pub use render::{
39    Block, Checkpoint, Render, RenderConfig, STREAMED, Silent, Stream, StreamConfig, answer,
40    answer_buffer, ledger_over, render, render_until_silent, sketch_atom,
41};
42pub use schedule::{Order, Schedule, schedule_from};
43pub use sva_formula::{C64, Codomain, Held, Line, NodeId, SpectralSum, Ty, Var};
44pub use sva_samples::{
45    Alias, AliasBand, BAND_COUNT, BandCrest, BandTrack, Bands, Buffer, Cost, Crest, Detail,
46    EnvelopeFrame, FormantFrame, Frames, Horizon, Label, LedgerEntry, Loudness, LoudnessFrame,
47    MAX_PINNED_FRAME, PSYCHOACOUSTIC_V1, PitchFrame, Profile, Rule, SignalKind, Source, Spectrum,
48    StereoFrame, StereoImage, measure_alias, pinned_frame,
49};
50pub use trace::{Traced, Up, trace};
51pub use typing::{Typing, Value};
52pub use vocabulary::{BUILTINS, MAX_WIDTH, is_builtin, named_may_move, recognized_named};
53
54use sva_ast::Graph;
55
56pub const DEFAULT_SAMPLE_RATE: u32 = 44100;
57
58/// One inference, so a lint and a render refuse identically.
59pub fn check_structure(graph: &Graph, root: &str) -> Result<(), EngineError> {
60    types(graph, root).map(|_| ())
61}
62
63/// One `Ty` per node, across refs, over the instances `root` reaches.
64pub fn types(graph: &Graph, root: &str) -> Result<Typing, EngineError> {
65    let instances = instantiate::instantiate(graph, root)?;
66    // A root names the instance its own defaults resolved to, as `render` asks for.
67    let held = instances.instance_of(root)?;
68    let order = schedule::schedule_from(&instances, std::slice::from_ref(&held))?;
69    typing::infer_all(&instances, &order)
70}
71
72/// Every instance whose samples are a function of the RATE, not just of `t`.
73pub fn rate_dependent(graph: &Graph, root: &str) -> Result<Vec<String>, EngineError> {
74    let instances = instantiate::instantiate(graph, root)?;
75    Ok(instances
76        .paths()
77        .filter(|p| instances.at(p).is_some_and(|(e, _)| reads_rate(e)))
78        .map(str::to_string)
79        .collect())
80}
81
82fn reads_rate(e: &sva_ast::Expr) -> bool {
83    match e {
84        sva_ast::Expr::Lit(sva_ast::Literal::Samples(_)) => true,
85        sva_ast::Expr::Lit(_) => false,
86        sva_ast::Expr::Var(_) => false,
87        sva_ast::Expr::Bin(_, a, b) => reads_rate(a) || reads_rate(b),
88        sva_ast::Expr::SelfRef { .. } => true,
89        sva_ast::Expr::Ref { arg, binds, .. } => {
90            reads_rate(arg) || binds.iter().any(|(_, v)| reads_rate(v))
91        }
92        sva_ast::Expr::Call { name, args, .. } => {
93            let drawn = name == "rand"
94                && !matches!(
95                    args.first(),
96                    Some(sva_ast::Arg::Pos(sva_ast::Expr::Lit(_))) | None
97                );
98            drawn
99                || args.iter().any(|a| match a {
100                    sva_ast::Arg::Pos(v) | sva_ast::Arg::Named(_, v) => reads_rate(v),
101                })
102        }
103    }
104}