feat: Now opaque types with one constr and one field are converted to inner field type

This commit is contained in:
Kasey White 2023-01-17 02:30:56 -05:00 committed by Lucas
parent 98d2cb5afc
commit 33d902ba2a
3 changed files with 158 additions and 94 deletions

View File

@ -164,7 +164,7 @@ pub enum Air {
RecordAccess {
scope: Vec<u64>,
index: u64,
record_index: u64,
tipo: Arc<Type>,
},
@ -183,7 +183,7 @@ pub enum Air {
TupleIndex {
scope: Vec<u64>,
tipo: Arc<Type>,
index: usize,
tuple_index: usize,
},
Todo {
@ -283,7 +283,11 @@ impl Air {
| Air::Todo { tipo, .. }
| Air::ErrorTerm { tipo, .. }
| Air::Trace { tipo, .. }
| Air::TupleAccessor { tipo, .. } => Some(tipo.clone()),
| Air::TupleAccessor { tipo, .. }
| Air::Var {
constructor: ValueConstructor { tipo, .. },
..
} => Some(tipo.clone()),
_ => None,
}
}

View File

@ -1180,6 +1180,31 @@ pub fn monomorphize(
needs_variant = true;
}
}
Air::TupleClause {
scope,
tipo,
indices,
predefined_indices,
subject_name,
count,
complex_clause,
} => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::TupleClause {
scope,
tipo,
indices,
predefined_indices,
subject_name,
count,
complex_clause,
};
needs_variant = true;
}
}
Air::ClauseGuard {
tipo,
scope,
@ -1218,6 +1243,59 @@ pub fn monomorphize(
needs_variant = true;
}
}
Air::Tuple { scope, tipo, count } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::Tuple { scope, tipo, count };
needs_variant = true;
}
}
Air::TupleIndex {
scope,
tipo,
tuple_index,
} => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::TupleIndex {
scope,
tipo,
tuple_index,
};
needs_variant = true;
}
}
Air::Todo { scope, label, tipo } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::Todo { scope, tipo, label };
needs_variant = true;
}
}
Air::ErrorTerm { scope, label, tipo } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::ErrorTerm { scope, tipo, label };
needs_variant = true;
}
}
Air::Trace { scope, text, tipo } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::Trace { scope, tipo, text };
needs_variant = true;
}
}
Air::Record {
scope,
constr_index,
@ -1237,10 +1315,9 @@ pub fn monomorphize(
needs_variant = true;
}
}
Air::RecordAccess {
scope,
index: record_index,
record_index,
tipo,
} => {
if tipo.is_generic() {
@ -1249,7 +1326,7 @@ pub fn monomorphize(
new_air[index] = Air::RecordAccess {
scope,
index: record_index,
record_index,
tipo,
};
needs_variant = true;
@ -1277,24 +1354,6 @@ pub fn monomorphize(
indices: new_indices,
};
}
Air::Tuple { scope, tipo, count } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::Tuple { scope, count, tipo };
needs_variant = true;
}
}
Air::Todo { scope, label, tipo } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::Todo { scope, label, tipo };
needs_variant = true;
}
}
Air::RecordUpdate {
scope,
highest_index,
@ -1326,31 +1385,6 @@ pub fn monomorphize(
needs_variant = true;
}
}
Air::TupleClause {
scope,
tipo,
indices,
predefined_indices,
subject_name,
count,
complex_clause,
} => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::TupleClause {
scope,
tipo,
indices,
predefined_indices,
subject_name,
count,
complex_clause,
};
needs_variant = true;
}
}
_ => {}
}
}
@ -1515,24 +1549,34 @@ pub fn check_replaceable_opaque_type(
data_types: &HashMap<DataTypeKey, &TypedDataType>,
) -> bool {
let data_type = lookup_data_type_by_tipo(data_types.clone(), t);
let args = t.arg_types();
if let Some(args) = args {
if let Some(data_type) = data_type {
args.len() == 1 && data_type.opaque && data_type.constructors.len() == 1
} else {
false
}
if let Some(data_type) = data_type {
let data_type_args = data_type.constructors[0].arguments.clone();
data_type_args.len() == 1 && data_type.opaque && data_type.constructors.len() == 1
} else {
false
}
}
pub fn replace_opaque_type(t: &mut Arc<Type>, data_types: HashMap<DataTypeKey, &TypedDataType>) {
if check_replaceable_opaque_type(t, &data_types) {
let new_args = t.arg_types();
let mut new_type = new_args.unwrap()[0].clone();
replace_opaque_type(&mut new_type, data_types.clone());
*t = new_type;
if check_replaceable_opaque_type(t, &data_types) && matches!(&**t, Type::App { .. }) {
let data_type = lookup_data_type_by_tipo(data_types.clone(), t).unwrap();
let new_type_fields = data_type.typed_parameters.clone();
let mut generics_type_map: HashMap<u64, Arc<Type>> = HashMap::new();
for (tipo, param) in new_type_fields.iter().zip(t.arg_types().unwrap()) {
let mut map = generics_type_map.into_iter().collect_vec();
map.append(&mut get_generics_and_type(tipo, &param));
generics_type_map = map.into_iter().collect();
}
let mut generic_type = data_type.constructors[0].arguments[0].tipo.clone();
find_generics_to_replace(&mut generic_type, &generics_type_map);
replace_opaque_type(&mut generic_type, data_types.clone());
*t = generic_type;
} else {
match (**t).clone() {
Type::App {

View File

@ -444,7 +444,7 @@ impl<'a> CodeGenerator<'a> {
ir_stack.push(Air::RecordAccess {
scope: scope.clone(),
index: *index,
record_index: *index,
tipo: tipo.clone(),
});
@ -583,7 +583,7 @@ impl<'a> CodeGenerator<'a> {
ir_stack.push(Air::TupleIndex {
scope: scope.clone(),
tipo: tuple.tipo(),
index: *index,
tuple_index: *index,
});
self.build_ir(tuple, ir_stack, scope);
@ -1884,6 +1884,9 @@ impl<'a> CodeGenerator<'a> {
let mut final_zero_arg_ir = dep_ir;
final_zero_arg_ir.extend(funt_comp.ir.clone());
self.convert_opaque_type_to_inner_ir(&mut final_zero_arg_ir);
self.zero_arg_functions.insert(func, final_zero_arg_ir);
for (key, val) in defined_functions.into_iter() {
@ -2270,7 +2273,8 @@ impl<'a> CodeGenerator<'a> {
}
fn convert_opaque_type_to_inner_ir(&mut self, ir_stack: &mut Vec<Air>) {
for (index, ir) in ir_stack.clone().into_iter().enumerate().rev() {
let mut indices_to_remove = vec![];
for (index, ir) in ir_stack.clone().into_iter().enumerate() {
match ir {
Air::Var {
scope,
@ -2478,14 +2482,18 @@ impl<'a> CodeGenerator<'a> {
count,
};
}
Air::TupleIndex { tipo, scope, index } => {
Air::TupleIndex {
tipo,
scope,
tuple_index,
} => {
let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone());
ir_stack[index] = Air::TupleIndex {
scope,
tipo: replaced_type,
index,
tuple_index,
};
}
Air::Todo { tipo, scope, label } => {
@ -2528,6 +2536,24 @@ impl<'a> CodeGenerator<'a> {
tipo: replaced_type,
};
}
Air::RecordUpdate {
highest_index,
indices,
scope,
} => {
let mut new_indices = vec![];
for (ind, tipo) in indices {
let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone());
new_indices.push((ind, replaced_type));
}
ir_stack[index] = Air::RecordUpdate {
scope,
indices: new_indices,
highest_index,
};
}
Air::Record {
constr_index,
tipo,
@ -2535,7 +2561,7 @@ impl<'a> CodeGenerator<'a> {
scope,
} => {
if check_replaceable_opaque_type(&tipo, self.data_types) {
ir_stack.remove(index);
indices_to_remove.push(index);
} else {
let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone());
@ -2549,7 +2575,7 @@ impl<'a> CodeGenerator<'a> {
}
}
Air::RecordAccess {
index: record_field_index,
record_index,
tipo,
scope,
} => {
@ -2557,14 +2583,14 @@ impl<'a> CodeGenerator<'a> {
let record_type = record.tipo();
if let Some(record_type) = record_type {
if check_replaceable_opaque_type(&record_type, self.data_types) {
ir_stack.remove(index);
indices_to_remove.push(index);
} else {
let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone());
ir_stack[index] = Air::RecordAccess {
scope,
index: record_field_index,
record_index,
tipo: replaced_type,
};
}
@ -2574,7 +2600,7 @@ impl<'a> CodeGenerator<'a> {
ir_stack[index] = Air::RecordAccess {
scope,
index: record_field_index,
record_index,
tipo: replaced_type,
};
}
@ -2621,27 +2647,13 @@ impl<'a> CodeGenerator<'a> {
};
}
}
Air::RecordUpdate {
highest_index,
indices,
scope,
} => {
let mut new_indices = vec![];
for (ind, tipo) in indices {
let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone());
new_indices.push((ind, replaced_type));
}
ir_stack[index] = Air::RecordUpdate {
scope,
indices: new_indices,
highest_index,
};
}
_ => {}
}
}
for index in indices_to_remove.into_iter().rev() {
ir_stack.remove(index);
}
}
fn uplc_code_gen(&mut self, ir_stack: &mut Vec<Air>) -> Term<Name> {
@ -3931,7 +3943,9 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term);
}
Air::RecordAccess { index, tipo, .. } => {
Air::RecordAccess {
record_index, tipo, ..
} => {
let constr = arg_stack.pop().unwrap();
let mut term = apply_wrap(
@ -3948,7 +3962,7 @@ impl<'a> CodeGenerator<'a> {
constr,
),
),
Term::Constant(UplcConstant::Integer(index.into())),
Term::Constant(UplcConstant::Integer(record_index.into())),
);
term = convert_data_to_type(term, &tipo);
@ -4352,11 +4366,13 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term);
}
Air::TupleIndex { tipo, index, .. } => {
Air::TupleIndex {
tipo, tuple_index, ..
} => {
let mut term = arg_stack.pop().unwrap();
if matches!(tipo.get_uplc_type(), UplcType::Pair(_, _)) {
if index == 0 {
if tuple_index == 0 {
term = convert_data_to_type(
apply_wrap(
Term::Builtin(DefaultFunction::FstPair)
@ -4387,7 +4403,7 @@ impl<'a> CodeGenerator<'a> {
}),
term,
),
Term::Constant(UplcConstant::Integer(index as i128)),
Term::Constant(UplcConstant::Integer(tuple_index as i128)),
);
}