feat: refactor handle_each_clause

fix expect type ordering on constr type checking
This commit is contained in:
Kasey White 2023-03-24 00:17:58 -04:00 committed by Lucas
parent f07a959ab8
commit 77afa76163
2 changed files with 142 additions and 95 deletions

View File

@ -712,56 +712,39 @@ impl<'a> CodeGenerator<'a> {
subject_type: &Arc<Type>,
) {
for (index, clause) in clauses.iter().enumerate() {
// scope per clause is different
let mut scope = scope.clone();
scope.push(self.id_gen.next());
// holds when clause pattern Air
let mut clause_subject_vec = vec![];
let mut clause_then_vec = vec![];
let mut clause_pattern_stack = ir_stack.empty_with_scope();
let mut clause_then_stack = ir_stack.empty_with_scope();
// reset complex clause setting per clause back to default
*clause_properties.is_complex_clause() = false;
let mut clause_scope = scope.clone();
clause_scope.push(self.id_gen.next());
self.build(&clause.then, &mut clause_then_vec);
self.build(&clause.then, &mut clause_then_stack);
if let Some(clause_guard) = &clause.guard {
let mut clause_guard_vec = vec![];
let mut clause_guard_stack = ir_stack.empty_with_scope();
let mut clause_guard_condition = ir_stack.empty_with_scope();
*clause_properties.is_complex_clause() = true;
let clause_guard_name = format!("__clause_guard_{}", self.id_gen.next());
let mut clause_guard_scope = scope.clone();
clause_guard_scope.push(self.id_gen.next());
builder::handle_clause_guard(clause_guard, &mut clause_guard_condition);
clause_guard_vec.push(Air::Let {
scope: clause_guard_scope.clone(),
name: clause_guard_name.clone(),
});
clause_guard_stack.let_assignment(clause_guard_name, clause_guard_condition);
builder::handle_clause_guard(
clause_guard,
&mut clause_guard_vec,
clause_guard_scope.clone(),
let condition_stack = ir_stack.empty_with_scope();
condition_stack.bool(true);
clause_guard_stack.clause_guard(
clause_guard_name,
bool(),
condition_stack,
clause_then_stack,
);
clause_guard_vec.push(Air::ClauseGuard {
scope: clause_guard_scope.clone(),
subject_name: clause_guard_name,
tipo: bool(),
});
clause_guard_vec.push(Air::Bool {
scope: clause_guard_scope.clone(),
value: true,
});
clause_guard_vec.append(&mut clause_then_vec);
clause_then_vec = clause_guard_vec;
clause_then_stack = clause_guard_stack;
}
match clause_properties {
@ -771,13 +754,10 @@ impl<'a> CodeGenerator<'a> {
} => {
let subject_name = original_subject_name.clone();
let mut clause_scope = scope.clone();
clause_scope.push(self.id_gen.next());
self.when_pattern(
&clause.pattern,
&mut clause_subject_vec,
&mut clause_then_vec,
&mut clause_pattern_stack,
clause_then_stack,
subject_type,
clause_properties,
);
@ -787,35 +767,33 @@ impl<'a> CodeGenerator<'a> {
if let Some(data_type) = data_type {
if data_type.constructors.len() > 1 {
ir_stack.push(Air::Clause {
scope,
tipo: subject_type.clone(),
complex_clause: *clause_properties.is_complex_clause(),
ir_stack.clause(
subject_type.clone(),
subject_name,
});
*clause_properties.is_complex_clause(),
clause_pattern_stack,
);
} else {
ir_stack.push(Air::Clause {
scope: scope.clone(),
tipo: subject_type.clone(),
complex_clause: *clause_properties.is_complex_clause(),
let condition_stack = ir_stack.empty_with_scope();
condition_stack.integer(0.to_string());
condition_stack.merge_child(clause_pattern_stack);
ir_stack.clause(
subject_type.clone(),
subject_name,
});
let mut scope = scope;
scope.push(self.id_gen.next());
ir_stack.push(Air::Int {
scope,
value: "0".to_string(),
});
*clause_properties.is_complex_clause(),
condition_stack,
);
}
} else {
ir_stack.push(Air::Clause {
scope: scope.clone(),
tipo: subject_type.clone(),
complex_clause: *clause_properties.is_complex_clause(),
ir_stack.clause(
subject_type.clone(),
subject_name,
});
*clause_properties.is_complex_clause(),
clause_pattern_stack,
);
}
}
ClauseProperties::ListClause {
@ -846,8 +824,8 @@ impl<'a> CodeGenerator<'a> {
self.when_pattern(
&clause.pattern,
&mut clause_subject_vec,
&mut clause_then_vec,
&mut clause_pattern_stack,
clause_then_stack,
subject_type,
clause_properties,
);
@ -861,11 +839,10 @@ impl<'a> CodeGenerator<'a> {
elements.len()
} else if let Pattern::Assign { pattern, .. } = &clauses[index + 1].pattern
{
if let Pattern::List { elements, .. } = pattern.as_ref() {
elements.len()
} else {
let Pattern::List { elements, .. } = pattern.as_ref() else {
unreachable!("{:#?}", pattern)
}
};
elements.len()
} else {
unreachable!()
};
@ -880,15 +857,15 @@ impl<'a> CodeGenerator<'a> {
let minus_tail = has_tail as i64;
if current_clause_index as i64 - minus_tail == prev_index {
ir_stack.push(Air::WrapClause { scope });
ir_stack.wrap_clause();
} else {
ir_stack.push(Air::ListClause {
scope,
tipo: subject_type.clone(),
tail_name: subject_name,
next_tail_name: next_tail,
complex_clause: *clause_properties.is_complex_clause(),
});
ir_stack.list_clause(
subject_type.clone(),
subject_name,
next_tail,
*clause_properties.is_complex_clause(),
clause_pattern_stack,
);
}
let ClauseProperties::ListClause { current_index, .. } = clause_properties else {
@ -907,8 +884,8 @@ impl<'a> CodeGenerator<'a> {
self.when_pattern(
&clause.pattern,
&mut clause_subject_vec,
&mut clause_then_vec,
&mut clause_pattern_stack,
clause_then_stack,
subject_type,
clause_properties,
);
@ -926,19 +903,16 @@ impl<'a> CodeGenerator<'a> {
.cloned()
.collect();
ir_stack.push(Air::TupleClause {
scope,
tipo: subject_type.clone(),
indices: indices_to_define,
predefined_indices: prev_defined_tuple_indices,
ir_stack.tuple_clause(
subject_type.clone(),
subject_name,
count: subject_type.get_inner_types().len(),
complex_clause: *clause_properties.is_complex_clause(),
});
indices_to_define,
prev_defined_tuple_indices,
*clause_properties.is_complex_clause(),
clause_pattern_stack,
);
}
}
ir_stack.append(&mut clause_subject_vec);
}
}
@ -2358,25 +2332,27 @@ impl<'a> CodeGenerator<'a> {
})
.collect_vec();
for (index, name, tipo) in arg_indices {
self.expect_type(&tipo, &mut arg_stack, &name);
}
arg_stack = if !arg_indices.is_empty() {
arg_stack.local_var(tipo, name);
let field_expose_stack = expect_stack.empty_with_scope();
field_expose_stack.integer(index.to_string());
field_expose_stack.fields_expose(arg_indices.clone(), true, arg_stack);
field_expose_stack
} else {
arg_stack.integer(index.to_string());
arg_stack
};
for (index, name, tipo) in arg_indices {
self.expect_type(&tipo, &mut arg_stack, &name);
}
arg_stack.void();
clause_stack.clause(tipo, format!("__subject_{new_id}"), index, false, arg_stack);
clause_stack.clause(tipo, format!("__subject_{new_id}"), false, arg_stack);
}
trace_stack.trace(tipo.clone());

View File

@ -1,5 +1,6 @@
use std::sync::Arc;
use indexmap::IndexSet;
use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
use crate::{
@ -341,7 +342,6 @@ impl<'a> AirStack<'a> {
&mut self,
tipo: Arc<Type>,
subject_name: impl ToString,
tag: usize,
complex_clause: bool,
body: AirStack,
) {
@ -354,11 +354,62 @@ impl<'a> AirStack<'a> {
tipo,
});
self.integer(tag.to_string());
self.merge_child(body);
}
pub fn list_clause(
&mut self,
tipo: Arc<Type>,
tail_name: impl ToString,
next_tail_name: Option<String>,
complex_clause: bool,
body: AirStack,
) {
self.new_scope();
self.air.push(Air::ListClause {
scope: self.scope.clone(),
tail_name: tail_name.to_string(),
next_tail_name,
complex_clause,
tipo,
});
self.merge_child(body);
}
pub fn tuple_clause(
&mut self,
tipo: Arc<Type>,
subject_name: impl ToString,
indices: IndexSet<(usize, String)>,
predefined_indices: IndexSet<(usize, String)>,
complex_clause: bool,
body: AirStack,
) {
self.new_scope();
self.air.push(Air::TupleClause {
scope: self.scope.clone(),
subject_name: subject_name.to_string(),
indices,
predefined_indices,
complex_clause,
tipo,
count: tipo.get_inner_types().len(),
});
self.merge_child(body);
}
pub fn wrap_clause(&mut self) {
self.new_scope();
self.air.push(Air::WrapClause {
scope: self.scope.clone(),
});
}
pub fn trace(&mut self, tipo: Arc<Type>) {
self.new_scope();
@ -537,4 +588,24 @@ impl<'a> AirStack<'a> {
value,
});
}
pub(crate) fn clause_guard(
&self,
subject_name: impl ToString,
tipo: Arc<Type>,
condition_stack: AirStack,
clause_then_stack: AirStack,
) {
self.new_scope();
self.air.push(Air::ClauseGuard {
scope: self.scope.clone(),
subject_name: subject_name.to_string(),
tipo,
});
self.merge_child(condition_stack);
self.merge_child(clause_then_stack);
}
}