Skip to content
This repository has been archived by the owner on May 6, 2020. It is now read-only.

Commit

Permalink
Get quasi to work with syntex
Browse files Browse the repository at this point in the history
  • Loading branch information
erickt committed May 18, 2015
1 parent a08065b commit 8c6bdd6
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 61 deletions.
8 changes: 5 additions & 3 deletions quasi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ license = "MIT/Apache-2.0"
description = "A quasi-quoting macro system"
repository = "https://github.com/erickt/rust-quasi"

[dev-dependencies]
aster = "*"
quasi_macros = { version = "*", path = "../quasi_macros" }
[features]
with-syntex = ["syntex_syntax"]

[dependencies]
syntex_syntax = { version = "*", optional = true }
6 changes: 5 additions & 1 deletion quasi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(collections, rustc_private)]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private))]

#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;

#[cfg(not(feature = "with-syntex"))]
extern crate syntax;

use std::rc::Rc;
Expand Down
7 changes: 6 additions & 1 deletion quasi_codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@ license = "MIT/Apache-2.0"
description = "A quasi-quoting macro system"
repository = "https://github.com/erickt/rust-quasi"

[features]
with-syntex = ["syntex", "syntex_syntax", "aster/with-syntex"]

[dependencies]
aster = "*"
aster = { version = "*", default-features = false }
syntex = { version = "*", optional = true }
syntex_syntax = { version = "*", optional = true }
149 changes: 110 additions & 39 deletions quasi_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(plugin_registrar, unboxed_closures, rustc_private)]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private))]

extern crate aster;
extern crate rustc;

#[cfg(feature = "with-syntex")]
extern crate syntex;

#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;

#[cfg(not(feature = "with-syntex"))]
extern crate syntax;

#[cfg(not(feature = "with-syntex"))]
extern crate rustc;

use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
Expand All @@ -35,7 +45,7 @@ fn expand_quote_tokens<'cx>(
tts: &[ast::TokenTree],
) -> Box<base::MacResult + 'cx> {
let (cx_expr, expr) = expand_tts(cx, sp, tts);
let expanded = expand_wrapper(sp, cx_expr, expr, &[&["quasi"]]);
let expanded = expand_wrapper(sp, cx_expr, expr);
base::MacEager::expr(expanded)
}

Expand All @@ -44,7 +54,12 @@ fn expand_quote_ty<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_ty", vec!(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_ty"],
vec!(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -53,7 +68,12 @@ fn expand_quote_expr<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_expr"],
Vec::new(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -62,7 +82,12 @@ fn expand_quote_stmt<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_stmt", vec!(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_stmt"],
vec!(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -73,8 +98,12 @@ fn expand_quote_attr<'cx>(
) -> Box<base::MacResult + 'cx> {
let builder = aster::AstBuilder::new().span(sp);

let expanded = expand_parse_call(cx, sp, "parse_attribute",
vec![builder.expr().bool(true)], tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "attr", "ParserAttr", "parse_attribute"],
vec![builder.expr().bool(true)],
tts);

base::MacEager::expr(expanded)
}
Expand All @@ -94,7 +123,7 @@ fn expand_quote_matcher<'cx>(
.with_stmts(vector)
.expr().id("tt");

let expanded = expand_wrapper(sp, cx_expr, block, &[&["quasi"]]);
let expanded = expand_wrapper(sp, cx_expr, block);
base::MacEager::expr(expanded)
}

Expand All @@ -103,7 +132,12 @@ fn expand_quote_pat<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_pat", vec!(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_pat"],
vec!(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -112,7 +146,12 @@ fn expand_quote_arm<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_arm", vec!(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_arm"],
vec!(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -121,7 +160,12 @@ fn expand_quote_block<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_block", Vec::new(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_block"],
Vec::new(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -130,8 +174,12 @@ fn expand_quote_item<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_item",
vec!(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_item"],
vec!(),
tts);
base::MacEager::expr(expanded)
}

Expand All @@ -140,8 +188,12 @@ fn expand_quote_impl_item<'cx>(
sp: Span,
tts: &[ast::TokenTree]
) -> Box<base::MacResult + 'cx> {
let expanded = expand_parse_call(cx, sp, "parse_impl_item",
vec!(), tts);
let expanded = expand_parse_call(
cx,
sp,
&["syntax", "parse", "parser", "Parser", "parse_impl_item"],
vec!(),
tts);
base::MacEager::expr(expanded)
}

Expand Down Expand Up @@ -405,8 +457,14 @@ fn statements_mk_tt(tt: &ast::TokenTree, matcher: bool) -> Vec<P<ast::Stmt>> {

let builder = builder.clone().span(sp);

let e_to_toks = builder.expr().method_call("to_tokens")
.id(ident)
let to_tokens = builder.path()
.global()
.ids(&["quasi", "ToTokens", "to_tokens"])
.build();

let e_to_toks = builder.expr().call()
.build_path(to_tokens)
.arg().addr_of().id(ident)
.arg().id("ext_cx")
.build();

Expand Down Expand Up @@ -596,8 +654,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])

fn expand_wrapper(sp: Span,
cx_expr: P<ast::Expr>,
expr: P<ast::Expr>,
imports: &[&[&str]]) -> P<ast::Expr> {
expr: P<ast::Expr>) -> P<ast::Expr> {
let builder = aster::AstBuilder::new().span(sp);

// Explicitly borrow to avoid moving from the invoker (#16992)
Expand All @@ -607,23 +664,14 @@ fn expand_wrapper(sp: Span,
let stmt_let_ext_cx = builder.stmt().let_id("ext_cx")
.build(cx_expr_borrow);

let use_stmts = imports.iter()
.map(|path| {
builder.stmt().item()
.attr().allow(&["unused_imports"])
.use_().ids(path.iter()).build()
.glob()
});

builder.expr().block()
.with_stmts(use_stmts)
.with_stmt(stmt_let_ext_cx)
.build_expr(expr)
}

fn expand_parse_call(cx: &ExtCtxt,
sp: Span,
parse_method: &str,
parse_method: &[&str],
arg_exprs: Vec<P<ast::Expr>> ,
tts: &[ast::TokenTree]) -> P<ast::Expr> {
let builder = aster::AstBuilder::new().span(sp);
Expand All @@ -638,26 +686,49 @@ fn expand_parse_call(cx: &ExtCtxt,
.id("ext_cx")
.build();

let new_parser_from_tts_path = builder.path()
.global()
.ids(&["syntax", "parse", "new_parser_from_tts"])
.build();

let new_parser_call = builder.expr().call()
.id("new_parser_from_tts")
.build_path(new_parser_from_tts_path)
.with_arg(parse_sess_call)
.with_arg(cfg_call)
.with_arg(tts_expr)
.build();

let expr = builder.expr().method_call(parse_method)
.build(new_parser_call)
let parse_method_path = builder.path()
.global()
.ids(parse_method)
.build();

let expr = builder.expr().call()
.build_path(parse_method_path)
.arg().mut_addr_of().build(new_parser_call)
.with_args(arg_exprs)
.build();

if parse_method == "parse_attribute" {
expand_wrapper(sp, cx_expr, expr, &[&["quasi"],
&["syntax", "parse", "attr"]])
} else {
expand_wrapper(sp, cx_expr, expr, &[&["quasi"]])
}
expand_wrapper(sp, cx_expr, expr)
}

#[cfg(feature = "with-syntex")]
pub fn register(reg: &mut syntex::Registry) {
reg.add_macro("quote_tokens", expand_quote_tokens);
reg.add_macro("quote_ty", expand_quote_ty);
reg.add_macro("quote_expr", expand_quote_expr);
reg.add_macro("quote_matcher", expand_quote_matcher);
reg.add_macro("quote_stmt", expand_quote_stmt);
reg.add_macro("quote_attr", expand_quote_attr);
reg.add_macro("quote_pat", expand_quote_pat);
reg.add_macro("quote_arm", expand_quote_arm);
reg.add_macro("quote_block", expand_quote_block);
reg.add_macro("quote_item", expand_quote_item);
reg.add_macro("quote_impl_item", expand_quote_impl_item);
//reg.add_macro("quote_where_clause", expand_quote_where_clause);
}

#[cfg(not(feature = "syntex"))]
pub fn register(reg: &mut rustc::plugin::Registry) {
reg.register_macro("quote_tokens", expand_quote_tokens);
reg.register_macro("quote_ty", expand_quote_ty);
Expand Down
4 changes: 4 additions & 0 deletions quasi_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ plugin = true

[dependencies]
quasi_codegen = { version = "*", path = "../quasi_codegen" }

[dev-dependencies]
aster = "*"
quasi = { version = "*", path = "../quasi" }
18 changes: 18 additions & 0 deletions quasi_macros/tests/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(plugin, rustc_private)]
#![plugin(quasi_macros)]

extern crate aster;
extern crate quasi;
extern crate syntax;

include!("../../quasi_tests/tests/test.rs.in");
18 changes: 18 additions & 0 deletions quasi_tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "quasi_tests"
version = "0.3.0"
authors = ["Erick Tryzelaar <[email protected]>"]
license = "MIT/Apache-2.0"
description = "A quasi-quoting macro system"
repository = "https://github.com/erickt/rust-quasi"
build = "build.rs"

[build-dependencies]
quasi_codegen = { version = "*", path = "../quasi_codegen", features = ["with-syntex"] }
syntex = { version = "*" }

[dev-dependencies]
aster = { version = "*", features = ["with-syntex"] }
quasi = { version = "*", path = "../quasi", features = ["with-syntex"] }
syntex = { version = "*" }
syntex_syntax = { version = "*" }
16 changes: 16 additions & 0 deletions quasi_tests/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
extern crate syntex;
extern crate quasi_codegen;

use std::env;
use std::path::Path;

pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let mut registry = syntex::Registry::new();
quasi_codegen::register(&mut registry);

let src = Path::new("tests/test.rs.in");
let dst = Path::new(&out_dir).join("test.rs");

registry.expand("", &src, &dst).unwrap();
}
15 changes: 15 additions & 0 deletions quasi_tests/tests/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate aster;
extern crate quasi;
extern crate syntex_syntax as syntax;

include!(concat!(env!("OUT_DIR"), "/test.rs"));
Loading

0 comments on commit 8c6bdd6

Please sign in to comment.