feat: changed air expressions clause guard

and list clause guard to air statements
This commit is contained in:
microproofs 2023-07-01 18:58:06 -04:00 committed by Kasey
parent 023be88bf6
commit 5bcc425f0f
3 changed files with 234 additions and 64 deletions

View File

@ -1217,7 +1217,34 @@ impl<'a> CodeGenerator<'a> {
defined_tails, defined_tails,
} => { } => {
let Pattern::List { elements, .. } = &clause.pattern let Pattern::List { elements, .. } = &clause.pattern
else { unreachable!() }; else {
let mut next_clause_props = ClauseProperties {
clause_var_name: props.clause_var_name.clone(),
complex_clause: false,
needs_constr_var: false,
original_subject_name: props.original_subject_name.clone(),
final_clause: false,
specific_clause: SpecificClause::ListClause {
current_index: *current_index,
defined_tails: defined_tails.clone(),
},
};
let (_, clause_assign) =
self.clause_pattern(&clause.pattern, subject_tipo, props);
let clause_assign_hoisted = clause_assign.hoist_over(clause_then);
return AirTree::wrap_clause(
clause_assign_hoisted,
self.handle_each_clause(
rest_clauses,
final_clause,
subject_tipo,
&mut next_clause_props,
),
);
};
let tail_name = if *current_index == 0 { let tail_name = if *current_index == 0 {
props.original_subject_name.clone() props.original_subject_name.clone()
@ -1255,7 +1282,7 @@ impl<'a> CodeGenerator<'a> {
let mut use_wrap_clause = false; let mut use_wrap_clause = false;
if elements.len() > *current_index as usize { if elements.len() >= *current_index as usize {
*current_index += 1; *current_index += 1;
defined_tails.push(tail_name.clone()); defined_tails.push(tail_name.clone());
} else if next_tail_name.is_none() { } else if next_tail_name.is_none() {
@ -1396,8 +1423,13 @@ impl<'a> CodeGenerator<'a> {
elem_name.clone(), elem_name.clone(),
); );
let statement = let statement = self.nested_clause_condition(
self.nested_clause_condition(elem, list_elem_type, &mut elem_props); elem,
AirTree::local_var(&elem_name, list_elem_type.clone()),
list_elem_type,
&mut elem_props,
);
*complex_clause = *complex_clause || elem_props.complex_clause; *complex_clause = *complex_clause || elem_props.complex_clause;
(tail, elem_name, statement) (tail, elem_name, statement)
@ -1419,7 +1451,7 @@ impl<'a> CodeGenerator<'a> {
tail.iter().for_each(|elem| { tail.iter().for_each(|elem| {
let tail = defined_tails let tail = defined_tails
.last() .last()
.unwrap_or_else(|| panic!("WHERE IS ME TAIL???")); .unwrap_or_else(|| panic!("WHERE IS THE TAIL???"));
let elem_name = match elem.as_ref() { let elem_name = match elem.as_ref() {
Pattern::Var { name, .. } => name.to_string(), Pattern::Var { name, .. } => name.to_string(),
Pattern::Assign { name, .. } => name.to_string(), Pattern::Assign { name, .. } => name.to_string(),
@ -1440,8 +1472,12 @@ impl<'a> CodeGenerator<'a> {
specific_clause: props.specific_clause.clone(), specific_clause: props.specific_clause.clone(),
}; };
let statement = let statement = self.nested_clause_condition(
self.nested_clause_condition(elem, subject_tipo, &mut elem_props); elem,
AirTree::local_var(&elem_name, subject_tipo.clone()),
subject_tipo,
&mut elem_props,
);
*complex_clause = *complex_clause || elem_props.complex_clause; *complex_clause = *complex_clause || elem_props.complex_clause;
air_elems.push(statement); air_elems.push(statement);
@ -1542,6 +1578,7 @@ impl<'a> CodeGenerator<'a> {
let statement = self.nested_clause_condition( let statement = self.nested_clause_condition(
&arg.value, &arg.value,
AirTree::local_var(&field_name, arg_type.clone()),
arg_type, arg_type,
&mut field_props, &mut field_props,
); );
@ -1585,9 +1622,37 @@ impl<'a> CodeGenerator<'a> {
fn nested_clause_condition( fn nested_clause_condition(
&mut self, &mut self,
pattern: &Pattern<PatternConstructor, Arc<Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
value: AirTree,
subject_tipo: &Arc<Type>, subject_tipo: &Arc<Type>,
props: &mut ClauseProperties, props: &mut ClauseProperties,
) -> AirTree { ) -> AirTree {
todo!() match pattern {
Pattern::Int { value, .. } => {
todo!();
}
Pattern::Var { location, name } => todo!(),
Pattern::Assign {
name,
location,
pattern,
} => todo!(),
Pattern::Discard { name, location } => todo!(),
Pattern::List {
location,
elements,
tail,
} => todo!(),
Pattern::Constructor {
is_record,
location,
name,
arguments,
module,
constructor,
with_spread,
tipo,
} => todo!(),
Pattern::Tuple { location, elems } => todo!(),
}
} }
} }

View File

@ -45,6 +45,20 @@ pub enum AirStatement {
is_true: bool, is_true: bool,
value: Box<AirTree>, value: Box<AirTree>,
}, },
// Clause Guards
ClauseGuard {
subject_name: String,
tipo: Arc<Type>,
pattern: Box<AirTree>,
then: Box<AirTree>,
},
ListClauseGuard {
tipo: Arc<Type>,
tail_name: String,
next_tail_name: Option<String>,
inverse: bool,
then: Box<AirTree>,
},
// Field Access // Field Access
FieldsExpose { FieldsExpose {
indices: Vec<(usize, String, Arc<Type>)>, indices: Vec<(usize, String, Arc<Type>)>,
@ -180,19 +194,7 @@ pub enum AirExpression {
then: Box<AirTree>, then: Box<AirTree>,
otherwise: Box<AirTree>, otherwise: Box<AirTree>,
}, },
ClauseGuard {
subject_name: String,
tipo: Arc<Type>,
pattern: Box<AirTree>,
then: Box<AirTree>,
},
ListClauseGuard {
tipo: Arc<Type>,
tail_name: String,
next_tail_name: Option<String>,
inverse: bool,
then: Box<AirTree>,
},
Finally { Finally {
pattern: Box<AirTree>, pattern: Box<AirTree>,
then: Box<AirTree>, then: Box<AirTree>,
@ -479,12 +481,15 @@ impl AirTree {
tipo: Arc<Type>, tipo: Arc<Type>,
then: AirTree, then: AirTree,
) -> AirTree { ) -> AirTree {
AirTree::Expression(AirExpression::ClauseGuard { AirTree::Statement {
statement: AirStatement::ClauseGuard {
subject_name: subject_name.to_string(), subject_name: subject_name.to_string(),
tipo, tipo,
pattern: pattern.into(), pattern: pattern.into(),
then: then.into(), then: then.into(),
}) },
hoisted_over: None,
}
} }
pub fn list_clause_guard( pub fn list_clause_guard(
tail_name: impl ToString, tail_name: impl ToString,
@ -493,13 +498,16 @@ impl AirTree {
then: AirTree, then: AirTree,
next_tail_name: Option<String>, next_tail_name: Option<String>,
) -> AirTree { ) -> AirTree {
AirTree::Expression(AirExpression::ListClauseGuard { AirTree::Statement {
statement: AirStatement::ListClauseGuard {
tipo, tipo,
tail_name: tail_name.to_string(), tail_name: tail_name.to_string(),
next_tail_name, next_tail_name,
inverse, inverse,
then: then.into(), then: then.into(),
}) },
hoisted_over: None,
}
} }
pub fn finally(pattern: AirTree, then: AirTree) -> AirTree { pub fn finally(pattern: AirTree, then: AirTree) -> AirTree {
AirTree::Expression(AirExpression::Finally { AirTree::Expression(AirExpression::Finally {
@ -768,6 +776,36 @@ impl AirTree {
air_vec.push(Air::AssertBool { is_true: *is_true }); air_vec.push(Air::AssertBool { is_true: *is_true });
value.create_air_vec(air_vec); value.create_air_vec(air_vec);
} }
AirStatement::ClauseGuard {
subject_name,
tipo,
pattern,
then,
} => {
air_vec.push(Air::ClauseGuard {
subject_name: subject_name.clone(),
tipo: tipo.clone(),
});
pattern.create_air_vec(air_vec);
then.create_air_vec(air_vec);
}
AirStatement::ListClauseGuard {
tipo,
tail_name,
next_tail_name,
inverse,
then,
} => {
air_vec.push(Air::ListClauseGuard {
tipo: tipo.clone(),
tail_name: tail_name.clone(),
next_tail_name: next_tail_name.clone(),
inverse: *inverse,
});
then.create_air_vec(air_vec);
}
AirStatement::FieldsExpose { AirStatement::FieldsExpose {
indices, indices,
check_last_item, check_last_item,
@ -991,36 +1029,6 @@ impl AirTree {
then.create_air_vec(air_vec); then.create_air_vec(air_vec);
otherwise.create_air_vec(air_vec); otherwise.create_air_vec(air_vec);
} }
AirExpression::ClauseGuard {
subject_name,
tipo,
pattern,
then,
} => {
air_vec.push(Air::ClauseGuard {
subject_name: subject_name.clone(),
tipo: tipo.clone(),
});
pattern.create_air_vec(air_vec);
then.create_air_vec(air_vec);
}
AirExpression::ListClauseGuard {
tipo,
tail_name,
next_tail_name,
inverse,
then,
} => {
air_vec.push(Air::ListClauseGuard {
tipo: tipo.clone(),
tail_name: tail_name.clone(),
next_tail_name: next_tail_name.clone(),
inverse: *inverse,
});
then.create_air_vec(air_vec);
}
AirExpression::Finally { pattern, then } => { AirExpression::Finally { pattern, then } => {
air_vec.push(Air::Finally); air_vec.push(Air::Finally);
pattern.create_air_vec(air_vec); pattern.create_air_vec(air_vec);

View File

@ -419,6 +419,103 @@ fn acceptance_test_4_concat_no_anon_func() {
); );
} }
#[test]
fn acceptance_test_5_direct_head() {
let src = r#"
use aiken/builtin.{head_list}
test head_1() {
let head = fn(xs){
when xs is {
[] -> None
_ -> Some(head_list(xs))
}
}
head([1, 2, 3]) == Some(1)
}
"#;
assert_uplc(
src,
Term::equals_data()
.apply(
Term::var("head")
.lambda("head")
.apply(
Term::var("xs")
.delayed_choose_list(
Term::Constant(Constant::Data(Data::constr(1, vec![])).into()),
Term::constr_data().apply(Term::integer(0.into())).apply(
Term::mk_cons()
.apply(Term::head_list().apply(Term::var("xs")))
.apply(Term::empty_list()),
),
)
.lambda("xs"),
)
.apply(Term::list_values(vec![
Constant::Data(Data::integer(1.into())),
Constant::Data(Data::integer(2.into())),
Constant::Data(Data::integer(3.into())),
])),
)
.apply(Term::Constant(
Constant::Data(Data::constr(0, vec![Data::integer(1.into())])).into(),
)),
false,
);
}
#[test]
fn acceptance_test_5_direct_2_heads() {
let src = r#"
use aiken/builtin.{head_list}
test head_2() {
let head = fn(xs: List<Int>){
when xs is {
[] -> None
[a] -> Some(xs)
[a, b, ..c] -> Some([a,b])
}
}
head([1, 2, 3]) == Some([1, 2])
}
"#;
assert_uplc(
src,
Term::equals_data()
.apply(
Term::var("head")
.lambda("head")
.apply(
Term::var("xs")
.delayed_choose_list(
Term::Constant(Constant::Data(Data::constr(1, vec![])).into()),
Term::constr_data().apply(Term::integer(0.into())).apply(
Term::mk_cons()
.apply(Term::head_list().apply(Term::var("xs")))
.apply(Term::empty_list()),
),
)
.lambda("xs"),
)
.apply(Term::list_values(vec![
Constant::Data(Data::integer(1.into())),
Constant::Data(Data::integer(2.into())),
Constant::Data(Data::integer(3.into())),
])),
)
.apply(Term::Constant(
Constant::Data(Data::constr(0, vec![Data::integer(1.into())])).into(),
)),
false,
);
}
#[test] #[test]
fn acceptance_test_5_head_not_empty() { fn acceptance_test_5_head_not_empty() {
let src = r#" let src = r#"