Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Adding eosio structure attribute #1082

Draft
wants to merge 9 commits into
base: transaction-sponsorship
Choose a base branch
from
1 change: 1 addition & 0 deletions libraries/eosiolib/contracts/eosio/contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define CONTRACT class [[eosio::contract]]
#define ACTION [[eosio::action]] void
#define TABLE struct [[eosio::table]]
#define STRUCTURE struct [[eosio::structure]]

namespace eosio {

Expand Down
7 changes: 7 additions & 0 deletions tools/include/eosio/abi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ struct abi_table {
bool operator<(const abi_table& t) const { return name < t.name; }
};

struct abi_structure {
std::string name;
std::string type;
bool operator<(const abi_structure& s) const { return name < s.name; }
};

struct abi_kv_index {
std::string name;
std::string type;
Expand Down Expand Up @@ -82,6 +88,7 @@ struct abi {
std::set<abi_typedef> typedefs;
std::set<abi_action> actions;
std::set<abi_table> tables;
std::set<abi_structure> structures;
std::set<abi_kv_table> kv_tables;
std::set<abi_variant> variants;
std::vector<abi_ricardian_clause_pair> ricardian_clauses;
Expand Down
52 changes: 50 additions & 2 deletions tools/include/eosio/abigen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,31 @@ namespace eosio { namespace cdt {
_abi.tables.insert(t);
}

void add_structure( const clang::CXXRecordDecl* decl ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused about this part.

I thought the idea of the new attribute was to flag data types to be included in the 'structs' section for abi conversions to be performed on it.

I don't see why we need another section that is duplicating the information.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that eosio::table attribute is made available in both 'structs' section, and also in a separate section, and I assumed that different tools get that information from different sections. I was mimicking that implementation. I can remove the separate section, if my assumption is incorrect, leaving eosio::structure attribute only in 'structs' section. Please advice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed ABI generation of structures section avoiding duplication.

structures.insert(decl);
abi_structure t;
t.type = decl->getNameAsString();
auto structure_name = decl->getEosioStructureAttr()->getName();
if (!structure_name.empty()) {
validate_name( structure_name.str(), [&](auto s) { CDT_ERROR("abigen_error", decl->getLocation(), s); } );
t.name = structure_name.str();
}
else {
t.name = t.type;
}
cstructures.insert(t);
}

void add_structure( uint64_t name, const clang::CXXRecordDecl* decl ) {
if ( !decl->isEosioStructure() )
return;

abi_structure t;
t.type = decl->getNameAsString();
t.name = name_to_string(name);
_abi.structures.insert(t);
}

void add_kv_map(const clang::ClassTemplateSpecializationDecl* decl) {
abi_kv_table akt;
const auto& first_arg = decl->getTemplateArgs()[0];
Expand Down Expand Up @@ -470,6 +495,13 @@ namespace eosio { namespace cdt {
return o;
}

ojson structure_to_json( const abi_structure& s ) {
ojson o;
o["name"] = s.name;
o["type"] = s.type;
return o;
}

std::pair<std::string, ojson> kv_table_to_json( const abi_kv_table& t ) {
ojson o;
o["type"] = t.type;
Expand Down Expand Up @@ -516,7 +548,7 @@ namespace eosio { namespace cdt {
set_of_tables.insert(t);
}

return _abi.structs.empty() && _abi.typedefs.empty() && _abi.actions.empty() && set_of_tables.empty() && _abi.ricardian_clauses.empty() && _abi.variants.empty();
return _abi.structs.empty() && _abi.typedefs.empty() && _abi.actions.empty() && set_of_tables.empty() && _abi.structures.empty() && _abi.ricardian_clauses.empty() && _abi.variants.empty();
}

ojson to_json() {
Expand Down Expand Up @@ -585,6 +617,10 @@ namespace eosio { namespace cdt {
if (as.name == _translate_type(t.type))
return true;
}
for ( auto s : _abi.structures ) {
if (as.name == _translate_type(s.type))
return true;
}
for ( const auto t : _abi.kv_tables ) {
if (as.name == _translate_type(t.type))
return true;
Expand Down Expand Up @@ -619,6 +655,9 @@ namespace eosio { namespace cdt {
for ( auto t : _abi.tables )
if ( t.type == td.new_type_name )
return true;
for ( auto s : _abi.structures )
if ( s.type == td.new_type_name )
return true;
for ( auto a : _abi.actions )
if ( a.type == td.new_type_name )
return true;
Expand Down Expand Up @@ -650,6 +689,10 @@ namespace eosio { namespace cdt {
for ( auto t : set_of_tables ) {
o["tables"].push_back(table_to_json( t ));
}
o["structures"] = ojson::array();
for ( auto s : _abi.structures ) {
o["structures"].push_back(structure_to_json( s ));
}
o["kv_tables"] = ojson::object();
for ( const auto& t : _abi.kv_tables ) {
auto kv_table = kv_table_to_json(t);
Expand Down Expand Up @@ -677,6 +720,8 @@ namespace eosio { namespace cdt {
abi _abi;
std::set<const clang::CXXRecordDecl*> tables;
std::set<abi_table> ctables;
std::set<const clang::CXXRecordDecl*> structures;
std::set<abi_structure> cstructures;
std::map<std::string, std::string> rcs;
std::set<const clang::Type*> evaluated;

Expand Down Expand Up @@ -750,12 +795,15 @@ namespace eosio { namespace cdt {
ag.add_contracts(parse_contracts());
has_added_clauses = true;
}
if ((decl->isEosioAction() || decl->isEosioTable()) && ag.is_eosio_contract(decl, ag.get_contract_name())) {
if ((decl->isEosioAction() || decl->isEosioTable() || decl->isEosioStructure())
&& ag.is_eosio_contract(decl, ag.get_contract_name())) {
ag.add_struct(decl);
if (decl->isEosioAction())
ag.add_action(decl);
if (decl->isEosioTable())
ag.add_table(decl);
if (decl->isEosioStructure())
ag.add_structure(decl);
for (auto field : decl->fields()) {
ag.add_type( field->getType() );
}
Expand Down