mod access;
mod boundary_constraints;
mod buses;
mod constant;
mod evaluators;
mod functions;
mod integrity_constraints;
mod ir;
mod list_comprehension;
mod list_folding;
mod pub_inputs;
mod selectors;
mod source_sections;
mod trace;
mod variables;
pub use crate::CompileError;
use std::sync::Arc;
use crate::ir::Mir;
use air_pass::Pass;
use miden_diagnostics::{CodeMap, DiagnosticsConfig, DiagnosticsHandler, Verbosity};
pub fn compile(source: &str) -> Result<Mir, ()> {
let compiler = Compiler::default();
match compiler.compile(source) {
Ok(mir) => Ok(mir),
Err(err) => {
compiler.diagnostics.emit(err);
compiler.emitter.print_captured_to_stderr();
Err(())
}
}
}
pub fn translate(source: &str) -> Result<Mir, ()> {
let compiler = Compiler::default();
match compiler.translate(source) {
Ok(mir) => Ok(mir),
Err(err) => {
compiler.diagnostics.emit(err);
compiler.emitter.print_captured_to_stderr();
Err(())
}
}
}
#[allow(dead_code)]
pub fn parse(source: &str) -> Result<air_parser::ast::Program, ()> {
let compiler = Compiler::default();
match compiler.parse(source) {
Ok(ast) => Ok(ast),
Err(err) => {
compiler.diagnostics.emit(err);
compiler.emitter.print_captured_to_stderr();
Err(())
}
}
}
#[track_caller]
pub fn expect_diagnostic(source: &str, expected: &str) {
let compiler = Compiler::default();
let err = match compiler.compile(source) {
Ok(ref ast) => {
panic!("expected compilation to fail, got {ast:#?}");
}
Err(err) => err,
};
compiler.diagnostics.emit(err);
let found = compiler.emitter.captured().contains(expected);
if !found {
compiler.emitter.print_captured_to_stderr();
}
assert!(
found,
"expected diagnostic output to contain the string: '{expected}'",
);
}
struct Compiler {
codemap: Arc<CodeMap>,
emitter: Arc<SplitEmitter>,
diagnostics: Arc<DiagnosticsHandler>,
}
impl Default for Compiler {
fn default() -> Self {
Self::new(DiagnosticsConfig {
verbosity: Verbosity::Warning,
warnings_as_errors: true,
no_warn: false,
display: Default::default(),
})
}
}
impl Compiler {
pub fn new(config: DiagnosticsConfig) -> Self {
let codemap = Arc::new(CodeMap::new());
let emitter = Arc::new(SplitEmitter::new());
let diagnostics = Arc::new(DiagnosticsHandler::new(
config,
codemap.clone(),
emitter.clone(),
));
Self {
codemap,
emitter,
diagnostics,
}
}
pub fn compile(&self, source: &str) -> Result<Mir, CompileError> {
air_parser::parse(&self.diagnostics, self.codemap.clone(), source)
.map_err(CompileError::Parse)
.and_then(|ast| {
let mut pipeline =
air_parser::transforms::ConstantPropagation::new(&self.diagnostics)
.chain(crate::passes::AstToMir::new(&self.diagnostics))
.chain(crate::passes::Inlining::new(&self.diagnostics))
.chain(crate::passes::Unrolling::new(&self.diagnostics));
pipeline.run(ast)
})
}
pub fn translate(&self, source: &str) -> Result<Mir, CompileError> {
air_parser::parse(&self.diagnostics, self.codemap.clone(), source)
.map_err(CompileError::Parse)
.and_then(|ast| {
let mut pipeline =
air_parser::transforms::ConstantPropagation::new(&self.diagnostics)
.chain(crate::passes::AstToMir::new(&self.diagnostics));
pipeline.run(ast)
})
}
#[allow(dead_code)]
pub fn parse(&self, source: &str) -> Result<air_parser::ast::Program, CompileError> {
air_parser::parse(&self.diagnostics, self.codemap.clone(), source)
.map_err(CompileError::Parse)
}
}
struct SplitEmitter {
capture: miden_diagnostics::CaptureEmitter,
default: miden_diagnostics::DefaultEmitter,
}
impl SplitEmitter {
#[inline]
pub fn new() -> Self {
use miden_diagnostics::term::termcolor::ColorChoice;
Self {
capture: Default::default(),
default: miden_diagnostics::DefaultEmitter::new(ColorChoice::Auto),
}
}
pub fn captured(&self) -> String {
self.capture.captured()
}
pub fn print_captured_to_stderr(&self) {
use miden_diagnostics::Emitter;
use std::io::Write;
let mut copy = self.default.buffer();
let captured = self.capture.captured();
copy.write_all(captured.as_bytes()).unwrap();
self.default.print(copy).unwrap();
}
}
impl miden_diagnostics::Emitter for SplitEmitter {
#[inline]
fn buffer(&self) -> miden_diagnostics::term::termcolor::Buffer {
self.capture.buffer()
}
#[inline]
fn print(&self, buffer: miden_diagnostics::term::termcolor::Buffer) -> std::io::Result<()> {
self.capture.print(buffer)
}
}