summaryrefslogtreecommitdiff
path: root/dhall_syntax
diff options
context:
space:
mode:
authorNadrieril2019-08-13 23:44:52 +0200
committerNadrieril2019-08-13 23:45:27 +0200
commit66260f8e386f7a447352bd8ccbda064b00b698bc (patch)
treeb3094a3d4e6b463724302b9be7e803a80ce4eed3 /dhall_syntax
parentc600bae72198350b78fe19cf993b7f4c6f35225a (diff)
Implement inline headers parsing
Diffstat (limited to '')
-rw-r--r--dhall_syntax/src/core/expr.rs17
-rw-r--r--dhall_syntax/src/core/import.rs62
-rw-r--r--dhall_syntax/src/core/visitor.rs4
-rw-r--r--dhall_syntax/src/parser.rs28
-rw-r--r--dhall_syntax/src/printer.rs13
5 files changed, 80 insertions, 44 deletions
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<SubExpr, Embed> {
/// `e.{ x, y, z }`
Projection(SubExpr, DupTreeSet<Label>),
/// `./some/path`
- Import(Import),
+ Import(Import<SubExpr>),
/// Embeds the result of resolving an import
Embed(Embed),
}
@@ -323,7 +323,7 @@ impl<SE, E> ExprF<SE, E> {
impl<E> Expr<E> {
pub fn traverse_resolve<E2, Err>(
&self,
- visit_import: impl FnMut(&Import) -> Result<E2, Err>,
+ visit_import: impl FnMut(&Import<SubExpr<E2>>) -> Result<E2, Err>,
) -> Result<Expr<E2>, Err> {
self.traverse_resolve_with_visitor(&mut visitor::ResolveVisitor(
visit_import,
@@ -335,15 +335,20 @@ impl<E> Expr<E> {
visitor: &mut visitor::ResolveVisitor<F1>,
) -> Result<Expr<E2>, Err>
where
- F1: FnMut(&Import) -> Result<E2, Err>,
+ F1: FnMut(&Import<SubExpr<E2>>) -> Result<E2, Err>,
{
match self {
ExprF::BinOp(BinOp::ImportAlt, l, r) => l
.as_ref()
.traverse_resolve_with_visitor(visitor)
.or(r.as_ref().traverse_resolve_with_visitor(visitor)),
- ExprF::Import(import) => Ok(ExprF::Embed((visitor.0)(import)?)),
- _ => self.visit(visitor),
+ _ => {
+ let e = self.visit(&mut *visitor)?;
+ Ok(match &e {
+ ExprF::Import(import) => ExprF::Embed((visitor.0)(import)?),
+ _ => e,
+ })
+ }
}
}
}
@@ -373,7 +378,7 @@ impl<E> SubExpr<E> {
impl<E> SubExpr<E> {
pub fn traverse_resolve<E2, Err>(
&self,
- visit_import: impl FnMut(&Import) -> Result<E2, Err>,
+ visit_import: impl FnMut(&Import<SubExpr<E2>>) -> Result<E2, Err>,
) -> Result<SubExpr<E2>, Err> {
Ok(self.rewrap(self.as_ref().traverse_resolve(visit_import)?))
}
diff --git a/dhall_syntax/src/core/import.rs b/dhall_syntax/src/core/import.rs
index d41eae2..9329d48 100644
--- a/dhall_syntax/src/core/import.rs
+++ b/dhall_syntax/src/core/import.rs
@@ -13,21 +13,20 @@ pub enum FilePrefix {
/// The location of import (i.e. local vs. remote vs. environment)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ImportLocation {
+pub enum ImportLocation<SubExpr> {
Local(FilePrefix, Vec<String>),
- Remote(URL),
+ Remote(URL<SubExpr>),
Env(String),
Missing,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct URL {
+pub struct URL<SubExpr> {
pub scheme: Scheme,
pub authority: String,
pub path: Vec<String>,
pub query: Option<String>,
- // TODO: implement inline headers
- pub headers: Option<Box<ImportHashed>>,
+ pub headers: Option<SubExpr>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -49,15 +48,54 @@ pub enum Hash {
SHA256(Vec<u8>),
}
+/// Reference to an external resource
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ImportHashed {
- pub location: ImportLocation,
+pub struct Import<SubExpr> {
+ pub mode: ImportMode,
+ pub location: ImportLocation<SubExpr>,
pub hash: Option<Hash>,
}
-/// Reference to an external resource
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Import {
- pub mode: ImportMode,
- pub location_hashed: ImportHashed,
+impl<SE> URL<SE> {
+ pub fn visit_subexpr<'a, Err, SE2>(
+ &'a self,
+ f: impl FnOnce(&'a SE) -> Result<SE2, Err>,
+ ) -> Result<URL<SE2>, Err> {
+ let headers = self.headers.as_ref().map(f).transpose()?;
+ Ok(URL {
+ scheme: self.scheme,
+ authority: self.authority.clone(),
+ path: self.path.clone(),
+ query: self.query.clone(),
+ headers,
+ })
+ }
+}
+
+impl<SE> ImportLocation<SE> {
+ pub fn visit_subexpr<'a, Err, SE2>(
+ &'a self,
+ f: impl FnOnce(&'a SE) -> Result<SE2, Err>,
+ ) -> Result<ImportLocation<SE2>, Err> {
+ use ImportLocation::*;
+ Ok(match self {
+ Local(prefix, path) => Local(prefix.clone(), path.clone()),
+ Remote(url) => Remote(url.visit_subexpr(f)?),
+ Env(env) => Env(env.clone()),
+ Missing => Missing,
+ })
+ }
+}
+
+impl<SE> Import<SE> {
+ pub fn visit_subexpr<'a, Err, SE2>(
+ &'a self,
+ f: impl FnOnce(&'a SE) -> Result<SE2, Err>,
+ ) -> Result<Import<SE2>, Err> {
+ Ok(Import {
+ mode: self.mode,
+ location: self.location.visit_subexpr(f)?,
+ hash: self.hash.clone(),
+ })
+ }
}
diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs
index f3d9194..7b4ed4b 100644
--- a/dhall_syntax/src/core/visitor.rs
+++ b/dhall_syntax/src/core/visitor.rs
@@ -153,7 +153,7 @@ where
Field(e, l) => Field(v.visit_subexpr(e)?, l.clone()),
Projection(e, ls) => Projection(v.visit_subexpr(e)?, ls.clone()),
Assert(e) => Assert(v.visit_subexpr(e)?),
- Import(a) => Import(a.clone()),
+ Import(i) => Import(i.visit_subexpr(|e| v.visit_subexpr(e))?),
Embed(a) => Embed(v.visit_embed(a)?),
})
}
@@ -251,7 +251,7 @@ impl<'a, 'b, E, E2, Err, F1>
ExprFFallibleVisitor<'a, SubExpr<E>, SubExpr<E2>, E, E2>
for &'b mut ResolveVisitor<F1>
where
- F1: FnMut(&Import) -> Result<E2, Err>,
+ F1: FnMut(&Import<SubExpr<E2>>) -> Result<E2, Err>,
{
type Error = Err;
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index a8dd359..8ecd0ab 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -598,7 +598,7 @@ make_parser! {
_ => unreachable!(),
});
- rule!(http_raw<URL>; children!(
+ rule!(http_raw<URL<ParsedSubExpr>>; children!(
[scheme(sch), authority(auth), path(p)] => URL {
scheme: sch,
authority: auth,
@@ -619,10 +619,10 @@ make_parser! {
rule!(query<String>; captured_str!(s) => s.to_owned());
- rule!(http<URL>; children!(
+ rule!(http<URL<ParsedSubExpr>>; children!(
[http_raw(url)] => url,
- [http_raw(url), import_hashed(ih)] =>
- URL { headers: Some(Box::new(ih)), ..url },
+ [http_raw(url), expression(e)] =>
+ URL { headers: Some(e), ..url },
));
rule!(env<String>; children!(
@@ -654,7 +654,7 @@ make_parser! {
token_rule!(missing<()>);
- rule!(import_type<ImportLocation>; children!(
+ rule!(import_type<ImportLocation<ParsedSubExpr>>; children!(
[missing(_)] => {
ImportLocation::Missing
},
@@ -679,33 +679,33 @@ make_parser! {
Hash::SHA256(hex::decode(hash).unwrap())
});
- rule!(import_hashed<ImportHashed>; children!(
+ rule!(import_hashed<crate::Import<ParsedSubExpr>>; children!(
[import_type(location)] =>
- ImportHashed { location, hash: None },
+ crate::Import {mode: ImportMode::Code, location, hash: None },
[import_type(location), hash(h)] =>
- ImportHashed { location, hash: Some(h) },
+ crate::Import {mode: ImportMode::Code, location, hash: Some(h) },
));
token_rule!(Text<()>);
token_rule!(Location<()>);
rule!(import<ParsedSubExpr> as expression; span; children!(
- [import_hashed(location_hashed)] => {
+ [import_hashed(imp)] => {
spanned(span, Import(crate::Import {
mode: ImportMode::Code,
- location_hashed
+ ..imp
}))
},
- [import_hashed(location_hashed), Text(_)] => {
+ [import_hashed(imp), Text(_)] => {
spanned(span, Import(crate::Import {
mode: ImportMode::RawText,
- location_hashed
+ ..imp
}))
},
- [import_hashed(location_hashed), Location(_)] => {
+ [import_hashed(imp), Location(_)] => {
spanned(span, Import(crate::Import {
mode: ImportMode::Location,
- location_hashed
+ ..imp
}))
},
));
diff --git a/dhall_syntax/src/printer.rs b/dhall_syntax/src/printer.rs
index 5f5f99b..256ea65 100644
--- a/dhall_syntax/src/printer.rs
+++ b/dhall_syntax/src/printer.rs
@@ -230,7 +230,7 @@ where
f.write_str(close)
}
-impl<SubExpr: Display + Clone> Display for InterpolatedText<SubExpr> {
+impl<SubExpr: Display> Display for InterpolatedText<SubExpr> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.write_str("\"")?;
for x in self.iter() {
@@ -344,10 +344,11 @@ impl Display for Hash {
}
}
}
-impl Display for ImportHashed {
+impl<SubExpr: Display> Display for Import<SubExpr> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use FilePrefix::*;
use ImportLocation::*;
+ use ImportMode::*;
let fmt_remote_path_component = |s: &str| -> String {
use percent_encoding::{
utf8_percent_encode, PATH_SEGMENT_ENCODE_SET,
@@ -423,14 +424,6 @@ impl Display for ImportHashed {
write!(f, " ")?;
hash.fmt(f)?;
}
- Ok(())
- }
-}
-
-impl Display for Import {
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- self.location_hashed.fmt(f)?;
- use ImportMode::*;
match self.mode {
Code => {}
RawText => write!(f, " as Text")?,