git.delta.rocks / unique-network / refs/commits / 7d5b680cd73d

difftreelog

refactor(evm-coder) toposort generated code

Yaroslav Bolyukin2022-07-12parent: #50d005e.patch.diff
in: master
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

3 files changed

modifiedcrates/evm-coder-macros/src/lib.rsdiffbeforeafterboth
--- 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)]
modifiedcrates/evm-coder-macros/src/solidity_interface.rsdiffbeforeafterboth
--- 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 {
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! Implementation detail of [`evm_coder::solidity_interface`] macro code-generation
1618
17#[cfg(not(feature = "std"))]19#[cfg(not(feature = "std"))]
18use alloc::{20use alloc::{
19 string::String,21 string::String,
20 vec::Vec,22 vec::Vec,
21 collections::{BTreeSet, BTreeMap},23 collections::BTreeMap,
22 format,24 format,
23};25};
24#[cfg(feature = "std")]26#[cfg(feature = "std")]
25use std::collections::{BTreeSet, BTreeMap};27use std::collections::BTreeMap;
26use core::{28use core::{
27 fmt::{self, Write},29 fmt::{self, Write},
28 marker::PhantomData,30 marker::PhantomData,
29 cell::{Cell, RefCell},31 cell::{Cell, RefCell},
32 cmp::Reverse,
30};33};
31use impl_trait_for_tuples::impl_for_tuples;34use impl_trait_for_tuples::impl_for_tuples;
32use crate::types::*;35use crate::types::*;
3336
34#[derive(Default)]37#[derive(Default)]
35pub struct TypeCollector {38pub struct TypeCollector {
39 /// Code => id
40 /// id ordering is required to perform topo-sort on the resulting data
36 structs: RefCell<BTreeSet<string>>,41 structs: RefCell<BTreeMap<string, usize>>,
37 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,42 anonymous: RefCell<BTreeMap<Vec<string>, usize>>,
38 id: Cell<usize>,43 id: Cell<usize>,
39}44}
42 Self::default()47 Self::default()
43 }48 }
44 pub fn collect(&self, item: string) {49 pub fn collect(&self, item: string) {
50 let id = self.next_id();
45 self.structs.borrow_mut().insert(item);51 self.structs.borrow_mut().insert(item, id);
46 }52 }
47 pub fn next_id(&self) -> usize {53 pub fn next_id(&self) -> usize {
48 let v = self.id.get();54 let v = self.id.get();
66 self.anonymous.borrow_mut().insert(names, id);72 self.anonymous.borrow_mut().insert(names, id);
67 format!("Tuple{}", id)73 format!("Tuple{}", id)
68 }74 }
69 pub fn finish(self) -> BTreeSet<string> {75 pub fn finish(self) -> Vec<string> {
70 self.structs.into_inner()76 let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();
77 data.sort_by_key(|(_, id)| Reverse(*id));
78 data.into_iter().map(|(code, _)| code).collect()
71 }79 }
72}80}
7381