1#![deny(unsafe_code)]
7#![warn(missing_docs)]
8
9pub mod ast;
10pub mod backend;
11pub mod builtin;
12pub mod error;
13pub mod ir;
14pub mod lexer;
15pub mod lower;
16pub mod parser;
17pub mod prelude;
18pub mod program;
19pub mod schedule;
20pub mod serde_def;
21pub mod types;
22
23pub use error::{CompileError, Span};
24pub use program::RillProgram;
25pub use serde_def::{compile_def, RillLangDef};
26
27pub use builtin::{BuiltinKind, BuiltinSig, Registry, SampleBuiltin};
28
29use rill_core::math::Transcendental;
30
31pub fn compile<T: Transcendental>(src: &str) -> Result<RillProgram<T>, CompileError> {
43 let tokens = lexer::tokenize(src)?;
44 let program = parser::parse(&tokens)?;
45 let typed = types::infer::infer_program(&program)?;
46 let ir = lower::lower(&typed)?;
47 Ok(RillProgram::<T>::new(ir))
48}
49
50pub fn compile_with<T: Transcendental>(
52 src: &str,
53 registry: &Registry<T>,
54 sample_rate: f32,
55) -> Result<RillProgram<T>, CompileError> {
56 let tokens = lexer::tokenize(src)?;
57 let program = parser::parse(&tokens)?;
58 let typed = types::infer::infer_program_with(&program, registry)?;
59 let ir = lower::lower_with(&typed, registry, sample_rate)?;
60 validate_block_builtins(&ir)?;
61 RillProgram::<T>::new_with(ir, registry, sample_rate)
62}
63
64fn validate_block_builtins(ir: &crate::ir::Ir) -> Result<(), CompileError> {
65 use crate::ir::Instr;
66 use crate::schedule::{build_schedule, Step};
67 for instr in &ir.instrs {
68 if let Instr::CallSample { srcs, .. } = instr {
69 if srcs.len() > backend::interp::MAX_SAMPLE_BUILTIN_INS {
70 return Err(CompileError::Unsupported(format!(
71 "sample built-in has {} signal inputs; the maximum is {}",
72 srcs.len(),
73 backend::interp::MAX_SAMPLE_BUILTIN_INS,
74 )));
75 }
76 }
77 }
78 let sched = build_schedule(ir);
79 for step in &sched.steps {
80 if let Step::Sample(instrs) = step {
81 for &idx in instrs {
82 if matches!(ir.instrs[idx], Instr::CallBlock { .. }) {
83 return Err(CompileError::Unsupported(
84 "block built-in cannot be used inside a feedback loop (`~`)".to_string(),
85 ));
86 }
87 }
88 }
89 }
90 Ok(())
91}