Skip to content

Commit 05d2044

Browse files
committed
Parse @ast-id annotation.
1 parent 42739b7 commit 05d2044

File tree

4 files changed

+107
-9
lines changed

4 files changed

+107
-9
lines changed

libyul/AST.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,22 @@ using Type = YulString;
3838

3939
struct DebugData
4040
{
41-
explicit DebugData(langutil::SourceLocation _location): location(std::move(_location)) {}
41+
explicit DebugData(langutil::SourceLocation _location, std::optional<int64_t> _astID = {}):
42+
location(std::move(_location)),
43+
astID(std::move(_astID))
44+
{}
45+
46+
static std::shared_ptr<DebugData const> create(
47+
langutil::SourceLocation _location = {},
48+
std::optional<int64_t> _astID = {}
49+
)
50+
{
51+
return std::make_shared<DebugData const>(std::move(_location), std::move(_astID));
52+
}
53+
4254
langutil::SourceLocation location;
4355
/// ID in the (Solidity) source AST.
4456
std::optional<int64_t> astID;
45-
static std::shared_ptr<DebugData const> create(langutil::SourceLocation _location = {})
46-
{
47-
return std::make_shared<DebugData const>(_location);
48-
}
4957
};
5058

5159
struct TypedName { std::shared_ptr<DebugData const> debugData; YulString name; Type type; };

libyul/AsmParser.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ unique_ptr<Block> Parser::parseInline(std::shared_ptr<Scanner> const& _scanner)
103103
try
104104
{
105105
m_scanner = _scanner;
106-
if (m_sourceNames)
106+
if (m_useSourceLocationFrom == UseSourceLocationFrom::Comments)
107107
fetchDebugDataFromComment();
108108
return make_unique<Block>(parseBlock());
109109
}
@@ -136,6 +136,8 @@ void Parser::fetchDebugDataFromComment()
136136
match_results<string_view::const_iterator> match;
137137

138138
langutil::SourceLocation sourceLocation = m_debugDataOverride->location;
139+
// Empty for each new node.
140+
optional<int> astID;
139141

140142
while (regex_search(commentLiteral.cbegin(), commentLiteral.cend(), match, tagRegex))
141143
{
@@ -149,12 +151,19 @@ void Parser::fetchDebugDataFromComment()
149151
else
150152
break;
151153
}
154+
else if (match[1] == "@ast-id")
155+
{
156+
if (auto parseResult = parseASTIDComment(commentLiteral, m_scanner->currentCommentLocation()))
157+
tie(commentLiteral, astID) = *parseResult;
158+
else
159+
break;
160+
}
152161
else
153162
// Ignore unrecognized tags.
154163
continue;
155164
}
156165

157-
m_debugDataOverride = DebugData::create(sourceLocation);
166+
m_debugDataOverride = DebugData::create(sourceLocation, astID);
158167
}
159168

160169
optional<pair<string_view, SourceLocation>> Parser::parseSrcComment(
@@ -222,6 +231,38 @@ optional<pair<string_view, SourceLocation>> Parser::parseSrcComment(
222231
return {{tail, SourceLocation{}}};
223232
}
224233

234+
optional<pair<string_view, optional<int>>> Parser::parseASTIDComment(
235+
string_view _arguments,
236+
langutil::SourceLocation const& _commentLocation
237+
)
238+
{
239+
static regex const argRegex = regex(
240+
R"~~(^(\d+)(?:\s|$))~~",
241+
regex_constants::ECMAScript | regex_constants::optimize
242+
);
243+
match_results<string_view::const_iterator> match;
244+
optional<int> astID;
245+
bool matched = regex_search(_arguments.cbegin(), _arguments.cend(), match, argRegex);
246+
string_view tail = _arguments;
247+
if (matched)
248+
{
249+
solAssert(match.size() == 2, "");
250+
tail = _arguments.substr(static_cast<size_t>(match.position() + match.length()));
251+
252+
astID = toInt(match[1].str());
253+
}
254+
255+
if (!matched || !astID || *astID < 0 || static_cast<int64_t>(*astID) != *astID)
256+
{
257+
m_errorReporter.syntaxError(1749_error, _commentLocation, "Invalid argument for @ast-id.");
258+
astID = nullopt;
259+
}
260+
if (matched)
261+
return {{_arguments, astID}};
262+
else
263+
return nullopt;
264+
}
265+
225266
Block Parser::parseBlock()
226267
{
227268
RecursionGuard recursionGuard(*this);

libyul/AsmParser.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,12 @@ class Parser: public langutil::ParserBase
108108

109109
void fetchDebugDataFromComment();
110110

111-
std::optional<std::pair<std::string_view, langutil::SourceLocation>>
112-
parseSrcComment(
111+
std::optional<std::pair<std::string_view, langutil::SourceLocation>> parseSrcComment(
112+
std::string_view _arguments,
113+
langutil::SourceLocation const& _commentLocation
114+
);
115+
116+
std::optional<std::pair<std::string_view, std::optional<int>>> parseASTIDComment(
113117
std::string_view _arguments,
114118
langutil::SourceLocation const& _commentLocation
115119
);

test/libyul/Parser.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,51 @@ BOOST_AUTO_TEST_CASE(customSourceLocations_with_code_snippets_with_nested_locati
804804
CHECK_LOCATION(literal128.debugData->location, "source1", 96, 165);
805805
}
806806

807+
BOOST_AUTO_TEST_CASE(astid)
808+
{
809+
ErrorList errorList;
810+
ErrorReporter reporter(errorList);
811+
auto const sourceText = R"(
812+
/// @src -1:-1:-1 @ast-id 7
813+
{
814+
/** @ast-id 2 */
815+
function f(x) -> y {}
816+
mstore(1, 2)
817+
}
818+
)";
819+
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
820+
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
821+
BOOST_REQUIRE(!!result);
822+
BOOST_CHECK(result->debugData->astID == int64_t(7));
823+
auto const& funDef = get<FunctionDefinition>(result->statements.at(0));
824+
BOOST_CHECK(funDef.debugData->astID == int64_t(2));
825+
BOOST_CHECK(funDef.parameters.at(0).debugData->astID == nullopt);
826+
BOOST_CHECK(debugDataOf(result->statements.at(1))->astID == nullopt);
827+
}
828+
829+
BOOST_AUTO_TEST_CASE(astid_reset)
830+
{
831+
ErrorList errorList;
832+
ErrorReporter reporter(errorList);
833+
auto const sourceText = R"(
834+
/// @src -1:-1:-1 @ast-id 7 @src 1:1:1
835+
{
836+
/** @ast-id 2 */
837+
function f(x) -> y {}
838+
mstore(1, 2)
839+
}
840+
)";
841+
EVMDialectTyped const& dialect = EVMDialectTyped::instance(EVMVersion{});
842+
shared_ptr<Block> result = parse(sourceText, dialect, reporter);
843+
BOOST_REQUIRE(!!result);
844+
BOOST_CHECK(result->debugData->astID == int64_t(7));
845+
auto const& funDef = get<FunctionDefinition>(result->statements.at(0));
846+
BOOST_CHECK(funDef.debugData->astID == int64_t(2));
847+
BOOST_CHECK(funDef.parameters.at(0).debugData->astID == nullopt);
848+
BOOST_CHECK(debugDataOf(result->statements.at(1))->astID == nullopt);
849+
}
850+
851+
807852
BOOST_AUTO_TEST_CASE(customSourceLocations_multiple_src_tags_on_one_line)
808853
{
809854
ErrorList errorList;

0 commit comments

Comments
 (0)