checkpoint
This commit is contained in:
parent
b97570bc00
commit
6126ee4cb4
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue