From f6a72cc7f992eb9360d6ebc8b2ff2f3b5a755280 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Sat, 29 Oct 2022 04:02:44 -0400 Subject: [PATCH] did hacky way for scope level, but now i know how it works and how to fix --- crates/project/src/lib.rs | 646 +++++++++++++++------------- examples/sample/src/sample.ak | 5 +- examples/sample/src/scripts/swap.ak | 15 +- thing.uplc | 22 + 4 files changed, 390 insertions(+), 298 deletions(-) create mode 100644 thing.uplc diff --git a/crates/project/src/lib.rs b/crates/project/src/lib.rs index dfc3501b..c8f8ead4 100644 --- a/crates/project/src/lib.rs +++ b/crates/project/src/lib.rs @@ -370,6 +370,20 @@ impl Project { let mut lookup_map = HashMap::new(); + self.recurse_scope_level( + body, + scripts, + 0, + &mut lookup_map, + &functions, + &type_aliases, + &data_types, + &imports, + &constants, + ); + + println!("Look up map is {:#?}", lookup_map); + let mut term = self.recurse_code_gen( body, scripts, @@ -417,195 +431,295 @@ impl Project { Ok(programs) } - // fn recurse_simplifier( - // &self, - // body: &TypedExpr, - // scripts: &[CheckedModule], - // scope_level: i32, - // lookup_map: &mut HashMap<_, _>, - // functions: &HashMap< - // (String, String), - // &Function, TypedExpr>, - // >, - // type_aliases: &HashMap< - // (String, String), - // &aiken_lang::ast::TypeAlias>, - // >, - // data_types: &HashMap< - // (String, String), - // &aiken_lang::ast::DataType>, - // >, - // imports: &HashMap<(String, String), &aiken_lang::ast::Use>, - // constants: &HashMap< - // (String, String), - // &aiken_lang::ast::ModuleConstant, String>, - // >, - // ) { - // match body { - // TypedExpr::Int { - // location, - // tipo, - // value, - // } => {} - // TypedExpr::String { - // location, - // tipo, - // value, - // } => {} - // TypedExpr::ByteArray { - // location, - // tipo, - // bytes, - // } => {} - // TypedExpr::Sequence { - // location, - // expressions, - // } => { - // for expression in expressions { - // self.recurse_simplifier( - // expression, - // scripts, - // scope_level, - // lookup_map, - // functions, - // type_aliases, - // data_types, - // imports, - // constants, - // ); - // } - // } - // TypedExpr::Pipeline { - // location, - // expressions, - // } => { - // for expression in expressions { - // self.recurse_simplifier( - // expression, - // scripts, - // scope_level, - // lookup_map, - // functions, - // type_aliases, - // data_types, - // imports, - // constants, - // ); - // } - // } - // TypedExpr::Var { - // location, - // constructor, - // name, - // } => match constructor.variant { - // aiken_lang::tipo::ValueConstructorVariant::LocalVariable { location } => {} - // aiken_lang::tipo::ValueConstructorVariant::ModuleConstant { - // location, - // module, - // literal, - // } => {} - // aiken_lang::tipo::ValueConstructorVariant::ModuleFn { - // name, - // field_map, - // module, - // arity, - // location, - // builtin, - // } => { + pub(crate) fn recurse_scope_level( + &self, + body: &TypedExpr, + scripts: &[CheckedModule], + scope_level: i32, + uplc_function_holder_lookup: &mut HashMap<(String, String), (i32, TypedExpr)>, + functions: &HashMap<(String, String), &Function, TypedExpr>>, + type_aliases: &HashMap<(String, String), &ast::TypeAlias>>, + data_types: &HashMap<(String, String), &ast::DataType>>, + imports: &HashMap<(String, String), &ast::Use>, + constants: &HashMap< + (String, String), + &ast::ModuleConstant, String>, + >, + ) { + match dbg!(body) { + TypedExpr::Int { value, .. } => {} + TypedExpr::String { value, .. } => {} + TypedExpr::ByteArray { bytes, .. } => {} + TypedExpr::Sequence { + location, + expressions, + } => { + // let mut terms = Vec::new(); + for (i, exp) in expressions.iter().enumerate().rev() { + self.recurse_scope_level( + exp, + scripts, + scope_level + i as i32 * 100 + 1, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + } + } + TypedExpr::Pipeline { + location, + expressions, + } => todo!(), + TypedExpr::Var { + location, + constructor, + name, + } => {} + TypedExpr::Fn { + location, + tipo, + is_capture, + args, + body, + return_annotation, + } => todo!(), + TypedExpr::List { + location, + tipo, + elements, + tail, + } => todo!(), + TypedExpr::Call { + location, + tipo, + fun, + args, + } => { + let mut term = self.recurse_scope_level( + fun, + scripts, + scope_level + args.len() as i32, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); - // self.recurse_simplifier(&functions.get(&(module, name)).unwrap().body, scripts, scope_level, lookup_map, functions, type_aliases, data_types, imports, constants) - // } - // aiken_lang::tipo::ValueConstructorVariant::Record { - // name, - // arity, - // field_map, - // location, - // module, - // constructors_count, - // } => todo!(), - // }, - // TypedExpr::Fn { - // location, - // tipo, - // is_capture, - // args, - // body, - // return_annotation, - // } => todo!(), - // TypedExpr::List { - // location, - // tipo, - // elements, - // tail, - // } => todo!(), - // TypedExpr::Call { - // location, - // tipo, - // fun, - // args, - // } => todo!(), - // TypedExpr::BinOp { - // location, - // tipo, - // name, - // left, - // right, - // } => todo!(), - // TypedExpr::Assignment { - // location, - // tipo, - // value, - // pattern, - // kind, - // } => todo!(), - // TypedExpr::Try { - // location, - // tipo, - // value, - // then, - // pattern, - // } => todo!(), - // TypedExpr::When { - // location, - // tipo, - // subjects, - // clauses, - // } => todo!(), - // TypedExpr::If { - // location, - // branches, - // final_else, - // tipo, - // } => todo!(), - // TypedExpr::RecordAccess { - // location, - // tipo, - // label, - // index, - // record, - // } => todo!(), - // TypedExpr::ModuleSelect { - // location, - // tipo, - // label, - // module_name, - // module_alias, - // constructor, - // } => todo!(), - // TypedExpr::Todo { - // location, - // label, - // tipo, - // } => todo!(), - // TypedExpr::RecordUpdate { - // location, - // tipo, - // spread, - // args, - // } => todo!(), - // TypedExpr::Negate { location, value } => todo!(), - // } - // } + for (i, arg) in args.iter().enumerate() { + self.recurse_scope_level( + &arg.value, + scripts, + scope_level + i as i32, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + } + } + TypedExpr::BinOp { + location, + tipo, + name, + left, + right, + } => { + todo!() + } + TypedExpr::Assignment { + location, + tipo, + value, + pattern, + kind, + } => match pattern { + ast::Pattern::Int { location, value } => todo!(), + ast::Pattern::String { location, value } => todo!(), + ast::Pattern::Var { location, name } => { + self.recurse_scope_level( + value, + scripts, + scope_level + 1, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + } + ast::Pattern::VarUsage { + location, + name, + tipo, + } => todo!(), + ast::Pattern::Assign { + name, + location, + pattern, + } => todo!(), + ast::Pattern::Discard { name, location } => todo!(), + ast::Pattern::List { + location, + elements, + tail, + } => todo!(), + ast::Pattern::Constructor { + location, + name, + arguments, + module, + constructor, + with_spread, + tipo, + } => todo!(), + }, + TypedExpr::Try { + location, + tipo, + value, + then, + pattern, + } => todo!(), + TypedExpr::When { + location, + tipo, + subjects, + clauses, + } => todo!(), + //if statements increase scope due to branching. + TypedExpr::If { + branches, + final_else, + .. + } => { + let mut final_if_term = self.recurse_scope_level( + final_else, + scripts, + scope_level + 1, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + + for branch in branches { + // Need some scoping count to potentially replace condition with var since we should assume a condition + // may be repeated 3 + times or be large enough series of binops to warrant var replacement + let condition_term = self.recurse_scope_level( + &branch.condition, + scripts, + scope_level + 1, // Since this happens before branching. Maybe not increase scope level + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + + let branch_term = self.recurse_scope_level( + &branch.body, + scripts, + scope_level + 1, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + } + } + TypedExpr::RecordAccess { + location, + tipo, + label, + index, + record, + } => todo!(), + a @ TypedExpr::ModuleSelect { + location, + tipo, + label, + module_name, + module_alias, + constructor, + } => match constructor { + ModuleValueConstructor::Record { + name, + arity, + tipo, + field_map, + location, + } => todo!(), + ModuleValueConstructor::Fn { + location, + module, + name, + } => { + if !uplc_function_holder_lookup + .contains_key(&(module.to_string(), name.to_string())) + { + let func_def = functions + .get(&(module.to_string(), name.to_string())) + .unwrap(); + + let mut term = self.recurse_scope_level( + &func_def.body, + scripts, + scope_level + func_def.arguments.len() as i32, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + + uplc_function_holder_lookup.insert( + (module.to_string(), name.to_string()), + (scope_level, a.clone()), + ); + } + + if uplc_function_holder_lookup + .get(&(module.to_string(), name.to_string())) + .unwrap() + .0 + > scope_level + { + uplc_function_holder_lookup.insert( + (module.to_string(), name.to_string()), + (scope_level, a.clone()), + ); + } + } + ModuleValueConstructor::Constant { literal, location } => todo!(), + }, + TypedExpr::Todo { + location, + label, + tipo, + } => todo!(), + TypedExpr::RecordUpdate { + location, + tipo, + spread, + args, + } => todo!(), + TypedExpr::Negate { location, value } => todo!(), + } + } fn recurse_code_gen( &self, @@ -613,10 +727,10 @@ impl Project { scripts: &[CheckedModule], scope_level: i32, uplc_function_holder: &mut Vec<(String, Term)>, - uplc_function_holder_lookup: &mut HashMap<(String, String), i32>, + uplc_function_holder_lookup: &mut HashMap<(String, String), (i32, TypedExpr)>, functions: &HashMap< (String, String), - &Function, aiken_lang::expr::TypedExpr>, + &Function, TypedExpr>, >, type_aliases: &HashMap< (String, String), @@ -644,18 +758,17 @@ impl Project { location, expressions, } => { - // let mut terms = Vec::new(); for (i, exp) in expressions.iter().enumerate().rev() { println!( "The index is {} and the scope level is {} and next scope is {}", i, scope_level, - scope_level + i as i32 + 1 + scope_level + i as i32 * 100 + 1, ); let mut term = self.recurse_code_gen( exp, scripts, - scope_level + i as i32 + 1, + scope_level + i as i32 * 100 + 1, uplc_function_holder, uplc_function_holder_lookup, functions, @@ -665,50 +778,57 @@ impl Project { constants, ); - let mut above_scope = Vec::new(); - for func in uplc_function_holder.clone() { - let mut split_name = func.0.split('_'); - let mut split_name2 = func.0.split('_'); - - println!("This is scope level {}", scope_level + i as i32 + 1); - println!( - "This is uplc_function_holder_lookup scope {} and func is {}", - uplc_function_holder_lookup - .get(&( - split_name2.next().unwrap().to_string(), - split_name2.next().unwrap().to_string(), - )) - .unwrap(), - func.0 - ); - - if uplc_function_holder_lookup - .get(&( - split_name.next().unwrap().to_string(), - split_name.next().unwrap().to_string(), - )) - .unwrap() - < &(scope_level + i as i32 + 1) + for func in uplc_function_holder_lookup.clone().keys() { + if uplc_function_holder_lookup.clone().get(func).unwrap().0 + > scope_level + i as i32 * 100 { + println!("Scope level -1 is {}", scope_level + i as i32); + let func_def = functions + .get(&(func.0.to_string(), func.1.to_string())) + .unwrap(); + + let mut function_body = self.recurse_code_gen( + &func_def.body, + scripts, + scope_level + func_def.arguments.len() as i32, + uplc_function_holder, + uplc_function_holder_lookup, + functions, + type_aliases, + data_types, + imports, + constants, + ); + + for arg in func_def.arguments.iter().rev() { + function_body = Term::Lambda { + parameter_name: Name { + text: arg + .arg_name + .get_variable_name() + .unwrap_or("_") + .to_string(), + unique: Unique::new(0), + }, + body: Rc::new(function_body), + } + } + term = Term::Apply { function: Term::Lambda { parameter_name: Name { - text: func.0.clone(), + text: format!("{}_{}", func.0, func.1), unique: 0.into(), }, body: term.into(), } .into(), - argument: func.1.clone().into(), + argument: function_body.into(), }; - } else { - above_scope.push(func); + uplc_function_holder_lookup.remove(func); } - - uplc_function_holder.drain(0..); - - uplc_function_holder.append(&mut above_scope); } + uplc_function_holder.push(("".to_string(), term.clone())); } @@ -777,7 +897,11 @@ impl Project { fun, args, } => { - println!("Scope is {} and Scope with args is {}", scope_level, scope_level + args.len() as i32); + println!( + "Scope is {} and Scope with args is {}", + scope_level, + scope_level + args.len() as i32 + ); let mut term = self.recurse_code_gen( fun, scripts, @@ -846,13 +970,14 @@ impl Project { ast::Pattern::Int { location, value } => todo!(), ast::Pattern::String { location, value } => todo!(), ast::Pattern::Var { location, name } => Term::Apply { - function: Rc::new(Term::Lambda { + function: Term::Lambda { parameter_name: Name { text: name.to_string(), unique: 0.into(), }, body: uplc_function_holder.pop().unwrap().1.into(), - }), + } + .into(), argument: self .recurse_code_gen( value, @@ -868,6 +993,7 @@ impl Project { ) .into(), }, + ast::Pattern::VarUsage { location, name, @@ -998,66 +1124,10 @@ impl Project { location, module, name, - } => { - if !uplc_function_holder_lookup - .contains_key(&(module.to_string(), name.to_string())) - { - let func_def = functions - .get(&(module.to_string(), name.to_string())) - .unwrap(); - - let mut term = self.recurse_code_gen( - &func_def.body, - scripts, - scope_level + func_def.arguments.len() as i32, - uplc_function_holder, - uplc_function_holder_lookup, - functions, - type_aliases, - data_types, - imports, - constants, - ); - - for arg in func_def.arguments.iter().rev() { - term = Term::Lambda { - parameter_name: Name { - text: arg - .arg_name - .get_variable_name() - .unwrap_or("_") - .to_string(), - unique: Unique::new(0), - }, - body: Rc::new(term), - } - } - - uplc_function_holder.push((format!("{module}_{name}"), term)); - - uplc_function_holder_lookup - .insert((module.to_string(), name.to_string()), scope_level); - } - - if uplc_function_holder_lookup - .get(&(module.to_string(), name.to_string())) - .unwrap() - > &scope_level - { - println!( - "This is scope level in module select {} and func is {}_{}", - scope_level, - module.to_string(), - name.to_string() - ); - uplc_function_holder_lookup - .insert((module.to_string(), name.to_string()), scope_level); - } - Term::Var(Name { - text: format!("{module}_{name}"), - unique: 0.into(), - }) - } + } => Term::Var(Name { + text: format!("{module}_{name}"), + unique: 0.into(), + }), ModuleValueConstructor::Constant { literal, location } => todo!(), }, TypedExpr::Todo { diff --git a/examples/sample/src/sample.ak b/examples/sample/src/sample.ak index 99915c0b..8983ac74 100644 --- a/examples/sample/src/sample.ak +++ b/examples/sample/src/sample.ak @@ -6,6 +6,7 @@ pub type Datum { something: String, } -pub fn thing(a: Datum, b){ - a.something == b +pub fn thing(a: Bool) { + a } + diff --git a/examples/sample/src/scripts/swap.ak b/examples/sample/src/scripts/swap.ak index 7e091fe6..b7221c63 100644 --- a/examples/sample/src/scripts/swap.ak +++ b/examples/sample/src/scripts/swap.ak @@ -7,12 +7,11 @@ pub type Redeemer { Sell(Int) } -pub fn spend(datum: Datum, rdmr: Redeemer, ctx: spend.ScriptContext) -> Bool { - if datum.something == "Aiken" { - True - } else if datum.something == "Wow" { - True - } else { - False - } + +pub fn spend(datum: sample.Datum, rdmr: Redeemer, ctx: spend.ScriptContext) -> Bool { + let a = True + let b = sample.thing(a) + let c = sample.thing(b) + + c } diff --git a/thing.uplc b/thing.uplc new file mode 100644 index 00000000..03a11c1b --- /dev/null +++ b/thing.uplc @@ -0,0 +1,22 @@ +(program + 1.0.0 + (lam + datum + (lam + rdmr + (lam + ctx + [ + (lam + a + [ + (lam b [ [ (lam sample_thing sample_thing) (lam a a) ] a ]) + (con bool False) + ] + ) + (con bool True) + ] + ) + ) + ) +) \ No newline at end of file