refactor away from tuples

This commit is contained in:
Kasey White 2022-11-19 01:57:59 -05:00 committed by Lucas
parent 0069c1f68a
commit d4f3eafc22
2 changed files with 326 additions and 190 deletions

View File

@ -82,24 +82,59 @@ impl Default for ScopeLevels {
} }
} }
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ConstrFieldKey {
pub local_var: String,
pub field_name: String,
}
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct DataTypeKey {
pub module_name: String,
pub defined_type: String,
}
pub type ConstrUsageKey = String;
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct FunctionAccessKey {
pub module_name: String,
pub function_name: String,
}
#[derive(Clone)]
pub struct ConstrConversionInfo {
local_var: String,
field: Option<String>,
scope: ScopeLevels,
index: Option<u64>,
returning_type: String,
}
#[derive(Clone)]
pub struct ScopedExpr {
scope: ScopeLevels,
expr: TypedExpr,
}
pub struct CodeGenerator<'a> { pub struct CodeGenerator<'a> {
uplc_function_holder: Vec<(String, Term<Name>)>, uplc_function_holder: Vec<(String, Term<Name>)>,
uplc_function_holder_lookup: IndexMap<(String, String), ScopeLevels>, uplc_function_holder_lookup: IndexMap<FunctionAccessKey, ScopeLevels>,
uplc_data_holder_lookup: IndexMap<(String, String, String), (ScopeLevels, TypedExpr)>, uplc_data_holder_lookup: IndexMap<ConstrFieldKey, ScopedExpr>,
uplc_data_constr_lookup: IndexMap<(String, String), ScopeLevels>, uplc_data_constr_lookup: IndexMap<DataTypeKey, ScopeLevels>,
uplc_data_usage_holder_lookup: IndexMap<(String, String), ScopeLevels>, uplc_data_usage_holder_lookup: IndexMap<ConstrUsageKey, ScopeLevels>,
functions: &'a HashMap<(String, String), &'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<(String, String), &'a DataType<Arc<tipo::Type>>>, data_types: &'a HashMap<DataTypeKey, &'a DataType<Arc<tipo::Type>>>,
// imports: &'a HashMap<(String, String), &'a Use<String>>, // imports: &'a HashMap<(String, String), &'a Use<String>>,
// constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>, // constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>,
} }
impl<'a> CodeGenerator<'a> { impl<'a> CodeGenerator<'a> {
pub fn new( pub fn new(
functions: &'a HashMap<(String, String), &'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<(String, String), &'a DataType<Arc<tipo::Type>>>, data_types: &'a HashMap<DataTypeKey, &'a DataType<Arc<tipo::Type>>>,
// imports: &'a HashMap<(String, String), &'a Use<String>>, // imports: &'a HashMap<(String, String), &'a Use<String>>,
// constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>, // constants: &'a HashMap<(String, String), &'a ModuleConstant<Arc<tipo::Type>, String>>,
) -> Self { ) -> Self {
@ -232,26 +267,45 @@ impl<'a> CodeGenerator<'a> {
ValueConstructorVariant::ModuleFn { name, module, .. } => { ValueConstructorVariant::ModuleFn { name, module, .. } => {
if self if self
.uplc_function_holder_lookup .uplc_function_holder_lookup
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.is_none() .is_none()
{ {
let func_def = self let func_def = self
.functions .functions
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.unwrap(); .unwrap();
self.recurse_scope_level(&func_def.body, scope_level.clone()); self.recurse_scope_level(&func_def.body, scope_level.clone());
self.uplc_function_holder_lookup self.uplc_function_holder_lookup.insert(
.insert((module, name), scope_level); FunctionAccessKey {
module_name: module,
function_name: name,
},
scope_level,
);
} else if scope_level.is_less_than( } else if scope_level.is_less_than(
self.uplc_function_holder_lookup self.uplc_function_holder_lookup
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.unwrap(), .unwrap(),
false, false,
) { ) {
self.uplc_function_holder_lookup self.uplc_function_holder_lookup.insert(
.insert((module, name), scope_level); FunctionAccessKey {
module_name: module,
function_name: name,
},
scope_level,
);
} }
} }
ValueConstructorVariant::Record { .. } => { ValueConstructorVariant::Record { .. } => {
@ -321,11 +375,10 @@ impl<'a> CodeGenerator<'a> {
self.recurse_scope_level(&branch.body, scope_level.scope_increment_sequence(1)); self.recurse_scope_level(&branch.body, scope_level.scope_increment_sequence(1));
} }
} }
a @ TypedExpr::RecordAccess { label, record, .. } => { expr @ TypedExpr::RecordAccess { label, record, .. } => {
self.recurse_scope_level(record, scope_level.clone()); self.recurse_scope_level(record, scope_level.clone());
let mut is_var = false; let mut is_var = false;
let mut current_var_name = "".to_string(); let mut current_var_name = String::new();
let mut module = "".to_string();
let mut current_record = *record.clone(); let mut current_record = *record.clone();
let mut current_scope = scope_level; let mut current_scope = scope_level;
while !is_var { while !is_var {
@ -336,19 +389,13 @@ impl<'a> CodeGenerator<'a> {
constructor.clone().variant.clone(), constructor.clone().variant.clone(),
(*constructor.tipo).clone(), (*constructor.tipo).clone(),
) { ) {
( (ValueConstructorVariant::LocalVariable { .. }, Type::App { .. }) => {
ValueConstructorVariant::LocalVariable { .. },
Type::App {
module: app_module, ..
},
) => {
current_var_name = if current_var_name.is_empty() { current_var_name = if current_var_name.is_empty() {
name name
} else { } else {
format!("{name}_field_{current_var_name}") format!("{name}_field_{current_var_name}")
}; };
is_var = true; is_var = true;
module = app_module.to_string();
} }
_ => todo!(), _ => todo!(),
}, },
@ -365,35 +412,46 @@ impl<'a> CodeGenerator<'a> {
} }
} }
if let Some(val) = self.uplc_data_holder_lookup.get(&( if let Some(val) = self.uplc_data_holder_lookup.get(&ConstrFieldKey {
module.to_string(), local_var: current_var_name.clone(),
current_var_name.clone(), field_name: label.clone(),
label.clone(), }) {
)) { if current_scope.is_less_than(&val.scope, false) {
if current_scope.is_less_than(&val.0, false) {
self.uplc_data_holder_lookup.insert( self.uplc_data_holder_lookup.insert(
(module.to_string(), current_var_name.clone(), label.clone()), ConstrFieldKey {
(current_scope.clone(), a.clone()), local_var: current_var_name.clone(),
field_name: label.clone(),
},
ScopedExpr {
scope: current_scope.clone(),
expr: expr.clone(),
},
); );
} }
} else { } else {
self.uplc_data_holder_lookup.insert( self.uplc_data_holder_lookup.insert(
(module.to_string(), current_var_name.clone(), label.clone()), ConstrFieldKey {
(current_scope.clone(), a.clone()), local_var: current_var_name.clone(),
field_name: label.clone(),
},
ScopedExpr {
scope: current_scope.clone(),
expr: expr.clone(),
},
); );
} }
if let Some(val) = self if let Some(val) = self
.uplc_data_usage_holder_lookup .uplc_data_usage_holder_lookup
.get(&(module.to_string(), current_var_name.clone())) .get(&current_var_name.clone())
{ {
if current_scope.is_less_than(val, false) { if current_scope.is_less_than(val, false) {
self.uplc_data_usage_holder_lookup self.uplc_data_usage_holder_lookup
.insert((module, current_var_name), current_scope); .insert(current_var_name, current_scope);
} }
} else { } else {
self.uplc_data_usage_holder_lookup self.uplc_data_usage_holder_lookup
.insert((module, current_var_name), current_scope); .insert(current_var_name, current_scope);
} }
} }
TypedExpr::ModuleSelect { constructor, .. } => match constructor { TypedExpr::ModuleSelect { constructor, .. } => match constructor {
@ -401,12 +459,18 @@ impl<'a> CodeGenerator<'a> {
ModuleValueConstructor::Fn { module, name, .. } => { ModuleValueConstructor::Fn { module, name, .. } => {
if self if self
.uplc_function_holder_lookup .uplc_function_holder_lookup
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.is_none() .is_none()
{ {
let func_def = self let func_def = self
.functions .functions
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.unwrap(); .unwrap();
self.recurse_scope_level( self.recurse_scope_level(
@ -415,21 +479,35 @@ impl<'a> CodeGenerator<'a> {
.scope_increment_sequence(func_def.arguments.len() as i32 + 1), .scope_increment_sequence(func_def.arguments.len() as i32 + 1),
); );
self.uplc_function_holder_lookup self.uplc_function_holder_lookup.insert(
.insert((module.to_string(), name.to_string()), scope_level); FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
},
scope_level,
);
} else if scope_level.is_less_than( } else if scope_level.is_less_than(
self.uplc_function_holder_lookup self.uplc_function_holder_lookup
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.unwrap(), .unwrap(),
false, false,
) { ) {
let func_def = self let func_def = self
.functions .functions
.get(&(module.to_string(), name.to_string())) .get(&FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
})
.unwrap(); .unwrap();
self.uplc_function_holder_lookup.insert( self.uplc_function_holder_lookup.insert(
(module.to_string(), name.to_string()), FunctionAccessKey {
module_name: module.to_string(),
function_name: name.to_string(),
},
scope_level scope_level
.scope_increment_sequence(func_def.arguments.len() as i32 + 1), .scope_increment_sequence(func_def.arguments.len() as i32 + 1),
); );
@ -471,17 +549,27 @@ impl<'a> CodeGenerator<'a> {
match &**tipo { match &**tipo {
Type::App { module, name, .. } => { Type::App { module, name, .. } => {
if let Some(val) = self if let Some(val) = self.uplc_data_constr_lookup.get(&DataTypeKey {
.uplc_data_constr_lookup module_name: module.to_string(),
.get(&(module.to_string(), name.clone())) defined_type: name.clone(),
{ }) {
if scope_level.is_less_than(val, false) { if scope_level.is_less_than(val, false) {
self.uplc_data_constr_lookup self.uplc_data_constr_lookup.insert(
.insert((module.to_string(), name.clone()), scope_level); DataTypeKey {
module_name: module.to_string(),
defined_type: name.clone(),
},
scope_level,
);
} }
} else { } else {
self.uplc_data_constr_lookup self.uplc_data_constr_lookup.insert(
.insert((module.to_string(), name.clone()), scope_level); DataTypeKey {
module_name: module.to_string(),
defined_type: name.clone(),
},
scope_level,
);
} }
} }
Type::Fn { .. } => { Type::Fn { .. } => {
@ -507,7 +595,7 @@ impl<'a> CodeGenerator<'a> {
rest => todo!("implement: {:#?}", rest), rest => todo!("implement: {:#?}", rest),
}; };
let mut type_name = "".to_string(); let mut type_name = String::new();
let mut is_app = false; let mut is_app = false;
let current_tipo = &*tipo; let current_tipo = &*tipo;
while !is_app { while !is_app {
@ -584,61 +672,70 @@ impl<'a> CodeGenerator<'a> {
kind: AssignmentKind::Let, kind: AssignmentKind::Let,
}; };
if let Some(val) = self.uplc_data_holder_lookup.get(&( if let Some(val) =
module.to_string(), self.uplc_data_holder_lookup.get(&ConstrFieldKey {
var_name.clone(), local_var: var_name.clone(),
label.clone(), field_name: label.clone(),
)) { })
if scope_level.is_less_than(&val.0, false) { {
if scope_level.is_less_than(&val.scope, false) {
self.uplc_data_holder_lookup.insert( self.uplc_data_holder_lookup.insert(
( ConstrFieldKey {
module.to_string(), local_var: var_name.clone(),
var_name.clone(), field_name: label.clone(),
label.clone(), },
), ScopedExpr {
( scope: scope_level.scope_increment(1),
scope_level.scope_increment(1), expr: record_access.clone(),
record_access.clone(), },
),
); );
} }
} else { } else {
self.uplc_data_holder_lookup.insert( self.uplc_data_holder_lookup.insert(
(module.to_string(), var_name.clone(), label.clone()), ConstrFieldKey {
(scope_level.scope_increment(1), record_access.clone()), local_var: var_name.clone(),
field_name: label.clone(),
},
ScopedExpr {
scope: scope_level.scope_increment(1),
expr: record_access.clone(),
},
); );
} }
if let Some(val) = self if let Some(val) =
.uplc_data_usage_holder_lookup self.uplc_data_usage_holder_lookup.get(&var_name.clone())
.get(&(module.to_string(), var_name.clone()))
{ {
if scope_level.is_less_than(val, false) { if scope_level.is_less_than(val, false) {
self.uplc_data_usage_holder_lookup.insert( self.uplc_data_usage_holder_lookup
(module.to_string(), var_name.clone()), .insert(var_name.clone(), scope_level.clone());
scope_level.clone(),
);
} }
} else { } else {
self.uplc_data_usage_holder_lookup.insert( self.uplc_data_usage_holder_lookup
(module.to_string(), var_name.clone()), .insert(var_name.clone(), scope_level.clone());
scope_level.clone(),
);
} }
if let Some(val) = self if let Some(val) =
.uplc_data_constr_lookup self.uplc_data_constr_lookup.get(&DataTypeKey {
.get(&(module.to_string(), type_name.clone())) module_name: module.to_string(),
defined_type: type_name.clone(),
})
{ {
if scope_level.is_less_than(val, false) { if scope_level.is_less_than(val, false) {
self.uplc_data_constr_lookup.insert( self.uplc_data_constr_lookup.insert(
(module.to_string(), type_name.clone()), DataTypeKey {
module_name: module.to_string(),
defined_type: type_name.clone(),
},
scope_level.clone(), scope_level.clone(),
); );
} }
} else { } else {
self.uplc_data_constr_lookup.insert( self.uplc_data_constr_lookup.insert(
(module.to_string(), type_name.clone()), DataTypeKey {
module_name: module.to_string(),
defined_type: type_name.clone(),
},
scope_level.clone(), scope_level.clone(),
); );
} }
@ -671,7 +768,7 @@ impl<'a> CodeGenerator<'a> {
.maybe_insert_def(term, scope_level.scope_increment_sequence(i as i32 + 1)); .maybe_insert_def(term, scope_level.scope_increment_sequence(i as i32 + 1));
self.uplc_function_holder self.uplc_function_holder
.push(("".to_string(), term.clone())); .push((String::new(), term.clone()));
} }
self.uplc_function_holder.pop().unwrap().1 self.uplc_function_holder.pop().unwrap().1
@ -711,9 +808,10 @@ impl<'a> CodeGenerator<'a> {
let mut term: Term<Name> = let mut term: Term<Name> =
Term::Constant(Constant::ProtoList(uplc::ast::Type::Data, vec![])); Term::Constant(Constant::ProtoList(uplc::ast::Type::Data, vec![]));
if let Some(data_type) = if let Some(data_type) = self.data_types.get(&DataTypeKey {
self.data_types.get(&(module.to_string(), name.to_string())) module_name: module.to_string(),
{ defined_type: name.to_string(),
}) {
let constr = data_type let constr = data_type
.constructors .constructors
.iter() .iter()
@ -1075,7 +1173,7 @@ impl<'a> CodeGenerator<'a> {
let mut is_var = false; let mut is_var = false;
let mut current_var_name = "".to_string(); let mut current_var_name = String::new();
let mut current_subject = subject.clone(); let mut current_subject = subject.clone();
@ -1111,7 +1209,7 @@ impl<'a> CodeGenerator<'a> {
let current_clauses = clauses.clone(); let current_clauses = clauses.clone();
let mut current_module = "".to_string(); let mut current_module = String::new();
let mut total_constr_length = 0; let mut total_constr_length = 0;
let pattern = &clauses[0].pattern[0]; let pattern = &clauses[0].pattern[0];
@ -1120,12 +1218,16 @@ impl<'a> CodeGenerator<'a> {
Pattern::Constructor { tipo, .. } => { Pattern::Constructor { tipo, .. } => {
let mut is_app = false; let mut is_app = false;
let mut tipo = &**tipo; let mut tipo = &**tipo;
let mut key: (String, String) = ("".to_string(), "".to_string()); let mut key = DataTypeKey {
module_name: String::new(),
defined_type: String::new(),
};
while !is_app { while !is_app {
match tipo { match tipo {
Type::App { module, name, .. } => { Type::App { module, name, .. } => {
is_app = true; is_app = true;
key = (module.clone(), name.clone()); key.module_name = module.clone();
key.defined_type = name.clone();
} }
Type::Fn { ret, .. } => { Type::Fn { ret, .. } => {
tipo = ret; tipo = ret;
@ -1161,13 +1263,13 @@ impl<'a> CodeGenerator<'a> {
let label = let label =
field.clone().label.unwrap_or(format!("{index}")); field.clone().label.unwrap_or(format!("{index}"));
if let Some((_, TypedExpr::Assignment { pattern, .. })) = if let Some(ScopedExpr {
self.uplc_data_holder_lookup.get(&( expr: TypedExpr::Assignment { pattern, .. },
key.0.clone(), ..
current_var_name.to_string(), }) = self.uplc_data_holder_lookup.get(&ConstrFieldKey {
label.clone(), local_var: current_var_name.to_string(),
)) field_name: label.clone(),
{ }) {
let var_name = match pattern { let var_name = match pattern {
Pattern::Var { name, .. } => name, Pattern::Var { name, .. } => name,
_ => todo!(), _ => todo!(),
@ -1384,7 +1486,7 @@ impl<'a> CodeGenerator<'a> {
} }
TypedExpr::RecordAccess { label, record, .. } => { TypedExpr::RecordAccess { label, record, .. } => {
let mut is_var = false; let mut is_var = false;
let mut current_var_name = "".to_string(); let mut current_var_name = String::new();
let mut current_record = *record.clone(); let mut current_record = *record.clone();
while !is_var { while !is_var {
match current_record.clone() { match current_record.clone() {
@ -1442,15 +1544,15 @@ impl<'a> CodeGenerator<'a> {
let mut term = current_term; let mut term = current_term;
// attempt to insert function definitions where needed // attempt to insert function definitions where needed
for func in self.uplc_function_holder_lookup.clone().keys() { for func_key in self.uplc_function_holder_lookup.clone().keys() {
if scope_level.is_less_than( if scope_level.is_less_than(
self.uplc_function_holder_lookup.clone().get(func).unwrap(), self.uplc_function_holder_lookup
.clone()
.get(func_key)
.unwrap(),
false, false,
) { ) {
let func_def = self let func_def = self.functions.get(func_key).unwrap();
.functions
.get(&(func.0.to_string(), func.1.to_string()))
.unwrap();
let mut function_body = self.recurse_code_gen( let mut function_body = self.recurse_code_gen(
&func_def.body, &func_def.body,
@ -1470,7 +1572,7 @@ impl<'a> CodeGenerator<'a> {
term = Term::Apply { term = Term::Apply {
function: Term::Lambda { function: Term::Lambda {
parameter_name: Name { parameter_name: Name {
text: format!("{}_{}", func.0, func.1), text: format!("{}_{}", func_key.module_name, func_key.function_name),
unique: 0.into(), unique: 0.into(),
}, },
body: term.into(), body: term.into(),
@ -1478,7 +1580,7 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
argument: function_body.into(), argument: function_body.into(),
}; };
self.uplc_function_holder_lookup.shift_remove(func); self.uplc_function_holder_lookup.shift_remove(func_key);
} }
} }
@ -1577,7 +1679,7 @@ impl<'a> CodeGenerator<'a> {
} }
.into(), .into(),
}; };
let module = &key.0; let module = &key.module_name;
term = Term::Apply { term = Term::Apply {
function: Term::Lambda { function: Term::Lambda {
@ -1594,28 +1696,37 @@ impl<'a> CodeGenerator<'a> {
} }
} }
// Pull out all uplc data holder and data usage, filter by Scope Level, Sort By Scope Depth, Then Apply // Pull out all uplc data holder fields and data usage, filter by Scope Level, Sort By Scope Depth, Then Apply
#[allow(clippy::type_complexity)] let mut data_holder: Vec<ConstrConversionInfo> = self
let mut data_holder: Vec<((String, String, String), (ScopeLevels, i128, String))> = self
.uplc_data_usage_holder_lookup .uplc_data_usage_holder_lookup
.iter() .clone()
.filter(|record_scope| scope_level.is_less_than(record_scope.1, false)) .into_iter()
.map(|((module, name), scope)| { .filter(|record_scope| scope_level.is_less_than(&record_scope.1, false))
( .map(|(var_name, scope)| ConstrConversionInfo {
(module.to_string(), name.to_string(), "".to_string()), local_var: var_name,
(scope.clone(), -1, "".to_string()), field: None,
) scope,
index: None,
returning_type: String::new(),
}) })
.collect(); .collect();
data_holder.extend( data_holder.extend(
self.uplc_data_holder_lookup self.uplc_data_holder_lookup
.iter() .clone()
.filter(|record_scope| scope_level.is_less_than(&record_scope.1 .0, false)) .into_iter()
.map(|((module, name, label), (scope, expr))| { .filter(|record_scope| scope_level.is_less_than(&record_scope.1.scope, false))
.map(
|(
ConstrFieldKey {
local_var,
field_name,
},
ScopedExpr { scope, expr },
)| {
let index_type = match expr { let index_type = match expr {
TypedExpr::RecordAccess { index, tipo, .. } => { TypedExpr::RecordAccess { index, tipo, .. } => {
let tipo = &**tipo; let tipo = &*tipo;
let name = match tipo { let name = match tipo {
Type::App { name, .. } => name, Type::App { name, .. } => name,
@ -1624,9 +1735,9 @@ impl<'a> CodeGenerator<'a> {
}; };
(index, name.clone()) (index, name.clone())
} }
TypedExpr::Assignment { value, .. } => match &**value { TypedExpr::Assignment { value, .. } => match *value {
TypedExpr::RecordAccess { index, tipo, .. } => { TypedExpr::RecordAccess { index, tipo, .. } => {
let tipo = &**tipo; let tipo = &*tipo;
let name = match tipo { let name = match tipo {
Type::App { name, .. } => name, Type::App { name, .. } => name,
@ -1640,57 +1751,40 @@ impl<'a> CodeGenerator<'a> {
_ => todo!(), _ => todo!(),
}; };
( ConstrConversionInfo {
(module.to_string(), name.to_string(), label.to_string()), local_var,
(scope.clone(), *index_type.0 as i128, index_type.1), field: Some(field_name),
scope,
index: Some(index_type.0),
returning_type: index_type.1,
}
},
) )
}) .collect::<Vec<ConstrConversionInfo>>(),
.collect::<Vec<((String, String, String), (ScopeLevels, i128, String))>>(),
); );
data_holder.sort_by(|item1, item2| { data_holder.sort_by(|item1, item2| {
if item1.1 .0.is_less_than(&item2.1 .0, true) { if item1.scope.is_less_than(&item2.scope, true) {
Ordering::Less Ordering::Less
} else if item2.1 .0.is_less_than(&item1.1 .0, true) { } else if item2.scope.is_less_than(&item1.scope, true) {
Ordering::Greater Ordering::Greater
} else if item1.1 .1 < item2.1 .1 { } else if item1.index < item2.index {
Ordering::Less Ordering::Less
} else if item2.1 .1 < item1.1 .1 { } else if item2.index < item1.index {
Ordering::Greater Ordering::Greater
} else { } else {
Ordering::Equal Ordering::Equal
} }
}); });
for (key @ (module, name, label), (_, index, tipo)) in data_holder.iter().rev() { for ConstrConversionInfo {
if index < &0 { local_var,
term = Term::Apply { field,
function: Term::Lambda { index,
parameter_name: Name { returning_type,
text: format!("{name}_fields"), ..
unique: 0.into(), } in data_holder.into_iter().rev()
}, {
body: term.into(), if let (Some(index), Some(field)) = (index, field) {
}
.into(),
// TODO: Find proper scope for this function if at all.
argument: Term::Apply {
function: Term::Var(Name {
text: "constr_fields_exposer".to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Var(Name {
text: name.to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
};
self.uplc_data_usage_holder_lookup
.shift_remove(&(module.clone(), name.clone()));
} else {
let var_term = Term::Apply { let var_term = Term::Apply {
function: Term::Apply { function: Term::Apply {
function: Term::Var(Name { function: Term::Var(Name {
@ -1699,16 +1793,16 @@ impl<'a> CodeGenerator<'a> {
}) })
.into(), .into(),
argument: Term::Var(Name { argument: Term::Var(Name {
text: format!("{name}_fields"), text: format!("{local_var}_fields"),
unique: 0.into(), unique: 0.into(),
}) })
.into(), .into(),
} }
.into(), .into(),
argument: Term::Constant(Constant::Integer(*index as i128)).into(), argument: Term::Constant(Constant::Integer(index as i128)).into(),
}; };
let type_conversion = match tipo.as_str() { let type_conversion = match returning_type.as_str() {
"ByteArray" => Term::Apply { "ByteArray" => Term::Apply {
function: Term::Builtin(DefaultFunction::UnBData).into(), function: Term::Builtin(DefaultFunction::UnBData).into(),
argument: var_term.into(), argument: var_term.into(),
@ -1723,7 +1817,7 @@ impl<'a> CodeGenerator<'a> {
term = Term::Apply { term = Term::Apply {
function: Term::Lambda { function: Term::Lambda {
parameter_name: Name { parameter_name: Name {
text: format!("{name}_field_{label}"), text: format!("{local_var}_field_{field}"),
unique: 0.into(), unique: 0.into(),
}, },
body: term.into(), body: term.into(),
@ -1731,7 +1825,37 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
argument: type_conversion.into(), argument: type_conversion.into(),
}; };
self.uplc_data_holder_lookup.shift_remove(key); self.uplc_data_holder_lookup.shift_remove(&ConstrFieldKey {
local_var,
field_name: field,
});
} else {
term = Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: format!("{local_var}_fields"),
unique: 0.into(),
},
body: term.into(),
}
.into(),
// TODO: Find proper scope for this function if at all.
argument: Term::Apply {
function: Term::Var(Name {
text: "constr_fields_exposer".to_string(),
unique: 0.into(),
})
.into(),
argument: Term::Var(Name {
text: local_var.to_string(),
unique: 0.into(),
})
.into(),
}
.into(),
};
self.uplc_data_usage_holder_lookup.shift_remove(&local_var);
} }
} }

View File

@ -14,7 +14,7 @@ use aiken_lang::{
ast::{Definition, Function, ModuleKind, TypedFunction}, ast::{Definition, Function, ModuleKind, TypedFunction},
builtins, builtins,
tipo::TypeInfo, tipo::TypeInfo,
uplc::CodeGenerator, uplc::{CodeGenerator, DataTypeKey, FunctionAccessKey},
IdGenerator, IdGenerator,
}; };
use pallas::{ use pallas::{
@ -312,13 +312,25 @@ impl Project {
for def in module.ast.definitions() { for def in module.ast.definitions() {
match def { match def {
Definition::Fn(func) => { Definition::Fn(func) => {
functions.insert((module.name.clone(), func.name.clone()), func); functions.insert(
FunctionAccessKey {
module_name: module.name.clone(),
function_name: func.name.clone(),
},
func,
);
} }
Definition::TypeAlias(ta) => { Definition::TypeAlias(ta) => {
type_aliases.insert((module.name.clone(), ta.alias.clone()), ta); type_aliases.insert((module.name.clone(), ta.alias.clone()), ta);
} }
Definition::DataType(dt) => { Definition::DataType(dt) => {
data_types.insert((module.name.clone(), dt.name.clone()), dt); data_types.insert(
DataTypeKey {
module_name: module.name.clone(),
defined_type: dt.name.clone(),
},
dt,
);
} }
Definition::Use(import) => { Definition::Use(import) => {
imports.insert((module.name.clone(), import.module.join("/")), import); imports.insert((module.name.clone(), import.module.join("/")), import);