feat: add complex function composability. Minor scope changes

This commit is contained in:
Kasey White 2022-11-14 01:53:17 -05:00 committed by Lucas
parent 491c13f3aa
commit 2cac7963c3
2 changed files with 107 additions and 87 deletions

View File

@ -120,6 +120,17 @@ impl<'a> CodeGenerator<'a> {
pub fn generate(&mut self, body: TypedExpr, arguments: Vec<TypedArg>) -> Program<Name> { pub fn generate(&mut self, body: TypedExpr, arguments: Vec<TypedArg>) -> Program<Name> {
self.recurse_scope_level(&body, ScopeLevels::new()); self.recurse_scope_level(&body, ScopeLevels::new());
self.uplc_function_holder_lookup
.sort_by(|_key1, value1, _key2, value2| {
if value1.is_less_than(value2, true) {
Ordering::Less
} else if value2.is_less_than(value1, true) {
Ordering::Greater
} else {
Ordering::Equal
}
});
let mut term = self.recurse_code_gen(&body, ScopeLevels::new()); let mut term = self.recurse_code_gen(&body, ScopeLevels::new());
// Apply constr exposer to top level. // Apply constr exposer to top level.
@ -202,7 +213,7 @@ impl<'a> CodeGenerator<'a> {
} }
pub(crate) fn recurse_scope_level(&mut self, body: &TypedExpr, scope_level: ScopeLevels) { pub(crate) fn recurse_scope_level(&mut self, body: &TypedExpr, scope_level: ScopeLevels) {
match dbg!(body) { match body {
TypedExpr::Int { .. } => {} TypedExpr::Int { .. } => {}
TypedExpr::String { .. } => {} TypedExpr::String { .. } => {}
TypedExpr::ByteArray { .. } => {} TypedExpr::ByteArray { .. } => {}
@ -221,17 +232,19 @@ impl<'a> CodeGenerator<'a> {
} => { } => {
match constructor.variant.clone() { match constructor.variant.clone() {
ValueConstructorVariant::LocalVariable { .. } => { ValueConstructorVariant::LocalVariable { .. } => {
let mut is_app_type = false; let mut is_done_loop = false;
let mut current_tipo: Type = (*constructor.tipo).clone(); let mut current_tipo: Type = (*constructor.tipo).clone();
let mut current_module = "".to_string(); let mut current_module = "".to_string();
while !is_app_type { while !is_done_loop {
match current_tipo.clone() { match current_tipo.clone() {
Type::App { module, .. } => { Type::App { module, .. } => {
is_app_type = true; is_done_loop = true;
current_module = module.clone(); current_module = module.clone();
} }
Type::Fn { .. } => todo!(), Type::Fn { .. } => {
is_done_loop = true;
}
Type::Var { tipo } => { Type::Var { tipo } => {
let x = tipo.borrow().clone(); let x = tipo.borrow().clone();
@ -268,11 +281,7 @@ impl<'a> CodeGenerator<'a> {
.get(&(module.to_string(), name.to_string())) .get(&(module.to_string(), name.to_string()))
.unwrap(); .unwrap();
self.recurse_scope_level( self.recurse_scope_level(&func_def.body, scope_level.clone());
&func_def.body,
scope_level
.scope_increment_sequence(func_def.arguments.len() as i32 + 1),
);
self.uplc_function_holder_lookup self.uplc_function_holder_lookup
.insert((module, name), scope_level); .insert((module, name), scope_level);
@ -282,16 +291,8 @@ impl<'a> CodeGenerator<'a> {
.unwrap(), .unwrap(),
false, false,
) { ) {
let func_def = self self.uplc_function_holder_lookup
.functions .insert((module, name), scope_level);
.get(&(module.to_string(), name.to_string()))
.unwrap();
self.uplc_function_holder_lookup.insert(
(module, name),
scope_level
.scope_increment_sequence(func_def.arguments.len() as i32 + 1),
);
} }
} }
ValueConstructorVariant::Record { .. } => { ValueConstructorVariant::Record { .. } => {
@ -305,10 +306,13 @@ impl<'a> CodeGenerator<'a> {
TypedExpr::Fn { .. } => todo!(), TypedExpr::Fn { .. } => todo!(),
TypedExpr::List { .. } => todo!(), TypedExpr::List { .. } => todo!(),
TypedExpr::Call { fun, args, .. } => { TypedExpr::Call { fun, args, .. } => {
self.recurse_scope_level(fun, scope_level.scope_increment(args.len() as i32 + 1)); self.recurse_scope_level(fun, scope_level.scope_increment(1));
for arg in args.iter() { for (index, arg) in args.iter().enumerate() {
self.recurse_scope_level(&arg.value, scope_level.clone()); self.recurse_scope_level(
&arg.value,
scope_level.scope_increment(index as i32 + 2),
);
} }
} }
TypedExpr::BinOp { left, right, .. } => { TypedExpr::BinOp { left, right, .. } => {
@ -626,11 +630,9 @@ 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![]));
let data_type = self if let Some(data_type) =
.data_types self.data_types.get(&(module.to_string(), name.to_string()))
.get(&(module.to_string(), name.to_string())) {
.unwrap();
let constr = data_type let constr = data_type
.constructors .constructors
.iter() .iter()
@ -683,8 +685,7 @@ impl<'a> CodeGenerator<'a> {
} }
term term
} else { } else {
let mut term = self let mut term = self.recurse_code_gen(fun, scope_level.scope_increment(1));
.recurse_code_gen(fun, scope_level.scope_increment(args.len() as i32 + 1));
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
term = Term::Apply { term = Term::Apply {
@ -692,7 +693,23 @@ impl<'a> CodeGenerator<'a> {
argument: self argument: self
.recurse_code_gen( .recurse_code_gen(
&arg.value, &arg.value,
scope_level.scope_increment(i as i32 + 1), scope_level.scope_increment(i as i32 + 2),
)
.into(),
};
}
term
}
} else {
let mut term = self.recurse_code_gen(fun, scope_level.scope_increment(1));
for (i, arg) in args.iter().enumerate() {
term = Term::Apply {
function: term.into(),
argument: self
.recurse_code_gen(
&arg.value,
scope_level.scope_increment(i as i32 + 2),
) )
.into(), .into(),
}; };

View File

@ -16,28 +16,31 @@ pub type Reen {
} }
pub fn twice(f: fn(Int) -> Int, x: Int) -> Int { pub fn twice(f: fn(Int) -> Int, initial: Int) -> Int {
f(f(x)) f(f(initial))
} }
pub fn add_one(x: Int) -> Int { pub fn add_one(value: Int) -> Int {
x + 1 value + 1
} }
pub fn add_two(x: Int) -> Int { pub fn add_two(x: Int) -> Int {
twice(add_one, x) twice(add_one, x)
} }
pub fn final_check(z: Int){
z < 4
}
pub fn spend( pub fn spend(
datum: sample.Datum, datum: sample.Datum,
rdmr: Redeemer, rdmr: Redeemer,
ctx: spend.ScriptContext, ctx: spend.ScriptContext,
) -> Bool { ) -> Bool {
let x = rdmr.signer
let z = datum.sc.signer.hash
let y = datum.sc
let a = datum.fin let a = datum.fin
a > 0 && z == x a
|> add_two
|> final_check
} }