checkpoint

This commit is contained in:
Kasey White 2022-12-22 05:52:05 -05:00 committed by Lucas
parent b97570bc00
commit 6126ee4cb4
4 changed files with 488 additions and 285 deletions

View File

@ -1,4 +1,4 @@
use std::sync::Arc; use std::{collections::HashSet, sync::Arc};
use uplc::builtins::DefaultFunction; use uplc::builtins::DefaultFunction;
@ -132,14 +132,25 @@ pub enum Air {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
tail_name: String, tail_name: String,
complex_clause: bool,
next_tail_name: Option<String>, next_tail_name: Option<String>,
complex_clause: bool,
},
TupleClause {
scope: Vec<u64>,
tipo: Arc<Type>,
indices: HashSet<(u64, String)>,
predefined_indices: HashSet<(u64, String)>,
subject_name: String,
count: usize,
complex_clause: bool,
}, },
ClauseGuard { ClauseGuard {
scope: Vec<u64>, scope: Vec<u64>,
subject_name: String, subject_name: String,
tipo: Arc<Type>, tipo: Arc<Type>,
invert: bool,
}, },
Discard { Discard {
@ -176,26 +187,19 @@ pub enum Air {
indices: Vec<(usize, String, Arc<Type>)>, indices: Vec<(usize, String, Arc<Type>)>,
}, },
// ModuleSelect {
// scope: Vec<u64>,
// tipo: Arc<Type>,
// label: String,
// module_name: String,
// module_alias: String,
// constructor: ModuleValueConstructor,
// },
Tuple { Tuple {
scope: Vec<u64>, scope: Vec<u64>,
tipo: Arc<Type>, tipo: Arc<Type>,
count: usize, count: usize,
}, },
// TupleIndex { TupleIndex {
// scope: Vec<u64>, scope: Vec<u64>,
// tipo: Arc<Type>, tipo: Arc<Type>,
// index: u64, index: u64,
// tuple: Box<Self>, name: String,
// }, },
Todo { Todo {
scope: Vec<u64>, scope: Vec<u64>,
label: Option<String>, label: Option<String>,
@ -274,7 +278,9 @@ impl Air {
| Air::RecordUpdate { scope, .. } | Air::RecordUpdate { scope, .. }
| Air::Negate { scope, .. } | Air::Negate { scope, .. }
| Air::Trace { scope, .. } | Air::Trace { scope, .. }
| Air::TupleAccessor { scope, .. } => scope.to_vec(), | Air::TupleAccessor { scope, .. }
| Air::TupleIndex { scope, .. }
| Air::TupleClause { scope, .. } => scope.to_vec(),
} }
} }
} }

View File

@ -1,4 +1,8 @@
use std::{cell::RefCell, collections::HashMap, sync::Arc}; use std::{
cell::RefCell,
collections::{HashMap, HashSet},
sync::Arc,
};
use indexmap::IndexMap; use indexmap::IndexMap;
use itertools::Itertools; use itertools::Itertools;
@ -46,12 +50,114 @@ pub struct FunctionAccessKey {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ClauseProperties { pub enum ClauseProperties {
pub clause_var_name: String, ConstrClause {
pub needs_constr_var: bool, clause_var_name: String,
pub is_complex_clause: bool, needs_constr_var: bool,
pub current_index: usize, is_complex_clause: bool,
pub original_subject_name: String, original_subject_name: String,
},
ListClause {
clause_var_name: String,
needs_constr_var: bool,
is_complex_clause: bool,
original_subject_name: String,
current_index: usize,
},
TupleClause {
clause_var_name: String,
needs_constr_var: bool,
is_complex_clause: bool,
original_subject_name: String,
defined_tuple_indices: HashSet<(u64, String)>,
},
}
impl ClauseProperties {
pub fn init(t: &Arc<Type>, constr_var: String, subject_name: String) -> Self {
if t.is_list() {
ClauseProperties::ListClause {
clause_var_name: constr_var,
needs_constr_var: false,
is_complex_clause: false,
original_subject_name: subject_name,
current_index: 0,
}
} else if t.is_tuple() {
ClauseProperties::TupleClause {
clause_var_name: constr_var,
needs_constr_var: false,
is_complex_clause: false,
original_subject_name: subject_name,
defined_tuple_indices: HashSet::new(),
}
} else {
ClauseProperties::ConstrClause {
clause_var_name: constr_var,
needs_constr_var: false,
is_complex_clause: false,
original_subject_name: subject_name,
}
}
}
pub fn is_complex_clause(&mut self) -> &mut bool {
match self {
ClauseProperties::ConstrClause {
is_complex_clause, ..
}
| ClauseProperties::ListClause {
is_complex_clause, ..
}
| ClauseProperties::TupleClause {
is_complex_clause, ..
} => is_complex_clause,
}
}
pub fn needs_constr_var(&mut self) -> &mut bool {
match self {
ClauseProperties::ConstrClause {
needs_constr_var, ..
}
| ClauseProperties::ListClause {
needs_constr_var, ..
}
| ClauseProperties::TupleClause {
needs_constr_var, ..
} => needs_constr_var,
}
}
pub fn clause_var_name(&mut self) -> &mut String {
match self {
ClauseProperties::ConstrClause {
clause_var_name, ..
}
| ClauseProperties::ListClause {
clause_var_name, ..
}
| ClauseProperties::TupleClause {
clause_var_name, ..
} => clause_var_name,
}
}
pub fn original_subject_name(&mut self) -> &mut String {
match self {
ClauseProperties::ConstrClause {
original_subject_name,
..
}
| ClauseProperties::ListClause {
original_subject_name,
..
}
| ClauseProperties::TupleClause {
original_subject_name,
..
} => original_subject_name,
}
}
} }
pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> { pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Name> {
@ -639,19 +745,18 @@ pub fn get_common_ancestor(scope: &[u64], scope_prev: &[u64]) -> Vec<u64> {
pub fn check_when_pattern_needs( pub fn check_when_pattern_needs(
pattern: &Pattern<PatternConstructor, Arc<Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
needs_access_to_constr_var: &mut bool, clause_properties: &mut ClauseProperties,
needs_clause_guard: &mut bool,
) { ) {
match pattern { match pattern {
Pattern::Var { .. } => { Pattern::Var { .. } => {
*needs_access_to_constr_var = true; *clause_properties.needs_constr_var() = true;
} }
Pattern::List { .. } Pattern::List { .. }
| Pattern::Constructor { .. } | Pattern::Constructor { .. }
| Pattern::Tuple { .. } | Pattern::Tuple { .. }
| Pattern::Int { .. } => { | Pattern::Int { .. } => {
*needs_access_to_constr_var = true; *clause_properties.needs_constr_var() = true;
*needs_clause_guard = true; *clause_properties.is_complex_clause() = true;
} }
Pattern::Discard { .. } => {} Pattern::Discard { .. } => {}
@ -1115,6 +1220,7 @@ pub fn monomorphize(
tipo, tipo,
scope, scope,
subject_name, subject_name,
invert,
} => { } => {
if tipo.is_generic() { if tipo.is_generic() {
let mut tipo = tipo.clone(); let mut tipo = tipo.clone();
@ -1124,6 +1230,7 @@ pub fn monomorphize(
scope, scope,
subject_name, subject_name,
tipo, tipo,
invert,
}; };
needs_variant = false; needs_variant = false;
} }

View File

@ -5,8 +5,8 @@ use itertools::Itertools;
use uplc::{ use uplc::{
ast::{ ast::{
builder::{ builder::{
self, constr_index_exposer, delayed_if_else, if_else, CONSTR_FIELDS_EXPOSER, self, constr_index_exposer, delayed_choose_list, delayed_if_else, if_else,
CONSTR_GET_FIELD, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD,
}, },
Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType, Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType,
}, },
@ -301,13 +301,11 @@ impl<'a> CodeGenerator<'a> {
if let Some((last_clause, clauses)) = clauses.split_last() { if let Some((last_clause, clauses)) = clauses.split_last() {
let mut pattern_vec = vec![]; let mut pattern_vec = vec![];
let mut clause_properties = ClauseProperties { let mut clause_properties = ClauseProperties::init(
clause_var_name: constr_var.clone(), &subject.tipo(),
needs_constr_var: false, constr_var.clone(),
is_complex_clause: false, subject_name.clone(),
current_index: 0, );
original_subject_name: subject_name.clone(),
};
self.handle_each_clause( self.handle_each_clause(
&mut pattern_vec, &mut pattern_vec,
@ -342,7 +340,7 @@ impl<'a> CodeGenerator<'a> {
final_scope, final_scope,
); );
if clause_properties.needs_constr_var { if *clause_properties.needs_constr_var() {
ir_stack.push(Air::Lam { ir_stack.push(Air::Lam {
scope: scope.clone(), scope: scope.clone(),
name: constr_var.clone(), name: constr_var.clone(),
@ -562,53 +560,112 @@ impl<'a> CodeGenerator<'a> {
// holds when clause pattern Air // holds when clause pattern Air
let mut clause_subject_vec = vec![]; let mut clause_subject_vec = vec![];
let mut clauses_vec = vec![]; let mut clause_then_vec = vec![];
// reset complex clause setting per clause back to default // reset complex clause setting per clause back to default
clause_properties.is_complex_clause = false; *clause_properties.is_complex_clause() = false;
self.build_ir(&clause.then, &mut clauses_vec, scope.clone()); self.build_ir(&clause.then, &mut clause_then_vec, scope.clone());
self.when_ir( match clause_properties {
&clause.pattern[0], ClauseProperties::ConstrClause {
&mut clause_subject_vec, original_subject_name,
&mut clauses_vec, ..
subject_type, } => {
clause_properties, let subject_name = original_subject_name.clone();
scope.clone(), self.when_ir(
); &clause.pattern[0],
&mut clause_subject_vec,
&mut clause_then_vec,
subject_type,
clause_properties,
scope.clone(),
);
let subject_name = if clause_properties.current_index == 0 { ir_stack.push(Air::Clause {
clause_properties.original_subject_name.clone() scope,
} else { tipo: subject_type.clone(),
format!("__tail_{}", clause_properties.current_index - 1) complex_clause: *clause_properties.is_complex_clause(),
}; subject_name,
});
}
ClauseProperties::ListClause {
original_subject_name,
current_index,
..
} => {
let current_clause_index = *current_index;
// Clause is last in Air pattern vec let subject_name = if current_clause_index == 0 {
if subject_type.is_list() { original_subject_name.clone()
let next_tail = if index == clauses.len() - 1 { } else {
None format!("__tail_{}", current_clause_index - 1)
} else { };
Some(format!("__tail_{}", clause_properties.current_index))
};
ir_stack.push(Air::ListClause { self.when_ir(
scope, &clause.pattern[0],
tipo: subject_type.clone(), &mut clause_subject_vec,
tail_name: subject_name, &mut clause_then_vec,
complex_clause: clause_properties.is_complex_clause, subject_type,
next_tail_name: next_tail, clause_properties,
}); scope.clone(),
);
clause_properties.current_index += 1; let next_tail = if index == clauses.len() - 1 {
} else { None
ir_stack.push(Air::Clause { } else {
scope, Some(format!("__tail_{}", current_clause_index))
tipo: subject_type.clone(), };
complex_clause: clause_properties.is_complex_clause,
subject_name, ir_stack.push(Air::ListClause {
}); scope,
tipo: subject_type.clone(),
tail_name: subject_name,
complex_clause: *clause_properties.is_complex_clause(),
next_tail_name: next_tail,
});
}
ClauseProperties::TupleClause {
original_subject_name,
defined_tuple_indices,
..
} => {
let prev_defined_tuple_indices = defined_tuple_indices.clone();
let subject_name = original_subject_name.clone();
self.when_ir(
&clause.pattern[0],
&mut clause_subject_vec,
&mut clause_then_vec,
subject_type,
clause_properties,
scope.clone(),
);
let current_defined_tuple_indices = match clause_properties {
ClauseProperties::TupleClause {
defined_tuple_indices,
..
} => defined_tuple_indices.clone(),
_ => unreachable!(),
};
let indices_to_define = current_defined_tuple_indices
.difference(&prev_defined_tuple_indices)
.cloned()
.collect();
ir_stack.push(Air::TupleClause {
scope,
tipo: subject_type.clone(),
indices: indices_to_define,
predefined_indices: prev_defined_tuple_indices,
subject_name,
count: subject_type.get_inner_types().len(),
complex_clause: *clause_properties.is_complex_clause(),
});
}
} }
ir_stack.append(&mut clause_subject_vec); ir_stack.append(&mut clause_subject_vec);
} }
} }
@ -649,7 +706,7 @@ impl<'a> CodeGenerator<'a> {
location: Span::empty(), location: Span::empty(),
}, },
), ),
name: clause_properties.original_subject_name.clone(), name: clause_properties.original_subject_name().clone(),
variant_name: String::new(), variant_name: String::new(),
}); });
pattern_vec.append(values); pattern_vec.append(values);
@ -669,7 +726,7 @@ impl<'a> CodeGenerator<'a> {
location: Span::empty(), location: Span::empty(),
}, },
), ),
name: clause_properties.original_subject_name.clone(), name: clause_properties.original_subject_name().clone(),
variant_name: String::new(), variant_name: String::new(),
}); });
@ -690,19 +747,14 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(values); pattern_vec.append(values);
} }
Pattern::List { elements, tail, .. } => { Pattern::List { elements, tail, .. } => {
let mut needs_clause_guard = false;
for element in elements { for element in elements {
check_when_pattern_needs(element, &mut false, &mut needs_clause_guard); check_when_pattern_needs(element, clause_properties);
} }
if let Some(tail) = tail { if let Some(tail) = tail {
check_when_pattern_needs(tail, &mut false, &mut needs_clause_guard); check_when_pattern_needs(tail, clause_properties);
}
if needs_clause_guard {
clause_properties.is_complex_clause = true;
} }
*clause_properties.needs_constr_var() = false;
pattern_vec.push(Air::Discard { pattern_vec.push(Air::Discard {
scope: scope.clone(), scope: scope.clone(),
@ -725,13 +777,10 @@ impl<'a> CodeGenerator<'a> {
.. ..
} => { } => {
for arg in arguments { for arg in arguments {
check_when_pattern_needs( check_when_pattern_needs(&arg.value, clause_properties);
&arg.value,
&mut clause_properties.needs_constr_var,
&mut clause_properties.is_complex_clause,
);
} }
// find data type definition
let data_type_key = match tipo { let data_type_key = match tipo {
Type::Fn { ret, .. } => match ret.as_ref() { Type::Fn { ret, .. } => match ret.as_ref() {
Type::App { module, name, .. } => DataTypeKey { Type::App { module, name, .. } => DataTypeKey {
@ -763,7 +812,7 @@ impl<'a> CodeGenerator<'a> {
location: Span::empty(), location: Span::empty(),
}, },
), ),
name: clause_properties.clause_var_name.clone(), name: clause_properties.clause_var_name().clone(),
scope: scope.clone(), scope: scope.clone(),
variant_name: String::new(), variant_name: String::new(),
}]; }];
@ -777,7 +826,7 @@ impl<'a> CodeGenerator<'a> {
}); });
} }
if clause_properties.needs_constr_var { if *clause_properties.needs_constr_var() {
self.when_recursive_ir( self.when_recursive_ir(
pattern, pattern,
pattern_vec, pattern_vec,
@ -800,17 +849,21 @@ impl<'a> CodeGenerator<'a> {
} }
} }
Pattern::Tuple { elems, .. } => { Pattern::Tuple { elems, .. } => {
let mut needs_clause_guard = false;
for elem in elems { for elem in elems {
check_when_pattern_needs(elem, &mut false, &mut needs_clause_guard); check_when_pattern_needs(elem, clause_properties);
} }
*clause_properties.needs_constr_var() = false;
if needs_clause_guard { self.when_recursive_ir(
clause_properties.is_complex_clause = true; pattern,
} pattern_vec,
&mut vec![],
clause_properties.clone(),
tipo,
scope,
);
todo!() pattern_vec.append(values);
} }
} }
} }
@ -824,6 +877,7 @@ impl<'a> CodeGenerator<'a> {
tipo: &Type, tipo: &Type,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
let mut clause_properties = clause_properties;
match pattern { match pattern {
Pattern::Int { .. } => todo!(), Pattern::Int { .. } => todo!(),
Pattern::String { .. } => todo!(), Pattern::String { .. } => todo!(),
@ -839,42 +893,18 @@ impl<'a> CodeGenerator<'a> {
// let mut elements_vec = vec![]; // let mut elements_vec = vec![];
let mut names = vec![]; let mut names = vec![];
let mut nested_pattern = vec![];
let items_type = &tipo.get_inner_types()[0];
// let mut nested_pattern = vec![];
for element in elements { for element in elements {
match element { let name = self.nested_pattern_ir_and_label(
Pattern::Var { name, .. } => { element,
names.push(name.clone()); &mut nested_pattern,
} items_type,
Pattern::Discard { .. } => { scope.clone(),
names.push("_".to_string()); );
}
Pattern::List { .. } => { names.push(name.unwrap_or_else(|| "_".to_string()))
todo!("Nested List Patterns Not Yet Done");
// let mut var_vec = vec![];
// let item_name = format!("list_item_id_{}", self.id_gen.next());
// names.push(item_name.clone());
// var_vec.push(Air::Var {
// constructor: ValueConstructor::public(
// Type::App {
// public: true,
// module: String::new(),
// name: String::new(),
// args: vec![],
// }
// .into(),
// ValueConstructorVariant::LocalVariable {
// location: Span::empty(),
// },
// ),
// name: item_name,
// scope: scope.clone(),
// });
// self.pattern_ir(a, &mut elements_vec, &mut var_vec, scope.clone());
}
Pattern::Tuple { .. } => {
todo!("Nested Tuple Patterns Not Yet Done");
}
_ => todo!(),
}
} }
let mut tail_name = String::new(); let mut tail_name = String::new();
@ -896,7 +926,7 @@ impl<'a> CodeGenerator<'a> {
.map(|(index, name)| { .map(|(index, name)| {
if index == 0 { if index == 0 {
( (
clause_properties.original_subject_name.clone(), clause_properties.original_subject_name().clone(),
name.clone(), name.clone(),
) )
} else { } else {
@ -907,7 +937,7 @@ impl<'a> CodeGenerator<'a> {
if tail.is_some() && !elements.is_empty() { if tail.is_some() && !elements.is_empty() {
let tail_var = if elements.len() == 1 { let tail_var = if elements.len() == 1 {
clause_properties.original_subject_name clause_properties.original_subject_name().clone()
} else { } else {
format!("__tail_{}", elements.len() - 2) format!("__tail_{}", elements.len() - 2)
}; };
@ -928,6 +958,7 @@ impl<'a> CodeGenerator<'a> {
} }
pattern_vec.append(values); pattern_vec.append(values);
pattern_vec.append(&mut nested_pattern);
} }
Pattern::Constructor { Pattern::Constructor {
is_record, is_record,
@ -978,80 +1009,27 @@ impl<'a> CodeGenerator<'a> {
let arguments_index = arguments let arguments_index = arguments
.iter() .iter()
.map(|item| { .filter_map(|item| {
let label = item.label.clone().unwrap_or_default(); let label = item.label.clone().unwrap_or_default();
let field_index = let field_index = field_map.fields.get(&label).unwrap_or(&0);
field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&0); let var_name = self.nested_pattern_ir_and_label(
let (discard, var_name) = match &item.value { &item.value,
Pattern::Var { name, .. } => (false, name.clone()), &mut nested_pattern,
Pattern::Discard { .. } => (true, "".to_string()), type_map.get(&label).unwrap(),
Pattern::List { .. } => todo!(), scope.clone(),
a @ Pattern::Constructor { );
tipo,
name: constr_name,
..
} => {
let id = self.id_gen.next();
let constr_var_name = format!("{constr_name}_{id}");
let data_type_key = match tipo.as_ref() {
Type::Fn { ret, .. } => match &**ret {
Type::App { module, name, .. } => DataTypeKey {
module_name: module.clone(),
defined_type: name.clone(),
},
_ => unreachable!(),
},
Type::App { module, name, .. } => DataTypeKey {
module_name: module.clone(),
defined_type: name.clone(),
},
_ => unreachable!(),
};
let data_type = self.data_types.get(&data_type_key).unwrap(); var_name.map(|var_name| (label, var_name, *field_index))
if data_type.constructors.len() > 1 {
nested_pattern.push(Air::ClauseGuard {
scope: scope.clone(),
tipo: tipo.clone(),
subject_name: constr_var_name.clone(),
});
}
let mut clause_complexity = ClauseProperties {
clause_var_name: constr_var_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
current_index: 0,
original_subject_name: constr_var_name.clone(),
};
self.when_ir(
a,
&mut nested_pattern,
&mut vec![],
tipo,
&mut clause_complexity,
scope.clone(),
);
(false, constr_var_name)
}
_ => todo!(),
};
(label, var_name, *field_index, discard)
}) })
.filter(|(_, _, _, discard)| !discard)
.sorted_by(|item1, item2| item1.2.cmp(&item2.2)) .sorted_by(|item1, item2| item1.2.cmp(&item2.2))
.collect::<Vec<(String, String, usize, bool)>>(); .collect::<Vec<(String, String, usize)>>();
if !arguments_index.is_empty() { if !arguments_index.is_empty() {
pattern_vec.push(Air::FieldsExpose { pattern_vec.push(Air::FieldsExpose {
count: arguments_index.len() + 2, count: arguments_index.len() + 2,
indices: arguments_index indices: arguments_index
.iter() .iter()
.map(|(label, var_name, index, _)| { .map(|(label, var_name, index)| {
let field_type = type_map.get(label).unwrap(); let field_type = type_map.get(label).unwrap();
(*index, var_name.clone(), field_type.clone()) (*index, var_name.clone(), field_type.clone())
}) })
@ -1071,76 +1049,24 @@ impl<'a> CodeGenerator<'a> {
let arguments_index = arguments let arguments_index = arguments
.iter() .iter()
.enumerate() .enumerate()
.map(|(index, item)| { .filter_map(|(index, item)| {
let (discard, var_name) = match &item.value { let var_name = self.nested_pattern_ir_and_label(
Pattern::Var { name, .. } => (false, name.clone()), &item.value,
Pattern::Discard { .. } => (true, "".to_string()), &mut nested_pattern,
Pattern::List { .. } => todo!(), type_map.get(&index).unwrap(),
a @ Pattern::Constructor { scope.clone(),
tipo, );
name: constr_name,
..
} => {
let id = self.id_gen.next();
let constr_var_name = format!("{constr_name}_{id}");
let data_type_key = match tipo.as_ref() {
Type::Fn { ret, .. } => match &**ret {
Type::App { module, name, .. } => DataTypeKey {
module_name: module.clone(),
defined_type: name.clone(),
},
_ => unreachable!(),
},
Type::App { module, name, .. } => DataTypeKey {
module_name: module.clone(),
defined_type: name.clone(),
},
_ => unreachable!(),
};
let data_type = self.data_types.get(&data_type_key).unwrap(); var_name.map(|var_name| (var_name, index))
if data_type.constructors.len() > 1 {
nested_pattern.push(Air::ClauseGuard {
scope: scope.clone(),
tipo: tipo.clone(),
subject_name: constr_var_name.clone(),
});
}
let mut clause_complexity = ClauseProperties {
clause_var_name: constr_var_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
current_index: 0,
original_subject_name: constr_var_name.clone(),
};
self.when_ir(
a,
&mut nested_pattern,
&mut vec![],
tipo,
&mut clause_complexity,
scope.clone(),
);
(false, constr_var_name)
}
_ => todo!(),
};
(var_name, index, discard)
}) })
.filter(|(_, _, discard)| !discard) .collect::<Vec<(String, usize)>>();
.collect::<Vec<(String, usize, bool)>>();
if !arguments_index.is_empty() { if !arguments_index.is_empty() {
pattern_vec.push(Air::FieldsExpose { pattern_vec.push(Air::FieldsExpose {
count: arguments_index.len() + 2, count: arguments_index.len() + 2,
indices: arguments_index indices: arguments_index
.iter() .iter()
.map(|(name, index, _)| { .map(|(name, index)| {
let field_type = type_map.get(index).unwrap(); let field_type = type_map.get(index).unwrap();
(*index, name.clone(), field_type.clone()) (*index, name.clone(), field_type.clone())
@ -1158,6 +1084,131 @@ impl<'a> CodeGenerator<'a> {
} }
} }
fn nested_pattern_ir_and_label(
&mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>,
pattern_type: &Arc<Type>,
scope: Vec<u64>,
) -> Option<String> {
match pattern {
Pattern::Var { name, .. } => Some(name.clone()),
Pattern::Discard { .. } => None,
a @ Pattern::List { elements, tail, .. } => {
let item_name = format!("list_item_id_{}", self.id_gen.next());
if elements.is_empty() {
pattern_vec.push(Air::ClauseGuard {
scope: scope.clone(),
subject_name: item_name.clone(),
tipo: pattern_type.clone(),
invert: false,
});
} else {
for (index, element) in elements.iter().enumerate() {
if index == 0 {
pattern_vec.push(Air::ClauseGuard {
scope: scope.clone(),
subject_name: item_name.clone(),
tipo: pattern_type.clone(),
invert: true,
});
pattern_vec.push(Air::ListAccessor {
scope: scope.clone(),
tipo: pattern_type.clone(),
names: vec![format!("todo")],
tail: false,
});
pattern_vec.push(Air::Var {
scope: scope.clone(),
constructor: ValueConstructor::public(
pattern_type.clone(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: item_name.clone(),
variant_name: String::new(),
});
}
}
}
let mut clause_properties = ClauseProperties::ListClause {
clause_var_name: item_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
original_subject_name: item_name.clone(),
current_index: 0,
};
self.when_ir(
a,
pattern_vec,
&mut vec![],
pattern_type,
&mut clause_properties,
scope,
);
// self.when_recursive_ir(a);
Some(item_name)
}
a @ Pattern::Constructor {
tipo,
name: constr_name,
..
} => {
let id = self.id_gen.next();
let constr_var_name = format!("{constr_name}_{id}");
let data_type_key = match tipo.as_ref() {
Type::Fn { ret, .. } => match &**ret {
Type::App { module, name, .. } => DataTypeKey {
module_name: module.clone(),
defined_type: name.clone(),
},
_ => unreachable!(),
},
Type::App { module, name, .. } => DataTypeKey {
module_name: module.clone(),
defined_type: name.clone(),
},
_ => unreachable!(),
};
let data_type = self.data_types.get(&data_type_key).unwrap();
if data_type.constructors.len() > 1 {
pattern_vec.push(Air::ClauseGuard {
scope: scope.clone(),
tipo: tipo.clone(),
subject_name: constr_var_name.clone(),
invert: false,
});
}
let mut clause_properties = ClauseProperties::ConstrClause {
clause_var_name: constr_var_name.clone(),
needs_constr_var: false,
is_complex_clause: false,
original_subject_name: constr_var_name.clone(),
};
self.when_ir(
a,
pattern_vec,
&mut vec![],
tipo,
&mut clause_properties,
scope.clone(),
);
Some(constr_var_name)
}
_ => todo!(),
}
}
fn assignment_ir( fn assignment_ir(
&mut self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>,
@ -3180,31 +3231,22 @@ impl<'a> CodeGenerator<'a> {
term term
}; };
term = Term::Apply { term = delayed_choose_list(
function: Term::Apply { Term::Var(Name {
function: Term::Apply { text: tail_name,
function: Term::Builtin(DefaultFunction::ChooseList) unique: 0.into(),
.force_wrap() }),
.force_wrap() body,
.into(), arg,
argument: Term::Var(Name { );
text: tail_name,
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Delay(body.into()).into(),
}
.into(),
argument: Term::Delay(arg.into()).into(),
}
.force_wrap();
arg_stack.push(term); arg_stack.push(term);
} }
Air::ClauseGuard { Air::ClauseGuard {
subject_name, tipo, .. subject_name,
tipo,
invert,
..
} => { } => {
let condition = arg_stack.pop().unwrap(); let condition = arg_stack.pop().unwrap();
@ -3229,6 +3271,7 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
} }
} else if tipo.is_bool() { } else if tipo.is_bool() {
// let term =
todo!() todo!()
} else if tipo.is_string() { } else if tipo.is_string() {
Term::Apply { Term::Apply {
@ -3576,6 +3619,7 @@ impl<'a> CodeGenerator<'a> {
); );
arg_stack.push(term); arg_stack.push(term);
} }
Air::TupleIndex { .. } => todo!(),
Air::TupleAccessor { tipo, names, .. } => { Air::TupleAccessor { tipo, names, .. } => {
let value = arg_stack.pop().unwrap(); let value = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
@ -3757,6 +3801,7 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(Term::Error) arg_stack.push(Term::Error)
} }
} }
Air::TupleClause { .. } => todo!(),
} }
} }
} }

View File

@ -305,3 +305,48 @@ pub fn if_else(condition: Term<Name>, then_term: Term<Name>, else_term: Term<Nam
argument: else_term.into(), argument: else_term.into(),
} }
} }
pub fn delayed_choose_list(
list: Term<Name>,
empty_list_term: Term<Name>,
else_term: Term<Name>,
) -> Term<Name> {
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.force_wrap()
.into(),
argument: list.into(),
}
.into(),
argument: Term::Delay(empty_list_term.into()).into(),
}
.into(),
argument: Term::Delay(else_term.into()).into(),
}
.force_wrap()
}
pub fn choose_list(
list: Term<Name>,
empty_list_term: Term<Name>,
else_term: Term<Name>,
) -> Term<Name> {
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Builtin(DefaultFunction::IfThenElse)
.force_wrap()
.force_wrap()
.into(),
argument: list.into(),
}
.into(),
argument: empty_list_term.into(),
}
.into(),
argument: else_term.into(),
}
}