[fine] test compilation, start removing print
This commit is contained in:
parent
d8db65af55
commit
d8988cb2cf
8 changed files with 239 additions and 81 deletions
|
|
@ -1,30 +1,32 @@
|
|||
use fine::compiler::{compile, Function, Module};
|
||||
use fine::parser::SyntaxTree;
|
||||
use fine::semantics::{Semantics, Type};
|
||||
use fine::tokens::Lines;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::fmt::Write as _;
|
||||
|
||||
fn rebase_concrete(source_path: &str, dump: &str) {
|
||||
fn rebase_section(source_path: &str, section: &str, value: &str) {
|
||||
let contents = std::fs::read_to_string(source_path)
|
||||
.expect(&format!("unable to read input file {}", source_path));
|
||||
|
||||
let mut result = String::new();
|
||||
let mut lines = contents.lines();
|
||||
|
||||
// Search for the "concrete:" section.
|
||||
let mut found_concrete_section = false;
|
||||
// Search for the section.
|
||||
let mut found_section = false;
|
||||
let marker = format!("// @{section}:");
|
||||
while let Some(line) = lines.next() {
|
||||
result.push_str(line);
|
||||
result.push_str("\n");
|
||||
|
||||
if line == "// @concrete:" {
|
||||
found_concrete_section = true;
|
||||
if line == marker {
|
||||
found_section = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found_concrete_section {
|
||||
if !found_section {
|
||||
panic!(
|
||||
"unable to locate the concrete section in {}. Is there a line that starts with '// concrete:'?",
|
||||
source_path
|
||||
"unable to locate the {section} section in {source_path}. Is there a line that starts with '// @{section}:'?"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +41,7 @@ fn rebase_concrete(source_path: &str, dump: &str) {
|
|||
// OK we're out of concrete syntax tree; copy in the
|
||||
// new CST. (We do this inline so we don't lose
|
||||
// `line`.)
|
||||
for expected_line in dump.lines() {
|
||||
for expected_line in value.lines() {
|
||||
result.push_str("// | ");
|
||||
result.push_str(expected_line);
|
||||
result.push_str("\n");
|
||||
|
|
@ -70,18 +72,24 @@ fn rebase_concrete(source_path: &str, dump: &str) {
|
|||
std::fs::write(source_path, result).expect("unable to write the new file!");
|
||||
}
|
||||
|
||||
fn assert_concrete(tree: &SyntaxTree, expected: &str, source_path: &str) {
|
||||
let dump = tree.dump(false);
|
||||
fn should_rebase() -> bool {
|
||||
let rebase = std::env::var("FINE_TEST_REBASE")
|
||||
.unwrap_or(String::new())
|
||||
.to_lowercase();
|
||||
match rebase.as_str() {
|
||||
"1" | "true" | "yes" | "y" => {
|
||||
if dump != expected {
|
||||
rebase_concrete(source_path, &dump)
|
||||
}
|
||||
"1" | "true" | "yes" | "y" => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_concrete(tree: &SyntaxTree, expected: &str, source_path: &str) {
|
||||
let dump = tree.dump(false);
|
||||
if dump != expected {
|
||||
if should_rebase() {
|
||||
rebase_section(source_path, "concrete", &dump)
|
||||
} else {
|
||||
assert_eq!(expected, dump, "concrete syntax trees did not match (set FINE_TEST_REBASE=1 to auto-rebase if the diff is expected)")
|
||||
}
|
||||
_ => assert_eq!(expected, dump, "concrete syntax trees did not match (set FINE_TEST_REBASE=1 to auto-rebase if the diff is expected)"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,4 +189,58 @@ fn assert_type_error_at(
|
|||
);
|
||||
}
|
||||
|
||||
fn dump_function(out: &mut String, function: &Function) -> std::fmt::Result {
|
||||
writeln!(
|
||||
out,
|
||||
"function {} ({} args, {} locals):",
|
||||
function.name(),
|
||||
function.args(),
|
||||
function.locals()
|
||||
)?;
|
||||
|
||||
let strings = function.strings();
|
||||
writeln!(out, " strings ({}):", strings.len())?;
|
||||
for (i, s) in strings.iter().enumerate() {
|
||||
writeln!(out, " {}: {}", i, s)?; // TODO: ESCAPE
|
||||
}
|
||||
|
||||
let code = function.instructions();
|
||||
writeln!(out, " code ({}):", code.len())?;
|
||||
for (i, inst) in code.iter().enumerate() {
|
||||
writeln!(out, " {}: {:?}", i, inst)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dump_module(out: &mut String, module: &Module) -> std::fmt::Result {
|
||||
for function in module.functions() {
|
||||
dump_function(out, function)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assert_compiles_to(tree: &SyntaxTree, lines: &Lines, expected: &str, source_path: &str) {
|
||||
let semantics = Semantics::new(tree, lines);
|
||||
let module = compile(&semantics);
|
||||
|
||||
let mut actual = String::new();
|
||||
dump_module(&mut actual, &module).expect("no dumping?");
|
||||
|
||||
if expected != actual {
|
||||
if should_rebase() {
|
||||
rebase_section(source_path, "compiles-to", &actual)
|
||||
} else {
|
||||
semantic_assert_eq!(
|
||||
&semantics,
|
||||
None,
|
||||
expected,
|
||||
actual,
|
||||
"did not compile as expected (set FINE_TEST_REBASE=1 to auto-rebase if the diff is expected)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/generated_tests.rs"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue