chore: Add scaffolding for assert

This commit is contained in:
Kasey White 2023-01-23 14:13:03 -05:00
parent 38c24cca01
commit d4eec1fe79
4 changed files with 142 additions and 41 deletions

View File

@ -98,7 +98,8 @@ pub enum Air {
// Assignment // Assignment
Assert { Assert {
scope: Vec<u64>, scope: Vec<u64>,
constr_index: usize, tipo: Arc<Type>,
value_is_data: bool,
}, },
Let { Let {
@ -106,6 +107,14 @@ pub enum Air {
name: String, name: String,
}, },
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>,
@ -260,6 +269,7 @@ impl Air {
| Air::BinOp { scope, .. } | Air::BinOp { scope, .. }
| Air::UnOp { scope, .. } | Air::UnOp { scope, .. }
| Air::Assert { scope, .. } | Air::Assert { scope, .. }
| Air::ListAssert { scope, .. }
| Air::Let { scope, .. } | Air::Let { scope, .. }
| Air::When { scope, .. } | Air::When { scope, .. }
| Air::Clause { scope, .. } | Air::Clause { scope, .. }
@ -338,6 +348,8 @@ 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::When { tipo, .. } | Air::When { tipo, .. }
| Air::Clause { tipo, .. } | Air::Clause { tipo, .. }
| Air::ListClause { tipo, .. } | Air::ListClause { tipo, .. }
@ -358,7 +370,6 @@ impl Air {
Air::DefineFunc { .. } Air::DefineFunc { .. }
| Air::Fn { .. } | Air::Fn { .. }
| Air::Assert { .. }
| Air::Let { .. } | Air::Let { .. }
| Air::WrapClause { .. } | Air::WrapClause { .. }
| Air::Finally { .. } | Air::Finally { .. }

View File

@ -1673,3 +1673,5 @@ pub fn replace_opaque_type(t: &mut Arc<Type>, data_types: IndexMap<DataTypeKey,
} }
} }
} }
pub fn recursive_assert(tipo: &Type, assert_vec: &mut Vec<Air>) {}

View File

@ -173,6 +173,14 @@ impl Type {
} }
} }
pub fn is_data(&self) -> bool {
match self {
Self::App { module, name, .. } => "Data" == name && module.is_empty(),
Self::Var { tipo } => tipo.borrow().is_data(),
_ => false,
}
}
pub fn is_generic(&self) -> bool { pub fn is_generic(&self) -> bool {
match self { match self {
Type::App { args, .. } => { Type::App { args, .. } => {
@ -467,6 +475,13 @@ impl TypeVar {
} }
} }
pub fn is_data(&self) -> bool {
match self {
Self::Link { tipo } => tipo.is_data(),
_ => false,
}
}
pub fn is_generic(&self) -> bool { pub fn is_generic(&self) -> bool {
match self { match self {
TypeVar::Generic { .. } => true, TypeVar::Generic { .. } => true,

View File

@ -26,12 +26,12 @@ use crate::{
convert_constants_to_data, convert_data_to_type, convert_type_to_data, get_common_ancestor, convert_constants_to_data, convert_data_to_type, convert_type_to_data, get_common_ancestor,
get_generics_and_type, handle_func_dependencies_ir, handle_recursion_ir, get_generics_and_type, handle_func_dependencies_ir, handle_recursion_ir,
list_access_to_uplc, lookup_data_type_by_tipo, monomorphize, rearrange_clauses, list_access_to_uplc, lookup_data_type_by_tipo, monomorphize, rearrange_clauses,
replace_opaque_type, wrap_validator_args, ClauseProperties, DataTypeKey, FuncComponents, recursive_assert, replace_opaque_type, wrap_validator_args, ClauseProperties, DataTypeKey,
FunctionAccessKey, FuncComponents, FunctionAccessKey,
}, },
expr::TypedExpr, expr::TypedExpr,
tipo::{ tipo::{
self, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
ValueConstructorVariant, ValueConstructorVariant,
}, },
IdGenerator, IdGenerator,
@ -76,11 +76,16 @@ impl<'a> CodeGenerator<'a> {
let mut ir_stack = vec![]; let mut ir_stack = vec![];
let scope = vec![self.id_gen.next()]; let scope = vec![self.id_gen.next()];
println!("{:#?}", body);
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);
@ -103,6 +108,7 @@ 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();
@ -285,6 +291,8 @@ impl<'a> CodeGenerator<'a> {
let mut value_scope = scope.clone(); let mut value_scope = scope.clone();
value_scope.push(self.id_gen.next()); value_scope.push(self.id_gen.next());
let value_is_data = value.tipo().is_data();
self.build_ir(value, &mut value_vec, value_scope); self.build_ir(value, &mut value_vec, value_scope);
self.assignment_ir( self.assignment_ir(
@ -292,6 +300,7 @@ impl<'a> CodeGenerator<'a> {
&mut pattern_vec, &mut pattern_vec,
&mut value_vec, &mut value_vec,
tipo, tipo,
value_is_data,
*kind, *kind,
scope, scope,
); );
@ -764,7 +773,7 @@ impl<'a> CodeGenerator<'a> {
fn when_ir( fn when_ir(
&mut self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>, values: &mut Vec<Air>,
tipo: &Type, tipo: &Type,
@ -962,7 +971,7 @@ impl<'a> CodeGenerator<'a> {
fn when_recursive_ir( fn when_recursive_ir(
&mut self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>, values: &mut Vec<Air>,
clause_properties: &mut ClauseProperties, clause_properties: &mut ClauseProperties,
@ -1244,7 +1253,7 @@ impl<'a> CodeGenerator<'a> {
fn nested_pattern_ir_and_label( fn nested_pattern_ir_and_label(
&mut self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
pattern_type: &Arc<Type>, pattern_type: &Arc<Type>,
scope: Vec<u64>, scope: Vec<u64>,
@ -1446,22 +1455,38 @@ impl<'a> CodeGenerator<'a> {
fn assignment_ir( fn assignment_ir(
&mut self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
value_vec: &mut Vec<Air>, value_vec: &mut Vec<Air>,
tipo: &Type, tipo: &Type,
value_is_data: bool,
kind: AssignmentKind, kind: AssignmentKind,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
match pattern { match pattern {
Pattern::Int { .. } | Pattern::String { .. } => unreachable!(), Pattern::Int { .. } | Pattern::String { .. } => unreachable!(),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
let mut assert_vec = vec![];
if matches!(kind, AssignmentKind::Assert) {
if value_is_data && !tipo.is_data() {
recursive_assert(tipo, &mut assert_vec);
}
pattern_vec.push(Air::Assert {
scope,
tipo: tipo.clone().into(),
value_is_data,
});
} else {
pattern_vec.push(Air::Let { pattern_vec.push(Air::Let {
name: name.clone(), name: name.clone(),
scope, scope,
}); });
}
pattern_vec.append(value_vec); pattern_vec.append(value_vec);
pattern_vec.append(&mut assert_vec);
} }
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
@ -1474,7 +1499,15 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(value_vec); pattern_vec.append(value_vec);
} }
list @ Pattern::List { .. } => { list @ Pattern::List { .. } => {
self.pattern_ir(list, pattern_vec, value_vec, tipo, scope); self.pattern_ir(
list,
pattern_vec,
value_vec,
tipo,
value_is_data,
kind,
scope,
);
} }
Pattern::Constructor { Pattern::Constructor {
name: constr_name, name: constr_name,
@ -1492,7 +1525,15 @@ impl<'a> CodeGenerator<'a> {
.unwrap(); .unwrap();
match kind { match kind {
AssignmentKind::Let => { AssignmentKind::Let => {
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope); self.pattern_ir(
pattern,
pattern_vec,
value_vec,
tipo,
value_is_data,
kind,
scope,
);
} }
AssignmentKind::Assert => { AssignmentKind::Assert => {
let name_id = self.id_gen.next(); let name_id = self.id_gen.next();
@ -1505,7 +1546,8 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.push(Air::Assert { pattern_vec.push(Air::Assert {
scope: scope.clone(), scope: scope.clone(),
constr_index: index, tipo: tipo.clone(),
value_is_data,
}); });
pattern_vec.push(Air::Var { pattern_vec.push(Air::Var {
@ -1535,6 +1577,8 @@ impl<'a> CodeGenerator<'a> {
variant_name: String::new(), variant_name: String::new(),
}], }],
tipo, tipo,
value_is_data,
kind,
scope, scope,
); );
} }
@ -1542,17 +1586,27 @@ impl<'a> CodeGenerator<'a> {
} }
} }
Pattern::Tuple { .. } => { Pattern::Tuple { .. } => {
self.pattern_ir(pattern, pattern_vec, value_vec, tipo, scope); self.pattern_ir(
pattern,
pattern_vec,
value_vec,
tipo,
value_is_data,
kind,
scope,
);
} }
} }
} }
fn pattern_ir( fn pattern_ir(
&mut self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_vec: &mut Vec<Air>,
values: &mut Vec<Air>, values: &mut Vec<Air>,
tipo: &Type, tipo: &Type,
value_is_data: bool,
kind: AssignmentKind,
scope: Vec<u64>, scope: Vec<u64>,
) { ) {
match pattern { match pattern {
@ -1561,11 +1615,7 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { .. } => todo!(), Pattern::Var { .. } => todo!(),
Pattern::VarUsage { .. } => todo!(), Pattern::VarUsage { .. } => todo!(),
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => { Pattern::Discard { .. } => todo!(),
pattern_vec.push(Air::Void { scope });
pattern_vec.append(values);
}
Pattern::List { elements, tail, .. } => { Pattern::List { elements, tail, .. } => {
let mut elements_vec = vec![]; let mut elements_vec = vec![];
@ -1601,6 +1651,8 @@ impl<'a> CodeGenerator<'a> {
&mut elements_vec, &mut elements_vec,
&mut var_vec, &mut var_vec,
&tipo.get_inner_types()[0], &tipo.get_inner_types()[0],
value_is_data,
kind,
scope.clone(), scope.clone(),
); );
} }
@ -1616,12 +1668,15 @@ impl<'a> CodeGenerator<'a> {
} }
} }
if matches!(kind, AssignmentKind::Assert) {
} else {
pattern_vec.push(Air::ListAccessor { pattern_vec.push(Air::ListAccessor {
names, names,
tail: tail.is_some(), tail: tail.is_some(),
scope, scope,
tipo: tipo.clone().into(), tipo: tipo.clone().into(),
}); });
}
pattern_vec.append(values); pattern_vec.append(values);
pattern_vec.append(&mut elements_vec); pattern_vec.append(&mut elements_vec);
@ -1644,9 +1699,7 @@ impl<'a> CodeGenerator<'a> {
let mut nested_pattern = vec![]; let mut nested_pattern = vec![];
if *is_record { if *is_record {
let field_map = match constructor { let field_map = match constructor {
tipo::PatternConstructor::Record { field_map, .. } => { PatternConstructor::Record { field_map, .. } => field_map.clone().unwrap(),
field_map.clone().unwrap()
}
}; };
let mut type_map: IndexMap<String, Arc<Type>> = IndexMap::new(); let mut type_map: IndexMap<String, Arc<Type>> = IndexMap::new();
@ -1690,6 +1743,8 @@ impl<'a> CodeGenerator<'a> {
variant_name: String::new(), variant_name: String::new(),
}], }],
tipo, tipo,
value_is_data,
kind,
scope.clone(), scope.clone(),
); );
@ -1756,6 +1811,8 @@ impl<'a> CodeGenerator<'a> {
variant_name: String::new(), variant_name: String::new(),
}], }],
tipo, tipo,
value_is_data,
kind,
scope.clone(), scope.clone(),
); );
@ -1826,6 +1883,8 @@ impl<'a> CodeGenerator<'a> {
&mut elements_vec, &mut elements_vec,
&mut var_vec, &mut var_vec,
&tipo.get_inner_types()[0], &tipo.get_inner_types()[0],
value_is_data,
kind,
scope.clone(), scope.clone(),
); );
} }
@ -3493,7 +3552,11 @@ impl<'a> CodeGenerator<'a> {
}; };
arg_stack.push(term); arg_stack.push(term);
} }
Air::Assert { constr_index, .. } => { Air::Assert {
tipo,
value_is_data,
..
} => {
let constr = arg_stack.pop().unwrap(); let constr = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
@ -3506,19 +3569,29 @@ impl<'a> CodeGenerator<'a> {
Term::Delay(Term::Error.into()), Term::Delay(Term::Error.into()),
) )
.force_wrap(); .force_wrap();
todo!();
let condition = apply_wrap( // let condition = apply_wrap(
apply_wrap( // apply_wrap(
DefaultFunction::EqualsInteger.into(), // DefaultFunction::EqualsInteger.into(),
Term::Constant(UplcConstant::Integer(constr_index as i128)), // Term::Constant(UplcConstant::Integer(constr_index as i128)),
), // ),
constr_index_exposer(constr), // constr_index_exposer(constr),
); // );
term = delayed_if_else(condition, term, trace_error); // term = delayed_if_else(condition, term, trace_error);
arg_stack.push(term); arg_stack.push(term);
} }
Air::ListAssert {
scope,
tipo,
names,
tail,
value_is_data,
} => {
todo!();
}
Air::DefineFunc { Air::DefineFunc {
func_name, func_name,
params, params,