[DEV-7084] TAMER: AsgBuilderState

This completes the POC extraction for AsgBuilder, but is still POC
code.  The commits that follow will clean it up and provide tests.
master
Mike Gerwitz 2020-04-07 10:43:54 -04:00
parent 3f46917da9
commit da69118592
3 changed files with 38 additions and 64 deletions

View File

@ -25,12 +25,12 @@ use crate::fs::{
};
use crate::global;
use crate::ir::asg::{
Asg, AsgError, DefaultAsg, IdentObject, IdentObjectData, ObjectRef,
Sections, SortableAsg,
Asg, AsgError, DefaultAsg, IdentObject, IdentObjectData, Sections,
SortableAsg,
};
use crate::obj::xmle::writer::XmleWriter;
use crate::obj::xmlo::reader::{XmloError, XmloReader};
use crate::obj::xmlo::{AsgBuilder, AsgBuilderResult};
use crate::obj::xmlo::{AsgBuilder, AsgBuilderState};
use crate::sym::{DefaultInterner, Interner, Symbol};
use fxhash::{FxBuildHasher, FxHashMap};
use std::error::Error;
@ -39,39 +39,33 @@ use std::io::BufReader;
use std::path::PathBuf;
type LinkerAsg<'i> = DefaultAsg<'i, IdentObject<'i>, global::ProgIdentSize>;
type LinkerObjectRef = ObjectRef<global::ProgIdentSize>;
type LoadResult<'i> =
Result<Option<(Option<&'i Symbol<'i>>, Option<String>)>, Box<dyn Error>>;
type LinkerAsgBuilderState<'i> =
AsgBuilderState<'i, FxBuildHasher, global::ProgIdentSize>;
pub fn main(package_path: &str, output: &str) -> Result<(), Box<dyn Error>> {
let mut fs = VisitOnceFilesystem::new();
let mut fragments: FxHashMap<&str, String> = Default::default();
let mut depgraph = LinkerAsg::with_capacity(65536, 65536);
let mut roots = Vec::new();
let interner = DefaultInterner::new();
let abs_path = fs::canonicalize(package_path)?;
let (name, relroot) = load_xmlo(
let state = load_xmlo(
&abs_path.to_str().unwrap().to_string(),
&mut fs,
&mut fragments,
&mut depgraph,
&interner,
&mut roots,
)?
.expect("missing root package information");
Default::default(),
)?;
// println!(
// "Graph {:?}",
// depgraph
// .graph
// .raw_nodes()
// .iter()
// .map(|node| &node.weight)
// .collect::<Vec<_>>()
// );
let AsgBuilderState {
mut roots,
name,
relroot,
found: _,
} = state;
roots.extend(
vec!["___yield", "___worksheet"]
@ -127,31 +121,24 @@ fn load_xmlo<'a, 'i, I: Interner<'i>>(
fragments: &mut FxHashMap<&'i str, String>,
depgraph: &mut LinkerAsg<'i>,
interner: &'i I,
roots: &mut Vec<LinkerObjectRef>,
) -> LoadResult<'i> {
let first = fs.visit_len() == 0;
state: LinkerAsgBuilderState<'i>,
) -> Result<LinkerAsgBuilderState<'i>, Box<dyn Error>> {
let cfile: CanonicalFile<BufReader<fs::File>> = match fs.open(path_str)? {
VisitOnceFile::FirstVisit(file) => file,
VisitOnceFile::Visited => return Ok(None),
VisitOnceFile::Visited => return Ok(state),
};
let (path, file) = cfile.into();
let xmlo: XmloReader<'_, _, _> = (file, interner).into();
let AsgBuilderResult::<'i, FxBuildHasher, _> {
found,
roots: mut pkgroots,
name,
relroot,
} = xmlo.build(depgraph, first)?;
roots.append(&mut pkgroots);
let mut state = xmlo.build(depgraph, state)?;
let mut dir: PathBuf = path.clone();
dir.pop();
let found = state.found.take().unwrap_or_default();
for relpath in found.iter() {
let mut path_buf = dir.clone();
path_buf.push(relpath);
@ -161,14 +148,10 @@ fn load_xmlo<'a, 'i, I: Interner<'i>>(
let path_abs = path_buf.canonicalize()?;
let path = path_abs.to_str().unwrap();
load_xmlo(path, fs, fragments, depgraph, interner, roots)?;
state = load_xmlo(path, fs, fragments, depgraph, interner, state)?;
}
if first {
Ok(Some((name, relroot)))
} else {
Ok(None)
}
Ok(state)
}
fn get_ident<'a, 'i>(

View File

@ -29,15 +29,16 @@ use std::io::BufRead;
// TODO error type
pub type Result<'i, S, Ix> =
std::result::Result<AsgBuilderResult<'i, S, Ix>, Box<dyn Error>>;
std::result::Result<AsgBuilderState<'i, S, Ix>, Box<dyn Error>>;
pub struct AsgBuilderResult<'i, S, Ix>
#[derive(Debug, Default)]
pub struct AsgBuilderState<'i, S, Ix>
where
S: BuildHasher + Default,
S: BuildHasher,
Ix: IndexType,
{
pub roots: Vec<ObjectRef<Ix>>,
pub found: HashSet<&'i str, S>,
pub found: Option<HashSet<&'i str, S>>,
pub name: Option<&'i Symbol<'i>>,
pub relroot: Option<String>,
}
@ -45,13 +46,13 @@ where
pub trait AsgBuilder<'i, O, S, Ix>
where
O: IdentObjectState<'i, O>,
S: BuildHasher + Default,
S: BuildHasher,
Ix: IndexType,
{
fn build<G: Asg<'i, O, Ix>>(
self,
graph: &mut G,
first: bool,
state: AsgBuilderState<'i, S, Ix>,
) -> Result<'i, S, Ix>;
}
@ -63,27 +64,22 @@ where
S: BuildHasher + Default,
Ix: IndexType,
{
// TOOD: remove first
fn build<G: Asg<'i, O, Ix>>(
mut self,
graph: &mut G,
first: bool,
mut state: AsgBuilderState<'i, S, Ix>,
) -> Result<'i, S, Ix> {
// TODO
let mut found: HashSet<&'i str, S> = Default::default();
let mut roots = Vec::new();
let mut elig = None;
let first = state.name.is_none();
let mut name: Option<&'i Symbol<'i>> = None;
let mut relroot: Option<String> = None;
let found = state.found.get_or_insert(Default::default());
loop {
match self.read_event() {
Ok(XmloEvent::Package(attrs)) => {
if first {
name = attrs.name;
relroot = attrs.relroot;
state.name = attrs.name;
state.relroot = attrs.relroot;
}
elig = attrs.elig;
}
@ -135,7 +131,7 @@ where
graph.declare(sym, kindval, src)?;
if link_root {
roots.push(node);
state.roots.push(node);
}
}
}
@ -168,16 +164,11 @@ where
}
if let Some(elig_sym) = elig {
roots.push(graph.lookup(elig_sym).expect(
state.roots.push(graph.lookup(elig_sym).expect(
"internal error: package elig references nonexistant symbol",
));
}
Ok(AsgBuilderResult {
roots,
found,
name,
relroot,
})
Ok(state)
}
}

View File

@ -77,4 +77,4 @@
pub mod reader;
mod asg_builder;
pub use asg_builder::{AsgBuilder, AsgBuilderResult};
pub use asg_builder::{AsgBuilder, AsgBuilderState};