Skip to content

Commit

Permalink
Support ethdebug types.
Browse files Browse the repository at this point in the history
  • Loading branch information
aarlt committed Aug 28, 2024
1 parent 93749ff commit d5c0c6b
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 4 deletions.
79 changes: 78 additions & 1 deletion libsolidity/ast/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ std::multimap<std::string, FunctionDefinition const*> const& ContractDefinition:
});
}


TypeNameAnnotation& TypeName::annotation() const
{
return initAnnotation<TypeNameAnnotation>();
Expand Down Expand Up @@ -399,6 +398,13 @@ StructDeclarationAnnotation& StructDefinition::annotation() const
return initAnnotation<StructDeclarationAnnotation>();
}

std::optional<Json> StructDefinition::ethdebug() const
{
Json result = Json::object();
result["kind"] = "struct";
return result;
}

Type const* EnumValue::type() const
{
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
Expand All @@ -416,6 +422,17 @@ TypeDeclarationAnnotation& EnumDefinition::annotation() const
return initAnnotation<TypeDeclarationAnnotation>();
}

std::optional<Json> EnumDefinition::ethdebug() const
{
Json result = Json::object();
result["kind"] = "enum";
Json values = Json::array();
for (auto const& value: members())
values.push_back(value->name());
result["values"] = values;
return result;
}

bool FunctionDefinition::libraryFunction() const
{
if (auto const* contractDef = dynamic_cast<ContractDefinition const*>(scope()))
Expand Down Expand Up @@ -543,6 +560,57 @@ FunctionDefinition const& FunctionDefinition::resolveVirtual(
return *this; // not reached
}

std::optional<Json> FunctionDefinition::ethdebug() const
{
Json result = Json::object();
if (isOrdinary())
result["kind"] = "function";
else if (isConstructor())
result["kind"] = "constructor";
else if (isFallback())
result["kind"] = "fallback";
else
solAssert(false);

if (!noVisibilitySpecified())
{
switch (visibility())
{
case solidity::frontend::Visibility::Default:
case solidity::frontend::Visibility::Private:
case solidity::frontend::Visibility::Internal:
result["internal"] = true;
break;
case solidity::frontend::Visibility::Public:
case solidity::frontend::Visibility::External:
result["external"] = true;
break;
}
}

Json definition = Json::object();
definition["name"] = name();
result["definition"] = definition;

Json parameters = Json::array();
for (auto const& param: this->parameters())
{
solAssert(param->ethdebug().has_value());
parameters.emplace_back(*param->ethdebug());
}
result["parameters"] = parameters;

Json returns = Json::array();
for (auto const& param: returnParameters())
{
solAssert(param->ethdebug().has_value());
returns.emplace_back(*param->ethdebug());
}
result["returns"] = returns;

return result;
}

Type const* ModifierDefinition::type() const
{
return TypeProvider::modifier(*this);
Expand Down Expand Up @@ -878,6 +946,15 @@ VariableDeclarationAnnotation& VariableDeclaration::annotation() const
return initAnnotation<VariableDeclarationAnnotation>();
}

std::optional<Json> VariableDeclaration::ethdebug() const
{
solAssert(type()->ethdebug().has_value());
Json result = Json::object();
result["name"] = name();
result["type"] = *type()->ethdebug();
return result;
}

StatementAnnotation& Statement::annotation() const
{
return initAnnotation<StatementAnnotation>();
Expand Down
10 changes: 10 additions & 0 deletions libsolidity/ast/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ class ASTNode

virtual bool experimentalSolidityOnly() const { return false; }

virtual std::optional<Json> ethdebug() const { return std::nullopt; }

protected:
size_t const m_id = 0;

Expand Down Expand Up @@ -753,6 +755,8 @@ class StructDefinition: public Declaration, public StructurallyDocumented, publi

StructDeclarationAnnotation& annotation() const override;

std::optional<Json> ethdebug() const override;

private:
std::vector<ASTPointer<VariableDeclaration>> m_members;
};
Expand Down Expand Up @@ -785,6 +789,8 @@ class EnumDefinition: public Declaration, public StructurallyDocumented, public

TypeDeclarationAnnotation& annotation() const override;

std::optional<Json> ethdebug() const override;

private:
std::vector<ASTPointer<EnumValue>> m_members;
};
Expand Down Expand Up @@ -1036,6 +1042,8 @@ class FunctionDefinition: public CallableDeclaration, public StructurallyDocumen

Expression const* experimentalReturnExpression() const { return m_experimentalReturnExpression.get(); }

std::optional<Json> ethdebug() const override;

private:
StateMutability m_stateMutability;
bool m_free;
Expand Down Expand Up @@ -1156,6 +1164,8 @@ class VariableDeclaration: public Declaration, public StructurallyDocumented
ASTPointer<Expression> const& typeExpression() const { return m_typeExpression; }
VariableDeclarationAnnotation& annotation() const override;

std::optional<Json> ethdebug() const override;

protected:
Visibility defaultVisibility() const override { return Visibility::Internal; }

Expand Down
79 changes: 79 additions & 0 deletions libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,85 @@ std::set<FunctionDefinition const*, ASTNode::CompareByID> Type::operatorDefiniti
return matchingDefinitions;
}

std::optional<Json> Type::ethdebug() const
{
Json result = Json::object();
switch (category())
{
case Category::Address:
result["kind"] = "address";
break;
case Category::Integer:
{
auto integer = dynamic_cast<IntegerType const*>(this);
if (integer->isSigned())
result["kind"] = "int";
else
result["kind"] = "uint";
result["bits"] = integer->numBits();
break;
}
case Category::RationalNumber:
result["kind"] = "rational";
break;
case Category::StringLiteral:
result["kind"] = "string";
break;
case Category::Bool:
result["kind"] = "bool";
break;
case Category::FixedPoint:
result["kind"] = "fixed";
break;
case Category::Array:
result["kind"] = "array";
break;
case Category::ArraySlice:
result["kind"] = "slice";
break;
case Category::FixedBytes:
result["kind"] = "bytes";
break;
case Category::Contract:
result["kind"] = "contract";
break;
case Category::Struct:
result["kind"] = "struct";
break;
case Category::Function:
result["kind"] = "function";
break;
case Category::Enum:
result["kind"] = "enum";
break;
case Category::UserDefinedValueType:
result["kind"] = "udvt";
break;
case Category::Tuple:
result["kind"] = "tuple";
break;
case Category::Mapping:
result["kind"] = "mapping";
break;
case Category::TypeType:
result["kind"] = "type-type";
break;
case Category::Modifier:
result["kind"] = "modifier";
break;
case Category::Magic:
result["kind"] = "magic";
break;
case Category::Module:
result["kind"] = "module";
break;
case Category::InaccessibleDynamic:
result["kind"] = "inaccessible-dynamic";
break;
}
return result;
}

MemberList::MemberMap Type::attachedFunctions(Type const& _type, ASTNode const& _scope)
{
MemberList::MemberMap members;
Expand Down
4 changes: 3 additions & 1 deletion libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@

#pragma once

#include <liblangutil/Exceptions.h>
#include <libsolidity/ast/ASTEnums.h>
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/parsing/Token.h>
#include <liblangutil/Exceptions.h>

#include <libsolutil/Common.h>
#include <libsolutil/Numeric.h>
#include <libsolutil/CommonIO.h>
#include <libsolutil/JSON.h>
#include <libsolutil/LazyInit.h>
#include <libsolutil/Result.h>

Expand Down Expand Up @@ -409,6 +410,7 @@ class Type
bool _unary
) const;

virtual std::optional<Json> ethdebug() const;
private:
/// @returns a member list containing all members added to this type by `using for` directives.
static MemberList::MemberMap attachedFunctions(Type const& _type, ASTNode const& _scope);
Expand Down
26 changes: 24 additions & 2 deletions libsolidity/interface/CompilerStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1105,11 +1105,33 @@ Json CompilerStack::ethdebug(Contract const& _contract) const
solUnimplementedAssert(!isExperimentalSolidity());
return _contract.ethdebug.init([&] {
Json result = Json::object();
result["not yet implemented"] = true;
result["types"] = ethdebugTypes(_contract);
return result;
});
}

Json CompilerStack::ethdebugTypes(Contract const& _contract) const
{
Json types = Json::object();
ContractDefinition const& contract = *_contract.contract;
for (auto const& _enum: contract.definedEnums())
{
solAssert(_enum->ethdebug().has_value());
types[_enum->name()] = *_enum->ethdebug();
}
for (auto const& _struct: contract.definedStructs())
{
solAssert(_struct->ethdebug().has_value());
types[_struct->name()] = *_struct->ethdebug();
}
for (auto const& _function: contract.definedFunctions())
{
solAssert(_function->ethdebug().has_value());
types[_function->name()] = *_function->ethdebug();
}
return types;
}

Json CompilerStack::runtimeEthdebug(std::string const& _contractName) const
{
solAssert(m_stackState >= AnalysisSuccessful, "Analysis was not successful.");
Expand All @@ -1123,7 +1145,7 @@ Json CompilerStack::runtimeEthdebug(Contract const& _contract) const
solUnimplementedAssert(!isExperimentalSolidity());
return _contract.ethdebugRuntime.init([&] {
Json result = Json::object();
result["not yet implemented (runtime)"] = true;
result["types"] = ethdebugTypes(_contract);
return result;
});
}
Expand Down
2 changes: 2 additions & 0 deletions libsolidity/interface/CompilerStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ class CompilerStack: public langutil::CharStreamProvider, public evmasm::Abstrac
mutable std::optional<std::string const> runtimeSourceMapping;
};

Json ethdebugTypes(Contract const& _contract) const;

void createAndAssignCallGraphs();
void findAndReportCyclicContractDependencies();

Expand Down

0 comments on commit d5c0c6b

Please sign in to comment.