Skip to content

Commit

Permalink
[yul] Add support for parsing debug data attributes.
Browse files Browse the repository at this point in the history
  • Loading branch information
aarlt committed Feb 15, 2024
1 parent 4032b59 commit 47e3966
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 19 deletions.
15 changes: 11 additions & 4 deletions liblangutil/DebugData.h
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include <liblangutil/SourceLocation.h>
#include <libsolutil/JSON.h>
#include <optional>
#include <memory>

Expand All @@ -32,23 +33,27 @@ struct DebugData
explicit DebugData(
langutil::SourceLocation _nativeLocation = {},
langutil::SourceLocation _originLocation = {},
std::optional<int64_t> _astID = {}
std::optional<int64_t> _astID = {},
Json::Value _attributes = {}
):
nativeLocation(std::move(_nativeLocation)),
originLocation(std::move(_originLocation)),
astID(_astID)
astID(_astID),
attributes(std::move(_attributes))
{}

static DebugData::ConstPtr create(
langutil::SourceLocation _nativeLocation,
langutil::SourceLocation _originLocation = {},
std::optional<int64_t> _astID = {}
std::optional<int64_t> _astID = {},
Json::Value _attributes = {}
)
{
return std::make_shared<DebugData>(
std::move(_nativeLocation),
std::move(_originLocation),
_astID
_astID,
std::move(_attributes)
);
}

Expand All @@ -65,6 +70,8 @@ struct DebugData
langutil::SourceLocation originLocation;
/// ID in the (Solidity) source AST.
std::optional<int64_t> astID;
/// Additional debug data attributes.
Json::Value attributes;
};

} // namespace solidity::langutil
60 changes: 45 additions & 15 deletions libyul/AsmParser.cpp
Expand Up @@ -64,11 +64,11 @@ langutil::DebugData::ConstPtr Parser::createDebugData() const
switch (m_useSourceLocationFrom)
{
case UseSourceLocationFrom::Scanner:
return DebugData::create(ParserBase::currentLocation(), ParserBase::currentLocation());
return DebugData::create(ParserBase::currentLocation(), ParserBase::currentLocation(), {}, m_currentDebugDataAttributes);
case UseSourceLocationFrom::LocationOverride:
return DebugData::create(m_locationOverride, m_locationOverride);
return DebugData::create(m_locationOverride, m_locationOverride, {}, m_currentDebugDataAttributes);
case UseSourceLocationFrom::Comments:
return DebugData::create(ParserBase::currentLocation(), m_locationFromComment, m_astIDFromComment);
return DebugData::create(ParserBase::currentLocation(), m_locationFromComment, m_astIDFromComment, m_currentDebugDataAttributes);
}
solAssert(false, "");
}
Expand Down Expand Up @@ -122,8 +122,7 @@ std::unique_ptr<Block> Parser::parseInline(std::shared_ptr<Scanner> const& _scan
try
{
m_scanner = _scanner;
if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments)
fetchDebugDataFromComment();
fetchDebugDataFromComment();
return std::make_unique<Block>(parseBlock());
}
catch (FatalError const&)
Expand All @@ -137,15 +136,12 @@ std::unique_ptr<Block> Parser::parseInline(std::shared_ptr<Scanner> const& _scan
langutil::Token Parser::advance()
{
auto const token = ParserBase::advance();
if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments)
fetchDebugDataFromComment();
fetchDebugDataFromComment();
return token;
}

void Parser::fetchDebugDataFromComment()
{
solAssert(m_sourceNames.has_value(), "");

static std::regex const tagRegex = std::regex(
R"~~((?:^|\s+)(@[a-zA-Z0-9\-_]+)(?:\s+|$))~~", // tag, e.g: @src
std::regex_constants::ECMAScript | std::regex_constants::optimize
Expand All @@ -154,9 +150,9 @@ void Parser::fetchDebugDataFromComment()
std::string_view commentLiteral = m_scanner->currentCommentLiteral();
std::match_results<std::string_view::const_iterator> match;

langutil::SourceLocation originLocation = m_locationFromComment;
// Empty for each new node.
std::optional<int> astID;
std::optional<Json::Value> json;

while (regex_search(commentLiteral.cbegin(), commentLiteral.cend(), match, tagRegex))
{
Expand All @@ -165,10 +161,14 @@ void Parser::fetchDebugDataFromComment()

if (match[1] == "@src")
{
if (auto parseResult = parseSrcComment(commentLiteral, m_scanner->currentCommentLocation()))
tie(commentLiteral, originLocation) = *parseResult;
else
break;
if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments)
{
solAssert(m_sourceNames.has_value(), "");
if (auto parseResult = parseSrcComment(commentLiteral, m_scanner->currentCommentLocation()))
tie(commentLiteral, m_locationFromComment) = *parseResult;
else
break;
}
}
else if (match[1] == "@ast-id")
{
Expand All @@ -177,13 +177,43 @@ void Parser::fetchDebugDataFromComment()
else
break;
}
else if (match[1] == "@attribute")
{
if (auto parseResult = parseDebugDataAttributeOperationComment(commentLiteral, m_scanner->currentCommentLocation()))
{
tie(commentLiteral, json) = *parseResult;
}
else
break;
}
else
// Ignore unrecognized tags.
continue;
}

m_locationFromComment = originLocation;
m_astIDFromComment = astID;
m_debugDataOperationFromComment = json;

if (m_debugDataOperationFromComment.has_value())
applyDebugDataAttributeOperation(m_currentDebugDataAttributes, m_debugDataOperationFromComment.value());
}

std::optional<std::pair<std::string_view, std::optional<Json::Value>>> Parser::parseDebugDataAttributeOperationComment(
std::string_view _arguments,
langutil::SourceLocation const& _commentLocation
)
{
(void)_arguments;
(void)_commentLocation;
// std::cout << "'" << _arguments << "' @ " << _commentLocation << std::endl;
std::optional<Json::Value> jsonData;
return {{_arguments, jsonData}};
}

void Parser::applyDebugDataAttributeOperation(Json::Value& _attributes, Json::Value const& _attributeOperation)
{
(void)_attributes;
(void)_attributeOperation;
}

std::optional<std::pair<std::string_view, SourceLocation>> Parser::parseSrcComment(
Expand Down
9 changes: 9 additions & 0 deletions libyul/AsmParser.h
Expand Up @@ -117,6 +117,13 @@ class Parser: public langutil::ParserBase
langutil::SourceLocation const& _commentLocation
);

std::optional<std::pair<std::string_view, std::optional<Json::Value>>> parseDebugDataAttributeOperationComment(
std::string_view _arguments,
langutil::SourceLocation const& _commentLocation
);

void applyDebugDataAttributeOperation(Json::Value& _attributes, Json::Value const& _attributeOperation);

/// Creates a DebugData object with the correct source location set.
langutil::DebugData::ConstPtr createDebugData() const;

Expand Down Expand Up @@ -160,9 +167,11 @@ class Parser: public langutil::ParserBase
langutil::SourceLocation m_locationOverride;
langutil::SourceLocation m_locationFromComment;
std::optional<int64_t> m_astIDFromComment;
std::optional<Json::Value> m_debugDataOperationFromComment;
UseSourceLocationFrom m_useSourceLocationFrom = UseSourceLocationFrom::Scanner;
ForLoopComponent m_currentForLoopComponent = ForLoopComponent::None;
bool m_insideFunction = false;
Json::Value m_currentDebugDataAttributes;
};

}

0 comments on commit 47e3966

Please sign in to comment.