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::{ use crate::{
ast::{ModuleKind, Span}, ast::{ModuleKind, Span},
tipo::{ tipo::{
self, fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor, fields::FieldMap, Type, TypeConstructor, TypeInfo, TypeVar, ValueConstructor,
ValueConstructorVariant, ValueConstructorVariant,
}, },
IdGenerator, IdGenerator,

View File

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

View File

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

View File

@ -12,6 +12,8 @@ use crate::{
}, },
}; };
pub mod builder;
/// This represents a program in Untyped Plutus Core. /// This represents a program in Untyped Plutus Core.
/// A program contains a version tuple and a term. /// A program contains a version tuple and a term.
/// It is generic because Term requires a generic type. /// 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 { pub type Datum {
Buy thing: Int,
Sell stuff: Int,
} }
pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool { pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool {
let x = [[[2, 9], [7]], [[4]], [[6]]] when datum.thing is {
0 -> True
let [[[a, g], d], b, ..] = x _ -> False
}
True
} }