Skip to content

Commit

Permalink
Add events to Schema in the call function (#293)
Browse files Browse the repository at this point in the history
* add `event_schemas` to HasEvents trait
* update `call`  function
  • Loading branch information
kpob authored Dec 13, 2023
1 parent 841b2f7 commit 2d014dd
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 43 deletions.
157 changes: 119 additions & 38 deletions odra-macros/src/ast/events_item.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
use syn::parse_quote;

use crate::ast::fn_utils::FnItem;
use crate::ast::utils::Named;
use crate::ast::utils::ImplItem;
use crate::ir::TypeIR;
use crate::utils::misc::AsBlock;
use crate::{ir::StructIR, utils};

#[derive(syn_derive::ToTokens)]
pub struct HasEventsImplItem {
impl_token: syn::token::Impl,
has_ident_ty: syn::Type,
for_token: syn::token::For,
module_ident: syn::Ident,
impl_item: ImplItem,
#[syn(braced)]
brace_token: syn::token::Brace,
#[syn(in = brace_token)]
events_fn: EventsFnItem
events_fn: EventsFnsItem
}

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

fn try_from(struct_ir: &'_ StructIR) -> Result<Self, Self::Error> {
fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
Ok(Self {
impl_token: Default::default(),
has_ident_ty: utils::ty::has_events(),
for_token: Default::default(),
module_ident: struct_ir.module_ident(),
impl_item: ImplItem::has_events(ir)?,
brace_token: Default::default(),
events_fn: struct_ir.try_into()?
events_fn: ir.try_into()?
})
}
}
Expand All @@ -38,54 +32,91 @@ impl TryFrom<&'_ TypeIR> for HasEventsImplItem {

fn try_from(ir: &'_ TypeIR) -> Result<Self, Self::Error> {
Ok(Self {
impl_token: Default::default(),
has_ident_ty: utils::ty::has_events(),
for_token: Default::default(),
module_ident: ir.name()?,
impl_item: ImplItem::has_events(ir)?,
brace_token: Default::default(),
events_fn: EventsFnItem::empty()
events_fn: EventsFnsItem::empty()
})
}
}

#[derive(syn_derive::ToTokens)]
pub struct EventsFnItem {
fn_item: FnItem
pub struct EventsFnsItem {
events_fn: FnItem,
wasm_attr: syn::Attribute,
event_schemas_fn: FnItem
}

impl EventsFnItem {
impl EventsFnsItem {
pub fn empty() -> Self {
let ident_events = utils::ident::events();
let empty_vec = utils::expr::empty_vec();
Self {
fn_item: FnItem::new(&ident_events, vec![], Self::ret_ty(), empty_vec.as_block())
events_fn: FnItem::new(
&utils::ident::events(),
vec![],
Self::events_ret_ty(),
utils::expr::empty_vec().as_block()
),
wasm_attr: utils::attr::wasm32(),
event_schemas_fn: FnItem::new(
&utils::ident::event_schemas(),
vec![],
Self::schemas_ret_ty(),
utils::expr::empty_btree_map().as_block()
)
}
}

fn ret_ty() -> syn::ReturnType {
fn events_ret_ty() -> syn::ReturnType {
let ev_ty = utils::ty::event();
let vec = utils::ty::vec_of(&ev_ty);
utils::misc::ret_ty(&vec)
}

fn schemas_ret_ty() -> syn::ReturnType {
let string_ty = utils::ty::string();
let schema_ty = utils::ty::schema();
let btree = utils::ty::typed_btree_map(&string_ty, &schema_ty);
utils::misc::ret_ty(&btree)
}

fn events_fn(ir: &StructIR) -> Result<FnItem, syn::Error> {
let ident_events = utils::ident::events();
let struct_events_stmt = struct_events_stmt(ir);
let chain_events_expr = chain_events_expr(ir)?;
Ok(FnItem::new(
&ident_events,
vec![],
EventsFnsItem::events_ret_ty(),
parse_quote!({
#struct_events_stmt
#chain_events_expr
})
))
}

fn event_schemas_fn(ir: &StructIR) -> Result<FnItem, syn::Error> {
let ident_events = utils::ident::event_schemas();
let struct_events_stmt = struct_event_schemas_stmt(ir);
let chain_events_expr = chain_event_schemas_expr(ir)?;
Ok(FnItem::new(
&ident_events,
vec![],
EventsFnsItem::schemas_ret_ty(),
parse_quote!({
#struct_events_stmt
#chain_events_expr
})
))
}
}

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

fn try_from(struct_ir: &'_ StructIR) -> Result<Self, Self::Error> {
let ident_events = utils::ident::events();
let struct_events_stmt = struct_events_stmt(struct_ir);
let chain_events_expr = chain_events_expr(struct_ir)?;
fn try_from(ir: &'_ StructIR) -> Result<Self, Self::Error> {
Ok(Self {
fn_item: FnItem::new(
&ident_events,
vec![],
Self::ret_ty(),
parse_quote!({
#struct_events_stmt
#chain_events_expr
})
)
events_fn: Self::events_fn(ir)?,
wasm_attr: utils::attr::wasm32(),
event_schemas_fn: Self::event_schemas_fn(ir)?
})
}
}
Expand Down Expand Up @@ -121,6 +152,40 @@ fn chain_events_expr(ir: &StructIR) -> Result<syn::Expr, syn::Error> {
))
}

fn struct_event_schemas_stmt(ir: &StructIR) -> syn::Stmt {
let result_ident = utils::ident::result();

let events = ir
.events()
.iter()
.map(|ty| {
let name = utils::expr::event_instance_name(ty);
let schema = utils::expr::event_instance_schema(ty);
quote::quote!((#name, #schema))
})
.collect::<syn::punctuated::Punctuated<_, syn::token::Comma>>();
let iter = utils::expr::vec(events);
let new_btree_map = utils::expr::btree_from_iter(&iter);
parse_quote!(let #result_ident = #new_btree_map;)
}

fn chain_event_schemas_expr(ir: &StructIR) -> Result<syn::Expr, syn::Error> {
let result_ident = utils::ident::result();
let fields_events = ir
.unique_fields_ty()?
.iter()
.map(utils::expr::event_schemas)
.map(|expr| quote::quote!(.chain(#expr)))
.collect::<Vec<_>>();

Ok(parse_quote!(
#result_ident
.into_iter()
#(#fields_events)*
.collect()
))
}

#[cfg(test)]
mod test {
use crate::test_utils;
Expand All @@ -146,6 +211,22 @@ mod test {
.chain(<Variable<u32> as odra::contract_def::HasEvents>::events())
.collect()
}

#[cfg(target_arch = "wasm32")]
fn event_schemas() -> odra::prelude::BTreeMap<odra::prelude::string::String, odra::casper_event_standard::Schema> {
let result = odra::prelude::BTreeMap::from_iter(
odra::prelude::vec![
(<OnTransfer as odra::casper_event_standard::EventInstance>::name(), <OnTransfer as odra::casper_event_standard::EventInstance>::schema()),
(<OnApprove as odra::casper_event_standard::EventInstance>::name(), <OnApprove as odra::casper_event_standard::EventInstance>::schema())
]
);
result
.into_iter()
.chain(<Mapping<u8, Counter> as odra::contract_def::HasEvents>::event_schemas())
.chain(<ModuleWrapper<Counter> as odra::contract_def::HasEvents>::event_schemas())
.chain(<Variable<u32> as odra::contract_def::HasEvents>::event_schemas())
.collect()
}
}
);
let actual = HasEventsImplItem::try_from(&module).unwrap();
Expand Down
10 changes: 10 additions & 0 deletions odra-macros/src/ast/odra_type_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ mod tests {
fn events() -> odra::prelude::vec::Vec<odra::contract_def::Event> {
odra::prelude::vec::Vec::new()
}

#[cfg(target_arch = "wasm32")]
fn event_schemas() -> odra::prelude::BTreeMap<odra::prelude::string::String, odra::casper_event_standard::Schema> {
odra::prelude::BTreeMap::new()
}
}

#[automatically_derived]
Expand Down Expand Up @@ -388,6 +393,11 @@ mod tests {
fn events() -> odra::prelude::vec::Vec<odra::contract_def::Event> {
odra::prelude::vec::Vec::new()
}

#[cfg(target_arch = "wasm32")]
fn event_schemas() -> odra::prelude::BTreeMap<odra::prelude::string::String, odra::casper_event_standard::Schema> {
odra::prelude::BTreeMap::new()
}
}

#[automatically_derived]
Expand Down
4 changes: 4 additions & 0 deletions odra-macros/src/ast/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ impl ImplItem {
Self::new(named, utils::ty::clone())
}

pub fn has_events<T: Named>(named: &T) -> Result<Self, syn::Error> {
Self::new(named, utils::ty::has_events())
}

pub fn from<T: Named>(named: &T, for_ty: &syn::Type) -> Result<Self, syn::Error> {
let ty_from = utils::ty::from(&named.name()?);
Ok(Self {
Expand Down
13 changes: 10 additions & 3 deletions odra-macros/src/ast/wasm_parts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use quote::TokenStreamExt;
use syn::parse_quote;

use crate::utils::misc::AsType;
use crate::{
ast::fn_utils,
ir::{FnIR, ModuleIR},
Expand Down Expand Up @@ -112,6 +113,7 @@ impl TryFrom<&'_ ModuleIR> for CallFnItem {
type Error = syn::Error;

fn try_from(module: &'_ ModuleIR) -> Result<Self, Self::Error> {
let module_ident = module.module_ident()?.as_type();
let ident_args = utils::ident::named_args();
let ident_schemas = utils::ident::schemas();
let ty_args = utils::ty::runtime_args();
Expand All @@ -123,7 +125,8 @@ impl TryFrom<&'_ ModuleIR> for CallFnItem {
}
None => parse_quote!(let #ident_args = Option::<#ty_args>::None)
};
let expr_new_schemas = utils::expr::new_schemas();
let events_expr = utils::expr::event_schemas(&module_ident);
let expr_new_schemas = utils::expr::schemas(&events_expr);
let install_contract_stmt = utils::stmt::install_contract(
parse_quote!(#ident_entry_points()),
parse_quote!(#ident_schemas),
Expand Down Expand Up @@ -316,7 +319,9 @@ mod test {

#[no_mangle]
fn call() {
let schemas = odra::casper_event_standard::Schemas::new();
let schemas = odra::casper_event_standard::Schemas(
<Erc20 as odra::contract_def::HasEvents>::event_schemas()
);
let named_args = Some({
let mut named_args = odra::RuntimeArgs::new();
let _ = named_args.insert(
Expand Down Expand Up @@ -399,7 +404,9 @@ mod test {

#[no_mangle]
fn call() {
let schemas = odra::casper_event_standard::Schemas::new();
let schemas = odra::casper_event_standard::Schemas(
<Erc20 as odra::contract_def::HasEvents>::event_schemas()
);
let named_args = Option::<odra::RuntimeArgs>::None;
odra::odra_casper_wasm_env::host_functions::install_contract(
entry_points(),
Expand Down
28 changes: 26 additions & 2 deletions odra-macros/src/utils/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ pub fn unit_cl_type() -> syn::Expr {
parse_quote!(<() as #ty_cl_typed>::cl_type())
}

pub fn new_schemas() -> syn::Expr {
pub fn schemas(events: &syn::Expr) -> syn::Expr {
let ty = super::ty::schemas();
parse_quote!(#ty::new())
parse_quote!(#ty(#events))
}

pub fn new_wasm_contract_env() -> syn::Expr {
Expand All @@ -80,6 +80,21 @@ pub fn events(ty: &syn::Type) -> syn::Expr {
let has_events_ty = super::ty::has_events();
parse_quote!(<#ty as #has_events_ty>::events())
}

pub fn event_schemas(ty: &syn::Type) -> syn::Expr {
let has_events_ty = super::ty::has_events();
parse_quote!(<#ty as #has_events_ty>::event_schemas())
}

pub fn event_instance_name(ty: &syn::Type) -> syn::Expr {
let event_instance_ty = super::ty::event_instance();
parse_quote!(<#ty as #event_instance_ty>::name())
}

pub fn event_instance_schema(ty: &syn::Type) -> syn::Expr {
let event_instance_ty = super::ty::event_instance();
parse_quote!(<#ty as #event_instance_ty>::schema())
}
pub fn new_blueprint(ident: &syn::Ident) -> syn::Expr {
let ty = super::ty::contract_blueprint();
parse_quote!(#ty::new::<#ident>())
Expand Down Expand Up @@ -117,6 +132,11 @@ pub fn empty_vec() -> syn::Expr {
parse_quote!(#ty::new())
}

pub fn empty_btree_map() -> syn::Expr {
let ty = super::ty::btree_map();
parse_quote!(#ty::new())
}

pub fn vec<T: ToTokens>(content: T) -> syn::Expr {
parse_quote!(odra::prelude::vec![#content])
}
Expand All @@ -138,6 +158,10 @@ pub fn none() -> syn::Expr {
parse_quote!(None)
}

pub fn btree_from_iter(expr: &syn::Expr) -> syn::Expr {
parse_quote!(odra::prelude::BTreeMap::from_iter(#expr))
}

pub trait IntoExpr {
fn into_expr(self) -> syn::Expr;
}
Expand Down
3 changes: 3 additions & 0 deletions odra-macros/src/utils/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ pub fn env_rc() -> syn::Ident {
pub fn events() -> syn::Ident {
format_ident!("events")
}
pub fn event_schemas() -> syn::Ident {
format_ident!("event_schemas")
}

pub fn module_schema() -> syn::Ident {
format_ident!("module_schema")
Expand Down
11 changes: 11 additions & 0 deletions odra-macros/src/utils/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ pub fn group() -> syn::Type {
pub fn schemas() -> syn::Type {
parse_quote!(odra::casper_event_standard::Schemas)
}
pub fn schema() -> syn::Type {
parse_quote!(odra::casper_event_standard::Schema)
}

pub fn cl_typed() -> syn::Type {
parse_quote!(odra::casper_types::CLTyped)
Expand Down Expand Up @@ -221,3 +224,11 @@ pub fn clone() -> syn::Type {
pub fn from<T: ToTokens>(ty: &T) -> syn::Type {
parse_quote!(::core::convert::From<#ty>)
}

pub fn typed_btree_map(key: &syn::Type, value: &syn::Type) -> syn::Type {
parse_quote!(odra::prelude::BTreeMap<#key, #value>)
}

pub fn btree_map() -> syn::Type {
parse_quote!(odra::prelude::BTreeMap)
}

0 comments on commit 2d014dd

Please sign in to comment.