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>,
},
WrapData {
scope: Vec<u64>,
tipo: Arc<Type>,
},
AssertConstr {
scope: Vec<u64>,
constr_index: usize,
@ -268,6 +273,7 @@ impl Air {
| Air::UnOp { scope, .. }
| Air::Let { scope, .. }
| Air::UnWrapData { scope, .. }
| Air::WrapData { scope, .. }
| Air::AssertConstr { scope, .. }
| Air::When { scope, .. }
| Air::Clause { scope, .. }
@ -339,6 +345,15 @@ impl Air {
}
.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::List { tipo, .. }
| Air::Tuple { tipo, .. }

View File

@ -53,7 +53,7 @@ pub struct FunctionAccessKey {
#[derive(Clone, Debug)]
pub struct AssignmentProperties {
pub value_is_data: bool,
pub value_type: Arc<Type>,
pub kind: AssignmentKind,
}
@ -1220,6 +1220,15 @@ pub fn monomorphize(
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 {
scope,
tipo,

View File

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