checkpoint
This commit is contained in:
parent
0854d71836
commit
f94c8213b6
|
@ -95,7 +95,10 @@ impl ClauseProperties {
|
||||||
original_subject_name: subject_name,
|
original_subject_name: subject_name,
|
||||||
final_clause: false,
|
final_clause: false,
|
||||||
needs_constr_var: false,
|
needs_constr_var: false,
|
||||||
specific_clause: SpecificClause::ConstrClause,
|
specific_clause: SpecificClause::ListClause {
|
||||||
|
current_index: 0,
|
||||||
|
defined_tails: vec![],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else if t.is_tuple() {
|
} else if t.is_tuple() {
|
||||||
ClauseProperties {
|
ClauseProperties {
|
||||||
|
|
|
@ -21,8 +21,8 @@ use crate::{
|
||||||
gen_uplc::{
|
gen_uplc::{
|
||||||
air::Air,
|
air::Air,
|
||||||
builder::{
|
builder::{
|
||||||
self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey,
|
self as build, lookup_data_type_by_tipo, AssignmentProperties, ClauseProperties,
|
||||||
SpecificClause,
|
DataTypeKey, FunctionAccessKey, SpecificClause,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tipo::{
|
tipo::{
|
||||||
|
@ -91,8 +91,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> {
|
pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> {
|
||||||
let mut air_tree = self.build(test_body);
|
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);
|
||||||
|
println!("{:#?}", air_tree.to_vec());
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -116,7 +118,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
while let Some(expression) = expressions.pop() {
|
while let Some(expression) = expressions.pop() {
|
||||||
let exp_tree = self.build(&expression);
|
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
|
last_exp
|
||||||
}
|
}
|
||||||
|
@ -309,7 +311,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
AirTree::hoist_over(assignment, clause_then)
|
assignment.hoist_over(clause_then)
|
||||||
} else {
|
} else {
|
||||||
clauses = if subject.tipo().is_list() {
|
clauses = if subject.tipo().is_list() {
|
||||||
build::rearrange_clauses(clauses)
|
build::rearrange_clauses(clauses)
|
||||||
|
@ -343,9 +345,14 @@ impl<'a> CodeGenerator<'a> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject));
|
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::int(expected_int),
|
||||||
AirTree::local_var(name, int()),
|
AirTree::local_var(name, int()),
|
||||||
);
|
);
|
||||||
AirTree::assert_bool(true, AirTree::hoist_over(assignment, expect))
|
AirTree::assert_bool(true, assignment.hoist_over(expect))
|
||||||
} else {
|
} else {
|
||||||
unreachable!("Code Gen should never reach here")
|
unreachable!("Code Gen should never reach here")
|
||||||
}
|
}
|
||||||
|
@ -524,13 +531,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let val = AirTree::local_var(name, tipo.clone());
|
let val = AirTree::local_var(name, tipo.clone());
|
||||||
|
|
||||||
if tipo.is_primitive() {
|
if tipo.is_primitive() {
|
||||||
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val))
|
AirTree::let_assignment(name, assignment.hoist_over(val))
|
||||||
} else {
|
} else {
|
||||||
let expect =
|
let expect =
|
||||||
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
|
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
|
||||||
let assign =
|
let assign = AirTree::let_assignment("_", assignment.hoist_over(expect));
|
||||||
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect));
|
AirTree::let_assignment(name, assign.hoist_over(val))
|
||||||
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AirTree::let_assignment(name, value)
|
AirTree::let_assignment(name, value)
|
||||||
|
@ -551,13 +557,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let assignment = AirTree::let_assignment(name, value);
|
let assignment = AirTree::let_assignment(name, value);
|
||||||
let val = AirTree::local_var(name, tipo.clone());
|
let val = AirTree::local_var(name, tipo.clone());
|
||||||
if tipo.is_primitive() {
|
if tipo.is_primitive() {
|
||||||
AirTree::let_assignment(name, AirTree::hoist_over(assignment, val))
|
AirTree::let_assignment(name, assignment.hoist_over(val))
|
||||||
} else {
|
} else {
|
||||||
let expect =
|
let expect =
|
||||||
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
|
self.expect_type(tipo, val.clone(), &mut index_map, pattern.location());
|
||||||
let assign =
|
let assign = AirTree::let_assignment("_", assignment.hoist_over(expect));
|
||||||
AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect));
|
AirTree::let_assignment(name, assign.hoist_over(val))
|
||||||
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
|
|
||||||
}
|
}
|
||||||
} else if !props.remove_unused {
|
} else if !props.remove_unused {
|
||||||
AirTree::let_assignment(name, value)
|
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();
|
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
|
// This `value` is either value param that was passed in or
|
||||||
// local var
|
// local var
|
||||||
sequence.push(AirTree::fields_expose(indices, false, value));
|
sequence.push(AirTree::fields_expose(indices, props.full_check, value));
|
||||||
|
|
||||||
sequence.append(
|
sequence.append(
|
||||||
&mut fields
|
&mut fields
|
||||||
|
@ -877,7 +881,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
// This `value` is either value param that was passed in or
|
// This `value` is either value param that was passed in or
|
||||||
// local var
|
// 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());
|
sequence.append(&mut elems.into_iter().map(|(_, field)| field).collect_vec());
|
||||||
|
|
||||||
|
@ -930,14 +939,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
location,
|
location,
|
||||||
);
|
);
|
||||||
|
|
||||||
let anon_func_body = AirTree::hoist_over(
|
let anon_func_body = AirTree::UnhoistedSequence(vec![
|
||||||
AirTree::UnhoistedSequence(vec![
|
|
||||||
tuple_access,
|
tuple_access,
|
||||||
AirTree::let_assignment("_", expect_fst),
|
AirTree::let_assignment("_", expect_fst),
|
||||||
AirTree::let_assignment("_", expect_snd),
|
AirTree::let_assignment("_", expect_snd),
|
||||||
]),
|
])
|
||||||
AirTree::void(),
|
.hoist_over(AirTree::void());
|
||||||
);
|
|
||||||
|
|
||||||
let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body);
|
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],
|
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() {
|
} else if tipo.is_list() {
|
||||||
assert!(!tipo.get_inner_types().is_empty());
|
assert!(!tipo.get_inner_types().is_empty());
|
||||||
let inner_list_type = &tipo.get_inner_types()[0];
|
let inner_list_type = &tipo.get_inner_types()[0];
|
||||||
|
@ -981,7 +988,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let anon_func_body =
|
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);
|
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],
|
vec![AirTree::local_var(list_name, tipo.clone()), unwrap_function],
|
||||||
);
|
);
|
||||||
|
|
||||||
AirTree::hoist_over(assign, func_call)
|
assign.hoist_over(func_call)
|
||||||
} else {
|
} 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!()
|
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>,
|
subject_tipo: &Arc<Type>,
|
||||||
props: &mut ClauseProperties,
|
props: &mut ClauseProperties,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
assert!(!clauses.is_empty());
|
assert!(
|
||||||
|
!subject_tipo.is_void(),
|
||||||
|
"WHY ARE YOU PATTERN MATCHING VOID???"
|
||||||
|
);
|
||||||
props.complex_clause = false;
|
props.complex_clause = false;
|
||||||
|
|
||||||
if let Some((clause, rest_clauses)) = clauses.split_first() {
|
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 {
|
} else {
|
||||||
// handle final_clause
|
// handle final_clause
|
||||||
props.final_clause = true;
|
props.final_clause = true;
|
||||||
assert!(final_clause.guard.is_none());
|
assert!(final_clause.guard.is_none());
|
||||||
let clause_then = self.build(&final_clause.then);
|
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::Discard { .. } => (AirTree::void(), AirTree::no_op()),
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
let ClauseProperties {
|
let ClauseProperties {
|
||||||
specific_clause:
|
specific_clause: SpecificClause::ListClause { defined_tails, .. },
|
||||||
SpecificClause::ListClause {
|
complex_clause,
|
||||||
current_index: _,
|
|
||||||
defined_tails,
|
|
||||||
},
|
|
||||||
clause_var_name: _,
|
|
||||||
complex_clause: _,
|
|
||||||
needs_constr_var: _,
|
|
||||||
original_subject_name: _,
|
original_subject_name: _,
|
||||||
final_clause: _,
|
final_clause: _,
|
||||||
|
..
|
||||||
} = props
|
} = props
|
||||||
else { unreachable!()};
|
else { unreachable!() };
|
||||||
|
|
||||||
let list_elem_types = subject_tipo.get_inner_types();
|
let list_elem_types = subject_tipo.get_inner_types();
|
||||||
|
|
||||||
|
@ -1116,7 +1353,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let statement =
|
let statement =
|
||||||
self.nested_clause_condition(elem, list_elem_type, &mut elem_props);
|
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)
|
(tail, elem_name, statement)
|
||||||
})
|
})
|
||||||
|
@ -1164,7 +1401,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let statement =
|
let statement =
|
||||||
self.nested_clause_condition(elem, subject_tipo, &mut elem_props);
|
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);
|
air_elems.push(statement);
|
||||||
list_tail = Some((tail.to_string(), elem_name));
|
list_tail = Some((tail.to_string(), elem_name));
|
||||||
|
@ -1183,7 +1420,123 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
(AirTree::void(), AirTree::UnhoistedSequence(sequence))
|
(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!(),
|
Pattern::Tuple { .. } => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ pub enum Air {
|
||||||
next_tail_name: Option<String>,
|
next_tail_name: Option<String>,
|
||||||
complex_clause: bool,
|
complex_clause: bool,
|
||||||
},
|
},
|
||||||
WrapClause {},
|
WrapClause,
|
||||||
TupleClause {
|
TupleClause {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
indices: IndexSet<(usize, String)>,
|
indices: IndexSet<(usize, String)>,
|
||||||
|
@ -122,7 +122,7 @@ pub enum Air {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
// Record Creation
|
// Record Creation
|
||||||
Record {
|
Constr {
|
||||||
tag: usize,
|
tag: usize,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
@ -246,7 +246,7 @@ impl Air {
|
||||||
| Air::ClauseGuard { tipo, .. }
|
| Air::ClauseGuard { tipo, .. }
|
||||||
| Air::If { tipo, .. }
|
| Air::If { tipo, .. }
|
||||||
| Air::ListClauseGuard { tipo, .. }
|
| Air::ListClauseGuard { tipo, .. }
|
||||||
| Air::Record { tipo, .. }
|
| Air::Constr { tipo, .. }
|
||||||
| Air::RecordUpdate { tipo, .. }
|
| Air::RecordUpdate { tipo, .. }
|
||||||
| Air::RecordAccess { tipo, .. }
|
| Air::RecordAccess { tipo, .. }
|
||||||
| Air::ListAccessor { tipo, .. }
|
| Air::ListAccessor { tipo, .. }
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
use crate::builtins::bool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{ast::Constant, tipo::Type};
|
use crate::{
|
||||||
|
ast::{BinOp, ClauseGuard, Constant, UnOp},
|
||||||
|
tipo::Type,
|
||||||
|
};
|
||||||
|
|
||||||
use super::tree::AirTree;
|
use super::tree::AirTree;
|
||||||
|
|
||||||
|
@ -15,3 +19,63 @@ pub fn constants_ir(literal: &Constant) -> AirTree {
|
||||||
Constant::ByteArray { bytes, .. } => AirTree::byte_array(bytes.clone()),
|
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::{
|
use crate::{
|
||||||
ast::{BinOp, Span, UnOp},
|
ast::{BinOp, Span, UnOp},
|
||||||
builtins::{data, list, void},
|
builtins::{data, list, void},
|
||||||
|
gen_uplc::air,
|
||||||
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,6 +147,7 @@ pub enum AirExpression {
|
||||||
When {
|
When {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
subject_name: String,
|
subject_name: String,
|
||||||
|
subject: Box<AirTree>,
|
||||||
clauses: Box<AirTree>,
|
clauses: Box<AirTree>,
|
||||||
},
|
},
|
||||||
Clause {
|
Clause {
|
||||||
|
@ -396,10 +398,16 @@ impl AirTree {
|
||||||
hoisted_over: None,
|
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 {
|
AirTree::Expression(AirExpression::When {
|
||||||
tipo,
|
tipo,
|
||||||
subject_name: subject_name.to_string(),
|
subject_name: subject_name.to_string(),
|
||||||
|
subject: subject.into(),
|
||||||
clauses: clauses.into(),
|
clauses: clauses.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -647,12 +655,12 @@ impl AirTree {
|
||||||
pub fn list_empty(list: AirTree) -> AirTree {
|
pub fn list_empty(list: AirTree) -> AirTree {
|
||||||
AirTree::Expression(AirExpression::ListEmpty { list: list.into() })
|
AirTree::Expression(AirExpression::ListEmpty { list: list.into() })
|
||||||
}
|
}
|
||||||
pub fn hoist_over(mut assignment: AirTree, next_exp: AirTree) -> AirTree {
|
pub fn hoist_over(mut self, next_exp: AirTree) -> AirTree {
|
||||||
match &mut assignment {
|
match &mut self {
|
||||||
AirTree::Statement { hoisted_over, .. } => {
|
AirTree::Statement { hoisted_over, .. } => {
|
||||||
assert!(hoisted_over.is_none());
|
assert!(hoisted_over.is_none());
|
||||||
*hoisted_over = Some(next_exp.into());
|
*hoisted_over = Some(next_exp.into());
|
||||||
assignment
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
AirTree::Expression(_) => {
|
AirTree::Expression(_) => {
|
||||||
|
@ -661,7 +669,7 @@ impl AirTree {
|
||||||
AirTree::UnhoistedSequence(seq) => {
|
AirTree::UnhoistedSequence(seq) => {
|
||||||
let mut final_exp = next_exp;
|
let mut final_exp = next_exp;
|
||||||
while let Some(assign) = seq.pop() {
|
while let Some(assign) = seq.pop() {
|
||||||
final_exp = Self::hoist_over(assign, final_exp);
|
final_exp = assign.hoist_over(final_exp);
|
||||||
}
|
}
|
||||||
final_exp
|
final_exp
|
||||||
}
|
}
|
||||||
|
@ -698,7 +706,7 @@ impl AirTree {
|
||||||
"__list_to_check",
|
"__list_to_check",
|
||||||
void(),
|
void(),
|
||||||
AirTree::void(),
|
AirTree::void(),
|
||||||
AirTree::hoist_over(assign, next_call),
|
assign.hoist_over(next_call),
|
||||||
None,
|
None,
|
||||||
false,
|
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 {
|
match self {
|
||||||
AirTree::Statement {
|
AirTree::Statement {
|
||||||
statement,
|
statement,
|
||||||
|
@ -722,7 +736,7 @@ impl AirTree {
|
||||||
match statement {
|
match statement {
|
||||||
AirStatement::Let { value, name } => {
|
AirStatement::Let { value, name } => {
|
||||||
air_vec.push(Air::Let { name: name.clone() });
|
air_vec.push(Air::Let { name: name.clone() });
|
||||||
value.to_vec(air_vec);
|
value.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirStatement::DefineFunc {
|
AirStatement::DefineFunc {
|
||||||
func_name,
|
func_name,
|
||||||
|
@ -739,7 +753,7 @@ impl AirTree {
|
||||||
recursive: *recursive,
|
recursive: *recursive,
|
||||||
variant_name: variant_name.clone(),
|
variant_name: variant_name.clone(),
|
||||||
});
|
});
|
||||||
func_body.to_vec(air_vec);
|
func_body.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirStatement::AssertConstr {
|
AirStatement::AssertConstr {
|
||||||
constr,
|
constr,
|
||||||
|
@ -748,18 +762,347 @@ impl AirTree {
|
||||||
air_vec.push(Air::AssertConstr {
|
air_vec.push(Air::AssertConstr {
|
||||||
constr_index: *constr_index,
|
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(_) => {
|
AirTree::UnhoistedSequence(_) => {
|
||||||
unreachable!("FIRST RESOLVE ALL UNHOISTED SEQUENCES")
|
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 {
|
pub fn is_data(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::App { module, name, .. } => "Data" == name && module.is_empty(),
|
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 {
|
pub fn is_data(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Link { tipo } => tipo.is_data(),
|
Self::Link { tipo } => tipo.is_data(),
|
||||||
|
|
Loading…
Reference in New Issue