diff --git a/Cargo.lock b/Cargo.lock index 632a4c93..cb2987fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,8 +85,11 @@ name = "aiken-project" version = "0.0.24" dependencies = [ "aiken-lang", + "hex", "ignore", "miette", + "pallas", + "pallas-traverse", "petgraph", "regex", "serde", @@ -601,6 +604,21 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "pallas" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9a54e891592befe6d7da8e43dc61606b86375d7a094dd78cc4cdf32e26d779" +dependencies = [ + "pallas-addresses", + "pallas-codec", + "pallas-crypto", + "pallas-miniprotocols", + "pallas-multiplexer", + "pallas-primitives", + "pallas-traverse", +] + [[package]] name = "pallas-addresses" version = "0.14.0" @@ -640,6 +658,34 @@ dependencies = [ "thiserror", ] +[[package]] +name = "pallas-miniprotocols" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "665d8bba23eaa69ce5715249d69c0b8c49c6034fc3f5ea4f010f9437d6fc7167" +dependencies = [ + "hex", + "itertools", + "log", + "pallas-codec", + "pallas-multiplexer", + "thiserror", +] + +[[package]] +name = "pallas-multiplexer" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe342b801c5954cfd31159bc68a38cb597e18d7a4ae89fc9397f5abcb5c5696" +dependencies = [ + "byteorder", + "hex", + "log", + "pallas-codec", + "rand", + "thiserror", +] + [[package]] name = "pallas-primitives" version = "0.14.0" @@ -956,6 +1002,7 @@ version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ + "indexmap", "itoa", "ryu", "serde", diff --git a/crates/lang/src/ast.rs b/crates/lang/src/ast.rs index e8bc89f8..74b33737 100644 --- a/crates/lang/src/ast.rs +++ b/crates/lang/src/ast.rs @@ -69,6 +69,8 @@ impl UntypedModule { pub type TypedDefinition = Definition, TypedExpr, String, String>; pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>; +pub type TypedFunction = Function, TypedExpr>; + #[derive(Debug, Clone, PartialEq)] pub struct Function { pub arguments: Vec>, diff --git a/crates/lang/src/uplc.rs b/crates/lang/src/uplc.rs index 56dd475f..df1524ae 100644 --- a/crates/lang/src/uplc.rs +++ b/crates/lang/src/uplc.rs @@ -185,7 +185,7 @@ impl<'a> CodeGenerator<'a> { } pub(crate) fn recurse_scope_level(&mut self, body: &TypedExpr, scope_level: ScopeLevels) { - match dbg!(body) { + match body { TypedExpr::Int { .. } => {} TypedExpr::String { .. } => {} TypedExpr::ByteArray { .. } => {} @@ -393,7 +393,7 @@ impl<'a> CodeGenerator<'a> { value: &TypedExpr, scope_level: ScopeLevels, ) { - match dbg!(pattern) { + match pattern { Pattern::Int { .. } | Pattern::String { .. } | Pattern::Var { .. } => { self.recurse_scope_level(value, scope_level); } @@ -403,11 +403,11 @@ impl<'a> CodeGenerator<'a> { Pattern::Discard { .. } => todo!(), Pattern::List { .. } => todo!(), Pattern::Constructor { - name: constructor_name, + // name: constructor_name, tipo, - arguments, - constructor, - module, + // arguments, + // constructor, + // module, .. } => { self.recurse_scope_level(value, scope_level.scope_increment_sequence(1)); @@ -428,17 +428,17 @@ impl<'a> CodeGenerator<'a> { } } Type::Fn { .. } => { - let mapping_index = match constructor { - tipo::PatternConstructor::Record { name, field_map } => { - if let Some(fields_mapping) = field_map { - fields_mapping.fields.clone() - } else { - HashMap::new() - } - } - }; - let mut args = arguments.clone(); - let local_var_name = ""; + // let mapping_index = match constructor { + // tipo::PatternConstructor::Record { name, field_map } => { + // if let Some(fields_mapping) = field_map { + // fields_mapping.fields.clone() + // } else { + // HashMap::new() + // } + // } + // }; + // let mut args = arguments.clone(); + // let local_var_name = ""; // arguments.iter().map(|x| { // let name = match &x.value { // Pattern::Var { location, name } => { @@ -480,7 +480,7 @@ impl<'a> CodeGenerator<'a> { } fn recurse_code_gen(&mut self, body: &TypedExpr, scope_level: ScopeLevels) -> Term { - match dbg!(body) { + match body { TypedExpr::Int { value, .. } => { Term::Constant(Constant::Integer(value.parse::().unwrap())) } @@ -1090,6 +1090,7 @@ impl<'a> CodeGenerator<'a> { } // Pull out all uplc data holder and data usage, filter by Scope Level, Sort By Scope Depth, Then Apply + #[allow(clippy::type_complexity)] let mut data_holder: Vec<((String, String, String), (bool, ScopeLevels, u64))> = self .uplc_data_usage_holder_lookup .iter() diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index a12afb7e..40920443 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -16,7 +16,10 @@ miette = { version = "5.3.0", features = ["fancy"] } petgraph = "0.6.2" regex = "1.6.0" serde = { version = "1.0.144", features = ["derive"] } -serde_json = "1.0.85" +serde_json = { version = "1.0.85", features = ["preserve_order"] } thiserror = "1.0.37" toml = "0.5.9" walkdir = "2.3.2" +hex = "0.4.3" +pallas = "0.14.0" +pallas-traverse = "0.14.0" diff --git a/crates/project/src/lib.rs b/crates/project/src/lib.rs index 9ca2c450..354983c4 100644 --- a/crates/project/src/lib.rs +++ b/crates/project/src/lib.rs @@ -8,15 +8,22 @@ pub mod config; pub mod error; pub mod format; pub mod module; +pub mod script; use aiken_lang::{ - ast::{Definition, Function, ModuleKind}, + ast::{Definition, Function, ModuleKind, TypedFunction}, builtins, tipo::TypeInfo, uplc::CodeGenerator, IdGenerator, }; -use uplc::ast::{NamedDeBruijn, Program}; +use pallas::{ + codec::minicbor, + ledger::{addresses::Address, primitives::babbage}, +}; +use pallas_traverse::ComputeHash; +use script::Script; +use serde_json::json; use crate::{ config::Config, @@ -88,7 +95,9 @@ impl Project { let scripts = self.validate_scripts(&mut checked_modules)?; if uplc_gen { - self.code_gen(scripts, &checked_modules)?; + let programs = self.code_gen(scripts, &checked_modules)?; + + self.write_build_outputs(programs)?; } Ok(()) @@ -238,27 +247,19 @@ impl Project { fn validate_scripts( &self, checked_modules: &mut CheckedModules, - ) -> Result, Error> { + ) -> Result, Error> { let mut errors = Vec::new(); let mut scripts = Vec::new(); + let mut indices_to_remove = Vec::new(); for module in checked_modules.scripts() { - scripts.push(module.clone()); - - for def in module.ast.definitions() { - if let Definition::Fn(Function { - arguments, - location, - name, - return_type, - .. - }) = def - { - if VALIDATOR_NAMES.contains(&name.as_str()) { + for (index, def) in module.ast.definitions().enumerate() { + if let Definition::Fn(func_def) = def { + if VALIDATOR_NAMES.contains(&func_def.name.as_str()) { // validators must return a Bool - if !return_type.is_bool() { + if !func_def.return_type.is_bool() { errors.push(Error::ValidatorMustReturnBool { - location: *location, + location: func_def.location, src: module.code.clone(), path: module.input_path.clone(), }) @@ -266,35 +267,40 @@ impl Project { // depending on name, validate the minimum number of arguments // if too low, push a new error on to errors - if [MINT, CERT, WITHDRAWL].contains(&name.as_str()) && arguments.len() < 2 { + if [MINT, CERT, WITHDRAWL].contains(&func_def.name.as_str()) + && func_def.arguments.len() < 2 + { errors.push(Error::WrongValidatorArity { - location: *location, + location: func_def.location, src: module.code.clone(), path: module.input_path.clone(), - name: name.clone(), + name: func_def.name.clone(), at_least: 2, }) } - if SPEND == name && arguments.len() < 3 { + if SPEND == func_def.name && func_def.arguments.len() < 3 { errors.push(Error::WrongValidatorArity { - location: *location, + location: func_def.location, src: module.code.clone(), path: module.input_path.clone(), - name: name.clone(), + name: func_def.name.clone(), at_least: 3, }) } + + scripts.push((module.name.clone(), func_def.clone())); + indices_to_remove.push(index); } } } + + for index in indices_to_remove.drain(0..) { + module.ast.definitions.remove(index); + } } if errors.is_empty() { - for script in &scripts { - checked_modules.remove(&script.name); - } - Ok(scripts) } else { Err(Error::List(errors)) @@ -303,9 +309,9 @@ impl Project { fn code_gen( &mut self, - scripts: Vec, + scripts: Vec<(String, TypedFunction)>, checked_modules: &CheckedModules, - ) -> Result>, Error> { + ) -> Result, Error> { let mut programs = Vec::new(); let mut functions = HashMap::new(); let mut type_aliases = HashMap::new(); @@ -335,35 +341,106 @@ impl Project { } } - for script in scripts { - for def in script.ast.into_definitions() { - if let Definition::Fn(Function { - arguments, - name, - body, - .. - }) = def - { - if VALIDATOR_NAMES.contains(&name.as_str()) { - let mut generator = CodeGenerator::new( - &functions, - // &type_aliases, - &data_types, - // &imports, - // &constants, - ); + for (module_name, func_def) in scripts { + let Function { + arguments, + name, + body, + .. + } = func_def; - let program = generator.generate(body, arguments); + let mut generator = CodeGenerator::new( + &functions, + // &type_aliases, + &data_types, + // &imports, + // &constants, + ); - programs.push(program.try_into().unwrap()); - } - } - } + let program = generator.generate(body, arguments); + + let script = Script::new(module_name, name, program.try_into().unwrap()); + + programs.push(script); } Ok(programs) } + fn write_build_outputs(&self, programs: Vec