Offer a way to print mono IR in uitest

This commit is contained in:
Ayaz Hafiz 2023-04-12 10:50:30 -05:00
parent 191d8a7408
commit 53af6ed4eb
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
6 changed files with 146 additions and 4 deletions

4
Cargo.lock generated
View file

@ -5084,8 +5084,12 @@ dependencies = [
"pretty_assertions",
"regex",
"roc_builtins",
"roc_collections",
"roc_derive",
"roc_load",
"roc_module",
"roc_mono",
"roc_packaging",
"roc_parse",
"roc_problem",
"roc_reporting",

View file

@ -373,9 +373,6 @@ pub fn infer_queries(src: &str, options: InferOptions) -> Result<InferredProgram
let line_info = LineInfo::new(&src);
let queries = parse_queries(&src, &line_info);
if queries.is_empty() {
return Err("No queries provided!".into());
}
let mut inferred_queries = Vec::with_capacity(queries.len());
let exposed_by_module = ExposedByModule::default();

View file

@ -14,8 +14,12 @@ harness = false
[dev-dependencies]
roc_builtins = { path = "../builtins" }
roc_collections = { path = "../collections" }
roc_derive = { path = "../derive", features = ["debug-derived-symbols"] }
roc_load = { path = "../load" }
roc_packaging = { path = "../../packaging" }
roc_module = { path = "../module", features = ["debug-symbols"] }
roc_mono = { path = "../mono" }
roc_parse = { path = "../parse" }
roc_problem = { path = "../problem" }
roc_reporting = { path = "../../reporting" }

View file

@ -0,0 +1,116 @@
use std::io;
use bumpalo::Bump;
use roc_collections::MutMap;
use roc_load::{ExecutionMode, LoadConfig, LoadMonomorphizedError, Threading};
use roc_module::symbol::{Interns, Symbol};
use roc_mono::{
ir::{Proc, ProcLayout},
layout::STLayoutInterner,
};
pub fn write_compiled_ir(writer: &mut impl io::Write, module_source: &str) -> io::Result<()> {
use roc_packaging::cache::RocCacheDir;
use std::path::PathBuf;
let exec_mode = ExecutionMode::Executable;
let arena = &Bump::new();
let filename = PathBuf::from("Test.roc");
let src_dir = PathBuf::from("fake/test/path");
let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(),
threading: Threading::Single,
render: roc_reporting::report::RenderTarget::Generic,
palette: roc_reporting::report::DEFAULT_PALETTE,
exec_mode,
};
let loaded = roc_load::load_and_monomorphize_from_str(
arena,
filename,
module_source,
src_dir,
RocCacheDir::Disallowed,
load_config,
);
let loaded = match loaded {
Ok(x) => x,
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
report,
))) => {
println!("{}", report);
panic!();
}
Err(e) => panic!("{:?}", e),
};
use roc_load::MonomorphizedModule;
let MonomorphizedModule {
procedures,
exposed_to_host,
mut layout_interner,
interns,
..
} = loaded;
let main_fn_symbol = exposed_to_host.top_level_values.keys().copied().next();
check_procedures(arena, &interns, &mut layout_interner, &procedures);
write_procedures(writer, layout_interner, procedures, main_fn_symbol)
}
fn check_procedures<'a>(
arena: &'a Bump,
interns: &Interns,
interner: &mut STLayoutInterner<'a>,
procedures: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
) {
use roc_mono::debug::{check_procs, format_problems};
let problems = check_procs(arena, interner, procedures);
if problems.is_empty() {
return;
}
let formatted = format_problems(interns, interner, problems);
panic!("IR problems found:\n{formatted}");
}
fn write_procedures<'a>(
writer: &mut impl io::Write,
interner: STLayoutInterner<'a>,
procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
opt_main_fn_symbol: Option<Symbol>,
) -> io::Result<()> {
let mut procs_strings = procedures
.values()
.map(|proc| proc.to_pretty(&interner, 200, false))
.collect::<Vec<_>>();
let opt_main_fn = opt_main_fn_symbol.map(|main_fn_symbol| {
let index = procedures
.keys()
.position(|(s, _)| *s == main_fn_symbol)
.unwrap();
procs_strings.swap_remove(index)
});
procs_strings.sort();
if let Some(main_fn) = opt_main_fn {
procs_strings.push(main_fn);
}
let mut procs = procs_strings.iter().peekable();
while let Some(proc) = procs.next() {
if procs.peek().is_some() {
writeln!(writer, "{}", proc)?;
} else {
write!(writer, "{}", proc)?;
}
}
Ok(())
}

View file

@ -13,6 +13,8 @@ use test_solve_helpers::{
infer_queries, Elaboration, InferOptions, InferredProgram, InferredQuery, MUTLILINE_MARKER,
};
mod mono;
fn main() -> Result<(), Box<dyn Error>> {
let args = Arguments::from_args();
@ -110,6 +112,7 @@ struct TestCase {
#[derive(Default)]
struct PrintOptions {
can_decls: bool,
mono: bool,
}
impl TestCase {
@ -154,6 +157,7 @@ impl TestCase {
let opt = infer_opt.name("opt").unwrap().as_str();
match opt.trim() {
"can_decls" => print_opts.can_decls = true,
"mono" => print_opts.mono = true,
other => return Err(format!("unknown print option: {other:?}").into()),
}
}
@ -197,12 +201,20 @@ fn assemble_query_output(
write_source_with_answers(&mut reflow, source, sorted_queries, 0)?;
// Finish up with any remaining print options we were asked to provide.
let PrintOptions { can_decls } = print_options;
let PrintOptions { can_decls, mono } = print_options;
if can_decls {
writeln!(writer, "\n{EMIT_HEADER}can_decls")?;
program.write_can_decls(writer)?;
}
if mono {
writeln!(writer, "\n{EMIT_HEADER}mono")?;
// Unfortunately, with the current setup we must now recompile into the IR.
// TODO: extend the data returned by a monomorphized module to include
// that of a solved module.
mono::write_compiled_ir(writer, source)?;
}
Ok(())
}

View file

@ -0,0 +1,9 @@
# +opt print:mono
app "test" provides [main] to "./platform"
main = ""
# -emit:mono
procedure Test.0 ():
let Test.1 : Str = "";
ret Test.1;