feat: Finish up assert feature

Better error reporing on NonFunctionalApplication Error
Refactor redundant code
Add handling of whens with one clause.
This commit is contained in:
Kasey White 2023-01-29 05:21:55 -05:00
parent 4c8089c28a
commit afd040fda5
6 changed files with 454 additions and 464 deletions

View File

@ -96,12 +96,6 @@ pub enum Air {
}, },
// Assignment // Assignment
Assert {
scope: Vec<u64>,
tipo: Arc<Type>,
value_is_data: bool,
},
Let { Let {
scope: Vec<u64>, scope: Vec<u64>,
name: String, name: String,
@ -112,14 +106,6 @@ pub enum Air {
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
ListAssert {
scope: Vec<u64>,
tipo: Arc<Type>,
names: Vec<String>,
tail: bool,
value_is_data: bool,
},
// When // When
When { When {
scope: Vec<u64>, scope: Vec<u64>,
@ -275,8 +261,6 @@ impl Air {
| Air::Builtin { scope, .. } | Air::Builtin { scope, .. }
| Air::BinOp { scope, .. } | Air::BinOp { scope, .. }
| Air::UnOp { scope, .. } | Air::UnOp { scope, .. }
| Air::Assert { scope, .. }
| Air::ListAssert { scope, .. }
| Air::Let { scope, .. } | Air::Let { scope, .. }
| Air::UnWrapData { scope, .. } | Air::UnWrapData { scope, .. }
| Air::When { scope, .. } | Air::When { scope, .. }
@ -356,8 +340,6 @@ impl Air {
| Air::Call { tipo, .. } | Air::Call { tipo, .. }
| Air::Builtin { tipo, .. } | Air::Builtin { tipo, .. }
| Air::BinOp { tipo, .. } | Air::BinOp { tipo, .. }
| Air::Assert { tipo, .. }
| Air::ListAssert { tipo, .. }
| Air::UnWrapData { tipo, .. } | Air::UnWrapData { tipo, .. }
| Air::When { tipo, .. } | Air::When { tipo, .. }
| Air::Clause { tipo, .. } | Air::Clause { tipo, .. }

View File

@ -4,7 +4,7 @@ use indexmap::{IndexMap, IndexSet};
use itertools::Itertools; use itertools::Itertools;
use uplc::{ use uplc::{
ast::{ ast::{
builder::{apply_wrap, choose_list, delayed_choose_list, if_else}, builder::{apply_wrap, delayed_choose_list, if_else},
Constant as UplcConstant, Name, Term, Type as UplcType, Constant as UplcConstant, Name, Term, Type as UplcType,
}, },
builtins::DefaultFunction, builtins::DefaultFunction,
@ -484,7 +484,7 @@ pub fn list_access_to_uplc(
tipos: Vec<Arc<Type>>, tipos: Vec<Arc<Type>>,
check_last_item: bool, check_last_item: bool,
) -> Term<Name> { ) -> Term<Name> {
let (first, names) = names.split_first().unwrap(); if let Some((first, names)) = names.split_first() {
let (current_tipo, tipos) = tipos.split_first().unwrap(); let (current_tipo, tipos) = tipos.split_first().unwrap();
let head_list = if current_tipo.is_map() { let head_list = if current_tipo.is_map() {
@ -546,8 +546,6 @@ pub fn list_access_to_uplc(
.into(), .into(),
} }
} else if names.is_empty() { } else if names.is_empty() {
// Maybe check list is actually empty or should we leave that to when .. is only
// this would replace term.into() if we decide to
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]),
@ -576,7 +574,8 @@ pub fn list_access_to_uplc(
apply_wrap( apply_wrap(
Term::Builtin(DefaultFunction::Trace).force_wrap(), Term::Builtin(DefaultFunction::Trace).force_wrap(),
Term::Constant(UplcConstant::String( Term::Constant(UplcConstant::String(
"List/Tuple contains more items than it should".to_string(), "List/Tuple contains more items than it should"
.to_string(),
)), )),
), ),
Term::Delay(Term::Error.into()), Term::Delay(Term::Error.into()),
@ -632,6 +631,9 @@ pub fn list_access_to_uplc(
.into(), .into(),
} }
} }
} else {
term
}
} }
pub fn get_common_ancestor(scope: &[u64], scope_prev: &[u64]) -> Vec<u64> { pub fn get_common_ancestor(scope: &[u64], scope_prev: &[u64]) -> Vec<u64> {

View File

@ -213,6 +213,7 @@ impl Type {
match self { match self {
Self::Fn { args, .. } => Some(args.clone()), Self::Fn { args, .. } => Some(args.clone()),
Self::App { args, .. } => Some(args.clone()), Self::App { args, .. } => Some(args.clone()),
Self::Var { tipo } => tipo.borrow().arg_types(),
_ => None, _ => None,
} }
} }
@ -498,6 +499,13 @@ impl TypeVar {
} }
} }
pub fn arg_types(&self) -> Option<Vec<Arc<Type>>> {
match self {
Self::Link { tipo } => tipo.arg_types(),
_ => None,
}
}
pub fn get_inner_type(&self) -> Vec<Arc<Type>> { pub fn get_inner_type(&self) -> Vec<Arc<Type>> {
match self { match self {
Self::Link { tipo } => tipo.get_inner_types(), Self::Link { tipo } => tipo.get_inner_types(),

View File

@ -1,4 +1,4 @@
use std::{clone, sync::Arc, vec}; use std::sync::Arc;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use itertools::Itertools; use itertools::Itertools;
@ -19,7 +19,7 @@ use uplc::{
use crate::{ use crate::{
air::Air, air::Air,
ast::{ ast::{
ArgName, AssignmentKind, BinOp, CallArg, Clause, Pattern, Span, TypedArg, TypedDataType, ArgName, AssignmentKind, BinOp, Clause, Pattern, Span, TypedArg, TypedDataType,
TypedFunction, UnOp, TypedFunction, UnOp,
}, },
builder::{ builder::{
@ -32,8 +32,8 @@ use crate::{
}, },
expr::TypedExpr, expr::TypedExpr,
tipo::{ tipo::{
fields::FieldMap, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, TypeVar, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
ValueConstructor, ValueConstructorVariant, ValueConstructorVariant,
}, },
IdGenerator, IdGenerator,
}; };
@ -80,13 +80,10 @@ impl<'a> CodeGenerator<'a> {
let scope = vec![self.id_gen.next()]; let scope = vec![self.id_gen.next()];
self.build_ir(&body, &mut ir_stack, scope); self.build_ir(&body, &mut ir_stack, scope);
println!("{:#?}", ir_stack);
self.define_ir(&mut ir_stack); self.define_ir(&mut ir_stack);
println!("{:#?}", ir_stack);
self.convert_opaque_type_to_inner_ir(&mut ir_stack); self.convert_opaque_type_to_inner_ir(&mut ir_stack);
println!("{:#?}", ir_stack);
let mut term = self.uplc_code_gen(&mut ir_stack); let mut term = self.uplc_code_gen(&mut ir_stack);
@ -115,7 +112,6 @@ impl<'a> CodeGenerator<'a> {
version: (1, 0, 0), version: (1, 0, 0),
term, term,
}; };
println!("{}", program.to_pretty());
let mut interner = Interner::new(); let mut interner = Interner::new();
@ -324,11 +320,30 @@ impl<'a> CodeGenerator<'a> {
// assuming one subject at the moment // assuming one subject at the moment
let subject = subjects[0].clone(); let subject = subjects[0].clone();
if clauses.len() <= 1 { if clauses.len() <= 1 {
todo!("Single clause cases not implemented") let mut value_vec: Vec<Air> = vec![];
} let mut pattern_vec: Vec<Air> = vec![];
let mut subject_vec: Vec<Air> = vec![];
self.build_ir(&clauses[0].then, &mut value_vec, scope.clone());
self.build_ir(&subject, &mut value_vec, scope.clone());
self.assignment_ir(
&clauses[0].pattern[0],
&mut pattern_vec,
&mut subject_vec,
&subject.tipo(),
AssignmentProperties {
value_is_data: false,
kind: AssignmentKind::Let,
},
scope,
);
ir_stack.append(&mut pattern_vec);
ir_stack.append(&mut value_vec);
} else {
let clauses = if matches!(clauses[0].pattern[0], Pattern::List { .. }) { let clauses = if matches!(clauses[0].pattern[0], Pattern::List { .. }) {
rearrange_clauses(clauses.clone()) rearrange_clauses(clauses.clone())
} else { } else {
@ -421,7 +436,8 @@ impl<'a> CodeGenerator<'a> {
} }
ir_stack.append(&mut pattern_vec); ir_stack.append(&mut pattern_vec);
}; }
}
} }
TypedExpr::If { TypedExpr::If {
branches, branches,
@ -479,7 +495,9 @@ impl<'a> CodeGenerator<'a> {
tipo, tipo,
.. ..
} => match constructor { } => match constructor {
ModuleValueConstructor::Record { .. } => todo!(), ModuleValueConstructor::Record { .. } => {
todo!("Records from modules not yet implemented.")
}
ModuleValueConstructor::Fn { name, module, .. } => { ModuleValueConstructor::Fn { name, module, .. } => {
let func = self.functions.get(&FunctionAccessKey { let func = self.functions.get(&FunctionAccessKey {
module_name: module_name.clone(), module_name: module_name.clone(),
@ -798,7 +816,7 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(values); pattern_vec.append(values);
} }
Pattern::String { .. } => todo!(), Pattern::String { .. } => todo!("String matching in whens not yet implemented"),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
pattern_vec.push(Air::Void { pattern_vec.push(Air::Void {
scope: scope.clone(), scope: scope.clone(),
@ -821,7 +839,7 @@ impl<'a> CodeGenerator<'a> {
}); });
pattern_vec.append(values); pattern_vec.append(values);
} }
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => unreachable!(),
Pattern::Assign { name, pattern, .. } => { Pattern::Assign { name, pattern, .. } => {
let mut new_vec = vec![]; let mut new_vec = vec![];
new_vec.push(Air::Let { new_vec.push(Air::Let {
@ -988,11 +1006,11 @@ impl<'a> CodeGenerator<'a> {
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
match pattern { match pattern {
Pattern::Int { .. } => todo!(), Pattern::Int { .. } => unreachable!(),
Pattern::String { .. } => todo!(), Pattern::String { .. } => unreachable!(),
Pattern::Var { .. } => todo!(), Pattern::Var { .. } => unreachable!(),
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => unreachable!(),
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!("Nested assign not yet implemented"),
Pattern::Discard { .. } => { Pattern::Discard { .. } => {
pattern_vec.push(Air::Void { scope }); pattern_vec.push(Air::Void { scope });
@ -1022,7 +1040,7 @@ impl<'a> CodeGenerator<'a> {
tail_name = name.clone(); tail_name = name.clone();
} }
Pattern::Discard { .. } => {} Pattern::Discard { .. } => {}
_ => todo!(), _ => unreachable!("Patterns in tail of list should not allow this"),
} }
} }
@ -1458,7 +1476,10 @@ impl<'a> CodeGenerator<'a> {
Some(item_name) Some(item_name)
} }
_ => todo!(), Pattern::Assign { .. } => todo!("Nested assign is not yet done"),
Pattern::Int { .. } => unimplemented!(),
Pattern::String { .. } => unimplemented!(),
Pattern::VarUsage { .. } => unreachable!(),
} }
} }
@ -1506,8 +1527,8 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(&mut assert_vec); pattern_vec.append(&mut assert_vec);
} }
} }
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => unreachable!(),
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!("Assign not yet implemented yet"),
Pattern::Discard { .. } => { Pattern::Discard { .. } => {
pattern_vec.push(Air::Let { pattern_vec.push(Air::Let {
name: "_".to_string(), name: "_".to_string(),
@ -1616,7 +1637,9 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
names.push(name.clone()); names.push(name.clone());
} }
a @ Pattern::List { .. } => { a @ (Pattern::List { .. }
| Pattern::Constructor { .. }
| Pattern::Tuple { .. }) => {
let mut var_vec = 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());
@ -1646,7 +1669,13 @@ impl<'a> CodeGenerator<'a> {
scope.clone(), scope.clone(),
); );
} }
_ => todo!(), Pattern::Int { .. } => todo!(),
Pattern::String { .. } => todo!(),
Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => {
names.push("_".to_string());
}
} }
} }
@ -1700,9 +1729,9 @@ impl<'a> CodeGenerator<'a> {
&item.value, &item.value,
*field_index, *field_index,
&mut nested_pattern, &mut nested_pattern,
type_map.get(field_index).unwrap(),
&assignment_properties, &assignment_properties,
&scope, &scope,
false,
) )
}) })
.sorted_by(|item1, item2| item1.1.cmp(&item2.1)) .sorted_by(|item1, item2| item1.1.cmp(&item2.1))
@ -1726,59 +1755,45 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(&mut nested_pattern); pattern_vec.append(&mut nested_pattern);
} }
Pattern::Tuple { elems, .. } => { Pattern::Tuple { elems, .. } => {
let mut elements_vec = vec![]; let mut nested_pattern = vec![];
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
let mut names = vec![]; for (index, arg) in tipo.get_inner_types().iter().enumerate() {
for element in elems { let field_type = arg.clone();
match element { type_map.insert(index, field_type);
Pattern::Var { name, .. } => {
names.push(name.clone());
}
Pattern::Discard { .. } => {
names.push("_".to_string());
}
a @ Pattern::List { .. } => {
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(),
variant_name: String::new(),
});
self.pattern_ir(
a,
&mut elements_vec,
&mut var_vec,
&tipo.get_inner_types()[0],
assignment_properties.clone(),
scope.clone(),
);
}
_ => todo!(),
}
} }
let arguments_index = elems
.iter()
.enumerate()
.filter_map(|(tuple_index, item)| {
self.extract_arg_and_index(
item,
tuple_index,
&mut nested_pattern,
type_map.get(&tuple_index).unwrap(),
&assignment_properties,
&scope,
)
})
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
.collect::<Vec<(String, usize)>>();
if !arguments_index.is_empty() {
pattern_vec.push(Air::TupleAccessor { pattern_vec.push(Air::TupleAccessor {
names,
scope, scope,
names: arguments_index
.into_iter()
.map(|(item, _)| item)
.collect_vec(),
tipo: tipo.clone().into(), tipo: tipo.clone().into(),
check_last_item: false, check_last_item: true,
}); });
}
pattern_vec.append(values); pattern_vec.append(values);
pattern_vec.append(&mut elements_vec);
pattern_vec.append(&mut nested_pattern);
} }
} }
} }
@ -1819,7 +1834,9 @@ impl<'a> CodeGenerator<'a> {
} }
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
l @ Pattern::List { .. } => { l @ (Pattern::List { .. }
| Pattern::Constructor { .. }
| Pattern::Tuple { .. }) => {
let name = format!("list_item_id_{}", self.id_gen.next()); let name = format!("list_item_id_{}", self.id_gen.next());
names.push(name.clone()); names.push(name.clone());
@ -1842,8 +1859,6 @@ impl<'a> CodeGenerator<'a> {
scope.clone(), scope.clone(),
); );
} }
Pattern::Constructor { .. } => todo!(),
Pattern::Tuple { elems, .. } => todo!(),
_ => {} _ => {}
} }
} }
@ -1899,8 +1914,6 @@ impl<'a> CodeGenerator<'a> {
type_map.insert(index, field_type); type_map.insert(index, field_type);
} }
println!("TYPE IS {:#?}", type_map);
let arguments_index = arguments let arguments_index = arguments
.iter() .iter()
.filter_map(|item| { .filter_map(|item| {
@ -1910,9 +1923,9 @@ impl<'a> CodeGenerator<'a> {
&item.value, &item.value,
*field_index, *field_index,
&mut nested_pattern, &mut nested_pattern,
type_map.get(field_index).unwrap(),
&assignment_properties, &assignment_properties,
&scope, &scope,
true,
) )
}) })
.sorted_by(|item1, item2| item1.1.cmp(&item2.1)) .sorted_by(|item1, item2| item1.1.cmp(&item2.1))
@ -1974,9 +1987,9 @@ impl<'a> CodeGenerator<'a> {
item, item,
field_index, field_index,
&mut nested_pattern, &mut nested_pattern,
type_map.get(&field_index).unwrap(),
&assignment_properties, &assignment_properties,
&scope, &scope,
true,
) )
}) })
.sorted_by(|item1, item2| item1.1.cmp(&item2.1)) .sorted_by(|item1, item2| item1.1.cmp(&item2.1))
@ -2003,7 +2016,7 @@ impl<'a> CodeGenerator<'a> {
} }
} }
if !arguments_index.is_empty() { if !final_args.is_empty() {
pattern_vec.push(Air::TupleAccessor { pattern_vec.push(Air::TupleAccessor {
scope, scope,
names: final_args.into_iter().map(|(item, _)| item).collect_vec(), names: final_args.into_iter().map(|(item, _)| item).collect_vec(),
@ -2336,7 +2349,7 @@ impl<'a> CodeGenerator<'a> {
assert_vec.push(Air::ErrorTerm { assert_vec.push(Air::ErrorTerm {
scope, scope,
tipo: tipo.clone().into(), tipo: tipo.clone().into(),
label: None, label: Some("Constr index did not match any type variant".to_string()),
}); });
} }
} }
@ -2346,15 +2359,63 @@ impl<'a> CodeGenerator<'a> {
item: &Pattern<PatternConstructor, Arc<Type>>, item: &Pattern<PatternConstructor, Arc<Type>>,
field_index: usize, field_index: usize,
nested_pattern: &mut Vec<Air>, nested_pattern: &mut Vec<Air>,
tipo: &Type,
assignment_properties: &AssignmentProperties, assignment_properties: &AssignmentProperties,
scope: &[u64], scope: &[u64],
assert: bool,
) -> Option<(String, usize)> { ) -> Option<(String, usize)> {
{ {
let (discard, var_name) = match item { let (discard, var_name) = match item {
Pattern::Var { name, .. } => (false, name.clone()), Pattern::Var { name, .. } => (false, name.clone()),
Pattern::Discard { .. } => (true, "".to_string()), Pattern::Discard { .. } => (true, "".to_string()),
Pattern::List { .. } => todo!(), a @ Pattern::List { .. } => {
let id = self.id_gen.next();
let list_name = format!("__list_{id}");
if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data
&& !tipo.is_data()
{
self.recursive_assert_pattern(
a,
nested_pattern,
&mut vec![Air::Var {
scope: scope.to_owned(),
constructor: ValueConstructor::public(
tipo.clone().into(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: list_name.clone(),
variant_name: String::new(),
}],
tipo,
assignment_properties.clone(),
scope.to_owned(),
);
} else {
self.pattern_ir(
a,
nested_pattern,
&mut vec![Air::Var {
scope: scope.to_owned(),
constructor: ValueConstructor::public(
tipo.clone().into(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: list_name.clone(),
variant_name: String::new(),
}],
tipo,
assignment_properties.clone(),
scope.to_owned(),
);
}
(false, list_name)
}
a @ Pattern::Constructor { a @ Pattern::Constructor {
tipo, tipo,
name: constr_name, name: constr_name,
@ -2363,7 +2424,10 @@ impl<'a> CodeGenerator<'a> {
let id = self.id_gen.next(); let id = self.id_gen.next();
let constr_name = format!("{constr_name}_{id}"); let constr_name = format!("{constr_name}_{id}");
if assert { if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data
&& !tipo.is_data()
{
self.recursive_assert_pattern( self.recursive_assert_pattern(
a, a,
nested_pattern, nested_pattern,
@ -2405,7 +2469,59 @@ impl<'a> CodeGenerator<'a> {
(false, constr_name) (false, constr_name)
} }
_ => todo!(), a @ Pattern::Tuple { .. } => {
let id = self.id_gen.next();
let tuple_name = format!("__tuple_name_{id}");
if matches!(assignment_properties.kind, AssignmentKind::Assert)
&& assignment_properties.value_is_data
&& !tipo.is_data()
{
self.recursive_assert_pattern(
a,
nested_pattern,
&mut vec![Air::Var {
scope: scope.to_owned(),
constructor: ValueConstructor::public(
tipo.clone().into(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: tuple_name.clone(),
variant_name: String::new(),
}],
tipo,
assignment_properties.clone(),
scope.to_owned(),
);
} else {
self.pattern_ir(
a,
nested_pattern,
&mut vec![Air::Var {
scope: scope.to_owned(),
constructor: ValueConstructor::public(
tipo.clone().into(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: tuple_name.clone(),
variant_name: String::new(),
}],
tipo,
assignment_properties.clone(),
scope.to_owned(),
);
}
(false, tuple_name)
}
Pattern::Int { .. } => todo!(),
Pattern::String { .. } => todo!(),
Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(),
}; };
if discard { if discard {
@ -3367,10 +3483,7 @@ impl<'a> CodeGenerator<'a> {
})); }));
} }
ValueConstructorVariant::Record { ValueConstructorVariant::Record {
name: constr_name, name: constr_name, ..
field_map,
arity,
..
} => { } => {
if constructor.tipo.is_bool() { if constructor.tipo.is_bool() {
arg_stack arg_stack
@ -3391,59 +3504,10 @@ impl<'a> CodeGenerator<'a> {
.find(|(_, x)| x.name == *constr_name) .find(|(_, x)| x.name == *constr_name)
.unwrap(); .unwrap();
let mut fields = let fields =
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![])); Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]));
let tipo = constructor.tipo; let term = apply_wrap(
let args_type = tipo.arg_types().unwrap();
if let Some(field_map) = field_map.clone() {
for field in field_map
.fields
.iter()
.sorted_by(|item1, item2| {
let (a, _) = item1.1;
let (b, _) = item2.1;
a.cmp(b)
})
.zip(&args_type)
.rev()
{
// TODO revisit
fields = apply_wrap(
apply_wrap(
Term::Builtin(DefaultFunction::MkCons).force_wrap(),
convert_type_to_data(
Term::Var(Name {
text: field.0 .0.clone(),
unique: 0.into(),
}),
field.1,
),
),
fields,
);
}
} else {
for (index, arg) in args_type.iter().enumerate().take(*arity) {
fields = apply_wrap(
apply_wrap(
Term::Builtin(DefaultFunction::MkCons).force_wrap(),
convert_type_to_data(
Term::Var(Name {
text: format!("__arg_{}", index),
unique: 0.into(),
}),
arg,
),
),
fields,
);
}
}
let mut term = apply_wrap(
apply_wrap( apply_wrap(
Term::Builtin(DefaultFunction::ConstrData), Term::Builtin(DefaultFunction::ConstrData),
Term::Constant(UplcConstant::Integer( Term::Constant(UplcConstant::Integer(
@ -3453,37 +3517,6 @@ impl<'a> CodeGenerator<'a> {
fields, fields,
); );
if let Some(field_map) = field_map {
for field in field_map
.fields
.iter()
.sorted_by(|item1, item2| {
let (a, _) = item1.1;
let (b, _) = item2.1;
a.cmp(b)
})
.rev()
{
term = Term::Lambda {
parameter_name: Name {
text: field.0.clone(),
unique: 0.into(),
},
body: term.into(),
};
}
} else {
for (index, _) in args_type.iter().enumerate().take(*arity) {
term = Term::Lambda {
parameter_name: Name {
text: format!("__arg_{}", index),
unique: 0.into(),
},
body: term.into(),
};
}
}
arg_stack.push(term); arg_stack.push(term);
} }
} }
@ -4094,46 +4127,6 @@ impl<'a> CodeGenerator<'a> {
}; };
arg_stack.push(term); arg_stack.push(term);
} }
Air::Assert {
tipo,
value_is_data,
..
} => {
let constr = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap();
let trace_error = apply_wrap(
apply_wrap(
Term::Builtin(DefaultFunction::Trace).force_wrap(),
Term::Constant(UplcConstant::String("Assert Failed".to_string())),
),
Term::Delay(Term::Error.into()),
)
.force_wrap();
todo!();
// let condition = apply_wrap(
// apply_wrap(
// DefaultFunction::EqualsInteger.into(),
// Term::Constant(UplcConstant::Integer(constr_index as i128)),
// ),
// constr_index_exposer(constr),
// );
// term = delayed_if_else(condition, term, trace_error);
arg_stack.push(term);
}
Air::ListAssert {
scope,
tipo,
names,
tail,
value_is_data,
} => {
todo!();
}
Air::DefineFunc { Air::DefineFunc {
func_name, func_name,
params, params,
@ -4735,19 +4728,8 @@ impl<'a> CodeGenerator<'a> {
let names = indices.iter().cloned().map(|item| item.1).collect_vec(); let names = indices.iter().cloned().map(|item| item.1).collect_vec();
let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec(); let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec();
term = apply_wrap( let tail_list = if !indices.is_empty() {
Term::Lambda { apply_wrap(
parameter_name: Name {
text: format!("__constr_fields_{}", list_id),
unique: 0.into(),
},
body: apply_wrap(
Term::Lambda {
parameter_name: Name {
text: first_name.1.clone(),
unique: 0.into(),
},
body: apply_wrap(
list_access_to_uplc( list_access_to_uplc(
&names, &names,
&id_list, &id_list,
@ -4765,7 +4747,23 @@ impl<'a> CodeGenerator<'a> {
}), }),
), ),
) )
.into(), } else {
term
};
term = apply_wrap(
Term::Lambda {
parameter_name: Name {
text: format!("__constr_fields_{}", list_id),
unique: 0.into(),
},
body: apply_wrap(
Term::Lambda {
parameter_name: Name {
text: first_name.1.clone(),
unique: 0.into(),
},
body: tail_list.into(),
}, },
head_list, head_list,
) )

View File

@ -343,7 +343,7 @@ impl Machine {
Err(Error::UnexpectedBuiltinTermArgument(t.as_ref().clone())) Err(Error::UnexpectedBuiltinTermArgument(t.as_ref().clone()))
} }
} }
rest => Err(Error::NonFunctionalApplication(rest)), rest => Err(Error::NonFunctionalApplication(rest, argument)),
} }
} }

View File

@ -16,8 +16,8 @@ pub enum Error {
EvaluationFailure, EvaluationFailure,
#[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")] #[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")]
NonPolymorphicInstantiation(Value), NonPolymorphicInstantiation(Value),
#[error("Attempted to apply a non-function:\n\n{0:#?}")] #[error("Attempted to apply a non-function:\n\n{0:#?} to argument:\n\n{1:#?}")]
NonFunctionalApplication(Value), NonFunctionalApplication(Value, Value),
#[error("Type mismatch expected '{0}' got '{1}'")] #[error("Type mismatch expected '{0}' got '{1}'")]
TypeMismatch(Type, Type), TypeMismatch(Type, Type),
#[error("Type mismatch expected '(list a)' got '{0}'")] #[error("Type mismatch expected '(list a)' got '{0}'")]