From 7d5b680cd73d8d635cffa0b58423e43c244d5654 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Tue, 12 Jul 2022 11:24:49 +0000 Subject: [PATCH] refactor(evm-coder): toposort generated code Previously, all items from evm-coder codegen was sorted lexically, which caused some problems, where lexically sorted names of contract were not in the same order as contract inherit chain Now they are sorted by insertion order, and macro-generated code now inserts them in order of definition, thus providing topological sort of output contract items --- --- a/crates/evm-coder-macros/src/lib.rs +++ b/crates/evm-coder-macros/src/lib.rs @@ -22,7 +22,7 @@ use sha3::{Digest, Keccak256}; use syn::{ DeriveInput, GenericArgument, Ident, ItemImpl, Pat, Path, PathArguments, - PathSegment, Type, parse_macro_input, spanned::Spanned, Attribute, parse::Parse, + PathSegment, Type, parse_macro_input, spanned::Spanned, }; mod solidity_interface; @@ -241,7 +241,7 @@ /// Event(#[indexed] uint32), /// } /// -/// #[solidity_interface(name = "MyContract", is(SuperContract), inline_is(InlineContract))] +/// #[solidity_interface(name = MyContract, is(SuperContract), inline_is(InlineContract))] /// impl Contract { /// /// Multiply two numbers /// #[weight(200 + a + b)] --- a/crates/evm-coder-macros/src/solidity_interface.rs +++ b/crates/evm-coder-macros/src/solidity_interface.rs @@ -989,26 +989,24 @@ #solidity_functions, )*), }; - if is_impl { - tc.collect("/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into()); - } else { - tc.collect("/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into()); - } - #( - #solidity_generators - )* - #( - #solidity_event_generators - )* let mut out = string::new(); - // In solidity interface usage (is) should be preceeded by interface definition - // HACK: this comment helps to sort it in a set if #solidity_name.starts_with("Inline") { out.push_str("/// @dev inlined interface\n"); } let _ = interface.format(is_impl, &mut out, tc); tc.collect(out); + #( + #solidity_event_generators + )* + #( + #solidity_generators + )* + if is_impl { + tc.collect("/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into()); + } else { + tc.collect("/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into()); + } } } impl #gen_ref ::evm_coder::Call for #call_name #gen_ref { --- a/crates/evm-coder/src/solidity.rs +++ b/crates/evm-coder/src/solidity.rs @@ -14,26 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . +//! Implementation detail of [`evm_coder::solidity_interface`] macro code-generation + #[cfg(not(feature = "std"))] use alloc::{ string::String, vec::Vec, - collections::{BTreeSet, BTreeMap}, + collections::BTreeMap, format, }; #[cfg(feature = "std")] -use std::collections::{BTreeSet, BTreeMap}; +use std::collections::BTreeMap; use core::{ fmt::{self, Write}, marker::PhantomData, cell::{Cell, RefCell}, + cmp::Reverse, }; use impl_trait_for_tuples::impl_for_tuples; use crate::types::*; #[derive(Default)] pub struct TypeCollector { - structs: RefCell>, + /// Code => id + /// id ordering is required to perform topo-sort on the resulting data + structs: RefCell>, anonymous: RefCell, usize>>, id: Cell, } @@ -42,7 +47,8 @@ Self::default() } pub fn collect(&self, item: string) { - self.structs.borrow_mut().insert(item); + let id = self.next_id(); + self.structs.borrow_mut().insert(item, id); } pub fn next_id(&self) -> usize { let v = self.id.get(); @@ -66,8 +72,10 @@ self.anonymous.borrow_mut().insert(names, id); format!("Tuple{}", id) } - pub fn finish(self) -> BTreeSet { - self.structs.into_inner() + pub fn finish(self) -> Vec { + let mut data = self.structs.into_inner().into_iter().collect::>(); + data.sort_by_key(|(_, id)| Reverse(*id)); + data.into_iter().map(|(code, _)| code).collect() } } -- gitstuff