add field access and list patterns are finished

Co-authored-by: rvcas <x@rvcas.dev>
This commit is contained in:
Kasey White 2022-11-27 03:12:13 -05:00 committed by Lucas
parent abe29a3883
commit 8b24a66b7e
6 changed files with 486 additions and 485 deletions

View File

@ -7,7 +7,7 @@ use uplc::builtins::DefaultFunction;
use crate::{
ast::{ModuleKind, Span},
tipo::{
self, fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor,
fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor,
ValueConstructorVariant,
},
IdGenerator,

View File

@ -3,11 +3,8 @@ use std::sync::Arc;
use uplc::builtins::DefaultFunction;
use crate::{
ast::{
Annotation, Arg, AssignmentKind, BinOp, CallArg, Clause, IfBranch, Pattern, Span,
TypedRecordUpdateArg,
},
tipo::{ModuleValueConstructor, PatternConstructor, Type, ValueConstructor},
ast::{AssignmentKind, BinOp, TypedRecordUpdateArg},
tipo::{Type, ValueConstructor},
};
// []
@ -79,7 +76,6 @@ pub enum IR {
DefineFunc {
func_name: String,
module_name: String,
count: usize,
},
DefineConst {
@ -131,9 +127,8 @@ pub enum IR {
},
RecordAccess {
label: String,
index: u64,
count: usize,
tipo: Arc<Type>,
},
FieldsExpose {

View File

@ -1,8 +1,10 @@
use std::{collections::HashMap, ops::Deref, sync::Arc};
use indexmap::IndexMap;
use uplc::{
ast::{Constant, Name, Program, Term, Type as UplcType},
ast::{
builder::{self, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD},
Constant, Name, Program, Term,
},
builtins::DefaultFunction,
parser::interner::Interner,
BigInt, PlutusData,
@ -18,12 +20,7 @@ use crate::{
};
pub struct CodeGenerator<'a> {
// uplc_function_holder: Vec<(String, Term<Name>)>,
// uplc_function_holder_lookup: IndexMap<FunctionAccessKey, ScopeLevels>,
// uplc_data_holder_lookup: IndexMap<ConstrFieldKey, ScopedExpr>,
// uplc_data_constr_lookup: IndexMap<DataTypeKey, ScopeLevels>,
// uplc_data_usage_holder_lookup: IndexMap<ConstrUsageKey, ScopeLevels>,
function_recurse_lookup: IndexMap<FunctionAccessKey, usize>,
defined_functions: HashMap<FunctionAccessKey, ()>,
functions: &'a HashMap<FunctionAccessKey, &'a Function<Arc<tipo::Type>, TypedExpr>>,
// type_aliases: &'a HashMap<(String, String), &'a TypeAlias<Arc<tipo::Type>>>,
data_types: &'a HashMap<DataTypeKey, &'a DataType<Arc<tipo::Type>>>,
@ -31,6 +28,7 @@ pub struct CodeGenerator<'a> {
// constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>,
module_types: &'a HashMap<String, TypeInfo>,
id_gen: IdGenerator,
needs_field_access: bool,
}
impl<'a> CodeGenerator<'a> {
@ -43,12 +41,7 @@ impl<'a> CodeGenerator<'a> {
module_types: &'a HashMap<String, TypeInfo>,
) -> Self {
CodeGenerator {
// uplc_function_holder: Vec::new(),
// uplc_function_holder_lookup: IndexMap::new(),
// uplc_data_holder_lookup: IndexMap::new(),
// uplc_data_constr_lookup: IndexMap::new(),
// uplc_data_usage_holder_lookup: IndexMap::new(),
function_recurse_lookup: IndexMap::new(),
defined_functions: HashMap::new(),
functions,
// type_aliases,
data_types,
@ -56,6 +49,7 @@ impl<'a> CodeGenerator<'a> {
// constants,
module_types,
id_gen: IdGenerator::new(),
needs_field_access: false,
}
}
@ -68,59 +62,14 @@ impl<'a> CodeGenerator<'a> {
let mut term = self.uplc_code_gen(&mut ir_stack);
// Apply constr exposer to top level.
term = Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "constr_fields_exposer".to_string(),
unique: 0.into(),
},
body: term.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "constr_var".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Force(
Term::Force(Term::Builtin(DefaultFunction::SndPair).into()).into(),
)
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::UnConstrData).into(),
argument: Term::Var(Name {
text: "constr_var".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
};
if self.needs_field_access {
term = builder::constr_get_field(term);
term = self.add_arg_getter(term);
term = builder::constr_fields_exposer(term);
}
term = Term::Force(
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::IfThenElse).into())
.into(),
argument: term.into(),
}
.into(),
argument: Term::Delay(Term::Constant(Constant::Unit).into()).into(),
}
.into(),
argument: Term::Delay(Term::Error.into()).into(),
}
.into(),
);
// Wrap the validator body if ifThenElse term unit error
term = builder::final_wrapper(term);
for arg in arguments.iter().rev() {
term = Term::Lambda {
@ -174,8 +123,6 @@ impl<'a> CodeGenerator<'a> {
constructor: constructor.clone(),
name: name.clone(),
});
// Add constructor information here?
}
TypedExpr::Fn { .. } => todo!(),
TypedExpr::List {
@ -193,9 +140,11 @@ impl<'a> CodeGenerator<'a> {
tipo: tipo.clone(),
tail: tail.is_some(),
});
for element in elements {
self.build_ir(element, ir_stack)
}
if let Some(tail) = tail {
ir_stack.push(IR::Tail { count: 1 });
self.build_ir(tail, ir_stack);
@ -212,16 +161,12 @@ impl<'a> CodeGenerator<'a> {
}
}
TypedExpr::BinOp {
name,
left,
right,
tipo,
..
name, left, right, ..
} => {
ir_stack.push(IR::BinOp {
name: *name,
count: 2,
tipo: tipo.clone(),
tipo: left.tipo(),
});
self.build_ir(left, ir_stack);
self.build_ir(right, ir_stack);
@ -246,10 +191,7 @@ impl<'a> CodeGenerator<'a> {
}
TypedExpr::Try { .. } => todo!(),
TypedExpr::When {
subjects,
clauses,
tipo,
..
subjects, clauses, ..
} => {
// assuming one subject at the moment
ir_stack.push(IR::When {
@ -274,19 +216,28 @@ impl<'a> CodeGenerator<'a> {
};
}
TypedExpr::If { .. } => todo!(),
TypedExpr::RecordAccess { .. } => todo!(),
TypedExpr::ModuleSelect {
TypedExpr::RecordAccess {
record,
index,
tipo,
..
} => {
self.needs_field_access = true;
ir_stack.push(IR::RecordAccess {
index: *index,
tipo: tipo.clone(),
});
self.build_ir(record, ir_stack);
}
TypedExpr::ModuleSelect {
constructor,
module_name,
..
} => match constructor {
tipo::ModuleValueConstructor::Record { .. } => todo!(),
tipo::ModuleValueConstructor::Fn {
location,
module,
name,
} => {
tipo::ModuleValueConstructor::Fn { name, .. } => {
let func = self.functions.get(&FunctionAccessKey {
module_name: module_name.clone(),
function_name: name.clone(),
@ -315,7 +266,7 @@ impl<'a> CodeGenerator<'a> {
}
}
fn define_ir(&self, value_vec: &Vec<IR>, _define_vec: &mut Vec<IR>) {
fn define_ir(&self, value_vec: &Vec<IR>, _define_vec: &mut [IR]) {
// get value item
for value in value_vec {
match dbg!(value) {
@ -390,7 +341,6 @@ impl<'a> CodeGenerator<'a> {
Pattern::Discard { .. } => todo!(),
Pattern::List { elements, tail, .. } => {
let mut elements_vec = vec![];
let mut var_vec = vec![];
let mut names = vec![];
for element in elements {
@ -399,8 +349,7 @@ impl<'a> CodeGenerator<'a> {
names.push(name.clone());
}
a @ Pattern::List { .. } => {
self.pattern_ir(a, &mut elements_vec, &mut vec![]);
let mut var_vec = vec![];
let item_name = format!("list_item_id_{}", self.id_gen.next());
names.push(item_name.clone());
var_vec.push(IR::Var {
@ -418,7 +367,7 @@ impl<'a> CodeGenerator<'a> {
),
name: item_name,
});
var_vec.append(&mut elements_vec);
self.pattern_ir(a, &mut elements_vec, &mut var_vec);
}
_ => todo!(),
}
@ -438,8 +387,7 @@ impl<'a> CodeGenerator<'a> {
});
pattern_vec.append(values);
pattern_vec.append(&mut var_vec);
pattern_vec.append(&mut elements_vec);
}
Pattern::Constructor { .. } => todo!(),
}
@ -488,7 +436,13 @@ impl<'a> CodeGenerator<'a> {
module_name: module.to_string(),
defined_type: name.to_string(),
},
Type::Fn { .. } => todo!(),
Type::Fn { ret, .. } => match ret.deref() {
Type::App { module, name, .. } => DataTypeKey {
module_name: module.to_string(),
defined_type: name.to_string(),
},
_ => unreachable!(),
},
Type::Var { .. } => todo!(),
};
@ -538,20 +492,14 @@ impl<'a> CodeGenerator<'a> {
}
}
println!("TIPO IS {tipo:#?}");
let list_type = match tipo.deref() {
Type::App { args, .. } => &args[0],
_ => unreachable!(),
};
println!("ARGS IS {:#?}", args);
println!("GET UPLC TYPE IS {:#?}", list_type.get_uplc_type());
if constants.len() == args.len() && !tail {
let list =
Term::Constant(Constant::ProtoList(list_type.get_uplc_type(), constants));
println!("LIST TERM IS {:#?}", list);
arg_stack.push(list);
} else {
@ -579,7 +527,7 @@ impl<'a> CodeGenerator<'a> {
}
IR::Tail { .. } => todo!(),
IR::ListAccessor { mut names, tail } => {
IR::ListAccessor { names, tail } => {
let value = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap();
@ -589,31 +537,6 @@ impl<'a> CodeGenerator<'a> {
id_list.push(self.id_gen.next());
}
// if tail {
// let last = names.pop().unwrap();
// let id = id_list[names.len() - 1];
// term = Term::Apply {
// function: Term::Lambda {
// parameter_name: Name {
// text: last,
// unique: 0.into(),
// },
// body: term.into(),
// }
// .into(),
// argument: Term::Apply {
// function: Term::Force(Term::Builtin(DefaultFunction::TailList).into())
// .into(),
// argument: Term::Var(Name {
// text: format!("tail_item_{}_{}", names.len() - 1, id),
// unique: 0.into(),
// })
// .into(),
// }
// .into(),
// };
// }
let current_index = 0;
let (first_name, names) = names.split_first().unwrap();
@ -624,8 +547,13 @@ impl<'a> CodeGenerator<'a> {
unique: 0.into(),
},
body: Term::Apply {
function: self
.list_access_to_uplc(names, &id_list, tail, current_index, term)
function: list_access_to_uplc(
names,
&id_list,
tail,
current_index,
term,
)
.into(),
argument: Term::Apply {
function: Term::Force(
@ -647,17 +575,6 @@ impl<'a> CodeGenerator<'a> {
.into(),
};
for (index, name) in names.iter().enumerate().rev() {
// let var_argument = if index == 0 {
// value.clone()
// } else {
// Term::Var(Name {
// text: format!("tail_item_{}", index - 1),
// unique: 0.into(),
// })
// };
}
arg_stack.push(term);
}
IR::Call { count } => {
@ -836,7 +753,11 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term);
}
IR::DefineFunc { .. } => todo!(),
IR::DefineFunc { func_name, .. } => {
let body = arg_stack.pop().unwrap();
todo!()
}
IR::DefineConst { .. } => todo!(),
IR::DefineConstrFields { .. } => todo!(),
IR::DefineConstrFieldAccess { .. } => todo!(),
@ -846,214 +767,58 @@ impl<'a> CodeGenerator<'a> {
IR::If { .. } => todo!(),
IR::Constr { .. } => todo!(),
IR::Fields { .. } => todo!(),
IR::RecordAccess { .. } => todo!(),
IR::RecordAccess { index, tipo } => {
let constr = arg_stack.pop().unwrap();
let mut term = Term::Apply {
function: Term::Apply {
function: Term::Var(Name {
text: CONSTR_GET_FIELD.to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Apply {
function: Term::Var(Name {
text: CONSTR_FIELDS_EXPOSER.to_string(),
unique: 0.into(),
})
.into(),
argument: constr.into(),
}
.into(),
}
.into(),
argument: Term::Constant(Constant::Integer(index.into())).into(),
};
if tipo.is_int() {
term = Term::Apply {
function: Term::Builtin(DefaultFunction::UnIData).into(),
argument: term.into(),
};
} else if tipo.is_bytearray() {
term = Term::Apply {
function: Term::Builtin(DefaultFunction::UnBData).into(),
argument: term.into(),
};
} else if tipo.is_list() {
term = Term::Apply {
function: Term::Builtin(DefaultFunction::UnListData).into(),
argument: term.into(),
};
}
arg_stack.push(term);
}
IR::FieldsExpose { .. } => todo!(),
IR::Todo { .. } => todo!(),
IR::RecordUpdate { .. } => todo!(),
IR::Negate { .. } => todo!(),
}
}
fn add_arg_getter(&self, term: Term<Name>) -> Term<Name> {
// Apply constr arg getter to top level.
Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "constr_field_get_arg".to_string(),
unique: 0.into(),
},
body: term.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "constr_list".to_string(),
unique: 0.into(),
},
body: Term::Lambda {
parameter_name: Name {
text: "arg_number".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "recurse".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Var(Name {
text: "recurse".to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Var(Name {
text: "recurse".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
// Start recursive with index 0 of list
argument: Term::Constant(Constant::Integer(0.into())).into(),
}
.into(),
argument: Term::Var(Name {
text: "constr_list".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "self_recursor".to_string(),
unique: 0.into(),
},
body: Term::Lambda {
parameter_name: Name {
text: "current_arg_number".to_string(),
unique: 0.into(),
},
body: Term::Lambda {
parameter_name: Name {
text: "list_of_constr_args".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::IfThenElse)
.into(),
)
.into(),
argument: Term::Apply {
function: Term::Apply {
function: Term::Builtin(
DefaultFunction::EqualsInteger,
)
.into(),
argument: Term::Var(Name {
text: "arg_number".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Var(Name {
text: "current_arg_number".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Force(
Term::Builtin(DefaultFunction::HeadList).into(),
)
.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "current_list_of_constr_args".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Var(Name {
text: "self_recursor".to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Var(Name {
text: "self_recursor".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Apply {
function: Term::Builtin(
DefaultFunction::AddInteger,
)
.into(),
argument: Term::Var(Name {
text: "current_arg_number"
.to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Constant(
Constant::Integer(1.into()),
)
.into(),
}
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Force(
Term::Builtin(
DefaultFunction::TailList,
)
.into(),
)
.into(),
argument: Term::Var(Name {
text: "current_list_of_constr_args"
.to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
argument: Term::Var(Name {
text: "list_of_constr_args".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
}
fn list_access_to_uplc(
&self,
names: &[String],
id_list: &[u64],
tail: bool,
@ -1063,7 +828,7 @@ impl<'a> CodeGenerator<'a> {
let (first, names) = names.split_first().unwrap();
if names.len() == 1 && tail {
let term = Term::Lambda {
Term::Lambda {
parameter_name: Name {
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
unique: 0.into(),
@ -1084,9 +849,7 @@ impl<'a> CodeGenerator<'a> {
}
.into(),
argument: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::TailList).into(),
)
function: Term::Force(Term::Builtin(DefaultFunction::TailList).into())
.into(),
argument: Term::Var(Name {
text: format!(
@ -1103,13 +866,9 @@ impl<'a> CodeGenerator<'a> {
}
.into(),
argument: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(),
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
argument: Term::Var(Name {
text: format!(
"tail_index_{}_{}",
current_index, id_list[current_index]
),
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
unique: 0.into(),
})
.into(),
@ -1117,10 +876,9 @@ impl<'a> CodeGenerator<'a> {
.into(),
}
.into(),
};
term
} else if names.len() == 0 {
let term = Term::Lambda {
}
} else if names.is_empty() {
Term::Lambda {
parameter_name: Name {
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
unique: 0.into(),
@ -1135,13 +893,9 @@ impl<'a> CodeGenerator<'a> {
}
.into(),
argument: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(),
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
argument: Term::Var(Name {
text: format!(
"tail_index_{}_{}",
current_index, id_list[current_index]
),
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
unique: 0.into(),
})
.into(),
@ -1149,10 +903,9 @@ impl<'a> CodeGenerator<'a> {
.into(),
}
.into(),
};
term
}
} else {
let term = Term::Lambda {
Term::Lambda {
parameter_name: Name {
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
unique: 0.into(),
@ -1164,14 +917,17 @@ impl<'a> CodeGenerator<'a> {
unique: 0.into(),
},
body: Term::Apply {
function: self
.list_access_to_uplc(names, id_list, tail, current_index + 1, term)
.into(),
argument: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::TailList).into(),
function: list_access_to_uplc(
names,
id_list,
tail,
current_index + 1,
term,
)
.into(),
argument: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::TailList).into())
.into(),
argument: Term::Var(Name {
text: format!(
"tail_index_{}_{}",
@ -1187,13 +943,9 @@ impl<'a> CodeGenerator<'a> {
}
.into(),
argument: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into())
.into(),
function: Term::Force(Term::Builtin(DefaultFunction::HeadList).into()).into(),
argument: Term::Var(Name {
text: format!(
"tail_index_{}_{}",
current_index, id_list[current_index]
),
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
unique: 0.into(),
})
.into(),
@ -1201,8 +953,6 @@ impl<'a> CodeGenerator<'a> {
.into(),
}
.into(),
};
term
}
}
}

View File

@ -12,6 +12,8 @@ use crate::{
},
};
pub mod builder;
/// This represents a program in Untyped Plutus Core.
/// A program contains a version tuple and a term.
/// It is generic because Term requires a generic type.

View File

@ -0,0 +1,255 @@
use crate::builtins::DefaultFunction;
use super::{Constant, Name, Term};
pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer";
pub const CONSTR_GET_FIELD: &str = "__constr_get_field";
pub fn final_wrapper<T>(term: Term<T>) -> Term<T> {
Term::Force(
Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(Term::Builtin(DefaultFunction::IfThenElse).into()).into(),
argument: term.into(),
}
.into(),
argument: Term::Delay(Term::Constant(Constant::Unit).into()).into(),
}
.into(),
argument: Term::Delay(Term::Error.into()).into(),
}
.into(),
)
}
pub fn constr_fields_exposer(term: Term<Name>) -> Term<Name> {
Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: CONSTR_FIELDS_EXPOSER.to_string(),
unique: 0.into(),
},
body: term.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "__constr_var".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Force(
Term::Force(Term::Builtin(DefaultFunction::SndPair).into()).into(),
)
.into(),
argument: Term::Apply {
function: Term::Builtin(DefaultFunction::UnConstrData).into(),
argument: Term::Var(Name {
text: "__constr_var".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
}
}
pub fn constr_get_field(term: Term<Name>) -> Term<Name> {
Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: CONSTR_GET_FIELD.to_string(),
unique: 0.into(),
},
body: term.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "__constr_list".to_string(),
unique: 0.into(),
},
body: Term::Lambda {
parameter_name: Name {
text: "__arg_number".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: "__recurse".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Var(Name {
text: "__recurse".to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Var(Name {
text: "__recurse".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
// Start recursive with index 0 of list
argument: Term::Constant(Constant::Integer(0.into())).into(),
}
.into(),
argument: Term::Var(Name {
text: "__constr_list".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "__self_recursor".to_string(),
unique: 0.into(),
},
body: Term::Lambda {
parameter_name: Name {
text: "__current_arg_number".to_string(),
unique: 0.into(),
},
body: Term::Lambda {
parameter_name: Name {
text: "__list_of_constr_args".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::IfThenElse)
.into(),
)
.into(),
argument: Term::Apply {
function: Term::Apply {
function: Term::Builtin(
DefaultFunction::EqualsInteger,
)
.into(),
argument: Term::Var(Name {
text: "__arg_number".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Var(Name {
text: "__current_arg_number".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
argument: Term::Force(
Term::Builtin(DefaultFunction::HeadList).into(),
)
.into(),
}
.into(),
argument: Term::Lambda {
parameter_name: Name {
text: "__current_list_of_constr_args".to_string(),
unique: 0.into(),
},
body: Term::Apply {
function: Term::Apply {
function: Term::Apply {
function: Term::Var(Name {
text: "__self_recursor".to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Var(Name {
text: "__self_recursor".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Apply {
function: Term::Builtin(
DefaultFunction::AddInteger,
)
.into(),
argument: Term::Var(Name {
text: "__current_arg_number"
.to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
argument: Term::Constant(
Constant::Integer(1.into()),
)
.into(),
}
.into(),
}
.into(),
argument: Term::Apply {
function: Term::Force(
Term::Builtin(DefaultFunction::TailList)
.into(),
)
.into(),
argument: Term::Var(Name {
text: "__current_list_of_constr_args"
.to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
argument: Term::Var(Name {
text: "__list_of_constr_args".to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
.into(),
}
}

View File

@ -44,14 +44,13 @@ pub fn who(a: ByteArray) -> ByteArray {
}
pub type Datum {
Buy
Sell
thing: Int,
stuff: Int,
}
pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool {
let x = [[[2, 9], [7]], [[4]], [[6]]]
let [[[a, g], d], b, ..] = x
True
when datum.thing is {
0 -> True
_ -> False
}
}