Fix ordinal index on pairs
This commit is contained in:
parent
2cb2c7fa1f
commit
7cb548a749
|
@ -2349,3 +2349,52 @@ fn partial_eq_callback_return() {
|
||||||
Err((_, Error::CouldNotUnify { .. }))
|
Err((_, Error::CouldNotUnify { .. }))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pair_access_on_call() {
|
||||||
|
let source_code = r#"
|
||||||
|
use aiken/builtin
|
||||||
|
|
||||||
|
pub fn list_at(xs: List<a>, index: Int) -> a {
|
||||||
|
if index == 0 {
|
||||||
|
builtin.head_list(xs)
|
||||||
|
} else {
|
||||||
|
list_at(builtin.tail_list(xs), index - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
[list_at([Pair(1, 2)], 0).2nd, ..[1, 2]]
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(check(parse(source_code)).is_ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pair_index_out_of_bound() {
|
||||||
|
let source_code = r#"
|
||||||
|
pub fn foo() {
|
||||||
|
Pair(1, 2).3rd
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
dbg!(check_validator(parse(source_code))),
|
||||||
|
Err((_, Error::PairIndexOutOfBound { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_indexable() {
|
||||||
|
let source_code = r#"
|
||||||
|
pub fn foo() {
|
||||||
|
"foo".1st
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
dbg!(check_validator(parse(source_code))),
|
||||||
|
Err((_, Error::NotIndexable { .. }))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -508,18 +508,16 @@ If you really meant to return that last expression, try to replace it with the f
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error(
|
#[error("I tripped over an attempt to access elements on something that isn't indexable.\n")]
|
||||||
"I tripped over an attempt to access tuple elements on something else than a tuple.\n"
|
|
||||||
)]
|
|
||||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||||
#[diagnostic(code("illegal::tuple_index"))]
|
#[diagnostic(code("illegal::indexable"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
r#"Because you used a tuple-index on an element, I assumed it had to be a tuple but instead I found something of type:
|
r#"Because you used an ordinal index on an element, I assumed it had to be a tuple or a pair but instead I found something of type:
|
||||||
|
|
||||||
╰─▶ {type_info}"#,
|
╰─▶ {type_info}"#,
|
||||||
type_info = tipo.to_pretty(0).if_supports_color(Stdout, |s| s.red())
|
type_info = tipo.to_pretty(0).if_supports_color(Stdout, |s| s.red())
|
||||||
))]
|
))]
|
||||||
NotATuple {
|
NotIndexable {
|
||||||
#[label]
|
#[label]
|
||||||
location: Span,
|
location: Span,
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
|
@ -675,12 +673,25 @@ You can help me by providing a type-annotation for 'x', as such:
|
||||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||||
#[diagnostic(code("invalid::tuple_index"))]
|
#[diagnostic(code("invalid::tuple_index"))]
|
||||||
TupleIndexOutOfBound {
|
TupleIndexOutOfBound {
|
||||||
#[label]
|
#[label("out of bounds")]
|
||||||
location: Span,
|
location: Span,
|
||||||
index: usize,
|
index: usize,
|
||||||
size: usize,
|
size: usize,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#[error(
|
||||||
|
"I discovered an attempt to access the {} element of a {}.\n",
|
||||||
|
Ordinal(*index + 1).to_string().if_supports_color(Stdout, |s| s.purple()),
|
||||||
|
"Pair".if_supports_color(Stdout, |s| s.bright_blue()).if_supports_color(Stdout, |s| s.bold()),
|
||||||
|
)]
|
||||||
|
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#pairs"))]
|
||||||
|
#[diagnostic(code("invalid::pair_index"))]
|
||||||
|
PairIndexOutOfBound {
|
||||||
|
#[label("out of bounds")]
|
||||||
|
location: Span,
|
||||||
|
index: usize,
|
||||||
|
},
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"I tripped over the following labeled argument: {}.\n",
|
"I tripped over the following labeled argument: {}.\n",
|
||||||
label.if_supports_color(Stdout, |s| s.purple())
|
label.if_supports_color(Stdout, |s| s.purple())
|
||||||
|
@ -1035,7 +1046,7 @@ impl ExtraData for Error {
|
||||||
| Error::MissingVarInAlternativePattern { .. }
|
| Error::MissingVarInAlternativePattern { .. }
|
||||||
| Error::MultiValidatorEqualArgs { .. }
|
| Error::MultiValidatorEqualArgs { .. }
|
||||||
| Error::NonLocalClauseGuardVariable { .. }
|
| Error::NonLocalClauseGuardVariable { .. }
|
||||||
| Error::NotATuple { .. }
|
| Error::NotIndexable { .. }
|
||||||
| Error::NotExhaustivePatternMatch { .. }
|
| Error::NotExhaustivePatternMatch { .. }
|
||||||
| Error::NotFn { .. }
|
| Error::NotFn { .. }
|
||||||
| Error::PositionalArgumentAfterLabeled { .. }
|
| Error::PositionalArgumentAfterLabeled { .. }
|
||||||
|
@ -1045,6 +1056,7 @@ impl ExtraData for Error {
|
||||||
| Error::RecursiveType { .. }
|
| Error::RecursiveType { .. }
|
||||||
| Error::RedundantMatchClause { .. }
|
| Error::RedundantMatchClause { .. }
|
||||||
| Error::TupleIndexOutOfBound { .. }
|
| Error::TupleIndexOutOfBound { .. }
|
||||||
|
| Error::PairIndexOutOfBound { .. }
|
||||||
| Error::UnexpectedLabeledArg { .. }
|
| Error::UnexpectedLabeledArg { .. }
|
||||||
| Error::UnexpectedLabeledArgInPattern { .. }
|
| Error::UnexpectedLabeledArgInPattern { .. }
|
||||||
| Error::UnknownLabels { .. }
|
| Error::UnknownLabels { .. }
|
||||||
|
|
|
@ -2065,13 +2065,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
|
|
||||||
fn infer_tuple_index(
|
fn infer_tuple_index(
|
||||||
&mut self,
|
&mut self,
|
||||||
tuple: UntypedExpr,
|
tuple_or_pair: UntypedExpr,
|
||||||
index: usize,
|
index: usize,
|
||||||
location: Span,
|
location: Span,
|
||||||
) -> Result<TypedExpr, Error> {
|
) -> Result<TypedExpr, Error> {
|
||||||
let tuple = self.infer(tuple)?;
|
let tuple_or_pair = self.infer(tuple_or_pair)?;
|
||||||
|
|
||||||
let tipo = match *collapse_links(tuple.tipo()) {
|
let tipo = match *collapse_links(tuple_or_pair.tipo()) {
|
||||||
Type::Tuple {
|
Type::Tuple {
|
||||||
ref elems,
|
ref elems,
|
||||||
alias: _,
|
alias: _,
|
||||||
|
@ -2087,9 +2087,22 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
Ok(elems[index].clone())
|
Ok(elems[index].clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(Error::NotATuple {
|
Type::Pair {
|
||||||
|
ref fst,
|
||||||
|
ref snd,
|
||||||
|
alias: _,
|
||||||
|
} => {
|
||||||
|
if index == 0 {
|
||||||
|
Ok(fst.clone())
|
||||||
|
} else if index == 1 {
|
||||||
|
Ok(snd.clone())
|
||||||
|
} else {
|
||||||
|
Err(Error::PairIndexOutOfBound { location, index })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(Error::NotIndexable {
|
||||||
location,
|
location,
|
||||||
tipo: tuple.tipo(),
|
tipo: tuple_or_pair.tipo(),
|
||||||
}),
|
}),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
@ -2097,7 +2110,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location,
|
location,
|
||||||
tipo,
|
tipo,
|
||||||
index,
|
index,
|
||||||
tuple: Box::new(tuple),
|
tuple: Box::new(tuple_or_pair),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2159,7 +2159,7 @@ fn acceptance_test_23_to_list() {
|
||||||
}
|
}
|
||||||
|
|
||||||
test to_list_2() {
|
test to_list_2() {
|
||||||
to_list(fixture_1()) == [Pair("foo", 42).2nd, Pair("bar", 14)]
|
to_list(fixture_1()) == [Pair("foo", 42), Pair("bar", 14)]
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue