Skip to content

Commit

Permalink
Few more places in codegen where we need to be able to deal with Pair…
Browse files Browse the repository at this point in the history
… records
  • Loading branch information
MicroProofs committed Apr 16, 2024
1 parent a228f0b commit 2430360
Show file tree
Hide file tree
Showing 3 changed files with 347 additions and 69 deletions.
181 changes: 114 additions & 67 deletions crates/aiken-lang/src/gen_uplc.rs
Expand Up @@ -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);

Expand Down Expand Up @@ -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, "")
}
Expand Down Expand Up @@ -772,76 +792,102 @@ 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),

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![];

index_types.push((arg.index, arg.value.tipo()));
update_args.push(arg_val);
}
let mut highest_index = 0;

AirTree::record_update(
index_types,
highest_index,
tipo.clone(),
self.build(spread, module_build_name, &[]),
update_args,
)
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);
}

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, &[]))
Expand Down Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion crates/aiken-lang/src/gen_uplc/tree.rs
Expand Up @@ -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 {
Expand Down

0 comments on commit 2430360

Please sign in to comment.