Merge remote-tracking branch 'origin/main' into abilities-syntax

This commit is contained in:
Richard Feldman 2023-08-10 20:29:27 -04:00
commit 2da41be29f
No known key found for this signature in database
GPG key ID: F1F21AA5B1D9E43B
524 changed files with 47536 additions and 15089 deletions

View file

@ -11,16 +11,19 @@ use roc_mono::{
use tempfile::tempdir;
use test_solve_helpers::format_problems;
use crate::CompilerSettings;
#[derive(Default)]
pub struct MonoOptions {
pub(crate) struct MonoOptions {
pub no_check: bool,
}
pub fn write_compiled_ir<'a>(
pub(crate) fn write_compiled_ir<'a>(
writer: &mut impl io::Write,
test_module: &str,
dependencies: impl IntoIterator<Item = (&'a str, &'a str)>,
options: MonoOptions,
compiler_settings: CompilerSettings,
allow_can_errors: bool,
) -> io::Result<()> {
use roc_packaging::cache::RocCacheDir;
@ -41,6 +44,7 @@ pub fn write_compiled_ir<'a>(
let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(),
function_kind: compiler_settings.function_kind,
threading: Threading::Single,
render: roc_reporting::report::RenderTarget::Generic,
palette: roc_reporting::report::DEFAULT_PALETTE,
@ -60,10 +64,10 @@ pub fn write_compiled_ir<'a>(
Err(LoadMonomorphizedError::LoadingProblem(roc_load::LoadingProblem::FormattedReport(
report,
))) => {
println!("{}", report);
println!("{report}");
panic!();
}
Err(e) => panic!("{:?}", e),
Err(e) => panic!("{e:?}"),
};
use roc_load::MonomorphizedModule;
@ -146,9 +150,9 @@ fn write_procedures<'a>(
let mut procs = procs_strings.iter().peekable();
while let Some(proc) = procs.next() {
if procs.peek().is_some() {
writeln!(writer, "{}", proc)?;
writeln!(writer, "{proc}")?;
} else {
write!(writer, "{}", proc)?;
write!(writer, "{proc}")?;
}
}

View file

@ -11,6 +11,7 @@ use libtest_mimic::{run, Arguments, Failed, Trial};
use mono::MonoOptions;
use regex::Regex;
use roc_collections::VecMap;
use roc_solve::FunctionKind;
use test_solve_helpers::{
infer_queries, Elaboration, InferOptions, InferredProgram, InferredQuery, MUTLILINE_MARKER,
};
@ -36,6 +37,10 @@ lazy_static! {
.join("uitest")
.join("tests");
/// # +set <setting>
static ref RE_SETTING: Regex =
Regex::new(r#"# \+set (?P<setting>.*?)=(?P<value>.*)"#).unwrap();
/// # +opt can:<opt>
static ref RE_OPT_CAN: Regex =
Regex::new(r#"# \+opt can:(?P<opt>.*)"#).unwrap();
@ -94,6 +99,7 @@ fn into_test(path: PathBuf) -> io::Result<Trial> {
fn run_test(path: PathBuf) -> Result<(), Failed> {
let data = std::fs::read_to_string(&path)?;
let TestCase {
compiler_settings,
can_options,
infer_options,
emit_options,
@ -109,6 +115,7 @@ fn run_test(path: PathBuf) -> Result<(), Failed> {
.map(|(md, src)| (&**md, &**src)),
infer_options,
can_options.allow_errors,
compiler_settings.function_kind,
)?;
{
@ -121,6 +128,7 @@ fn run_test(path: PathBuf) -> Result<(), Failed> {
&mut fd,
program,
inferred_program,
compiler_settings,
can_options,
mono_options,
emit_options,
@ -141,6 +149,7 @@ struct Modules<'a> {
}
struct TestCase<'a> {
compiler_settings: CompilerSettings,
can_options: CanOptions,
infer_options: InferOptions,
mono_options: MonoOptions,
@ -148,6 +157,18 @@ struct TestCase<'a> {
program: Modules<'a>,
}
struct CompilerSettings {
function_kind: FunctionKind,
}
impl Default for CompilerSettings {
fn default() -> Self {
Self {
function_kind: FunctionKind::LambdaSet,
}
}
}
#[derive(Default)]
struct CanOptions {
allow_errors: bool,
@ -166,6 +187,7 @@ impl<'a> TestCase<'a> {
data = data[..drop_at].trim_end();
}
let compiler_settings = Self::parse_compiler_settings(data)?;
let can_options = Self::parse_can_options(data)?;
let infer_options = Self::parse_infer_options(data)?;
let mono_options = Self::parse_mono_options(data)?;
@ -174,6 +196,7 @@ impl<'a> TestCase<'a> {
let program = Self::parse_modules(data);
Ok(TestCase {
compiler_settings,
can_options,
infer_options,
mono_options,
@ -229,6 +252,26 @@ impl<'a> TestCase<'a> {
}
}
fn parse_compiler_settings(data: &str) -> Result<CompilerSettings, Failed> {
let mut settings = CompilerSettings::default();
let found_settings = RE_SETTING.captures_iter(data);
for set in found_settings {
let setting = set.name("setting").unwrap().as_str();
let value = set.name("value").unwrap().as_str();
match setting.trim() {
"function_kind" => match value.trim() {
"lambda_set" => settings.function_kind = FunctionKind::LambdaSet,
"erased" => settings.function_kind = FunctionKind::Erased,
other => return Err(format!("unknown function kind: {other:?}").into()),
},
other => return Err(format!("unknown compiler setting: {other:?}").into()),
}
}
Ok(settings)
}
fn parse_can_options(data: &str) -> Result<CanOptions, Failed> {
let mut can_opts = CanOptions::default();
@ -321,6 +364,7 @@ fn assemble_query_output(
writer: &mut impl io::Write,
program: Modules<'_>,
inferred_program: InferredProgram,
compiler_settings: CompilerSettings,
can_options: CanOptions,
mono_options: MonoOptions,
emit_options: EmitOptions,
@ -337,7 +381,7 @@ fn assemble_query_output(
for (module, source) in other_modules.iter() {
writeln!(writer, "## module {module}")?;
writeln!(writer, "{}\n", source)?;
writeln!(writer, "{source}\n")?;
}
if !other_modules.is_empty() {
@ -369,6 +413,7 @@ fn assemble_query_output(
test_module,
other_modules,
mono_options,
compiler_settings,
can_options.allow_errors,
)?;
}
@ -393,7 +438,7 @@ fn write_source_with_answers<W: io::Write>(
Some(InferredQuery {
source_line_column,
..
}) if source_line_column.line == i as _
}) if source_line_column.line == i as u32
) {
let inferred = sorted_queries.pop().unwrap();

View file

@ -8,5 +8,5 @@ main =
s2 = Set.empty {}
Bool.isEq s1 s1 && Bool.isEq s2 s2
# ^^^^^^^^^ Set#Bool.isEq(17): Set Str, Set Str -[[Set.isEq(17)]]-> Bool
# ^^^^^^^^^ Set#Bool.isEq(17): Set U8, Set U8 -[[Set.isEq(17)]]-> Bool
# ^^^^^^^^^ Set#Bool.isEq(20): Set Str, Set Str -[[Set.isEq(20)]]-> Bool
# ^^^^^^^^^ Set#Bool.isEq(20): Set U8, Set U8 -[[Set.isEq(20)]]-> Bool

View file

@ -0,0 +1,87 @@
# +set function_kind=erased
# +emit:mono
app "test" provides [main] to "./platform"
f = \s ->
if Bool.true
then \{} -> ""
# ^^^^^^^^^ {}* -?-> Str
else \{} -> s
# ^^^^^^^^ {}* -?-> Str
main = (f "") {}
# ^^^^ {} -?-> Str
# -emit:mono
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Test.1 (Test.2):
let Test.34 : Int1 = CallByName Bool.2;
if Test.34 then
dec Test.2;
let Test.38 : FunPtr(({}) -> Str) = FunctionPointer Test.3;
let Test.35 : ?Erased = ErasedMake { value: <null>, callee: Test.38 };
ret Test.35;
else
let Test.33 : {Str} = Struct {Test.2};
let Test.31 : [<rnu><null>, C {Str}] = TagId(0) Test.33;
let Test.32 : FunPtr(({}, ?Erased) -> Str) = FunctionPointer Test.4;
let Test.26 : ?Erased = ErasedMake { value: Test.31, callee: Test.32 };
ret Test.26;
procedure Test.3 (Test.36):
let Test.37 : Str = "";
ret Test.37;
procedure Test.4 (Test.27, #Attr.12):
let Test.29 : [<rnu><null>, C {Str}] = ErasedLoad #Attr.12 .Value;
let Test.30 : {Str} = UnionAtIndex (Id 0) (Index 0) Test.29;
joinpoint #Derived_gen.0:
let Test.2 : Str = StructAtIndex 0 Test.30;
ret Test.2;
in
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.29;
if #Derived_gen.1 then
free Test.29;
jump #Derived_gen.0;
else
inc Test.30;
decref Test.29;
jump #Derived_gen.0;
procedure Test.0 ():
let Test.6 : {} = Struct {};
let Test.16 : Str = "";
let Test.39 : FunPtr((Str) -> ?Erased) = FunctionPointer Test.1;
let Test.17 : ?Erased = ErasedMake { value: <null>, callee: Test.39 };
joinpoint Test.18 Test.7:
joinpoint Test.8 Test.5:
ret Test.5;
in
let Test.9 : Ptr([]) = ErasedLoad Test.7 .ValuePtr;
let Test.11 : Ptr([]) = NullPointer;
let Test.10 : Int1 = lowlevel Eq Test.9 Test.11;
if Test.10 then
dec Test.7;
let Test.12 : FunPtr(({}) -> Str) = ErasedLoad Test.7 .Callee;
let Test.13 : Str = CallByPtr Test.12 Test.6;
jump Test.8 Test.13;
else
let Test.14 : FunPtr(({}, ?Erased) -> Str) = ErasedLoad Test.7 .Callee;
let Test.15 : Str = CallByPtr Test.14 Test.6 Test.7;
jump Test.8 Test.15;
in
let Test.19 : Ptr([]) = ErasedLoad Test.17 .ValuePtr;
let Test.21 : Ptr([]) = NullPointer;
let Test.20 : Int1 = lowlevel Eq Test.19 Test.21;
if Test.20 then
dec Test.17;
let Test.22 : FunPtr((Str) -> ?Erased) = ErasedLoad Test.17 .Callee;
let Test.23 : ?Erased = CallByPtr Test.22 Test.16;
jump Test.18 Test.23;
else
let Test.24 : FunPtr((Str, ?Erased) -> ?Erased) = ErasedLoad Test.17 .Callee;
let Test.25 : ?Erased = CallByPtr Test.24 Test.16 Test.17;
jump Test.18 Test.25;

View file

@ -3,22 +3,22 @@
app "test" provides [main] to "./platform"
f = \{} ->
#^{-1} <1599><116>{} -<119>[[f(1)]]-> <115>[Ok <1607>{}]<79>*
#^{-1} <1600><117>{} -<120>[[f(1)]]-> <116>[Ok <1608>{}]<80>*
when g {} is
# ^ <1589><1607>{} -<1597>[[g(2)]]-> <71>[Ok <1607>{}]<101>*
# ^ <1590><1608>{} -<1598>[[g(2)]]-> <72>[Ok <1608>{}]<102>*
_ -> Ok {}
g = \{} ->
#^{-1} <1589><1607>{} -<1597>[[g(2)]]-> <71>[Ok <1607>{}]<101>*
#^{-1} <1590><1608>{} -<1598>[[g(2)]]-> <72>[Ok <1608>{}]<102>*
when h {} is
# ^ <1594><1607>{} -<1602>[[h(3)]]-> <93>[Ok <1607>{}]<123>*
# ^ <1595><1608>{} -<1603>[[h(3)]]-> <94>[Ok <1608>{}]<124>*
_ -> Ok {}
h = \{} ->
#^{-1} <1594><1607>{} -<1602>[[h(3)]]-> <93>[Ok <1607>{}]<123>*
#^{-1} <1595><1608>{} -<1603>[[h(3)]]-> <94>[Ok <1608>{}]<124>*
when f {} is
# ^ <1599><116>{} -<119>[[f(1)]]-> <115>[Ok <1607>{}]<79>*
# ^ <1600><117>{} -<120>[[f(1)]]-> <116>[Ok <1608>{}]<80>*
_ -> Ok {}
main = f {}
# ^ <1609><132>{} -<135>[[f(1)]]-> <137>[Ok <1607>{}]<1608>w_a
# ^ <1610><133>{} -<136>[[f(1)]]-> <138>[Ok <1608>{}]<1609>w_a

View file

@ -0,0 +1,19 @@
interface Test exposes [main] imports []
Term : [
Bar Term,
Foo,
]
f = \list ->
when list is
# ^^^^ List ([Bar [Bar a]*, Foo]* as a)
[] -> Foo
[b] -> b
[b, ..] -> Bar (Bar b)
whatever : Term -> Str
whatever = \_ -> "done"
main = whatever (f [])
# ^^ List ([Bar a, Foo] as a)