Skip to content

Commit

Permalink
Fix ordinal index on pairs
Browse files Browse the repository at this point in the history
  • Loading branch information
KtorZ authored and MicroProofs committed Apr 27, 2024
1 parent 2d5e544 commit 2c30f2f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 22 deletions.
49 changes: 49 additions & 0 deletions crates/aiken-lang/src/tests/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2295,3 +2295,52 @@ fn tuple_access_on_call() {

assert!(check(parse(source_code)).is_ok())
}

#[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 { .. }))
))
}
28 changes: 20 additions & 8 deletions crates/aiken-lang/src/tipo/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -1035,7 +1046,7 @@ impl ExtraData for Error {
| Error::MissingVarInAlternativePattern { .. }
| Error::MultiValidatorEqualArgs { .. }
| Error::NonLocalClauseGuardVariable { .. }
| Error::NotATuple { .. }
| Error::NotIndexable { .. }
| Error::NotExhaustivePatternMatch { .. }
| Error::NotFn { .. }
| Error::PositionalArgumentAfterLabeled { .. }
Expand All @@ -1045,6 +1056,7 @@ impl ExtraData for Error {
| Error::RecursiveType { .. }
| Error::RedundantMatchClause { .. }
| Error::TupleIndexOutOfBound { .. }
| Error::PairIndexOutOfBound { .. }
| Error::UnexpectedLabeledArg { .. }
| Error::UnexpectedLabeledArgInPattern { .. }
| Error::UnknownLabels { .. }
Expand Down
25 changes: 19 additions & 6 deletions crates/aiken-lang/src/tipo/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: _,
Expand All @@ -2087,17 +2087,30 @@ 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(),
}),
}?;

Ok(TypedExpr::TupleIndex {
location,
tipo,
index,
tuple: Box::new(tuple),
tuple: Box::new(tuple_or_pair),
})
}

Expand Down
16 changes: 8 additions & 8 deletions crates/aiken-project/src/tests/gen_uplc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2118,27 +2118,27 @@ 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,
value v: value,
) -> 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 {
[] ->
Expand All @@ -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)]
}
"#;

Expand Down

0 comments on commit 2c30f2f

Please sign in to comment.