checkpoint
This commit is contained in:
parent
0854d71836
commit
f94c8213b6
|
@ -95,7 +95,10 @@ impl ClauseProperties {
|
|||
original_subject_name: subject_name,
|
||||
final_clause: false,
|
||||
needs_constr_var: false,
|
||||
specific_clause: SpecificClause::ConstrClause,
|
||||
specific_clause: SpecificClause::ListClause {
|
||||
current_index: 0,
|
||||
defined_tails: vec![],
|
||||
},
|
||||
}
|
||||
} else if t.is_tuple() {
|
||||
ClauseProperties {
|
||||
|
|
|
@ -21,8 +21,8 @@ use crate::{
|
|||
gen_uplc::{
|
||||
air::Air,
|
||||
builder::{
|
||||
self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey,
|
||||
SpecificClause,
|
||||
self as build, lookup_data_type_by_tipo, AssignmentProperties, ClauseProperties,
|
||||
DataTypeKey, FunctionAccessKey, SpecificClause,
|
||||
},
|
||||
},
|
||||
tipo::{
|
||||
|
@ -91,8 +91,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> {
|
||||
let mut air_tree = self.build(test_body);
|
||||
air_tree = AirTree::hoist_over(AirTree::no_op(), air_tree);
|
||||
|
||||
air_tree = AirTree::no_op().hoist_over(air_tree);
|
||||
println!("{:#?}", air_tree);
|
||||
println!("{:#?}", air_tree.to_vec());
|
||||
|
||||
todo!()
|
||||
}
|
||||
|
@ -116,7 +118,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
while let Some(expression) = expressions.pop() {
|
||||
let exp_tree = self.build(&expression);
|
||||
|
||||
last_exp = AirTree::hoist_over(exp_tree, last_exp);
|
||||
last_exp = exp_tree.hoist_over(last_exp);
|
||||
}
|
||||
last_exp
|
||||
}
|
||||
|
@ -309,7 +311,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
},
|
||||
);
|
||||
|
||||
AirTree::hoist_over(assignment, clause_then)
|
||||
assignment.hoist_over(clause_then)
|
||||
} else {
|
||||
clauses = if subject.tipo().is_list() {
|
||||
build::rearrange_clauses(clauses)
|
||||
|
@ -343,9 +345,14 @@ impl<'a> CodeGenerator<'a> {
|
|||
);
|
||||
|
||||
let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject));
|
||||
let when_assign = AirTree::when(subject_name, subject.tipo(), clauses);
|
||||
let when_assign = AirTree::when(
|
||||
subject_name,
|
||||
subject.tipo(),
|
||||
AirTree::local_var(constr_var, tipo.clone()),
|
||||
clauses,
|
||||
);
|
||||
|
||||
AirTree::hoist_over(constr_assign, when_assign)
|
||||
constr_assign.hoist_over(when_assign)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,7 +518,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
AirTree::int(expected_int),
|
||||
AirTree::local_var(name, int()),
|
||||
);
|
||||
AirTree::assert_bool(true, AirTree::hoist_over(assignment, expect))
|
||||
AirTree::assert_bool(true, assignment.hoist_over(expect))
|
||||
} else {
|
||||
unreachable!("Code Gen should never reach here")
|
||||
}
|
||||
|
@ -524,13 +531,12 @@ impl<'a> CodeGenerator<'a> {
|
|||
let val = AirTree::local_var(name, tipo.clone());
|
||||
|
||||
if tipo.is_primitive() {
|
||||
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val))
|
||||
AirTree::let_assignment(name, assignment.hoist_over(val))
|
||||
} else {
|
||||
let expect =
|
||||
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
|
||||
let assign =
|
||||
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect));
|
||||
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
|
||||
let assign = AirTree::let_assignment("_", assignment.hoist_over(expect));
|
||||
AirTree::let_assignment(name, assign.hoist_over(val))
|
||||
}
|
||||
} else {
|
||||
AirTree::let_assignment(name, value)
|
||||
|
@ -551,13 +557,12 @@ impl<'a> CodeGenerator<'a> {
|
|||
let assignment = AirTree::let_assignment(name, value);
|
||||
let val = AirTree::local_var(name, tipo.clone());
|
||||
if tipo.is_primitive() {
|
||||
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val))
|
||||
AirTree::let_assignment(name, assignment.hoist_over(val))
|
||||
} else {
|
||||
let expect =
|
||||
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
|
||||
let assign =
|
||||
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect));
|
||||
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
|
||||
let assign = AirTree::let_assignment("_", assignment.hoist_over(expect));
|
||||
AirTree::let_assignment(name, assign.hoist_over(val))
|
||||
}
|
||||
} else if !props.remove_unused {
|
||||
AirTree::let_assignment(name, value)
|
||||
|
@ -653,7 +658,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
},
|
||||
),
|
||||
));
|
||||
println!("ELEMS IS {:#?}", elems);
|
||||
});
|
||||
|
||||
let names = elems.iter().map(|(name, _)| name.to_string()).collect_vec();
|
||||
|
@ -801,7 +805,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
// This `value` is either value param that was passed in or
|
||||
// local var
|
||||
sequence.push(AirTree::fields_expose(indices, false, value));
|
||||
sequence.push(AirTree::fields_expose(indices, props.full_check, value));
|
||||
|
||||
sequence.append(
|
||||
&mut fields
|
||||
|
@ -877,7 +881,12 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
// This `value` is either value param that was passed in or
|
||||
// local var
|
||||
sequence.push(AirTree::tuple_access(indices, tipo.clone(), false, value));
|
||||
sequence.push(AirTree::tuple_access(
|
||||
indices,
|
||||
tipo.clone(),
|
||||
props.full_check,
|
||||
value,
|
||||
));
|
||||
|
||||
sequence.append(&mut elems.into_iter().map(|(_, field)| field).collect_vec());
|
||||
|
||||
|
@ -930,14 +939,12 @@ impl<'a> CodeGenerator<'a> {
|
|||
location,
|
||||
);
|
||||
|
||||
let anon_func_body = AirTree::hoist_over(
|
||||
AirTree::UnhoistedSequence(vec![
|
||||
tuple_access,
|
||||
AirTree::let_assignment("_", expect_fst),
|
||||
AirTree::let_assignment("_", expect_snd),
|
||||
]),
|
||||
AirTree::void(),
|
||||
);
|
||||
let anon_func_body = AirTree::UnhoistedSequence(vec![
|
||||
tuple_access,
|
||||
AirTree::let_assignment("_", expect_fst),
|
||||
AirTree::let_assignment("_", expect_snd),
|
||||
])
|
||||
.hoist_over(AirTree::void());
|
||||
|
||||
let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body);
|
||||
|
||||
|
@ -963,7 +970,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
vec![AirTree::local_var(map_name, tipo.clone()), unwrap_function],
|
||||
);
|
||||
|
||||
AirTree::hoist_over(assign, func_call)
|
||||
assign.hoist_over(func_call)
|
||||
} else if tipo.is_list() {
|
||||
assert!(!tipo.get_inner_types().is_empty());
|
||||
let inner_list_type = &tipo.get_inner_types()[0];
|
||||
|
@ -981,7 +988,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
);
|
||||
|
||||
let anon_func_body =
|
||||
AirTree::hoist_over(AirTree::let_assignment("_", expect_item), AirTree::void());
|
||||
AirTree::let_assignment("_", expect_item).hoist_over(AirTree::void());
|
||||
|
||||
let unwrap_function = AirTree::anon_func(vec![item_name], anon_func_body);
|
||||
|
||||
|
@ -1007,9 +1014,86 @@ impl<'a> CodeGenerator<'a> {
|
|||
vec![AirTree::local_var(list_name, tipo.clone()), unwrap_function],
|
||||
);
|
||||
|
||||
AirTree::hoist_over(assign, func_call)
|
||||
} else {
|
||||
assign.hoist_over(func_call)
|
||||
} else if tipo.is_2_tuple() {
|
||||
let tuple_inner_types = tipo.get_inner_types();
|
||||
|
||||
let pair_name = format!("__pair_span_{}_{}", location.start, location.end);
|
||||
let fst_name = format!("__pair_fst_span_{}_{}", location.start, location.end);
|
||||
let snd_name = format!("__pair_snd_span_{}_{}", location.start, location.end);
|
||||
|
||||
let tuple_assign = AirTree::let_assignment(&pair_name, value);
|
||||
|
||||
let tuple_access = AirTree::tuple_access(
|
||||
vec![fst_name.clone(), snd_name.clone()],
|
||||
tipo.clone(),
|
||||
false,
|
||||
AirTree::local_var(pair_name, tipo.clone()),
|
||||
);
|
||||
|
||||
let expect_fst = self.expect_type(
|
||||
&tuple_inner_types[0],
|
||||
AirTree::local_var(fst_name, tuple_inner_types[0].clone()),
|
||||
defined_data_types,
|
||||
location,
|
||||
);
|
||||
|
||||
let expect_snd = self.expect_type(
|
||||
&tuple_inner_types[1],
|
||||
AirTree::local_var(snd_name, tuple_inner_types[1].clone()),
|
||||
defined_data_types,
|
||||
location,
|
||||
);
|
||||
|
||||
AirTree::UnhoistedSequence(vec![
|
||||
tuple_assign,
|
||||
tuple_access,
|
||||
AirTree::let_assignment("_", expect_fst),
|
||||
AirTree::let_assignment("_", expect_snd),
|
||||
])
|
||||
.hoist_over(AirTree::void())
|
||||
} else if tipo.is_tuple() {
|
||||
todo!()
|
||||
} else {
|
||||
let data_type =
|
||||
build::lookup_data_type_by_tipo(&self.data_types, tipo).unwrap_or_else(|| {
|
||||
unreachable!("We need a data type definition fot type {:#?}", tipo)
|
||||
});
|
||||
|
||||
// for (index, arg) in tipo.arg_types().unwrap().iter().enumerate() {
|
||||
// let field_type = arg.clone();
|
||||
// type_map.insert(index, field_type);
|
||||
// }
|
||||
|
||||
// TODO calculate the variant name.
|
||||
let data_type_name = format!("__expect_{}{}", data_type.name, "");
|
||||
let function = self.code_gen_functions.get(&data_type_name);
|
||||
|
||||
if function.is_none() && defined_data_types.get(&data_type_name).is_none() {
|
||||
todo!()
|
||||
} else if let Some(counter) = defined_data_types.get_mut(&data_type_name) {
|
||||
*counter += 1;
|
||||
} else {
|
||||
defined_data_types.insert(data_type_name.to_string(), 0);
|
||||
}
|
||||
|
||||
let func_var = AirTree::var(
|
||||
ValueConstructor::public(
|
||||
tipo.clone(),
|
||||
ValueConstructorVariant::ModuleFn {
|
||||
name: data_type_name.to_string(),
|
||||
field_map: None,
|
||||
module: "".to_string(),
|
||||
arity: 1,
|
||||
location: Span::empty(),
|
||||
builtin: None,
|
||||
},
|
||||
),
|
||||
data_type_name,
|
||||
"",
|
||||
);
|
||||
|
||||
AirTree::call(func_var, void(), vec![value])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1020,19 +1104,177 @@ impl<'a> CodeGenerator<'a> {
|
|||
subject_tipo: &Arc<Type>,
|
||||
props: &mut ClauseProperties,
|
||||
) -> AirTree {
|
||||
assert!(!clauses.is_empty());
|
||||
assert!(
|
||||
!subject_tipo.is_void(),
|
||||
"WHY ARE YOU PATTERN MATCHING VOID???"
|
||||
);
|
||||
props.complex_clause = false;
|
||||
|
||||
if let Some((clause, rest_clauses)) = clauses.split_first() {
|
||||
todo!()
|
||||
let mut clause_then = self.build(&clause.then);
|
||||
|
||||
if let Some(guard) = &clause.guard {
|
||||
props.complex_clause = true;
|
||||
let clause_guard_name = format!(
|
||||
"__clause_guard_span_{}_{}",
|
||||
clause.location.start, clause.location.end
|
||||
);
|
||||
|
||||
let clause_guard_assign =
|
||||
AirTree::let_assignment(clause_guard_name, builder::handle_clause_guard(guard));
|
||||
|
||||
clause_then = clause_guard_assign.hoist_over(clause_then);
|
||||
}
|
||||
|
||||
match &mut props.specific_clause {
|
||||
SpecificClause::ConstrClause => {
|
||||
let data_type = build::lookup_data_type_by_tipo(&self.data_types, subject_tipo);
|
||||
|
||||
let (clause_cond, clause_assign) =
|
||||
self.clause_pattern(&clause.pattern, subject_tipo, props);
|
||||
|
||||
let clause_assign_hoisted = clause_assign.hoist_over(clause_then);
|
||||
|
||||
let complex_clause = props.complex_clause;
|
||||
|
||||
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: props.specific_clause.clone(),
|
||||
};
|
||||
|
||||
if let Some(data_type) = data_type {
|
||||
if data_type.constructors.len() > 1 {
|
||||
AirTree::clause(
|
||||
&props.original_subject_name,
|
||||
clause_cond,
|
||||
subject_tipo.clone(),
|
||||
clause_assign_hoisted,
|
||||
self.handle_each_clause(
|
||||
rest_clauses,
|
||||
final_clause,
|
||||
subject_tipo,
|
||||
&mut next_clause_props,
|
||||
),
|
||||
complex_clause,
|
||||
)
|
||||
} else {
|
||||
AirTree::wrap_clause(
|
||||
clause_assign_hoisted,
|
||||
self.handle_each_clause(
|
||||
rest_clauses,
|
||||
final_clause,
|
||||
subject_tipo,
|
||||
&mut next_clause_props,
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AirTree::clause(
|
||||
&props.original_subject_name,
|
||||
clause_cond,
|
||||
subject_tipo.clone(),
|
||||
clause_assign_hoisted,
|
||||
self.handle_each_clause(
|
||||
rest_clauses,
|
||||
final_clause,
|
||||
subject_tipo,
|
||||
&mut next_clause_props,
|
||||
),
|
||||
complex_clause,
|
||||
)
|
||||
}
|
||||
}
|
||||
SpecificClause::ListClause {
|
||||
current_index,
|
||||
defined_tails,
|
||||
} => {
|
||||
let Pattern::List { elements, .. } = &clause.pattern
|
||||
else { unreachable!() };
|
||||
|
||||
let tail_name = if *current_index == 0 {
|
||||
props.original_subject_name.clone()
|
||||
} else {
|
||||
format!(
|
||||
"tail_index_{}_span_{}_{}",
|
||||
*current_index,
|
||||
clause.pattern.location().start,
|
||||
clause.pattern.location().end
|
||||
)
|
||||
};
|
||||
|
||||
let next_tail_name = {
|
||||
let next_elements_len = match &rest_clauses[0].pattern {
|
||||
Pattern::List { elements, .. } => elements.len(),
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if (*current_index as usize) < next_elements_len {
|
||||
Some(format!(
|
||||
"tail_index_{}_span_{}_{}",
|
||||
*current_index,
|
||||
rest_clauses[0].pattern.location().start,
|
||||
rest_clauses[0].pattern.location().end
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if elements.len() > *current_index as usize {
|
||||
*current_index += 1;
|
||||
defined_tails.push(tail_name.clone());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
let complex_clause = props.complex_clause;
|
||||
|
||||
AirTree::list_clause(
|
||||
tail_name,
|
||||
subject_tipo.clone(),
|
||||
clause_assign_hoisted,
|
||||
self.handle_each_clause(
|
||||
clauses,
|
||||
final_clause,
|
||||
subject_tipo,
|
||||
&mut next_clause_props,
|
||||
),
|
||||
next_tail_name,
|
||||
complex_clause,
|
||||
);
|
||||
|
||||
todo!();
|
||||
}
|
||||
SpecificClause::TupleClause { .. } => todo!(),
|
||||
}
|
||||
} else {
|
||||
// handle final_clause
|
||||
props.final_clause = true;
|
||||
assert!(final_clause.guard.is_none());
|
||||
let clause_then = self.build(&final_clause.then);
|
||||
let (_, assignments) = self.clause_pattern(&final_clause.pattern, subject_tipo, props);
|
||||
let (condition, assignments) =
|
||||
self.clause_pattern(&final_clause.pattern, subject_tipo, props);
|
||||
|
||||
AirTree::hoist_over(assignments, clause_then)
|
||||
AirTree::finally(condition, assignments.hoist_over(clause_then))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1072,18 +1314,13 @@ impl<'a> CodeGenerator<'a> {
|
|||
Pattern::Discard { .. } => (AirTree::void(), AirTree::no_op()),
|
||||
Pattern::List { elements, tail, .. } => {
|
||||
let ClauseProperties {
|
||||
specific_clause:
|
||||
SpecificClause::ListClause {
|
||||
current_index: _,
|
||||
defined_tails,
|
||||
},
|
||||
clause_var_name: _,
|
||||
complex_clause: _,
|
||||
needs_constr_var: _,
|
||||
specific_clause: SpecificClause::ListClause { defined_tails, .. },
|
||||
complex_clause,
|
||||
original_subject_name: _,
|
||||
final_clause: _,
|
||||
..
|
||||
} = props
|
||||
else { unreachable!()};
|
||||
else { unreachable!() };
|
||||
|
||||
let list_elem_types = subject_tipo.get_inner_types();
|
||||
|
||||
|
@ -1116,7 +1353,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
let statement =
|
||||
self.nested_clause_condition(elem, list_elem_type, &mut elem_props);
|
||||
props.complex_clause = props.complex_clause || elem_props.complex_clause;
|
||||
*complex_clause = *complex_clause || elem_props.complex_clause;
|
||||
|
||||
(tail, elem_name, statement)
|
||||
})
|
||||
|
@ -1164,7 +1401,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
let statement =
|
||||
self.nested_clause_condition(elem, subject_tipo, &mut elem_props);
|
||||
props.complex_clause = props.complex_clause || elem_props.complex_clause;
|
||||
*complex_clause = *complex_clause || elem_props.complex_clause;
|
||||
|
||||
air_elems.push(statement);
|
||||
list_tail = Some((tail.to_string(), elem_name));
|
||||
|
@ -1183,7 +1420,123 @@ impl<'a> CodeGenerator<'a> {
|
|||
|
||||
(AirTree::void(), AirTree::UnhoistedSequence(sequence))
|
||||
}
|
||||
Pattern::Constructor { .. } => todo!(),
|
||||
Pattern::Constructor {
|
||||
name,
|
||||
arguments,
|
||||
constructor,
|
||||
..
|
||||
} => {
|
||||
if subject_tipo.is_bool() {
|
||||
(AirTree::bool(name == "True"), AirTree::no_op())
|
||||
} else {
|
||||
let data_type = build::lookup_data_type_by_tipo(&self.data_types, subject_tipo)
|
||||
.unwrap_or_else(|| {
|
||||
unreachable!(
|
||||
"Code Gen should have the definition for this constructor {}",
|
||||
name
|
||||
)
|
||||
});
|
||||
|
||||
assert!(!data_type.constructors.is_empty());
|
||||
|
||||
let (constr_index, _) = data_type
|
||||
.constructors
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, dt)| &dt.name == name)
|
||||
.unwrap();
|
||||
|
||||
let field_map = match constructor {
|
||||
PatternConstructor::Record { field_map, .. } => field_map.clone(),
|
||||
};
|
||||
|
||||
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
|
||||
|
||||
println!("tipo is {subject_tipo:#?}");
|
||||
|
||||
for (index, arg) in subject_tipo.arg_types().unwrap().iter().enumerate() {
|
||||
let field_type = arg.clone();
|
||||
type_map.insert(index, field_type);
|
||||
}
|
||||
|
||||
let fields = arguments
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, arg)| {
|
||||
let label = arg.label.clone().unwrap_or_default();
|
||||
|
||||
let field_index = if let Some(field_map) = &field_map {
|
||||
*field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&index)
|
||||
} else {
|
||||
index
|
||||
};
|
||||
|
||||
let field_name = match &arg.value {
|
||||
Pattern::Var { name, .. } => name.to_string(),
|
||||
Pattern::Assign { name, .. } => name.to_string(),
|
||||
Pattern::Discard { .. } => "_".to_string(),
|
||||
_ => format!(
|
||||
"field_{}_span_{}_{}",
|
||||
field_index,
|
||||
arg.value.location().start,
|
||||
arg.value.location().end
|
||||
),
|
||||
};
|
||||
|
||||
let arg_type = type_map.get(&field_index).unwrap_or_else(|| {
|
||||
unreachable!(
|
||||
"Missing type for field {} of constr {}",
|
||||
field_index, name
|
||||
)
|
||||
});
|
||||
|
||||
let mut field_props = ClauseProperties {
|
||||
clause_var_name: field_name.clone(),
|
||||
complex_clause: false,
|
||||
needs_constr_var: false,
|
||||
original_subject_name: field_name.clone(),
|
||||
final_clause: props.final_clause,
|
||||
specific_clause: props.specific_clause.clone(),
|
||||
};
|
||||
|
||||
let statement = self.nested_clause_condition(
|
||||
&arg.value,
|
||||
arg_type,
|
||||
&mut field_props,
|
||||
);
|
||||
|
||||
props.complex_clause =
|
||||
props.complex_clause || field_props.complex_clause;
|
||||
|
||||
(field_index, field_name, arg_type, statement)
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
let indices = fields
|
||||
.iter()
|
||||
.map(|(constr_index, name, tipo, _)| {
|
||||
(*constr_index, name.to_string(), (*tipo).clone())
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
let mut air_fields = fields.into_iter().map(|(_, _, _, val)| val).collect_vec();
|
||||
|
||||
let field_assign = AirTree::fields_expose(
|
||||
indices,
|
||||
false,
|
||||
AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
|
||||
);
|
||||
|
||||
let mut sequence = vec![field_assign];
|
||||
|
||||
sequence.append(&mut air_fields);
|
||||
|
||||
(
|
||||
AirTree::int(constr_index),
|
||||
AirTree::UnhoistedSequence(sequence),
|
||||
)
|
||||
}
|
||||
}
|
||||
Pattern::Tuple { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ pub enum Air {
|
|||
next_tail_name: Option<String>,
|
||||
complex_clause: bool,
|
||||
},
|
||||
WrapClause {},
|
||||
WrapClause,
|
||||
TupleClause {
|
||||
tipo: Arc<Type>,
|
||||
indices: IndexSet<(usize, String)>,
|
||||
|
@ -122,7 +122,7 @@ pub enum Air {
|
|||
tipo: Arc<Type>,
|
||||
},
|
||||
// Record Creation
|
||||
Record {
|
||||
Constr {
|
||||
tag: usize,
|
||||
tipo: Arc<Type>,
|
||||
count: usize,
|
||||
|
@ -246,7 +246,7 @@ impl Air {
|
|||
| Air::ClauseGuard { tipo, .. }
|
||||
| Air::If { tipo, .. }
|
||||
| Air::ListClauseGuard { tipo, .. }
|
||||
| Air::Record { tipo, .. }
|
||||
| Air::Constr { tipo, .. }
|
||||
| Air::RecordUpdate { tipo, .. }
|
||||
| Air::RecordAccess { tipo, .. }
|
||||
| Air::ListAccessor { tipo, .. }
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
use crate::builtins::bool;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{ast::Constant, tipo::Type};
|
||||
use crate::{
|
||||
ast::{BinOp, ClauseGuard, Constant, UnOp},
|
||||
tipo::Type,
|
||||
};
|
||||
|
||||
use super::tree::AirTree;
|
||||
|
||||
|
@ -15,3 +19,63 @@ pub fn constants_ir(literal: &Constant) -> AirTree {
|
|||
Constant::ByteArray { bytes, .. } => AirTree::byte_array(bytes.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_clause_guard(clause_guard: &ClauseGuard<Arc<Type>>) -> AirTree {
|
||||
match clause_guard {
|
||||
ClauseGuard::Not { value, .. } => {
|
||||
let val = handle_clause_guard(value);
|
||||
|
||||
AirTree::unop(UnOp::Not, val)
|
||||
}
|
||||
ClauseGuard::Equals { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::Eq, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::NotEquals { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::NotEq, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::GtInt { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::GtInt, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::GtEqInt { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::GtEqInt, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::LtInt { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::LtInt, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::LtEqInt { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::LtEqInt, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::Or { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::Or, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::And { left, right, .. } => {
|
||||
let left = handle_clause_guard(left);
|
||||
let right = handle_clause_guard(right);
|
||||
|
||||
AirTree::binop(BinOp::And, bool(), left, right)
|
||||
}
|
||||
ClauseGuard::Var { tipo, name, .. } => AirTree::local_var(name, tipo.clone()),
|
||||
ClauseGuard::Constant(constant) => constants_ir(constant),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
|
|||
use crate::{
|
||||
ast::{BinOp, Span, UnOp},
|
||||
builtins::{data, list, void},
|
||||
gen_uplc::air,
|
||||
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
||||
};
|
||||
|
||||
|
@ -146,6 +147,7 @@ pub enum AirExpression {
|
|||
When {
|
||||
tipo: Arc<Type>,
|
||||
subject_name: String,
|
||||
subject: Box<AirTree>,
|
||||
clauses: Box<AirTree>,
|
||||
},
|
||||
Clause {
|
||||
|
@ -396,10 +398,16 @@ impl AirTree {
|
|||
hoisted_over: None,
|
||||
}
|
||||
}
|
||||
pub fn when(subject_name: impl ToString, tipo: Arc<Type>, clauses: AirTree) -> AirTree {
|
||||
pub fn when(
|
||||
subject_name: impl ToString,
|
||||
tipo: Arc<Type>,
|
||||
subject: AirTree,
|
||||
clauses: AirTree,
|
||||
) -> AirTree {
|
||||
AirTree::Expression(AirExpression::When {
|
||||
tipo,
|
||||
subject_name: subject_name.to_string(),
|
||||
subject: subject.into(),
|
||||
clauses: clauses.into(),
|
||||
})
|
||||
}
|
||||
|
@ -647,12 +655,12 @@ impl AirTree {
|
|||
pub fn list_empty(list: AirTree) -> AirTree {
|
||||
AirTree::Expression(AirExpression::ListEmpty { list: list.into() })
|
||||
}
|
||||
pub fn hoist_over(mut assignment: AirTree, next_exp: AirTree) -> AirTree {
|
||||
match &mut assignment {
|
||||
pub fn hoist_over(mut self, next_exp: AirTree) -> AirTree {
|
||||
match &mut self {
|
||||
AirTree::Statement { hoisted_over, .. } => {
|
||||
assert!(hoisted_over.is_none());
|
||||
*hoisted_over = Some(next_exp.into());
|
||||
assignment
|
||||
self
|
||||
}
|
||||
|
||||
AirTree::Expression(_) => {
|
||||
|
@ -661,7 +669,7 @@ impl AirTree {
|
|||
AirTree::UnhoistedSequence(seq) => {
|
||||
let mut final_exp = next_exp;
|
||||
while let Some(assign) = seq.pop() {
|
||||
final_exp = Self::hoist_over(assign, final_exp);
|
||||
final_exp = assign.hoist_over(final_exp);
|
||||
}
|
||||
final_exp
|
||||
}
|
||||
|
@ -698,7 +706,7 @@ impl AirTree {
|
|||
"__list_to_check",
|
||||
void(),
|
||||
AirTree::void(),
|
||||
AirTree::hoist_over(assign, next_call),
|
||||
assign.hoist_over(next_call),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
@ -713,7 +721,13 @@ impl AirTree {
|
|||
)
|
||||
}
|
||||
|
||||
fn to_vec(&self, air_vec: &mut Vec<Air>) {
|
||||
pub fn to_vec(&self) -> Vec<Air> {
|
||||
let mut air_vec = vec![];
|
||||
self.create_air_vec(&mut air_vec);
|
||||
air_vec
|
||||
}
|
||||
|
||||
fn create_air_vec(&self, air_vec: &mut Vec<Air>) {
|
||||
match self {
|
||||
AirTree::Statement {
|
||||
statement,
|
||||
|
@ -722,7 +736,7 @@ impl AirTree {
|
|||
match statement {
|
||||
AirStatement::Let { value, name } => {
|
||||
air_vec.push(Air::Let { name: name.clone() });
|
||||
value.to_vec(air_vec);
|
||||
value.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::DefineFunc {
|
||||
func_name,
|
||||
|
@ -739,7 +753,7 @@ impl AirTree {
|
|||
recursive: *recursive,
|
||||
variant_name: variant_name.clone(),
|
||||
});
|
||||
func_body.to_vec(air_vec);
|
||||
func_body.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::AssertConstr {
|
||||
constr,
|
||||
|
@ -748,18 +762,347 @@ impl AirTree {
|
|||
air_vec.push(Air::AssertConstr {
|
||||
constr_index: *constr_index,
|
||||
});
|
||||
constr.to_vec(air_vec);
|
||||
constr.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::AssertBool { is_true, value } => {
|
||||
air_vec.push(Air::AssertBool { is_true: *is_true });
|
||||
value.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::FieldsExpose {
|
||||
indices,
|
||||
check_last_item,
|
||||
record,
|
||||
} => {
|
||||
air_vec.push(Air::FieldsExpose {
|
||||
indices: indices.clone(),
|
||||
check_last_item: *check_last_item,
|
||||
});
|
||||
record.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::ListAccessor {
|
||||
tipo,
|
||||
names,
|
||||
tail,
|
||||
check_last_item,
|
||||
list,
|
||||
} => {
|
||||
air_vec.push(Air::ListAccessor {
|
||||
tipo: tipo.clone(),
|
||||
names: names.clone(),
|
||||
tail: *tail,
|
||||
check_last_item: *check_last_item,
|
||||
});
|
||||
list.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::ListExpose {
|
||||
tipo,
|
||||
tail_head_names,
|
||||
tail,
|
||||
list,
|
||||
} => {
|
||||
air_vec.push(Air::ListExpose {
|
||||
tipo: tipo.clone(),
|
||||
tail_head_names: tail_head_names.clone(),
|
||||
tail: tail.clone(),
|
||||
});
|
||||
list.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::TupleAccessor {
|
||||
names,
|
||||
tipo,
|
||||
check_last_item,
|
||||
tuple,
|
||||
} => {
|
||||
air_vec.push(Air::TupleAccessor {
|
||||
names: names.clone(),
|
||||
tipo: tipo.clone(),
|
||||
check_last_item: *check_last_item,
|
||||
});
|
||||
tuple.create_air_vec(air_vec);
|
||||
}
|
||||
AirStatement::NoOp => {
|
||||
air_vec.push(Air::NoOp);
|
||||
}
|
||||
AirStatement::AssertBool { .. } => todo!(),
|
||||
AirStatement::FieldsExpose { .. } => todo!(),
|
||||
AirStatement::ListAccessor { .. } => todo!(),
|
||||
AirStatement::ListExpose { .. } => todo!(),
|
||||
AirStatement::TupleAccessor { .. } => todo!(),
|
||||
AirStatement::NoOp { .. } => todo!(),
|
||||
};
|
||||
exp.to_vec(air_vec);
|
||||
exp.create_air_vec(air_vec);
|
||||
}
|
||||
AirTree::Expression(_) => todo!(),
|
||||
AirTree::Expression(exp) => match exp {
|
||||
AirExpression::Int { value } => air_vec.push(Air::Int {
|
||||
value: value.clone(),
|
||||
}),
|
||||
AirExpression::String { value } => air_vec.push(Air::String {
|
||||
value: value.clone(),
|
||||
}),
|
||||
AirExpression::ByteArray { bytes } => air_vec.push(Air::ByteArray {
|
||||
bytes: bytes.clone(),
|
||||
}),
|
||||
AirExpression::Bool { value } => air_vec.push(Air::Bool { value: *value }),
|
||||
AirExpression::List { tipo, tail, items } => {
|
||||
air_vec.push(Air::List {
|
||||
count: items.len(),
|
||||
tipo: tipo.clone(),
|
||||
tail: *tail,
|
||||
});
|
||||
for item in items {
|
||||
item.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::Tuple { tipo, items } => {
|
||||
air_vec.push(Air::Tuple {
|
||||
tipo: tipo.clone(),
|
||||
count: items.len(),
|
||||
});
|
||||
for item in items {
|
||||
item.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::Void => air_vec.push(Air::Void),
|
||||
AirExpression::Var {
|
||||
constructor,
|
||||
name,
|
||||
variant_name,
|
||||
} => air_vec.push(Air::Var {
|
||||
constructor: constructor.clone(),
|
||||
name: name.clone(),
|
||||
variant_name: variant_name.clone(),
|
||||
}),
|
||||
AirExpression::Call { tipo, func, args } => {
|
||||
air_vec.push(Air::Call {
|
||||
count: args.len(),
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
func.create_air_vec(air_vec);
|
||||
for arg in args {
|
||||
arg.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::Fn { params, func_body } => {
|
||||
air_vec.push(Air::Fn {
|
||||
params: params.clone(),
|
||||
});
|
||||
func_body.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::Builtin { func, tipo, args } => {
|
||||
air_vec.push(Air::Builtin {
|
||||
count: args.len(),
|
||||
func: *func,
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
|
||||
for arg in args {
|
||||
arg.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::BinOp {
|
||||
name,
|
||||
tipo,
|
||||
left,
|
||||
right,
|
||||
} => {
|
||||
air_vec.push(Air::BinOp {
|
||||
name: name.clone(),
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
left.create_air_vec(air_vec);
|
||||
right.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::UnOp { op, arg } => {
|
||||
air_vec.push(Air::UnOp { op: *op });
|
||||
arg.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::UnWrapData { tipo, value } => {
|
||||
air_vec.push(Air::UnWrapData { tipo: tipo.clone() });
|
||||
value.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::WrapData { tipo, value } => {
|
||||
air_vec.push(Air::WrapData { tipo: tipo.clone() });
|
||||
value.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::When {
|
||||
tipo,
|
||||
subject_name,
|
||||
subject,
|
||||
clauses,
|
||||
} => {
|
||||
air_vec.push(Air::When {
|
||||
tipo: tipo.clone(),
|
||||
subject_name: subject_name.clone(),
|
||||
});
|
||||
subject.create_air_vec(air_vec);
|
||||
clauses.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::Clause {
|
||||
tipo,
|
||||
subject_name,
|
||||
complex_clause,
|
||||
pattern,
|
||||
then,
|
||||
otherwise,
|
||||
} => {
|
||||
air_vec.push(Air::Clause {
|
||||
tipo: tipo.clone(),
|
||||
subject_name: subject_name.clone(),
|
||||
complex_clause: *complex_clause,
|
||||
});
|
||||
pattern.create_air_vec(air_vec);
|
||||
then.create_air_vec(air_vec);
|
||||
otherwise.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::ListClause {
|
||||
tipo,
|
||||
tail_name,
|
||||
next_tail_name,
|
||||
complex_clause,
|
||||
then,
|
||||
otherwise,
|
||||
} => {
|
||||
air_vec.push(Air::ListClause {
|
||||
tipo: tipo.clone(),
|
||||
tail_name: tail_name.clone(),
|
||||
next_tail_name: next_tail_name.clone(),
|
||||
complex_clause: *complex_clause,
|
||||
});
|
||||
then.create_air_vec(air_vec);
|
||||
otherwise.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::WrapClause { then, otherwise } => {
|
||||
air_vec.push(Air::WrapClause);
|
||||
then.create_air_vec(air_vec);
|
||||
otherwise.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::TupleClause {
|
||||
tipo,
|
||||
indices,
|
||||
predefined_indices,
|
||||
subject_name,
|
||||
type_count,
|
||||
complex_clause,
|
||||
then,
|
||||
otherwise,
|
||||
} => {
|
||||
air_vec.push(Air::TupleClause {
|
||||
tipo: tipo.clone(),
|
||||
indices: indices.clone(),
|
||||
predefined_indices: predefined_indices.clone(),
|
||||
subject_name: subject_name.clone(),
|
||||
count: *type_count,
|
||||
complex_clause: *complex_clause,
|
||||
});
|
||||
then.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 } => {
|
||||
air_vec.push(Air::Finally);
|
||||
pattern.create_air_vec(air_vec);
|
||||
then.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::If {
|
||||
tipo,
|
||||
pattern,
|
||||
then,
|
||||
otherwise,
|
||||
} => {
|
||||
air_vec.push(Air::If { tipo: tipo.clone() });
|
||||
pattern.create_air_vec(air_vec);
|
||||
then.create_air_vec(air_vec);
|
||||
otherwise.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::Constr { tag, tipo, args } => {
|
||||
air_vec.push(Air::Constr {
|
||||
tag: *tag,
|
||||
tipo: tipo.clone(),
|
||||
count: args.len(),
|
||||
});
|
||||
for arg in args {
|
||||
arg.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::RecordUpdate {
|
||||
highest_index,
|
||||
indices,
|
||||
tipo,
|
||||
record,
|
||||
args,
|
||||
} => {
|
||||
air_vec.push(Air::RecordUpdate {
|
||||
highest_index: *highest_index,
|
||||
indices: indices.clone(),
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
record.create_air_vec(air_vec);
|
||||
for arg in args {
|
||||
arg.create_air_vec(air_vec);
|
||||
}
|
||||
}
|
||||
AirExpression::RecordAccess {
|
||||
field_index,
|
||||
tipo,
|
||||
record,
|
||||
} => {
|
||||
air_vec.push(Air::RecordAccess {
|
||||
record_index: *field_index,
|
||||
tipo: tipo.clone(),
|
||||
});
|
||||
record.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::TupleIndex {
|
||||
tipo,
|
||||
tuple_index,
|
||||
tuple,
|
||||
} => {
|
||||
air_vec.push(Air::TupleIndex {
|
||||
tipo: tipo.clone(),
|
||||
tuple_index: *tuple_index,
|
||||
});
|
||||
tuple.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::ErrorTerm { tipo } => {
|
||||
air_vec.push(Air::ErrorTerm { tipo: tipo.clone() })
|
||||
}
|
||||
AirExpression::Trace { tipo, msg, then } => {
|
||||
air_vec.push(Air::Trace { tipo: tipo.clone() });
|
||||
msg.create_air_vec(air_vec);
|
||||
then.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::FieldsEmpty { constr } => {
|
||||
air_vec.push(Air::FieldsEmpty);
|
||||
constr.create_air_vec(air_vec);
|
||||
}
|
||||
AirExpression::ListEmpty { list } => {
|
||||
air_vec.push(Air::ListEmpty);
|
||||
list.create_air_vec(air_vec);
|
||||
}
|
||||
},
|
||||
AirTree::UnhoistedSequence(_) => {
|
||||
unreachable!("FIRST RESOLVE ALL UNHOISTED SEQUENCES")
|
||||
}
|
||||
|
|
|
@ -180,6 +180,14 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_2_tuple(&self) -> bool {
|
||||
match self {
|
||||
Type::Var { tipo } => tipo.borrow().is_2_tuple(),
|
||||
Type::Tuple { elems } => elems.len() == 2,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_data(&self) -> bool {
|
||||
match self {
|
||||
Self::App { module, name, .. } => "Data" == name && module.is_empty(),
|
||||
|
@ -483,6 +491,13 @@ impl TypeVar {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_2_tuple(&self) -> bool {
|
||||
match self {
|
||||
Self::Link { tipo } => tipo.is_2_tuple(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_data(&self) -> bool {
|
||||
match self {
|
||||
Self::Link { tipo } => tipo.is_data(),
|
||||
|
|
Loading…
Reference in New Issue