Skip to content

Commit

Permalink
Use prefered solution for local crate references from procedural macros
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Jan 21, 2019
1 parent 7a5bdf6 commit 5b7af83
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 79 deletions.
44 changes: 22 additions & 22 deletions kas-macros/src/layout_cw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ use syn::Ident;
use syn::parse::{Error, Result};
use crate::args::Child;

pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
pub(crate) fn fns(children: &Vec<Child>, layout: Option<Ident>)
-> Result<TokenStream>
{
let (constraints, appls) = if children.is_empty() {
// TODO: warn on invalid layout specification
(quote!{
let v_w = #c::cw_var!(self, w);
let v_h = #c::cw_var!(self, h);
let v_w = kas::cw_var!(self, w);
let v_h = kas::cw_var!(self, h);

let (min, hint) = tk.size_hints(self.tkd());

Expand Down Expand Up @@ -54,11 +54,11 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
let ident = &children[0].ident;
(quote!{
s.add_constraint(cw::Constraint::new(
cw::Expression::from(#c::cw_var!(self, w)) - #c::cw_var!(self.#ident, w),
cw::Expression::from(kas::cw_var!(self, w)) - kas::cw_var!(self.#ident, w),
cw::RelationalOperator::Equal,
cw::strength::STRONG)).unwrap();
s.add_constraint(cw::Constraint::new(
cw::Expression::from(#c::cw_var!(self, h)) - #c::cw_var!(self.#ident, h),
cw::Expression::from(kas::cw_var!(self, h)) - kas::cw_var!(self.#ident, h),
cw::RelationalOperator::Equal,
cw::strength::STRONG)).unwrap();
self.#ident.init_constraints(tk, s, _use_default);
Expand All @@ -67,17 +67,17 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
if let Some(l) = layout {
if l == "horizontal" {
let mut constr = quote!{
let mut width = cw::Expression::from(#c::cw_var!(self, w));
let height = cw::Expression::from(#c::cw_var!(self, h));
let mut width = cw::Expression::from(kas::cw_var!(self, w));
let height = cw::Expression::from(kas::cw_var!(self, h));
};
let mut appls = quote!{ let mut cpos = pos; };

for child in children {
let ident = &child.ident;

constr.append_all(quote!{
let child_v_w = #c::cw_var!(self.#ident, w);
let child_v_h = #c::cw_var!(self.#ident, h);
let child_v_w = kas::cw_var!(self.#ident, w);
let child_v_h = kas::cw_var!(self.#ident, h);
width -= child_v_w;
s.add_constraint(cw::Constraint::new(
height.clone() - child_v_h,
Expand All @@ -92,7 +92,7 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)

appls.append_all(quote!{
self.#ident.apply_constraints(tk, s, cpos);
cpos.0 += s.get_value(#c::cw_var!(self.#ident, w)) as i32;
cpos.0 += s.get_value(kas::cw_var!(self.#ident, w)) as i32;
});
}

Expand All @@ -106,17 +106,17 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
(constr, appls)
} else if l == "vertical" {
let mut constr = quote!{
let width = cw::Expression::from(#c::cw_var!(self, w));
let mut height = cw::Expression::from(#c::cw_var!(self, h));
let width = cw::Expression::from(kas::cw_var!(self, w));
let mut height = cw::Expression::from(kas::cw_var!(self, h));
};
let mut appls = quote!{ let mut cpos = pos; };

for child in children {
let ident = &child.ident;

constr.append_all(quote!{
let child_v_w = #c::cw_var!(self.#ident, w);
let child_v_h = #c::cw_var!(self.#ident, h);
let child_v_w = kas::cw_var!(self.#ident, w);
let child_v_h = kas::cw_var!(self.#ident, h);
s.add_constraint(cw::Constraint::new(
width.clone() - child_v_w,
cw::RelationalOperator::GreaterOrEqual,
Expand All @@ -131,7 +131,7 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)

appls.append_all(quote!{
self.#ident.apply_constraints(tk, s, cpos);
cpos.1 += s.get_value(#c::cw_var!(self.#ident, h)) as i32;
cpos.1 += s.get_value(kas::cw_var!(self.#ident, h)) as i32;
});
}

Expand All @@ -154,20 +154,20 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
}
};
Ok(quote! {
fn init_constraints(&self, tk: &#c::TkWidget,
s: &mut #c::cw::Solver, _use_default: bool)
fn init_constraints(&self, tk: &kas::TkWidget,
s: &mut kas::cw::Solver, _use_default: bool)
{
use #c::cw;
use kas::cw;
#constraints
}

fn apply_constraints(&mut self, tk: &#c::TkWidget,
s: &#c::cw::Solver, pos: #c::Coord)
fn apply_constraints(&mut self, tk: &kas::TkWidget,
s: &kas::cw::Solver, pos: kas::Coord)
{
#appls

let w = s.get_value(#c::cw_var!(self, w)) as i32;
let h = s.get_value(#c::cw_var!(self, h)) as i32;
let w = s.get_value(kas::cw_var!(self, w)) as i32;
let h = s.get_value(kas::cw_var!(self, h)) as i32;
let tkd = self.tkd();
let rect = self.rect_mut();
rect.pos = pos;
Expand Down
20 changes: 10 additions & 10 deletions kas-macros/src/layout_extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ use syn::{parse_quote, Path, Ident};
use syn::parse::{Error, Result};
use crate::args::Child;

pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
pub(crate) fn fns(children: &Vec<Child>, layout: Option<Ident>)
-> Result<TokenStream>
{
let layout: Path = if let Some(l) = layout {
if l == "single" {
parse_quote!{ #c::ChildLayout::None }
parse_quote!{ kas::ChildLayout::None }
} else if l == "horizontal" {
parse_quote!{ #c::ChildLayout::Horizontal }
parse_quote!{ kas::ChildLayout::Horizontal }
} else if l == "vertical" {
parse_quote!{ #c::ChildLayout::Vertical }
parse_quote!{ kas::ChildLayout::Vertical }
} else if l == "grid" {
parse_quote!{ #c::ChildLayout::Grid }
parse_quote!{ kas::ChildLayout::Grid }
} else {
return Err(Error::new(l.span(),
"expected one of: single, horizontal, vertical, grid"));
}
} else {
parse_quote!{ #c::ChildLayout::None }
parse_quote!{ kas::ChildLayout::None }
};

let mut pos_rules = TokenStream::new();
Expand All @@ -40,19 +40,19 @@ pub(crate) fn fns(c: &TokenStream, children: &Vec<Child>, layout: Option<Ident>)
}

Ok(quote! {
fn child_layout(&self) -> #c::ChildLayout {
fn child_layout(&self) -> kas::ChildLayout {
#layout
}

fn grid_pos(&self, _index: usize) -> Option<#c::GridPos> {
fn grid_pos(&self, _index: usize) -> Option<kas::GridPos> {
match _index {
#pos_rules
_ => None
}
}

fn sync_size(&mut self, tk: &#c::TkWidget) {
use #c::Core;
fn sync_size(&mut self, tk: &kas::TkWidget) {
use kas::Core;
let new_rect = tk.get_rect(self.tkd());
*self.rect_mut() = new_rect;

Expand Down
79 changes: 32 additions & 47 deletions kas-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ extern crate proc_macro;

mod args;

use std::env;
use std::fmt::Write;
use proc_macro2::{Span, TokenStream};
use quote::{quote, TokenStreamExt};
Expand Down Expand Up @@ -146,7 +145,6 @@ use self::args::{Class, ChildType};
#[proc_macro_derive(Widget, attributes(core, widget, handler))]
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput);
let c = c();

let args = match args::read_attrs(&mut ast) {
Ok(w) => w,
Expand All @@ -159,7 +157,7 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let class = args.widget.class;
let count = args.children.len();

let layout_fns = match layout::fns(&c, &args.children, args.widget.layout) {
let layout_fns = match layout::fns(&args.children, args.widget.layout) {
Ok(fns) => fns,
Err(err) => return err.to_compile_error().into(),
};
Expand All @@ -176,58 +174,58 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let get_mut_rules = make_match_rules(&args.children, quote!{mut});

let mut toks = quote! {
impl #impl_generics #c::Core
impl #impl_generics kas::Core
for #name #ty_generics #where_clause
{
fn number(&self) -> u32 {
use #c::Core;
use kas::Core;
self.#core.number()
}
fn set_number(&mut self, number: u32) {
use #c::Core;
use kas::Core;
self.#core.set_number(number);
}

fn tkd(&self) -> #c::TkData {
use #c::Core;
fn tkd(&self) -> kas::TkData {
use kas::Core;
self.#core.tkd()
}
fn set_tkd(&mut self, tkd: #c::TkData) {
use #c::Core;
fn set_tkd(&mut self, tkd: kas::TkData) {
use kas::Core;
self.#core.set_tkd(tkd)
}

fn rect(&self) -> &#c::Rect {
use #c::Core;
fn rect(&self) -> &kas::Rect {
use kas::Core;
self.#core.rect()
}
fn rect_mut(&mut self) -> &mut #c::Rect {
use #c::Core;
fn rect_mut(&mut self) -> &mut kas::Rect {
use kas::Core;
self.#core.rect_mut()
}
}

impl #impl_generics #c::Layout
impl #impl_generics kas::Layout
for #name #ty_generics #where_clause
{
#layout_fns
}

impl #impl_generics #c::Widget
impl #impl_generics kas::Widget
for #name #ty_generics #where_clause
{
fn class(&self) -> #c::Class { #class }
fn class(&self) -> kas::Class { #class }

fn len(&self) -> usize {
#count
}
fn get(&self, _index: usize) -> Option<&#c::Widget> {
fn get(&self, _index: usize) -> Option<&kas::Widget> {
match _index {
#get_rules
_ => None
}
}
fn get_mut(&mut self, _index: usize) -> Option<&mut #c::Widget> {
fn get_mut(&mut self, _index: usize) -> Option<&mut kas::Widget> {
match _index {
#get_mut_rules
_ => None
Expand Down Expand Up @@ -276,15 +274,15 @@ pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
}

toks.append_all(quote! {
impl #impl_generics #c::event::Handler
impl #impl_generics kas::event::Handler
for #name #ty_generics #where_clause
{
type Response = #response;

fn handle_action(&mut self, _tk: &#c::TkWidget, action: #c::event::Action,
fn handle_action(&mut self, _tk: &kas::TkWidget, action: kas::event::Action,
num: u32) -> Self::Response
{
use #c::{Core, event::{Handler, err_unhandled, err_num}};
use kas::{Core, event::{Handler, err_unhandled, err_num}};

if num == self.number() {
// we may want to allow custom handlers on self here?
Expand Down Expand Up @@ -442,10 +440,8 @@ pub fn make_widget(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
// Used to make fresh identifiers for generic types
let mut name_buf = String::with_capacity(32);

let c = c();

// fields of anonymous struct:
let mut field_toks = quote!{ #[core] core: #c::CoreData, };
let mut field_toks = quote!{ #[core] core: kas::CoreData, };
// initialisers for these fields:
let mut field_val_toks = quote!{ core: Default::default(), };
// debug impl
Expand All @@ -463,10 +459,10 @@ pub fn make_widget(input: proc_macro::TokenStream) -> proc_macro::TokenStream {

let widget_args = match args.class {
Class::Container(layout) => quote!{
class = #c::Class::Container, layout = #layout
class = kas::Class::Container, layout = #layout
},
Class::Frame => quote!{
class = #c::Class::Frame
class = kas::Class::Frame
},
};

Expand All @@ -492,32 +488,32 @@ pub fn make_widget(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
gen_tys.push(ty.clone());
if let Some(ref wattr) = attr {
if let Some(tyr) = gen_response {
handler_clauses.push(quote!{ #ty: #c::event::Handler<Response = #tyr> });
handler_clauses.push(quote!{ #ty: kas::event::Handler<Response = #tyr> });
} else {
// No typing. If a handler is specified, then the child must implement
// Handler<Response = X> where the handler takes type X; otherwise
// we use `msg.into()` and this conversion must be supported.
if let Some(ref handler) = wattr.args.handler {
if let Some(ty_bound) = find_handler_ty(handler, &args.impls) {
handler_clauses.push(quote!{ #ty: #c::event::Handler<Response = #ty_bound> });
handler_clauses.push(quote!{ #ty: kas::event::Handler<Response = #ty_bound> });
} else {
return quote!{}.into(); // exit after emitting error
}
} else {
name_buf.push_str("R");
let tyr = Ident::new(&name_buf, Span::call_site());
handler_extra.push(tyr.clone());
handler_clauses.push(quote!{ #ty: #c::event::Handler<Response = #tyr> });
handler_clauses.push(quote!{ #tyr: From<#c::event::NoResponse> });
handler_clauses.push(quote!{ #ty: kas::event::Handler<Response = #tyr> });
handler_clauses.push(quote!{ #tyr: From<kas::event::NoResponse> });
handler_clauses.push(quote!{ #response: From<#tyr> });
}
}

if let Some(mut bound) = gen_bound {
bound.bounds.push(parse_quote!{ #c::Widget });
bound.bounds.push(parse_quote!{ kas::Widget });
gen_ptrs.push(quote!{ #ty: #bound });
} else {
gen_ptrs.push(quote!{ #ty: #c::Widget });
gen_ptrs.push(quote!{ #ty: kas::Widget });
}
} else {
gen_ptrs.push(quote!{ #ty });
Expand Down Expand Up @@ -563,7 +559,7 @@ pub fn make_widget(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let toks = (quote!{ {
#[widget(#widget_args)]
#[handler(response = #response, generics = < #handler_extra > #handler_where)]
#[derive(Clone, Debug, #c::macros::Widget)]
#[derive(Clone, Debug, kas::macros::Widget)]
struct AnonWidget<#gen_ptrs> {
#field_toks
}
Expand All @@ -585,28 +581,17 @@ pub fn make_widget(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
#[proc_macro_derive(NoResponse)]
pub fn derive_no_response(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let c = c();
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let name = &ast.ident;

let toks = quote!{
impl #impl_generics From<#c::event::NoResponse>
impl #impl_generics From<kas::event::NoResponse>
for #name #ty_generics #where_clause
{
fn from(_: #c::event::NoResponse) -> Self {
fn from(_: kas::event::NoResponse) -> Self {
#name::None
}
}
};
toks.into()
}

// Our stand-in for $crate. Imperfect, but works (excepting other crates in
// the same package, i.e. doc-tests, examples, integration tests, benches).
fn c() -> TokenStream {
if env::var("CARGO_PKG_NAME") == Ok("kas".to_string()) {
parse_quote!( crate )
} else {
parse_quote!( kas )
}
}
Loading

0 comments on commit 5b7af83

Please sign in to comment.