Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: parse some more doc comments #47

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions crates/parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,7 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
fn parse_enum(&mut self) -> PResult<'sess, ItemEnum<'ast>> {
let name = self.parse_ident()?;
let (variants, _) = self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
// Ignore doc-comments.
let _ = this.parse_doc_comments()?;
this.ignore_doc_comments();
this.parse_ident()
})?;
Ok(ItemEnum { name, variants })
Expand Down Expand Up @@ -706,8 +705,7 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
ty
}
None => {
// Ignore doc-comments.
let _ = self.parse_doc_comments()?;
self.ignore_doc_comments();
self.parse_type()?
}
};
Expand Down
39 changes: 38 additions & 1 deletion crates/parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,10 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
/// This always-inlined version should only be used on hot code paths.
#[inline(always)]
fn inlined_bump_with(&mut self, next_token: Token) {
#[cfg(debug_assertions)]
if next_token.is_comment() {
self.comment_in_stream(next_token.span);
}
self.prev_token = std::mem::replace(&mut self.token, next_token);
self.expected_tokens.clear();
}
Expand Down Expand Up @@ -773,19 +777,52 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
}
}

/// Parses and ignores contiguous doc comments.
#[inline]
pub fn ignore_doc_comments(&mut self) {
if matches!(self.token.kind, TokenKind::Comment(..)) {
self.ignore_doc_comments_inner();
}
}

#[cold]
fn ignore_doc_comments_inner(&mut self) {
while let Token { span, kind: TokenKind::Comment(is_doc, _kind, _symbol) } = self.token {
if !is_doc {
self.comment_in_stream(span);
}
self.bump();
}
}

/// Parses contiguous doc comments. Can be empty.
#[inline]
pub fn parse_doc_comments(&mut self) -> PResult<'sess, DocComments<'ast>> {
if matches!(self.token.kind, TokenKind::Comment(..)) {
self.parse_doc_comments_inner()
} else {
Ok(Default::default())
}
}

#[cold]
fn parse_doc_comments_inner(&mut self) -> PResult<'sess, DocComments<'ast>> {
let mut doc_comments = SmallVec::<[_; 4]>::new();
while let Token { span, kind: TokenKind::Comment(is_doc, kind, symbol) } = self.token {
if !is_doc {
self.dcx().bug("comments should not be in the token stream").span(span).emit();
self.comment_in_stream(span);
}
doc_comments.push(DocComment { kind, span, symbol });
self.bump();
}
Ok(self.alloc_smallvec(doc_comments))
}

#[cold]
fn comment_in_stream(&self, span: Span) -> ! {
self.dcx().bug("comments should not be in the token stream").span(span).emit()
}

/// Parses a qualified identifier: `foo.bar.baz`.
#[track_caller]
pub fn parse_path(&mut self) -> PResult<'sess, AstPath<'ast>> {
Expand Down
14 changes: 6 additions & 8 deletions crates/parse/src/parser/yul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::SeqSep;
use crate::{PResult, Parser};
use smallvec::SmallVec;
use sulk_ast::{
ast::{yul::*, AstPath, Box, LitKind, PathSlice, StrKind, StrLit},
ast::{yul::*, AstPath, Box, DocComments, LitKind, PathSlice, StrKind, StrLit},
token::*,
};
use sulk_interface::{error_code, kw, sym, Ident};
Expand All @@ -16,10 +16,7 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
pub fn parse_yul_file_object(&mut self) -> PResult<'sess, Object<'ast>> {
let docs = self.parse_doc_comments()?;
let object = if self.check_keyword(sym::object) {
self.parse_yul_object().map(|mut obj| {
obj.docs = docs;
obj
})
self.parse_yul_object(docs)
} else {
let lo = self.token.span;
self.parse_yul_block().map(|code| {
Expand All @@ -36,8 +33,7 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
/// Parses a Yul object.
///
/// Reference: <https://docs.soliditylang.org/en/latest/yul.html#specification-of-yul-object>
pub fn parse_yul_object(&mut self) -> PResult<'sess, Object<'ast>> {
let docs = self.parse_doc_comments()?;
pub fn parse_yul_object(&mut self, docs: DocComments<'ast>) -> PResult<'sess, Object<'ast>> {
let lo = self.token.span;
self.expect_keyword(sym::object)?;
let name = self.parse_str_lit()?;
Expand All @@ -47,8 +43,9 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {
let mut children = Vec::new();
let mut data = Vec::new();
loop {
let docs = self.parse_doc_comments()?;
if self.check_keyword(sym::object) {
children.push(self.parse_yul_object()?);
children.push(self.parse_yul_object(docs)?);
} else if self.check_keyword(sym::data) {
data.push(self.parse_yul_data()?);
} else {
Expand Down Expand Up @@ -242,6 +239,7 @@ impl<'sess, 'ast> Parser<'sess, 'ast> {

/// Parses a Yul expression.
fn parse_yul_expr(&mut self) -> PResult<'sess, Expr<'ast>> {
self.ignore_doc_comments();
self.parse_spanned(Self::parse_yul_expr_kind).map(|(span, kind)| Expr { span, kind })
}

Expand Down
194 changes: 194 additions & 0 deletions tests/ui/parser/yul/solc_generated.opt.yul
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
// solc +0.8.26 --ir-optimized ./c.sol
contract C {
function f(uint256 x) public returns (uint256) {
uint256 y = 1;
y += 69;
unchecked {
y *= x;
}
y /= 64;
return y;
}
}
*/

/// @use-src 0:"c.sol"
object "C_28" {
code {
{
/// @src 0:0:198 "contract C {..."
mstore(64, memoryguard(0x80))
if callvalue()
{
revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
}
let _1 := allocate_unbounded()
codecopy(_1, dataoffset("C_28_deployed"), datasize("C_28_deployed"))
return(_1, datasize("C_28_deployed"))
}
function allocate_unbounded() -> memPtr
{ memPtr := mload(64) }
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
{ revert(0, 0) }
}
/// @use-src 0:"c.sol"
object "C_28_deployed" {
code {
{
/// @src 0:0:198 "contract C {..."
mstore(64, memoryguard(0x80))
if iszero(lt(calldatasize(), 4))
{
let selector := shift_right_unsigned(calldataload(0))
switch selector
case 0xb3de648b { external_fun_f() }
default { }
}
revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74()
}
function shift_right_unsigned(value) -> newValue
{ newValue := shr(224, value) }
function allocate_unbounded() -> memPtr
{ memPtr := mload(64) }
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
{ revert(0, 0) }
function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b()
{ revert(0, 0) }
function cleanup_uint256(value) -> cleaned
{ cleaned := value }
function validator_revert_uint256(value)
{
if iszero(eq(value, cleanup_uint256(value))) { revert(0, 0) }
}
function abi_decode_uint256(offset, end) -> value
{
value := calldataload(offset)
validator_revert_uint256(value)
}
function abi_decode_tuple_uint256(headStart, dataEnd) -> value0
{
if slt(sub(dataEnd, headStart), 32)
{
revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b()
}
let offset := 0
value0 := abi_decode_uint256(add(headStart, offset), dataEnd)
}
function abi_encode_uint256_to_uint256(value, pos)
{
mstore(pos, cleanup_uint256(value))
}
function abi_encode_uint256(headStart, value0) -> tail
{
tail := add(headStart, 32)
abi_encode_uint256_to_uint256(value0, add(headStart, 0))
}
function external_fun_f()
{
if callvalue()
{
revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
}
let param := abi_decode_tuple_uint256(4, calldatasize())
let ret := fun_f(param)
let memPos := allocate_unbounded()
let memEnd := abi_encode_uint256(memPos, ret)
return(memPos, sub(memEnd, memPos))
}
function revert_error_42b3090547df1d2001c96683413b8cf91c1b902ef5e3cb8d9f6f304cf7446f74()
{ revert(0, 0) }
function zero_value_for_split_uint256() -> ret
{ ret := 0 }
function cleanup_rational_by(value) -> cleaned
{ cleaned := value }
function identity(value) -> ret
{ ret := value }
function convert_rational_1_by_1_to_uint256(value) -> converted
{
converted := cleanup_uint256(identity(cleanup_rational_by(value)))
}
function cleanup_t_rational_by(value) -> cleaned
{ cleaned := value }
function convert_t_rational_by_to_t_uint256(value) -> converted
{
converted := cleanup_uint256(identity(cleanup_t_rational_by(value)))
}
function panic_error_0x11()
{
mstore(0, shl(224, 0x4e487b71))
mstore(4, 0x11)
revert(0, 0x24)
}
function checked_add_uint256(x, y) -> sum
{
x := cleanup_uint256(x)
y := cleanup_uint256(y)
sum := add(x, y)
if gt(x, sum) { panic_error_0x11() }
}
function wrapping_mul_uint256(x, y) -> product
{
product := cleanup_uint256(mul(x, y))
}
function cleanup_rational_by_1(value) -> cleaned
{ cleaned := value }
function convert_rational_by_to_uint256(value) -> converted
{
converted := cleanup_uint256(identity(cleanup_rational_by_1(value)))
}
function panic_error_0x12()
{
mstore(0, shl(224, 0x4e487b71))
mstore(4, 0x12)
revert(0, 0x24)
}
function checked_div_uint256(x, y) -> r
{
x := cleanup_uint256(x)
y := cleanup_uint256(y)
if iszero(y) { panic_error_0x12() }
r := div(x, y)
}
/// @ast-id 27 @src 0:17:196 "function f(uint256 x) public returns (uint256) {..."
function fun_f(var_x) -> var
{
/// @src 0:55:62 "uint256"
let zero_uint256 := zero_value_for_split_uint256()
var := zero_uint256
/// @src 0:86:87 "1"
let expr := 0x01
/// @src 0:74:87 "uint256 y = 1"
let var_y := convert_rational_1_by_1_to_uint256(expr)
/// @src 0:102:104 "69"
let expr_1 := 0x45
/// @src 0:97:104 "y += 69"
let _1 := convert_t_rational_by_to_t_uint256(expr_1)
let _2 := var_y
let expr_2 := checked_add_uint256(_2, _1)
var_y := expr_2
/// @src 0:143:144 "x"
let _3 := var_x
let expr_3 := _3
/// @src 0:138:144 "y *= x"
let _4 := var_y
let expr_4 := wrapping_mul_uint256(_4, expr_3)
var_y := expr_4
/// @src 0:169:171 "64"
let expr_5 := 0x40
/// @src 0:164:171 "y /= 64"
let _5 := convert_rational_by_to_uint256(expr_5)
let _6 := var_y
let expr_6 := checked_div_uint256(_6, _5)
var_y := expr_6
/// @src 0:188:189 "y"
let _7 := var_y
let expr_7 := _7
/// @src 0:181:189 "return y"
var := expr_7
leave
}
}
data ".metadata" hex"a2646970667358221220cb9774dc0239e8b062f7fc217650f80938f632767d6cc747e42e316bf835731064736f6c634300081a0033"
}
}
Loading