feat: Add boolean conditions to when statements
This commit is contained in:
parent
75808cc046
commit
d7e4aef4c5
|
@ -24,6 +24,11 @@ pub enum Air {
|
||||||
bytes: Vec<u8>,
|
bytes: Vec<u8>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Bool {
|
||||||
|
scope: Vec<u64>,
|
||||||
|
value: bool,
|
||||||
|
},
|
||||||
|
|
||||||
Var {
|
Var {
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
constructor: ValueConstructor,
|
constructor: ValueConstructor,
|
||||||
|
@ -228,6 +233,7 @@ impl Air {
|
||||||
Air::Int { scope, .. }
|
Air::Int { scope, .. }
|
||||||
| Air::String { scope, .. }
|
| Air::String { scope, .. }
|
||||||
| Air::ByteArray { scope, .. }
|
| Air::ByteArray { scope, .. }
|
||||||
|
| Air::Bool { scope, .. }
|
||||||
| Air::Var { scope, .. }
|
| Air::Var { scope, .. }
|
||||||
| Air::List { scope, .. }
|
| Air::List { scope, .. }
|
||||||
| Air::ListAccessor { scope, .. }
|
| Air::ListAccessor { scope, .. }
|
||||||
|
|
|
@ -838,61 +838,68 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let mut temp_clause_properties = clause_properties.clone();
|
let mut temp_clause_properties = clause_properties.clone();
|
||||||
*temp_clause_properties.needs_constr_var() = false;
|
*temp_clause_properties.needs_constr_var() = false;
|
||||||
|
|
||||||
for arg in arguments {
|
if tipo.is_bool() {
|
||||||
check_when_pattern_needs(&arg.value, &mut temp_clause_properties);
|
pattern_vec.push(Air::Bool {
|
||||||
}
|
scope,
|
||||||
|
value: constr_name == "True",
|
||||||
// find data type definition
|
|
||||||
let data_type = lookup_data_type_by_tipo(self.data_types.clone(), tipo).unwrap();
|
|
||||||
|
|
||||||
let (index, _) = data_type
|
|
||||||
.constructors
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|(_, dt)| &dt.name == constr_name)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut new_vec = vec![Air::Var {
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone().into(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: temp_clause_properties.clause_var_name().clone(),
|
|
||||||
scope: scope.clone(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
}];
|
|
||||||
|
|
||||||
// if only one constructor, no need to check
|
|
||||||
if data_type.constructors.len() > 1 {
|
|
||||||
// push constructor Index
|
|
||||||
pattern_vec.push(Air::Int {
|
|
||||||
value: index.to_string(),
|
|
||||||
scope: scope.clone(),
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if *temp_clause_properties.needs_constr_var() {
|
|
||||||
self.when_recursive_ir(
|
|
||||||
pattern,
|
|
||||||
pattern_vec,
|
|
||||||
&mut new_vec,
|
|
||||||
clause_properties,
|
|
||||||
tipo,
|
|
||||||
scope,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
self.when_recursive_ir(
|
for arg in arguments {
|
||||||
pattern,
|
check_when_pattern_needs(&arg.value, &mut temp_clause_properties);
|
||||||
pattern_vec,
|
}
|
||||||
&mut vec![],
|
|
||||||
clause_properties,
|
|
||||||
tipo,
|
|
||||||
scope,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// find data type definition
|
||||||
|
let data_type =
|
||||||
|
lookup_data_type_by_tipo(self.data_types.clone(), tipo).unwrap();
|
||||||
|
|
||||||
|
let (index, _) = data_type
|
||||||
|
.constructors
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, dt)| &dt.name == constr_name)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut new_vec = vec![Air::Var {
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo.clone().into(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: temp_clause_properties.clause_var_name().clone(),
|
||||||
|
scope: scope.clone(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
// if only one constructor, no need to check
|
||||||
|
if data_type.constructors.len() > 1 {
|
||||||
|
// push constructor Index
|
||||||
|
pattern_vec.push(Air::Int {
|
||||||
|
value: index.to_string(),
|
||||||
|
scope: scope.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if *temp_clause_properties.needs_constr_var() {
|
||||||
|
self.when_recursive_ir(
|
||||||
|
pattern,
|
||||||
|
pattern_vec,
|
||||||
|
&mut new_vec,
|
||||||
|
clause_properties,
|
||||||
|
tipo,
|
||||||
|
scope,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.when_recursive_ir(
|
||||||
|
pattern,
|
||||||
|
pattern_vec,
|
||||||
|
&mut vec![],
|
||||||
|
clause_properties,
|
||||||
|
tipo,
|
||||||
|
scope,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
pattern_vec.append(values);
|
pattern_vec.append(values);
|
||||||
|
|
||||||
// unify clause properties
|
// unify clause properties
|
||||||
|
@ -2684,6 +2691,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let term = Term::Constant(UplcConstant::ByteString(bytes));
|
let term = Term::Constant(UplcConstant::ByteString(bytes));
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
}
|
}
|
||||||
|
Air::Bool { value, .. } => {
|
||||||
|
let term = Term::Constant(UplcConstant::Bool(value));
|
||||||
|
arg_stack.push(term);
|
||||||
|
}
|
||||||
Air::Var {
|
Air::Var {
|
||||||
name,
|
name,
|
||||||
constructor,
|
constructor,
|
||||||
|
@ -3626,66 +3637,86 @@ impl<'a> CodeGenerator<'a> {
|
||||||
// the next branch in the when expression
|
// the next branch in the when expression
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let checker = if tipo.is_int() {
|
if tipo.is_bool() {
|
||||||
apply_wrap(
|
if matches!(clause, Term::Constant(UplcConstant::Bool(true))) {
|
||||||
DefaultFunction::EqualsInteger.into(),
|
term = delayed_if_else(
|
||||||
Term::Var(Name {
|
Term::Var(Name {
|
||||||
text: subject_name,
|
text: subject_name,
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else if tipo.is_bytearray() {
|
|
||||||
apply_wrap(
|
|
||||||
DefaultFunction::EqualsByteString.into(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else if tipo.is_bool() {
|
|
||||||
todo!("Bool in when statements not done yet")
|
|
||||||
} else if tipo.is_string() {
|
|
||||||
apply_wrap(
|
|
||||||
DefaultFunction::EqualsString.into(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else if tipo.is_list() || tipo.is_tuple() {
|
|
||||||
unreachable!()
|
|
||||||
} else {
|
|
||||||
apply_wrap(
|
|
||||||
DefaultFunction::EqualsInteger.into(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if complex_clause {
|
|
||||||
term = apply_wrap(
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: "__other_clauses_delayed".to_string(),
|
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
},
|
}),
|
||||||
body: if_else(
|
body,
|
||||||
apply_wrap(checker, clause),
|
term,
|
||||||
Term::Delay(body.into()),
|
);
|
||||||
Term::Var(Name {
|
} else {
|
||||||
|
term = delayed_if_else(
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
term,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let checker = if tipo.is_int() {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsInteger.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if tipo.is_bytearray() {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsByteString.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if tipo.is_string() {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsString.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if tipo.is_list() || tipo.is_tuple() {
|
||||||
|
unreachable!()
|
||||||
|
} else {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsInteger.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if complex_clause {
|
||||||
|
term = apply_wrap(
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
text: "__other_clauses_delayed".to_string(),
|
text: "__other_clauses_delayed".to_string(),
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
}),
|
},
|
||||||
)
|
body: if_else(
|
||||||
.force_wrap()
|
apply_wrap(checker, clause),
|
||||||
.into(),
|
Term::Delay(body.into()),
|
||||||
},
|
Term::Var(Name {
|
||||||
Term::Delay(term.into()),
|
text: "__other_clauses_delayed".to_string(),
|
||||||
);
|
unique: 0.into(),
|
||||||
} else {
|
}),
|
||||||
term = delayed_if_else(apply_wrap(checker, clause), body, term);
|
)
|
||||||
|
.force_wrap()
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
Term::Delay(term.into()),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
term = delayed_if_else(apply_wrap(checker, clause), body, term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
|
@ -3767,55 +3798,81 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let then = arg_stack.pop().unwrap();
|
let then = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let checker = if tipo.is_int() {
|
if tipo.is_bool() {
|
||||||
apply_wrap(
|
let mut term = Term::Var(Name {
|
||||||
DefaultFunction::EqualsInteger.into(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else if tipo.is_bytearray() {
|
|
||||||
apply_wrap(
|
|
||||||
DefaultFunction::EqualsByteString.into(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else if tipo.is_bool() {
|
|
||||||
todo!("Nested bool usage in when statements not yet implemented")
|
|
||||||
} else if tipo.is_string() {
|
|
||||||
apply_wrap(
|
|
||||||
DefaultFunction::EqualsString.into(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else if tipo.is_list() || tipo.is_tuple() {
|
|
||||||
unreachable!()
|
|
||||||
} else {
|
|
||||||
apply_wrap(
|
|
||||||
DefaultFunction::EqualsInteger.into(),
|
|
||||||
constr_index_exposer(Term::Var(Name {
|
|
||||||
text: subject_name,
|
|
||||||
unique: 0.into(),
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let term = if_else(
|
|
||||||
apply_wrap(checker, condition),
|
|
||||||
Term::Delay(then.into()),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: "__other_clauses_delayed".to_string(),
|
text: "__other_clauses_delayed".to_string(),
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
}),
|
});
|
||||||
)
|
if matches!(condition, Term::Constant(UplcConstant::Bool(true))) {
|
||||||
.force_wrap();
|
term = if_else(
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
Term::Delay(then.into()),
|
||||||
|
term,
|
||||||
|
)
|
||||||
|
.force_wrap();
|
||||||
|
} else {
|
||||||
|
term = if_else(
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
term,
|
||||||
|
Term::Delay(then.into()),
|
||||||
|
)
|
||||||
|
.force_wrap();
|
||||||
|
}
|
||||||
|
arg_stack.push(term);
|
||||||
|
} else {
|
||||||
|
let checker = if tipo.is_int() {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsInteger.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if tipo.is_bytearray() {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsByteString.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if tipo.is_string() {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsString.into(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else if tipo.is_list() || tipo.is_tuple() {
|
||||||
|
unreachable!()
|
||||||
|
} else {
|
||||||
|
apply_wrap(
|
||||||
|
DefaultFunction::EqualsInteger.into(),
|
||||||
|
constr_index_exposer(Term::Var(Name {
|
||||||
|
text: subject_name,
|
||||||
|
unique: 0.into(),
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
arg_stack.push(term);
|
let term = if_else(
|
||||||
|
apply_wrap(checker, condition),
|
||||||
|
Term::Delay(then.into()),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: "__other_clauses_delayed".to_string(),
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.force_wrap();
|
||||||
|
arg_stack.push(term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Air::ListClauseGuard {
|
Air::ListClauseGuard {
|
||||||
tail_name,
|
tail_name,
|
||||||
|
|
Loading…
Reference in New Issue