Return compilation errors
use petgraph::Graph;
use std::collections::HashMap;
+pub type Name = String;
+pub type Src = String;
+
#[derive(Debug, PartialEq)]
pub struct Compiled {
pub name: String,
pub out: String,
}
-pub fn compile(srcs: Vec<(String, String)>) -> Result<Vec<Compiled>, ()> {
+#[derive(Debug, PartialEq)]
+pub enum Error {
+ Parse {
+ name: Name,
+ src: Src,
+ error: lalrpop_util::ParseError<usize, (usize, String), String>,
+ },
+
+ Type {
+ name: Name,
+ src: Src,
+ error: crate::typ::Error,
+ },
+
+ DependencyCycle,
+}
+
+pub fn compile(srcs: Vec<(Name, Src)>) -> Result<Vec<Compiled>, Error> {
let mut deps_graph = Graph::new();
let mut deps_vec = Vec::with_capacity(srcs.len());
let mut indexes = HashMap::new();
@@ -16,14 +36,20 @@ pub fn compile(srcs: Vec<(String, String)>) -> Result<Vec<Compiled>, ()> {
for (name, src) in srcs {
let mut module = crate::grammar::ModuleParser::new()
.parse(&crate::parser::strip_extra(&src))
- .expect(&format!("Unable to parse {:?}", name));
+ .map_err(|e| Error::Parse {
+ name: name.clone(),
+ src: src.clone(),
+ error: e
+ .map_error(|s| s.to_string())
+ .map_token(|crate::grammar::Token(a, b)| (a, b.to_string())),
+ })?;
module.name = name.clone();
let index = deps_graph.add_node(name.clone());
deps_vec.push((name.clone(), module.dependancies()));
indexes.insert(name.clone(), index.clone());
- modules.insert(index, module);
+ modules.insert(index, (src, module));
}
// Register each module's deps so that we can determine a correct order to compile the modules.
@@ -37,32 +63,36 @@ pub fn compile(srcs: Vec<(String, String)>) -> Result<Vec<Compiled>, ()> {
let mut module_types = HashMap::new();
- Ok(petgraph::algo::toposort(&deps_graph, None)
- .expect("Could not determine module compile order")
+ petgraph::algo::toposort(&deps_graph, None)
+ .map_err(|_| Error::DependencyCycle)?
.into_iter()
.map(|i| {
- let module = modules.remove(&i).expect("Unknown graph index");
+ let (src, module) = modules.remove(&i).expect("Unknown graph index");
let name = module.name.clone();
println!("Compiling {}", name);
- let module = crate::typ::infer_module(module, &module_types)
- .expect(&format!("Unable to infer types of {:?}", name));
+ let module =
+ crate::typ::infer_module(module, &module_types).map_err(|error| Error::Type {
+ name: name.clone(),
+ src,
+ error,
+ })?;
module_types.insert(name.clone(), module.typ.clone());
let out = crate::erl::module(module);
- Compiled { name, out }
+ Ok(Compiled { name, out })
})
- .collect())
+ .collect()
}
#[test]
fn compile_test() {
struct Case {
- input: Vec<(String, String)>,
- expected: Result<Vec<Compiled>, ()>,
+ input: Vec<(Name, Src)>,
+ expected: Result<Vec<Compiled>, Error>,
}
let cases = vec![
