mirror of
https://github.com/tweag/nickel.git
synced 2024-09-11 11:47:03 +03:00
Guess input format based on extension similarly like in multiple input case.
This commit is contained in:
parent
07cd7197e1
commit
aca39eff18
@ -58,6 +58,14 @@ impl InputFormat {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Renturns an [InputFormat] based on the extension of a source path.
|
||||||
|
pub fn from_source_path(source_path: &SourcePath) -> Option<InputFormat> {
|
||||||
|
if let SourcePath::Path(p) = source_path {
|
||||||
|
Self::from_path(p)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// File and terms cache.
|
/// File and terms cache.
|
||||||
@ -456,50 +464,10 @@ impl Cache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a source and populate the corresponding entry in the cache, or do nothing if the
|
|
||||||
/// entry has already been parsed. This function is error tolerant: parts of the source which
|
|
||||||
/// result in parse errors are parsed as [`crate::term::Term::ParseError`] and the
|
|
||||||
/// corresponding error messages are collected and returned.
|
|
||||||
///
|
|
||||||
/// The `Err` part of the result corresponds to non-recoverable errors.
|
|
||||||
fn parse_lax(&mut self, file_id: FileId) -> Result<CacheOp<ParseErrors>, ParseError> {
|
|
||||||
if let Some(TermEntry { parse_errs, .. }) = self.terms.get(&file_id) {
|
|
||||||
Ok(CacheOp::Cached(parse_errs.clone()))
|
|
||||||
} else {
|
|
||||||
let (term, parse_errs) = self.parse_nocache(file_id)?;
|
|
||||||
self.terms.insert(
|
|
||||||
file_id,
|
|
||||||
TermEntry {
|
|
||||||
term,
|
|
||||||
state: EntryState::Parsed,
|
|
||||||
parse_errs: parse_errs.clone(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(CacheOp::Done(parse_errs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a source and populate the corresponding entry in the cache, or do
|
|
||||||
/// nothing if the entry has already been parsed. This function is error
|
|
||||||
/// tolerant if `self.error_tolerant` is `true`.
|
|
||||||
pub fn parse(&mut self, file_id: FileId) -> Result<CacheOp<ParseErrors>, ParseErrors> {
|
|
||||||
let result = self.parse_lax(file_id);
|
|
||||||
|
|
||||||
match self.error_tolerance {
|
|
||||||
ErrorTolerance::Tolerant => result.map_err(|err| err.into()),
|
|
||||||
ErrorTolerance::Strict => match result? {
|
|
||||||
CacheOp::Done(e) | CacheOp::Cached(e) if !e.no_errors() => Err(e),
|
|
||||||
CacheOp::Done(_) => Ok(CacheOp::Done(ParseErrors::none())),
|
|
||||||
CacheOp::Cached(_) => Ok(CacheOp::Cached(ParseErrors::none())),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a source and populate the corresponding entry in the cache, or do
|
/// Parse a source and populate the corresponding entry in the cache, or do
|
||||||
/// nothing if the entry has already been parsed. Support multiple formats.
|
/// nothing if the entry has already been parsed. Support multiple formats.
|
||||||
/// This function is always error tolerant, independently from `self.error_tolerant`.
|
/// This function is always error tolerant, independently from `self.error_tolerant`.
|
||||||
fn parse_multi_lax(
|
fn parse_lax(
|
||||||
&mut self,
|
&mut self,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
format: InputFormat,
|
format: InputFormat,
|
||||||
@ -523,12 +491,12 @@ impl Cache {
|
|||||||
/// Parse a source and populate the corresponding entry in the cache, or do
|
/// Parse a source and populate the corresponding entry in the cache, or do
|
||||||
/// nothing if the entry has already been parsed. Support multiple formats.
|
/// nothing if the entry has already been parsed. Support multiple formats.
|
||||||
/// This function is error tolerant if `self.error_tolerant` is `true`.
|
/// This function is error tolerant if `self.error_tolerant` is `true`.
|
||||||
pub fn parse_multi(
|
pub fn parse(
|
||||||
&mut self,
|
&mut self,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
format: InputFormat,
|
format: InputFormat,
|
||||||
) -> Result<CacheOp<ParseErrors>, ParseErrors> {
|
) -> Result<CacheOp<ParseErrors>, ParseErrors> {
|
||||||
let result = self.parse_multi_lax(file_id, format);
|
let result = self.parse_lax(file_id, format);
|
||||||
|
|
||||||
match self.error_tolerance {
|
match self.error_tolerance {
|
||||||
ErrorTolerance::Tolerant => result.map_err(|err| err.into()),
|
ErrorTolerance::Tolerant => result.map_err(|err| err.into()),
|
||||||
@ -902,7 +870,12 @@ impl Cache {
|
|||||||
) -> Result<CacheOp<()>, Error> {
|
) -> Result<CacheOp<()>, Error> {
|
||||||
let mut result = CacheOp::Cached(());
|
let mut result = CacheOp::Cached(());
|
||||||
|
|
||||||
if let CacheOp::Done(_) = self.parse(file_id)? {
|
let format = self
|
||||||
|
.file_paths
|
||||||
|
.get(&file_id)
|
||||||
|
.and_then(InputFormat::from_source_path)
|
||||||
|
.unwrap_or_default();
|
||||||
|
if let CacheOp::Done(_) = self.parse(file_id, format)? {
|
||||||
result = CacheOp::Done(());
|
result = CacheOp::Done(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1134,7 +1107,7 @@ impl Cache {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for (_, file_id) in file_ids.iter() {
|
for (_, file_id) in file_ids.iter() {
|
||||||
self.parse(*file_id)?;
|
self.parse(*file_id, InputFormat::Nickel)?;
|
||||||
}
|
}
|
||||||
self.stdlib_ids.replace(file_ids);
|
self.stdlib_ids.replace(file_ids);
|
||||||
Ok(CacheOp::Done(()))
|
Ok(CacheOp::Done(()))
|
||||||
@ -1371,7 +1344,7 @@ impl ImportResolver for Cache {
|
|||||||
self.rev_imports.entry(file_id).or_default().insert(parent);
|
self.rev_imports.entry(file_id).or_default().insert(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.parse_multi(file_id, format)
|
self.parse(file_id, format)
|
||||||
.map_err(|err| ImportError::ParseErrors(err, *pos))?;
|
.map_err(|err| ImportError::ParseErrors(err, *pos))?;
|
||||||
|
|
||||||
Ok((result, file_id))
|
Ok((result, file_id))
|
||||||
|
@ -371,7 +371,7 @@ impl<EC: EvalCache> Program<EC> {
|
|||||||
pub fn parse(&mut self) -> Result<RichTerm, Error> {
|
pub fn parse(&mut self) -> Result<RichTerm, Error> {
|
||||||
self.vm
|
self.vm
|
||||||
.import_resolver_mut()
|
.import_resolver_mut()
|
||||||
.parse(self.main_id)
|
.parse(self.main_id, InputFormat::Nickel)
|
||||||
.map_err(Error::ParseErrors)?;
|
.map_err(Error::ParseErrors)?;
|
||||||
Ok(self
|
Ok(self
|
||||||
.vm
|
.vm
|
||||||
@ -496,7 +496,9 @@ impl<EC: EvalCache> Program<EC> {
|
|||||||
|
|
||||||
/// Load, parse, and typecheck the program and the standard library, if not already done.
|
/// Load, parse, and typecheck the program and the standard library, if not already done.
|
||||||
pub fn typecheck(&mut self) -> Result<(), Error> {
|
pub fn typecheck(&mut self) -> Result<(), Error> {
|
||||||
self.vm.import_resolver_mut().parse(self.main_id)?;
|
self.vm
|
||||||
|
.import_resolver_mut()
|
||||||
|
.parse(self.main_id, InputFormat::Nickel)?;
|
||||||
self.vm.import_resolver_mut().load_stdlib()?;
|
self.vm.import_resolver_mut().load_stdlib()?;
|
||||||
let initial_env = self.vm.import_resolver().mk_type_ctxt().expect(
|
let initial_env = self.vm.import_resolver().mk_type_ctxt().expect(
|
||||||
"program::typecheck(): \
|
"program::typecheck(): \
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
//! Dually, the frontend is the user-facing part, which may be a CLI, a web application, a
|
//! Dually, the frontend is the user-facing part, which may be a CLI, a web application, a
|
||||||
//! jupyter-kernel (which is not exactly user-facing, but still manages input/output and
|
//! jupyter-kernel (which is not exactly user-facing, but still manages input/output and
|
||||||
//! formatting), etc.
|
//! formatting), etc.
|
||||||
use crate::cache::{Cache, Envs, ErrorTolerance, SourcePath};
|
use crate::cache::{Cache, Envs, ErrorTolerance, InputFormat, SourcePath};
|
||||||
use crate::error::{
|
use crate::error::{
|
||||||
report::{self, ColorOpt, ErrorFormat},
|
report::{self, ColorOpt, ErrorFormat},
|
||||||
Error, EvalError, IOError, IntoDiagnostics, ParseError, ParseErrors, ReplError,
|
Error, EvalError, IOError, IntoDiagnostics, ParseError, ParseErrors, ReplError,
|
||||||
@ -232,7 +232,9 @@ impl<EC: EvalCache> Repl for ReplImpl<EC> {
|
|||||||
.import_resolver_mut()
|
.import_resolver_mut()
|
||||||
.add_file(OsString::from(path.as_ref()))
|
.add_file(OsString::from(path.as_ref()))
|
||||||
.map_err(IOError::from)?;
|
.map_err(IOError::from)?;
|
||||||
self.vm.import_resolver_mut().parse(file_id)?;
|
self.vm
|
||||||
|
.import_resolver_mut()
|
||||||
|
.parse(file_id, InputFormat::Nickel)?;
|
||||||
|
|
||||||
let term = self.vm.import_resolver().get_owned(file_id).unwrap();
|
let term = self.vm.import_resolver().get_owned(file_id).unwrap();
|
||||||
let pos = term.pos;
|
let pos = term.pos;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use nickel_lang_core::{
|
use nickel_lang_core::{
|
||||||
cache::SourcePath,
|
cache::{InputFormat, SourcePath},
|
||||||
parser::lexer::{self, NormalToken, SpannedToken, Token},
|
parser::lexer::{self, NormalToken, SpannedToken, Token},
|
||||||
position::RawSpan,
|
position::RawSpan,
|
||||||
term::{RichTerm, Term},
|
term::{RichTerm, Term},
|
||||||
@ -102,7 +102,7 @@ fn resolve_imports(rt: RichTerm, world: &mut World) -> RichTerm {
|
|||||||
} = import_resolution::tolerant::resolve_imports(rt, &mut world.cache);
|
} = import_resolution::tolerant::resolve_imports(rt, &mut world.cache);
|
||||||
|
|
||||||
for id in resolved_ids {
|
for id in resolved_ids {
|
||||||
if world.cache.parse(id).is_ok() {
|
if world.cache.parse(id, InputFormat::Nickel).is_ok() {
|
||||||
// If a new input got imported in an incomplete term, try to typecheck
|
// If a new input got imported in an incomplete term, try to typecheck
|
||||||
// (and build lookup tables etc.) for it, but don't issue diagnostics.
|
// (and build lookup tables etc.) for it, but don't issue diagnostics.
|
||||||
let _ = world.typecheck(id);
|
let _ = world.typecheck(id);
|
||||||
|
@ -8,7 +8,7 @@ use codespan::FileId;
|
|||||||
use lsp_server::{ErrorCode, ResponseError};
|
use lsp_server::{ErrorCode, ResponseError};
|
||||||
use lsp_types::Url;
|
use lsp_types::Url;
|
||||||
use nickel_lang_core::{
|
use nickel_lang_core::{
|
||||||
cache::{Cache, CacheError, ErrorTolerance, SourcePath},
|
cache::{Cache, CacheError, ErrorTolerance, InputFormat, SourcePath},
|
||||||
error::{ImportError, IntoDiagnostics},
|
error::{ImportError, IntoDiagnostics},
|
||||||
position::{RawPos, RawSpan},
|
position::{RawPos, RawSpan},
|
||||||
term::{record::FieldMetadata, RichTerm, Term, UnaryOp},
|
term::{record::FieldMetadata, RichTerm, Term, UnaryOp},
|
||||||
@ -160,7 +160,7 @@ impl World {
|
|||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
) -> Result<Vec<SerializableDiagnostic>, Vec<SerializableDiagnostic>> {
|
) -> Result<Vec<SerializableDiagnostic>, Vec<SerializableDiagnostic>> {
|
||||||
self.cache
|
self.cache
|
||||||
.parse(file_id)
|
.parse(file_id, InputFormat::Nickel)
|
||||||
.map(|nonfatal| self.lsp_diagnostics(file_id, nonfatal.inner()))
|
.map(|nonfatal| self.lsp_diagnostics(file_id, nonfatal.inner()))
|
||||||
.map_err(|fatal| self.lsp_diagnostics(file_id, fatal))
|
.map_err(|fatal| self.lsp_diagnostics(file_id, fatal))
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ macro_rules! ncl_bench_group {
|
|||||||
(name = $group_name:ident; config = $config:expr; $($b:tt),+ $(,)*) => {
|
(name = $group_name:ident; config = $config:expr; $($b:tt),+ $(,)*) => {
|
||||||
pub fn $group_name() {
|
pub fn $group_name() {
|
||||||
use nickel_lang_core::{
|
use nickel_lang_core::{
|
||||||
cache::{Envs, Cache, ErrorTolerance, ImportResolver},
|
cache::{Envs, Cache, ErrorTolerance, ImportResolver, InputFormat},
|
||||||
eval::{VirtualMachine, cache::{CacheImpl, Cache as EvalCache}},
|
eval::{VirtualMachine, cache::{CacheImpl, Cache as EvalCache}},
|
||||||
transform::import_resolution::strict::resolve_imports,
|
transform::import_resolution::strict::resolve_imports,
|
||||||
error::report::{report, ColorOpt, ErrorFormat},
|
error::report::{report, ColorOpt, ErrorFormat},
|
||||||
@ -194,7 +194,7 @@ macro_rules! ncl_bench_group {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.transformed_term;
|
.transformed_term;
|
||||||
if bench.eval_mode == $crate::bench::EvalMode::TypeCheck {
|
if bench.eval_mode == $crate::bench::EvalMode::TypeCheck {
|
||||||
cache.parse(id).unwrap();
|
cache.parse(id, InputFormat::Nickel).unwrap();
|
||||||
cache.resolve_imports(id).unwrap();
|
cache.resolve_imports(id).unwrap();
|
||||||
}
|
}
|
||||||
(cache, id, t)
|
(cache, id, t)
|
||||||
|
Loading…
Reference in New Issue
Block a user