bend/fun/
load_book.rs

1use super::{
2  parser::{FunParser, ParseBook},
3  Book, Name, Source, SourceKind,
4};
5use crate::{
6  diagnostics::{Diagnostics, DiagnosticsConfig, TextSpan},
7  imports::PackageLoader,
8};
9use std::path::Path;
10
11// TODO: Refactor so that we don't mix the two syntaxes here.
12
13/// Reads a file and parses to a definition book.
14pub fn load_file_to_book(
15  path: &Path,
16  package_loader: impl PackageLoader,
17  diag: DiagnosticsConfig,
18) -> Result<Book, Diagnostics> {
19  match path.try_exists() {
20    Ok(exists) => {
21      if !exists {
22        return Err(format!("The file '{}' was not found.", path.display()).into());
23      }
24      let code = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
25      load_to_book(path, &code, package_loader, diag)
26    }
27    Err(e) => Err(e.to_string().into()),
28  }
29}
30
31pub fn load_to_book(
32  origin: &Path,
33  code: &str,
34  package_loader: impl PackageLoader,
35  diag: DiagnosticsConfig,
36) -> Result<Book, Diagnostics> {
37  let builtins = ParseBook::builtins();
38  let book = do_parse_book(code, origin, builtins)?;
39  book.load_imports(package_loader, diag)
40}
41
42pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result<ParseBook, Diagnostics> {
43  book.source = Name::new(origin.to_string_lossy());
44  FunParser::new(book.source.clone(), code, false).parse_book(book).map_err(|err| {
45    let mut diagnostics = Diagnostics::default();
46    let span = TextSpan::from_byte_span(code, err.span.0..err.span.1);
47    let source =
48      Source { file: Some(origin.to_string_lossy().into()), span: Some(span), kind: SourceKind::User };
49    diagnostics.add_parsing_error(err, source);
50    diagnostics
51  })
52}