Skip to content

Move the TypeCollector trait to the ir module #177

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

Merged
merged 1 commit into from
Oct 31, 2016
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
129 changes: 1 addition & 128 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ use ir::item_kind::ItemKind;
use ir::comp::{CompKind, CompInfo, Field, Method};
use ir::layout::Layout;
use ir::annotations::FieldAccessorKind;
use ir::type_collector::{ItemSet, TypeCollector};

use std::ops;
use std::borrow::Cow;
use std::mem;
use std::collections::BTreeSet;
use std::collections::HashSet;
use std::collections::hash_map::{HashMap, Entry};

Expand Down Expand Up @@ -1584,133 +1584,6 @@ impl CodeGenerator for Function {
}
}

type ItemSet = BTreeSet<ItemId>;

trait TypeCollector {
type Extra;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
extra: &Self::Extra);
}

impl TypeCollector for ItemId {
type Extra = ();

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
extra: &()) {
context.resolve_item(*self).collect_types(context, types, extra);
}
}

impl TypeCollector for Item {
type Extra = ();

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
_extra: &()) {
if self.is_hidden(context) || types.contains(&self.id()) {
return;
}

match *self.kind() {
ItemKind::Type(ref ty) => {
types.insert(self.id());
if !self.is_opaque(context) {
ty.collect_types(context, types, self);
}
}
_ => {}, // FIXME.
}
}
}

impl TypeCollector for Type {
type Extra = Item;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
item: &Item) {
match *self.kind() {
TypeKind::Pointer(inner) |
TypeKind::Reference(inner) |
TypeKind::Array(inner, _) |
TypeKind::TemplateAlias(inner, _) |
TypeKind::Alias(_, inner) |
TypeKind::Named(_, Some(inner)) |
TypeKind::ResolvedTypeRef(inner)
=> inner.collect_types(context, types, &()),

TypeKind::TemplateRef(inner, ref template_args) => {
inner.collect_types(context, types, &());
for item in template_args {
item.collect_types(context, types, &());
}
}
TypeKind::Comp(ref ci) => ci.collect_types(context, types, item),
TypeKind::Function(ref sig) => {
sig.collect_types(context, types, item)
}
// FIXME: Pending types!
ref other @ _ => {
debug!("Ignoring: {:?}", other);
},
}
}
}

impl TypeCollector for FunctionSig {
type Extra = Item;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
_item: &Item) {
self.return_type().collect_types(context, types, &());

for &(_, ty) in self.argument_types() {
ty.collect_types(context, types, &());
}
}
}

impl TypeCollector for CompInfo {
type Extra = Item;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
item: &Item) {
if let Some(template) = self.specialized_template() {
template.collect_types(context, types, &());
}

let applicable_template_args = item.applicable_template_args(context);
for arg in applicable_template_args {
arg.collect_types(context, types, &());
}

for base in self.base_members() {
base.collect_types(context, types, &());
}

for field in self.fields() {
field.ty().collect_types(context, types, &());
}

for ty in self.inner_types() {
ty.collect_types(context, types, &());
}

// FIXME(emilio): Methods, VTable?
}
}

pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
context.gen(|context| {
let mut result = CodegenResult::new();
Expand Down
33 changes: 33 additions & 0 deletions src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use super::context::BindgenContext;
use super::layout::Layout;
use super::item::{Item, ItemId};
use super::ty::{Type, RUST_DERIVE_IN_ARRAY_LIMIT};
use super::type_collector::{ItemSet, TypeCollector};
use std::cell::Cell;
use std::cmp;
use parse::{ClangItemParser, ParseError};
Expand Down Expand Up @@ -804,3 +805,35 @@ impl CompInfo {
})
}
}

impl TypeCollector for CompInfo {
type Extra = Item;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
item: &Item) {
if let Some(template) = self.specialized_template() {
template.collect_types(context, types, &());
}

let applicable_template_args = item.applicable_template_args(context);
for arg in applicable_template_args {
arg.collect_types(context, types, &());
}

for base in self.base_members() {
base.collect_types(context, types, &());
}

for field in self.fields() {
field.ty().collect_types(context, types, &());
}

for ty in self.inner_types() {
ty.collect_types(context, types, &());
}

// FIXME(emilio): Methods, VTable?
}
}
2 changes: 1 addition & 1 deletion src/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enum TypeKey {
// context.
struct GenContext<'ctx>(ExtCtxt<'ctx>);

impl<'ctx> fmt::Debug for GenContext <'ctx> {
impl<'ctx> fmt::Debug for GenContext<'ctx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "GenContext {{ ... }}")
}
Expand Down
18 changes: 17 additions & 1 deletion src/ir/function.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Intermediate representation for C/C++ functions and methods.

use super::context::BindgenContext;
use super::item::{Item, ItemId};
use super::ty::TypeKind;
use super::context::BindgenContext;
use super::type_collector::{ItemSet, TypeCollector};
use syntax::abi;
use clang;
use clangll::Enum_CXCallingConv;
Expand Down Expand Up @@ -246,3 +247,18 @@ impl ClangSubItemParser for Function {
Ok(ParseResult::New(function, Some(cursor)))
}
}

impl TypeCollector for FunctionSig {
type Extra = Item;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
_item: &Item) {
self.return_type().collect_types(context, types, &());

for &(_, ty) in self.argument_types() {
ty.collect_types(context, types, &());
}
}
}
39 changes: 37 additions & 2 deletions src/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use regex::Regex;
use super::context::BindgenContext;
use super::item_kind::ItemKind;
use super::ty::{Type, TypeKind};
use super::type_collector::{ItemSet, TypeCollector};
use super::function::Function;
use super::module::Module;
use super::annotations::Annotations;
Expand Down Expand Up @@ -76,6 +77,40 @@ impl ItemCanonicalPath for ItemId {
}
}

impl TypeCollector for ItemId {
type Extra = ();

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
extra: &()) {
context.resolve_item(*self).collect_types(context, types, extra);
}
}

impl TypeCollector for Item {
type Extra = ();

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
_extra: &()) {
if self.is_hidden(context) || types.contains(&self.id()) {
return;
}

match *self.kind() {
ItemKind::Type(ref ty) => {
types.insert(self.id());
if !self.is_opaque(context) {
ty.collect_types(context, types, self);
}
}
_ => {}, // FIXME.
}
}
}

/// An item is the base of the bindgen representation, it can be either a
/// module, a type, a function, or a variable (see `ItemKind` for more
/// information).
Expand Down Expand Up @@ -566,12 +601,12 @@ impl Item {
static ref RE_ENDS_WITH_BINDGEN_TY: Regex = Regex::new(r"_bindgen_ty(_\d+)+$").unwrap();
static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = Regex::new(r"_bindgen_mod(_\d+)+$").unwrap();
}

let (re, kind) = match *self.kind() {
ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"),
_ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"),
};

let parent_name = parent_name.and_then(|n| if n.is_empty() { None } else { Some(n) });
match (parent_name, base_name) {
(Some(parent), Some(base)) => format!("{}_{}", parent, base),
Expand Down
1 change: 1 addition & 0 deletions src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ pub mod item_kind;
pub mod layout;
pub mod module;
pub mod ty;
pub mod type_collector;
pub mod var;
36 changes: 36 additions & 0 deletions src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use super::item::{Item, ItemId};
use super::int::IntKind;
use super::layout::Layout;
use super::context::BindgenContext;
use super::type_collector::{ItemSet, TypeCollector};
use parse::{ClangItemParser, ParseResult, ParseError};
use clang::{self, Cursor};

Expand Down Expand Up @@ -709,3 +710,38 @@ impl Type {
Ok(ParseResult::New(ty, Some(cursor.canonical())))
}
}

impl TypeCollector for Type {
type Extra = Item;

fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
item: &Item) {
match *self.kind() {
TypeKind::Pointer(inner) |
TypeKind::Reference(inner) |
TypeKind::Array(inner, _) |
TypeKind::TemplateAlias(inner, _) |
TypeKind::Alias(_, inner) |
TypeKind::Named(_, Some(inner)) |
TypeKind::ResolvedTypeRef(inner)
=> inner.collect_types(context, types, &()),

TypeKind::TemplateRef(inner, ref template_args) => {
inner.collect_types(context, types, &());
for item in template_args {
item.collect_types(context, types, &());
}
}
TypeKind::Comp(ref ci) => ci.collect_types(context, types, item),
TypeKind::Function(ref sig) => {
sig.collect_types(context, types, item)
}
// FIXME: Pending types!
ref other @ _ => {
debug!("Ignoring: {:?}", other);
},
}
}
}
23 changes: 23 additions & 0 deletions src/ir/type_collector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//! Collecting type items.

use std::collections::BTreeSet;
use super::context::BindgenContext;
use super::item::ItemId;

/// A set of items.
pub type ItemSet = BTreeSet<ItemId>;

/// Collect all the type items referenced by this item.
pub trait TypeCollector {
/// If a particular type needs extra information beyond what it has in
/// `self` and `context` to find its referenced type items, its
/// implementation can define this associated type, forcing callers to pass
/// the needed information through.
type Extra;

/// Add each type item referenced by `self` into the `types` set.
fn collect_types(&self,
context: &BindgenContext,
types: &mut ItemSet,
extra: &Self::Extra);
}