Skip to content

Commit

Permalink
Autogenerate __env field in a module struct
Browse files Browse the repository at this point in the history
* update macros
* update examples
* update templates
  • Loading branch information
kpob committed Dec 7, 2023
1 parent d440682 commit 2cb4229
Show file tree
Hide file tree
Showing 17 changed files with 156 additions and 29 deletions.
1 change: 0 additions & 1 deletion examples2/src/counter_pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use odra::ModuleWrapper;

#[odra::module]
pub struct CounterPack {
env: Rc<ContractEnv>,
counter0: ModuleWrapper<Counter>,
counter1: ModuleWrapper<Counter>,
counter2: ModuleWrapper<Counter>,
Expand Down
11 changes: 5 additions & 6 deletions examples2/src/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ impl From<Erc20Error> for OdraError {

#[odra::module(events = [OnTransfer, OnCrossTransfer, OnApprove])]
pub struct Erc20 {
env: Rc<ContractEnv>,
total_supply: Variable<U256>,
balances: Mapping<Address, U256>
}
Expand All @@ -54,8 +53,8 @@ impl Erc20 {
}

pub fn approve(&mut self, to: Address, amount: U256) {
self.env.emit_event(OnApprove {
owner: self.env.caller(),
self.env().emit_event(OnApprove {
owner: self.env().caller(),
spender: to,
value: amount
});
Expand All @@ -79,7 +78,7 @@ impl Erc20 {
}
balances.set(&caller, from_balance.saturating_sub(value));
balances.set(&to, to_balance.saturating_add(value));
self.env.emit_event(OnTransfer {
self.env().emit_event(OnTransfer {
from: Some(caller),
to: Some(to),
amount: value
Expand Down Expand Up @@ -134,8 +133,8 @@ impl Erc20 {
};

other_erc20.transfer(to, value);
self.env.emit_event(OnCrossTransfer {
from: Some(self.env.self_address()),
self.env().emit_event(OnCrossTransfer {
from: Some(self.env().self_address()),
to: Some(to),
other_contract: other,
amount: value
Expand Down
2 changes: 2 additions & 0 deletions odra-macros/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod exec_parts;
mod fn_utils;
mod host_ref_item;
mod ident_item;
mod module_def;
mod module_item;
mod parts_utils;
mod ref_item;
Expand All @@ -20,6 +21,7 @@ pub(crate) use entrypoints_item::HasEntrypointsImplItem;
pub(crate) use events_item::HasEventsImplItem;
pub(crate) use exec_parts::{ExecPartsItem, ExecPartsReexportItem};
pub(crate) use ident_item::HasIdentImplItem;
pub(crate) use module_def::ModuleDefItem;
pub(crate) use module_item::ModuleModItem;
pub(crate) use ref_item::RefItem;
pub(crate) use test_parts::{TestPartsItem, TestPartsReexportItem};
Expand Down
56 changes: 56 additions & 0 deletions odra-macros/src/ast/module_def.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::ir::StructIR;
use crate::utils;

#[derive(syn_derive::ToTokens)]
pub struct ModuleDefItem {
item_struct: syn::ItemStruct
}

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

fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
let mut item_struct = ir.self_code().clone();
let env_field: syn::Field = utils::misc::field(
&utils::ident::underscored_env(),
&utils::ty::rc_contract_env()
);

let fields = item_struct
.fields
.into_iter()
.chain(vec![env_field])
.collect::<syn::punctuated::Punctuated<_, _>>();

item_struct.fields = syn::Fields::Named(syn::FieldsNamed {
brace_token: Default::default(),
named: fields
});

Ok(Self { item_struct })
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::{assert_eq, mock_module_definition};

#[test]
fn test_module_def_item() {
let ir = mock_module_definition();
let def = ModuleDefItem::try_from(&ir).unwrap();
let expected = quote::quote! {
pub struct CounterPack {
counter0: ModuleWrapper<Counter>,
counter1: ModuleWrapper<Counter>,
counter2: ModuleWrapper<Counter>,
counters: Variable<u32>,
counters_map: Mapping<u8, Counter>,
__env: Rc<odra::ContractEnv>
}
};

assert_eq(def, expected);
}
}
56 changes: 45 additions & 11 deletions odra-macros/src/ast/module_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use syn::parse_quote;

use crate::{
ir::{EnumeratedTypedField, StructIR},
utils
utils::{self, expr::IntoExpr}
};

use super::parts_utils::UseSuperItem;
Expand Down Expand Up @@ -80,11 +80,11 @@ 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 ty_contract_env = utils::ty::rc_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),
sig: parse_quote!(fn new(#env: #ty_contract_env) -> Self),
braces: Default::default(),
fields: fields.iter().map(Into::into).collect(),
instance: ir.try_into()?
Expand Down Expand Up @@ -119,17 +119,26 @@ struct ModuleInstanceItem {
#[syn(braced)]
braces: syn::token::Brace,
#[syn(in = braces)]
values: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]>
values: syn::punctuated::Punctuated<ValueInitItem, syn::Token![,]>
}

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

fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
let ident_underscored_env = utils::ident::underscored_env();
let ident_env = utils::ident::env();
let env_init = ValueInitItem::with_init(ident_underscored_env, ident_env.into_expr());

Ok(Self {
self_token: Default::default(),
braces: Default::default(),
values: ir.field_names()?.into_iter().collect()
values: ir
.field_names()?
.into_iter()
.map(ValueInitItem::new)
.chain(vec![env_init])
.collect()
})
}
}
Expand All @@ -138,17 +147,42 @@ 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();
let ty_contract_env = utils::ty::rc_contract_env();
let m_env = utils::member::underscored_env();

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

#[derive(syn_derive::ToTokens)]
struct ValueInitItem {
ident: syn::Ident,
colon_token: Option<syn::Token![:]>,
init_expr: Option<syn::Expr>
}

impl ValueInitItem {
fn new(ident: syn::Ident) -> Self {
Self {
ident,
colon_token: None,
init_expr: None
}
}

fn with_init(ident: syn::Ident, init_expr: syn::Expr) -> Self {
Self {
ident,
colon_token: Some(Default::default()),
init_expr: Some(init_expr)
}
}
}

#[cfg(test)]
mod test {
use crate::test_utils;
Expand All @@ -171,17 +205,17 @@ mod test {
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
counters_map,
__env: env
}
}

fn env(&self) -> Rc<odra::ContractEnv> {
self.env.clone()
self.__env.clone()
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions odra-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ struct ModuleImpl {
#[derive(syn_derive::ToTokens, TryFromRef)]
#[source(StructIR)]
struct ModuleStruct {
#[expr(item.self_code().clone())]
self_code: syn::ItemStruct,
self_code: ModuleDefItem,
mod_item: ModuleModItem,
has_ident_item: HasIdentImplItem,
has_events_item: HasEventsImplItem
Expand Down
1 change: 0 additions & 1 deletion odra-macros/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ pub fn mock_module() -> ModuleIR {
pub fn mock_module_definition() -> StructIR {
let module = quote!(
pub struct CounterPack {
env: Rc<ContractEnv>,
counter0: ModuleWrapper<Counter>,
counter1: ModuleWrapper<Counter>,
counter2: ModuleWrapper<Counter>,
Expand Down
10 changes: 10 additions & 0 deletions odra-macros/src/utils/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,13 @@ pub fn new_blueprint(ident: &syn::Ident) -> syn::Expr {
pub fn string_from(string: String) -> syn::Expr {
parse_quote!(String::from(#string))
}

pub trait IntoExpr {
fn into_expr(self) -> syn::Expr;
}

impl IntoExpr for syn::Ident {
fn into_expr(self) -> syn::Expr {
parse_quote!(#self)
}
}
3 changes: 3 additions & 0 deletions odra-macros/src/utils/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub fn env() -> syn::Ident {
format_ident!("env")
}

pub fn underscored_env() -> syn::Ident {
format_ident!("__env")
}
pub fn exec_env() -> syn::Ident {
format_ident!("exec_env")
}
Expand Down
14 changes: 11 additions & 3 deletions odra-macros/src/utils/member.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
pub fn address() -> syn::ExprField {
syn::parse_quote!(self.address)
member(super::ident::address())
}

pub fn attached_value() -> syn::ExprField {
syn::parse_quote!(self.attached_value)
member(super::ident::attached_value())
}

pub fn env() -> syn::ExprField {
syn::parse_quote!(self.env)
member(super::ident::env())
}

pub fn underscored_env() -> syn::ExprField {
member(super::ident::underscored_env())
}

fn member(ident: syn::Ident) -> syn::ExprField {
syn::parse_quote!(self.#ident)
}
10 changes: 10 additions & 0 deletions odra-macros/src/utils/misc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pub fn field(ident: &syn::Ident, ty: &syn::Type) -> syn::Field {
syn::Field {
attrs: vec![],
vis: super::syn::visibility_private(),
mutability: syn::FieldMutability::None,
ident: Some(ident.clone()),
colon_token: Some(Default::default()),
ty: ty.clone()
}
}
1 change: 1 addition & 0 deletions odra-macros/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod attr;
pub mod expr;
pub mod ident;
pub mod member;
pub mod misc;
pub mod stmt;
pub mod string;
pub mod syn;
Expand Down
4 changes: 4 additions & 0 deletions odra-macros/src/utils/syn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ pub fn visibility_pub() -> syn::Visibility {
parse_quote!(pub)
}

pub fn visibility_private() -> syn::Visibility {
parse_quote!()
}

pub fn last_segment_ident(ty: &syn::Type) -> Result<syn::Ident, syn::Error> {
match ty {
syn::Type::Path(type_path) => type_path
Expand Down
4 changes: 4 additions & 0 deletions odra-macros/src/utils/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ pub fn contract_env() -> syn::Type {
parse_quote!(odra::ContractEnv)
}

pub fn rc_contract_env() -> syn::Type {
parse_quote!(Rc<odra::ContractEnv>)
}

pub fn from_bytes() -> syn::Type {
parse_quote!(odra::FromBytes)
}
Expand Down
4 changes: 2 additions & 2 deletions templates/blank/bin/build_schema.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use odra::contract_def::ContractBlueprint2;
use odra::contract_def::ContractBlueprint;

extern "Rust" {
fn module_schema() -> ContractBlueprint2;
fn module_schema() -> ContractBlueprint;
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions templates/full/bin/build_schema.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use odra::contract_def::ContractBlueprint2;
use odra::contract_def::ContractBlueprint;

extern "Rust" {
fn module_schema() -> ContractBlueprint2;
fn module_schema() -> ContractBlueprint;
}

fn main() {
Expand Down
1 change: 0 additions & 1 deletion templates/full/src/flipper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use odra::{Module, Variable, ContractEnv};
/// or/and another modules.
#[odra::module]
pub struct Flipper {
env: Rc<ContractEnv>,
/// The module itself does not store the value,
/// it's a proxy that writes/reads value to/from the host.
value: Variable<bool>,
Expand Down

0 comments on commit 2cb4229

Please sign in to comment.