Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate odra::Module implementation #268

Merged
merged 7 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 1 addition & 41 deletions examples2/src/counter_pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use odra::Mapping;
use odra::Module;
use odra::ModuleWrapper;

#[odra_macros::module]
zie1ony marked this conversation as resolved.
Show resolved Hide resolved
pub struct CounterPack {
env: Rc<ContractEnv>,
counter0: ModuleWrapper<Counter>,
Expand Down Expand Up @@ -61,47 +62,6 @@ impl CounterPack {
}
}

// autogenerated
mod odra_core_module {
use super::*;

impl Module for CounterPack {
fn new(env: Rc<ContractEnv>) -> Self {
let counter0 = ModuleWrapper::new(Rc::clone(&env), 0);
let counter1 = ModuleWrapper::new(Rc::clone(&env), 1);
let counter2 = ModuleWrapper::new(Rc::clone(&env), 2);
let counter3 = ModuleWrapper::new(Rc::clone(&env), 3);
let counter4 = ModuleWrapper::new(Rc::clone(&env), 4);
let counter5 = ModuleWrapper::new(Rc::clone(&env), 5);
let counter6 = ModuleWrapper::new(Rc::clone(&env), 6);
let counter7 = ModuleWrapper::new(Rc::clone(&env), 7);
let counter8 = ModuleWrapper::new(Rc::clone(&env), 8);
let counter9 = ModuleWrapper::new(Rc::clone(&env), 9);
let counters = Mapping::new(Rc::clone(&env), 10);
let counters_map = Mapping::new(Rc::clone(&env), 11);
Self {
env,
counter0,
counter1,
counter2,
counter3,
counter4,
counter5,
counter6,
counter7,
counter8,
counter9,
counters,
counters_map
}
}

fn env(&self) -> Rc<ContractEnv> {
self.env.clone()
}
}
}

#[cfg(odra_module = "CounterPack")]
#[cfg(target_arch = "wasm32")]
mod __counter_pack_wasm_parts {
Expand Down
23 changes: 1 addition & 22 deletions examples2/src/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl From<Erc20Error> for OdraError {
}
}

#[odra_macros::module]
pub struct Erc20 {
env: Rc<ContractEnv>,
total_supply: Variable<U256>,
Expand Down Expand Up @@ -138,28 +139,6 @@ impl Erc20 {
}
}

// autogenerated for general purpose module.
mod __erc20_module {
use super::Erc20;
use odra::{module::Module, prelude::*, ContractEnv, Mapping, Variable};

impl Module for Erc20 {
fn new(env: Rc<ContractEnv>) -> Self {
let total_supply = Variable::new(Rc::clone(&env), 1);
let balances = Mapping::new(Rc::clone(&env), 2);
Self {
env,
total_supply,
balances
}
}

fn env(&self) -> Rc<ContractEnv> {
self.env.clone()
}
}
}

#[cfg(odra_module = "Erc20")]
mod __erc20_schema {
use odra::{contract_def::ContractBlueprint2, prelude::String};
Expand Down
2 changes: 1 addition & 1 deletion odra-macros/src/ast/host_ref_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ mod ref_item_tests {
self.env.last_call().contract_last_call(self.address)
}

pub fn try_total_supply(&self) -> Result<U256, OdraError> {
pub fn try_total_supply(&self) -> Result<U256, odra::OdraError> {
zie1ony marked this conversation as resolved.
Show resolved Hide resolved
self.env.call_contract(
self.address,
odra::CallDef::new(
Expand Down
2 changes: 2 additions & 0 deletions odra-macros/src/ast/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
mod deployer_item;
mod deployer_utils;
mod host_ref_item;
mod module_item;
mod parts_utils;
mod ref_item;
mod ref_utils;
mod test_parts;

pub(crate) use module_item::ModuleModItem;
pub(crate) use ref_item::RefItem;
pub(crate) use test_parts::{TestParts, TestPartsReexport};
192 changes: 192 additions & 0 deletions odra-macros/src/ast/module_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
use quote::{ToTokens, TokenStreamExt};
use syn::parse_quote;

use crate::{
ir::{EnumeratedTypedField, StructIR},
utils
};

use super::parts_utils::UseSuperItem;

#[derive(syn_derive::ToTokens)]
pub struct ModuleModItem {
mod_token: syn::token::Mod,
mod_ident: syn::Ident,
#[syn(braced)]
braces: syn::token::Brace,
#[syn(in = braces)]
use_super: UseSuperItem,
#[syn(in = braces)]
item: ModuleImplItem
}

impl TryFrom<&'_ StructIR> for ModuleModItem {
type Error = syn::Error;

fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
Ok(Self {
mod_token: Default::default(),
mod_ident: ir.module_mod_ident(),
use_super: UseSuperItem,
braces: Default::default(),
item: ir.try_into()?
})
}
}

#[derive(syn_derive::ToTokens)]
struct ModuleImplItem {
impl_token: syn::token::Impl,
trait_path: syn::Type,
for_token: syn::token::For,
module_path: syn::Ident,
#[syn(braced)]
braces: syn::token::Brace,
#[syn(in = braces)]
new_fn: NewModuleFnItem,
#[syn(in = braces)]
env_fn: EnvFnItem
}

impl TryFrom<&'_ StructIR> for ModuleImplItem {
type Error = syn::Error;

fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
Ok(Self {
impl_token: Default::default(),
trait_path: utils::ty::module(),
for_token: Default::default(),
module_path: ir.module_ident(),
braces: Default::default(),
new_fn: ir.try_into()?,
env_fn: EnvFnItem
})
}
}

#[derive(syn_derive::ToTokens)]
struct NewModuleFnItem {
sig: syn::Signature,
#[syn(braced)]
braces: syn::token::Brace,
#[syn(in = braces)]
#[to_tokens(|tokens, val| tokens.append_all(val))]
fields: Vec<ModuleFieldItem>,
#[syn(in = braces)]
instance: ModuleInstanceItem
}

impl TryFrom<&'_ StructIR> for NewModuleFnItem {
type Error = syn::Error;

fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
let ty_contract_env = utils::ty::contract_env();
let env = utils::ident::env();
let fields = ir.typed_fields()?;
Ok(Self {
sig: parse_quote!(fn new(#env: Rc<#ty_contract_env>) -> Self),
braces: Default::default(),
fields: fields.iter().map(Into::into).collect(),
instance: ir.try_into()?
})
}
}

#[derive(syn_derive::ToTokens)]
struct ModuleFieldItem {
let_token: syn::token::Let,
ident: syn::Ident,
assign_token: syn::token::Eq,
field_expr: syn::Expr,
semi_token: syn::token::Semi
}

impl From<&'_ EnumeratedTypedField> for ModuleFieldItem {
fn from(field: &'_ EnumeratedTypedField) -> Self {
Self {
let_token: Default::default(),
ident: field.ident.clone(),
assign_token: Default::default(),
field_expr: utils::expr::new_type(&field.ty, &utils::ident::env(), field.idx),
semi_token: Default::default()
}
}
}

#[derive(syn_derive::ToTokens)]
struct ModuleInstanceItem {
self_token: syn::token::SelfType,
#[syn(braced)]
braces: syn::token::Brace,
#[syn(in = braces)]
values: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]>
}

impl TryFrom<&'_ StructIR> for ModuleInstanceItem {
type Error = syn::Error;

fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
Ok(Self {
self_token: Default::default(),
braces: Default::default(),
values: ir.field_names()?.into_iter().collect()
})
}
}

struct EnvFnItem;

impl ToTokens for EnvFnItem {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let ty_contract_env = utils::ty::contract_env();
let m_env = utils::member::env();

tokens.extend(quote::quote!(
fn env(&self) -> Rc<#ty_contract_env> {
#m_env.clone()
}
))
}
}

#[cfg(test)]
mod test {
use crate::test_utils;
use quote::quote;

use super::ModuleModItem;

#[test]
fn counter_pack() {
let module = test_utils::mock_module_definition();
let expected = quote!(
mod __counter_pack_module {
use super::*;

impl odra::Module for CounterPack {
fn new(env: Rc<odra::ContractEnv>) -> Self {
let counter0 = ModuleWrapper::new(Rc::clone(&env), 0u8);
let counter1 = ModuleWrapper::new(Rc::clone(&env), 1u8);
let counter2 = ModuleWrapper::new(Rc::clone(&env), 2u8);
let counters = Variable::new(Rc::clone(&env), 3u8);
let counters_map = Mapping::new(Rc::clone(&env), 4u8);
Self {
env,
counter0,
counter1,
counter2,
counters,
counters_map
}
}

fn env(&self) -> Rc<odra::ContractEnv> {
self.env.clone()
}
}
}
);
let actual = ModuleModItem::try_from(&module).unwrap();
test_utils::assert_eq(actual, expected);
}
}
2 changes: 1 addition & 1 deletion odra-macros/src/ast/test_parts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ mod test {
self.env.last_call().contract_last_call(self.address)
}

pub fn try_total_supply(&self) -> Result<U256, OdraError> {
pub fn try_total_supply(&self) -> Result<U256, odra::OdraError> {
self.env.call_contract(
self.address,
odra::CallDef::new(
Expand Down
Loading
Loading