refactor away from tuples
This commit is contained in:
parent
0069c1f68a
commit
d4f3eafc22
|
@ -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(¤t_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue