fix: expect_type now works on recursice constructors and validator args are now handled by air

This commit is contained in:
Kasey White 2023-04-06 00:44:03 -04:00 committed by Kasey
parent a1b3ae52d8
commit bc7b07c1d9
3 changed files with 181 additions and 95 deletions

View File

@ -18,7 +18,7 @@ use crate::{
ArgName, AssignmentKind, BinOp, Pattern, Span, TypedArg, TypedClause, TypedDataType, ArgName, AssignmentKind, BinOp, Pattern, Span, TypedArg, TypedClause, TypedDataType,
TypedFunction, TypedValidator, UnOp, TypedFunction, TypedValidator, UnOp,
}, },
builtins::{bool, data, void}, builtins::{bool, data},
expr::TypedExpr, expr::TypedExpr,
tipo::{ tipo::{
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
@ -97,7 +97,7 @@ impl<'a> CodeGenerator<'a> {
) -> Program<Name> { ) -> Program<Name> {
let mut ir_stack = AirStack::new(self.id_gen.clone()); let mut ir_stack = AirStack::new(self.id_gen.clone());
ir_stack.noop(); ir_stack.validator(fun.arguments.clone());
self.build(&fun.body, &mut ir_stack); self.build(&fun.body, &mut ir_stack);
@ -109,16 +109,11 @@ impl<'a> CodeGenerator<'a> {
let mut term = self.uplc_code_gen(&mut ir_stack); let mut term = self.uplc_code_gen(&mut ir_stack);
// Wrap the validator body if ifThenElse term unit error
term = term.final_wrapper();
term = self.wrap_validator_args(term, &fun.arguments, true);
if let Some(other) = other_fun { if let Some(other) = other_fun {
self.reset(); self.reset();
let mut other_ir_stack = AirStack::new(self.id_gen.clone()); let mut other_ir_stack = AirStack::new(self.id_gen.clone());
other_ir_stack.noop(); other_ir_stack.validator(other.arguments.clone());
self.build(&other.body, &mut other_ir_stack); self.build(&other.body, &mut other_ir_stack);
@ -144,7 +139,7 @@ impl<'a> CodeGenerator<'a> {
self.needs_field_access = true; self.needs_field_access = true;
} }
term = self.wrap_validator_args(term, params, false); term = builder::wrap_validator_args(term, params);
self.finalize(term) self.finalize(term)
} }
@ -152,7 +147,7 @@ impl<'a> CodeGenerator<'a> {
pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> { pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> {
let mut ir_stack = AirStack::new(self.id_gen.clone()); let mut ir_stack = AirStack::new(self.id_gen.clone());
ir_stack.noop(); ir_stack.validator(vec![]);
self.build(test_body, &mut ir_stack); self.build(test_body, &mut ir_stack);
@ -1647,8 +1642,6 @@ impl<'a> CodeGenerator<'a> {
{ {
let mut expect_stack = pattern_stack.empty_with_scope(); let mut expect_stack = pattern_stack.empty_with_scope();
println!("GETTING 2 HERE");
self.expect_pattern( self.expect_pattern(
pattern, pattern,
&mut expect_stack, &mut expect_stack,
@ -1991,7 +1984,7 @@ impl<'a> CodeGenerator<'a> {
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
expect_stack.merge(value_stack); expect_stack.merge(value_stack);
self.expect_type(tipo, expect_stack, name); self.expect_type(tipo, expect_stack, name, &mut IndexMap::new());
} }
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => unreachable!(), Pattern::Discard { .. } => unreachable!(),
@ -2044,7 +2037,14 @@ impl<'a> CodeGenerator<'a> {
format!("__tail_{}", self.id_gen.next()) format!("__tail_{}", self.id_gen.next())
}; };
self.expect_type(inner_list_type, &mut tail_stack, &name); self.expect_type(
inner_list_type,
&mut tail_stack,
&name,
&mut IndexMap::new(),
);
expect_list_stacks.push(tail_stack);
names.push(name); names.push(name);
@ -2126,6 +2126,7 @@ impl<'a> CodeGenerator<'a> {
type_map.get(&index).unwrap(), type_map.get(&index).unwrap(),
&mut stacks, &mut stacks,
&format!("__field_{index}_{id_next}"), &format!("__field_{index}_{id_next}"),
&mut IndexMap::new(),
) )
} }
} }
@ -2207,6 +2208,7 @@ impl<'a> CodeGenerator<'a> {
type_map.get(&index).unwrap(), type_map.get(&index).unwrap(),
&mut stacks, &mut stacks,
&format!("__tuple_{index}_{id_next}"), &format!("__tuple_{index}_{id_next}"),
&mut IndexMap::new(),
) )
} }
} }
@ -2223,7 +2225,13 @@ impl<'a> CodeGenerator<'a> {
} }
} }
fn expect_type(&mut self, tipo: &Type, expect_stack: &mut AirStack, name: &str) { fn expect_type(
&mut self,
tipo: &Type,
expect_stack: &mut AirStack,
name: &str,
defined_data_types: &mut IndexMap<String, u64>,
) {
let mut tipo = tipo.clone().into(); let mut tipo = tipo.clone().into();
builder::replace_opaque_type(&mut tipo, self.data_types.clone()); builder::replace_opaque_type(&mut tipo, self.data_types.clone());
@ -2262,12 +2270,14 @@ impl<'a> CodeGenerator<'a> {
&inner_pair_types[0], &inner_pair_types[0],
&mut pair_access_stack, &mut pair_access_stack,
&format!("__pair_fst_{}", id_pair.0), &format!("__pair_fst_{}", id_pair.0),
defined_data_types,
); );
self.expect_type( self.expect_type(
&inner_pair_types[1], &inner_pair_types[1],
&mut pair_access_stack, &mut pair_access_stack,
&format!("__pair_snd_{}", id_pair.1), &format!("__pair_snd_{}", id_pair.1),
defined_data_types,
); );
unwrap_function_stack unwrap_function_stack
@ -2309,6 +2319,7 @@ impl<'a> CodeGenerator<'a> {
inner_list_type, inner_list_type,
&mut list_access_stack, &mut list_access_stack,
&format!("__list_item_{new_id}"), &format!("__list_item_{new_id}"),
defined_data_types,
); );
unwrap_function_stack unwrap_function_stack
@ -2355,7 +2366,12 @@ impl<'a> CodeGenerator<'a> {
.into_iter() .into_iter()
.map(|(index, id)| (index, format!("__tuple_index_{index}_{id}"))) .map(|(index, id)| (index, format!("__tuple_index_{index}_{id}")))
{ {
self.expect_type(&tuple_inner_types[index], expect_stack, &name); self.expect_type(
&tuple_inner_types[index],
expect_stack,
&name,
defined_data_types,
);
} }
} else { } else {
let data_type = let data_type =
@ -2363,82 +2379,150 @@ impl<'a> CodeGenerator<'a> {
let new_id = self.id_gen.next(); let new_id = self.id_gen.next();
let mut clause_stack = expect_stack.empty_with_scope(); let mut var_stack = expect_stack.empty_with_scope();
let mut when_stack = expect_stack.empty_with_scope(); let mut func_stack = expect_stack.empty_with_scope();
let mut trace_stack = expect_stack.empty_with_scope(); let mut call_stack = expect_stack.empty_with_scope();
let mut subject_stack = expect_stack.empty_with_scope();
for (index, constr) in data_type.constructors.iter().enumerate() { let data_type_name = format!("__expect_{}", data_type.name);
let arg_indices = constr
.arguments
.iter()
.enumerate()
.map(|(index, arg)| {
let arg_name = arg
.label
.clone()
.unwrap_or(format!("__field_{index}_{new_id}"));
(index, arg_name, arg.tipo.clone()) let function = self.code_gen_functions.get(&data_type_name);
})
.collect_vec();
let mut arg_stack = expect_stack.empty_with_scope(); if function.is_none() && defined_data_types.get(&data_type_name).is_none() {
defined_data_types.insert(data_type_name.clone(), 1);
let mut arg_stack = if !arg_indices.is_empty() { let mut clause_stack = expect_stack.empty_with_scope();
let mut field_expose_stack = expect_stack.empty_with_scope(); let mut when_stack = expect_stack.empty_with_scope();
let mut trace_stack = expect_stack.empty_with_scope();
let mut subject_stack = expect_stack.empty_with_scope();
let mut data_type_stack = expect_stack.empty_with_scope();
field_expose_stack.integer(index.to_string()); for (index, constr) in data_type.constructors.iter().enumerate() {
let arg_indices = constr
.arguments
.iter()
.enumerate()
.map(|(index, arg)| {
let arg_name = arg
.label
.clone()
.unwrap_or(format!("__field_{index}_{new_id}"));
arg_stack.local_var(tipo.clone(), name); (index, arg_name, arg.tipo.clone())
})
.collect_vec();
field_expose_stack.fields_expose(arg_indices.clone(), true, arg_stack); let mut arg_stack = expect_stack.empty_with_scope();
field_expose_stack let mut arg_stack = if !arg_indices.is_empty() {
} else { let mut field_expose_stack = expect_stack.empty_with_scope();
let mut var_stack = expect_stack.empty_with_scope();
var_stack.local_var(tipo.clone(), name); field_expose_stack.integer(index.to_string());
arg_stack.integer(index.to_string()); arg_stack.local_var(tipo.clone(), name);
arg_stack.fields_empty(var_stack); field_expose_stack.fields_expose(arg_indices.clone(), true, arg_stack);
arg_stack field_expose_stack
}; } else {
let mut var_stack = expect_stack.empty_with_scope();
for (_index, name, tipo) in arg_indices { var_stack.local_var(tipo.clone(), name);
self.expect_type(&tipo, &mut arg_stack, &name);
arg_stack.integer(index.to_string());
arg_stack.fields_empty(var_stack);
arg_stack
};
for (_index, name, tipo) in arg_indices.clone() {
let mut call_stack = expect_stack.empty_with_scope();
let mut inner_defined_types = IndexMap::new();
self.expect_type(&tipo, &mut call_stack, &name, &mut inner_defined_types);
arg_stack.merge_child(call_stack);
for (inner_data_type, inner_count) in inner_defined_types {
if let Some(count) = defined_data_types.get_mut(&inner_data_type) {
*count += inner_count
} else {
defined_data_types.insert(inner_data_type, inner_count);
}
}
}
arg_stack.void();
clause_stack.clause(
tipo.clone(),
format!("__subject_{new_id}"),
false,
arg_stack,
);
} }
arg_stack.void(); trace_stack.trace(tipo.clone());
clause_stack.clause( trace_stack.string("Constr index did not match any type variant");
trace_stack.error(tipo.clone());
subject_stack.local_var(tipo.clone(), name);
when_stack.when(
tipo.clone(), tipo.clone(),
format!("__subject_{new_id}"), format!("__subject_{new_id}"),
false, subject_stack,
arg_stack, clause_stack,
trace_stack,
);
let recursive = *defined_data_types.get(&data_type_name).unwrap() >= 1;
data_type_stack.define_func(
&data_type_name,
"",
"",
vec![name.to_string()],
recursive,
when_stack,
);
self.code_gen_functions.insert(
data_type_name.clone(),
CodeGenFunction::Function(
data_type_stack.complete(),
defined_data_types
.keys()
.cloned()
.filter(|x| x != &data_type_name)
.collect_vec(),
),
); );
} }
trace_stack.trace(tipo.clone()); func_stack.var(
ValueConstructor::public(
trace_stack.string("Constr index did not match any type variant"); tipo.clone(),
ValueConstructorVariant::ModuleFn {
trace_stack.error(tipo.clone()); name: data_type_name.to_string(),
field_map: None,
subject_stack.local_var(tipo.clone(), name); module: "".to_string(),
arity: 1,
when_stack.when( location: Span::empty(),
tipo.clone(), builtin: None,
format!("__subject_{new_id}"), },
subject_stack, ),
clause_stack, data_type_name,
trace_stack, "",
); );
// Only used here var_stack.local_var(tipo.clone(), name);
expect_stack.expect_constr_from_data(tipo.clone(), when_stack);
call_stack.call(tipo.clone(), func_stack, vec![var_stack]);
expect_stack.expect_constr_from_data(tipo, call_stack);
} }
} }
@ -4831,7 +4915,15 @@ impl<'a> CodeGenerator<'a> {
} }
arg_stack.push(term); arg_stack.push(term);
} }
Air::Noop { .. } => {} Air::Validator { params, .. } => {
// Wrap the validator body if ifThenElse term unit error
let mut term = arg_stack.pop().unwrap();
term = term.final_wrapper();
term = self.wrap_validator_args(term, &params, true);
arg_stack.push(term);
}
} }
} }
@ -4854,9 +4946,8 @@ impl<'a> CodeGenerator<'a> {
param_stack.local_var(data(), arg.arg_name.get_variable_name().unwrap_or("_")); param_stack.local_var(data(), arg.arg_name.get_variable_name().unwrap_or("_"));
let mut actual_type = arg.tipo.clone(); let mut actual_type = arg.tipo.clone();
println!("GETTING HERE");
replace_opaque_type(&mut actual_type, self.data_types.clone()); replace_opaque_type(&mut actual_type, self.data_types.clone());
println!("ALSO HERE. TYPE IS {:#?}", actual_type);
self.assignment( self.assignment(
&Pattern::Var { &Pattern::Var {
@ -4876,8 +4967,6 @@ impl<'a> CodeGenerator<'a> {
arg.arg_name.get_variable_name().unwrap_or("_").to_string(), arg.arg_name.get_variable_name().unwrap_or("_").to_string(),
); );
println!("CONTINUING HERE");
let mut air_vec = air_stack.complete(); let mut air_vec = air_stack.complete();
term = term term = term

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use uplc::builtins::DefaultFunction; use uplc::builtins::DefaultFunction;
use crate::{ use crate::{
ast::{BinOp, UnOp}, ast::{Arg, BinOp, UnOp},
tipo::{Type, ValueConstructor}, tipo::{Type, ValueConstructor},
}; };
@ -213,8 +213,9 @@ pub enum Air {
scope: Scope, scope: Scope,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
Noop { Validator {
scope: Scope, scope: Scope,
params: Vec<Arg<Arc<Type>>>,
}, },
FieldsEmpty { FieldsEmpty {
scope: Scope, scope: Scope,
@ -263,7 +264,7 @@ impl Air {
| Air::TupleIndex { scope, .. } | Air::TupleIndex { scope, .. }
| Air::ErrorTerm { scope, .. } | Air::ErrorTerm { scope, .. }
| Air::Trace { scope, .. } | Air::Trace { scope, .. }
| Air::Noop { scope } => scope.clone(), | Air::Validator { scope, .. } => scope.clone(),
} }
} }
pub fn scope_mut(&mut self) -> &mut Scope { pub fn scope_mut(&mut self) -> &mut Scope {
@ -307,7 +308,7 @@ impl Air {
| Air::TupleIndex { scope, .. } | Air::TupleIndex { scope, .. }
| Air::ErrorTerm { scope, .. } | Air::ErrorTerm { scope, .. }
| Air::Trace { scope, .. } | Air::Trace { scope, .. }
| Air::Noop { scope } => scope, | Air::Validator { scope, .. } => scope,
} }
} }
pub fn tipo(&self) -> Option<Arc<Type>> { pub fn tipo(&self) -> Option<Arc<Type>> {
@ -398,7 +399,7 @@ impl Air {
| Air::Finally { .. } | Air::Finally { .. }
| Air::FieldsExpose { .. } | Air::FieldsExpose { .. }
| Air::FieldsEmpty { .. } | Air::FieldsEmpty { .. }
| Air::Noop { .. } => None, | Air::Validator { .. } => None,
Air::UnOp { op, .. } => match op { Air::UnOp { op, .. } => match op {
UnOp::Not => Some( UnOp::Not => Some(
Type::App { Type::App {

View File

@ -1,10 +1,11 @@
use std::{rc::Rc, sync::Arc}; use std::{rc::Rc, sync::Arc};
use indexmap::IndexSet; use indexmap::IndexSet;
use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
use crate::{ use crate::{
ast::Span, ast::{Arg, Span},
builtins::{data, list, void}, builtins::{data, list, void},
tipo::{Type, ValueConstructor, ValueConstructorVariant}, tipo::{Type, ValueConstructor, ValueConstructorVariant},
IdGenerator, IdGenerator,
@ -681,30 +682,31 @@ impl AirStack {
pub fn define_func( pub fn define_func(
&mut self, &mut self,
func_name: String, func_name: impl ToString,
module_name: String, module_name: impl ToString,
variant_name: String, variant_name: impl ToString,
params: Vec<String>, params: Vec<String>,
recursive: bool, recursive: bool,
body_stack: AirStack, body_stack: AirStack,
) { ) {
self.air.push(Air::DefineFunc { self.air.push(Air::DefineFunc {
scope: self.scope.clone(), scope: self.scope.clone(),
func_name, func_name: func_name.to_string(),
module_name, module_name: module_name.to_string(),
params, params,
recursive, recursive,
variant_name, variant_name: variant_name.to_string(),
}); });
self.merge_child(body_stack); self.merge_child(body_stack);
} }
pub fn noop(&mut self) { pub fn validator(&mut self, params: Vec<Arg<Arc<Type>>>) {
self.new_scope(); self.new_scope();
self.air.push(Air::Noop { self.air.push(Air::Validator {
scope: self.scope.clone(), scope: self.scope.clone(),
params,
}); });
} }
@ -752,13 +754,7 @@ impl AirStack {
void_stack.void(); void_stack.void();
void_stack.void(); void_stack.void();
self.list_clause( self.list_clause(void(), "__list_to_check", None, false, void_stack);
void(),
"__list_to_check",
None,
false,
void_stack,
);
self.choose_unit(check_with_stack); self.choose_unit(check_with_stack);