Skip to content

Commit

Permalink
feat: parse some more doc comments (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored Aug 20, 2024
1 parent 6c73224 commit 0be73ba
Show file tree
Hide file tree
Showing 5 changed files with 503 additions and 13 deletions.
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

0 comments on commit 0be73ba

Please sign in to comment.