summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock33
-rw-r--r--Cargo.toml13
-rw-r--r--dhall/.gitignore (renamed from dhall_generated_parser/.gitignore)0
-rw-r--r--dhall/Cargo.toml16
-rw-r--r--dhall/build.rs98
l---------dhall/src/dhall.abnf (renamed from dhall_generated_parser/src/dhall.abnf)0
-rw-r--r--dhall/src/dhall.pest.visibility (renamed from dhall_generated_parser/src/dhall.pest.visibility)0
-rw-r--r--dhall/src/lib.rs5
-rw-r--r--dhall/src/semantics/core/context.rs (renamed from dhall/src/core/context.rs)11
-rw-r--r--dhall/src/semantics/core/mod.rs (renamed from dhall/src/core/mod.rs)0
-rw-r--r--dhall/src/semantics/core/value.rs (renamed from dhall/src/core/value.rs)17
-rw-r--r--dhall/src/semantics/core/valuef.rs (renamed from dhall/src/core/valuef.rs)14
-rw-r--r--dhall/src/semantics/core/var.rs (renamed from dhall/src/core/var.rs)10
-rw-r--r--dhall/src/semantics/error/mod.rs (renamed from dhall/src/error/mod.rs)11
-rw-r--r--dhall/src/semantics/mod.rs3
-rw-r--r--dhall/src/semantics/phase/mod.rs (renamed from dhall/src/phase/mod.rs)18
-rw-r--r--dhall/src/semantics/phase/normalize.rs (renamed from dhall/src/phase/normalize.rs)22
-rw-r--r--dhall/src/semantics/phase/parse.rs (renamed from dhall/src/phase/parse.rs)14
-rw-r--r--dhall/src/semantics/phase/resolve.rs (renamed from dhall/src/phase/resolve.rs)13
-rw-r--r--dhall/src/semantics/phase/typecheck.rs (renamed from dhall/src/phase/typecheck.rs)53
-rw-r--r--dhall/src/syntax/binary/decode.rs (renamed from dhall/src/phase/binary.rs)329
-rw-r--r--dhall/src/syntax/binary/encode.rs319
-rw-r--r--dhall/src/syntax/binary/mod.rs4
-rw-r--r--dhall/src/syntax/core/context.rs (renamed from dhall_syntax/src/core/context.rs)0
-rw-r--r--dhall/src/syntax/core/expr.rs (renamed from dhall_syntax/src/core/expr.rs)8
-rw-r--r--dhall/src/syntax/core/import.rs (renamed from dhall_syntax/src/core/import.rs)0
-rw-r--r--dhall/src/syntax/core/label.rs (renamed from dhall_syntax/src/core/label.rs)0
-rw-r--r--dhall/src/syntax/core/map.rs (renamed from dhall_syntax/src/core/map.rs)0
-rw-r--r--dhall/src/syntax/core/mod.rs (renamed from dhall_syntax/src/core/mod.rs)0
-rw-r--r--dhall/src/syntax/core/span.rs (renamed from dhall_syntax/src/core/span.rs)0
-rw-r--r--dhall/src/syntax/core/text.rs (renamed from dhall_syntax/src/core/text.rs)0
-rw-r--r--dhall/src/syntax/core/visitor.rs (renamed from dhall_syntax/src/core/visitor.rs)6
-rw-r--r--dhall/src/syntax/mod.rs15
-rw-r--r--dhall/src/syntax/text/mod.rs2
-rw-r--r--dhall/src/syntax/text/parser.rs (renamed from dhall_syntax/src/parser.rs)180
-rw-r--r--dhall/src/syntax/text/printer.rs (renamed from dhall_syntax/src/printer.rs)14
-rw-r--r--dhall/src/tests.rs4
-rw-r--r--dhall_generated_parser/Cargo.toml18
-rw-r--r--dhall_generated_parser/build.rs90
-rw-r--r--dhall_generated_parser/src/lib.rs22
-rw-r--r--dhall_syntax/Cargo.toml21
-rw-r--r--dhall_syntax/src/lib.rs22
-rw-r--r--serde_dhall/Cargo.toml1
-rw-r--r--serde_dhall/src/lib.rs8
-rw-r--r--serde_dhall/src/serde.rs4
-rw-r--r--serde_dhall/src/static_type.rs2
46 files changed, 658 insertions, 762 deletions
diff --git a/Cargo.lock b/Cargo.lock
index aa4b536..b196894 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -73,10 +73,16 @@ dependencies = [
name = "dhall"
version = "0.1.0"
dependencies = [
+ "abnf_to_pest 0.1.1",
"bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "dhall_syntax 0.1.0",
+ "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"improved_slice_patterns 2.0.0",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_consume 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_cbor 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -86,15 +92,6 @@ dependencies = [
]
[[package]]
-name = "dhall_generated_parser"
-version = "0.1.0"
-dependencies = [
- "abnf_to_pest 0.1.1",
- "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "dhall_proc_macros"
version = "0.1.0"
dependencies = [
@@ -105,21 +102,6 @@ dependencies = [
]
[[package]]
-name = "dhall_syntax"
-version = "0.1.0"
-dependencies = [
- "dhall_generated_parser 0.1.0",
- "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "pest_consume 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -376,7 +358,6 @@ version = "0.1.0"
dependencies = [
"dhall 0.1.0",
"dhall_proc_macros 0.1.0",
- "dhall_syntax 0.1.0",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/Cargo.toml b/Cargo.toml
index 1e40748..fc1f68d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,20 +4,7 @@ cargo-features = ["profile-overrides"]
members = [
"abnf_to_pest",
"dhall",
- "dhall_generated_parser",
- "dhall_syntax",
"dhall_proc_macros",
"improved_slice_patterns",
"serde_dhall"
]
-
-# # Parser is super slow when not optimized
-# [profile.dev.overrides.dhall_parser]
-# opt-level = 3
-# [profile.dev.overrides.dhall_syntax]
-# opt-level = 3
-# [profile.dev.overrides.dhall]
-# opt-level = 3
-# [profile.dev]
-# opt-level = 3
-
diff --git a/dhall_generated_parser/.gitignore b/dhall/.gitignore
index 8a0bac6..8a0bac6 100644
--- a/dhall_generated_parser/.gitignore
+++ b/dhall/.gitignore
diff --git a/dhall/Cargo.toml b/dhall/Cargo.toml
index 16c1c78..962b466 100644
--- a/dhall/Cargo.toml
+++ b/dhall/Cargo.toml
@@ -8,17 +8,25 @@ build = "build.rs"
[dependencies]
bytecount = "0.5.1"
+either = "1.5.2"
+improved_slice_patterns = { version = "2.0.0", path = "../improved_slice_patterns" }
itertools = "0.8.0"
-take_mut = "0.2.2"
-term-painter = "0.2.3"
+hex = "0.3.2"
+lazy_static = "1.4.0"
+percent-encoding = "2.1.0"
+pest = "2.1"
+# pest_consume = { path = "../../pest_consume/pest_consume" }
+pest_consume = "1.0"
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" }
+take_mut = "0.2.2"
+term-painter = "0.2.3"
[dev-dependencies]
pretty_assertions = "0.6.1"
[build-dependencies]
walkdir = "2"
+abnf_to_pest = { version = "0.1.1", path = "../abnf_to_pest" }
+
diff --git a/dhall/build.rs b/dhall/build.rs
index a0106de..50f423e 100644
--- a/dhall/build.rs
+++ b/dhall/build.rs
@@ -1,10 +1,12 @@
use std::env;
use std::ffi::OsString;
use std::fs::File;
-use std::io::Write;
+use std::io::{BufRead, BufReader, Read, Write};
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
+use abnf_to_pest::render_rules_to_pest;
+
#[derive(Debug, Clone, Copy)]
enum FileType {
Text,
@@ -100,7 +102,7 @@ fn make_test_module(
Ok(())
}
-fn main() -> std::io::Result<()> {
+fn generate_tests() -> std::io::Result<()> {
// Tries to detect when the submodule gets updated.
// To force regeneration of the test list, just `touch dhall-lang/.git`
println!("cargo:rerun-if-changed=../dhall-lang/.git");
@@ -404,3 +406,95 @@ fn main() -> std::io::Result<()> {
Ok(())
}
+
+fn convert_abnf_to_pest() -> std::io::Result<()> {
+ let abnf_path = "src/dhall.abnf";
+ let visibility_path = "src/dhall.pest.visibility";
+ let pest_path = "src/dhall.pest";
+ println!("cargo:rerun-if-changed={}", abnf_path);
+ println!("cargo:rerun-if-changed={}", visibility_path);
+
+ let mut file = File::open(abnf_path)?;
+ let mut data = Vec::new();
+ file.read_to_end(&mut data)?;
+ data.push('\n' as u8);
+
+ let mut rules = abnf_to_pest::parse_abnf(&data)?;
+ for line in BufReader::new(File::open(visibility_path)?).lines() {
+ let line = line?;
+ if line.len() >= 2 && &line[0..2] == "# " {
+ rules.get_mut(&line[2..]).map(|x| x.silent = true);
+ }
+ }
+
+ let mut file = File::create(pest_path)?;
+ writeln!(&mut file, "// AUTO-GENERATED FILE. See build.rs.")?;
+
+ // 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 = {{
+ keyword ~ simple_label_next_char+
+ | !keyword ~ simple_label_first_char ~ simple_label_next_char*
+ }}"
+ )?;
+
+ rules.remove("nonreserved_label");
+ writeln!(
+ &mut file,
+ "nonreserved_label = _{{
+ !(builtin ~ !simple_label_next_char) ~ label
+ }}"
+ )?;
+
+ // Setup grammar for precedence climbing
+ rules.remove("operator_expression");
+ writeln!(&mut file, r##"
+ import_alt = {{ "?" ~ whsp1 }}
+ bool_or = {{ "||" }}
+ natural_plus = {{ "+" ~ whsp1 }}
+ text_append = {{ "++" }}
+ list_append = {{ "#" }}
+ bool_and = {{ "&&" }}
+ natural_times = {{ "*" }}
+ bool_eq = {{ "==" }}
+ bool_ne = {{ "!=" }}
+
+ operator = _{{
+ equivalent |
+ bool_ne |
+ bool_eq |
+ natural_times |
+ combine_types |
+ prefer |
+ combine |
+ bool_and |
+ list_append |
+ text_append |
+ natural_plus |
+ bool_or |
+ import_alt
+ }}
+ operator_expression = {{ application_expression ~ (whsp ~ operator ~ whsp ~ application_expression)* }}
+ "##)?;
+
+ writeln!(
+ &mut file,
+ "final_expression = ${{ SOI ~ complete_expression ~ EOI }}"
+ )?;
+
+ writeln!(&mut file)?;
+ writeln!(&mut file, "{}", render_rules_to_pest(rules).pretty(80))?;
+
+ Ok(())
+}
+
+fn main() -> std::io::Result<()> {
+ convert_abnf_to_pest()?;
+ generate_tests()?;
+ Ok(())
+}
diff --git a/dhall_generated_parser/src/dhall.abnf b/dhall/src/dhall.abnf
index ce13b8e..ce13b8e 120000
--- a/dhall_generated_parser/src/dhall.abnf
+++ b/dhall/src/dhall.abnf
diff --git a/dhall_generated_parser/src/dhall.pest.visibility b/dhall/src/dhall.pest.visibility
index 17c1edc..17c1edc 100644
--- a/dhall_generated_parser/src/dhall.pest.visibility
+++ b/dhall/src/dhall.pest.visibility
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs
index ed4435a..0991375 100644
--- a/dhall/src/lib.rs
+++ b/dhall/src/lib.rs
@@ -12,6 +12,5 @@
mod tests;
-pub mod core;
-pub mod error;
-pub mod phase;
+pub mod semantics;
+pub mod syntax;
diff --git a/dhall/src/core/context.rs b/dhall/src/semantics/core/context.rs
index 2bf39c5..d150e56 100644
--- a/dhall/src/core/context.rs
+++ b/dhall/src/semantics/core/context.rs
@@ -1,12 +1,11 @@
use std::collections::HashMap;
use std::rc::Rc;
-use dhall_syntax::{Label, V};
-
-use crate::core::value::Value;
-use crate::core::valuef::ValueF;
-use crate::core::var::{AlphaVar, Shift, Subst};
-use crate::error::TypeError;
+use crate::semantics::core::value::Value;
+use crate::semantics::core::valuef::ValueF;
+use crate::semantics::core::var::{AlphaVar, Shift, Subst};
+use crate::semantics::error::TypeError;
+use crate::syntax::{Label, V};
#[derive(Debug, Clone)]
enum CtxItem {
diff --git a/dhall/src/core/mod.rs b/dhall/src/semantics/core/mod.rs
index 08213f7..08213f7 100644
--- a/dhall/src/core/mod.rs
+++ b/dhall/src/semantics/core/mod.rs
diff --git a/dhall/src/core/value.rs b/dhall/src/semantics/core/value.rs
index d4f5131..6e6739f 100644
--- a/dhall/src/core/value.rs
+++ b/dhall/src/semantics/core/value.rs
@@ -1,15 +1,14 @@
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;
-use dhall_syntax::{Builtin, Const, Span};
-
-use crate::core::context::TypecheckContext;
-use crate::core::valuef::ValueF;
-use crate::core::var::{AlphaVar, Shift, Subst};
-use crate::error::{TypeError, TypeMessage};
-use crate::phase::normalize::{apply_any, normalize_whnf};
-use crate::phase::typecheck::{builtin_to_value, const_to_value};
-use crate::phase::{NormalizedExpr, Typed};
+use crate::semantics::core::context::TypecheckContext;
+use crate::semantics::core::valuef::ValueF;
+use crate::semantics::core::var::{AlphaVar, Shift, Subst};
+use crate::semantics::error::{TypeError, TypeMessage};
+use crate::semantics::phase::normalize::{apply_any, normalize_whnf};
+use crate::semantics::phase::typecheck::{builtin_to_value, const_to_value};
+use crate::semantics::phase::{NormalizedExpr, Typed};
+use crate::syntax::{Builtin, Const, Span};
#[derive(Debug, Clone, Copy)]
pub(crate) enum Form {
diff --git a/dhall/src/core/valuef.rs b/dhall/src/semantics/core/valuef.rs
index e5d0807..73c715a 100644
--- a/dhall/src/core/valuef.rs
+++ b/dhall/src/semantics/core/valuef.rs
@@ -1,15 +1,15 @@
use std::collections::HashMap;
-use dhall_syntax::{
+use crate::semantics::core::value::{ToExprOptions, Value};
+use crate::semantics::core::var::{AlphaLabel, AlphaVar, Shift, Subst};
+use crate::semantics::phase::typecheck::rc;
+use crate::semantics::phase::{Normalized, NormalizedExpr};
+use crate::syntax;
+use crate::syntax::{
Builtin, Const, ExprF, Integer, InterpolatedTextContents, Label,
NaiveDouble, Natural,
};
-use crate::core::value::{ToExprOptions, Value};
-use crate::core::var::{AlphaLabel, AlphaVar, Shift, Subst};
-use crate::phase::typecheck::rc;
-use crate::phase::{Normalized, NormalizedExpr};
-
/// A semantic value. Subexpressions are Values, which are partially evaluated expressions that are
/// normalized on-demand.
/// If you compare for equality two `ValueF`s in WHNF, then equality will be up to
@@ -117,7 +117,7 @@ impl ValueF {
.collect(),
)),
ValueF::Equivalence(x, y) => rc(ExprF::BinOp(
- dhall_syntax::BinOp::Equivalence,
+ syntax::BinOp::Equivalence,
x.to_expr(opts),
y.to_expr(opts),
)),
diff --git a/dhall/src/core/var.rs b/dhall/src/semantics/core/var.rs
index 3795f10..184a372 100644
--- a/dhall/src/core/var.rs
+++ b/dhall/src/semantics/core/var.rs
@@ -1,6 +1,6 @@
use std::collections::HashMap;
-use dhall_syntax::{Label, V};
+use crate::syntax::{ExprF, InterpolatedTextContents, Label, V};
/// Stores a pair of variables: a normal one and one
/// that corresponds to the alpha-normalized version of the first one.
@@ -190,7 +190,7 @@ impl<T: Shift> Shift for std::cell::RefCell<T> {
}
}
-impl<T: Shift, E: Clone> Shift for dhall_syntax::ExprF<T, E> {
+impl<T: Shift, E: Clone> Shift for ExprF<T, E> {
fn shift(&self, delta: isize, var: &AlphaVar) -> Option<Self> {
Some(self.traverse_ref_with_special_handling_of_binders(
|v| Ok(v.shift(delta, var)?),
@@ -222,7 +222,7 @@ where
}
}
-impl<T: Shift> Shift for dhall_syntax::InterpolatedTextContents<T> {
+impl<T: Shift> Shift for InterpolatedTextContents<T> {
fn shift(&self, delta: isize, var: &AlphaVar) -> Option<Self> {
Some(self.traverse_ref(|x| Ok(x.shift(delta, var)?))?)
}
@@ -262,7 +262,7 @@ impl<S, T: Subst<S>> Subst<S> for std::cell::RefCell<T> {
}
}
-impl<S: Shift, T: Subst<S>, E: Clone> Subst<S> for dhall_syntax::ExprF<T, E> {
+impl<S: Shift, T: Subst<S>, E: Clone> Subst<S> for ExprF<T, E> {
fn subst_shift(&self, var: &AlphaVar, val: &S) -> Self {
self.map_ref_with_special_handling_of_binders(
|v| v.subst_shift(var, val),
@@ -277,7 +277,7 @@ impl<S, T: Subst<S>> Subst<S> for Vec<T> {
}
}
-impl<S, T: Subst<S>> Subst<S> for dhall_syntax::InterpolatedTextContents<T> {
+impl<S, T: Subst<S>> Subst<S> for InterpolatedTextContents<T> {
fn subst_shift(&self, var: &AlphaVar, val: &S) -> Self {
self.map_ref(|x| x.subst_shift(var, val))
}
diff --git a/dhall/src/error/mod.rs b/dhall/src/semantics/error/mod.rs
index e4baea0..1288c12 100644
--- a/dhall/src/error/mod.rs
+++ b/dhall/src/semantics/error/mod.rs
@@ -1,11 +1,10 @@
use std::io::Error as IOError;
-use dhall_syntax::{BinOp, Import, Label, ParseError, Span};
-
-use crate::core::context::TypecheckContext;
-use crate::core::value::Value;
-use crate::phase::resolve::ImportStack;
-use crate::phase::NormalizedExpr;
+use crate::semantics::core::context::TypecheckContext;
+use crate::semantics::core::value::Value;
+use crate::semantics::phase::resolve::ImportStack;
+use crate::semantics::phase::NormalizedExpr;
+use crate::syntax::{BinOp, Import, Label, ParseError, Span};
pub type Result<T> = std::result::Result<T, Error>;
diff --git a/dhall/src/semantics/mod.rs b/dhall/src/semantics/mod.rs
new file mode 100644
index 0000000..9d2e462
--- /dev/null
+++ b/dhall/src/semantics/mod.rs
@@ -0,0 +1,3 @@
+pub mod core;
+pub mod error;
+pub mod phase;
diff --git a/dhall/src/phase/mod.rs b/dhall/src/semantics/phase/mod.rs
index 337ce3d..752c257 100644
--- a/dhall/src/phase/mod.rs
+++ b/dhall/src/semantics/phase/mod.rs
@@ -1,16 +1,14 @@
use std::fmt::Display;
use std::path::Path;
-use dhall_syntax::{Builtin, Const, Expr};
-
-use crate::core::value::{ToExprOptions, Value};
-use crate::core::valuef::ValueF;
-use crate::core::var::{AlphaVar, Shift, Subst};
-use crate::error::{EncodeError, Error, ImportError, TypeError};
-
+use crate::semantics::core::value::{ToExprOptions, Value};
+use crate::semantics::core::valuef::ValueF;
+use crate::semantics::core::var::{AlphaVar, Shift, Subst};
+use crate::semantics::error::{EncodeError, Error, ImportError, TypeError};
+use crate::syntax::binary;
+use crate::syntax::{Builtin, Const, Expr};
use resolve::ImportRoot;
-pub(crate) mod binary;
pub(crate) mod normalize;
pub(crate) mod parse;
pub(crate) mod resolve;
@@ -62,7 +60,7 @@ impl Parsed {
}
pub fn encode(&self) -> Result<Vec<u8>, EncodeError> {
- crate::phase::binary::encode(&self.0)
+ binary::encode(&self.0)
}
}
@@ -172,7 +170,7 @@ impl Typed {
impl Normalized {
pub fn encode(&self) -> Result<Vec<u8>, EncodeError> {
- crate::phase::binary::encode(&self.to_expr())
+ binary::encode(&self.to_expr())
}
pub(crate) fn to_expr(&self) -> NormalizedExpr {
diff --git a/dhall/src/phase/normalize.rs b/dhall/src/semantics/phase/normalize.rs
index b712027..81c3ce1 100644
--- a/dhall/src/phase/normalize.rs
+++ b/dhall/src/semantics/phase/normalize.rs
@@ -1,21 +1,21 @@
use std::collections::HashMap;
-use dhall_syntax::Const::Type;
-use dhall_syntax::{
+use crate::semantics::core::value::Value;
+use crate::semantics::core::valuef::ValueF;
+use crate::semantics::core::var::{AlphaLabel, AlphaVar, Shift, Subst};
+use crate::semantics::phase::Normalized;
+use crate::syntax;
+use crate::syntax::Const::Type;
+use crate::syntax::{
BinOp, Builtin, ExprF, InterpolatedText, InterpolatedTextContents, Label,
NaiveDouble,
};
-use crate::core::value::Value;
-use crate::core::valuef::ValueF;
-use crate::core::var::{AlphaLabel, Shift, Subst};
-use crate::phase::Normalized;
-
// Ad-hoc macro to help construct closures
macro_rules! make_closure {
(#$var:ident) => { $var.clone() };
(var($var:ident, $n:expr, $($ty:tt)*)) => {{
- let var = crate::core::var::AlphaVar::from_var_and_alpha(
+ let var = AlphaVar::from_var_and_alpha(
Label::from(stringify!($var)).into(),
$n
);
@@ -47,7 +47,7 @@ macro_rules! make_closure {
}};
(1 + $($rest:tt)*) => {
ValueF::PartialExpr(ExprF::BinOp(
- dhall_syntax::BinOp::NaturalPlus,
+ syntax::BinOp::NaturalPlus,
make_closure!($($rest)*),
Value::from_valuef_and_type(
ValueF::NaturalLit(1),
@@ -62,7 +62,7 @@ macro_rules! make_closure {
let tail = make_closure!($($tail)*);
let list_type = tail.get_type_not_sort();
ValueF::PartialExpr(ExprF::BinOp(
- dhall_syntax::BinOp::ListAppend,
+ syntax::BinOp::ListAppend,
ValueF::NEListLit(vec![head])
.into_value_with_type(list_type.clone()),
tail,
@@ -76,7 +76,7 @@ pub(crate) fn apply_builtin(
args: Vec<Value>,
ty: &Value,
) -> ValueF {
- use dhall_syntax::Builtin::*;
+ use syntax::Builtin::*;
use ValueF::*;
// Small helper enum
diff --git a/dhall/src/phase/parse.rs b/dhall/src/semantics/phase/parse.rs
index 540ceea..4c8ad7b 100644
--- a/dhall/src/phase/parse.rs
+++ b/dhall/src/semantics/phase/parse.rs
@@ -2,11 +2,11 @@ use std::fs::File;
use std::io::Read;
use std::path::Path;
-use dhall_syntax::parse_expr;
-
-use crate::error::Error;
-use crate::phase::resolve::ImportRoot;
-use crate::phase::Parsed;
+use crate::semantics::error::Error;
+use crate::semantics::phase::resolve::ImportRoot;
+use crate::semantics::phase::Parsed;
+use crate::syntax::binary;
+use crate::syntax::parse_expr;
pub(crate) fn parse_file(f: &Path) -> Result<Parsed, Error> {
let mut buffer = String::new();
@@ -23,7 +23,7 @@ pub(crate) fn parse_str(s: &str) -> Result<Parsed, Error> {
}
pub(crate) fn parse_binary(data: &[u8]) -> Result<Parsed, Error> {
- let expr = crate::phase::binary::decode(data)?;
+ let expr = binary::decode(data)?;
let root = ImportRoot::LocalDir(std::env::current_dir()?);
Ok(Parsed(expr, root))
}
@@ -31,7 +31,7 @@ pub(crate) fn parse_binary(data: &[u8]) -> Result<Parsed, Error> {
pub(crate) fn parse_binary_file(f: &Path) -> Result<Parsed, Error> {
let mut buffer = Vec::new();
File::open(f)?.read_to_end(&mut buffer)?;
- let expr = crate::phase::binary::decode(&buffer)?;
+ let expr = binary::decode(&buffer)?;
let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned());
Ok(Parsed(expr, root))
}
diff --git a/dhall/src/phase/resolve.rs b/dhall/src/semantics/phase/resolve.rs
index c302bfa..86dc7ae 100644
--- a/dhall/src/phase/resolve.rs
+++ b/dhall/src/semantics/phase/resolve.rs
@@ -1,11 +1,12 @@
use std::collections::HashMap;
use std::path::{Path, PathBuf};
-use crate::error::{Error, ImportError};
-use crate::phase::{Normalized, NormalizedExpr, Parsed, Resolved};
-use dhall_syntax::{FilePath, ImportLocation, URL};
+use crate::semantics::error::{Error, ImportError};
+use crate::semantics::phase::{Normalized, NormalizedExpr, Parsed, Resolved};
+use crate::syntax;
+use crate::syntax::{FilePath, ImportLocation, URL};
-type Import = dhall_syntax::Import<NormalizedExpr>;
+type Import = syntax::Import<NormalizedExpr>;
/// A root from which to resolve relative imports.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -24,8 +25,8 @@ fn resolve_import(
import_stack: &ImportStack,
) -> Result<Normalized, ImportError> {
use self::ImportRoot::*;
- use dhall_syntax::FilePrefix::*;
- use dhall_syntax::ImportLocation::*;
+ use syntax::FilePrefix::*;
+ use syntax::ImportLocation::*;
let cwd = match root {
LocalDir(cwd) => cwd,
};
diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/semantics/phase/typecheck.rs
index ef8340d..59380a3 100644
--- a/dhall/src/phase/typecheck.rs
+++ b/dhall/src/semantics/phase/typecheck.rs
@@ -1,24 +1,25 @@
use std::cmp::max;
use std::collections::HashMap;
-use dhall_syntax::{
+use crate::semantics::core::context::TypecheckContext;
+use crate::semantics::core::value::Value;
+use crate::semantics::core::valuef::ValueF;
+use crate::semantics::core::var::{Shift, Subst};
+use crate::semantics::error::{TypeError, TypeMessage};
+use crate::semantics::phase::normalize::merge_maps;
+use crate::semantics::phase::Normalized;
+use crate::syntax;
+use crate::syntax::{
Builtin, Const, Expr, ExprF, InterpolatedTextContents, Label, RawExpr, Span,
};
-use crate::core::context::TypecheckContext;
-use crate::core::value::Value;
-use crate::core::valuef::ValueF;
-use crate::core::var::{Shift, Subst};
-use crate::error::{TypeError, TypeMessage};
-use crate::phase::Normalized;
-
fn tck_pi_type(
ctx: &TypecheckContext,
x: Label,
tx: Value,
te: Value,
) -> Result<Value, TypeError> {
- use crate::error::TypeMessage::*;
+ use TypeMessage::*;
let ctx2 = ctx.insert_type(&x, tx.clone());
let ka = match tx.get_type()?.as_const() {
@@ -48,8 +49,8 @@ fn tck_record_type(
ctx: &TypecheckContext,
kts: impl IntoIterator<Item = Result<(Label, Value), TypeError>>,
) -> Result<Value, TypeError> {
- use crate::error::TypeMessage::*;
use std::collections::hash_map::Entry;
+ use TypeMessage::*;
let mut new_kts = HashMap::new();
// An empty record type has type Type
let mut k = Const::Type;
@@ -83,8 +84,8 @@ fn tck_union_type<Iter>(
where
Iter: IntoIterator<Item = Result<(Label, Option<Value>), TypeError>>,
{
- use crate::error::TypeMessage::*;
use std::collections::hash_map::Entry;
+ use TypeMessage::*;
let mut new_kts = HashMap::new();
// Check that all types are the same const
let mut k = None;
@@ -155,7 +156,7 @@ macro_rules! make_type {
(Double) => { ExprF::Builtin(Builtin::Double) };
(Text) => { ExprF::Builtin(Builtin::Text) };
($var:ident) => {
- ExprF::Var(dhall_syntax::V(stringify!($var).into(), 0))
+ ExprF::Var(syntax::V(stringify!($var).into(), 0))
};
(Optional $ty:ident) => {
ExprF::App(
@@ -170,7 +171,7 @@ macro_rules! make_type {
)
};
({ $($label:ident : $ty:ident),* }) => {{
- let mut kts = dhall_syntax::map::DupTreeMap::new();
+ let mut kts = syntax::map::DupTreeMap::new();
$(
kts.insert(
Label::from(stringify!($label)),
@@ -203,7 +204,7 @@ macro_rules! make_type {
}
fn type_of_builtin<E>(b: Builtin) -> Expr<E> {
- use dhall_syntax::Builtin::*;
+ use syntax::Builtin::*;
rc(match b {
Bool | Natural | Integer | Double | Text => make_type!(Type),
List | Optional => make_type!(
@@ -303,7 +304,7 @@ fn type_with(
ctx: &TypecheckContext,
e: Expr<Normalized>,
) -> Result<Value, TypeError> {
- use dhall_syntax::ExprF::{Annot, Embed, Lam, Let, Pi, Var};
+ use syntax::ExprF::{Annot, Embed, Lam, Let, Pi, Var};
let span = e.span();
Ok(match e.as_ref() {
@@ -361,11 +362,11 @@ fn type_last_layer(
e: ExprF<Value, Normalized>,
span: Span,
) -> Result<Value, TypeError> {
- use crate::error::TypeMessage::*;
- use dhall_syntax::BinOp::*;
- use dhall_syntax::Builtin::*;
- use dhall_syntax::Const::Type;
- use dhall_syntax::ExprF::*;
+ use syntax::BinOp::*;
+ use syntax::Builtin::*;
+ use syntax::Const::Type;
+ use syntax::ExprF::*;
+ use TypeMessage::*;
let mkerr = |msg: TypeMessage| Err(TypeError::new(ctx, msg));
/// Intermediary return type
@@ -434,7 +435,7 @@ fn type_last_layer(
}
EmptyListLit(t) => {
match &*t.as_whnf() {
- ValueF::AppliedBuiltin(dhall_syntax::Builtin::List, args)
+ ValueF::AppliedBuiltin(syntax::Builtin::List, args)
if args.len() == 1 => {}
_ => return mkerr(InvalidListType(t.clone())),
}
@@ -457,7 +458,7 @@ fn type_last_layer(
return mkerr(InvalidListType(t));
}
- RetTypeOnly(Value::from_builtin(dhall_syntax::Builtin::List).app(t))
+ RetTypeOnly(Value::from_builtin(syntax::Builtin::List).app(t))
}
SomeLit(x) => {
let t = x.get_type()?;
@@ -465,9 +466,7 @@ fn type_last_layer(
return mkerr(InvalidOptionalType(t));
}
- RetTypeOnly(
- Value::from_builtin(dhall_syntax::Builtin::Optional).app(t),
- )
+ RetTypeOnly(Value::from_builtin(syntax::Builtin::Optional).app(t))
}
RecordType(kts) => RetWhole(tck_record_type(
ctx,
@@ -548,8 +547,6 @@ fn type_last_layer(
RetTypeOnly(text_type)
}
BinOp(RightBiasedRecordMerge, l, r) => {
- use crate::phase::normalize::merge_maps;
-
let l_type = l.get_type()?;
let r_type = r.get_type()?;
@@ -589,8 +586,6 @@ fn type_last_layer(
Span::Artificial,
)?),
BinOp(RecursiveRecordTypeMerge, l, r) => {
- use crate::phase::normalize::merge_maps;
-
// Extract the LHS record type
let borrow_l = l.as_whnf();
let kts_x = match &*borrow_l {
diff --git a/dhall/src/phase/binary.rs b/dhall/src/syntax/binary/decode.rs
index 0639120..46c9921 100644
--- a/dhall/src/phase/binary.rs
+++ b/dhall/src/syntax/binary/decode.rs
@@ -1,18 +1,15 @@
use itertools::Itertools;
use serde_cbor::value::value as cbor;
use std::iter::FromIterator;
-use std::vec;
-use dhall_syntax::map::DupTreeMap;
-use dhall_syntax::{
- Expr, ExprF, FilePath, FilePrefix, Hash, Import, ImportLocation,
- ImportMode, Integer, InterpolatedText, Label, Natural, RawExpr, Scheme,
- Span, URL, V,
+use crate::semantics::error::DecodeError;
+use crate::semantics::phase::DecodedExpr;
+use crate::syntax;
+use crate::syntax::{
+ Expr, ExprF, FilePath, FilePrefix, Hash, ImportLocation, ImportMode,
+ Integer, InterpolatedText, Label, Natural, RawExpr, Scheme, Span, URL, V,
};
-use crate::error::{DecodeError, EncodeError};
-use crate::phase::DecodedExpr;
-
pub(crate) fn decode(data: &[u8]) -> Result<DecodedExpr, DecodeError> {
match serde_cbor::de::from_slice(data) {
Ok(v) => cbor_value_to_dhall(&v),
@@ -20,19 +17,14 @@ pub(crate) fn decode(data: &[u8]) -> Result<DecodedExpr, DecodeError> {
}
}
-pub(crate) fn encode<E>(expr: &Expr<E>) -> Result<Vec<u8>, EncodeError> {
- serde_cbor::ser::to_vec(&Serialize::Expr(expr))
- .map_err(|e| EncodeError::CBORError(e))
-}
-
// Should probably rename this
-pub fn rc<E>(x: RawExpr<E>) -> Expr<E> {
+fn rc<E>(x: RawExpr<E>) -> Expr<E> {
Expr::new(x, Span::Decoded)
}
fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> {
use cbor::Value::*;
- use dhall_syntax::{BinOp, Builtin, Const};
+ use syntax::{BinOp, Builtin, Const};
use ExprF::*;
Ok(rc(match data {
String(s) => match Builtin::parse(s) {
@@ -350,7 +342,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> {
"import/type".to_owned(),
))?,
};
- Import(dhall_syntax::Import {
+ Import(syntax::Import {
mode,
hash,
location,
@@ -443,306 +435,3 @@ where
})
.collect::<Result<_, _>>()
}
-
-enum Serialize<'a, E> {
- Expr(&'a Expr<E>),
- CBOR(cbor::Value),
- RecordMap(&'a DupTreeMap<Label, Expr<E>>),
- UnionMap(&'a DupTreeMap<Label, Option<Expr<E>>>),
-}
-
-macro_rules! count {
- (@replace_with $_t:tt $sub:expr) => { $sub };
- ($($tts:tt)*) => {0usize $(+ count!(@replace_with $tts 1usize))*};
-}
-
-macro_rules! ser_seq {
- ($ser:expr; $($elt:expr),* $(,)?) => {{
- use serde::ser::SerializeSeq;
- let count = count!($($elt)*);
- let mut ser_seq = $ser.serialize_seq(Some(count))?;
- $(
- ser_seq.serialize_element(&$elt)?;
- )*
- ser_seq.end()
- }};
-}
-
-fn serialize_subexpr<S, E>(ser: S, e: &Expr<E>) -> Result<S::Ok, S::Error>
-where
- S: serde::ser::Serializer,
-{
- use cbor::Value::{String, I64, U64};
- use dhall_syntax::Builtin;
- use dhall_syntax::ExprF::*;
- use std::iter::once;
-
- use self::Serialize::{RecordMap, UnionMap};
- fn expr<E>(x: &Expr<E>) -> self::Serialize<'_, E> {
- self::Serialize::Expr(x)
- }
- let cbor =
- |v: cbor::Value| -> self::Serialize<'_, E> { self::Serialize::CBOR(v) };
- let tag = |x: u64| cbor(U64(x));
- let null = || cbor(cbor::Value::Null);
- let label = |l: &Label| cbor(cbor::Value::String(l.into()));
-
- match e.as_ref() {
- Const(c) => ser.serialize_str(&c.to_string()),
- Builtin(b) => ser.serialize_str(&b.to_string()),
- BoolLit(b) => ser.serialize_bool(*b),
- NaturalLit(n) => ser_seq!(ser; tag(15), U64(*n as u64)),
- IntegerLit(n) => ser_seq!(ser; tag(16), I64(*n as i64)),
- DoubleLit(n) => {
- let n: f64 = (*n).into();
- ser.serialize_f64(n)
- }
- BoolIf(x, y, z) => ser_seq!(ser; tag(14), expr(x), expr(y), expr(z)),
- Var(V(l, n)) if l == &"_".into() => ser.serialize_u64(*n as u64),
- Var(V(l, n)) => ser_seq!(ser; label(l), U64(*n as u64)),
- Lam(l, x, y) if l == &"_".into() => {
- ser_seq!(ser; tag(1), expr(x), expr(y))
- }
- Lam(l, x, y) => ser_seq!(ser; tag(1), label(l), expr(x), expr(y)),
- Pi(l, x, y) if l == &"_".into() => {
- ser_seq!(ser; tag(2), expr(x), expr(y))
- }
- Pi(l, x, y) => ser_seq!(ser; tag(2), label(l), expr(x), expr(y)),
- Let(_, _, _, _) => {
- let (bound_e, bindings) = collect_nested_lets(e);
- let count = 1 + 3 * bindings.len() + 1;
-
- use serde::ser::SerializeSeq;
- let mut ser_seq = ser.serialize_seq(Some(count))?;
- ser_seq.serialize_element(&tag(25))?;
- for (l, t, v) in bindings {
- ser_seq.serialize_element(&label(l))?;
- match t {
- Some(t) => ser_seq.serialize_element(&expr(t))?,
- None => ser_seq.serialize_element(&null())?,
- }
- ser_seq.serialize_element(&expr(v))?;
- }
- ser_seq.serialize_element(&expr(bound_e))?;
- ser_seq.end()
- }
- App(_, _) => {
- let (f, args) = collect_nested_applications(e);
- ser.collect_seq(
- once(tag(0))
- .chain(once(expr(f)))
- .chain(args.into_iter().rev().map(expr)),
- )
- }
- Annot(x, y) => ser_seq!(ser; tag(26), expr(x), expr(y)),
- Assert(x) => ser_seq!(ser; tag(19), expr(x)),
- SomeLit(x) => ser_seq!(ser; tag(5), null(), expr(x)),
- EmptyListLit(x) => match x.as_ref() {
- App(f, a) => match f.as_ref() {
- ExprF::Builtin(Builtin::List) => ser_seq!(ser; tag(4), expr(a)),
- _ => ser_seq!(ser; tag(28), expr(x)),
- },
- _ => ser_seq!(ser; tag(28), expr(x)),
- },
- NEListLit(xs) => ser.collect_seq(
- once(tag(4)).chain(once(null())).chain(xs.iter().map(expr)),
- ),
- TextLit(xs) => {
- use dhall_syntax::InterpolatedTextContents::{Expr, Text};
- ser.collect_seq(once(tag(18)).chain(xs.iter().map(|x| match x {
- Expr(x) => expr(x),
- Text(x) => cbor(String(x.clone())),
- })))
- }
- RecordType(map) => ser_seq!(ser; tag(7), RecordMap(map)),
- RecordLit(map) => ser_seq!(ser; tag(8), RecordMap(map)),
- UnionType(map) => ser_seq!(ser; tag(11), UnionMap(map)),
- Field(x, l) => ser_seq!(ser; tag(9), expr(x), label(l)),
- BinOp(op, x, y) => {
- use dhall_syntax::BinOp::*;
- let op = match op {
- BoolOr => 0,
- BoolAnd => 1,
- BoolEQ => 2,
- BoolNE => 3,
- NaturalPlus => 4,
- NaturalTimes => 5,
- TextAppend => 6,
- ListAppend => 7,
- RecursiveRecordMerge => 8,
- RightBiasedRecordMerge => 9,
- RecursiveRecordTypeMerge => 10,
- ImportAlt => 11,
- Equivalence => 12,
- };
- ser_seq!(ser; tag(3), U64(op), expr(x), expr(y))
- }
- Merge(x, y, None) => ser_seq!(ser; tag(6), expr(x), expr(y)),
- Merge(x, y, Some(z)) => {
- ser_seq!(ser; tag(6), expr(x), expr(y), expr(z))
- }
- ToMap(x, None) => ser_seq!(ser; tag(27), expr(x)),
- ToMap(x, Some(y)) => ser_seq!(ser; tag(27), expr(x), expr(y)),
- Projection(x, ls) => ser.collect_seq(
- once(tag(10))
- .chain(once(expr(x)))
- .chain(ls.iter().map(label)),
- ),
- ProjectionByExpr(x, y) => {
- ser_seq!(ser; tag(10), expr(x), vec![expr(y)])
- }
- Import(import) => serialize_import(ser, import),
- Embed(_) => unimplemented!(
- "An expression with resolved imports cannot be binary-encoded"
- ),
- }
-}
-
-fn serialize_import<S, E>(
- ser: S,
- import: &Import<Expr<E>>,
-) -> Result<S::Ok, S::Error>
-where
- S: serde::ser::Serializer,
-{
- use cbor::Value::{Bytes, Null, U64};
- use serde::ser::SerializeSeq;
-
- let count = 4 + match &import.location {
- ImportLocation::Remote(url) => 3 + url.path.file_path.len(),
- ImportLocation::Local(_, path) => path.file_path.len(),
- ImportLocation::Env(_) => 1,
- ImportLocation::Missing => 0,
- };
- let mut ser_seq = ser.serialize_seq(Some(count))?;
-
- ser_seq.serialize_element(&U64(24))?;
-
- let hash = match &import.hash {
- None => Null,
- Some(Hash::SHA256(h)) => {
- let mut bytes = vec![18, 32];
- bytes.extend_from_slice(h);
- Bytes(bytes)
- }
- };
- ser_seq.serialize_element(&hash)?;
-
- let mode = match import.mode {
- ImportMode::Code => 0,
- ImportMode::RawText => 1,
- ImportMode::Location => 2,
- };
- ser_seq.serialize_element(&U64(mode))?;
-
- let scheme = match &import.location {
- ImportLocation::Remote(url) => match url.scheme {
- Scheme::HTTP => 0,
- Scheme::HTTPS => 1,
- },
- ImportLocation::Local(prefix, _) => match prefix {
- FilePrefix::Absolute => 2,
- FilePrefix::Here => 3,
- FilePrefix::Parent => 4,
- FilePrefix::Home => 5,
- },
- ImportLocation::Env(_) => 6,
- ImportLocation::Missing => 7,
- };
- ser_seq.serialize_element(&U64(scheme))?;
-
- match &import.location {
- ImportLocation::Remote(url) => {
- match &url.headers {
- None => ser_seq.serialize_element(&Null)?,
- Some(e) => {
- ser_seq.serialize_element(&self::Serialize::Expr(e))?
- }
- };
- ser_seq.serialize_element(&url.authority)?;
- for p in url.path.file_path.iter() {
- ser_seq.serialize_element(&p)?;
- }
- match &url.query {
- None => ser_seq.serialize_element(&Null)?,
- Some(x) => ser_seq.serialize_element(x)?,
- };
- }
- ImportLocation::Local(_, path) => {
- for p in path.file_path.iter() {
- ser_seq.serialize_element(&p)?;
- }
- }
- ImportLocation::Env(env) => {
- ser_seq.serialize_element(env)?;
- }
- ImportLocation::Missing => {}
- }
-
- ser_seq.end()
-}
-
-impl<'a, E> serde::ser::Serialize for Serialize<'a, E> {
- fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
- where
- S: serde::ser::Serializer,
- {
- match self {
- Serialize::Expr(e) => serialize_subexpr(ser, e),
- Serialize::CBOR(v) => v.serialize(ser),
- Serialize::RecordMap(map) => {
- ser.collect_map(map.iter().map(|(k, v)| {
- (cbor::Value::String(k.into()), Serialize::Expr(v))
- }))
- }
- Serialize::UnionMap(map) => {
- ser.collect_map(map.iter().map(|(k, v)| {
- let v = match v {
- Some(x) => Serialize::Expr(x),
- None => Serialize::CBOR(cbor::Value::Null),
- };
- (cbor::Value::String(k.into()), v)
- }))
- }
- }
- }
-}
-
-fn collect_nested_applications<'a, E>(
- e: &'a Expr<E>,
-) -> (&'a Expr<E>, Vec<&'a Expr<E>>) {
- fn go<'a, E>(e: &'a Expr<E>, vec: &mut Vec<&'a Expr<E>>) -> &'a Expr<E> {
- match e.as_ref() {
- ExprF::App(f, a) => {
- vec.push(a);
- go(f, vec)
- }
- _ => e,
- }
- }
- let mut vec = vec![];
- let e = go(e, &mut vec);
- (e, vec)
-}
-
-type LetBinding<'a, E> = (&'a Label, &'a Option<Expr<E>>, &'a Expr<E>);
-
-fn collect_nested_lets<'a, E>(
- e: &'a Expr<E>,
-) -> (&'a Expr<E>, Vec<LetBinding<'a, E>>) {
- fn go<'a, E>(
- e: &'a Expr<E>,
- vec: &mut Vec<LetBinding<'a, E>>,
- ) -> &'a Expr<E> {
- match e.as_ref() {
- ExprF::Let(l, t, v, e) => {
- vec.push((l, t, v));
- go(e, vec)
- }
- _ => e,
- }
- }
- let mut vec = vec![];
- let e = go(e, &mut vec);
- (e, vec)
-}
diff --git a/dhall/src/syntax/binary/encode.rs b/dhall/src/syntax/binary/encode.rs
new file mode 100644
index 0000000..8e13efd
--- /dev/null
+++ b/dhall/src/syntax/binary/encode.rs
@@ -0,0 +1,319 @@
+use serde_cbor::value::value as cbor;
+use std::vec;
+
+use crate::semantics::error::EncodeError;
+use crate::syntax;
+use crate::syntax::map::DupTreeMap;
+use crate::syntax::{
+ Expr, ExprF, FilePrefix, Hash, Import, ImportLocation, ImportMode, Label,
+ Scheme, V,
+};
+
+/// Warning: will fail if `expr` contains an `Embed` node.
+pub(crate) fn encode<E>(expr: &Expr<E>) -> Result<Vec<u8>, EncodeError> {
+ serde_cbor::ser::to_vec(&Serialize::Expr(expr))
+ .map_err(|e| EncodeError::CBORError(e))
+}
+
+enum Serialize<'a, E> {
+ Expr(&'a Expr<E>),
+ CBOR(cbor::Value),
+ RecordMap(&'a DupTreeMap<Label, Expr<E>>),
+ UnionMap(&'a DupTreeMap<Label, Option<Expr<E>>>),
+}
+
+macro_rules! count {
+ (@replace_with $_t:tt $sub:expr) => { $sub };
+ ($($tts:tt)*) => {0usize $(+ count!(@replace_with $tts 1usize))*};
+}
+
+macro_rules! ser_seq {
+ ($ser:expr; $($elt:expr),* $(,)?) => {{
+ use serde::ser::SerializeSeq;
+ let count = count!($($elt)*);
+ let mut ser_seq = $ser.serialize_seq(Some(count))?;
+ $(
+ ser_seq.serialize_element(&$elt)?;
+ )*
+ ser_seq.end()
+ }};
+}
+
+fn serialize_subexpr<S, E>(ser: S, e: &Expr<E>) -> Result<S::Ok, S::Error>
+where
+ S: serde::ser::Serializer,
+{
+ use cbor::Value::{String, I64, U64};
+ use std::iter::once;
+ use syntax::Builtin;
+ use syntax::ExprF::*;
+
+ use self::Serialize::{RecordMap, UnionMap};
+ fn expr<E>(x: &Expr<E>) -> self::Serialize<'_, E> {
+ self::Serialize::Expr(x)
+ }
+ let cbor =
+ |v: cbor::Value| -> self::Serialize<'_, E> { self::Serialize::CBOR(v) };
+ let tag = |x: u64| cbor(U64(x));
+ let null = || cbor(cbor::Value::Null);
+ let label = |l: &Label| cbor(cbor::Value::String(l.into()));
+
+ match e.as_ref() {
+ Const(c) => ser.serialize_str(&c.to_string()),
+ Builtin(b) => ser.serialize_str(&b.to_string()),
+ BoolLit(b) => ser.serialize_bool(*b),
+ NaturalLit(n) => ser_seq!(ser; tag(15), U64(*n as u64)),
+ IntegerLit(n) => ser_seq!(ser; tag(16), I64(*n as i64)),
+ DoubleLit(n) => {
+ let n: f64 = (*n).into();
+ ser.serialize_f64(n)
+ }
+ BoolIf(x, y, z) => ser_seq!(ser; tag(14), expr(x), expr(y), expr(z)),
+ Var(V(l, n)) if l == &"_".into() => ser.serialize_u64(*n as u64),
+ Var(V(l, n)) => ser_seq!(ser; label(l), U64(*n as u64)),
+ Lam(l, x, y) if l == &"_".into() => {
+ ser_seq!(ser; tag(1), expr(x), expr(y))
+ }
+ Lam(l, x, y) => ser_seq!(ser; tag(1), label(l), expr(x), expr(y)),
+ Pi(l, x, y) if l == &"_".into() => {
+ ser_seq!(ser; tag(2), expr(x), expr(y))
+ }
+ Pi(l, x, y) => ser_seq!(ser; tag(2), label(l), expr(x), expr(y)),
+ Let(_, _, _, _) => {
+ let (bound_e, bindings) = collect_nested_lets(e);
+ let count = 1 + 3 * bindings.len() + 1;
+
+ use serde::ser::SerializeSeq;
+ let mut ser_seq = ser.serialize_seq(Some(count))?;
+ ser_seq.serialize_element(&tag(25))?;
+ for (l, t, v) in bindings {
+ ser_seq.serialize_element(&label(l))?;
+ match t {
+ Some(t) => ser_seq.serialize_element(&expr(t))?,
+ None => ser_seq.serialize_element(&null())?,
+ }
+ ser_seq.serialize_element(&expr(v))?;
+ }
+ ser_seq.serialize_element(&expr(bound_e))?;
+ ser_seq.end()
+ }
+ App(_, _) => {
+ let (f, args) = collect_nested_applications(e);
+ ser.collect_seq(
+ once(tag(0))
+ .chain(once(expr(f)))
+ .chain(args.into_iter().rev().map(expr)),
+ )
+ }
+ Annot(x, y) => ser_seq!(ser; tag(26), expr(x), expr(y)),
+ Assert(x) => ser_seq!(ser; tag(19), expr(x)),
+ SomeLit(x) => ser_seq!(ser; tag(5), null(), expr(x)),
+ EmptyListLit(x) => match x.as_ref() {
+ App(f, a) => match f.as_ref() {
+ ExprF::Builtin(Builtin::List) => ser_seq!(ser; tag(4), expr(a)),
+ _ => ser_seq!(ser; tag(28), expr(x)),
+ },
+ _ => ser_seq!(ser; tag(28), expr(x)),
+ },
+ NEListLit(xs) => ser.collect_seq(
+ once(tag(4)).chain(once(null())).chain(xs.iter().map(expr)),
+ ),
+ TextLit(xs) => {
+ use syntax::InterpolatedTextContents::{Expr, Text};
+ ser.collect_seq(once(tag(18)).chain(xs.iter().map(|x| match x {
+ Expr(x) => expr(x),
+ Text(x) => cbor(String(x.clone())),
+ })))
+ }
+ RecordType(map) => ser_seq!(ser; tag(7), RecordMap(map)),
+ RecordLit(map) => ser_seq!(ser; tag(8), RecordMap(map)),
+ UnionType(map) => ser_seq!(ser; tag(11), UnionMap(map)),
+ Field(x, l) => ser_seq!(ser; tag(9), expr(x), label(l)),
+ BinOp(op, x, y) => {
+ use syntax::BinOp::*;
+ let op = match op {
+ BoolOr => 0,
+ BoolAnd => 1,
+ BoolEQ => 2,
+ BoolNE => 3,
+ NaturalPlus => 4,
+ NaturalTimes => 5,
+ TextAppend => 6,
+ ListAppend => 7,
+ RecursiveRecordMerge => 8,
+ RightBiasedRecordMerge => 9,
+ RecursiveRecordTypeMerge => 10,
+ ImportAlt => 11,
+ Equivalence => 12,
+ };
+ ser_seq!(ser; tag(3), U64(op), expr(x), expr(y))
+ }
+ Merge(x, y, None) => ser_seq!(ser; tag(6), expr(x), expr(y)),
+ Merge(x, y, Some(z)) => {
+ ser_seq!(ser; tag(6), expr(x), expr(y), expr(z))
+ }
+ ToMap(x, None) => ser_seq!(ser; tag(27), expr(x)),
+ ToMap(x, Some(y)) => ser_seq!(ser; tag(27), expr(x), expr(y)),
+ Projection(x, ls) => ser.collect_seq(
+ once(tag(10))
+ .chain(once(expr(x)))
+ .chain(ls.iter().map(label)),
+ ),
+ ProjectionByExpr(x, y) => {
+ ser_seq!(ser; tag(10), expr(x), vec![expr(y)])
+ }
+ Import(import) => serialize_import(ser, import),
+ Embed(_) => unimplemented!(
+ "An expression with resolved imports cannot be binary-encoded"
+ ),
+ }
+}
+
+fn serialize_import<S, E>(
+ ser: S,
+ import: &Import<Expr<E>>,
+) -> Result<S::Ok, S::Error>
+where
+ S: serde::ser::Serializer,
+{
+ use cbor::Value::{Bytes, Null, U64};
+ use serde::ser::SerializeSeq;
+
+ let count = 4 + match &import.location {
+ ImportLocation::Remote(url) => 3 + url.path.file_path.len(),
+ ImportLocation::Local(_, path) => path.file_path.len(),
+ ImportLocation::Env(_) => 1,
+ ImportLocation::Missing => 0,
+ };
+ let mut ser_seq = ser.serialize_seq(Some(count))?;
+
+ ser_seq.serialize_element(&U64(24))?;
+
+ let hash = match &import.hash {
+ None => Null,
+ Some(Hash::SHA256(h)) => {
+ let mut bytes = vec![18, 32];
+ bytes.extend_from_slice(h);
+ Bytes(bytes)
+ }
+ };
+ ser_seq.serialize_element(&hash)?;
+
+ let mode = match import.mode {
+ ImportMode::Code => 0,
+ ImportMode::RawText => 1,
+ ImportMode::Location => 2,
+ };
+ ser_seq.serialize_element(&U64(mode))?;
+
+ let scheme = match &import.location {
+ ImportLocation::Remote(url) => match url.scheme {
+ Scheme::HTTP => 0,
+ Scheme::HTTPS => 1,
+ },
+ ImportLocation::Local(prefix, _) => match prefix {
+ FilePrefix::Absolute => 2,
+ FilePrefix::Here => 3,
+ FilePrefix::Parent => 4,
+ FilePrefix::Home => 5,
+ },
+ ImportLocation::Env(_) => 6,
+ ImportLocation::Missing => 7,
+ };
+ ser_seq.serialize_element(&U64(scheme))?;
+
+ match &import.location {
+ ImportLocation::Remote(url) => {
+ match &url.headers {
+ None => ser_seq.serialize_element(&Null)?,
+ Some(e) => {
+ ser_seq.serialize_element(&self::Serialize::Expr(e))?
+ }
+ };
+ ser_seq.serialize_element(&url.authority)?;
+ for p in url.path.file_path.iter() {
+ ser_seq.serialize_element(&p)?;
+ }
+ match &url.query {
+ None => ser_seq.serialize_element(&Null)?,
+ Some(x) => ser_seq.serialize_element(x)?,
+ };
+ }
+ ImportLocation::Local(_, path) => {
+ for p in path.file_path.iter() {
+ ser_seq.serialize_element(&p)?;
+ }
+ }
+ ImportLocation::Env(env) => {
+ ser_seq.serialize_element(env)?;
+ }
+ ImportLocation::Missing => {}
+ }
+
+ ser_seq.end()
+}
+
+impl<'a, E> serde::ser::Serialize for Serialize<'a, E> {
+ fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::ser::Serializer,
+ {
+ match self {
+ Serialize::Expr(e) => serialize_subexpr(ser, e),
+ Serialize::CBOR(v) => v.serialize(ser),
+ Serialize::RecordMap(map) => {
+ ser.collect_map(map.iter().map(|(k, v)| {
+ (cbor::Value::String(k.into()), Serialize::Expr(v))
+ }))
+ }
+ Serialize::UnionMap(map) => {
+ ser.collect_map(map.iter().map(|(k, v)| {
+ let v = match v {
+ Some(x) => Serialize::Expr(x),
+ None => Serialize::CBOR(cbor::Value::Null),
+ };
+ (cbor::Value::String(k.into()), v)
+ }))
+ }
+ }
+ }
+}
+
+fn collect_nested_applications<'a, E>(
+ e: &'a Expr<E>,
+) -> (&'a Expr<E>, Vec<&'a Expr<E>>) {
+ fn go<'a, E>(e: &'a Expr<E>, vec: &mut Vec<&'a Expr<E>>) -> &'a Expr<E> {
+ match e.as_ref() {
+ ExprF::App(f, a) => {
+ vec.push(a);
+ go(f, vec)
+ }
+ _ => e,
+ }
+ }
+ let mut vec = vec![];
+ let e = go(e, &mut vec);
+ (e, vec)
+}
+
+type LetBinding<'a, E> = (&'a Label, &'a Option<Expr<E>>, &'a Expr<E>);
+
+fn collect_nested_lets<'a, E>(
+ e: &'a Expr<E>,
+) -> (&'a Expr<E>, Vec<LetBinding<'a, E>>) {
+ fn go<'a, E>(
+ e: &'a Expr<E>,
+ vec: &mut Vec<LetBinding<'a, E>>,
+ ) -> &'a Expr<E> {
+ match e.as_ref() {
+ ExprF::Let(l, t, v, e) => {
+ vec.push((l, t, v));
+ go(e, vec)
+ }
+ _ => e,
+ }
+ }
+ let mut vec = vec![];
+ let e = go(e, &mut vec);
+ (e, vec)
+}
diff --git a/dhall/src/syntax/binary/mod.rs b/dhall/src/syntax/binary/mod.rs
new file mode 100644
index 0000000..7ed1f6e
--- /dev/null
+++ b/dhall/src/syntax/binary/mod.rs
@@ -0,0 +1,4 @@
+mod decode;
+mod encode;
+pub(crate) use decode::decode;
+pub(crate) use encode::encode;
diff --git a/dhall_syntax/src/core/context.rs b/dhall/src/syntax/core/context.rs
index 6844baa..6844baa 100644
--- a/dhall_syntax/src/core/context.rs
+++ b/dhall/src/syntax/core/context.rs
diff --git a/dhall_syntax/src/core/expr.rs b/dhall/src/syntax/core/expr.rs
index 131f97e..5b9f401 100644
--- a/dhall_syntax/src/core/expr.rs
+++ b/dhall/src/syntax/core/expr.rs
@@ -1,6 +1,6 @@
-use crate::map::{DupTreeMap, DupTreeSet};
-use crate::visitor::{self, ExprFMutVisitor, ExprFVisitor};
-use crate::*;
+use crate::syntax::map::{DupTreeMap, DupTreeSet};
+use crate::syntax::visitor::{self, ExprFMutVisitor, ExprFVisitor};
+use crate::syntax::*;
pub type Integer = isize;
pub type Natural = usize;
@@ -351,7 +351,7 @@ impl<E> Expr<E> {
}
/// Add an isize to an usize
-/// Panics on over/underflow
+/// Returns `None` on over/underflow
fn add_ui(u: usize, i: isize) -> Option<usize> {
Some(if i < 0 {
u.checked_sub(i.checked_neg()? as usize)?
diff --git a/dhall_syntax/src/core/import.rs b/dhall/src/syntax/core/import.rs
index da3e99b..da3e99b 100644
--- a/dhall_syntax/src/core/import.rs
+++ b/dhall/src/syntax/core/import.rs
diff --git a/dhall_syntax/src/core/label.rs b/dhall/src/syntax/core/label.rs
index 43c3f53..43c3f53 100644
--- a/dhall_syntax/src/core/label.rs
+++ b/dhall/src/syntax/core/label.rs
diff --git a/dhall_syntax/src/core/map.rs b/dhall/src/syntax/core/map.rs
index c4c6126..c4c6126 100644
--- a/dhall_syntax/src/core/map.rs
+++ b/dhall/src/syntax/core/map.rs
diff --git a/dhall_syntax/src/core/mod.rs b/dhall/src/syntax/core/mod.rs
index 66bf229..66bf229 100644
--- a/dhall_syntax/src/core/mod.rs
+++ b/dhall/src/syntax/core/mod.rs
diff --git a/dhall_syntax/src/core/span.rs b/dhall/src/syntax/core/span.rs
index f9c7008..f9c7008 100644
--- a/dhall_syntax/src/core/span.rs
+++ b/dhall/src/syntax/core/span.rs
diff --git a/dhall_syntax/src/core/text.rs b/dhall/src/syntax/core/text.rs
index fb390ee..fb390ee 100644
--- a/dhall_syntax/src/core/text.rs
+++ b/dhall/src/syntax/core/text.rs
diff --git a/dhall_syntax/src/core/visitor.rs b/dhall/src/syntax/core/visitor.rs
index 143e556..b76d037 100644
--- a/dhall_syntax/src/core/visitor.rs
+++ b/dhall/src/syntax/core/visitor.rs
@@ -1,4 +1,4 @@
-use crate::*;
+use crate::syntax::*;
use std::iter::FromIterator;
/// A visitor trait that can be used to traverse `ExprF`s. We need this pattern so that Rust lets
@@ -111,7 +111,7 @@ where
.collect()
}
- use crate::ExprF::*;
+ use crate::syntax::ExprF::*;
Ok(match input {
Var(v) => Var(v.clone()),
Lam(l, t, e) => {
@@ -225,7 +225,7 @@ where
Ok(())
}
- use crate::ExprF::*;
+ use crate::syntax::ExprF::*;
match input {
Var(_) | Const(_) | Builtin(_) | BoolLit(_) | NaturalLit(_)
| IntegerLit(_) | DoubleLit(_) => {}
diff --git a/dhall/src/syntax/mod.rs b/dhall/src/syntax/mod.rs
new file mode 100644
index 0000000..a82e827
--- /dev/null
+++ b/dhall/src/syntax/mod.rs
@@ -0,0 +1,15 @@
+#![allow(
+ clippy::many_single_char_names,
+ clippy::should_implement_trait,
+ clippy::new_without_default,
+ clippy::type_complexity
+)]
+
+mod core;
+pub use crate::syntax::core::context;
+pub use crate::syntax::core::visitor;
+pub use crate::syntax::core::*;
+pub use crate::syntax::text::parser::*;
+pub use crate::syntax::text::printer::*;
+pub mod binary;
+pub mod text;
diff --git a/dhall/src/syntax/text/mod.rs b/dhall/src/syntax/text/mod.rs
new file mode 100644
index 0000000..c868288
--- /dev/null
+++ b/dhall/src/syntax/text/mod.rs
@@ -0,0 +1,2 @@
+pub mod parser;
+pub mod printer;
diff --git a/dhall_syntax/src/parser.rs b/dhall/src/syntax/text/parser.rs
index f5d161f..f6b6577 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall/src/syntax/text/parser.rs
@@ -3,36 +3,42 @@ use pest::prec_climber as pcl;
use pest::prec_climber::PrecClimber;
use std::rc::Rc;
-use dgp::Rule;
-use dhall_generated_parser as dgp;
use pest_consume::{match_nodes, Parser};
-use crate::map::{DupTreeMap, DupTreeSet};
-use crate::ExprF::*;
-use crate::*;
+use crate::semantics::phase::Normalized;
+use crate::syntax;
+use crate::syntax::core;
+use crate::syntax::map::{DupTreeMap, DupTreeSet};
+use crate::syntax::ExprF::*;
+use crate::syntax::{
+ FilePath, FilePrefix, Hash, ImportLocation, ImportMode, InterpolatedText,
+ InterpolatedTextContents, Label, NaiveDouble, RawExpr, Scheme, Span, URL,
+ V,
+};
// This file consumes the parse tree generated by pest and turns it into
// our own AST. All those custom macros should eventually moved into
// their own crate because they are quite general and useful. For now they
// are here and hopefully you can figure out how they work.
-type ParsedText<E> = InterpolatedText<Expr<E>>;
-type ParsedTextContents<E> = InterpolatedTextContents<Expr<E>>;
+type Expr = syntax::Expr<Normalized>;
+type ParsedText = InterpolatedText<Expr>;
+type ParsedTextContents = InterpolatedTextContents<Expr>;
type ParseInput<'input> = pest_consume::Node<'input, Rule, Rc<str>>;
pub type ParseError = pest::error::Error<Rule>;
pub type ParseResult<T> = Result<T, ParseError>;
#[derive(Debug)]
-enum Selector<E> {
+enum Selector {
Field(Label),
Projection(DupTreeSet<Label>),
- ProjectionByExpr(Expr<E>),
+ ProjectionByExpr(Expr),
}
-impl crate::Builtin {
+impl crate::syntax::Builtin {
pub fn parse(s: &str) -> Option<Self> {
- use crate::Builtin::*;
+ use crate::syntax::Builtin::*;
match s {
"Bool" => Some(Bool),
"Natural" => Some(Natural),
@@ -71,16 +77,16 @@ impl crate::Builtin {
fn input_to_span(input: ParseInput) -> Span {
Span::make(input.user_data().clone(), input.as_pair().as_span())
}
-fn spanned<E>(input: ParseInput, x: RawExpr<E>) -> Expr<E> {
+fn spanned(input: ParseInput, x: RawExpr<Normalized>) -> Expr {
Expr::new(x, input_to_span(input))
}
-fn spanned_union<E>(span1: Span, span2: Span, x: RawExpr<E>) -> Expr<E> {
+fn spanned_union(span1: Span, span2: Span, x: RawExpr<Normalized>) -> Expr {
Expr::new(x, span1.union(&span2))
}
// Trim the shared indent off of a vec of lines, as defined by the Dhall semantics of multiline
// literals.
-fn trim_indent<E: Clone>(lines: &mut Vec<ParsedText<E>>) {
+fn trim_indent(lines: &mut Vec<ParsedText>) {
let is_indent = |c: char| c == ' ' || c == '\t';
// There is at least one line so this is safe
@@ -147,9 +153,11 @@ lazy_static::lazy_static! {
};
}
+#[derive(Parser)]
+#[grammar = "dhall.pest"]
struct DhallParser;
-#[pest_consume::parser(parser = dgp::DhallParser, rule = dgp::Rule)]
+#[pest_consume::parser(parser = DhallParser, rule = Rule)]
impl DhallParser {
fn EOI(_input: ParseInput) -> ParseResult<()> {
Ok(())
@@ -164,9 +172,7 @@ impl DhallParser {
Ok(Label::from(input.as_str()))
}
- fn double_quote_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ParsedText<E>> {
+ fn double_quote_literal(input: ParseInput) -> ParseResult<ParsedText> {
Ok(match_nodes!(input.into_children();
[double_quote_chunk(chunks)..] => {
chunks.collect()
@@ -174,9 +180,9 @@ impl DhallParser {
))
}
- fn double_quote_chunk<E: Clone>(
+ fn double_quote_chunk(
input: ParseInput,
- ) -> ParseResult<ParsedTextContents<E>> {
+ ) -> ParseResult<ParsedTextContents> {
Ok(match_nodes!(input.into_children();
[expression(e)] => {
InterpolatedTextContents::Expr(e)
@@ -261,18 +267,16 @@ impl DhallParser {
Ok(input.as_str().to_owned())
}
- fn single_quote_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ParsedText<E>> {
+ fn single_quote_literal(input: ParseInput) -> ParseResult<ParsedText> {
Ok(match_nodes!(input.into_children();
[single_quote_continue(lines)] => {
- let newline: ParsedText<E> = "\n".to_string().into();
+ let newline: ParsedText = "\n".to_string().into();
// Reverse lines and chars in each line
- let mut lines: Vec<ParsedText<E>> = lines
+ let mut lines: Vec<ParsedText> = lines
.into_iter()
.rev()
- .map(|l| l.into_iter().rev().collect::<ParsedText<E>>())
+ .map(|l| l.into_iter().rev().collect::<ParsedText>())
.collect();
trim_indent(&mut lines);
@@ -281,7 +285,7 @@ impl DhallParser {
.into_iter()
.intersperse(newline)
.flat_map(InterpolatedText::into_iter)
- .collect::<ParsedText<E>>()
+ .collect::<ParsedText>()
}
))
}
@@ -298,9 +302,9 @@ impl DhallParser {
}
// Returns a vec of lines in reversed order, where each line is also in reversed order.
- fn single_quote_continue<E: Clone>(
+ fn single_quote_continue(
input: ParseInput,
- ) -> ParseResult<Vec<Vec<ParsedTextContents<E>>>> {
+ ) -> ParseResult<Vec<Vec<ParsedTextContents>>> {
Ok(match_nodes!(input.into_children();
[expression(e), single_quote_continue(lines)] => {
let c = InterpolatedTextContents::Expr(e);
@@ -326,16 +330,16 @@ impl DhallParser {
}
#[alias(expression)]
- fn builtin<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn builtin(input: ParseInput) -> ParseResult<Expr> {
let s = input.as_str();
- let e = match crate::Builtin::parse(s) {
+ let e = match crate::syntax::Builtin::parse(s) {
Some(b) => Builtin(b),
None => match s {
"True" => BoolLit(true),
"False" => BoolLit(false),
- "Type" => Const(crate::Const::Type),
- "Kind" => Const(crate::Const::Kind),
- "Sort" => Const(crate::Const::Sort),
+ "Type" => Const(crate::syntax::Const::Type),
+ "Kind" => Const(crate::syntax::Const::Kind),
+ "Sort" => Const(crate::syntax::Const::Sort),
_ => {
Err(input.error(format!("Unrecognized builtin: '{}'", s)))?
}
@@ -387,7 +391,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn identifier<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn identifier(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[variable(v)] => spanned(input, Var(v)),
[expression(e)] => e,
@@ -441,9 +445,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn local<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn local(input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(match_nodes!(input.into_children();
[local_path((prefix, p))] => ImportLocation::Local(prefix, p),
))
@@ -482,7 +484,7 @@ impl DhallParser {
})
}
- fn http_raw<E: Clone>(input: ParseInput) -> ParseResult<URL<Expr<E>>> {
+ fn http_raw(input: ParseInput) -> ParseResult<URL<Expr>> {
Ok(match_nodes!(input.into_children();
[scheme(sch), authority(auth), path(p)] => URL {
scheme: sch,
@@ -510,9 +512,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn http<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn http(input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(ImportLocation::Remote(match_nodes!(input.into_children();
[http_raw(url)] => url,
[http_raw(url), expression(e)] => URL { headers: Some(e), ..url },
@@ -520,9 +520,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn env<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn env(input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(match_nodes!(input.into_children();
[environment_variable(v)] => ImportLocation::Env(v),
))
@@ -557,9 +555,7 @@ impl DhallParser {
}
#[alias(import_type)]
- fn missing<E: Clone>(
- _input: ParseInput,
- ) -> ParseResult<ImportLocation<Expr<E>>> {
+ fn missing(_input: ParseInput) -> ParseResult<ImportLocation<Expr>> {
Ok(ImportLocation::Missing)
}
@@ -573,10 +569,10 @@ impl DhallParser {
Ok(Hash::SHA256(hex::decode(hash).unwrap()))
}
- fn import_hashed<E: Clone>(
+ fn import_hashed(
input: ParseInput,
- ) -> ParseResult<crate::Import<Expr<E>>> {
- use crate::Import;
+ ) -> ParseResult<crate::syntax::Import<Expr>> {
+ use crate::syntax::Import;
let mode = ImportMode::Code;
Ok(match_nodes!(input.into_children();
[import_type(location)] => Import { mode, location, hash: None },
@@ -594,8 +590,8 @@ impl DhallParser {
}
#[alias(expression)]
- fn import<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
- use crate::Import;
+ fn import(input: ParseInput) -> ParseResult<Expr> {
+ use crate::syntax::Import;
let import = match_nodes!(input.children();
[import_hashed(imp)] => {
Import { mode: ImportMode::Code, ..imp }
@@ -630,13 +626,13 @@ impl DhallParser {
}
#[alias(expression)]
- fn empty_list_literal<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn empty_list_literal(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => spanned(input, EmptyListLit(e)),
))
}
- fn expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[lambda(()), label(l), expression(typ),
arrow(()), expression(body)] => {
@@ -681,9 +677,9 @@ impl DhallParser {
))
}
- fn let_binding<E: Clone>(
+ fn let_binding(
input: ParseInput,
- ) -> ParseResult<(Label, Option<Expr<E>>, Expr<E>, Span)> {
+ ) -> ParseResult<(Label, Option<Expr>, Expr, Span)> {
Ok(match_nodes!(input.children();
[label(name), expression(annot), expression(expr)] =>
(name, Some(annot), expr, input_to_span(input)),
@@ -694,12 +690,12 @@ impl DhallParser {
#[alias(expression, shortcut = true)]
#[prec_climb(expression, PRECCLIMBER)]
- fn operator_expression<E: Clone>(
- l: Expr<E>,
+ fn operator_expression(
+ l: Expr,
op: ParseInput,
- r: Expr<E>,
- ) -> ParseResult<Expr<E>> {
- use crate::BinOp::*;
+ r: Expr,
+ ) -> ParseResult<Expr> {
+ use crate::syntax::BinOp::*;
use Rule::*;
let op = match op.as_rule() {
import_alt => ImportAlt,
@@ -726,9 +722,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn application_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn application_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => e,
[expression(first), expression(rest)..] => {
@@ -747,9 +741,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn first_application_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn first_application_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[Some_(()), expression(e)] => {
spanned(input, SomeLit(e))
@@ -765,9 +757,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn selector_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn selector_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => e,
[expression(first), selector(rest)..] => {
@@ -789,9 +779,7 @@ impl DhallParser {
))
}
- fn selector<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<(Selector<E>, Span)> {
+ fn selector(input: ParseInput) -> ParseResult<(Selector, Span)> {
let stor = match_nodes!(input.children();
[label(l)] => Selector::Field(l),
[labels(ls)] => Selector::Projection(ls),
@@ -807,9 +795,7 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
- fn primitive_expression<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn primitive_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[double_literal(n)] => spanned(input, DoubleLit(n)),
[natural_literal(n)] => spanned(input, NaturalLit(n)),
@@ -821,21 +807,19 @@ impl DhallParser {
}
#[alias(expression)]
- fn empty_record_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn empty_record_literal(input: ParseInput) -> ParseResult<Expr> {
Ok(spanned(input, RecordLit(Default::default())))
}
#[alias(expression)]
- fn empty_record_type<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn empty_record_type(input: ParseInput) -> ParseResult<Expr> {
Ok(spanned(input, RecordType(Default::default())))
}
#[alias(expression)]
- fn non_empty_record_type_or_literal<E: Clone>(
+ fn non_empty_record_type_or_literal(
input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ ) -> ParseResult<Expr> {
let e = match_nodes!(input.children();
[label(first_label), non_empty_record_type(rest)] => {
let (first_expr, mut map) = rest;
@@ -851,9 +835,9 @@ impl DhallParser {
Ok(spanned(input, e))
}
- fn non_empty_record_type<E: Clone>(
+ fn non_empty_record_type(
input: ParseInput,
- ) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> {
+ ) -> ParseResult<(Expr, DupTreeMap<Label, Expr>)> {
Ok(match_nodes!(input.into_children();
[expression(expr), record_type_entry(entries)..] => {
(expr, entries.collect())
@@ -861,17 +845,15 @@ impl DhallParser {
))
}
- fn record_type_entry<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<(Label, Expr<E>)> {
+ fn record_type_entry(input: ParseInput) -> ParseResult<(Label, Expr)> {
Ok(match_nodes!(input.into_children();
[label(name), expression(expr)] => (name, expr)
))
}
- fn non_empty_record_literal<E: Clone>(
+ fn non_empty_record_literal(
input: ParseInput,
- ) -> ParseResult<(Expr<E>, DupTreeMap<Label, Expr<E>>)> {
+ ) -> ParseResult<(Expr, DupTreeMap<Label, Expr>)> {
Ok(match_nodes!(input.into_children();
[expression(expr), record_literal_entry(entries)..] => {
(expr, entries.collect())
@@ -879,16 +861,14 @@ impl DhallParser {
))
}
- fn record_literal_entry<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<(Label, Expr<E>)> {
+ fn record_literal_entry(input: ParseInput) -> ParseResult<(Label, Expr)> {
Ok(match_nodes!(input.into_children();
[label(name), expression(expr)] => (name, expr)
))
}
#[alias(expression)]
- fn union_type<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn union_type(input: ParseInput) -> ParseResult<Expr> {
let map = match_nodes!(input.children();
[empty_union_type(_)] => Default::default(),
[union_type_entry(entries)..] => entries.collect(),
@@ -900,9 +880,9 @@ impl DhallParser {
Ok(())
}
- fn union_type_entry<E: Clone>(
+ fn union_type_entry(
input: ParseInput,
- ) -> ParseResult<(Label, Option<Expr<E>>)> {
+ ) -> ParseResult<(Label, Option<Expr>)> {
Ok(match_nodes!(input.children();
[label(name), expression(expr)] => (name, Some(expr)),
[label(name)] => (name, None),
@@ -910,9 +890,7 @@ impl DhallParser {
}
#[alias(expression)]
- fn non_empty_list_literal<E: Clone>(
- input: ParseInput,
- ) -> ParseResult<Expr<E>> {
+ fn non_empty_list_literal(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(items)..] => spanned(
input,
@@ -922,14 +900,14 @@ impl DhallParser {
}
#[alias(expression)]
- fn final_expression<E: Clone>(input: ParseInput) -> ParseResult<Expr<E>> {
+ fn final_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.into_children();
[expression(e), EOI(_)] => e
))
}
}
-pub fn parse_expr<E: Clone>(input_str: &str) -> ParseResult<Expr<E>> {
+pub fn parse_expr(input_str: &str) -> ParseResult<Expr> {
let rc_input_str = input_str.to_string().into();
let inputs = DhallParser::parse_with_userdata(
Rule::final_expression,
diff --git a/dhall_syntax/src/printer.rs b/dhall/src/syntax/text/printer.rs
index ce6ff97..8df456b 100644
--- a/dhall_syntax/src/printer.rs
+++ b/dhall/src/syntax/text/printer.rs
@@ -1,11 +1,11 @@
-use crate::*;
+use crate::syntax::*;
use itertools::Itertools;
use std::fmt::{self, Display};
/// Generic instance that delegates to subexpressions
impl<SE: Display + Clone, E: Display> Display for ExprF<SE, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- use crate::ExprF::*;
+ use crate::syntax::ExprF::*;
match self {
Lam(a, b, c) => {
write!(f, "λ({} : {}) → {}", a, b, c)?;
@@ -141,7 +141,7 @@ impl<A: Display + Clone> RawExpr<A> {
f: &mut fmt::Formatter,
phase: PrintPhase,
) -> Result<(), fmt::Error> {
- use crate::ExprF::*;
+ use crate::syntax::ExprF::*;
use PrintPhase::*;
let needs_paren = match self {
@@ -298,7 +298,7 @@ impl Display for Const {
impl Display for BinOp {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- use crate::BinOp::*;
+ use crate::syntax::BinOp::*;
f.write_str(match self {
BoolOr => "||",
TextAppend => "++",
@@ -344,7 +344,7 @@ impl Display for Label {
let is_reserved = match s.as_str() {
"let" | "in" | "if" | "then" | "else" | "Type" | "Kind"
| "Sort" | "True" | "False" => true,
- _ => crate::Builtin::parse(&s).is_some(),
+ _ => crate::syntax::Builtin::parse(&s).is_some(),
};
if !is_reserved && s.chars().all(|c| c.is_ascii_alphanumeric()) {
write!(f, "{}", s)
@@ -443,7 +443,7 @@ impl<SubExpr: Display> Display for Import<SubExpr> {
impl Display for Builtin {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- use crate::Builtin::*;
+ use crate::syntax::Builtin::*;
f.write_str(match *self {
Bool => "Bool",
Natural => "Natural",
@@ -480,7 +480,7 @@ impl Display for Builtin {
impl Display for Scheme {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- use crate::Scheme::*;
+ use crate::syntax::Scheme::*;
f.write_str(match *self {
HTTP => "http",
HTTPS => "https",
diff --git a/dhall/src/tests.rs b/dhall/src/tests.rs
index 1037ef9..9e5c744 100644
--- a/dhall/src/tests.rs
+++ b/dhall/src/tests.rs
@@ -47,8 +47,8 @@ use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;
-use crate::error::{Error, Result};
-use crate::phase::Parsed;
+use crate::semantics::error::{Error, Result};
+use crate::semantics::phase::Parsed;
#[allow(dead_code)]
#[derive(Clone)]
diff --git a/dhall_generated_parser/Cargo.toml b/dhall_generated_parser/Cargo.toml
deleted file mode 100644
index b1f0d02..0000000
--- a/dhall_generated_parser/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "dhall_generated_parser"
-version = "0.1.0"
-authors = ["Nadrieril <nadrieril@users.noreply.github.com>"]
-license = "BSD-2-Clause"
-edition = "2018"
-build = "build.rs"
-
-[lib]
-test = false
-doctest = false
-
-[build-dependencies]
-abnf_to_pest = { version = "0.1.1", path = "../abnf_to_pest" }
-
-[dependencies]
-pest = "2.1"
-pest_derive = "2.1"
diff --git a/dhall_generated_parser/build.rs b/dhall_generated_parser/build.rs
deleted file mode 100644
index d846f92..0000000
--- a/dhall_generated_parser/build.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-use std::fs::File;
-use std::io::{BufRead, BufReader, Read, Write};
-
-use abnf_to_pest::render_rules_to_pest;
-
-fn main() -> std::io::Result<()> {
- let abnf_path = "src/dhall.abnf";
- let visibility_path = "src/dhall.pest.visibility";
- let pest_path = "src/dhall.pest";
- println!("cargo:rerun-if-changed={}", abnf_path);
- println!("cargo:rerun-if-changed={}", visibility_path);
-
- let mut file = File::open(abnf_path)?;
- let mut data = Vec::new();
- file.read_to_end(&mut data)?;
- data.push('\n' as u8);
-
- let mut rules = abnf_to_pest::parse_abnf(&data)?;
- for line in BufReader::new(File::open(visibility_path)?).lines() {
- let line = line?;
- if line.len() >= 2 && &line[0..2] == "# " {
- rules.get_mut(&line[2..]).map(|x| x.silent = true);
- }
- }
-
- let mut file = File::create(pest_path)?;
- writeln!(&mut file, "// AUTO-GENERATED FILE. See build.rs.")?;
-
- // 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 = {{
- keyword ~ simple_label_next_char+
- | !keyword ~ simple_label_first_char ~ simple_label_next_char*
- }}"
- )?;
-
- rules.remove("nonreserved_label");
- writeln!(
- &mut file,
- "nonreserved_label = _{{
- !(builtin ~ !simple_label_next_char) ~ label
- }}"
- )?;
-
- // Setup grammar for precedence climbing
- rules.remove("operator_expression");
- writeln!(&mut file, r##"
- import_alt = {{ "?" ~ whsp1 }}
- bool_or = {{ "||" }}
- natural_plus = {{ "+" ~ whsp1 }}
- text_append = {{ "++" }}
- list_append = {{ "#" }}
- bool_and = {{ "&&" }}
- natural_times = {{ "*" }}
- bool_eq = {{ "==" }}
- bool_ne = {{ "!=" }}
-
- operator = _{{
- equivalent |
- bool_ne |
- bool_eq |
- natural_times |
- combine_types |
- prefer |
- combine |
- bool_and |
- list_append |
- text_append |
- natural_plus |
- bool_or |
- import_alt
- }}
- operator_expression = {{ application_expression ~ (whsp ~ operator ~ whsp ~ application_expression)* }}
- "##)?;
-
- writeln!(
- &mut file,
- "final_expression = ${{ SOI ~ complete_expression ~ EOI }}"
- )?;
-
- writeln!(&mut file)?;
- writeln!(&mut file, "{}", render_rules_to_pest(rules).pretty(80))?;
-
- Ok(())
-}
diff --git a/dhall_generated_parser/src/lib.rs b/dhall_generated_parser/src/lib.rs
deleted file mode 100644
index fbb9ccd..0000000
--- a/dhall_generated_parser/src/lib.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-//! This crate only contains a [pest][pest]-generated parser for the [dhall][dhall] language.
-//! It is part of the [dhall-rust][dhall-rust] crate.
-//!
-//! [pest]: https://pest.rs
-//! [dhall]: https://dhall-lang.org/
-//! [dhall-rust]: https://github.com/Nadrieril/dhall-rust
-
-// This crate only contains the grammar-generated parser. The rest of the
-// parser is in dhall_syntax. This separation is because compiling the
-// grammar-generated parser is extremely slow.
-// See the https://pest.rs documentation for details on what this crate contains.
-// The pest file is auto-generated and is located at ./dhall.pest.
-// It is generated from grammar.abnf in a rather straightforward manner. Some
-// additional overrides are done in ../build.rs.
-// The lines that are commented out in ./dhall.pest.visibility are marked as
-// silent (see pest docs for what that means) in the generated pest file.
-
-use pest_derive::Parser;
-
-#[derive(Parser)]
-#[grammar = "dhall.pest"]
-pub struct DhallParser;
diff --git a/dhall_syntax/Cargo.toml b/dhall_syntax/Cargo.toml
deleted file mode 100644
index 2724fa5..0000000
--- a/dhall_syntax/Cargo.toml
+++ /dev/null
@@ -1,21 +0,0 @@
-[package]
-name = "dhall_syntax"
-version = "0.1.0"
-authors = ["NanoTech <nanotech@nanotechcorp.net>", "Nadrieril <nadrieril@users.noreply.github.com>"]
-license = "BSD-2-Clause"
-edition = "2018"
-
-[lib]
-doctest = false
-
-[dependencies]
-itertools = "0.8.0"
-percent-encoding = "2.1.0"
-pest = "2.1"
-either = "1.5.2"
-take_mut = "0.2.2"
-hex = "0.3.2"
-lazy_static = "1.4.0"
-dhall_generated_parser = { path = "../dhall_generated_parser" }
-# pest_consume = { path = "../../pest_consume/pest_consume" }
-pest_consume = "1.0"
diff --git a/dhall_syntax/src/lib.rs b/dhall_syntax/src/lib.rs
deleted file mode 100644
index b8fa19f..0000000
--- a/dhall_syntax/src/lib.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(trace_macros)]
-#![feature(never_type)]
-#![allow(
- clippy::many_single_char_names,
- clippy::should_implement_trait,
- clippy::new_without_default,
- clippy::type_complexity
-)]
-
-//! This crate contains the core AST-handling primitives for the [dhall-rust][dhall-rust] crate.
-//! This is highly unstable and breaks regularly; use at your own risk.
-//!
-//! [dhall-rust]: https://github.com/Nadrieril/dhall-rust
-
-mod core;
-pub use crate::core::context;
-pub use crate::core::visitor;
-pub use crate::core::*;
-mod printer;
-pub use crate::printer::*;
-mod parser;
-pub use crate::parser::*;
diff --git a/serde_dhall/Cargo.toml b/serde_dhall/Cargo.toml
index c61ddcd..9d46822 100644
--- a/serde_dhall/Cargo.toml
+++ b/serde_dhall/Cargo.toml
@@ -8,5 +8,4 @@ edition = "2018"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
dhall = { path = "../dhall" }
-dhall_syntax = { path = "../dhall_syntax" }
dhall_proc_macros = { path = "../dhall_proc_macros" }
diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs
index d371d6d..80ebaf8 100644
--- a/serde_dhall/src/lib.rs
+++ b/serde_dhall/src/lib.rs
@@ -122,8 +122,8 @@ pub use value::Value;
// A Dhall value.
pub mod value {
- use dhall::phase::{NormalizedExpr, Parsed, Typed};
- use dhall_syntax::Builtin;
+ use dhall::semantics::phase::{NormalizedExpr, Parsed, Typed};
+ use dhall::syntax::Builtin;
use super::de::{Error, Result};
@@ -138,7 +138,7 @@ pub mod value {
fn from_str_using_dhall_error_type(
s: &str,
ty: Option<&Value>,
- ) -> dhall::error::Result<Self> {
+ ) -> dhall::semantics::error::Result<Self> {
let resolved = Parsed::parse_str(s)?.resolve()?;
let typed = match ty {
None => resolved.typecheck()?,
@@ -193,7 +193,7 @@ pub mod de {
pub use error::{Error, Result};
mod error {
- use dhall::error::Error as DhallError;
+ use dhall::semantics::error::Error as DhallError;
pub type Result<T> = std::result::Result<T, Error>;
diff --git a/serde_dhall/src/serde.rs b/serde_dhall/src/serde.rs
index 26708c1..9006a08 100644
--- a/serde_dhall/src/serde.rs
+++ b/serde_dhall/src/serde.rs
@@ -1,7 +1,7 @@
use std::borrow::Cow;
-use dhall::phase::NormalizedExpr;
-use dhall_syntax::ExprF;
+use dhall::semantics::phase::NormalizedExpr;
+use dhall::syntax::ExprF;
use crate::de::{Deserialize, Error, Result};
use crate::Value;
diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs
index 67a7bc4..1323aa3 100644
--- a/serde_dhall/src/static_type.rs
+++ b/serde_dhall/src/static_type.rs
@@ -1,4 +1,4 @@
-use dhall_syntax::{Builtin, Integer, Natural};
+use dhall::syntax::{Builtin, Integer, Natural};
use crate::Value;