checkpoint
This commit is contained in:
parent
389699f485
commit
c6f90a999b
|
@ -38,8 +38,8 @@ use self::{
|
||||||
air::Air,
|
air::Air,
|
||||||
builder::{
|
builder::{
|
||||||
cast_validator_args, convert_type_to_data, lookup_data_type_by_tipo, modify_self_calls,
|
cast_validator_args, convert_type_to_data, lookup_data_type_by_tipo, modify_self_calls,
|
||||||
rearrange_clauses, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey,
|
rearrange_list_clauses, AssignmentProperties, ClauseProperties, DataTypeKey,
|
||||||
UserFunction,
|
FunctionAccessKey, UserFunction,
|
||||||
},
|
},
|
||||||
tree::{AirExpression, AirTree, TreePath},
|
tree::{AirExpression, AirTree, TreePath},
|
||||||
};
|
};
|
||||||
|
@ -218,9 +218,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::Sequence { expressions, .. } | TypedExpr::Pipeline { expressions, .. } => {
|
TypedExpr::Sequence { expressions, .. } | TypedExpr::Pipeline { expressions, .. } => {
|
||||||
let mut expressions = expressions.clone();
|
let mut expressions = expressions.clone();
|
||||||
|
|
||||||
let mut last_exp = self.build(&expressions.pop().unwrap_or_else(|| {
|
assert!(
|
||||||
unreachable!("Sequence or Pipeline should have at least one expression")
|
!expressions.is_empty(),
|
||||||
}));
|
"Sequence or Pipeline should have at least one expression"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut last_exp = self.build(&expressions.pop().unwrap_or_else(|| unreachable!()));
|
||||||
|
|
||||||
while let Some(expression) = expressions.pop() {
|
while let Some(expression) = expressions.pop() {
|
||||||
let exp_tree = self.build(&expression);
|
let exp_tree = self.build(&expression);
|
||||||
|
@ -276,8 +279,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let Some(data_type) = lookup_data_type_by_tipo(&self.data_types, tipo)
|
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo)
|
||||||
else {unreachable!("Creating a record with no record definition.")};
|
.expect("Creating a record with no record definition.");
|
||||||
|
|
||||||
let (constr_index, _) = data_type
|
let (constr_index, _) = data_type
|
||||||
.constructors
|
.constructors
|
||||||
|
@ -299,7 +302,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!("Expected a function type with arguments")};
|
let fun_arg_types = fun
|
||||||
|
.tipo()
|
||||||
|
.arg_types()
|
||||||
|
.expect("Expected a function type with arguments");
|
||||||
|
|
||||||
|
assert!(args.len() == fun_arg_types.len());
|
||||||
|
|
||||||
let func_args = args
|
let func_args = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -331,7 +339,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let ValueConstructorVariant::ModuleFn { builtin, .. } = &value.variant else {unreachable!("Missing module function definition")};
|
let ValueConstructorVariant::ModuleFn { builtin, .. } = &value.variant else {unreachable!("Missing module function definition")};
|
||||||
|
|
||||||
let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!("Expected a function type with arguments")};
|
let fun_arg_types = fun
|
||||||
|
.tipo()
|
||||||
|
.arg_types()
|
||||||
|
.expect("Expected a function type with arguments");
|
||||||
|
|
||||||
|
assert!(args.len() == fun_arg_types.len());
|
||||||
|
|
||||||
let func_args = args
|
let func_args = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -353,7 +366,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!("Expected a function type with arguments")};
|
let fun_arg_types = fun
|
||||||
|
.tipo()
|
||||||
|
.arg_types()
|
||||||
|
.expect("Expected a function type with arguments");
|
||||||
|
|
||||||
|
assert!(args.len() == fun_arg_types.len());
|
||||||
|
|
||||||
let func_args = args
|
let func_args = args
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -447,7 +465,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
assignment.hoist_over(clause_then)
|
assignment.hoist_over(clause_then)
|
||||||
} else {
|
} else {
|
||||||
clauses = if subject.tipo().is_list() {
|
clauses = if subject.tipo().is_list() {
|
||||||
rearrange_clauses(clauses)
|
rearrange_list_clauses(clauses)
|
||||||
} else {
|
} else {
|
||||||
clauses
|
clauses
|
||||||
};
|
};
|
||||||
|
@ -478,6 +496,7 @@ 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(
|
let when_assign = AirTree::when(
|
||||||
subject_name,
|
subject_name,
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
|
@ -535,9 +554,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
module: module_name.clone(),
|
module: module_name.clone(),
|
||||||
constructors_count: data_type
|
constructors_count: data_type
|
||||||
.unwrap_or_else(|| {
|
.expect("Created a module type without a definition?")
|
||||||
unreachable!("Created a module type without a definition?")
|
|
||||||
})
|
|
||||||
.constructors
|
.constructors
|
||||||
.len() as u16,
|
.len() as u16,
|
||||||
},
|
},
|
||||||
|
@ -552,6 +569,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let type_info = self.module_types.get(module_name).unwrap();
|
let type_info = self.module_types.get(module_name).unwrap();
|
||||||
|
|
||||||
let value = type_info.values.get(name).unwrap();
|
let value = type_info.values.get(name).unwrap();
|
||||||
|
|
||||||
if let Some(_func) = func {
|
if let Some(_func) = func {
|
||||||
|
@ -643,6 +661,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
"__expected_by_{}_span_{}_{}",
|
"__expected_by_{}_span_{}_{}",
|
||||||
expected_int, location.start, location.end
|
expected_int, location.start, location.end
|
||||||
);
|
);
|
||||||
|
|
||||||
let assignment = AirTree::let_assignment(&name, value);
|
let assignment = AirTree::let_assignment(&name, value);
|
||||||
|
|
||||||
let expect = AirTree::binop(
|
let expect = AirTree::binop(
|
||||||
|
@ -660,9 +679,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
if props.full_check {
|
if props.full_check {
|
||||||
let mut index_map = IndexMap::new();
|
let mut index_map = IndexMap::new();
|
||||||
|
|
||||||
let non_opaque_tipo = convert_opaque_type(tipo, &self.data_types);
|
let non_opaque_tipo = convert_opaque_type(tipo, &self.data_types);
|
||||||
|
|
||||||
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() {
|
||||||
|
@ -676,6 +697,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let assign_expect = AirTree::let_assignment("_", expect);
|
let assign_expect = AirTree::let_assignment("_", expect);
|
||||||
|
|
||||||
AirTree::let_assignment(
|
AirTree::let_assignment(
|
||||||
name,
|
name,
|
||||||
assignment.hoist_over(assign_expect.hoist_over(val)),
|
assignment.hoist_over(assign_expect.hoist_over(val)),
|
||||||
|
@ -688,6 +710,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Assign { name, pattern, .. } => {
|
Pattern::Assign { name, pattern, .. } => {
|
||||||
let inner_pattern =
|
let inner_pattern =
|
||||||
self.assignment(pattern, AirTree::local_var(name, tipo.clone()), tipo, props);
|
self.assignment(pattern, AirTree::local_var(name, tipo.clone()), tipo, props);
|
||||||
|
|
||||||
let assign = AirTree::let_assignment(name, value);
|
let assign = AirTree::let_assignment(name, value);
|
||||||
|
|
||||||
AirTree::UnhoistedSequence(vec![assign, inner_pattern])
|
AirTree::UnhoistedSequence(vec![assign, inner_pattern])
|
||||||
|
@ -696,9 +719,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
if props.full_check {
|
if props.full_check {
|
||||||
let name = &format!("__discard_expect_{}", name);
|
let name = &format!("__discard_expect_{}", name);
|
||||||
let mut index_map = IndexMap::new();
|
let mut index_map = IndexMap::new();
|
||||||
|
|
||||||
let tipo = convert_opaque_type(tipo, &self.data_types);
|
let tipo = convert_opaque_type(tipo, &self.data_types);
|
||||||
|
|
||||||
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, assignment.hoist_over(val))
|
AirTree::let_assignment(name, assignment.hoist_over(val))
|
||||||
} else {
|
} else {
|
||||||
|
@ -710,6 +737,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let assign_expect = AirTree::let_assignment("_", expect);
|
let assign_expect = AirTree::let_assignment("_", expect);
|
||||||
|
|
||||||
AirTree::let_assignment(
|
AirTree::let_assignment(
|
||||||
name,
|
name,
|
||||||
assignment.hoist_over(assign_expect.hoist_over(val)),
|
assignment.hoist_over(assign_expect.hoist_over(val)),
|
||||||
|
@ -724,6 +752,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
assert!(tipo.is_list());
|
assert!(tipo.is_list());
|
||||||
assert!(props.kind.is_expect());
|
assert!(props.kind.is_expect());
|
||||||
|
|
||||||
let list_elem_types = tipo.get_inner_types();
|
let list_elem_types = tipo.get_inner_types();
|
||||||
|
|
||||||
let list_elem_type = list_elem_types
|
let list_elem_type = list_elem_types
|
||||||
|
@ -843,7 +872,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} else {
|
} else {
|
||||||
if props.kind.is_expect() {
|
if props.kind.is_expect() {
|
||||||
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo)
|
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo)
|
||||||
.unwrap_or_else(|| panic!("Failed to find definition for {}", name));
|
.unwrap_or_else(|| {
|
||||||
|
unreachable!("Failed to find definition for {}", name)
|
||||||
|
});
|
||||||
|
|
||||||
if data_type.constructors.len() > 1 || props.full_check {
|
if data_type.constructors.len() > 1 || props.full_check {
|
||||||
let (index, _) = data_type
|
let (index, _) = data_type
|
||||||
|
@ -885,11 +916,19 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
|
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
|
||||||
|
|
||||||
for (index, arg) in constr_tipo.arg_types().unwrap().iter().enumerate() {
|
for (index, arg) in constr_tipo
|
||||||
|
.arg_types()
|
||||||
|
.expect("Mismatched type")
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
let field_type = arg.clone();
|
let field_type = arg.clone();
|
||||||
|
|
||||||
type_map.insert(index, field_type);
|
type_map.insert(index, field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert!(type_map.len() == arguments.len());
|
||||||
|
|
||||||
let fields = arguments
|
let fields = arguments
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@ -979,7 +1018,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
type_map.insert(index, field_type);
|
type_map.insert(index, field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("TIPO {:#?}", tipo);
|
assert!(type_map.len() == elems.len());
|
||||||
|
|
||||||
let elems = elems
|
let elems = elems
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1055,13 +1094,16 @@ impl<'a> CodeGenerator<'a> {
|
||||||
location: Span,
|
location: Span,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
assert!(tipo.get_generic().is_none());
|
assert!(tipo.get_generic().is_none());
|
||||||
|
|
||||||
if tipo.is_primitive() {
|
if tipo.is_primitive() {
|
||||||
// Since we would return void anyway and ignore then we can just return value here and ignore
|
// Since we would return void anyway and ignore then we can just return value here and ignore
|
||||||
value
|
value
|
||||||
} else if tipo.is_map() {
|
} else if tipo.is_map() {
|
||||||
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];
|
||||||
let inner_pair_types = inner_list_type.get_inner_types();
|
let inner_pair_types = inner_list_type.get_inner_types();
|
||||||
|
|
||||||
assert!(inner_pair_types.len() == 2);
|
assert!(inner_pair_types.len() == 2);
|
||||||
|
|
||||||
let map_name = format!("__map_span_{}_{}", location.start, location.end);
|
let map_name = format!("__map_span_{}_{}", location.start, location.end);
|
||||||
|
@ -1142,6 +1184,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
assign.hoist_over(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];
|
||||||
|
|
||||||
let list_name = format!("__list_span_{}_{}", location.start, location.end);
|
let list_name = format!("__list_span_{}_{}", location.start, location.end);
|
||||||
|
@ -1206,6 +1249,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} else if tipo.is_2_tuple() {
|
} else if tipo.is_2_tuple() {
|
||||||
let tuple_inner_types = tipo.get_inner_types();
|
let tuple_inner_types = tipo.get_inner_types();
|
||||||
|
|
||||||
|
assert!(tuple_inner_types.len() == 2);
|
||||||
|
|
||||||
let pair_name = format!("__pair_span_{}_{}", location.start, location.end);
|
let pair_name = format!("__pair_span_{}_{}", location.start, location.end);
|
||||||
|
|
||||||
let fst_name = format!("__pair_fst_span_{}_{}", location.start, location.end);
|
let fst_name = format!("__pair_fst_span_{}_{}", location.start, location.end);
|
||||||
|
@ -1243,6 +1288,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} else if tipo.is_tuple() {
|
} else if tipo.is_tuple() {
|
||||||
let tuple_inner_types = tipo.get_inner_types();
|
let tuple_inner_types = tipo.get_inner_types();
|
||||||
|
|
||||||
|
assert!(!tuple_inner_types.is_empty());
|
||||||
|
|
||||||
let tuple_name = format!("__tuple_span_{}_{}", location.start, location.end);
|
let tuple_name = format!("__tuple_span_{}_{}", location.start, location.end);
|
||||||
let tuple_assign = AirTree::let_assignment(&tuple_name, value);
|
let tuple_assign = AirTree::let_assignment(&tuple_name, value);
|
||||||
|
|
||||||
|
@ -1293,7 +1340,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::UnhoistedSequence(sequence).hoist_over(AirTree::void())
|
AirTree::UnhoistedSequence(sequence).hoist_over(AirTree::void())
|
||||||
} else {
|
} else {
|
||||||
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo).unwrap_or_else(|| {
|
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo).unwrap_or_else(|| {
|
||||||
unreachable!("We need a data type definition fot type {:#?}", tipo)
|
unreachable!("We need a data type definition for type {:#?}", tipo)
|
||||||
});
|
});
|
||||||
|
|
||||||
let data_type_variant = tipo
|
let data_type_variant = tipo
|
||||||
|
@ -1302,6 +1349,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.map(|arg| get_arg_type_name(arg))
|
.map(|arg| get_arg_type_name(arg))
|
||||||
.join("_");
|
.join("_");
|
||||||
|
|
||||||
|
assert!(data_type.typed_parameters.len() == tipo.arg_types().unwrap().len());
|
||||||
|
|
||||||
let mono_types: IndexMap<u64, Arc<Type>> = if !data_type.typed_parameters.is_empty() {
|
let mono_types: IndexMap<u64, Arc<Type>> = if !data_type.typed_parameters.is_empty() {
|
||||||
data_type
|
data_type
|
||||||
.typed_parameters
|
.typed_parameters
|
||||||
|
@ -1484,8 +1533,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
if let Some((clause, rest_clauses)) = clauses.split_first() {
|
if let Some((clause, rest_clauses)) = clauses.split_first() {
|
||||||
let mut clause_then = self.build(&clause.then);
|
let mut clause_then = self.build(&clause.then);
|
||||||
|
|
||||||
|
// handles clause guard if it exists
|
||||||
if let Some(guard) = &clause.guard {
|
if let Some(guard) = &clause.guard {
|
||||||
props.complex_clause = true;
|
props.complex_clause = true;
|
||||||
|
|
||||||
let clause_guard_name = format!(
|
let clause_guard_name = format!(
|
||||||
"__clause_guard_span_{}_{}",
|
"__clause_guard_span_{}_{}",
|
||||||
clause.location.start, clause.location.end
|
clause.location.start, clause.location.end
|
||||||
|
@ -1546,6 +1597,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Case of ByteArray or Int or Bool matches
|
||||||
|
assert!(subject_tipo.is_primitive());
|
||||||
|
|
||||||
AirTree::clause(
|
AirTree::clause(
|
||||||
&props.original_subject_name,
|
&props.original_subject_name,
|
||||||
clause_cond,
|
clause_cond,
|
||||||
|
@ -1564,7 +1618,19 @@ impl<'a> CodeGenerator<'a> {
|
||||||
SpecificClause::ListClause {
|
SpecificClause::ListClause {
|
||||||
current_index,
|
current_index,
|
||||||
defined_tails,
|
defined_tails,
|
||||||
|
checked_index,
|
||||||
} => {
|
} => {
|
||||||
|
let mut clause_pattern = &clause.pattern;
|
||||||
|
|
||||||
|
if let Pattern::Assign { pattern, .. } = clause_pattern {
|
||||||
|
clause_pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
clause_pattern,
|
||||||
|
Pattern::List { .. } | Pattern::Var { .. } | Pattern::Discard { .. }
|
||||||
|
));
|
||||||
|
|
||||||
let Pattern::List { elements, tail, .. } = &clause.pattern
|
let Pattern::List { elements, tail, .. } = &clause.pattern
|
||||||
else {
|
else {
|
||||||
let mut next_clause_props = ClauseProperties {
|
let mut next_clause_props = ClauseProperties {
|
||||||
|
@ -1576,6 +1642,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
specific_clause: SpecificClause::ListClause {
|
specific_clause: SpecificClause::ListClause {
|
||||||
current_index: *current_index,
|
current_index: *current_index,
|
||||||
defined_tails: defined_tails.clone(),
|
defined_tails: defined_tails.clone(),
|
||||||
|
checked_index: *checked_index,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1595,31 +1662,37 @@ impl<'a> CodeGenerator<'a> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut tail_name = if *current_index == 0 {
|
let tail_name = defined_tails
|
||||||
props.original_subject_name.clone()
|
.last()
|
||||||
} else {
|
.cloned()
|
||||||
format!(
|
.unwrap_or(props.original_subject_name.clone());
|
||||||
"tail_index_{}_span_{}_{}",
|
|
||||||
*current_index,
|
|
||||||
clause.pattern.location().start,
|
|
||||||
clause.pattern.location().end
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let next_tail_name = {
|
let next_tail_name = {
|
||||||
if rest_clauses.is_empty() {
|
if rest_clauses.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let next_clause = &rest_clauses[0];
|
let next_clause = &rest_clauses[0];
|
||||||
|
|
||||||
let next_elements_len = match &next_clause.pattern {
|
let next_elements_len = match &next_clause.pattern {
|
||||||
Pattern::List { elements, .. } => elements.len(),
|
Pattern::List { elements, tail, .. } => {
|
||||||
|
elements.len() - usize::from(tail.is_some())
|
||||||
|
}
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (*current_index as usize) < next_elements_len {
|
if (*current_index as usize) < next_elements_len {
|
||||||
|
*current_index += 1;
|
||||||
|
|
||||||
|
defined_tails.push(format!(
|
||||||
|
"tail_index_{}_span_{}_{}",
|
||||||
|
*current_index,
|
||||||
|
clause.pattern.location().start,
|
||||||
|
clause.pattern.location().end
|
||||||
|
));
|
||||||
|
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"tail_index_{}_span_{}_{}",
|
"tail_index_{}_span_{}_{}",
|
||||||
*current_index + 1,
|
*current_index,
|
||||||
next_clause.pattern.location().start,
|
next_clause.pattern.location().start,
|
||||||
next_clause.pattern.location().end
|
next_clause.pattern.location().end
|
||||||
))
|
))
|
||||||
|
@ -1629,16 +1702,21 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if elements.len() - usize::from(tail.is_some() && !elements.is_empty())
|
let mut is_wild_card_elems_clause = clause.guard.is_none();
|
||||||
>= *current_index as usize
|
for elements in elements.iter() {
|
||||||
|
if let Pattern::Constructor { .. }
|
||||||
|
| Pattern::Tuple { .. }
|
||||||
|
| Pattern::List { .. } = elements
|
||||||
{
|
{
|
||||||
*current_index += 1;
|
is_wild_card_elems_clause = false;
|
||||||
defined_tails.push(tail_name.clone());
|
}
|
||||||
} else if next_tail_name.is_none() {
|
}
|
||||||
tail_name = defined_tails
|
let elements_len = elements.len() - usize::from(tail.is_some());
|
||||||
.last()
|
|
||||||
.cloned()
|
if *checked_index < elements_len.try_into().unwrap()
|
||||||
.unwrap_or(props.original_subject_name.clone());
|
&& is_wild_card_elems_clause
|
||||||
|
{
|
||||||
|
*checked_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut next_clause_props = ClauseProperties {
|
let mut next_clause_props = ClauseProperties {
|
||||||
|
@ -1650,6 +1728,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
specific_clause: SpecificClause::ListClause {
|
specific_clause: SpecificClause::ListClause {
|
||||||
current_index: *current_index,
|
current_index: *current_index,
|
||||||
defined_tails: defined_tails.clone(),
|
defined_tails: defined_tails.clone(),
|
||||||
|
checked_index: *checked_index,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1660,6 +1739,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let complex_clause = props.complex_clause;
|
let complex_clause = props.complex_clause;
|
||||||
|
|
||||||
|
// TODO: stuff
|
||||||
AirTree::list_clause(
|
AirTree::list_clause(
|
||||||
tail_name,
|
tail_name,
|
||||||
subject_tipo.clone(),
|
subject_tipo.clone(),
|
||||||
|
@ -1734,7 +1814,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} 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 (condition, assignments) =
|
let (condition, assignments) =
|
||||||
self.clause_pattern(&final_clause.pattern, subject_tipo, props);
|
self.clause_pattern(&final_clause.pattern, subject_tipo, props);
|
||||||
|
@ -2190,6 +2272,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
SpecificClause::ListClause {
|
SpecificClause::ListClause {
|
||||||
current_index,
|
current_index,
|
||||||
defined_tails,
|
defined_tails,
|
||||||
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} = props
|
} = props
|
||||||
|
|
|
@ -100,6 +100,7 @@ pub enum SpecificClause {
|
||||||
ListClause {
|
ListClause {
|
||||||
current_index: i64,
|
current_index: i64,
|
||||||
defined_tails: Vec<String>,
|
defined_tails: Vec<String>,
|
||||||
|
checked_index: i64,
|
||||||
},
|
},
|
||||||
TupleClause {
|
TupleClause {
|
||||||
defined_tuple_indices: IndexSet<(usize, String)>,
|
defined_tuple_indices: IndexSet<(usize, String)>,
|
||||||
|
@ -118,6 +119,7 @@ impl ClauseProperties {
|
||||||
specific_clause: SpecificClause::ListClause {
|
specific_clause: SpecificClause::ListClause {
|
||||||
current_index: 0,
|
current_index: 0,
|
||||||
defined_tails: vec![],
|
defined_tails: vec![],
|
||||||
|
checked_index: -1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if t.is_tuple() {
|
} else if t.is_tuple() {
|
||||||
|
@ -159,6 +161,7 @@ impl ClauseProperties {
|
||||||
specific_clause: SpecificClause::ListClause {
|
specific_clause: SpecificClause::ListClause {
|
||||||
current_index: 0,
|
current_index: 0,
|
||||||
defined_tails: vec![],
|
defined_tails: vec![],
|
||||||
|
checked_index: -1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if t.is_tuple() {
|
} else if t.is_tuple() {
|
||||||
|
@ -598,7 +601,8 @@ pub fn modify_self_calls(air_tree: &mut AirTree, func_key: &FunctionAccessKey, v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
// TODO: write some tests
|
||||||
|
pub fn rearrange_list_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
let mut sorted_clauses = clauses;
|
let mut sorted_clauses = clauses;
|
||||||
|
|
||||||
// if we have a list sort clauses so we can plug holes for cases not covered by clauses
|
// if we have a list sort clauses so we can plug holes for cases not covered by clauses
|
||||||
|
@ -610,7 +614,7 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
.sorted_by(|(index1, clause1), (index2, clause2)| {
|
.sorted_by(|(index1, clause1), (index2, clause2)| {
|
||||||
let clause1_len = match &clause1.pattern {
|
let clause1_len = match &clause1.pattern {
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
Some(elements.len() + usize::from(tail.is_some()))
|
Some(elements.len() + usize::from(tail.is_some() && clause1.guard.is_none()))
|
||||||
}
|
}
|
||||||
_ if clause1.guard.is_none() => Some(100000),
|
_ if clause1.guard.is_none() => Some(100000),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -618,7 +622,7 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
|
|
||||||
let clause2_len = match &clause2.pattern {
|
let clause2_len = match &clause2.pattern {
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
Some(elements.len() + usize::from(tail.is_some()))
|
Some(elements.len() + usize::from(tail.is_some() && clause2.guard.is_none()))
|
||||||
}
|
}
|
||||||
_ if clause2.guard.is_none() => Some(100001),
|
_ if clause2.guard.is_none() => Some(100001),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -635,15 +639,15 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
.map(|(_, item)| item)
|
.map(|(_, item)| item)
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
let mut elems_len = 0;
|
|
||||||
let mut final_clauses = sorted_clauses.clone();
|
let mut final_clauses = sorted_clauses.clone();
|
||||||
let mut holes_to_fill = vec![];
|
let mut holes_to_fill = vec![];
|
||||||
let mut last_clause_index = 0;
|
let mut last_clause_index = 0;
|
||||||
let mut last_clause_set = false;
|
let mut last_clause_set = false;
|
||||||
|
let mut wild_card_clause_elems = 0;
|
||||||
|
|
||||||
// If we have a catch all, use that. Otherwise use todo which will result in error
|
// If we have a catch all, use that. Otherwise use todo which will result in error
|
||||||
// TODO: fill in todo label with description
|
// TODO: fill in todo label with description
|
||||||
let plug_in_then = |index: usize, last_clause: &TypedClause| {
|
let plug_in_then = &|index: usize, last_clause: &TypedClause| {
|
||||||
if last_clause.guard.is_none() {
|
if last_clause.guard.is_none() {
|
||||||
match &last_clause.pattern {
|
match &last_clause.pattern {
|
||||||
Pattern::Var { .. } | Pattern::Discard { .. } => last_clause.clone().then,
|
Pattern::Var { .. } | Pattern::Discard { .. } => last_clause.clone().then,
|
||||||
|
@ -692,14 +696,29 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
};
|
};
|
||||||
|
|
||||||
for (index, clause) in sorted_clauses.iter().enumerate() {
|
for (index, clause) in sorted_clauses.iter().enumerate() {
|
||||||
if let Pattern::List { elements, .. } = &clause.pattern {
|
if last_clause_set {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut clause_pattern = &clause.pattern;
|
||||||
|
|
||||||
|
if let Pattern::Assign { pattern, .. } = clause_pattern {
|
||||||
|
clause_pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
clause_pattern,
|
||||||
|
Pattern::List { .. } | Pattern::Var { .. } | Pattern::Discard { .. }
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Pattern::List { elements, tail, .. } = &clause.pattern {
|
||||||
// found a hole and now we plug it
|
// found a hole and now we plug it
|
||||||
while elems_len < elements.len() {
|
while wild_card_clause_elems < elements.len() - usize::from(tail.is_some()) {
|
||||||
let mut discard_elems = vec![];
|
let mut discard_elems = vec![];
|
||||||
|
|
||||||
for _ in 0..elems_len {
|
for _ in 0..wild_card_clause_elems {
|
||||||
discard_elems.push(Pattern::Discard {
|
discard_elems.push(Pattern::Discard {
|
||||||
name: "_".to_string(),
|
name: "__fill".to_string(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -719,7 +738,7 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
.into(),
|
.into(),
|
||||||
},
|
},
|
||||||
guard: None,
|
guard: None,
|
||||||
then: plug_in_then(elems_len, last_clause),
|
then: plug_in_then(wild_card_clause_elems, last_clause),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TypedClause {
|
TypedClause {
|
||||||
|
@ -730,44 +749,38 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
tail: None,
|
tail: None,
|
||||||
},
|
},
|
||||||
guard: None,
|
guard: None,
|
||||||
then: plug_in_then(elems_len, last_clause),
|
then: plug_in_then(wild_card_clause_elems, last_clause),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
holes_to_fill.push((index, clause_to_fill));
|
holes_to_fill.push((index, clause_to_fill));
|
||||||
elems_len += 1;
|
wild_card_clause_elems += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut is_wild_card_elems_clause = clause.guard.is_none();
|
||||||
|
|
||||||
|
for elements in elements.iter() {
|
||||||
|
if let Pattern::Constructor { .. } | Pattern::Tuple { .. } | Pattern::List { .. } =
|
||||||
|
elements
|
||||||
|
{
|
||||||
|
is_wild_card_elems_clause = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have a pattern with no clause guards and a tail then no lists will get past here to other clauses
|
if is_wild_card_elems_clause {
|
||||||
|
wild_card_clause_elems += 1;
|
||||||
|
if clause.guard.is_none() && tail.is_some() {
|
||||||
|
last_clause_index = index;
|
||||||
|
last_clause_set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Pattern::Var { .. } | Pattern::Discard { .. } = &clause.pattern {
|
||||||
if clause.guard.is_none() {
|
if clause.guard.is_none() {
|
||||||
match &clause.pattern {
|
|
||||||
Pattern::Var { .. } => {
|
|
||||||
last_clause_index = index + 1;
|
|
||||||
last_clause_set = true;
|
last_clause_set = true;
|
||||||
|
last_clause_index = index;
|
||||||
}
|
}
|
||||||
Pattern::Discard { .. } => {
|
} else {
|
||||||
last_clause_index = index + 1;
|
unreachable!("Found a clause that is not a list or var or discard");
|
||||||
last_clause_set = true;
|
|
||||||
}
|
|
||||||
Pattern::List {
|
|
||||||
elements,
|
|
||||||
tail: Some(tail),
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut elements = elements.clone();
|
|
||||||
elements.push(*tail.clone());
|
|
||||||
if elements.iter().all(|element| {
|
|
||||||
matches!(element, Pattern::Var { .. } | Pattern::Discard { .. })
|
|
||||||
}) && !last_clause_set
|
|
||||||
&& !elements.is_empty()
|
|
||||||
{
|
|
||||||
last_clause_index = index + 1;
|
|
||||||
last_clause_set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the last condition doesn't have a catch all or tail then add a catch all with a todo
|
// If the last condition doesn't have a catch all or tail then add a catch all with a todo
|
||||||
|
@ -784,8 +797,6 @@ pub fn rearrange_clauses(clauses: Vec<TypedClause>) -> Vec<TypedClause> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elems_len += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encountered a tail so stop there with that as last clause
|
// Encountered a tail so stop there with that as last clause
|
||||||
|
|
Loading…
Reference in New Issue