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

View File

@ -1180,6 +1180,31 @@ pub fn monomorphize(
needs_variant = true; 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 { Air::ClauseGuard {
tipo, tipo,
scope, scope,
@ -1218,6 +1243,59 @@ pub fn monomorphize(
needs_variant = true; 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 { Air::Record {
scope, scope,
constr_index, constr_index,
@ -1237,10 +1315,9 @@ pub fn monomorphize(
needs_variant = true; needs_variant = true;
} }
} }
Air::RecordAccess { Air::RecordAccess {
scope, scope,
index: record_index, record_index,
tipo, tipo,
} => { } => {
if tipo.is_generic() { if tipo.is_generic() {
@ -1249,7 +1326,7 @@ pub fn monomorphize(
new_air[index] = Air::RecordAccess { new_air[index] = Air::RecordAccess {
scope, scope,
index: record_index, record_index,
tipo, tipo,
}; };
needs_variant = true; needs_variant = true;
@ -1277,24 +1354,6 @@ pub fn monomorphize(
indices: new_indices, 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 { Air::RecordUpdate {
scope, scope,
highest_index, highest_index,
@ -1326,31 +1385,6 @@ pub fn monomorphize(
needs_variant = true; 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>, data_types: &HashMap<DataTypeKey, &TypedDataType>,
) -> bool { ) -> bool {
let data_type = lookup_data_type_by_tipo(data_types.clone(), t); 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 { if let Some(data_type) = data_type {
args.len() == 1 && data_type.opaque && data_type.constructors.len() == 1 let data_type_args = data_type.constructors[0].arguments.clone();
} else { data_type_args.len() == 1 && data_type.opaque && data_type.constructors.len() == 1
false
}
} else { } else {
false false
} }
} }
pub fn replace_opaque_type(t: &mut Arc<Type>, data_types: HashMap<DataTypeKey, &TypedDataType>) { pub fn replace_opaque_type(t: &mut Arc<Type>, data_types: HashMap<DataTypeKey, &TypedDataType>) {
if check_replaceable_opaque_type(t, &data_types) { if check_replaceable_opaque_type(t, &data_types) && matches!(&**t, Type::App { .. }) {
let new_args = t.arg_types(); let data_type = lookup_data_type_by_tipo(data_types.clone(), t).unwrap();
let mut new_type = new_args.unwrap()[0].clone(); let new_type_fields = data_type.typed_parameters.clone();
replace_opaque_type(&mut new_type, data_types.clone());
*t = new_type; 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 { } else {
match (**t).clone() { match (**t).clone() {
Type::App { Type::App {

View File

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