summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2019-03-06 23:35:39 +0100
committerNadrieril2019-03-06 23:35:39 +0100
commit54382cd107d1befd6015f8232716158a20db44a4 (patch)
tree81afc63e474ad58f384dde36550f9d50756c5217
parent39fc0af2548127a7c2ee1345d4ea63d473e0ab5a (diff)
Start parsing imports
-rw-r--r--dhall/src/imports.rs11
-rw-r--r--dhall/src/lib.rs2
-rw-r--r--dhall/src/main.rs4
-rw-r--r--dhall/src/normalize.rs2
-rw-r--r--dhall/tests/tests.rs2
-rw-r--r--dhall_core/src/core.rs83
-rw-r--r--dhall_core/src/grammar_util.rs4
-rw-r--r--dhall_core/src/parser.rs65
-rw-r--r--dhall_generator/src/lib.rs4
-rw-r--r--dhall_parser/src/dhall.abnf13
-rw-r--r--dhall_parser/src/dhall.pest.visibility2
11 files changed, 162 insertions, 30 deletions
diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs
new file mode 100644
index 0000000..32ddfd7
--- /dev/null
+++ b/dhall/src/imports.rs
@@ -0,0 +1,11 @@
+use dhall_core::{Expr, Import, ImportLocation, ImportMode, FilePrefix, X};
+
+
+// fn resolve_import(import: Import) -> Expr<X, Import> {
+
+// }
+
+pub fn resolve_imports<'i, S: Clone>(expr: &Expr<'i, S, Import>) -> Expr<'i, S, X> {
+ let no_import = |_: &Import| -> X { panic!("ahhh import") };
+ expr.map_embed(&no_import)
+}
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs
index 58b29a3..54f0983 100644
--- a/dhall/src/lib.rs
+++ b/dhall/src/lib.rs
@@ -5,4 +5,4 @@
mod normalize;
pub use crate::normalize::*;
pub mod typecheck;
-
+pub mod imports;
diff --git a/dhall/src/main.rs b/dhall/src/main.rs
index 3e8aca4..43d03ce 100644
--- a/dhall/src/main.rs
+++ b/dhall/src/main.rs
@@ -91,9 +91,7 @@ fn main() {
}
};
- /*
- expr' <- load expr
- */
+ let expr = imports::resolve_imports(&expr);
let type_expr = match typecheck::type_of(&expr) {
Err(e) => {
diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs
index ec594da..b46722a 100644
--- a/dhall/src/normalize.rs
+++ b/dhall/src/normalize.rs
@@ -145,7 +145,7 @@ where
},
// Normalize everything else before matching
- e => match e.map_shallow(normalize, |_| unreachable!()) {
+ e => match e.map_shallow(normalize, |_| unreachable!(), |x| x.clone()) {
BinOp(BoolAnd, box BoolLit(x), box BoolLit(y)) => BoolLit(x && y),
BinOp(BoolOr, box BoolLit(x), box BoolLit(y)) => BoolLit(x || y),
BinOp(BoolEQ, box BoolLit(x), box BoolLit(y)) => BoolLit(x == y),
diff --git a/dhall/tests/tests.rs b/dhall/tests/tests.rs
index a523b6e..8b910a2 100644
--- a/dhall/tests/tests.rs
+++ b/dhall/tests/tests.rs
@@ -14,7 +14,7 @@ make_spec_test!(normalization, spec_normalization_success_haskell_tutorial_acces
// make_spec_test!(normalization, spec_normalization_success_multiline_preserveComment, "normalization/success/multiline/preserveComment");
// make_spec_test!(normalization, spec_normalization_success_multiline_singleLine, "normalization/success/multiline/singleLine");
// make_spec_test!(normalization, spec_normalization_success_multiline_twoLines, "normalization/success/multiline/twoLines");
-// make_spec_test!(normalization, spec_normalization_success_prelude_Bool_and_0, "normalization/success/prelude/Bool/and/0");
+make_spec_test!(normalization, spec_normalization_success_prelude_Bool_and_0, "normalization/success/prelude/Bool/and/0");
// make_spec_test!(normalization, spec_normalization_success_prelude_Bool_and_1, "normalization/success/prelude/Bool/and/1");
// make_spec_test!(normalization, spec_normalization_success_prelude_Bool_build_0, "normalization/success/prelude/Bool/build/0");
// make_spec_test!(normalization, spec_normalization_success_prelude_Bool_build_1, "normalization/success/prelude/Bool/build/1");
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs
index fcb7713..cb4d6ca 100644
--- a/dhall_core/src/core.rs
+++ b/dhall_core/src/core.rs
@@ -24,17 +24,47 @@ use std::path::PathBuf;
/// Note that Dhall does not support functions from terms to types and therefore
/// Dhall is not a dependently typed language
///
-#[derive(Debug, Copy, Clone, PartialEq, Eq)] // (Show, Bounded, Enum)
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Const {
Type,
Kind,
}
-/// Path to an external resource
-#[derive(Debug, Clone, PartialEq, Eq)] // (Eq, Ord, Show)
-pub enum Path {
- File(PathBuf),
- URL(String),
+/// The beginning of a file path which anchors subsequent path components
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum FilePrefix {
+ /// Absolute path
+ Absolute,
+ /// Path relative to .
+ Here,
+ /// Path relative to ..
+ Parent,
+ /// Path relative to ~
+ Home,
+}
+
+/// The location of import (i.e. local vs. remote vs. environment)
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ImportLocation {
+ Local(FilePrefix, PathBuf),
+ // TODO: other import types
+}
+
+/// How to interpret the import's contents (i.e. as Dhall code or raw text)
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ImportMode {
+ Code,
+ // TODO
+ // RawText,
+}
+
+/// Reference to an external resource
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Import {
+ pub mode: ImportMode,
+ pub location: ImportLocation,
+ // TODO
+ pub hash: Option<()>,
}
/// Label for a bound variable
@@ -231,19 +261,34 @@ impl<'i, S, A> From<Builtin> for Expr<'i, S, A> {
}
impl<'i, S, A> Expr<'i, S, A> {
- pub fn map_shallow<T, F1, F2>(
+ pub fn map_shallow<T, B, F1, F2, F3>(
&self,
map_expr: F1,
map_note: F2,
- ) -> Expr<'i, T, A>
+ map_embed: F3,
+ ) -> Expr<'i, T, B>
where
A: Clone,
T: Clone,
S: Clone,
- F1: Fn(&Self) -> Expr<'i, T, A>,
+ F1: Fn(&Self) -> Expr<'i, T, B>,
F2: FnOnce(&S) -> T,
+ F3: FnOnce(&A) -> B,
+ {
+ map_shallow(self, map_expr, map_note, map_embed)
+ }
+
+ pub fn map_embed<B, F>(
+ &self,
+ map_embed: &F,
+ ) -> Expr<'i, S, B>
+ where
+ A: Clone,
+ S: Clone,
+ F: Fn(&A) -> B,
{
- map_shallow(self, map_expr, map_note)
+ let recurse = |e: &Expr<'i, S, A>| -> Expr<'i, S, B> { e.map_embed(map_embed) };
+ map_shallow(self, recurse, |x| x.clone(), map_embed)
}
pub fn bool_lit(&self) -> Option<bool> {
@@ -512,6 +557,12 @@ impl Display for Const {
}
}
+impl Display for Import {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ <Self as fmt::Debug>::fmt(self, f)
+ }
+}
+
impl Display for Builtin {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use crate::Builtin::*;
@@ -643,20 +694,22 @@ fn add_ui(u: usize, i: isize) -> usize {
}
}
-pub fn map_shallow<'i, S, T, A, F1, F2>(
+pub fn map_shallow<'i, S, T, A, B, F1, F2, F3>(
e: &Expr<'i, S, A>,
map: F1,
map_note: F2,
-) -> Expr<'i, T, A>
+ map_embed: F3,
+) -> Expr<'i, T, B>
where
A: Clone,
S: Clone,
T: Clone,
- F1: Fn(&Expr<'i, S, A>) -> Expr<'i, T, A>,
+ F1: Fn(&Expr<'i, S, A>) -> Expr<'i, T, B>,
F2: FnOnce(&S) -> T,
+ F3: FnOnce(&A) -> B,
{
use crate::Expr::*;
- let bxmap = |x: &Expr<'i, S, A>| -> Box<Expr<'i, T, A>> { bx(map(x)) };
+ let bxmap = |x: &Expr<'i, S, A>| -> Box<Expr<'i, T, B>> { bx(map(x)) };
let opt = |x| map_opt_box(x, &map);
match *e {
Const(k) => Const(k),
@@ -691,7 +744,7 @@ where
Merge(ref x, ref y, ref t) => Merge(bxmap(x), bxmap(y), opt(t)),
Field(ref r, x) => Field(bxmap(r), x),
Note(ref n, ref e) => Note(map_note(n), bxmap(e)),
- Embed(ref a) => Embed(a.clone()),
+ Embed(ref a) => Embed(map_embed(a)),
}
}
diff --git a/dhall_core/src/grammar_util.rs b/dhall_core/src/grammar_util.rs
index ce73444..82528f4 100644
--- a/dhall_core/src/grammar_util.rs
+++ b/dhall_core/src/grammar_util.rs
@@ -1,6 +1,6 @@
-use crate::core::{Expr, X};
+use crate::core::{Expr, X, Import};
-pub type ParsedExpr<'i> = Expr<'i, X, X>; // FIXME Parse paths and replace the second X with Path
+pub type ParsedExpr<'i> = Expr<'i, X, Import>;
pub type BoxExpr<'i> = Box<ParsedExpr<'i>>;
pub type ExprOpFn<'i> = fn(BoxExpr<'i>, BoxExpr<'i>) -> ParsedExpr<'i>;
pub type ExprListFn<'i> =
diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs
index f5a9129..09863a2 100644
--- a/dhall_core/src/parser.rs
+++ b/dhall_core/src/parser.rs
@@ -3,11 +3,12 @@ use std::collections::BTreeMap;
use lalrpop_util;
use pest::iterators::Pair;
use pest::Parser;
+use std::path::PathBuf;
use dhall_parser::{DhallParser, Rule};
use crate::core;
-use crate::core::{bx, BinOp, Builtin, Const, Expr, V};
+use crate::core::*;
use crate::grammar;
use crate::grammar_util::{BoxExpr, ParsedExpr};
use crate::lexer::{Lexer, LexicalError, Tok};
@@ -496,6 +497,67 @@ rule!(integer_literal_raw<core::Integer>;
}
);
+rule!(path<PathBuf>; captured_str!(s) => s.into());
+
+rule!(parent_path<(FilePrefix, PathBuf)>;
+ children!(p: path) => (FilePrefix::Parent, p)
+);
+
+rule!(here_path<(FilePrefix, PathBuf)>;
+ children!(p: path) => (FilePrefix::Here, p)
+);
+
+rule!(home_path<(FilePrefix, PathBuf)>;
+ children!(p: path) => (FilePrefix::Home, p)
+);
+
+rule!(absolute_path<(FilePrefix, PathBuf)>;
+ children!(p: path) => (FilePrefix::Absolute, p)
+);
+
+rule_group!(local_raw<(FilePrefix, PathBuf)>;
+ parent_path,
+ here_path,
+ home_path,
+ absolute_path
+);
+
+// TODO: other import types
+rule!(import_type_raw<ImportLocation>;
+ // children!(_e: missing_raw) => {
+ // ImportLocation::Missing
+ // }
+ // children!(e: env_raw) => {
+ // ImportLocation::Env(e)
+ // }
+ // children!(url: http) => {
+ // ImportLocation::Remote(url)
+ // }
+ children!(import: local_raw) => {
+ let (prefix, path) = import;
+ ImportLocation::Local(prefix, path)
+ }
+);
+
+rule!(import_hashed_raw<(ImportLocation, Option<()>)>;
+ // TODO: handle hash
+ children!(import: import_type_raw) => {
+ (import, None)
+ }
+);
+
+rule!(import_raw<BoxExpr<'a>>;
+ // TODO: handle "as Text"
+ children!(import: import_hashed_raw) => {
+ let (location, hash) = import;
+ bx(Expr::Embed(Import {
+ mode: ImportMode::Code,
+ hash,
+ location,
+ }))
+ }
+);
+
rule_group!(expression<BoxExpr<'a>>;
identifier_raw,
lambda_expression,
@@ -522,6 +584,7 @@ rule_group!(expression<BoxExpr<'a>>;
not_equal_expression,
application_expression,
+ import_raw,
selector_expression_raw,
literal_expression_raw,
empty_record_type,
diff --git a/dhall_generator/src/lib.rs b/dhall_generator/src/lib.rs
index 5b3cc6f..b26ea63 100644
--- a/dhall_generator/src/lib.rs
+++ b/dhall_generator/src/lib.rs
@@ -8,7 +8,9 @@ use quote::quote;
#[proc_macro]
pub fn dhall(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input_str = input.to_string();
- let expr = parser::parse_expr_pest(&input_str).unwrap();
+ let expr: Box<Expr<X, Import>> = parser::parse_expr_pest(&input_str).unwrap();
+ let no_import = |_: &Import| -> X { panic!("Don't use import in dhall!()") };
+ let expr = expr.map_embed(&no_import);
let output = dhall_to_tokenstream(&expr, &Context::new());
output.into()
}
diff --git a/dhall_parser/src/dhall.abnf b/dhall_parser/src/dhall.abnf
index 76af24b..d803770 100644
--- a/dhall_parser/src/dhall.abnf
+++ b/dhall_parser/src/dhall.abnf
@@ -384,15 +384,20 @@ path-component = "/" ( 1*path-character / %x22 1*quoted-path-character %x22 )
path = 1*path-component
local-raw =
- ".." path ; Relative path
- / "." path ; Relative path
- / "~" path ; Home-anchored path
+ parent-path
+ / here-path
+ / home-path
; NOTE: Backtrack if parsing this alternative fails
;
; This is because the first character of this alternative will be "/", but
; if the second character is "/" or "\" then this should have been parsed
; as an operator instead of a path
- / path ; Absolute path
+ / absolute-path
+
+parent-path = ".." path ; Relative path
+here-path = "." path ; Relative path
+home-path = "~" path ; Home-anchored path
+absolute-path = path ; Absolute path
; `http[s]` URI grammar based on RFC7230 and RFC 3986 with some differences
; noted below
diff --git a/dhall_parser/src/dhall.pest.visibility b/dhall_parser/src/dhall.pest.visibility
index 08171b3..f9c9d0b 100644
--- a/dhall_parser/src/dhall.pest.visibility
+++ b/dhall_parser/src/dhall.pest.visibility
@@ -92,7 +92,7 @@ identifier
# quoted_path_character
# path_component
path
-local_raw
+# local_raw
scheme
http_raw
authority