Few more places in codegen where we need to be able to deal with Pair records
This commit is contained in:
parent
26f68c2fb4
commit
3c332ca42a
|
@ -659,6 +659,12 @@ impl<'a> CodeGenerator<'a> {
|
|||
} => {
|
||||
if check_replaceable_opaque_type(&record.tipo(), &self.data_types) {
|
||||
self.build(record, module_build_name, &[])
|
||||
} else if record.tipo().is_pair() {
|
||||
AirTree::pair_index(
|
||||
*index,
|
||||
tipo.clone(),
|
||||
self.build(record, module_build_name, &[]),
|
||||
)
|
||||
} else {
|
||||
let function_name = format!("__access_index_{}", *index);
|
||||
|
||||
|
@ -708,9 +714,22 @@ impl<'a> CodeGenerator<'a> {
|
|||
field_map,
|
||||
..
|
||||
} => {
|
||||
let val_constructor = if tipo.is_pair() {
|
||||
ValueConstructor::public(
|
||||
tipo.clone(),
|
||||
ValueConstructorVariant::Record {
|
||||
module: "".into(),
|
||||
name: name.clone(),
|
||||
field_map: field_map.clone(),
|
||||
arity: 2,
|
||||
location: Span::empty(),
|
||||
constructors_count: 1,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo);
|
||||
|
||||
let val_constructor = ValueConstructor::public(
|
||||
ValueConstructor::public(
|
||||
tipo.clone(),
|
||||
ValueConstructorVariant::Record {
|
||||
name: name.clone(),
|
||||
|
@ -724,7 +743,8 @@ impl<'a> CodeGenerator<'a> {
|
|||
.len()
|
||||
as u16,
|
||||
},
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
AirTree::var(val_constructor, name, "")
|
||||
}
|
||||
|
@ -772,13 +792,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
TypedExpr::TupleIndex {
|
||||
index, tuple, tipo, ..
|
||||
} => {
|
||||
if tuple.tipo().is_pair() {
|
||||
AirTree::pair_index(
|
||||
*index,
|
||||
tipo.clone(),
|
||||
self.build(tuple, module_build_name, &[]),
|
||||
)
|
||||
} else {
|
||||
let function_name = format!("__access_index_{}", *index);
|
||||
|
||||
if self.code_gen_functions.get(&function_name).is_none() {
|
||||
|
@ -809,13 +822,45 @@ impl<'a> CodeGenerator<'a> {
|
|||
self.build(tuple, module_build_name, &[]),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TypedExpr::ErrorTerm { tipo, .. } => AirTree::error(tipo.clone(), false),
|
||||
|
||||
TypedExpr::RecordUpdate {
|
||||
tipo, spread, args, ..
|
||||
} => {
|
||||
if tipo.is_pair() {
|
||||
assert!(args.len() == 1);
|
||||
|
||||
let Some(arg) = args.first() else {
|
||||
unreachable!("Pair update with no arguments")
|
||||
};
|
||||
|
||||
let arg_val = self.build(&arg.value, module_build_name, &[]);
|
||||
|
||||
let other_pair = self.build(spread, module_build_name, &[]);
|
||||
|
||||
if arg.index == 0 {
|
||||
AirTree::pair(
|
||||
arg_val,
|
||||
AirTree::pair_index(
|
||||
1,
|
||||
tipo.get_inner_types()[1].clone(),
|
||||
other_pair,
|
||||
),
|
||||
tipo.clone(),
|
||||
)
|
||||
} else {
|
||||
AirTree::pair(
|
||||
AirTree::pair_index(
|
||||
0,
|
||||
tipo.get_inner_types()[0].clone(),
|
||||
other_pair,
|
||||
),
|
||||
arg_val,
|
||||
tipo.clone(),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let mut index_types = vec![];
|
||||
let mut update_args = vec![];
|
||||
|
||||
|
@ -843,6 +888,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
update_args,
|
||||
)
|
||||
}
|
||||
}
|
||||
TypedExpr::UnOp { value, op, .. } => {
|
||||
AirTree::unop(*op, self.build(value, module_build_name, &[]))
|
||||
}
|
||||
|
@ -4195,6 +4241,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
ValueConstructorVariant::Record {
|
||||
name: constr_name, ..
|
||||
} => {
|
||||
// TODO handle pair
|
||||
if constructor.tipo.is_bool() {
|
||||
Some(Term::bool(constr_name == "True"))
|
||||
} else if constructor.tipo.is_void() {
|
||||
|
|
|
@ -937,7 +937,7 @@ impl AirTree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pair_index(index: usize, tipo: Rc<Type>, tuple: AirTree) -> AirTree {
|
||||
pub fn pair_index(index: u64, tipo: Rc<Type>, tuple: AirTree) -> AirTree {
|
||||
AirTree::cast_from_data(
|
||||
AirTree::builtin(
|
||||
if index == 0 {
|
||||
|
|
|
@ -2994,7 +2994,238 @@ fn acceptance_test_28_unique_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn acceptance_test_29_union() {
|
||||
fn acceptance_test_29_union_pair() {
|
||||
let src = r#"
|
||||
type Map<a,b> = List<Pair<a,b>>
|
||||
|
||||
pub opaque type AssocList<key, value> {
|
||||
inner: Map<key, value>,
|
||||
}
|
||||
|
||||
pub fn new() -> AssocList<key, value> {
|
||||
AssocList { inner: [] }
|
||||
}
|
||||
|
||||
pub fn from_list(xs: Map<key, value>) -> AssocList<key, value> {
|
||||
AssocList { inner: do_from_list(xs) }
|
||||
}
|
||||
|
||||
fn do_from_list(xs: Map<key, value>) -> Map<key, value> {
|
||||
when xs is {
|
||||
[] ->
|
||||
[]
|
||||
[Pair(k, v), ..rest] ->
|
||||
do_insert(do_from_list(rest), k, v)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
[] ->
|
||||
[Pair(k, v)]
|
||||
[Pair(k2, v2), ..rest] ->
|
||||
if k == k2 {
|
||||
[Pair(k, v), ..rest]
|
||||
} else {
|
||||
[Pair(k2, v2), ..do_insert(rest, k, v)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn union(
|
||||
left: AssocList<key, value>,
|
||||
right: AssocList<key, value>,
|
||||
) -> AssocList<key, value> {
|
||||
AssocList { inner: do_union(left.inner, right.inner) }
|
||||
}
|
||||
|
||||
fn do_union(
|
||||
left: Map<key, value>,
|
||||
right: Map<key, value>,
|
||||
) -> Map<key, value> {
|
||||
when left is {
|
||||
[] ->
|
||||
right
|
||||
[Pair{fst: k, snd: v}, ..rest] ->
|
||||
do_union(rest, do_insert(right, k, v))
|
||||
}
|
||||
}
|
||||
|
||||
fn fixture_1() {
|
||||
new()
|
||||
|> insert("foo", 42)
|
||||
|> insert("bar", 14)
|
||||
}
|
||||
|
||||
test union_1() {
|
||||
union(fixture_1(), new()) == fixture_1()
|
||||
}
|
||||
|
||||
"#;
|
||||
|
||||
assert_uplc(
|
||||
src,
|
||||
Term::equals_data()
|
||||
.apply(
|
||||
Term::map_data().apply(
|
||||
Term::var("union")
|
||||
.lambda("union")
|
||||
.apply(
|
||||
Term::var("do_union")
|
||||
.apply(Term::var("left"))
|
||||
.apply(Term::var("right"))
|
||||
.lambda("right")
|
||||
.lambda("left"),
|
||||
)
|
||||
.lambda("do_union")
|
||||
.apply(Term::var("do_union").apply(Term::var("do_union")))
|
||||
.lambda("do_union")
|
||||
.apply(
|
||||
Term::var("left")
|
||||
.delayed_choose_list(
|
||||
Term::var("right"),
|
||||
Term::var("do_union")
|
||||
.apply(Term::var("do_union"))
|
||||
.apply(Term::var("rest"))
|
||||
.apply(
|
||||
Term::var("do_insert")
|
||||
.apply(Term::var("right"))
|
||||
.apply(Term::var("k"))
|
||||
.apply(Term::var("v")),
|
||||
)
|
||||
.lambda("v")
|
||||
.apply(
|
||||
Term::un_i_data()
|
||||
.apply(Term::snd_pair().apply(Term::var("pair"))),
|
||||
)
|
||||
.lambda("k")
|
||||
.apply(
|
||||
Term::un_b_data()
|
||||
.apply(Term::fst_pair().apply(Term::var("pair"))),
|
||||
)
|
||||
.lambda("rest")
|
||||
.apply(Term::tail_list().apply(Term::var("left")))
|
||||
.lambda("pair")
|
||||
.apply(Term::head_list().apply(Term::var("left"))),
|
||||
)
|
||||
.lambda("right")
|
||||
.lambda("left")
|
||||
.lambda("do_union"),
|
||||
)
|
||||
.lambda("do_insert")
|
||||
.apply(
|
||||
Term::var("do_insert")
|
||||
.apply(Term::var("do_insert"))
|
||||
.apply(Term::var("elems"))
|
||||
.lambda("do_insert")
|
||||
.apply(
|
||||
Term::var("elems")
|
||||
.delayed_choose_list(
|
||||
Term::mk_cons()
|
||||
.apply(
|
||||
Term::mk_pair_data()
|
||||
.apply(Term::b_data().apply(Term::var("k")))
|
||||
.apply(
|
||||
Term::i_data().apply(Term::var("v")),
|
||||
),
|
||||
)
|
||||
.apply(Term::empty_map()),
|
||||
Term::equals_bytestring()
|
||||
.apply(Term::var("k"))
|
||||
.apply(Term::var("k2"))
|
||||
.delayed_if_then_else(
|
||||
Term::mk_cons()
|
||||
.apply(
|
||||
Term::mk_pair_data()
|
||||
.apply(
|
||||
Term::b_data()
|
||||
.apply(Term::var("k")),
|
||||
)
|
||||
.apply(
|
||||
Term::i_data()
|
||||
.apply(Term::var("v")),
|
||||
),
|
||||
)
|
||||
.apply(Term::var("rest")),
|
||||
Term::mk_cons()
|
||||
.apply(
|
||||
Term::mk_pair_data()
|
||||
.apply(
|
||||
Term::b_data()
|
||||
.apply(Term::var("k2")),
|
||||
)
|
||||
.apply(
|
||||
Term::i_data()
|
||||
.apply(Term::var("v2")),
|
||||
),
|
||||
)
|
||||
.apply(
|
||||
Term::var("do_insert")
|
||||
.apply(Term::var("do_insert"))
|
||||
.apply(Term::var("rest")),
|
||||
),
|
||||
)
|
||||
.lambda("v2")
|
||||
.apply(Term::un_i_data().apply(
|
||||
Term::snd_pair().apply(Term::var("pair")),
|
||||
))
|
||||
.lambda("k2")
|
||||
.apply(Term::un_b_data().apply(
|
||||
Term::fst_pair().apply(Term::var("pair")),
|
||||
))
|
||||
.lambda("rest")
|
||||
.apply(Term::tail_list().apply(Term::var("elems")))
|
||||
.lambda("pair")
|
||||
.apply(Term::head_list().apply(Term::var("elems"))),
|
||||
)
|
||||
.lambda("elems")
|
||||
.lambda("do_insert"),
|
||||
)
|
||||
.lambda("v")
|
||||
.lambda("k")
|
||||
.lambda("elems"),
|
||||
)
|
||||
.apply(Term::map_values(vec![
|
||||
Constant::ProtoPair(
|
||||
Type::Data,
|
||||
Type::Data,
|
||||
Constant::Data(Data::bytestring("foo".as_bytes().to_vec())).into(),
|
||||
Constant::Data(Data::integer(42.into())).into(),
|
||||
),
|
||||
Constant::ProtoPair(
|
||||
Type::Data,
|
||||
Type::Data,
|
||||
Constant::Data(Data::bytestring("bar".as_bytes().to_vec())).into(),
|
||||
Constant::Data(Data::integer(14.into())).into(),
|
||||
),
|
||||
]))
|
||||
.apply(Term::empty_map()),
|
||||
),
|
||||
)
|
||||
.apply(Term::data(Data::map(vec![
|
||||
(
|
||||
Data::bytestring("foo".as_bytes().to_vec()),
|
||||
Data::integer(42.into()),
|
||||
),
|
||||
(
|
||||
Data::bytestring("bar".as_bytes().to_vec()),
|
||||
Data::integer(14.into()),
|
||||
),
|
||||
]))),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acceptance_test_29_union_tuple() {
|
||||
let src = r#"
|
||||
pub opaque type AssocList<key, value> {
|
||||
inner: List<(key, value)>,
|
||||
|
|
Loading…
Reference in New Issue