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) {
|
if check_replaceable_opaque_type(&record.tipo(), &self.data_types) {
|
||||||
self.build(record, module_build_name, &[])
|
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 {
|
} else {
|
||||||
let function_name = format!("__access_index_{}", *index);
|
let function_name = format!("__access_index_{}", *index);
|
||||||
|
|
||||||
|
@ -708,9 +714,22 @@ impl<'a> CodeGenerator<'a> {
|
||||||
field_map,
|
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 data_type = lookup_data_type_by_tipo(&self.data_types, tipo);
|
||||||
|
|
||||||
let val_constructor = ValueConstructor::public(
|
ValueConstructor::public(
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
ValueConstructorVariant::Record {
|
ValueConstructorVariant::Record {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
@ -724,7 +743,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.len()
|
.len()
|
||||||
as u16,
|
as u16,
|
||||||
},
|
},
|
||||||
);
|
)
|
||||||
|
};
|
||||||
|
|
||||||
AirTree::var(val_constructor, name, "")
|
AirTree::var(val_constructor, name, "")
|
||||||
}
|
}
|
||||||
|
@ -772,13 +792,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::TupleIndex {
|
TypedExpr::TupleIndex {
|
||||||
index, tuple, tipo, ..
|
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);
|
let function_name = format!("__access_index_{}", *index);
|
||||||
|
|
||||||
if self.code_gen_functions.get(&function_name).is_none() {
|
if self.code_gen_functions.get(&function_name).is_none() {
|
||||||
|
@ -809,13 +822,45 @@ impl<'a> CodeGenerator<'a> {
|
||||||
self.build(tuple, module_build_name, &[]),
|
self.build(tuple, module_build_name, &[]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TypedExpr::ErrorTerm { tipo, .. } => AirTree::error(tipo.clone(), false),
|
TypedExpr::ErrorTerm { tipo, .. } => AirTree::error(tipo.clone(), false),
|
||||||
|
|
||||||
TypedExpr::RecordUpdate {
|
TypedExpr::RecordUpdate {
|
||||||
tipo, spread, args, ..
|
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 index_types = vec![];
|
||||||
let mut update_args = vec![];
|
let mut update_args = vec![];
|
||||||
|
|
||||||
|
@ -843,6 +888,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
update_args,
|
update_args,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
TypedExpr::UnOp { value, op, .. } => {
|
TypedExpr::UnOp { value, op, .. } => {
|
||||||
AirTree::unop(*op, self.build(value, module_build_name, &[]))
|
AirTree::unop(*op, self.build(value, module_build_name, &[]))
|
||||||
}
|
}
|
||||||
|
@ -4195,6 +4241,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
ValueConstructorVariant::Record {
|
ValueConstructorVariant::Record {
|
||||||
name: constr_name, ..
|
name: constr_name, ..
|
||||||
} => {
|
} => {
|
||||||
|
// TODO handle pair
|
||||||
if constructor.tipo.is_bool() {
|
if constructor.tipo.is_bool() {
|
||||||
Some(Term::bool(constr_name == "True"))
|
Some(Term::bool(constr_name == "True"))
|
||||||
} else if constructor.tipo.is_void() {
|
} 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::cast_from_data(
|
||||||
AirTree::builtin(
|
AirTree::builtin(
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
|
|
|
@ -2994,7 +2994,238 @@ fn acceptance_test_28_unique_list() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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#"
|
let src = r#"
|
||||||
pub opaque type AssocList<key, value> {
|
pub opaque type AssocList<key, value> {
|
||||||
inner: List<(key, value)>,
|
inner: List<(key, value)>,
|
||||||
|
|
Loading…
Reference in New Issue