feat: changed air expressions clause guard
and list clause guard to air statements
This commit is contained in:
parent
023be88bf6
commit
5bcc425f0f
|
@ -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!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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#"
|
||||||
|
|
Loading…
Reference in New Issue