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

Support yul ast #268

Merged
merged 19 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f77819c
feat: support for basic yul types
mouseless0x Sep 4, 2023
ed50a53
feat: support parsing of yul-like evm opcodes
mouseless0x Sep 5, 2023
dc4ed26
feat(syn-solidity): parse yul function calls
mouseless0x Sep 6, 2023
cf5ee38
feat(syn-solidity): support parsing yul for loops
mouseless0x Sep 6, 2023
b57f356
feat(syn-solidity): support parsing yul switch statements
mouseless0x Sep 8, 2023
766cde1
feat(syn-solidity): move walrus token to own file, support parsing as…
mouseless0x Sep 9, 2023
7c5741d
feat(syn-solidity): parse yul stmts
mouseless0x Sep 10, 2023
5642d78
feat(syn-solidity): parse hex num, yul lits, + cleanup
mouseless0x Sep 11, 2023
3b3f3ed
feat(syn-solidity): support yul path + bug fixes
mouseless0x Sep 12, 2023
6d2385b
cleanup + parsing bug fixes
mouseless0x Sep 13, 2023
4b249b5
fix small nits
mouseless0x Sep 13, 2023
c0bb4e6
Update crates/syn-solidity/src/yul/type/function.rs
mouseless0x Sep 15, 2023
c6decf4
fix: correct doc link for yulAssignment
mouseless0x Sep 15, 2023
4133d3e
fix: expose private struct vars
mouseless0x Sep 15, 2023
c74a7f5
fix: replace redudant YulPath enum with wrapper struct
mouseless0x Sep 16, 2023
e781035
fix: ignore tokens in fmt::Debug, convert YulAssign & YulDecl into st…
mouseless0x Sep 16, 2023
80d4064
fix: replace blob import with individual imports
mouseless0x Sep 16, 2023
bef16a0
fix: ensure switch has atleast one case or default
mouseless0x Sep 16, 2023
f646ef3
fix: remove YulLit and replace with crate::Lit
mouseless0x Sep 16, 2023
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
82 changes: 82 additions & 0 deletions crates/syn-solidity/src/kw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,86 @@ custom_keywords!(
new,
revert,
unchecked,

// Yul other
switch,
case,
default,
leave,

// Yul-EVM-builtin opcodes
stop,
add,
sub,
mul,
div,
sdiv,
//mod,
smod,
exp,
not,
lt,
gt,
slt,
sgt,
eq,
iszero,
and,
or,
xor,
byte,
shl,
shr,
sar,
addmod,
mulmod,
signextend,
keccak256,
pop,
mload,
mstore,
mstore8,
sload,
sstore,
msize,
gas,
address,
balance,
selfbalance,
caller,
callvalue,
calldataload,
calldatasize,
calldatacopy,
extcodesize,
extcodecopy,
returndatasize,
returndatacopy,
extcodehash,
create,
create2,
call,
callcode,
delegatecall,
staticcall,
//return,
//revert,
selfdestruct,
invalid,
log0,
log1,
log2,
log3,
log4,
chainid,
origin,
gasprice,
blockhash,
coinbase,
timestamp,
number,
difficulty,
prevrandao,
gaslimit,
basefee,
);
6 changes: 5 additions & 1 deletion crates/syn-solidity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ pub mod visit_mut;
pub use visit_mut::VisitMut;

mod yul;
pub use yul::YulBlock;
pub use yul::{
WalrusToken, YulBlock, YulCaseBranch, YulEVMBuiltIn, YulExpr, YulFnCall, YulFor,
YulFunctionDef, YulIdent, YulIf, YulPath, YulReturns, YulStmt, YulSwitch, YulSwitchDefault,
YulVarAssign, YulVarDecl,
};

/// Parse a Solidity [`proc_macro::TokenStream`] into a [`File`].
pub fn parse(input: proc_macro::TokenStream) -> Result<File> {
Expand Down
104 changes: 104 additions & 0 deletions crates/syn-solidity/src/yul/expr/fn_call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use crate::{utils::DebugPunctuated, Spanned, YulEVMBuiltIn, YulExpr, YulIdent};

use proc_macro2::Span;
use std::fmt;
use syn::{
parenthesized,
parse::{discouraged::Speculative, Parse, ParseStream, Result},
punctuated::Punctuated,
token::Paren,
Token,
};

/// Yul function call.
///
/// Solidity Reference:
/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulFunctionCall>
#[derive(Clone)]
pub struct YulFnCall {
pub function_type: FnType,
pub paren_token: Paren,
pub arguments: Punctuated<YulExpr, Token![,]>,
}

impl Parse for YulFnCall {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let content;
Ok(Self {
function_type: input.parse()?,
paren_token: parenthesized!(content in input),
arguments: content.parse_terminated(YulExpr::parse, Token![,])?,
})
}
}

impl Spanned for YulFnCall {
fn span(&self) -> Span {
let span = self.function_type.span();
span.join(self.arguments.span()).unwrap_or(span)
}

fn set_span(&mut self, span: Span) {
self.function_type.set_span(span);
self.paren_token = Paren(span);
self.arguments.set_span(span);
}
}

impl fmt::Debug for YulFnCall {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("YulFnCall")
.field("function_type", &self.function_type)
.field("arguments", DebugPunctuated::new(&self.arguments))
.finish()
}
}

/// What type of function is called.
#[derive(Clone)]
pub enum FnType {
/// When calling a self defined function
Custom(YulIdent),

/// When calling a built in evm opcode
EVMOpcode(YulEVMBuiltIn),
}

impl Parse for FnType {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let speculative_parse = input.fork();

if let Ok(evm_builtin) = speculative_parse.parse::<YulEVMBuiltIn>() {
input.advance_to(&speculative_parse);
Ok(Self::EVMOpcode(evm_builtin))
} else {
Ok(Self::Custom(input.parse::<YulIdent>()?))
}
}
}

impl Spanned for FnType {
fn span(&self) -> Span {
match self {
Self::Custom(custom) => custom.span(),
Self::EVMOpcode(opcode) => opcode.span(),
}
}

fn set_span(&mut self, span: Span) {
match self {
Self::Custom(custom) => custom.set_span(span),
Self::EVMOpcode(opcode) => opcode.set_span(span),
}
}
}

impl fmt::Debug for FnType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("FnType::")?;
match self {
Self::Custom(custom) => custom.fmt(f),
Self::EVMOpcode(opcode) => opcode.fmt(f),
}
}
}
69 changes: 69 additions & 0 deletions crates/syn-solidity/src/yul/expr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use crate::{Lit, Spanned, YulPath};

use std::fmt;

use proc_macro2::Span;
use syn::{
parse::{discouraged::Speculative, Parse, ParseStream, Result},
token::Paren,
};

mod fn_call;
pub use fn_call::YulFnCall;

/// A Yul expression.
///
/// Solidity Reference:
/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.yulExpression>
#[derive(Clone)]
pub enum YulExpr {
Path(YulPath),
Call(YulFnCall),
Literal(Lit),
}

impl Parse for YulExpr {
fn parse(input: ParseStream<'_>) -> Result<Self> {
if input.peek2(Paren) {
return input.parse().map(Self::Call)
}

let speculative_parse = input.fork();

if let Ok(lit) = speculative_parse.parse::<Lit>() {
input.advance_to(&speculative_parse);
return Ok(Self::Literal(lit))
}

input.parse().map(Self::Path)
}
}

impl Spanned for YulExpr {
fn span(&self) -> Span {
match self {
Self::Path(path) => path.span(),
Self::Call(call) => call.span(),
Self::Literal(lit) => lit.span(),
}
}

fn set_span(&mut self, span: Span) {
match self {
Self::Path(path) => path.set_span(span),
Self::Call(call) => call.set_span(span),
Self::Literal(lit) => lit.set_span(span),
}
}
}

impl fmt::Debug for YulExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("YulExpr::")?;
match self {
Self::Path(path) => path.fmt(f),
Self::Call(call) => call.fmt(f),
Self::Literal(lit) => lit.fmt(f),
}
}
}
Loading