Skip to content

Commit

Permalink
Add analysis::class_hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
gkoz committed Feb 24, 2016
1 parent 6a9f7fc commit 56a56ce
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 0 deletions.
70 changes: 70 additions & 0 deletions src/analysis/class_hierarchy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use library::*;
use std::collections::{HashMap, HashSet};
use std::iter::{self, Iterator};

struct Node {
supers: Vec<TypeId>,
subs: HashSet<TypeId>,
}

pub struct Info {
hier: HashMap<TypeId, Node>,
}

pub fn run(library: &Library) -> Info {
let mut hier = HashMap::new();
for (tid, _) in library.types() {
get_node(library, &mut hier, tid);
}
Info { hier: hier }
}

fn get_node<'a>(library: &Library, hier: &'a mut HashMap<TypeId, Node>, tid: TypeId)
-> Option<&'a mut Node> {
if hier.contains_key(&tid) {
return hier.get_mut(&tid)
}

let direct_supers: Vec<TypeId> = match *library.type_(tid) {
Type::Class(Class { ref parent, ref implements, .. }) => {
parent.iter()
.chain(implements.iter())
.cloned()
.collect()
}
Type::Interface(Interface { ref prerequisites, .. }) => {
prerequisites.clone()
}
_ => return None,
};

let mut supers = Vec::new();
for super_ in direct_supers {
let node = get_node(library, hier, super_).expect("parent must be a class or interface");
node.subs.insert(tid);
for &tid in [super_].iter().chain(node.supers.iter()) {
if !supers.contains(&tid) {
supers.push(tid);
}
}
}

hier.insert(tid, Node { supers: supers, subs: HashSet::new() });
hier.get_mut(&tid)
}

impl Info {
pub fn subtypes<'a>(&'a self, tid: TypeId) -> Box<Iterator<Item = TypeId> + 'a> {
match self.hier.get(&tid) {
Some(ref node) => Box::new(node.subs.iter().cloned()),
None => Box::new(iter::empty()),
}
}

pub fn supertypes(&self, tid: TypeId) -> &[TypeId] {
match self.hier.get(&tid) {
Some(ref node) => &node.supers,
None => &[],
}
}
}
1 change: 1 addition & 0 deletions src/analysis/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod bounds;
pub mod c_type;
pub mod class_hierarchy;
pub mod conversion_type;
pub mod functions;
pub mod general;
Expand Down
1 change: 1 addition & 0 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub struct Env {
pub config: Config,
pub namespaces: analysis::namespaces::Info,
pub symbols: RefCell<analysis::symbols::Info>,
pub class_hierarchy: analysis::class_hierarchy::Info,
}

impl Env {
Expand Down
12 changes: 12 additions & 0 deletions src/library.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::{BTreeSet, HashMap, HashSet};
use std::iter::Iterator;
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use nameutil::split_namespace_name;
Expand Down Expand Up @@ -678,6 +679,17 @@ impl Library {
pub fn register_version(&mut self, ns_id: u16, version: Version) {
self.namespace_mut(ns_id).versions.insert(version);
}

pub fn types<'a>(&'a self) -> Box<Iterator<Item = (TypeId, &Type)> + 'a> {
Box::new(self.namespaces.iter().enumerate()
.flat_map(|(ns_id, ns)| {
ns.types.iter().enumerate()
.filter_map(move |(id, type_)| {
let tid = TypeId { ns_id: ns_id as u16, id: id as u32 };
type_.as_ref().map(|t| (tid, t))
})
}))
}
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ fn do_main() -> Result<(), Box<Error>> {

let namespaces = analysis::namespaces::run(&library);
let symbols = analysis::symbols::run(&library, &namespaces);
let class_hierarchy = analysis::class_hierarchy::run(&library);

let env = Env{
library: library,
config: cfg,
namespaces: namespaces,
symbols: RefCell::new(symbols),
class_hierarchy: class_hierarchy,
};
codegen::generate(&env);

Expand Down

0 comments on commit 56a56ce

Please sign in to comment.