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 { .. }))
|
||||
));
|
||||
}
|
||||
|
||||
#[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,
|
||||
},
|
||||
|
||||
#[error(
|
||||
"I tripped over an attempt to access tuple elements on something else than a tuple.\n"
|
||||
)]
|
||||
#[error("I tripped over an attempt to access elements on something that isn't indexable.\n")]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||
#[diagnostic(code("illegal::tuple_index"))]
|
||||
#[diagnostic(code("illegal::indexable"))]
|
||||
#[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 = tipo.to_pretty(0).if_supports_color(Stdout, |s| s.red())
|
||||
))]
|
||||
NotATuple {
|
||||
NotIndexable {
|
||||
#[label]
|
||||
location: Span,
|
||||
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(code("invalid::tuple_index"))]
|
||||
TupleIndexOutOfBound {
|
||||
#[label]
|
||||
#[label("out of bounds")]
|
||||
location: Span,
|
||||
index: 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(
|
||||
"I tripped over the following labeled argument: {}.\n",
|
||||
label.if_supports_color(Stdout, |s| s.purple())
|
||||
|
@ -1035,7 +1046,7 @@ impl ExtraData for Error {
|
|||
| Error::MissingVarInAlternativePattern { .. }
|
||||
| Error::MultiValidatorEqualArgs { .. }
|
||||
| Error::NonLocalClauseGuardVariable { .. }
|
||||
| Error::NotATuple { .. }
|
||||
| Error::NotIndexable { .. }
|
||||
| Error::NotExhaustivePatternMatch { .. }
|
||||
| Error::NotFn { .. }
|
||||
| Error::PositionalArgumentAfterLabeled { .. }
|
||||
|
@ -1045,6 +1056,7 @@ impl ExtraData for Error {
|
|||
| Error::RecursiveType { .. }
|
||||
| Error::RedundantMatchClause { .. }
|
||||
| Error::TupleIndexOutOfBound { .. }
|
||||
| Error::PairIndexOutOfBound { .. }
|
||||
| Error::UnexpectedLabeledArg { .. }
|
||||
| Error::UnexpectedLabeledArgInPattern { .. }
|
||||
| Error::UnknownLabels { .. }
|
||||
|
|
|
@ -2065,13 +2065,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
|
||||
fn infer_tuple_index(
|
||||
&mut self,
|
||||
tuple: UntypedExpr,
|
||||
tuple_or_pair: UntypedExpr,
|
||||
index: usize,
|
||||
location: Span,
|
||||
) -> 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 {
|
||||
ref elems,
|
||||
alias: _,
|
||||
|
@ -2087,9 +2087,22 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
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,
|
||||
tipo: tuple.tipo(),
|
||||
tipo: tuple_or_pair.tipo(),
|
||||
}),
|
||||
}?;
|
||||
|
||||
|
@ -2097,7 +2110,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
location,
|
||||
tipo,
|
||||
index,
|
||||
tuple: Box::new(tuple),
|
||||
tuple: Box::new(tuple_or_pair),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -2118,19 +2118,19 @@ fn acceptance_test_23_to_list() {
|
|||
let src = r#"
|
||||
pub type Map<key, value> =
|
||||
List<Pair<key, value>>
|
||||
|
||||
|
||||
pub opaque type AssocList<key, value> {
|
||||
inner: Map<key, value>,
|
||||
}
|
||||
|
||||
|
||||
pub fn new() -> AssocList<key, value> {
|
||||
AssocList { inner: [] }
|
||||
}
|
||||
|
||||
|
||||
pub fn to_list(m: AssocList<key, value>) -> Map<key, value> {
|
||||
m.inner
|
||||
}
|
||||
|
||||
|
||||
pub fn insert(
|
||||
in m: AssocList<key, value>,
|
||||
key k: key,
|
||||
|
@ -2138,7 +2138,7 @@ fn acceptance_test_23_to_list() {
|
|||
) -> AssocList<key, value> {
|
||||
AssocList { inner: do_insert(m.inner, k, v) }
|
||||
}
|
||||
|
||||
|
||||
fn do_insert(elems: Map<key, value>, k: key, v: value) -> Map<key, value> {
|
||||
when elems is {
|
||||
[] ->
|
||||
|
@ -2151,15 +2151,15 @@ fn acceptance_test_23_to_list() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn fixture_1() {
|
||||
new()
|
||||
|> insert("foo", 42)
|
||||
|> insert("bar", 14)
|
||||
}
|
||||
|
||||
|
||||
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