Got nested field access working efficiently. Will clean up code soon.
This commit is contained in:
parent
e3fa9ac105
commit
805bf19081
|
@ -2,7 +2,6 @@ use std::{cmp::Ordering, collections::HashMap, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{Constant, Name, Program, Term, Unique},
|
ast::{Constant, Name, Program, Term, Unique},
|
||||||
builtins::DefaultFunction,
|
builtins::DefaultFunction,
|
||||||
|
@ -18,23 +17,28 @@ use crate::{
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ScopeLevels {
|
pub struct ScopeLevels {
|
||||||
scope_tracker: Vec<i32>,
|
scope_tracker: Vec<i32>,
|
||||||
|
field_depth: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScopeLevels {
|
impl ScopeLevels {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ScopeLevels {
|
ScopeLevels {
|
||||||
scope_tracker: vec![0],
|
scope_tracker: vec![0],
|
||||||
|
field_depth: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_less_than(&self, other: &ScopeLevels) -> bool {
|
pub fn is_less_than(&self, other: &ScopeLevels, include_depth: bool) -> bool {
|
||||||
if self.scope_tracker.is_empty() && !other.scope_tracker.is_empty() {
|
if self.scope_tracker.is_empty() && !other.scope_tracker.is_empty() {
|
||||||
return true;
|
return true;
|
||||||
} else if other.scope_tracker.is_empty() {
|
} else if other.scope_tracker.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = self.scope_tracker.len() < other.scope_tracker.len();
|
let mut result = self.scope_tracker.len() < other.scope_tracker.len()
|
||||||
|
|| (self.scope_tracker.len() == other.scope_tracker.len()
|
||||||
|
&& include_depth
|
||||||
|
&& self.field_depth < other.field_depth);
|
||||||
|
|
||||||
for (scope_self, scope_other) in self.scope_tracker.iter().zip(other.scope_tracker.iter()) {
|
for (scope_self, scope_other) in self.scope_tracker.iter().zip(other.scope_tracker.iter()) {
|
||||||
match scope_self.cmp(scope_other) {
|
match scope_self.cmp(scope_other) {
|
||||||
|
@ -64,6 +68,12 @@ impl ScopeLevels {
|
||||||
*new_scope.scope_tracker.last_mut().unwrap() += inc;
|
*new_scope.scope_tracker.last_mut().unwrap() += inc;
|
||||||
new_scope
|
new_scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn depth_increment(&self, inc: i32) -> ScopeLevels {
|
||||||
|
let mut new_scope = self.clone();
|
||||||
|
new_scope.field_depth += inc;
|
||||||
|
new_scope
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ScopeLevels {
|
impl Default for ScopeLevels {
|
||||||
|
@ -393,9 +403,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.uplc_data_usage_holder_lookup
|
.uplc_data_usage_holder_lookup
|
||||||
.get(&(module.to_string(), name.clone()))
|
.get(&(module.to_string(), name.clone()))
|
||||||
{
|
{
|
||||||
if scope_level.is_less_than(val) {
|
if scope_level.is_less_than(val, false) {
|
||||||
self.uplc_data_usage_holder_lookup
|
self.uplc_data_usage_holder_lookup
|
||||||
.insert((module, name.clone()), scope_level.scope_increment(1));
|
.insert((module, name.clone()), scope_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,11 +483,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a @ TypedExpr::RecordAccess { label, record, .. } => {
|
a @ TypedExpr::RecordAccess { label, record, .. } => {
|
||||||
self.recurse_scope_level(record, scope_level.scope_increment(1));
|
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 = "".to_string();
|
||||||
let mut module = "".to_string();
|
let mut module = "".to_string();
|
||||||
let mut current_record = *record.clone();
|
let mut current_record = *record.clone();
|
||||||
|
let mut current_scope = scope_level.clone();
|
||||||
while !is_var {
|
while !is_var {
|
||||||
match current_record.clone() {
|
match current_record.clone() {
|
||||||
TypedExpr::Var {
|
TypedExpr::Var {
|
||||||
|
@ -509,6 +520,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
format!("{label}_field_{current_var_name}")
|
format!("{label}_field_{current_var_name}")
|
||||||
};
|
};
|
||||||
current_record = *record.clone();
|
current_record = *record.clone();
|
||||||
|
current_scope = current_scope.depth_increment(1);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -519,16 +531,16 @@ impl<'a> CodeGenerator<'a> {
|
||||||
current_var_name.clone(),
|
current_var_name.clone(),
|
||||||
label.clone(),
|
label.clone(),
|
||||||
)) {
|
)) {
|
||||||
if scope_level.is_less_than(&val.0) {
|
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()),
|
(module.to_string(), current_var_name.clone(), label.clone()),
|
||||||
(scope_level.clone(), a.clone()),
|
(current_scope.clone(), a.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.uplc_data_holder_lookup.insert(
|
self.uplc_data_holder_lookup.insert(
|
||||||
(module.to_string(), current_var_name.clone(), label.clone()),
|
(module.to_string(), current_var_name.clone(), label.clone()),
|
||||||
(scope_level.clone(), a.clone()),
|
(current_scope.clone(), a.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,13 +548,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.uplc_data_usage_holder_lookup
|
.uplc_data_usage_holder_lookup
|
||||||
.get(&(module.to_string(), current_var_name.clone()))
|
.get(&(module.to_string(), current_var_name.clone()))
|
||||||
{
|
{
|
||||||
if scope_level.is_less_than(val) {
|
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.clone()), scope_level);
|
.insert((module, current_var_name), current_scope);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.uplc_data_usage_holder_lookup
|
self.uplc_data_usage_holder_lookup
|
||||||
.insert((module, current_var_name), scope_level);
|
.insert((module, current_var_name), current_scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a @ TypedExpr::ModuleSelect { constructor, .. } => match constructor {
|
a @ TypedExpr::ModuleSelect { constructor, .. } => match constructor {
|
||||||
|
@ -579,6 +591,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.get(&(module.to_string(), name.to_string()))
|
.get(&(module.to_string(), name.to_string()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0,
|
.0,
|
||||||
|
false,
|
||||||
) {
|
) {
|
||||||
self.uplc_function_holder_lookup.insert(
|
self.uplc_function_holder_lookup.insert(
|
||||||
(module.to_string(), name.to_string()),
|
(module.to_string(), name.to_string()),
|
||||||
|
@ -821,7 +834,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
argument: self
|
argument: self
|
||||||
.recurse_code_gen(value, scope_level.scope_increment(1))
|
.recurse_code_gen(value, scope_level.scope_increment_sequence(1))
|
||||||
.into(),
|
.into(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1051,6 +1064,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.get(func)
|
.get(func)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0,
|
.0,
|
||||||
|
false,
|
||||||
) {
|
) {
|
||||||
let func_def = self
|
let func_def = self
|
||||||
.functions
|
.functions
|
||||||
|
@ -1089,48 +1103,48 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
// Pull out all uplc data holder and data usage, Sort By Scope Level, Then
|
// Pull out all uplc data holder and data usage, Sort By Scope Level, Then
|
||||||
let mut data_holder: Vec<((String, String, String), (bool, ScopeLevels, u64))> = self
|
let mut data_holder: Vec<((String, String, String), (bool, ScopeLevels, u64))> = self
|
||||||
.uplc_data_holder_lookup
|
.uplc_data_usage_holder_lookup
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|record_scope| scope_level.is_less_than(&record_scope.1 .0))
|
.filter(|record_scope| scope_level.is_less_than(&record_scope.1, false))
|
||||||
.map(|((module, name, label), (scope, expr))| {
|
.map(|((module, name), scope)| {
|
||||||
let index = match expr {
|
|
||||||
TypedExpr::RecordAccess { index, .. } => index,
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
(
|
(
|
||||||
(module.to_string(), name.to_string(), label.to_string()),
|
(module.to_string(), name.to_string(), "".to_string()),
|
||||||
(false, scope.clone(), *index),
|
(true, scope.clone(), 0),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
data_holder.extend(
|
data_holder.extend(
|
||||||
self.uplc_data_usage_holder_lookup
|
self.uplc_data_holder_lookup
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|record_scope| scope_level.is_less_than(&record_scope.1))
|
.filter(|record_scope| scope_level.is_less_than(&record_scope.1 .0, false))
|
||||||
.map(|((module, name), scope)| {
|
.map(|((module, name, label), (scope, expr))| {
|
||||||
|
let index = match expr {
|
||||||
|
TypedExpr::RecordAccess { index, .. } => index,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
(
|
(
|
||||||
(module.to_string(), name.to_string(), "".to_string()),
|
(module.to_string(), name.to_string(), label.to_string()),
|
||||||
(true, scope.clone(), 0),
|
(false, scope.clone(), *index),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<((String, String, String), (bool, ScopeLevels, u64))>>(),
|
.collect::<Vec<((String, String, String), (bool, ScopeLevels, u64))>>(),
|
||||||
);
|
);
|
||||||
data_holder.sort_by(|b, d| {
|
data_holder.sort_by(|b, d| {
|
||||||
if b.1 .1.is_less_than(&d.1 .1) {
|
if b.1 .1.is_less_than(&d.1 .1, true) {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else if d.1 .1.is_less_than(&b.1 .1) {
|
} else if d.1 .1.is_less_than(&b.1 .1, true) {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
} else if b.1 .0 && !d.1 .0 {
|
} else if b.1 .0 && !d.1 .0 {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else if !b.1 .0 && d.1 .0 {
|
} else if d.1 .0 && !b.1 .0 {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
} else {
|
} else {
|
||||||
Ordering::Equal
|
Ordering::Equal
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (key @ (module, name, label), (is_data_usage, _, index)) in data_holder.iter() {
|
for (key @ (module, name, label), (is_data_usage, _, index)) in data_holder.iter().rev() {
|
||||||
if *is_data_usage {
|
if *is_data_usage {
|
||||||
term = Term::Apply {
|
term = Term::Apply {
|
||||||
function: Term::Lambda {
|
function: Term::Lambda {
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
|
|
||||||
|
pub type Signer {
|
||||||
|
hash: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub type ScriptContext {
|
pub type ScriptContext {
|
||||||
thing: ByteArray
|
signer: Signer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Redeem {
|
||||||
|
Buy
|
||||||
|
Sell
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Datum {
|
pub type Datum {
|
||||||
something: ScriptContext,
|
fin: Int,
|
||||||
fin: Int
|
sc: ScriptContext,
|
||||||
|
rdmr: Redeem,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eqInt(a: Int, b: Int) {
|
pub fn eqInt(a: Int, b: Int) {
|
||||||
|
|
|
@ -11,8 +11,9 @@ pub type Redeemer {
|
||||||
pub fn spend(datum: sample.Datum, rdmr: Redeemer, ctx: spend.ScriptContext) -> Bool {
|
pub fn spend(datum: sample.Datum, rdmr: Redeemer, ctx: spend.ScriptContext) -> Bool {
|
||||||
|
|
||||||
let y = 2
|
let y = 2
|
||||||
let x = 1
|
let x = datum.sc.signer
|
||||||
let a = datum.something.thing
|
let a = datum.sc.signer.hash
|
||||||
let b = 2
|
let b = datum.rdmr
|
||||||
b == 1
|
let c = 1
|
||||||
|
c == 1
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue