feat: some code gen improvements

* fix assert on pattern Var
* fix tuple index unwrapping closes #334
* allow wrapping when casting with let
* allow wrapping when casting via function call
This commit is contained in:
Kasey White 2023-02-04 02:27:12 -05:00 committed by Lucas
parent 6053e76f6f
commit 86ca466807
3 changed files with 86 additions and 31 deletions

View File

@ -106,6 +106,11 @@ pub enum Air {
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
WrapData {
scope: Vec<u64>,
tipo: Arc<Type>,
},
AssertConstr { AssertConstr {
scope: Vec<u64>, scope: Vec<u64>,
constr_index: usize, constr_index: usize,
@ -268,6 +273,7 @@ impl Air {
| Air::UnOp { scope, .. } | Air::UnOp { scope, .. }
| Air::Let { scope, .. } | Air::Let { scope, .. }
| Air::UnWrapData { scope, .. } | Air::UnWrapData { scope, .. }
| Air::WrapData { scope, .. }
| Air::AssertConstr { scope, .. } | Air::AssertConstr { scope, .. }
| Air::When { scope, .. } | Air::When { scope, .. }
| Air::Clause { scope, .. } | Air::Clause { scope, .. }
@ -339,6 +345,15 @@ impl Air {
} }
.into(), .into(),
), ),
Air::WrapData { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Data".to_string(),
args: vec![],
}
.into(),
),
Air::Var { constructor, .. } => Some(constructor.tipo.clone()), Air::Var { constructor, .. } => Some(constructor.tipo.clone()),
Air::List { tipo, .. } Air::List { tipo, .. }
| Air::Tuple { tipo, .. } | Air::Tuple { tipo, .. }

View File

@ -53,7 +53,7 @@ pub struct FunctionAccessKey {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct AssignmentProperties { pub struct AssignmentProperties {
pub value_is_data: bool, pub value_type: Arc<Type>,
pub kind: AssignmentKind, pub kind: AssignmentKind,
} }
@ -1220,6 +1220,15 @@ pub fn monomorphize(
needs_variant = true; needs_variant = true;
} }
} }
Air::WrapData { scope, tipo } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::WrapData { scope, tipo };
needs_variant = true;
}
}
Air::When { Air::When {
scope, scope,
tipo, tipo,

View File

@ -255,10 +255,20 @@ impl<'a> CodeGenerator<'a> {
scope_fun.push(self.id_gen.next()); scope_fun.push(self.id_gen.next());
self.build_ir(fun, ir_stack, scope_fun); self.build_ir(fun, ir_stack, scope_fun);
for arg in args { if let Some(fun_arg_types) = fun.tipo().arg_types() {
let mut scope = scope.clone(); for (arg, func_type) in args.iter().zip(fun_arg_types) {
scope.push(self.id_gen.next()); let mut scope = scope.clone();
self.build_ir(&arg.value, ir_stack, scope); scope.push(self.id_gen.next());
if func_type.is_data() && !arg.value.tipo().is_data() {
ir_stack.push(Air::WrapData {
scope: scope.clone(),
tipo: arg.value.tipo(),
})
}
self.build_ir(&arg.value, ir_stack, scope);
}
} }
} }
TypedExpr::BinOp { TypedExpr::BinOp {
@ -292,8 +302,6 @@ impl<'a> CodeGenerator<'a> {
let mut value_scope = scope.clone(); let mut value_scope = scope.clone();
value_scope.push(self.id_gen.next()); value_scope.push(self.id_gen.next());
let value_is_data = value.tipo().is_data();
self.build_ir(value, &mut value_vec, value_scope); self.build_ir(value, &mut value_vec, value_scope);
self.assignment_ir( self.assignment_ir(
@ -302,7 +310,7 @@ impl<'a> CodeGenerator<'a> {
&mut value_vec, &mut value_vec,
tipo, tipo,
AssignmentProperties { AssignmentProperties {
value_is_data, value_type: value.tipo(),
kind: *kind, kind: *kind,
}, },
scope, scope,
@ -333,7 +341,7 @@ impl<'a> CodeGenerator<'a> {
&mut subject_vec, &mut subject_vec,
&subject.tipo(), &subject.tipo(),
AssignmentProperties { AssignmentProperties {
value_is_data: false, value_type: clauses[0].then.tipo(),
kind: AssignmentKind::Let, kind: AssignmentKind::Let,
}, },
scope, scope,
@ -1514,7 +1522,7 @@ impl<'a> CodeGenerator<'a> {
assignment_properties: AssignmentProperties, assignment_properties: AssignmentProperties,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
if assignment_properties.value_is_data && !tipo.is_data() && !pattern.is_discard() { if assignment_properties.value_type.is_data() && !tipo.is_data() && !pattern.is_discard() {
value_vec.insert( value_vec.insert(
0, 0,
Air::UnWrapData { Air::UnWrapData {
@ -1523,6 +1531,15 @@ impl<'a> CodeGenerator<'a> {
}, },
); );
} }
if !assignment_properties.value_type.is_data() && tipo.is_data() && !pattern.is_discard() {
value_vec.insert(
0,
Air::WrapData {
scope: scope.clone(),
tipo: assignment_properties.value_type.clone(),
},
)
}
match pattern { match pattern {
Pattern::Int { .. } | Pattern::String { .. } => unreachable!(), Pattern::Int { .. } | Pattern::String { .. } => unreachable!(),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
@ -1534,7 +1551,7 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(value_vec); pattern_vec.append(value_vec);
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
let mut assert_vec = vec![]; let mut assert_vec = vec![];
@ -1560,7 +1577,7 @@ impl<'a> CodeGenerator<'a> {
} }
list @ Pattern::List { .. } => { list @ Pattern::List { .. } => {
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
self.recursive_assert_pattern( self.recursive_assert_pattern(
@ -1585,7 +1602,7 @@ impl<'a> CodeGenerator<'a> {
// TODO: Check constr for assert on all cases // TODO: Check constr for assert on all cases
constr @ Pattern::Constructor { .. } => { constr @ Pattern::Constructor { .. } => {
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
self.recursive_assert_pattern( self.recursive_assert_pattern(
@ -1609,7 +1626,7 @@ impl<'a> CodeGenerator<'a> {
} }
tuple @ Pattern::Tuple { .. } => { tuple @ Pattern::Tuple { .. } => {
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
self.recursive_assert_pattern( self.recursive_assert_pattern(
@ -1831,11 +1848,6 @@ impl<'a> CodeGenerator<'a> {
Pattern::Int { .. } => unreachable!(), Pattern::Int { .. } => unreachable!(),
Pattern::String { .. } => unreachable!(), Pattern::String { .. } => unreachable!(),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
pattern_vec.push(Air::Let {
scope: scope.clone(),
name: name.clone(),
});
pattern_vec.append(value_vec); pattern_vec.append(value_vec);
self.recursive_assert_tipo(tipo, pattern_vec, name, scope); self.recursive_assert_tipo(tipo, pattern_vec, name, scope);
@ -2426,7 +2438,7 @@ impl<'a> CodeGenerator<'a> {
let list_name = format!("__list_{id}"); let list_name = format!("__list_{id}");
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
self.recursive_assert_pattern( self.recursive_assert_pattern(
@ -2479,7 +2491,7 @@ impl<'a> CodeGenerator<'a> {
let constr_name = format!("{constr_name}_{id}"); let constr_name = format!("{constr_name}_{id}");
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
self.recursive_assert_pattern( self.recursive_assert_pattern(
@ -2528,7 +2540,7 @@ impl<'a> CodeGenerator<'a> {
let tuple_name = format!("__tuple_name_{id}"); let tuple_name = format!("__tuple_name_{id}");
if matches!(assignment_properties.kind, AssignmentKind::Assert) if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
self.recursive_assert_pattern( self.recursive_assert_pattern(
@ -3459,6 +3471,15 @@ impl<'a> CodeGenerator<'a> {
tipo: replaced_type, tipo: replaced_type,
}; };
} }
Air::WrapData { scope, tipo } => {
let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone());
ir_stack[index] = Air::WrapData {
scope,
tipo: replaced_type,
};
}
_ => {} _ => {}
} }
} }
@ -4361,6 +4382,13 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
} }
Air::WrapData { tipo, .. } => {
let mut term = arg_stack.pop().unwrap();
term = convert_type_to_data(term, &tipo);
arg_stack.push(term);
}
Air::AssertConstr { constr_index, .. } => { Air::AssertConstr { constr_index, .. } => {
let constr = arg_stack.pop().unwrap(); let constr = arg_stack.pop().unwrap();
@ -5388,18 +5416,21 @@ impl<'a> CodeGenerator<'a> {
} }
} else { } else {
self.needs_field_access = true; self.needs_field_access = true;
term = apply_wrap( term = convert_data_to_type(
apply_wrap( apply_wrap(
Term::Var( apply_wrap(
Name { Term::Var(
text: CONSTR_GET_FIELD.to_string(), Name {
unique: 0.into(), text: CONSTR_GET_FIELD.to_string(),
} unique: 0.into(),
.into(), }
.into(),
),
term,
), ),
term, Term::Constant(UplcConstant::Integer(tuple_index as i128).into()),
), ),
Term::Constant(UplcConstant::Integer(tuple_index as i128).into()), &tipo.get_inner_types()[tuple_index],
); );
} }