Skip to content

Commit

Permalink
Next. Initial working demo.
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioBenitez committed Dec 30, 2017
1 parent 0a169d4 commit b49a4b4
Show file tree
Hide file tree
Showing 8 changed files with 1,773 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ required-features = ["extra-traits", "parsing", "printing", "full"]

[features]
default = ["parsing", "printing", "clone-impls"]
unstable = ["visit", "proc-macro2/unstable"]
full = []
parsing = ["quote"]
printing = ["quote"]
Expand All @@ -36,3 +37,6 @@ unicode-xid = "0.1"
[dev-dependencies]
rayon = "0.9"
walkdir = "1.0.1"

[patch.crates-io]
proc-macro2 = { path = "../proc-macro2" }
52 changes: 52 additions & 0 deletions codegen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const SYN_CRATE_ROOT: &str = "../src/lib.rs";
const FOLD_SRC: &str = "../src/gen/fold.rs";
const VISIT_SRC: &str = "../src/gen/visit.rs";
const VISIT_MUT_SRC: &str = "../src/gen/visit_mut.rs";
const SPANNED_SRC: &str = "../src/gen/spanned.rs";

const IGNORED_MODS: &[&str] = &["fold", "visit", "visit_mut"];

Expand Down Expand Up @@ -317,6 +318,7 @@ mod codegen {
pub visit_mut_impl: String,
pub fold_trait: String,
pub fold_impl: String,
pub spanned_impls: String,
}

fn under_name(name: Ident) -> Ident {
Expand Down Expand Up @@ -724,6 +726,22 @@ mod codegen {
ty = s.ast.ident,
));

if under_name != "span" {
state.spanned_impls.push_str(&format!(
"{features}\n\
impl Spanned for ::{ty} {{\n \
fn span(&self) -> Option<::proc_macro::Span> {{\n \
let mut visitor = SpanVisitor::default();\n \
visitor.visit_{under_name}(self);\n \
visitor.span\n \
}}\n\
}}\n\n",
features = s.features,
under_name = under_name,
ty = s.item.ident,
));
}

// XXX: This part is a disaster - I'm not sure how to make it cleaner though :'(
match s.ast.body {
Body::Enum(ref e) => {
Expand Down Expand Up @@ -1108,4 +1126,38 @@ pub trait VisitorMut {{
visit_mut_trait = state.visit_mut_trait,
visit_mut_impl = state.visit_mut_impl
).unwrap();

let mut spanned_file = File::create(SPANNED_SRC).unwrap();
write!(spanned_file,
"\
// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT
#![cfg_attr(rustfmt, rustfmt_skip)]
#![cfg_attr(feature = \"cargo-clippy\", allow(match_same_arms))]
use visit::Visitor;
pub trait Spanned {{
/// Returns the `proc_macro::Span` of this item if it can be retrieved. When
/// using the `Span` for error reporting, it is safe to `unwrap()` it.
///
/// This method is only available when the `unstable` feature is enabled.
fn span(&self) -> Option<::proc_macro::Span>;
}}
#[derive(Default)]
struct SpanVisitor {{
span: Option<::proc_macro::Span>,
}}
impl<'a> Visitor<'a> for SpanVisitor {{
fn visit_span(&mut self, sp: &'a ::proc_macro2::Span) {{
self.span = self.span.map_or(Some(sp.into_inner()), |s| s.join(sp.into_inner()));
}}
}}
{spanned_impls}
",
spanned_impls = state.spanned_impls
).unwrap();
}
17 changes: 17 additions & 0 deletions examples/unstable/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "unstable"
version = "0.1.0"
authors = ["Sergio Benitez <sb@sergio.bz>"]

[lib]
proc-macro = true

[[bin]]
name = "unstable"
path = "src/main.rs"

[dependencies]
syn = { path = "../../", features = ["full", "unstable"] }

[patch.crates-io]
proc-macro2 = { path = "../../../proc-macro2" }
66 changes: 66 additions & 0 deletions examples/unstable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#![feature(proc_macro)]

extern crate syn;
extern crate proc_macro;

use proc_macro::{TokenStream, Diagnostic};

use syn::*;
use syn::spanned::Spanned;
use syn::synom::{Synom, Cursor, SynomBuffer};

struct Parser {
buffer: Box<SynomBuffer>,
cursor: Cursor<'static>
}

impl Parser {
fn new(tokens: TokenStream) -> Parser {
let buffer = Box::new(SynomBuffer::new(tokens.into()));
let cursor = unsafe {
let buffer: &'static SynomBuffer = ::std::mem::transmute(&*buffer);
buffer.begin()
};

Parser {
buffer: buffer,
cursor: cursor
}
}

fn parse<T: Synom>(&mut self) -> Result<T, Diagnostic> {
let (cursor, val) = T::parse(self.cursor).map_err(|e| e.into())?;
self.cursor = cursor;
Ok(val)
}
}

fn eval(input: TokenStream) -> Result<TokenStream, Diagnostic> {
let mut parser = Parser::new(input);

let a = parser.parse::<ExprTuple>()?;
parser.parse::<token::Eq>()?;
let b = parser.parse::<ExprTuple>()?;

let (a_len, b_len) = (a.args.len(), b.args.len());
if a_len != b_len {
let diag = b.span().expect("b's span")
.error(format!("expected {} element(s), got {}", a_len, b_len))
.span_note(a.span().expect("a's span"), "because of this");

return Err(diag);
}

Ok("println!(\"All good!\")".parse().unwrap())
}

#[proc_macro]
pub fn demo(input: TokenStream) -> TokenStream {
match eval(input) {
Ok(val) => val,
Err(diag) => {
diag.emit();
"".parse().unwrap()
}
}
}
7 changes: 7 additions & 0 deletions examples/unstable/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[macro_use]
extern crate unstable;

pub fn main() {
demo!((a, b) = (1, 2, 3));
}

10 changes: 10 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ impl Display for ParseError {
}
}

#[cfg(feature = "unstable")]
use proc_macro::{Level, Diagnostic};

#[cfg(feature = "unstable")]
impl Into<Diagnostic> for ParseError {
fn into(self) -> Diagnostic {
Diagnostic::new(Level::Error, self.to_string())
}
}

impl ParseError {
// For syn use only. Not public API.
#[doc(hidden)]
Expand Down
Loading

0 comments on commit b49a4b4

Please sign in to comment.