mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-04 00:55:00 +00:00
Introduce polarity for extension variable printing
This commit is contained in:
parent
ae1a9e4dd6
commit
d77080529a
6 changed files with 187 additions and 78 deletions
|
|
@ -229,10 +229,7 @@ fn expect_types(mut loaded_module: LoadedModule, mut expected_types: HashMap<&st
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
||||||
let debug_print = DebugPrint {
|
let debug_print = DebugPrint::NOTHING;
|
||||||
print_lambda_sets: false,
|
|
||||||
print_only_under_alias: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
let interns = &loaded_module.interns;
|
let interns = &loaded_module.interns;
|
||||||
let declarations = loaded_module.declarations_by_id.remove(&home).unwrap();
|
let declarations = loaded_module.declarations_by_id.remove(&home).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,7 @@ mod solve_expr {
|
||||||
DebugPrint {
|
DebugPrint {
|
||||||
print_lambda_sets: true,
|
print_lambda_sets: true,
|
||||||
print_only_under_alias: options.print_only_under_alias,
|
print_only_under_alias: options.print_only_under_alias,
|
||||||
|
ignore_polarity: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
subs.rollback_to(snapshot);
|
subs.rollback_to(snapshot);
|
||||||
|
|
@ -844,7 +845,7 @@ mod solve_expr {
|
||||||
List.map ["a", "b"] \elem -> Foo elem
|
List.map ["a", "b"] \elem -> Foo elem
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"List [Foo Str]*",
|
"List [Foo Str]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,7 +860,7 @@ mod solve_expr {
|
||||||
foo "hi"
|
foo "hi"
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[Foo Str]*",
|
"[Foo Str]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -872,7 +873,7 @@ mod solve_expr {
|
||||||
List.map ["a", "b"] Foo
|
List.map ["a", "b"] Foo
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"List [Foo Str]*",
|
"List [Foo Str]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -885,7 +886,7 @@ mod solve_expr {
|
||||||
[\x -> Bar x, Foo]
|
[\x -> Bar x, Foo]
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"List (a -> [Bar a, Foo a]*)",
|
"List (a -> [Bar a, Foo a])",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -898,7 +899,7 @@ mod solve_expr {
|
||||||
[Foo, \x -> Bar x]
|
[Foo, \x -> Bar x]
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"List (a -> [Bar a, Foo a]*)",
|
"List (a -> [Bar a, Foo a])",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -917,7 +918,7 @@ mod solve_expr {
|
||||||
}
|
}
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"{ x : List [Foo]*, y : List (a -> [Foo a]*), z : List (b, c -> [Foo b c]*) }",
|
"{ x : List [Foo], y : List (a -> [Foo a]), z : List (b, c -> [Foo b c]) }",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1572,7 +1573,7 @@ mod solve_expr {
|
||||||
Foo
|
Foo
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[Foo]*",
|
"[Foo]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1611,7 +1612,7 @@ mod solve_expr {
|
||||||
Foo "happy" 12
|
Foo "happy" 12
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[Foo Str (Num *)]*",
|
"[Foo Str (Num *)]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1652,7 +1653,7 @@ mod solve_expr {
|
||||||
\Foo x -> Foo x
|
\Foo x -> Foo x
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[Foo a] -> [Foo a]*",
|
"[Foo a] -> [Foo a]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1664,7 +1665,7 @@ mod solve_expr {
|
||||||
\Foo x _ -> Foo x "y"
|
\Foo x _ -> Foo x "y"
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[Foo a *] -> [Foo a Str]*",
|
"[Foo a *] -> [Foo a Str]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2672,7 +2673,7 @@ mod solve_expr {
|
||||||
fromBit
|
fromBit
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Num * -> [False, True]*",
|
"Num * -> [False, True]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2899,7 +2900,7 @@ mod solve_expr {
|
||||||
map
|
map
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"(a -> b), [Cons a c, Nil] as c -> [Cons b d, Nil]* as d",
|
"(a -> b), [Cons a c, Nil] as c -> [Cons b d, Nil] as d",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3160,7 +3161,7 @@ mod solve_expr {
|
||||||
map
|
map
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[S a, Z] as a -> [S b, Z]* as b",
|
"[S a, Z] as a -> [S b, Z] as b",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3179,7 +3180,7 @@ mod solve_expr {
|
||||||
map
|
map
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[S a, Z] as a -> [S b, Z]* as b",
|
"[S a, Z] as a -> [S b, Z] as b",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3250,7 +3251,7 @@ mod solve_expr {
|
||||||
map
|
map
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"(a -> b), [Cons { x : a, xs : c }*, Nil] as c -> [Cons { x : b, xs : d }, Nil]* as d",
|
"(a -> b), [Cons { x : a, xs : c }*, Nil] as c -> [Cons { x : b, xs : d }, Nil] as d",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3317,7 +3318,7 @@ mod solve_expr {
|
||||||
toAs
|
toAs
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"(a -> b), [Cons c [Cons a d, Nil], Nil] as d -> [Cons c [Cons b e]*, Nil]* as e",
|
"(a -> b), [Cons c [Cons a d, Nil], Nil] as d -> [Cons c [Cons b e], Nil] as e",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4248,10 +4249,10 @@ mod solve_expr {
|
||||||
Foo Bar 1
|
Foo Bar 1
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[Foo [Bar]* (Num *)]*",
|
"[Foo [Bar] (Num *)]",
|
||||||
);
|
);
|
||||||
|
|
||||||
infer_eq_without_problem("Foo Bar 1", "[Foo [Bar]* (Num *)]*");
|
infer_eq_without_problem("Foo Bar 1", "[Foo [Bar] (Num *)]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -4979,7 +4980,7 @@ mod solve_expr {
|
||||||
canIGo
|
canIGo
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Str -> Result Str [SlowIt Str, StopIt Str, UnknownColor Str]*",
|
"Str -> Result Str [SlowIt Str, StopIt Str, UnknownColor Str]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5106,7 +5107,7 @@ mod solve_expr {
|
||||||
B -> Y
|
B -> Y
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A, B] -> [X, Y]*",
|
"[A, B] -> [X, Y]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5122,7 +5123,7 @@ mod solve_expr {
|
||||||
_ -> Z
|
_ -> Z
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A, B]* -> [X, Y, Z]*",
|
"[A, B]* -> [X, Y, Z]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5137,7 +5138,7 @@ mod solve_expr {
|
||||||
A N -> Y
|
A N -> Y
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A [M, N]] -> [X, Y]*",
|
"[A [M, N]] -> [X, Y]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5153,7 +5154,7 @@ mod solve_expr {
|
||||||
A _ -> Z
|
A _ -> Z
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A [M, N]*] -> [X, Y, Z]*",
|
"[A [M, N]*] -> [X, Y, Z]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5168,7 +5169,7 @@ mod solve_expr {
|
||||||
A (N K) -> X
|
A (N K) -> X
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A [M [J], N [K]]] -> [X]*",
|
"[A [M [J], N [K]]] -> [X]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5184,7 +5185,7 @@ mod solve_expr {
|
||||||
A N -> X
|
A N -> X
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A [M, N], B] -> [X]*",
|
"[A [M, N], B] -> [X]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5199,9 +5200,6 @@ mod solve_expr {
|
||||||
t -> t
|
t -> t
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
// TODO: we could be a bit smarter by subtracting "A" as a possible
|
|
||||||
// tag in the union known by t, which would yield the principal type
|
|
||||||
// [A,]a -> [X]a
|
|
||||||
"[A, X]a -> [A, X]a",
|
"[A, X]a -> [A, X]a",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -5528,7 +5526,7 @@ mod solve_expr {
|
||||||
Job lst s -> P lst s
|
Job lst s -> P lst s
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[P (List ([Job (List a) Str] as a)) Str]*",
|
"[P (List ([Job (List a) Str] as a)) Str]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5646,7 +5644,7 @@ mod solve_expr {
|
||||||
else @Id (Id 21 (Z "felix"))
|
else @Id (Id 21 (Z "felix"))
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
r#"Id [Y Str, Z Str]*"#,
|
r#"Id [Y Str, Z Str]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5933,7 +5931,7 @@ mod solve_expr {
|
||||||
if Bool.true then List.first [] else Str.toI64 ""
|
if Bool.true then List.first [] else Str.toI64 ""
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Result I64 [InvalidNumStr, ListWasEmpty]*",
|
"Result I64 [InvalidNumStr, ListWasEmpty]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7853,7 +7851,7 @@ mod solve_expr {
|
||||||
g ""
|
g ""
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"[A Str, B Str]*",
|
"[A Str, B Str]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,7 @@ fn assemble_derived_golden(
|
||||||
DebugPrint {
|
DebugPrint {
|
||||||
print_lambda_sets: true,
|
print_lambda_sets: true,
|
||||||
print_only_under_alias,
|
print_only_under_alias,
|
||||||
|
..DebugPrint::NOTHING
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
subs.rollback_to(snapshot);
|
subs.rollback_to(snapshot);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ use crate::subs::{
|
||||||
self, AliasVariables, Content, FlatType, GetSubsSlice, Label, Subs, SubsIndex, UnionLabels,
|
self, AliasVariables, Content, FlatType, GetSubsSlice, Label, Subs, SubsIndex, UnionLabels,
|
||||||
UnionTags, UnsortedUnionLabels, Variable,
|
UnionTags, UnsortedUnionLabels, Variable,
|
||||||
};
|
};
|
||||||
use crate::types::{name_type_var, name_type_var_with_hint, AbilitySet, RecordField, Uls};
|
use crate::types::{
|
||||||
|
name_type_var, name_type_var_with_hint, AbilitySet, Polarity, RecordField, Uls,
|
||||||
|
};
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
|
|
@ -52,12 +54,14 @@ macro_rules! write_parens {
|
||||||
pub struct DebugPrint {
|
pub struct DebugPrint {
|
||||||
pub print_lambda_sets: bool,
|
pub print_lambda_sets: bool,
|
||||||
pub print_only_under_alias: bool,
|
pub print_only_under_alias: bool,
|
||||||
|
pub ignore_polarity: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugPrint {
|
impl DebugPrint {
|
||||||
pub const NOTHING: DebugPrint = DebugPrint {
|
pub const NOTHING: DebugPrint = DebugPrint {
|
||||||
print_lambda_sets: false,
|
print_lambda_sets: false,
|
||||||
print_only_under_alias: false,
|
print_only_under_alias: false,
|
||||||
|
ignore_polarity: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -552,6 +556,7 @@ fn content_to_string(
|
||||||
interns: &Interns,
|
interns: &Interns,
|
||||||
named_result: NamedResult,
|
named_result: NamedResult,
|
||||||
debug_print: DebugPrint,
|
debug_print: DebugPrint,
|
||||||
|
pol: Polarity,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let env = Env {
|
let env = Env {
|
||||||
|
|
@ -564,7 +569,15 @@ fn content_to_string(
|
||||||
recursion_structs_to_expand: named_result.recursion_structs_to_expand,
|
recursion_structs_to_expand: named_result.recursion_structs_to_expand,
|
||||||
};
|
};
|
||||||
|
|
||||||
write_content(&env, &mut ctx, content, subs, &mut buf, Parens::Unnecessary);
|
write_content(
|
||||||
|
&env,
|
||||||
|
&mut ctx,
|
||||||
|
content,
|
||||||
|
subs,
|
||||||
|
&mut buf,
|
||||||
|
Parens::Unnecessary,
|
||||||
|
pol,
|
||||||
|
);
|
||||||
|
|
||||||
ctx.able_variables.sort();
|
ctx.able_variables.sort();
|
||||||
ctx.able_variables.dedup();
|
ctx.able_variables.dedup();
|
||||||
|
|
@ -593,7 +606,15 @@ pub fn name_and_print_var(
|
||||||
) -> String {
|
) -> String {
|
||||||
let named_result = name_all_type_vars(var, subs, debug_print.print_only_under_alias);
|
let named_result = name_all_type_vars(var, subs, debug_print.print_only_under_alias);
|
||||||
let content = subs.get_content_without_compacting(var);
|
let content = subs.get_content_without_compacting(var);
|
||||||
content_to_string(content, subs, home, interns, named_result, debug_print)
|
content_to_string(
|
||||||
|
content,
|
||||||
|
subs,
|
||||||
|
home,
|
||||||
|
interns,
|
||||||
|
named_result,
|
||||||
|
debug_print,
|
||||||
|
Polarity::Pos,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_single_arg<'a>(subs: &'a Subs, args: &'a AliasVariables) -> &'a Content {
|
pub fn get_single_arg<'a>(subs: &'a Subs, args: &'a AliasVariables) -> &'a Content {
|
||||||
|
|
@ -614,6 +635,7 @@ fn write_content<'a>(
|
||||||
subs: &'a Subs,
|
subs: &'a Subs,
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
use crate::subs::Content::*;
|
use crate::subs::Content::*;
|
||||||
|
|
||||||
|
|
@ -660,6 +682,7 @@ fn write_content<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let name = &subs.field_names[name_index.index as usize];
|
let name = &subs.field_names[name_index.index as usize];
|
||||||
|
|
@ -670,7 +693,7 @@ fn write_content<'a>(
|
||||||
unreachable!("This should always be filled in!")
|
unreachable!("This should always be filled in!")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Structure(flat_type) => write_flat_type(env, ctx, flat_type, subs, buf, parens),
|
Structure(flat_type) => write_flat_type(env, ctx, flat_type, subs, buf, parens, pol),
|
||||||
Alias(symbol, args, actual, _kind) => {
|
Alias(symbol, args, actual, _kind) => {
|
||||||
let write_parens = parens == Parens::InTypeParam && !args.is_empty();
|
let write_parens = parens == Parens::InTypeParam && !args.is_empty();
|
||||||
|
|
||||||
|
|
@ -688,6 +711,7 @@ fn write_content<'a>(
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
write_parens,
|
write_parens,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Symbol::NUM_FLOATINGPOINT => write_float(
|
Symbol::NUM_FLOATINGPOINT => write_float(
|
||||||
|
|
@ -698,17 +722,18 @@ fn write_content<'a>(
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
write_parens,
|
write_parens,
|
||||||
|
pol,
|
||||||
),
|
),
|
||||||
|
|
||||||
_ => write_parens!(write_parens, buf, {
|
_ => write_parens!(write_parens, buf, {
|
||||||
buf.push_str("Num ");
|
buf.push_str("Num ");
|
||||||
write_content(env, ctx, content, subs, buf, parens);
|
write_content(env, ctx, content, subs, buf, parens, pol);
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => write_parens!(write_parens, buf, {
|
_ => write_parens!(write_parens, buf, {
|
||||||
buf.push_str("Num ");
|
buf.push_str("Num ");
|
||||||
write_content(env, ctx, content, subs, buf, parens);
|
write_content(env, ctx, content, subs, buf, parens, pol);
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -716,7 +741,7 @@ fn write_content<'a>(
|
||||||
Symbol::NUM_INT => {
|
Symbol::NUM_INT => {
|
||||||
let content = get_single_arg(subs, args);
|
let content = get_single_arg(subs, args);
|
||||||
|
|
||||||
write_integer(env, ctx, content, subs, buf, parens, write_parens)
|
write_integer(env, ctx, content, subs, buf, parens, write_parens, pol)
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol::NUM_FRAC => write_float(
|
Symbol::NUM_FRAC => write_float(
|
||||||
|
|
@ -727,11 +752,12 @@ fn write_content<'a>(
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
write_parens,
|
write_parens,
|
||||||
|
pol,
|
||||||
),
|
),
|
||||||
|
|
||||||
_ if env.debug.print_only_under_alias => write_parens!(write_parens, buf, {
|
_ if env.debug.print_only_under_alias => write_parens!(write_parens, buf, {
|
||||||
let content = subs.get_content_without_compacting(*actual);
|
let content = subs.get_content_without_compacting(*actual);
|
||||||
write_content(env, ctx, content, subs, buf, parens)
|
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
_ => write_parens!(write_parens, buf, {
|
_ => write_parens!(write_parens, buf, {
|
||||||
|
|
@ -747,13 +773,14 @@ fn write_content<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::InTypeParam,
|
Parens::InTypeParam,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
roc_debug_flags::dbg_do!(roc_debug_flags::ROC_PRETTY_PRINT_ALIAS_CONTENTS, {
|
roc_debug_flags::dbg_do!(roc_debug_flags::ROC_PRETTY_PRINT_ALIAS_CONTENTS, {
|
||||||
buf.push_str("[[ but really ");
|
buf.push_str("[[ but really ");
|
||||||
let content = subs.get_content_without_compacting(*actual);
|
let content = subs.get_content_without_compacting(*actual);
|
||||||
write_content(env, ctx, content, subs, buf, parens);
|
write_content(env, ctx, content, subs, buf, parens, pol);
|
||||||
buf.push_str("]]");
|
buf.push_str("]]");
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
@ -793,6 +820,7 @@ fn write_content<'a>(
|
||||||
buf,
|
buf,
|
||||||
solved.unsorted_lambdas(subs),
|
solved.unsorted_lambdas(subs),
|
||||||
print_symbol,
|
print_symbol,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
|
|
||||||
buf.push(']');
|
buf.push(']');
|
||||||
|
|
@ -806,6 +834,7 @@ fn write_content<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -818,6 +847,7 @@ fn write_content<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::Unnecessary,
|
Parens::Unnecessary,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
buf.push(':');
|
buf.push(':');
|
||||||
buf.push_str(&print_symbol(member));
|
buf.push_str(&print_symbol(member));
|
||||||
|
|
@ -840,6 +870,7 @@ fn write_content<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::Unnecessary,
|
Parens::Unnecessary,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
buf.push(')');
|
buf.push(')');
|
||||||
|
|
@ -856,6 +887,7 @@ fn write_float<'a>(
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
write_parens: bool,
|
write_parens: bool,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
use crate::subs::Content::*;
|
use crate::subs::Content::*;
|
||||||
match content {
|
match content {
|
||||||
|
|
@ -864,7 +896,7 @@ fn write_float<'a>(
|
||||||
Alias(Symbol::NUM_DECIMAL, _, _, _) => buf.push_str("Dec"),
|
Alias(Symbol::NUM_DECIMAL, _, _, _) => buf.push_str("Dec"),
|
||||||
_ => write_parens!(write_parens, buf, {
|
_ => write_parens!(write_parens, buf, {
|
||||||
buf.push_str("Float ");
|
buf.push_str("Float ");
|
||||||
write_content(env, ctx, content, subs, buf, parens);
|
write_content(env, ctx, content, subs, buf, parens, pol);
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -877,6 +909,7 @@ fn write_integer<'a>(
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
write_parens: bool,
|
write_parens: bool,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
use crate::subs::Content::*;
|
use crate::subs::Content::*;
|
||||||
|
|
||||||
|
|
@ -894,7 +927,7 @@ fn write_integer<'a>(
|
||||||
buf,
|
buf,
|
||||||
{
|
{
|
||||||
buf.push_str("Int ");
|
buf.push_str("Int ");
|
||||||
write_content(env, ctx, actual, subs, buf, parens);
|
write_content(env, ctx, actual, subs, buf, parens, pol);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -923,12 +956,20 @@ enum ExtContent<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExtContent<'a> {
|
impl<'a> ExtContent<'a> {
|
||||||
fn from_var(subs: &'a Subs, ext: Variable) -> Self {
|
fn for_tag(subs: &'a Subs, ext: Variable, pol: Polarity, debug_flags: &DebugPrint) -> Self {
|
||||||
let content = subs.get_content_without_compacting(ext);
|
let content = subs.get_content_without_compacting(ext);
|
||||||
match content {
|
match content {
|
||||||
Content::Structure(FlatType::EmptyTagUnion) => ExtContent::Empty,
|
Content::Structure(FlatType::EmptyTagUnion) => ExtContent::Empty,
|
||||||
Content::Structure(FlatType::EmptyRecord) => ExtContent::Empty,
|
Content::Structure(FlatType::EmptyRecord) => ExtContent::Empty,
|
||||||
|
|
||||||
|
Content::FlexVar(None) | Content::FlexAbleVar(None, _)
|
||||||
|
if pol.is_pos() && !debug_flags.ignore_polarity =>
|
||||||
|
{
|
||||||
|
// This is a wildcard `[...]*`, which is elided in positive positions!
|
||||||
|
ExtContent::Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other vars are named, and must appear regardless of their position.
|
||||||
Content::FlexVar(_)
|
Content::FlexVar(_)
|
||||||
| Content::FlexAbleVar(..)
|
| Content::FlexAbleVar(..)
|
||||||
| Content::RigidVar(_)
|
| Content::RigidVar(_)
|
||||||
|
|
@ -946,6 +987,7 @@ fn write_ext_content<'a>(
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
ext_content: ExtContent<'a>,
|
ext_content: ExtContent<'a>,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
if let ExtContent::Content(_, content) = ext_content {
|
if let ExtContent::Content(_, content) = ext_content {
|
||||||
// This is an open record or tag union, so print the variable
|
// This is an open record or tag union, so print the variable
|
||||||
|
|
@ -953,7 +995,7 @@ fn write_ext_content<'a>(
|
||||||
//
|
//
|
||||||
// e.g. the "*" at the end of `{ x: I64 }*`
|
// e.g. the "*" at the end of `{ x: I64 }*`
|
||||||
// or the "r" at the end of `{ x: I64 }r`
|
// or the "r" at the end of `{ x: I64 }r`
|
||||||
write_content(env, ctx, content, subs, buf, parens)
|
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -964,6 +1006,7 @@ fn write_sorted_tags2<'a, L>(
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
tags: UnsortedUnionLabels<L>,
|
tags: UnsortedUnionLabels<L>,
|
||||||
label_to_string: impl Fn(&L) -> String,
|
label_to_string: impl Fn(&L) -> String,
|
||||||
|
pol: Polarity,
|
||||||
) where
|
) where
|
||||||
L: Label + Ord,
|
L: Label + Ord,
|
||||||
{
|
{
|
||||||
|
|
@ -991,6 +1034,7 @@ fn write_sorted_tags2<'a, L>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::InTypeParam,
|
Parens::InTypeParam,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1003,6 +1047,7 @@ fn write_sorted_tags<'a>(
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
tags: &MutMap<TagName, Vec<Variable>>,
|
tags: &MutMap<TagName, Vec<Variable>>,
|
||||||
ext_var: Variable,
|
ext_var: Variable,
|
||||||
|
pol: Polarity,
|
||||||
) -> ExtContent<'a> {
|
) -> ExtContent<'a> {
|
||||||
// Sort the fields so they always end up in the same order.
|
// Sort the fields so they always end up in the same order.
|
||||||
let mut sorted_fields = Vec::with_capacity(tags.len());
|
let mut sorted_fields = Vec::with_capacity(tags.len());
|
||||||
|
|
@ -1042,11 +1087,12 @@ fn write_sorted_tags<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::InTypeParam,
|
Parens::InTypeParam,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtContent::from_var(subs, ext_var)
|
ExtContent::for_tag(subs, ext_var, pol, &env.debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_flat_type<'a>(
|
fn write_flat_type<'a>(
|
||||||
|
|
@ -1056,6 +1102,7 @@ fn write_flat_type<'a>(
|
||||||
subs: &'a Subs,
|
subs: &'a Subs,
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
use crate::subs::FlatType::*;
|
use crate::subs::FlatType::*;
|
||||||
|
|
||||||
|
|
@ -1068,6 +1115,7 @@ fn write_flat_type<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
),
|
),
|
||||||
EmptyRecord => buf.push_str(EMPTY_RECORD),
|
EmptyRecord => buf.push_str(EMPTY_RECORD),
|
||||||
EmptyTagUnion => buf.push_str(EMPTY_TAG_UNION),
|
EmptyTagUnion => buf.push_str(EMPTY_TAG_UNION),
|
||||||
|
|
@ -1080,6 +1128,7 @@ fn write_flat_type<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
),
|
),
|
||||||
Record(fields, ext_var) => {
|
Record(fields, ext_var) => {
|
||||||
use crate::types::{gather_fields, RecordStructure};
|
use crate::types::{gather_fields, RecordStructure};
|
||||||
|
|
@ -1123,6 +1172,7 @@ fn write_flat_type<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::Unnecessary,
|
Parens::Unnecessary,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1139,7 +1189,7 @@ fn write_flat_type<'a>(
|
||||||
//
|
//
|
||||||
// e.g. the "*" at the end of `{ x: I64 }*`
|
// e.g. the "*" at the end of `{ x: I64 }*`
|
||||||
// or the "r" at the end of `{ x: I64 }r`
|
// or the "r" at the end of `{ x: I64 }r`
|
||||||
write_content(env, ctx, content, subs, buf, parens)
|
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1148,7 +1198,15 @@ fn write_flat_type<'a>(
|
||||||
|
|
||||||
// Sort the fields so they always end up in the same order.
|
// Sort the fields so they always end up in the same order.
|
||||||
let (tags, new_ext_var) = tags.unsorted_tags_and_ext(subs, *ext_var);
|
let (tags, new_ext_var) = tags.unsorted_tags_and_ext(subs, *ext_var);
|
||||||
write_sorted_tags2(env, ctx, subs, buf, tags, |tag| tag.0.as_str().to_string());
|
write_sorted_tags2(
|
||||||
|
env,
|
||||||
|
ctx,
|
||||||
|
subs,
|
||||||
|
buf,
|
||||||
|
tags,
|
||||||
|
|tag| tag.0.as_str().to_string(),
|
||||||
|
pol,
|
||||||
|
);
|
||||||
|
|
||||||
buf.push(']');
|
buf.push(']');
|
||||||
|
|
||||||
|
|
@ -1157,8 +1215,9 @@ fn write_flat_type<'a>(
|
||||||
ctx,
|
ctx,
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
ExtContent::from_var(subs, new_ext_var),
|
ExtContent::for_tag(subs, new_ext_var, pol, &env.debug),
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1171,11 +1230,11 @@ fn write_flat_type<'a>(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|t| (t.clone(), vec![])),
|
.map(|t| (t.clone(), vec![])),
|
||||||
);
|
);
|
||||||
let ext_content = write_sorted_tags(env, ctx, subs, buf, &tags, *ext_var);
|
let ext_content = write_sorted_tags(env, ctx, subs, buf, &tags, *ext_var, pol);
|
||||||
|
|
||||||
buf.push(']');
|
buf.push(']');
|
||||||
|
|
||||||
write_ext_content(env, ctx, subs, buf, ext_content, parens)
|
write_ext_content(env, ctx, subs, buf, ext_content, parens, pol)
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
|
|
@ -1183,7 +1242,15 @@ fn write_flat_type<'a>(
|
||||||
buf.push('[');
|
buf.push('[');
|
||||||
|
|
||||||
let (tags, new_ext_var) = tags.unsorted_tags_and_ext(subs, *ext_var);
|
let (tags, new_ext_var) = tags.unsorted_tags_and_ext(subs, *ext_var);
|
||||||
write_sorted_tags2(env, ctx, subs, buf, tags, |tag| tag.0.as_str().to_string());
|
write_sorted_tags2(
|
||||||
|
env,
|
||||||
|
ctx,
|
||||||
|
subs,
|
||||||
|
buf,
|
||||||
|
tags,
|
||||||
|
|tag| tag.0.as_str().to_string(),
|
||||||
|
pol,
|
||||||
|
);
|
||||||
|
|
||||||
buf.push(']');
|
buf.push(']');
|
||||||
|
|
||||||
|
|
@ -1192,8 +1259,9 @@ fn write_flat_type<'a>(
|
||||||
ctx,
|
ctx,
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
ExtContent::from_var(subs, new_ext_var),
|
ExtContent::for_tag(subs, new_ext_var, pol, &env.debug),
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
|
|
||||||
buf.push_str(" as ");
|
buf.push_str(" as ");
|
||||||
|
|
@ -1204,6 +1272,7 @@ fn write_flat_type<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1278,6 +1347,7 @@ fn write_apply<'a>(
|
||||||
subs: &'a Subs,
|
subs: &'a Subs,
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
let write_parens = parens == Parens::InTypeParam && !args.is_empty();
|
let write_parens = parens == Parens::InTypeParam && !args.is_empty();
|
||||||
|
|
||||||
|
|
@ -1299,7 +1369,15 @@ fn write_apply<'a>(
|
||||||
buf.push('(');
|
buf.push('(');
|
||||||
}
|
}
|
||||||
|
|
||||||
write_content(env, ctx, content, subs, &mut arg_param, Parens::InTypeParam);
|
write_content(
|
||||||
|
env,
|
||||||
|
ctx,
|
||||||
|
content,
|
||||||
|
subs,
|
||||||
|
&mut arg_param,
|
||||||
|
Parens::InTypeParam,
|
||||||
|
pol,
|
||||||
|
);
|
||||||
buf.push_str("Num ");
|
buf.push_str("Num ");
|
||||||
buf.push_str(&arg_param);
|
buf.push_str(&arg_param);
|
||||||
|
|
||||||
|
|
@ -1337,6 +1415,7 @@ fn write_apply<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::InTypeParam,
|
Parens::InTypeParam,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1357,6 +1436,7 @@ fn write_fn<'a>(
|
||||||
subs: &'a Subs,
|
subs: &'a Subs,
|
||||||
buf: &mut String,
|
buf: &mut String,
|
||||||
parens: Parens,
|
parens: Parens,
|
||||||
|
pol: Polarity,
|
||||||
) {
|
) {
|
||||||
let mut needs_comma = false;
|
let mut needs_comma = false;
|
||||||
let use_parens = parens != Parens::Unnecessary;
|
let use_parens = parens != Parens::Unnecessary;
|
||||||
|
|
@ -1379,6 +1459,7 @@ fn write_fn<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::InFn,
|
Parens::InFn,
|
||||||
|
Polarity::Neg,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1393,6 +1474,7 @@ fn write_fn<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
parens,
|
parens,
|
||||||
|
pol,
|
||||||
);
|
);
|
||||||
buf.push_str("-> ");
|
buf.push_str("-> ");
|
||||||
}
|
}
|
||||||
|
|
@ -1404,6 +1486,7 @@ fn write_fn<'a>(
|
||||||
subs,
|
subs,
|
||||||
buf,
|
buf,
|
||||||
Parens::InFn,
|
Parens::InFn,
|
||||||
|
Polarity::Pos,
|
||||||
);
|
);
|
||||||
|
|
||||||
if use_parens {
|
if use_parens {
|
||||||
|
|
|
||||||
|
|
@ -333,6 +333,36 @@ impl OptAbleType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Polarity of a type, or roughly, what side of an arrow it appears on.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Polarity {
|
||||||
|
/// A type that appears in negative/input position
|
||||||
|
Neg,
|
||||||
|
/// A type that appears in positive/output position
|
||||||
|
Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Neg for Polarity {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Polarity::Neg => todo!(),
|
||||||
|
Polarity::Pos => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Polarity {
|
||||||
|
pub fn is_neg(&self) -> bool {
|
||||||
|
matches!(self, Self::Neg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_pos(&self) -> bool {
|
||||||
|
matches!(self, Self::Pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
EmptyRec,
|
EmptyRec,
|
||||||
|
|
|
||||||
|
|
@ -144,26 +144,26 @@ fn bool_false() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arbitrary_tag_unions() {
|
fn arbitrary_tag_unions() {
|
||||||
expect_success("if 1 == 1 then Red else Green", "Red : [Green, Red]*");
|
expect_success("if 1 == 1 then Red else Green", "Red : [Green, Red]");
|
||||||
expect_success("if 1 != 1 then Red else Green", "Green : [Green, Red]*");
|
expect_success("if 1 != 1 then Red else Green", "Green : [Green, Red]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tag_without_arguments() {
|
fn tag_without_arguments() {
|
||||||
expect_success("True", "True : [True]*");
|
expect_success("True", "True : [True]");
|
||||||
expect_success("False", "False : [False]*");
|
expect_success("False", "False : [False]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn byte_tag_union() {
|
fn byte_tag_union() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"if 1 == 1 then Red else if 1 == 1 then Green else Blue",
|
"if 1 == 1 then Red else if 1 == 1 then Green else Blue",
|
||||||
"Red : [Blue, Green, Red]*",
|
"Red : [Blue, Green, Red]",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ y: { x: if 1 == 1 then Red else if 1 == 1 then Green else Blue } }",
|
"{ y: { x: if 1 == 1 then Red else if 1 == 1 then Green else Blue } }",
|
||||||
"{ y: { x: Red } } : { y : { x : [Blue, Green, Red]* } }",
|
"{ y: { x: Red } } : { y : { x : [Blue, Green, Red] } }",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,24 +171,24 @@ fn byte_tag_union() {
|
||||||
fn tag_in_record() {
|
fn tag_in_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ x: Foo 1 2 3, y : 4 }",
|
"{ x: Foo 1 2 3, y : 4 }",
|
||||||
"{ x: Foo 1 2 3, y: 4 } : { x : [Foo (Num *) (Num *) (Num *)]*, y : Num * }",
|
"{ x: Foo 1 2 3, y: 4 } : { x : [Foo (Num *) (Num *) (Num *)], y : Num * }",
|
||||||
);
|
);
|
||||||
expect_success(
|
expect_success(
|
||||||
"{ x: Foo 1 2 3 }",
|
"{ x: Foo 1 2 3 }",
|
||||||
"{ x: Foo 1 2 3 } : { x : [Foo (Num *) (Num *) (Num *)]* }",
|
"{ x: Foo 1 2 3 } : { x : [Foo (Num *) (Num *) (Num *)] }",
|
||||||
);
|
);
|
||||||
expect_success("{ x: Unit }", "{ x: Unit } : { x : [Unit]* }");
|
expect_success("{ x: Unit }", "{ x: Unit } : { x : [Unit] }");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_element_tag_union() {
|
fn single_element_tag_union() {
|
||||||
expect_success("True 1", "True 1 : [True (Num *)]*");
|
expect_success("True 1", "True 1 : [True (Num *)]");
|
||||||
expect_success("Foo 1 3.14", "Foo 1 3.14 : [Foo (Num *) (Float *)]*");
|
expect_success("Foo 1 3.14", "Foo 1 3.14 : [Foo (Num *) (Float *)]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn newtype_of_unit() {
|
fn newtype_of_unit() {
|
||||||
expect_success("Foo Bar", "Foo Bar : [Foo [Bar]*]*");
|
expect_success("Foo Bar", "Foo Bar : [Foo [Bar]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -202,7 +202,7 @@ fn newtype_of_big_data() {
|
||||||
A lefty
|
A lefty
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
r#"A (Left "loosey") : [A (Either Str Str)]*"#,
|
r#"A (Left "loosey") : [A (Either Str Str)]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,7 +217,7 @@ fn newtype_nested() {
|
||||||
A (B (C lefty))
|
A (B (C lefty))
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
r#"A (B (C (Left "loosey"))) : [A [B [C (Either Str Str)]*]*]*"#,
|
r#"A (B (C (Left "loosey"))) : [A [B [C (Either Str Str)]]]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,17 +232,17 @@ fn newtype_of_big_of_newtype() {
|
||||||
A big
|
A big
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
r#"A (Big "s" (Wrapper (Newtype "t"))) : [A (Big Str)]*"#,
|
r#"A (Big "s" (Wrapper (Newtype "t"))) : [A (Big Str)]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tag_with_arguments() {
|
fn tag_with_arguments() {
|
||||||
expect_success("True 1", "True 1 : [True (Num *)]*");
|
expect_success("True 1", "True 1 : [True (Num *)]");
|
||||||
|
|
||||||
expect_success(
|
expect_success(
|
||||||
"if 1 == 1 then True 3 else False 3.14",
|
"if 1 == 1 then True 3 else False 3.14",
|
||||||
"True 3 : [False (Float *), True (Num *)]*",
|
"True 3 : [False (Float *), True (Num *)]",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -886,7 +886,7 @@ fn function_in_unwrapped_record() {
|
||||||
fn function_in_tag() {
|
fn function_in_tag() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"Adder (\x -> x + 1)"#,
|
r#"Adder (\x -> x + 1)"#,
|
||||||
r#"Adder <function> : [Adder (Num a -> Num a)]*"#,
|
r#"Adder <function> : [Adder (Num a -> Num a)]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -894,7 +894,7 @@ fn function_in_tag() {
|
||||||
fn newtype_of_record_of_tag_of_record_of_tag() {
|
fn newtype_of_record_of_tag_of_record_of_tag() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"A {b: C {d: 1}}"#,
|
r#"A {b: C {d: 1}}"#,
|
||||||
r#"A { b: C { d: 1 } } : [A { b : [C { d : Num * }]* }]*"#,
|
r#"A { b: C { d: 1 } } : [A { b : [C { d : Num * }] }]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1089,7 +1089,7 @@ fn opaque_pattern_and_call() {
|
||||||
f (@F (Package A {}))
|
f (@F (Package A {}))
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
r#"@F (Package {} A) : F {} [A]*"#,
|
r#"@F (Package {} A) : F {} [A]"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue