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(syn-solidity): add statements and expressions #199

Merged
merged 27 commits into from
Aug 23, 2023
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
2 changes: 1 addition & 1 deletion crates/sol-macro/src/expand/enum.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! [`ItemEnum`] expansion.

use super::ExpCtxt;
use ast::ItemEnum;
use ast::{ItemEnum, Spanned};
use proc_macro2::TokenStream;
use quote::quote;
use syn::Result;
Expand Down
2 changes: 1 addition & 1 deletion crates/sol-macro/src/expand/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::{anon_name, expand_tuple_types, expand_type, ExpCtxt};
use crate::expand::ty::expand_event_tokenize_func;
use ast::{EventParameter, ItemEvent, SolIdent};
use ast::{EventParameter, ItemEvent, SolIdent, Spanned};
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
use syn::Result;
Expand Down
11 changes: 7 additions & 4 deletions crates/sol-macro/src/expand/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use crate::{
utils::ExprArray,
};
use ast::{
File, Item, ItemError, ItemEvent, ItemFunction, Parameters, SolIdent, SolPath, Type,
File, Item, ItemError, ItemEvent, ItemFunction, Parameters, SolIdent, SolPath, Spanned, Type,
VariableDeclaration, Visit,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, IdentFragment};
use quote::{format_ident, quote};
use std::{borrow::Borrow, collections::HashMap, fmt::Write};
use syn::{parse_quote, Attribute, Error, Result};

Expand Down Expand Up @@ -329,7 +329,7 @@ impl ExpCtxt<'_> {
}
}

fn raw_call_name(&self, function_name: impl IdentFragment + std::fmt::Display) -> Ident {
fn raw_call_name(&self, function_name: impl quote::IdentFragment + std::fmt::Display) -> Ident {
format_ident!("{function_name}Call")
}

Expand All @@ -338,7 +338,10 @@ impl ExpCtxt<'_> {
self.raw_call_name(function_name)
}

fn raw_return_name(&self, function_name: impl IdentFragment + std::fmt::Display) -> Ident {
fn raw_return_name(
&self,
function_name: impl quote::IdentFragment + std::fmt::Display,
) -> Ident {
format_ident!("{function_name}Return")
}

Expand Down
2 changes: 1 addition & 1 deletion crates/sol-macro/src/expand/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use super::{
expand_fields, expand_from_into_tuples, expand_type, ty::expand_tokenize_func, ExpCtxt,
};
use ast::{Item, ItemStruct, Type, VariableDeclaration};
use ast::{Item, ItemStruct, Spanned, Type, VariableDeclaration};
use proc_macro2::TokenStream;
use quote::quote;
use std::num::NonZeroU16;
Expand Down
18 changes: 10 additions & 8 deletions crates/sol-macro/src/expand/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::ExpCtxt;
use crate::expand::generate_name;
use ast::{EventParameter, Item, Parameters, Type, TypeArray, VariableDeclaration};
use ast::{EventParameter, Item, Parameters, Spanned, Type, TypeArray, VariableDeclaration};
use proc_macro2::{Literal, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
use std::{fmt, num::NonZeroU16};
Expand Down Expand Up @@ -102,7 +102,7 @@ fn rec_expand_type(ty: &Type, tokens: &mut TokenStream) {
Type::Array(ref array) => {
let ty = expand_type(&array.ty);
let span = array.span();
if let Some(size) = &array.size {
if let Some(size) = array.size() {
quote_spanned! {span=>
::alloy_sol_types::sol_data::FixedArray<#ty, #size>
}
Expand Down Expand Up @@ -153,11 +153,13 @@ pub(super) fn type_base_data_size(cx: &ExpCtxt<'_>, ty: &Type) -> usize {
Type::String(_) | Type::Bytes(_) | Type::Array(TypeArray { size: None, .. }) => 64,

// fixed array: size * encoded size
Type::Array(TypeArray {
ty: inner,
size: Some(size),
..
}) => type_base_data_size(cx, inner) * size.base10_parse::<usize>().unwrap(),
Type::Array(
a @ TypeArray {
ty: inner,
size: Some(_),
..
},
) => type_base_data_size(cx, inner) * a.size().unwrap(),

// tuple: sum of encoded sizes
Type::Tuple(tuple) => tuple
Expand Down Expand Up @@ -295,7 +297,7 @@ impl fmt::Display for TypePrinter<'_> {
Type::Array(array) => {
Self::new(self.cx, &array.ty).fmt(f)?;
f.write_str("[")?;
if let Some(size) = &array.size {
if let Some(size) = array.size() {
size.fmt(f)?;
}
f.write_str("]")
Expand Down
19 changes: 11 additions & 8 deletions crates/sol-macro/src/input.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use ast::Spanned;
use proc_macro2::TokenStream;
use quote::quote;
use std::path::PathBuf;
use syn::{
parse::{Parse, ParseStream},
parse::{discouraged::Speculative, Parse, ParseStream},
Error, Ident, LitStr, Result, Token,
};

#[derive(Clone, Debug)]
pub enum SolInputKind {
Sol(ast::File),
Type(ast::Type),
Expand All @@ -16,15 +18,15 @@ pub enum SolInputKind {
// doesn't parse Json
impl Parse for SolInputKind {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let start = input.fork();
match input.parse() {
Ok(file) => Ok(Self::Sol(file)),
Err(e) => match start.parse() {
let fork = input.fork();
match fork.parse() {
Ok(file) => {
input.advance_to(&fork);
Ok(Self::Sol(file))
}
Err(e) => match input.parse() {
Ok(ast::Type::Custom(_)) | Err(_) => Err(e),

Ok(ast::Type::Function(f)) => {
Err(Error::new(f.span(), "function types are not yet supported"))
}
Ok(ast::Type::Mapping(m)) => {
Err(Error::new(m.span(), "mapping types are not yet supported"))
}
Expand All @@ -35,6 +37,7 @@ impl Parse for SolInputKind {
}
}

#[derive(Clone, Debug)]
pub struct SolInput {
pub path: Option<PathBuf>,
pub kind: SolInputKind,
Expand Down
1 change: 0 additions & 1 deletion crates/sol-macro/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ fn expand_abi(name: &Ident, abi: JsonAbi) -> Result<TokenStream> {
// `Other` is a UDVT if it's not a basic Solidity type
if let Some(it) = internal_type.other_specifier() {
if it.try_basic_solidity().is_err() {
let _ = dbg!(it.try_basic_solidity());
udvts.insert(struct_ident(ty).to_owned(), real_ty.to_owned());
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/sol-types/tests/ui/type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ error: proc macro panicked
741 | | }
| |_^
|
= help: message: mapping types are unsupported: TypeMapping { key: TypeMapping { key: Custom([SolIdent("a")]), key_name: Some(SolIdent("b")), value: Custom([SolIdent("c")]), value_name: Some(SolIdent("d")) }, key_name: Some(SolIdent("e")), value: TypeMapping { key: Custom([SolIdent("f")]), key_name: Some(SolIdent("g")), value: Custom([SolIdent("h")]), value_name: Some(SolIdent("i")) }, value_name: Some(SolIdent("j")) }
= help: message: mapping types are unsupported: TypeMapping { key: Type::TypeMapping { key: Type::Custom([SolIdent("a")]), key_name: Some(SolIdent("b")), value: Type::Custom([SolIdent("c")]), value_name: Some(SolIdent("d")) }, key_name: Some(SolIdent("e")), value: Type::TypeMapping { key: Type::Custom([SolIdent("f")]), key_name: Some(SolIdent("g")), value: Type::Custom([SolIdent("h")]), value_name: Some(SolIdent("i")) }, value_name: Some(SolIdent("j")) }

error: proc macro panicked
--> tests/ui/type.rs:743:1
Expand All @@ -84,7 +84,7 @@ error: proc macro panicked
745 | | }
| |_^
|
= help: message: mapping types are unsupported: TypeMapping { key: Uint(Some(256)), key_name: Some(SolIdent("a")), value: Bool, value_name: Some(SolIdent("b")) }
= help: message: mapping types are unsupported: TypeMapping { key: Type::Uint(Some(256)), key_name: Some(SolIdent("a")), value: Type::Bool, value_name: Some(SolIdent("b")) }

error[E0412]: cannot find type `bytes_` in this scope
--> tests/ui/type.rs:205:9
Expand Down
20 changes: 16 additions & 4 deletions crates/syn-solidity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Basic usage:

```rust
use quote::quote;
use syn_solidity::{File, Item};
use syn_solidity::{Expr, File, Item, Lit, Stmt};

// Create a Solidity `TokenStream`
let tokens = quote! {
Expand All @@ -80,16 +80,28 @@ let tokens = quote! {
let ast: File = syn_solidity::parse2(tokens)?;

let items: &[Item] = &ast.items;
let Some(Item::Contract(contract)) = items.first() else { unreachable!() };
let Some(Item::Contract(contract)) = items.first() else {
unreachable!()
};
assert_eq!(contract.name, "HelloWorld");
assert_eq!(contract.attrs.len(), 2); // doc comments

let body: &[Item] = &contract.body;
let Some(Item::Function(function)) = body.first() else { unreachable!() };
let Some(Item::Function(function)) = body.first() else {
unreachable!()
};
assert_eq!(function.attrs.len(), 1); // doc comment
assert_eq!(function.name.as_ref().unwrap(), "helloWorld");
assert!(function.arguments.is_empty()); // ()
assert!(function.arguments.is_empty()); // ()
assert_eq!(function.attributes.len(), 2); // external pure
assert!(function.returns.is_some());

let Some([Stmt::Return(ret)]) = function.body() else {
unreachable!()
};
let Some(Expr::Lit(Lit::Str(s))) = &ret.expr else {
unreachable!()
};
assert_eq!(s.value(), "Hello, World!");
# syn::Result::Ok(())
```
53 changes: 35 additions & 18 deletions crates/syn-solidity/src/attribute/function.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use super::{kw, Modifier, Mutability, Override, SolPath, VariableAttribute, Visibility};
use crate::{kw, Modifier, Mutability, Override, SolPath, Spanned, VariableAttribute, Visibility};
use proc_macro2::Span;
use std::{
collections::HashSet,
fmt,
hash::{Hash, Hasher},
mem,
Expand All @@ -11,16 +10,22 @@ use syn::{
ext::IdentExt,
parse::{Parse, ParseStream},
token::Brace,
Error, Ident, Result,
Error, Ident, Result, Token,
};

/// A list of unique function attributes. Used in
/// [ItemFunction][crate::ItemFunction].
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct FunctionAttributes(pub HashSet<FunctionAttribute>);
#[derive(Clone, Default, PartialEq, Eq)]
pub struct FunctionAttributes(pub Vec<FunctionAttribute>);

impl fmt::Debug for FunctionAttributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl Deref for FunctionAttributes {
type Target = HashSet<FunctionAttribute>;
type Target = Vec<FunctionAttribute>;

fn deref(&self) -> &Self::Target {
&self.0
Expand All @@ -35,24 +40,34 @@ impl DerefMut for FunctionAttributes {

impl Parse for FunctionAttributes {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let mut attributes = HashSet::<FunctionAttribute>::new();
while !(input.is_empty() || input.peek(kw::returns) || !input.peek(Ident::peek_any)) {
let attr = input.parse()?;
if let Some(prev) = attributes.get(&attr) {
let mut attributes = Vec::<FunctionAttribute>::new();
while !input.is_empty() && !input.peek(kw::returns) && input.peek(Ident::peek_any) {
let attr: FunctionAttribute = input.parse()?;
if let Some(prev) = attributes.iter().find(|a| **a == attr) {
let mut e = Error::new(attr.span(), "duplicate attribute");
e.combine(Error::new(prev.span(), "previous declaration is here"));
return Err(e)
}
attributes.insert(attr);
attributes.push(attr);
}
Ok(Self(attributes))
}
}

impl Spanned for FunctionAttributes {
fn span(&self) -> Span {
crate::utils::join_spans(&self.0)
}

fn set_span(&mut self, span: Span) {
crate::utils::set_spans_clone(&mut self.0, span)
}
}

impl FunctionAttributes {
#[inline]
pub fn new() -> Self {
Self(HashSet::new())
Self(Vec::new())
}

pub fn visibility(&self) -> Option<Visibility> {
Expand Down Expand Up @@ -112,7 +127,7 @@ pub enum FunctionAttribute {
/// A [Mutability] attribute.
Mutability(Mutability),
/// `virtual`
Virtual(kw::Virtual),
Virtual(Token![virtual]),
/// `immutable`
Immutable(kw::immutable),
/// An [Override] attribute.
Expand Down Expand Up @@ -174,9 +189,9 @@ impl Parse for FunctionAttribute {
input.parse().map(Self::Visibility)
} else if Mutability::peek(&lookahead) {
input.parse().map(Self::Mutability)
} else if lookahead.peek(kw::Virtual) {
} else if lookahead.peek(Token![virtual]) {
input.parse().map(Self::Virtual)
} else if lookahead.peek(kw::Override) {
} else if lookahead.peek(Token![override]) {
input.parse().map(Self::Override)
} else if lookahead.peek(kw::immutable) {
input.parse().map(Self::Immutable)
Expand All @@ -202,8 +217,8 @@ impl From<VariableAttribute> for FunctionAttribute {
}
}

impl FunctionAttribute {
pub fn span(&self) -> Span {
impl Spanned for FunctionAttribute {
fn span(&self) -> Span {
match self {
Self::Visibility(v) => v.span(),
Self::Mutability(m) => m.span(),
Expand All @@ -214,7 +229,7 @@ impl FunctionAttribute {
}
}

pub fn set_span(&mut self, span: Span) {
fn set_span(&mut self, span: Span) {
match self {
Self::Visibility(v) => v.set_span(span),
Self::Mutability(m) => m.set_span(span),
Expand All @@ -224,7 +239,9 @@ impl FunctionAttribute {
Self::Modifier(m) => m.set_span(span),
}
}
}

impl FunctionAttribute {
#[inline]
pub const fn visibility(&self) -> Option<Visibility> {
match self {
Expand Down
Loading
Loading