Got nested field access working efficiently. Will clean up code soon.

This commit is contained in:
Kasey White 2022-11-06 01:58:47 -04:00 committed by Lucas
parent e3fa9ac105
commit 805bf19081
3 changed files with 65 additions and 38 deletions

View File

@ -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,9 +1103,21 @@ 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), scope)| {
(
(module.to_string(), name.to_string(), "".to_string()),
(true, scope.clone(), 0),
)
})
.collect();
data_holder.extend(
self.uplc_data_holder_lookup
.iter()
.filter(|record_scope| scope_level.is_less_than(&record_scope.1 .0, false))
.map(|((module, name, label), (scope, expr))| { .map(|((module, name, label), (scope, expr))| {
let index = match expr { let index = match expr {
TypedExpr::RecordAccess { index, .. } => index, TypedExpr::RecordAccess { index, .. } => index,
@ -1102,35 +1128,23 @@ impl<'a> CodeGenerator<'a> {
(false, scope.clone(), *index), (false, scope.clone(), *index),
) )
}) })
.collect();
data_holder.extend(
self.uplc_data_usage_holder_lookup
.iter()
.filter(|record_scope| scope_level.is_less_than(&record_scope.1))
.map(|((module, name), scope)| {
(
(module.to_string(), name.to_string(), "".to_string()),
(true, scope.clone(), 0),
)
})
.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 {

View File

@ -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) {

View File

@ -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
} }