summaryrefslogtreecommitdiff
path: root/dhall_core/src
diff options
context:
space:
mode:
authorNadrieril2019-03-06 23:35:39 +0100
committerNadrieril2019-03-06 23:35:39 +0100
commit54382cd107d1befd6015f8232716158a20db44a4 (patch)
tree81afc63e474ad58f384dde36550f9d50756c5217 /dhall_core/src
parent39fc0af2548127a7c2ee1345d4ea63d473e0ab5a (diff)
Start parsing imports
Diffstat (limited to 'dhall_core/src')
-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
3 files changed, 134 insertions, 18 deletions
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,