Parse destructured tag annotations as annotations rather than aliases

Closes #178
This commit is contained in:
ayazhafiz 2021-12-26 15:39:36 -06:00
parent fe62e59e31
commit b3ddfa7515
8 changed files with 192 additions and 34 deletions

View file

@ -265,6 +265,17 @@ pub enum Def<'a> {
NotYetImplemented(&'static str),
}
impl<'a> Def<'a> {
pub fn unroll_spaces_before(&self) -> (&'a [CommentOrNewline<'a>], &Def) {
let (spaces, def): (&'a [_], &Def) = match self {
Def::SpaceBefore(def, spaces) => (spaces, def),
def => (&[], def),
};
debug_assert!(!matches!(def, Def::SpaceBefore(_, _)));
(spaces, def)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TypeAnnotation<'a> {
/// A function. The types of its arguments, then the type of its return value.

View file

@ -571,27 +571,8 @@ fn append_body_definition<'a>(
if spaces.len() <= 1 {
let last = defs.pop();
match last {
Some(Loc {
value: Def::Annotation(ann_pattern, ann_type),
..
}) => {
return append_body_definition_help(
arena,
defs,
region,
&[],
spaces,
loc_pattern,
loc_def_body,
ann_pattern,
ann_type,
);
}
Some(Loc {
value: Def::SpaceBefore(Def::Annotation(ann_pattern, ann_type), before_ann_spaces),
..
}) => {
match last.map(|d| d.value.unroll_spaces_before()) {
Some((before_ann_spaces, Def::Annotation(ann_pattern, ann_type))) => {
return append_body_definition_help(
arena,
defs,
@ -604,6 +585,37 @@ fn append_body_definition<'a>(
ann_type,
);
}
Some((
before_ann_spaces,
Def::Alias {
name,
vars,
ann: ann_type,
},
)) => {
// This is a case like
// UserId x : [ UserId Int ]
// UserId x = UserId 42
// We optimistically parsed the first line as an alias; we now turn it
// into an annotation.
let loc_name = arena.alloc(name.map(|x| Pattern::GlobalTag(x)));
let ann_pattern = Pattern::Apply(loc_name, vars);
let vars_region = Region::across_all(vars.iter().map(|v| &v.region));
let region_ann_pattern = Region::span_across(&loc_name.region, &vars_region);
let loc_ann_pattern = Loc::at(region_ann_pattern, ann_pattern);
return append_body_definition_help(
arena,
defs,
region,
before_ann_spaces,
spaces,
loc_pattern,
loc_def_body,
arena.alloc(loc_ann_pattern),
ann_type,
);
}
_ => {
defs.extend(last);
}

View file

@ -0,0 +1,62 @@
Defs(
[
|L 1-1, C 0-34| AnnotatedBody {
ann_pattern: |L 0-0, C 0-8| RecordDestructure(
[
|L 0-0, C 2-3| Identifier(
"x",
),
|L 0-0, C 5-7| Identifier(
"y",
),
],
),
ann_type: |L 0-0, C 11-14| Apply(
"",
"Foo",
[],
),
comment: None,
body_pattern: |L 1-1, C 0-8| RecordDestructure(
[
|L 1-1, C 2-3| Identifier(
"x",
),
|L 1-1, C 5-6| Identifier(
"y",
),
],
),
body_expr: |L 1-1, C 11-34| Record(
[
|L 1-1, C 13-22| RequiredValue(
|L 1-1, C 13-14| "x",
[],
|L 1-1, C 17-22| Str(
PlainLine(
"foo",
),
),
),
|L 1-1, C 24-32| RequiredValue(
|L 1-1, C 24-25| "y",
[],
|L 1-1, C 28-32| Float(
"3.14",
),
),
],
),
},
],
|L 3-3, C 0-1| SpaceBefore(
Var {
module_name: "",
ident: "x",
},
[
Newline,
Newline,
],
),
)

View file

@ -0,0 +1,4 @@
{ x, y } : Foo
{ x, y } = { x : "foo", y : 3.14 }
x

View file

@ -0,0 +1,63 @@
Defs(
[
|L 1-1, C 0-20| AnnotatedBody {
ann_pattern: |L 0-0, C 0-8| Apply(
|L 0-0, C 0-6| GlobalTag(
"UserId",
),
[
|L 0-0, C 7-8| Identifier(
"x",
),
],
),
ann_type: |L 0-0, C 11-25| TagUnion {
ext: None,
tags: [
|L 0-0, C 13-23| Global {
name: |L 0-0, C 13-19| "UserId",
args: [
|L 0-0, C 20-23| Apply(
"",
"I64",
[],
),
],
},
],
},
comment: None,
body_pattern: |L 1-1, C 0-8| Apply(
|L 1-1, C 0-6| GlobalTag(
"UserId",
),
[
|L 1-1, C 7-8| Identifier(
"x",
),
],
),
body_expr: |L 1-1, C 11-20| Apply(
|L 1-1, C 11-17| GlobalTag(
"UserId",
),
[
|L 1-1, C 18-20| Num(
"42",
),
],
Space,
),
},
],
|L 3-3, C 0-1| SpaceBefore(
Var {
module_name: "",
ident: "x",
},
[
Newline,
Newline,
],
),
)

View file

@ -0,0 +1,4 @@
UserId x : [ UserId I64 ]
UserId x = UserId 42
x

View file

@ -110,6 +110,8 @@ mod test_parse {
fail/type_double_comma.expr,
pass/add_var_with_spaces.expr,
pass/add_with_spaces.expr,
pass/annotated_record_destructure.expr,
pass/annotated_tag_destructure.expr,
pass/apply_global_tag.expr,
pass/apply_parenthetical_global_tag_args.expr,
pass/apply_private_tag.expr,

View file

@ -2981,20 +2981,20 @@ mod solve_expr {
);
}
// #[test]
// fn let_tag_pattern_with_annotation() {
// infer_eq_without_problem(
// indoc!(
// r#"
// UserId x : [ UserId I64 ]
// UserId x = UserId 42
#[test]
fn let_tag_pattern_with_annotation() {
infer_eq_without_problem(
indoc!(
r#"
UserId x : [ UserId I64 ]
UserId x = UserId 42
// x
// "#
// ),
// "I64",
// );
// }
x
"#
),
"I64",
);
}
#[test]
fn typecheck_record_linked_list_map() {