blob: 49d30dc6c68e66860b1e0da2cb399eb1cb710f82 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::bind_library;
use crate::bind_program;
use crate::dependency_graph::{self, DependencyGraph};
use crate::parser_common::{self, CompoundIdentifier, Include};
use std::path::PathBuf;
#[derive(Debug, PartialEq)]
pub enum CompilerError {
FileOpenError(PathBuf),
FileReadError(PathBuf),
FileWriteError(PathBuf),
BindParserError(parser_common::BindParserError),
DependencyError(dependency_graph::DependencyError<CompoundIdentifier>),
UnknownKey(CompoundIdentifier),
}
#[allow(dead_code)]
fn resolve_dependencies<'a>(
program: &bind_program::Ast,
libraries: impl Iterator<Item = &'a bind_library::Ast> + Clone,
) -> Result<Vec<&'a bind_library::Ast>, CompilerError> {
(|| {
let mut graph = DependencyGraph::new();
for library in libraries.clone() {
graph.insert_node(library.name.clone(), library);
}
for Include { name, .. } in &program.using {
graph.insert_edge_from_root(name)?;
}
for from in libraries {
for to in &from.using {
graph.insert_edge(&from.name, &to.name)?;
}
}
graph.resolve()
})()
.map_err(CompilerError::DependencyError)
}
#[cfg(test)]
mod test {
use super::*;
use crate::make_identifier;
#[test]
fn dependencies() {
let program = bind_program::Ast {
using: vec![Include { name: make_identifier!("A"), alias: None }],
statements: vec![],
};
let libraries = vec![
bind_library::Ast {
name: make_identifier!("A"),
using: vec![Include { name: make_identifier!("A", "B"), alias: None }],
declarations: vec![],
},
bind_library::Ast {
name: make_identifier!("A", "B"),
using: vec![],
declarations: vec![],
},
bind_library::Ast {
name: make_identifier!("A", "C"),
using: vec![],
declarations: vec![],
},
];
assert_eq!(
resolve_dependencies(&program, libraries.iter()),
Ok(vec![
&bind_library::Ast {
name: make_identifier!("A"),
using: vec![Include { name: make_identifier!("A", "B"), alias: None }],
declarations: vec![],
},
&bind_library::Ast {
name: make_identifier!("A", "B"),
using: vec![],
declarations: vec![],
},
])
);
}
#[test]
fn dependencies_error() {
let program = bind_program::Ast {
using: vec![Include { name: make_identifier!("A"), alias: None }],
statements: vec![],
};
let libraries = vec![
bind_library::Ast {
name: make_identifier!("A"),
using: vec![Include { name: make_identifier!("A", "B"), alias: None }],
declarations: vec![],
},
bind_library::Ast {
name: make_identifier!("A", "C"),
using: vec![],
declarations: vec![],
},
];
assert_eq!(
resolve_dependencies(&program, libraries.iter()),
Err(CompilerError::DependencyError(
dependency_graph::DependencyError::MissingDependency(make_identifier!("A", "B"))
))
);
}
}