Few more places in codegen where we need to be able to deal with Pair records

This commit is contained in:
microproofs
2024-03-29 16:05:16 -04:00
committed by Kasey
parent 26f68c2fb4
commit 3c332ca42a
3 changed files with 347 additions and 69 deletions

View File

@@ -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,23 +714,37 @@ impl<'a> CodeGenerator<'a> {
field_map,
..
} => {
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo);
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(
tipo.clone(),
ValueConstructorVariant::Record {
name: name.clone(),
arity: *arity,
field_map: field_map.clone(),
location: Span::empty(),
module: module_name.clone(),
constructors_count: data_type
.expect("Created a module type without a definition?")
.constructors
.len()
as u16,
},
);
ValueConstructor::public(
tipo.clone(),
ValueConstructorVariant::Record {
name: name.clone(),
arity: *arity,
field_map: field_map.clone(),
location: Span::empty(),
module: module_name.clone(),
constructors_count: data_type
.expect("Created a module type without a definition?")
.constructors
.len()
as u16,
},
)
};
AirTree::var(val_constructor, name, "")
}
@@ -772,43 +792,35 @@ 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);
let function_name = format!("__access_index_{}", *index);
if self.code_gen_functions.get(&function_name).is_none() {
let mut body = AirTree::local_var("__fields", list(data()));
if self.code_gen_functions.get(&function_name).is_none() {
let mut body = AirTree::local_var("__fields", list(data()));
for _ in 0..*index {
body = AirTree::builtin(
DefaultFunction::TailList,
list(data()),
vec![body],
)
}
body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]);
self.code_gen_functions.insert(
function_name.clone(),
CodeGenFunction::Function {
body,
params: vec!["__fields".to_string()],
},
);
for _ in 0..*index {
body = AirTree::builtin(
DefaultFunction::TailList,
list(data()),
vec![body],
)
}
AirTree::index_access(
function_name,
tipo.clone(),
self.build(tuple, module_build_name, &[]),
)
body = AirTree::builtin(DefaultFunction::HeadList, data(), vec![body]);
self.code_gen_functions.insert(
function_name.clone(),
CodeGenFunction::Function {
body,
params: vec!["__fields".to_string()],
},
);
}
AirTree::index_access(
function_name,
tipo.clone(),
self.build(tuple, module_build_name, &[]),
)
}
TypedExpr::ErrorTerm { tipo, .. } => AirTree::error(tipo.clone(), false),
@@ -816,32 +828,66 @@ impl<'a> CodeGenerator<'a> {
TypedExpr::RecordUpdate {
tipo, spread, args, ..
} => {
let mut index_types = vec![];
let mut update_args = vec![];
if tipo.is_pair() {
assert!(args.len() == 1);
let mut highest_index = 0;
let Some(arg) = args.first() else {
unreachable!("Pair update with no arguments")
};
for arg in args
.iter()
.sorted_by(|arg1, arg2| arg1.index.cmp(&arg2.index))
{
let arg_val = self.build(&arg.value, module_build_name, &[]);
if arg.index > highest_index {
highest_index = arg.index;
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![];
let mut highest_index = 0;
for arg in args
.iter()
.sorted_by(|arg1, arg2| arg1.index.cmp(&arg2.index))
{
let arg_val = self.build(&arg.value, module_build_name, &[]);
if arg.index > highest_index {
highest_index = arg.index;
}
index_types.push((arg.index, arg.value.tipo()));
update_args.push(arg_val);
}
index_types.push((arg.index, arg.value.tipo()));
update_args.push(arg_val);
AirTree::record_update(
index_types,
highest_index,
tipo.clone(),
self.build(spread, module_build_name, &[]),
update_args,
)
}
AirTree::record_update(
index_types,
highest_index,
tipo.clone(),
self.build(spread, module_build_name, &[]),
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() {

View File

@@ -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 {