From 52f9ecfc4dac65d305fd920e8c7f748889a0804f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 12 Aug 2019 23:24:48 +0200 Subject: Move api into its own crate --- dhall/src/error/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'dhall/src/error') diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs index 3c00017..ecf3510 100644 --- a/dhall/src/error/mod.rs +++ b/dhall/src/error/mod.rs @@ -192,3 +192,13 @@ impl From for Error { Error::Typecheck(err) } } + +impl serde::de::Error for Error { + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Deserialize(msg.to_string()) + } +} + -- cgit v1.3.1 From 74bb40e88c71b80ab785f07fd19da22404ab6e95 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 13 Aug 2019 15:11:31 +0200 Subject: Add new error type for serde_dhall --- dhall/Cargo.toml | 2 +- dhall/src/error/mod.rs | 12 ---------- serde_dhall/src/lib.rs | 58 +++++++++++++++++++++++++++++++++++++++++------- serde_dhall/src/serde.rs | 12 +--------- 4 files changed, 52 insertions(+), 32 deletions(-) (limited to 'dhall/src/error') diff --git a/dhall/Cargo.toml b/dhall/Cargo.toml index aa52d58..0a257e4 100644 --- a/dhall/Cargo.toml +++ b/dhall/Cargo.toml @@ -10,7 +10,7 @@ build = "build.rs" bytecount = "0.5.1" itertools = "0.8.0" term-painter = "0.2.3" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0" } serde_cbor = "0.9.0" improved_slice_patterns = { version = "2.0.0", path = "../improved_slice_patterns" } dhall_syntax = { path = "../dhall_syntax" } diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs index ecf3510..3626d96 100644 --- a/dhall/src/error/mod.rs +++ b/dhall/src/error/mod.rs @@ -17,7 +17,6 @@ pub enum Error { Encode(EncodeError), Resolve(ImportError), Typecheck(TypeError), - Deserialize(String), } #[derive(Debug)] @@ -156,7 +155,6 @@ impl std::fmt::Display for Error { Error::Encode(err) => write!(f, "{:?}", err), Error::Resolve(err) => write!(f, "{:?}", err), Error::Typecheck(err) => write!(f, "{:?}", err), - Error::Deserialize(err) => write!(f, "{}", err), } } } @@ -192,13 +190,3 @@ impl From for Error { Error::Typecheck(err) } } - -impl serde::de::Error for Error { - fn custom(msg: T) -> Self - where - T: std::fmt::Display, - { - Error::Deserialize(msg.to_string()) - } -} - diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs index 1dbbf99..f8f9ae9 100644 --- a/serde_dhall/src/lib.rs +++ b/serde_dhall/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(non_exhaustive)] + //! [Dhall][dhall] is a programmable configuration language that provides a non-repetitive //! alternative to JSON and YAML. //! @@ -109,8 +111,8 @@ pub(crate) mod static_type; pub use value::Value; mod value { + use super::de::{Error, Result}; use super::Type; - use dhall::error::Result; use dhall::phase::{NormalizedSubExpr, Parsed, Typed}; // A Dhall value @@ -118,6 +120,12 @@ mod value { impl Value { pub fn from_str(s: &str, ty: Option<&Type>) -> Result { + Value::from_str_using_dhall_error_type(s, ty).map_err(Error::Dhall) + } + fn from_str_using_dhall_error_type( + s: &str, + ty: Option<&Type>, + ) -> dhall::error::Result { let resolved = Parsed::parse_str(s)?.resolve()?; let typed = match ty { None => resolved.typecheck()?, @@ -137,12 +145,12 @@ mod value { pub use typ::Type; mod typ { - use dhall_syntax::Builtin; - use dhall::core::thunk::{Thunk, TypeThunk}; use dhall::core::value::Value; - use dhall::error::Result; use dhall::phase::{NormalizedSubExpr, Typed}; + use dhall_syntax::Builtin; + + use super::de::Result; /// A Dhall expression representing a type. /// @@ -205,21 +213,55 @@ mod typ { } } - impl crate::de::Deserialize for Type { + impl super::de::Deserialize for Type { fn from_dhall(v: &super::Value) -> Result { Ok(Type(v.to_typed())) } } } +mod error { + use dhall::error::Error as DhallError; + + pub type Result = std::result::Result; + + #[derive(Debug)] + #[non_exhaustive] + pub enum Error { + Dhall(DhallError), + Deserialize(String), + } + + impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Error::Dhall(err) => write!(f, "{}", err), + Error::Deserialize(err) => write!(f, "{}", err), + } + } + } + + impl std::error::Error for Error {} + + impl serde::de::Error for Error { + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Deserialize(msg.to_string()) + } + } +} + /// Deserialization of Dhall expressions into Rust pub mod de { - pub use super::static_type::StaticType; - pub use super::{Type, Value}; - use dhall::error::Result; #[doc(hidden)] pub use dhall_proc_macros::StaticType; + pub use super::error::{Error, Result}; + pub use super::static_type::StaticType; + pub use super::{Type, Value}; + /// A data structure that can be deserialized from a Dhall expression /// /// This is automatically implemented for any type that [serde][serde] diff --git a/serde_dhall/src/serde.rs b/serde_dhall/src/serde.rs index 3dad2d8..1f639e6 100644 --- a/serde_dhall/src/serde.rs +++ b/serde_dhall/src/serde.rs @@ -1,5 +1,4 @@ -use crate::de::{Deserialize, Value}; -use dhall::error::{Error, Result}; +use crate::de::{Deserialize, Error, Result, Value}; use dhall_syntax::{ExprF, SubExpr, X}; use std::borrow::Cow; @@ -14,15 +13,6 @@ where struct Deserializer<'a>(Cow<'a, SubExpr>); -// impl serde::de::Error for Error { -// fn custom(msg: T) -> Self -// where -// T: std::fmt::Display, -// { -// Error::Deserialize(msg.to_string()) -// } -// } - impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> { type Deserializer = Deserializer<'a>; fn into_deserializer(self) -> Self::Deserializer { -- cgit v1.3.1 From 66260f8e386f7a447352bd8ccbda064b00b698bc Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 13 Aug 2019 23:44:52 +0200 Subject: Implement inline headers parsing --- dhall/build.rs | 16 +---------- dhall/src/error/mod.rs | 8 +++--- dhall/src/phase/binary.rs | 50 ++++++++++++-------------------- dhall/src/phase/resolve.rs | 8 +++--- dhall_generated_parser/build.rs | 30 +++++++------------ dhall_syntax/src/core/expr.rs | 17 +++++++---- dhall_syntax/src/core/import.rs | 62 ++++++++++++++++++++++++++++++++-------- dhall_syntax/src/core/visitor.rs | 4 +-- dhall_syntax/src/parser.rs | 28 +++++++++--------- dhall_syntax/src/printer.rs | 13 ++------- 10 files changed, 119 insertions(+), 117 deletions(-) (limited to 'dhall/src/error') diff --git a/dhall/build.rs b/dhall/build.rs index 790ad8e..cbda288 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -93,13 +93,6 @@ fn main() -> std::io::Result<()> { make_test_module(&mut file, "parse", "parser/", "Parser", |path| { // Too slow in debug mode path == "success/largeExpression" - // TODO: Inline headers - || path == "success/unit/import/inlineUsing" - || path == "success/unit/import/Headers" - || path == "success/unit/import/HeadersDoubleHash" - || path == "success/unit/import/HeadersDoubleHashPrecedence" - || path == "success/unit/import/HeadersHashPrecedence" - || path == "success/unit/import/HeadersInteriorHash" // TODO: projection by expression || path == "success/recordProjectionByExpression" || path == "success/RecordProjectionByType" @@ -119,9 +112,6 @@ fn main() -> std::io::Result<()> { path.starts_with("failure/") // Too slow in debug mode || path == "success/largeExpression" - // TODO: Inline headers - || path == "success/unit/import/inlineUsing" - || path == "success/unit/import/Headers" // TODO: projection by expression || path == "success/recordProjectionByExpression" || path == "success/RecordProjectionByType" @@ -149,9 +139,6 @@ fn main() -> std::io::Result<()> { || path == "success/double" || path == "success/unit/DoubleLitExponentNoDot" || path == "success/unit/DoubleLitSecretelyInt" - // TODO: Inline headers - || path == "success/unit/import/inlineUsing" - || path == "success/unit/import/Headers" // TODO: projection by expression || path == "success/recordProjectionByExpression" || path == "success/RecordProjectionByType" @@ -237,10 +224,9 @@ fn main() -> std::io::Result<()> { false // TODO: Enable imports in typecheck tests || path == "failure/importBoundary" + || path == "failure/customHeadersUsingBoundVariable" // Too slow || path == "success/prelude" - // TODO: Inline headers - || path == "failure/customHeadersUsingBoundVariable" // TODO: projection by expression || path == "failure/unit/RecordProjectionByTypeFieldTypeMismatch" || path == "failure/unit/RecordProjectionByTypeNotPresent" diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs index 3626d96..8f6ff51 100644 --- a/dhall/src/error/mod.rs +++ b/dhall/src/error/mod.rs @@ -4,7 +4,7 @@ use dhall_syntax::{BinOp, Import, Label, ParseError, V}; use crate::core::context::TypecheckContext; use crate::phase::resolve::ImportStack; -use crate::phase::{Normalized, Type, Typed}; +use crate::phase::{Normalized, NormalizedSubExpr, Type, Typed}; pub type Result = std::result::Result; @@ -21,9 +21,9 @@ pub enum Error { #[derive(Debug)] pub enum ImportError { - Recursive(Import, Box), - UnexpectedImport(Import), - ImportCycle(ImportStack, Import), + Recursive(Import, Box), + UnexpectedImport(Import), + ImportCycle(ImportStack, Import), } #[derive(Debug)] diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs index 9ed823c..36dd471 100644 --- a/dhall/src/phase/binary.rs +++ b/dhall/src/phase/binary.rs @@ -4,9 +4,8 @@ use std::iter::FromIterator; use dhall_syntax::map::DupTreeMap; use dhall_syntax::{ - rc, ExprF, FilePrefix, Hash, Import, ImportHashed, ImportLocation, - ImportMode, Integer, InterpolatedText, Label, Natural, Scheme, SubExpr, - URL, V, + rc, ExprF, FilePrefix, Hash, Import, ImportLocation, ImportMode, Integer, + InterpolatedText, Label, Natural, Scheme, SubExpr, URL, V, }; use crate::error::{DecodeError, EncodeError}; @@ -260,20 +259,12 @@ fn cbor_value_to_dhall( }; let headers = match rest.next() { Some(Null) => None, - // TODO - // Some(x) => { - // match cbor_value_to_dhall(&x)?.as_ref() { - // Import(import) => Some(Box::new( - // import.location_hashed.clone(), - // )), - // _ => Err(DecodeError::WrongFormatError( - // "import/remote/headers".to_owned(), - // ))?, - // } - // } + Some(x) => { + let x = cbor_value_to_dhall(&x)?; + Some(x) + } _ => Err(DecodeError::WrongFormatError( - "import/remote/headers is unimplemented" - .to_owned(), + "import/remote/headers".to_owned(), ))?, }; let authority = match rest.next() { @@ -341,7 +332,8 @@ fn cbor_value_to_dhall( }; Import(dhall_syntax::Import { mode, - location_hashed: ImportHashed { hash, location }, + hash, + location, }) } [U64(25), bindings..] => { @@ -572,14 +564,17 @@ where } } -fn serialize_import(ser: S, import: &Import) -> Result +fn serialize_import( + ser: S, + import: &Import>, +) -> Result where S: serde::ser::Serializer, { use cbor::Value::{Bytes, Null, U64}; use serde::ser::SerializeSeq; - let count = 4 + match &import.location_hashed.location { + let count = 4 + match &import.location { ImportLocation::Remote(url) => 3 + url.path.len(), ImportLocation::Local(_, path) => path.len(), ImportLocation::Env(_) => 1, @@ -589,7 +584,7 @@ where ser_seq.serialize_element(&U64(24))?; - let hash = match &import.location_hashed.hash { + let hash = match &import.hash { None => Null, Some(Hash::SHA256(h)) => { let mut bytes = vec![18, 32]; @@ -606,7 +601,7 @@ where }; ser_seq.serialize_element(&U64(mode))?; - let scheme = match &import.location_hashed.location { + let scheme = match &import.location { ImportLocation::Remote(url) => match url.scheme { Scheme::HTTP => 0, Scheme::HTTPS => 1, @@ -622,19 +617,12 @@ where }; ser_seq.serialize_element(&U64(scheme))?; - match &import.location_hashed.location { + match &import.location { ImportLocation::Remote(url) => { match &url.headers { None => ser_seq.serialize_element(&Null)?, - Some(location_hashed) => { - let e = rc( - ExprF::Import(dhall_syntax::Import { - mode: ImportMode::Code, - location_hashed: location_hashed.as_ref().clone(), - }), - ); - let s: Serialize<'_, ()> = self::Serialize::Expr(&e); - ser_seq.serialize_element(&s)? + Some(e) => { + ser_seq.serialize_element(&self::Serialize::Expr(e))? } }; ser_seq.serialize_element(&url.authority)?; diff --git a/dhall/src/phase/resolve.rs b/dhall/src/phase/resolve.rs index abcee7e..52353e4 100644 --- a/dhall/src/phase/resolve.rs +++ b/dhall/src/phase/resolve.rs @@ -1,10 +1,10 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use dhall_syntax::Import; - use crate::error::{Error, ImportError}; -use crate::phase::{Normalized, Parsed, Resolved}; +use crate::phase::{Normalized, NormalizedSubExpr, Parsed, Resolved}; + +type Import = dhall_syntax::Import; /// A root from which to resolve relative imports. #[derive(Debug, Clone, PartialEq, Eq)] @@ -28,7 +28,7 @@ fn resolve_import( let cwd = match root { LocalDir(cwd) => cwd, }; - match &import.location_hashed.location { + match &import.location { Local(prefix, path) => { let path: PathBuf = path.iter().cloned().collect(); let path = match prefix { diff --git a/dhall_generated_parser/build.rs b/dhall_generated_parser/build.rs index 5275097..070aa9c 100644 --- a/dhall_generated_parser/build.rs +++ b/dhall_generated_parser/build.rs @@ -26,16 +26,15 @@ fn main() -> std::io::Result<()> { rules.get_mut(&line[2..]).map(|x| x.silent = true); } } - rules.remove("http"); - rules.remove("url_path"); - rules.remove("simple_label"); - rules.remove("nonreserved_label"); let mut file = File::create(pest_path)?; writeln!(&mut file, "// AUTO-GENERATED FILE. See build.rs.")?; - writeln!(&mut file, "{}", render_rules_to_pest(rules).pretty(80))?; - writeln!(&mut file)?; + // TODO: this is a cheat; properly support RFC3986 URLs instead + rules.remove("url_path"); + writeln!(&mut file, "url_path = _{{ path }}")?; + + rules.remove("simple_label"); writeln!( &mut file, "simple_label = {{ @@ -43,30 +42,23 @@ fn main() -> std::io::Result<()> { | !keyword ~ simple_label_first_char ~ simple_label_next_char* }}" )?; - // TODO: this is a cheat; actually implement inline headers instead - writeln!( - &mut file, - "http = {{ - http_raw - ~ (whsp - ~ using - ~ whsp1 - ~ (import_hashed | ^\"(\" ~ whsp ~ import_hashed ~ whsp ~ ^\")\"))? - }}" - )?; - // TODO: this is a cheat; properly support RFC3986 URLs instead - writeln!(&mut file, "url_path = _{{ path }}")?; + + rules.remove("nonreserved_label"); writeln!( &mut file, "nonreserved_label = _{{ !(builtin ~ !simple_label_next_char) ~ label }}" )?; + writeln!( &mut file, "final_expression = ${{ SOI ~ complete_expression ~ EOI }}" )?; + writeln!(&mut file)?; + writeln!(&mut file, "{}", render_rules_to_pest(rules).pretty(80))?; + // Generate pest parser manually to avoid spurious recompilations let derived = { let pest_path = "dhall.pest"; diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs index 9729efb..30ac4eb 100644 --- a/dhall_syntax/src/core/expr.rs +++ b/dhall_syntax/src/core/expr.rs @@ -258,7 +258,7 @@ pub enum ExprF { /// `e.{ x, y, z }` Projection(SubExpr, DupTreeSet