summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock224
-rw-r--r--dhall/src/core/value.rs11
-rw-r--r--dhall/src/core/valuef.rs27
-rw-r--r--dhall/src/core/var.rs12
-rw-r--r--dhall/src/phase/mod.rs4
-rw-r--r--dhall/src/phase/resolve.rs41
-rw-r--r--dhall_generated_parser/Cargo.toml2
-rw-r--r--dhall_generated_parser/src/dhall.pest.visibility18
-rw-r--r--dhall_proc_macros/src/make_parser.rs325
-rw-r--r--dhall_proc_macros/src/parse_children.rs11
-rw-r--r--dhall_syntax/src/core/expr.rs101
-rw-r--r--dhall_syntax/src/core/import.rs34
-rw-r--r--dhall_syntax/src/core/map.rs65
-rw-r--r--dhall_syntax/src/core/text.rs56
-rw-r--r--dhall_syntax/src/core/visitor.rs412
-rw-r--r--dhall_syntax/src/parser.rs446
-rw-r--r--tests_buffer2
17 files changed, 1072 insertions, 719 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 976b3c5..d5ce864 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,7 +2,7 @@
# It is not intended for manual editing.
[[package]]
name = "abnf"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -12,8 +12,8 @@ dependencies = [
name = "abnf_to_pest"
version = "0.1.1"
dependencies = [
- "abnf 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "abnf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -23,26 +23,31 @@ name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "arrayref"
-version = "0.3.5"
+name = "block-buffer"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
-name = "block-buffer"
-version = "0.3.3"
+name = "block-padding"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byte-tools"
-version = "0.2.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -52,16 +57,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
-version = "1.3.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ctor"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -73,11 +78,11 @@ dependencies = [
"improved_slice_patterns 2.0.0",
"itertools 0.8.0 (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.90 (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)",
"take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"term-painter 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -85,9 +90,9 @@ name = "dhall_generated_parser"
version = "0.1.0"
dependencies = [
"abnf_to_pest 0.1.1",
- "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -111,7 +116,7 @@ dependencies = [
"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.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -122,10 +127,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "digest"
-version = "0.7.6"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -140,10 +145,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
-version = "0.9.0"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -162,7 +167,7 @@ version = "2.0.0"
[[package]]
name = "indexmap"
-version = "1.0.2"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -189,12 +194,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "maplit"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
-version = "2.2.0"
+version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -202,16 +207,21 @@ name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
+name = "opaque-debug"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "output_vt100"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -221,32 +231,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pest"
-version = "2.1.0"
+version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pest_generator"
-version = "2.1.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pest_meta"
-version = "2.1.0"
+version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -254,7 +264,7 @@ name = "pretty"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "typed-arena 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "typed-arena 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -263,21 +273,13 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
-version = "0.4.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "proc-macro2"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -286,14 +288,6 @@ dependencies = [
[[package]]
name = "quote"
-version = "0.6.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "quote"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -302,7 +296,7 @@ dependencies = [
[[package]]
name = "same-file"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -310,10 +304,10 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.90"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -321,19 +315,19 @@ name = "serde_cbor"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive"
-version = "1.0.90"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -343,28 +337,18 @@ dependencies = [
"dhall 0.1.0",
"dhall_proc_macros 0.1.0",
"dhall_syntax 0.1.0",
- "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sha-1"
-version = "0.7.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "syn"
-version = "0.15.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -401,22 +385,17 @@ dependencies = [
[[package]]
name = "typed-arena"
-version = "1.4.1"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typenum"
-version = "1.10.0"
+version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-trie"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "unicode-xid"
-version = "0.1.0"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -431,11 +410,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
-version = "2.2.7"
+version = "2.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -446,7 +425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
-version = "0.3.7"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -468,7 +447,7 @@ name = "winapi-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -477,58 +456,55 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
-"checksum abnf 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cd52ccec58f8b39e3b25620953fd8dfbdcf932b50907b29d577cf1dd12477b6"
+"checksum abnf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d972ae01fad2d4693b272854546bd763966c95575a4f1d6333dc95b85ff182db"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
-"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
-"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
+"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
+"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c"
-"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
-"checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c"
+"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+"checksum ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5b6b2f4752cc29efbfd03474c532ce8f916f2d44ec5bb8c21f93bc76e5365528"
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
-"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
+"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
-"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
+"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
"checksum half 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9353c2a89d550b58fa0061d8ed8d002a7d8cdf2494eb0e432859bd3a9e543836"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
-"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
+"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356"
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
-"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
+"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
+"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
-"checksum pest 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "54f0c72a98d8ab3c99560bfd16df8059cc10e1f9a8e83e6e3b97718dd766e9c3"
-"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646"
-"checksum pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e"
+"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a"
+"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0"
+"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547"
"checksum pretty 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f60c0d9f6fc88ecdd245d90c1920ff76a430ab34303fc778d33b1d0a4c3bf6d3"
"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
-"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95"
-"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
-"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
-"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4"
+"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
+"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
"checksum serde_cbor 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45cd6d95391b16cd57e88b68be41d504183b7faae22030c0cc3b3f73dd57b2fd"
-"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79"
-"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
-"checksum syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a"
+"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
+"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term-painter 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dcaa948f0e3e38470cd8dc8dcfe561a75c9e43f28075bb183845be2b9b3c08cf"
-"checksum typed-arena 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c06a92aef38bb4dc5b0df00d68496fc31307c5344c867bb61678c6e1671ec5"
-"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
-"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
-"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+"checksum typed-arena 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f70f5c346cc11bc044ae427ab2feae213350dca9e2d637047797d5ff316a646"
+"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
+"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
+"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
-"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
+"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
diff --git a/dhall/src/core/value.rs b/dhall/src/core/value.rs
index 3cccb1d..b4b6b08 100644
--- a/dhall/src/core/value.rs
+++ b/dhall/src/core/value.rs
@@ -212,17 +212,6 @@ impl Value {
WHNF | NF => {}
}
}
- pub(crate) fn normalize_nf(&self) {
- let borrow = self.as_internal();
- match borrow.form {
- Unevaled | WHNF => {
- drop(borrow);
- self.as_internal_mut().normalize_nf();
- }
- // Already in NF
- NF => {}
- }
- }
pub(crate) fn app(&self, v: Value) -> Value {
let body_t = match &*self.get_type_not_sort().as_whnf() {
diff --git a/dhall/src/core/valuef.rs b/dhall/src/core/valuef.rs
index 7ecec86..4e457e6 100644
--- a/dhall/src/core/valuef.rs
+++ b/dhall/src/core/valuef.rs
@@ -110,17 +110,11 @@ impl ValueF {
ValueF::UnionConstructor(l.clone(), kts.clone()).to_expr(opts),
v.to_expr(opts),
)),
- ValueF::TextLit(elts) => {
- use InterpolatedTextContents::{Expr, Text};
- rc(ExprF::TextLit(
- elts.iter()
- .map(|contents| match contents {
- Expr(e) => Expr(e.to_expr(opts)),
- Text(s) => Text(s.clone()),
- })
- .collect(),
- ))
- }
+ ValueF::TextLit(elts) => rc(ExprF::TextLit(
+ elts.iter()
+ .map(|contents| contents.map_ref(|e| e.to_expr(opts)))
+ .collect(),
+ )),
ValueF::Equivalence(x, y) => rc(ExprF::BinOp(
dhall_syntax::BinOp::Equivalence,
x.to_expr(opts),
@@ -187,11 +181,7 @@ impl ValueF {
}
ValueF::TextLit(elts) => {
for x in elts.iter_mut() {
- use InterpolatedTextContents::{Expr, Text};
- match x {
- Expr(n) => n.normalize_mut(),
- Text(_) => {}
- }
+ x.map_mut(Value::normalize_mut);
}
}
ValueF::Equivalence(x, y) => {
@@ -199,10 +189,7 @@ impl ValueF {
y.normalize_mut();
}
ValueF::PartialExpr(e) => {
- // TODO: need map_mut
- e.map_ref(|v| {
- v.normalize_nf();
- });
+ e.map_mut(Value::normalize_mut);
}
}
}
diff --git a/dhall/src/core/var.rs b/dhall/src/core/var.rs
index ce4d137..3795f10 100644
--- a/dhall/src/core/var.rs
+++ b/dhall/src/core/var.rs
@@ -224,11 +224,7 @@ where
impl<T: Shift> Shift for dhall_syntax::InterpolatedTextContents<T> {
fn shift(&self, delta: isize, var: &AlphaVar) -> Option<Self> {
- use dhall_syntax::InterpolatedTextContents::{Expr, Text};
- Some(match self {
- Expr(x) => Expr(x.shift(delta, var)?),
- Text(s) => Text(s.clone()),
- })
+ Some(self.traverse_ref(|x| Ok(x.shift(delta, var)?))?)
}
}
@@ -283,11 +279,7 @@ impl<S, T: Subst<S>> Subst<S> for Vec<T> {
impl<S, T: Subst<S>> Subst<S> for dhall_syntax::InterpolatedTextContents<T> {
fn subst_shift(&self, var: &AlphaVar, val: &S) -> Self {
- use dhall_syntax::InterpolatedTextContents::{Expr, Text};
- match self {
- Expr(x) => Expr(x.subst_shift(var, val)),
- Text(s) => Text(s.clone()),
- }
+ self.map_ref(|x| x.subst_shift(var, val))
}
}
diff --git a/dhall/src/phase/mod.rs b/dhall/src/phase/mod.rs
index 2c5505c..337ce3d 100644
--- a/dhall/src/phase/mod.rs
+++ b/dhall/src/phase/mod.rs
@@ -16,8 +16,8 @@ pub(crate) mod parse;
pub(crate) mod resolve;
pub(crate) mod typecheck;
-pub type ParsedExpr = Expr<!>;
-pub type DecodedExpr = Expr<!>;
+pub type ParsedExpr = Expr<Normalized>;
+pub type DecodedExpr = Expr<Normalized>;
pub type ResolvedExpr = Expr<Normalized>;
pub type NormalizedExpr = Expr<Normalized>;
diff --git a/dhall/src/phase/resolve.rs b/dhall/src/phase/resolve.rs
index 4034a5c..cccc7a7 100644
--- a/dhall/src/phase/resolve.rs
+++ b/dhall/src/phase/resolve.rs
@@ -59,18 +59,16 @@ fn load_import(
}
fn do_resolve_expr(
- Parsed(expr, root): Parsed,
+ parsed: Parsed,
import_cache: &mut ImportCache,
import_stack: &ImportStack,
) -> Result<Resolved, ImportError> {
- let resolve = |import: &Import| -> Result<Normalized, ImportError> {
- if import_stack.contains(import) {
- return Err(ImportError::ImportCycle(
- import_stack.clone(),
- import.clone(),
- ));
+ let Parsed(mut expr, root) = parsed;
+ let mut resolve = |import: Import| -> Result<Normalized, ImportError> {
+ if import_stack.contains(&import) {
+ return Err(ImportError::ImportCycle(import_stack.clone(), import));
}
- match import_cache.get(import) {
+ match import_cache.get(&import) {
Some(expr) => Ok(expr.clone()),
None => {
// Copy the import stack and push the current import
@@ -78,16 +76,20 @@ fn do_resolve_expr(
import_stack.push(import.clone());
// Resolve the import recursively
- let expr =
- resolve_import(import, &root, import_cache, &import_stack)?;
+ let expr = resolve_import(
+ &import,
+ &root,
+ import_cache,
+ &import_stack,
+ )?;
// Add the import to the cache
- import_cache.insert(import.clone(), expr.clone());
+ import_cache.insert(import, expr.clone());
Ok(expr)
}
}
};
- let expr = expr.traverse_resolve(resolve)?;
+ expr.traverse_resolve_mut(&mut resolve)?;
Ok(Resolved(expr))
}
@@ -96,12 +98,13 @@ pub(crate) fn resolve(e: Parsed) -> Result<Resolved, ImportError> {
}
pub(crate) fn skip_resolve_expr(
- Parsed(expr, _root): Parsed,
+ parsed: Parsed,
) -> Result<Resolved, ImportError> {
- let resolve = |import: &Import| -> Result<Normalized, ImportError> {
- Err(ImportError::UnexpectedImport(import.clone()))
+ let mut expr = parsed.0;
+ let mut resolve = |import: Import| -> Result<Normalized, ImportError> {
+ Err(ImportError::UnexpectedImport(import))
};
- let expr = expr.traverse_resolve(resolve)?;
+ expr.traverse_resolve_mut(&mut resolve)?;
Ok(Resolved(expr))
}
@@ -201,9 +204,9 @@ mod spec_tests {
// import_success!(success_alternativeEnvNatural, "alternativeEnvNatural");
// import_success!(success_alternativeEnvSimple, "alternativeEnvSimple");
// import_success!(success_alternativeHashMismatch, "alternativeHashMismatch");
- // import_success!(success_alternativeNatural, "alternativeNatural");
- // import_success!(success_alternativeParseError, "alternativeParseError");
- // import_success!(success_alternativeTypeError, "alternativeTypeError");
+ import_success!(success_alternativeNatural, "alternativeNatural");
+ import_success!(success_alternativeParseError, "alternativeParseError");
+ import_success!(success_alternativeTypeError, "alternativeTypeError");
// import_success!(success_asLocation, "asLocation");
// import_success!(success_asText, "asText");
// import_success!(success_customHeaders, "customHeaders");
diff --git a/dhall_generated_parser/Cargo.toml b/dhall_generated_parser/Cargo.toml
index aed54b8..0730f60 100644
--- a/dhall_generated_parser/Cargo.toml
+++ b/dhall_generated_parser/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
[build-dependencies]
abnf_to_pest = { version = "0.1.1", path = "../abnf_to_pest" }
pest_generator = "2.1"
-quote = "0.6.11"
+quote = "1.0.2"
[dependencies]
pest = "2.1"
diff --git a/dhall_generated_parser/src/dhall.pest.visibility b/dhall_generated_parser/src/dhall.pest.visibility
index dcebf45..17c1edc 100644
--- a/dhall_generated_parser/src/dhall.pest.visibility
+++ b/dhall_generated_parser/src/dhall.pest.visibility
@@ -18,7 +18,7 @@
simple_label
# quoted_label_char
quoted_label
-label
+# label
# nonreserved_label
# any_label
double_quote_chunk
@@ -31,13 +31,13 @@ escaped_quote_pair
escaped_interpolation
single_quote_char
single_quote_literal
-interpolation
+# interpolation
# text_literal
if_
# then
# else_
# let_
-in_
+# in_
# as_
# using
merge
@@ -49,9 +49,9 @@ toMap
assert
# keyword
builtin
-Optional
+# Optional
Text
-List
+# List
Location
# Bool
# True
@@ -95,7 +95,7 @@ arrow
numeric_double_literal
minus_infinity_literal
plus_infinity_literal
-double_literal
+# double_literal
natural_literal
integer_literal
identifier
@@ -104,7 +104,7 @@ variable
# quoted_path_character
unquoted_path_component
quoted_path_component
-path_component
+# path_component
path
local
parent_path
@@ -136,7 +136,7 @@ env
bash_environment_variable
posix_environment_variable
posix_environment_variable_character
-import_type
+# import_type
hash
import_hashed
import
@@ -160,7 +160,7 @@ not_equal_expression
equivalent_expression
application_expression
first_application_expression
-import_expression
+# import_expression
selector_expression
selector
labels
diff --git a/dhall_proc_macros/src/make_parser.rs b/dhall_proc_macros/src/make_parser.rs
index 268a639..a17ab61 100644
--- a/dhall_proc_macros/src/make_parser.rs
+++ b/dhall_proc_macros/src/make_parser.rs
@@ -1,70 +1,188 @@
+use std::collections::HashMap;
+use std::iter;
+
use quote::quote;
-use syn::parse::{ParseStream, Result};
+use syn::parse::{Parse, ParseStream, Result};
use syn::spanned::Spanned;
use syn::{
parse_quote, Error, Expr, FnArg, Ident, ImplItem, ImplItemMethod, ItemImpl,
- Pat, Token,
+ LitBool, Pat, Token,
};
-fn apply_special_attrs(function: &mut ImplItemMethod) -> Result<()> {
+mod kw {
+ syn::custom_keyword!(shortcut);
+}
+
+struct AliasArgs {
+ target: Ident,
+ is_shortcut: bool,
+}
+
+struct PrecClimbArgs {
+ child_rule: Ident,
+ climber: Expr,
+}
+
+struct AliasSrc {
+ ident: Ident,
+ is_shortcut: bool,
+}
+
+struct ParsedFn<'a> {
+ // Body of the function
+ function: &'a mut ImplItemMethod,
+ // Name of the function.
+ fn_name: Ident,
+ // Name of the first argument of the function, which should be of type `ParseInput`.
+ input_arg: Ident,
+ // List of aliases pointing to this function
+ alias_srcs: Vec<AliasSrc>,
+}
+
+impl Parse for AliasArgs {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let target = input.parse()?;
+ let is_shortcut = if input.peek(Token![,]) {
+ // #[alias(rule, shortcut = true)]
+ let _: Token![,] = input.parse()?;
+ let _: kw::shortcut = input.parse()?;
+ let _: Token![=] = input.parse()?;
+ let b: LitBool = input.parse()?;
+ b.value
+ } else {
+ // #[alias(rule)]
+ false
+ };
+ Ok(AliasArgs {
+ target,
+ is_shortcut,
+ })
+ }
+}
+
+impl Parse for PrecClimbArgs {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let child_rule = input.parse()?;
+ let _: Token![,] = input.parse()?;
+ let climber = input.parse()?;
+ Ok(PrecClimbArgs {
+ child_rule,
+ climber,
+ })
+ }
+}
+
+fn collect_aliases(
+ imp: &mut ItemImpl,
+) -> Result<HashMap<Ident, Vec<AliasSrc>>> {
+ let functions = imp.items.iter_mut().flat_map(|item| match item {
+ ImplItem::Method(m) => Some(m),
+ _ => None,
+ });
+
+ let mut alias_map = HashMap::new();
+ for function in functions {
+ let fn_name = function.sig.ident.clone();
+ let mut alias_attrs = function
+ .attrs
+ .drain_filter(|attr| attr.path.is_ident("alias"))
+ .collect::<Vec<_>>()
+ .into_iter();
+
+ if let Some(attr) = alias_attrs.next() {
+ let args: AliasArgs = attr.parse_args()?;
+ alias_map.entry(args.target).or_insert_with(Vec::new).push(
+ AliasSrc {
+ ident: fn_name,
+ is_shortcut: args.is_shortcut,
+ },
+ );
+ }
+ if let Some(attr) = alias_attrs.next() {
+ return Err(Error::new(
+ attr.span(),
+ "expected at most one alias attribute",
+ ));
+ }
+ }
+
+ Ok(alias_map)
+}
+
+fn parse_fn<'a>(
+ function: &'a mut ImplItemMethod,
+ alias_map: &mut HashMap<Ident, Vec<AliasSrc>>,
+) -> Result<ParsedFn<'a>> {
+ let fn_name = function.sig.ident.clone();
+ // Get the name of the first (`input`) function argument
+ let input_arg = function.sig.inputs.first().ok_or_else(|| {
+ Error::new(
+ function.sig.inputs.span(),
+ "a rule function needs an `input` argument",
+ )
+ })?;
+ let input_arg = match &input_arg {
+ FnArg::Receiver(_) => return Err(Error::new(
+ input_arg.span(),
+ "a rule function should not have a `self` argument",
+ )),
+ FnArg::Typed(input_arg) => match &*input_arg.pat{
+ Pat::Ident(ident) => ident.ident.clone(),
+ _ => return Err(Error::new(
+ input_arg.span(),
+ "this argument should be a plain identifier instead of a pattern",
+ )),
+ }
+ };
+
+ let alias_srcs = alias_map.remove(&fn_name).unwrap_or_else(Vec::new);
+
+ Ok(ParsedFn {
+ function,
+ fn_name,
+ input_arg,
+ alias_srcs,
+ })
+}
+
+fn apply_special_attrs(f: &mut ParsedFn, rule_enum: &Ident) -> Result<()> {
+ let function = &mut *f.function;
+ let fn_name = &f.fn_name;
+ let input_arg = &f.input_arg;
+
*function = parse_quote!(
- #[allow(non_snake_case, dead_code)]
+ #[allow(non_snake_case)]
#function
);
- let recognized_attrs: Vec<_> = function
+ // `prec_climb` attr
+ let prec_climb_attrs: Vec<_> = function
.attrs
.drain_filter(|attr| attr.path.is_ident("prec_climb"))
.collect();
- let name = function.sig.ident.clone();
-
- if recognized_attrs.is_empty() {
- // do nothing
- } else if recognized_attrs.len() > 1 {
+ if prec_climb_attrs.len() > 1 {
return Err(Error::new(
- recognized_attrs[1].span(),
- "expected a single prec_climb attribute",
+ prec_climb_attrs[1].span(),
+ "expected at most one prec_climb attribute",
));
+ } else if prec_climb_attrs.is_empty() {
+ // do nothing
} else {
- let attr = recognized_attrs.into_iter().next().unwrap();
- let (child_rule, climber) =
- attr.parse_args_with(|input: ParseStream| {
- let child_rule: Ident = input.parse()?;
- let _: Token![,] = input.parse()?;
- let climber: Expr = input.parse()?;
- Ok((child_rule, climber))
- })?;
-
- // Get the name of the first (`input`) function argument
- let first_arg = function.sig.inputs.first().ok_or_else(|| {
- Error::new(
- function.sig.inputs.span(),
- "a prec_climb function needs 4 arguments",
- )
- })?;
- let first_arg = match &first_arg {
- FnArg::Receiver(_) => return Err(Error::new(
- first_arg.span(),
- "a prec_climb function should not have a `self` argument",
- )),
- FnArg::Typed(first_arg) => match &*first_arg.pat{
- Pat::Ident(ident) => &ident.ident,
- _ => return Err(Error::new(
- first_arg.span(),
- "this argument should be a plain identifier instead of a pattern",
- )),
- }
- };
+ let attr = prec_climb_attrs.into_iter().next().unwrap();
+ let PrecClimbArgs {
+ child_rule,
+ climber,
+ } = attr.parse_args()?;
function.block = parse_quote!({
#function
#climber.climb(
- #first_arg.pair.clone().into_inner(),
- |p| Self::#child_rule(#first_arg.with_pair(p)),
+ #input_arg.pair.clone().into_inner(),
+ |p| Self::#child_rule(#input_arg.with_pair(p)),
|l, op, r| {
- #name(#first_arg.clone(), l?, op, r?)
+ #fn_name(#input_arg.clone(), l?, op, r?)
},
)
});
@@ -81,6 +199,37 @@ fn apply_special_attrs(function: &mut ImplItemMethod) -> Result<()> {
})?;
}
+ // `alias` attr
+ if !f.alias_srcs.is_empty() {
+ let aliases = f.alias_srcs.iter().map(|src| &src.ident);
+ let block = &function.block;
+ function.block = parse_quote!({
+ let mut #input_arg = #input_arg;
+ // While the current rule allows shortcutting, and there is a single child, and the
+ // child can still be parsed by the current function, then skip to that child.
+ while <Self as PestConsumer>::allows_shortcut(#input_arg.as_rule()) {
+ if let Some(child) = #input_arg.single_child() {
+ if &<Self as PestConsumer>::rule_alias(child.as_rule())
+ == stringify!(#fn_name) {
+ #input_arg = child;
+ continue;
+ }
+ }
+ break
+ }
+
+ match #input_arg.as_rule() {
+ #(#rule_enum::#aliases => Self::#aliases(#input_arg),)*
+ #rule_enum::#fn_name => #block,
+ r => unreachable!(
+ "make_parser: called {} on {:?}",
+ stringify!(#fn_name),
+ r
+ )
+ }
+ });
+ }
+
Ok(())
}
@@ -89,21 +238,95 @@ pub fn make_parser(
input: proc_macro::TokenStream,
) -> Result<proc_macro2::TokenStream> {
let rule_enum: Ident = syn::parse(attrs)?;
-
let mut imp: ItemImpl = syn::parse(input)?;
- imp.items
+
+ let mut alias_map = collect_aliases(&mut imp)?;
+ let rule_alias_branches: Vec<_> = alias_map
+ .iter()
+ .flat_map(|(tgt, srcs)| iter::repeat(tgt).zip(srcs))
+ .map(|(tgt, src)| {
+ let ident = &src.ident;
+ quote!(
+ #rule_enum::#ident => stringify!(#tgt).to_string(),
+ )
+ })
+ .collect();
+ let shortcut_branches: Vec<_> = alias_map
+ .iter()
+ .flat_map(|(_tgt, srcs)| srcs)
+ .map(|AliasSrc { ident, is_shortcut }| {
+ quote!(
+ #rule_enum::#ident => #is_shortcut,
+ )
+ })
+ .collect();
+
+ let fn_map: HashMap<Ident, ParsedFn> = imp
+ .items
.iter_mut()
- .map(|item| match item {
- ImplItem::Method(m) => apply_special_attrs(m),
- _ => Ok(()),
+ .flat_map(|item| match item {
+ ImplItem::Method(m) => Some(m),
+ _ => None,
+ })
+ .map(|method| {
+ let mut f = parse_fn(method, &mut alias_map)?;
+ apply_special_attrs(&mut f, &rule_enum)?;
+ Ok((f.fn_name.clone(), f))
+ })
+ .collect::<Result<_>>()?;
+
+ // Entries that remain in the alias map don't have a matching method, so we create one.
+ let extra_fns: Vec<_> = alias_map
+ .iter()
+ .map(|(tgt, srcs)| {
+ // Get the signature of one of the functions that has this alias. They should all have
+ // essentially the same signature anyways.
+ let f = fn_map.get(&srcs.first().unwrap().ident).unwrap();
+ let input_arg = f.input_arg.clone();
+ let mut sig = f.function.sig.clone();
+ sig.ident = tgt.clone();
+ let srcs = srcs.iter().map(|src| &src.ident);
+
+ Ok(parse_quote!(
+ #sig {
+ match #input_arg.as_rule() {
+ #(#rule_enum::#srcs => Self::#srcs(#input_arg),)*
+ // We can't match on #rule_enum::#tgt since `tgt` might be an arbitrary
+ // identifier.
+ r if &format!("{:?}", r) == stringify!(#tgt) =>
+ return Err(#input_arg.error(format!(
+ "make_parser: missing method for rule {}",
+ stringify!(#tgt),
+ ))),
+ r => unreachable!(
+ "make_parser: called {} on {:?}",
+ stringify!(#tgt),
+ r
+ )
+ }
+ }
+ ))
})
- .collect::<Result<()>>()?;
+ .collect::<Result<_>>()?;
+ imp.items.extend(extra_fns);
let ty = &imp.self_ty;
let (impl_generics, _, where_clause) = imp.generics.split_for_impl();
Ok(quote!(
impl #impl_generics PestConsumer for #ty #where_clause {
- type RuleEnum = #rule_enum;
+ type Rule = #rule_enum;
+ fn rule_alias(rule: Self::Rule) -> String {
+ match rule {
+ #(#rule_alias_branches)*
+ r => format!("{:?}", r),
+ }
+ }
+ fn allows_shortcut(rule: Self::Rule) -> bool {
+ match rule {
+ #(#shortcut_branches)*
+ _ => false,
+ }
+ }
}
#imp
diff --git a/dhall_proc_macros/src/parse_children.rs b/dhall_proc_macros/src/parse_children.rs
index b1d43fc..a35c03f 100644
--- a/dhall_proc_macros/src/parse_children.rs
+++ b/dhall_proc_macros/src/parse_children.rs
@@ -88,9 +88,7 @@ fn make_parser_branch(
let i_variable_pattern =
Ident::new("___variable_pattern", Span::call_site());
let match_pat = branch.pattern.iter().map(|item| match item {
- Single { rule_name, .. } => {
- quote!(<<Self as PestConsumer>::RuleEnum>::#rule_name)
- }
+ Single { rule_name, .. } => quote!(stringify!(#rule_name)),
Multiple { .. } => quote!(#i_variable_pattern @ ..),
});
let match_filter = branch.pattern.iter().map(|item| match item {
@@ -101,7 +99,7 @@ fn make_parser_branch(
// https://github.com/rust-lang/rust/issues/59803.
let all_match = |slice: &[_]| {
slice.iter().all(|r|
- r == &<<Self as PestConsumer>::RuleEnum>::#rule_name
+ *r == stringify!(#rule_name)
)
};
all_match(#i_variable_pattern)
@@ -192,6 +190,11 @@ pub fn parse_children(
.clone()
.into_inner()
.map(|p| p.as_rule())
+ .map(<Self as PestConsumer>::rule_alias)
+ .collect();
+ let #i_children_rules: Vec<&str> = #i_children_rules
+ .iter()
+ .map(String::as_str)
.collect();
#[allow(unused_mut)]
diff --git a/dhall_syntax/src/core/expr.rs b/dhall_syntax/src/core/expr.rs
index eeee4d8..2cb23c9 100644
--- a/dhall_syntax/src/core/expr.rs
+++ b/dhall_syntax/src/core/expr.rs
@@ -1,7 +1,7 @@
use std::rc::Rc;
use crate::map::{DupTreeMap, DupTreeSet};
-use crate::visitor;
+use crate::visitor::{self, ExprFMutVisitor, ExprFVisitor};
use crate::*;
pub type Integer = isize;
@@ -256,13 +256,6 @@ pub enum ExprF<SubExpr, Embed> {
}
impl<SE, E> ExprF<SE, E> {
- pub(crate) fn visit<'a, V, Return>(&'a self, v: V) -> Return
- where
- V: visitor::GenericVisitor<&'a ExprF<SE, E>, Return>,
- {
- v.visit(self)
- }
-
pub fn traverse_ref_with_special_handling_of_binders<'a, SE2, Err>(
&'a self,
visit_subexpr: impl FnMut(&'a SE) -> Result<SE2, Err>,
@@ -271,10 +264,11 @@ impl<SE, E> ExprF<SE, E> {
where
E: Clone,
{
- self.visit(visitor::TraverseRefWithBindersVisitor {
+ visitor::TraverseRefWithBindersVisitor {
visit_subexpr,
visit_under_binder,
- })
+ }
+ .visit(self)
}
fn traverse_ref<'a, SE2, Err>(
@@ -284,7 +278,14 @@ impl<SE, E> ExprF<SE, E> {
where
E: Clone,
{
- self.visit(visitor::TraverseRefVisitor { visit_subexpr })
+ visitor::TraverseRefVisitor { visit_subexpr }.visit(self)
+ }
+
+ fn traverse_mut<'a, Err>(
+ &'a mut self,
+ visit_subexpr: impl FnMut(&'a mut SE) -> Result<(), Err>,
+ ) -> Result<(), Err> {
+ visitor::TraverseMutVisitor { visit_subexpr }.visit(self)
}
pub fn map_ref_with_special_handling_of_binders<'a, SE2>(
@@ -310,38 +311,9 @@ impl<SE, E> ExprF<SE, E> {
{
trivial_result(self.traverse_ref(|x| Ok(map_subexpr(x))))
}
-}
-impl<E> RawExpr<E> {
- pub fn traverse_resolve<E2, Err>(
- &self,
- visit_import: impl FnMut(&Import<Expr<E2>>) -> Result<E2, Err>,
- ) -> Result<RawExpr<E2>, Err> {
- self.traverse_resolve_with_visitor(&mut visitor::ResolveVisitor(
- visit_import,
- ))
- }
-
- pub(crate) fn traverse_resolve_with_visitor<E2, Err, F1>(
- &self,
- visitor: &mut visitor::ResolveVisitor<F1>,
- ) -> Result<RawExpr<E2>, Err>
- where
- F1: FnMut(&Import<Expr<E2>>) -> Result<E2, Err>,
- {
- match self {
- ExprF::BinOp(BinOp::ImportAlt, l, r) => l
- .as_ref()
- .traverse_resolve_with_visitor(visitor)
- .or_else(|_| r.as_ref().traverse_resolve_with_visitor(visitor)),
- _ => {
- let e = self.visit(&mut *visitor)?;
- Ok(match &e {
- ExprF::Import(import) => ExprF::Embed((visitor.0)(import)?),
- _ => e,
- })
- }
- }
+ pub fn map_mut<'a>(&'a mut self, mut map_subexpr: impl FnMut(&'a mut SE)) {
+ trivial_result(self.traverse_mut(|x| Ok(map_subexpr(x))))
}
}
@@ -349,6 +321,9 @@ impl<E> Expr<E> {
pub fn as_ref(&self) -> &RawExpr<E> {
&self.0.as_ref().0
}
+ pub fn as_mut(&mut self) -> &mut RawExpr<E> {
+ &mut self.0.as_mut().0
+ }
pub fn new(x: RawExpr<E>, n: Span) -> Self {
Expr(Box::new((x, Some(n))))
@@ -365,14 +340,42 @@ impl<E> Expr<E> {
pub fn rewrap<E2>(&self, x: RawExpr<E2>) -> Expr<E2> {
Expr(Box::new((x, (self.0).1.clone())))
}
-}
-impl<E> Expr<E> {
- pub fn traverse_resolve<E2, Err>(
- &self,
- visit_import: impl FnMut(&Import<Expr<E2>>) -> Result<E2, Err>,
- ) -> Result<Expr<E2>, Err> {
- Ok(self.rewrap(self.as_ref().traverse_resolve(visit_import)?))
+ pub fn traverse_resolve_mut<Err, F1>(
+ &mut self,
+ f: &mut F1,
+ ) -> Result<(), Err>
+ where
+ E: Clone,
+ F1: FnMut(Import<Expr<E>>) -> Result<E, Err>,
+ {
+ match self.as_mut() {
+ ExprF::BinOp(BinOp::ImportAlt, l, r) => {
+ let garbage_expr = ExprF::BoolLit(false);
+ let new_self = if l.traverse_resolve_mut(f).is_ok() {
+ l
+ } else {
+ r.traverse_resolve_mut(f)?;
+ r
+ };
+ *self.as_mut() =
+ std::mem::replace(new_self.as_mut(), garbage_expr);
+ }
+ _ => {
+ self.as_mut().traverse_mut(|e| e.traverse_resolve_mut(f))?;
+ if let ExprF::Import(import) = self.as_mut() {
+ let garbage_import = Import {
+ mode: ImportMode::Code,
+ location: ImportLocation::Missing,
+ hash: None,
+ };
+ // Move out of &mut import
+ let import = std::mem::replace(import, garbage_import);
+ *self.as_mut() = ExprF::Embed(f(import)?);
+ }
+ }
+ }
+ Ok(())
}
}
diff --git a/dhall_syntax/src/core/import.rs b/dhall_syntax/src/core/import.rs
index cc38bb0..da3e99b 100644
--- a/dhall_syntax/src/core/import.rs
+++ b/dhall_syntax/src/core/import.rs
@@ -62,7 +62,7 @@ pub struct Import<SubExpr> {
}
impl<SE> URL<SE> {
- pub fn visit_subexpr<'a, Err, SE2>(
+ pub fn traverse_ref<'a, Err, SE2>(
&'a self,
f: impl FnOnce(&'a SE) -> Result<SE2, Err>,
) -> Result<URL<SE2>, Err> {
@@ -75,32 +75,56 @@ impl<SE> URL<SE> {
headers,
})
}
+ pub fn traverse_mut<'a, Err>(
+ &'a mut self,
+ f: impl FnOnce(&'a mut SE) -> Result<(), Err>,
+ ) -> Result<(), Err> {
+ if let Some(header) = &mut self.headers {
+ f(header)?;
+ }
+ Ok(())
+ }
}
impl<SE> ImportLocation<SE> {
- pub fn visit_subexpr<'a, Err, SE2>(
+ pub fn traverse_ref<'a, Err, SE2>(
&'a self,
f: impl FnOnce(&'a SE) -> Result<SE2, Err>,
) -> Result<ImportLocation<SE2>, Err> {
use ImportLocation::*;
Ok(match self {
Local(prefix, path) => Local(*prefix, path.clone()),
- Remote(url) => Remote(url.visit_subexpr(f)?),
+ Remote(url) => Remote(url.traverse_ref(f)?),
Env(env) => Env(env.clone()),
Missing => Missing,
})
}
+ pub fn traverse_mut<'a, Err>(
+ &'a mut self,
+ f: impl FnOnce(&'a mut SE) -> Result<(), Err>,
+ ) -> Result<(), Err> {
+ if let ImportLocation::Remote(url) = self {
+ url.traverse_mut(f)?;
+ }
+ Ok(())
+ }
}
impl<SE> Import<SE> {
- pub fn visit_subexpr<'a, Err, SE2>(
+ pub fn traverse_ref<'a, Err, SE2>(
&'a self,
f: impl FnOnce(&'a SE) -> Result<SE2, Err>,
) -> Result<Import<SE2>, Err> {
Ok(Import {
mode: self.mode,
- location: self.location.visit_subexpr(f)?,
+ location: self.location.traverse_ref(f)?,
hash: self.hash.clone(),
})
}
+ pub fn traverse_mut<'a, Err>(
+ &'a mut self,
+ f: impl FnOnce(&'a mut SE) -> Result<(), Err>,
+ ) -> Result<(), Err> {
+ self.location.traverse_mut(f)
+ }
}
diff --git a/dhall_syntax/src/core/map.rs b/dhall_syntax/src/core/map.rs
index 6a0ebda..c4c6126 100644
--- a/dhall_syntax/src/core/map.rs
+++ b/dhall_syntax/src/core/map.rs
@@ -13,6 +13,8 @@ mod one_or_more {
}
pub type Iter<'a, T> = Either<slice::Iter<'a, T>, iter::Once<&'a T>>;
+ pub type IterMut<'a, T> =
+ Either<slice::IterMut<'a, T>, iter::Once<&'a mut T>>;
pub type IntoIter<T> = Either<vec::IntoIter<T>, iter::Once<T>>;
impl<T> OneOrMore<T> {
@@ -36,6 +38,13 @@ mod one_or_more {
OneOrMore::One(x) => Either::Right(iter::once(x)),
}
}
+
+ pub fn iter_mut(&mut self) -> IterMut<'_, T> {
+ match self {
+ OneOrMore::More(vec) => Either::Left(vec.iter_mut()),
+ OneOrMore::One(x) => Either::Right(iter::once(x)),
+ }
+ }
}
impl<T> IntoIterator for OneOrMore<T> {
@@ -76,6 +85,19 @@ mod dup_tree_map {
iter: IterInternal<'a, K, V>,
size: usize,
}
+ pub type IterMutInternalIntermediate<'a, K, V> =
+ iter::Zip<iter::Repeat<&'a K>, one_or_more::IterMut<'a, V>>;
+ pub type IterMutInternal<'a, K, V> = iter::FlatMap<
+ btree_map::IterMut<'a, K, OneOrMore<V>>,
+ IterMutInternalIntermediate<'a, K, V>,
+ for<'b> fn(
+ (&'b K, &'b mut OneOrMore<V>),
+ ) -> IterMutInternalIntermediate<'b, K, V>,
+ >;
+ pub struct IterMut<'a, K, V> {
+ iter: IterMutInternal<'a, K, V>,
+ size: usize,
+ }
pub type IntoIterInternalIntermediate<K, V> =
iter::Zip<iter::Repeat<K>, one_or_more::IntoIter<V>>;
pub type IntoIterInternal<K, V> = iter::FlatMap<
@@ -134,6 +156,21 @@ mod dup_tree_map {
size: self.size,
}
}
+
+ pub fn iter_mut(&mut self) -> IterMut<'_, K, V>
+ where
+ K: Ord,
+ {
+ fn foo<'a, K, V>(
+ (k, oom): (&'a K, &'a mut OneOrMore<V>),
+ ) -> IterMutInternalIntermediate<'a, K, V> {
+ iter::repeat(k).zip(oom.iter_mut())
+ }
+ IterMut {
+ iter: self.map.iter_mut().flat_map(foo),
+ size: self.size,
+ }
+ }
}
impl<K, V> Default for DupTreeMap<K, V>
@@ -180,6 +217,18 @@ mod dup_tree_map {
}
}
+ impl<'a, K, V> IntoIterator for &'a mut DupTreeMap<K, V>
+ where
+ K: Ord,
+ {
+ type Item = (&'a K, &'a mut V);
+ type IntoIter = IterMut<'a, K, V>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+ }
+
impl<K, V> iter::FromIterator<(K, V)> for DupTreeMap<K, V>
where
K: Ord,
@@ -212,6 +261,22 @@ mod dup_tree_map {
}
}
+ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
+ type Item = (&'a K, &'a mut V);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let next = self.iter.next();
+ if next.is_some() {
+ self.size -= 1;
+ }
+ next
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.size, Some(self.size))
+ }
+ }
+
impl<K, V> Iterator for IntoIter<K, V>
where
K: Clone,
diff --git a/dhall_syntax/src/core/text.rs b/dhall_syntax/src/core/text.rs
index 10fd68a..fb390ee 100644
--- a/dhall_syntax/src/core/text.rs
+++ b/dhall_syntax/src/core/text.rs
@@ -40,6 +40,52 @@ impl<SubExpr> InterpolatedTextContents<SubExpr> {
Text(s) => s.is_empty(),
}
}
+
+ pub fn traverse_ref<'a, SubExpr2, E, F>(
+ &'a self,
+ mut f: F,
+ ) -> Result<InterpolatedTextContents<SubExpr2>, E>
+ where
+ F: FnMut(&'a SubExpr) -> Result<SubExpr2, E>,
+ {
+ use InterpolatedTextContents::{Expr, Text};
+ Ok(match self {
+ Expr(e) => Expr(f(e)?),
+ Text(s) => Text(s.clone()),
+ })
+ }
+ pub fn traverse_mut<'a, E, F>(&'a mut self, mut f: F) -> Result<(), E>
+ where
+ F: FnMut(&'a mut SubExpr) -> Result<(), E>,
+ {
+ use InterpolatedTextContents::Expr;
+ if let Expr(e) = self {
+ f(e)?;
+ }
+ Ok(())
+ }
+ pub fn map_ref<'a, SubExpr2, F>(
+ &'a self,
+ mut f: F,
+ ) -> InterpolatedTextContents<SubExpr2>
+ where
+ F: FnMut(&'a SubExpr) -> SubExpr2,
+ {
+ use InterpolatedTextContents::{Expr, Text};
+ match self {
+ Expr(e) => Expr(f(e)),
+ Text(s) => Text(s.clone()),
+ }
+ }
+ pub fn map_mut<'a, F>(&'a mut self, mut f: F)
+ where
+ F: FnMut(&'a mut SubExpr),
+ {
+ use InterpolatedTextContents::Expr;
+ if let Expr(e) = self {
+ f(e);
+ }
+ }
}
impl<SubExpr> InterpolatedText<SubExpr> {
@@ -76,6 +122,16 @@ impl<SubExpr> InterpolatedText<SubExpr> {
})
}
+ pub fn traverse_mut<'a, E, F>(&'a mut self, mut f: F) -> Result<(), E>
+ where
+ F: FnMut(&'a mut SubExpr) -> Result<(), E>,
+ {
+ for (e, _) in &mut self.tail {
+ f(e)?
+ }
+ Ok(())
+ }
+
pub fn iter<'a>(
&'a self,
) -> impl Iterator<Item = InterpolatedTextContents<&'a SubExpr>> + 'a {
diff --git a/dhall_syntax/src/core/visitor.rs b/dhall_syntax/src/core/visitor.rs
index 435771e..39a027f 100644
--- a/dhall_syntax/src/core/visitor.rs
+++ b/dhall_syntax/src/core/visitor.rs
@@ -1,11 +1,6 @@
use crate::*;
use std::iter::FromIterator;
-/// A way too generic Visitor trait.
-pub trait GenericVisitor<Input, Output>: Sized {
- fn visit(self, input: Input) -> Output;
-}
-
/// A visitor trait that can be used to traverse `ExprF`s. We need this pattern so that Rust lets
/// us have as much mutability as we can.
/// For example, `traverse_ref_with_special_handling_of_binders` cannot be made using only
@@ -14,7 +9,7 @@ pub trait GenericVisitor<Input, Output>: Sized {
/// preventing exactly this ! So we have to be more clever. The visitor pattern allows us to have
/// only one mutable thing the whole time: the visitor itself. The visitor can then carry around
/// multiple closures or just one, and Rust is ok with either. See for example TraverseRefVisitor.
-pub trait ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>: Sized {
+pub trait ExprFVisitor<'a, SE1, SE2, E1, E2>: Sized {
type Error;
fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result<SE2, Self::Error>;
@@ -27,174 +22,263 @@ pub trait ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>: Sized {
) -> Result<SE2, Self::Error> {
self.visit_subexpr(subexpr)
}
+
+ fn visit(
+ self,
+ input: &'a ExprF<SE1, E1>,
+ ) -> Result<ExprF<SE2, E2>, Self::Error> {
+ visit_ref(self, input)
+ }
}
-/// Like ExprFFallibleVisitor, but without the error handling.
-pub trait ExprFInFallibleVisitor<'a, SE1, SE2, E1, E2>: Sized {
- fn visit_subexpr(&mut self, subexpr: &'a SE1) -> SE2;
- fn visit_embed(self, embed: &'a E1) -> E2;
+/// Like `ExprFVisitor`, but by mutable reference
+pub trait ExprFMutVisitor<'a, SE, E>: Sized {
+ type Error;
+
+ fn visit_subexpr(&mut self, subexpr: &'a mut SE)
+ -> Result<(), Self::Error>;
+ fn visit_embed(self, _embed: &'a mut E) -> Result<(), Self::Error> {
+ Ok(())
+ }
fn visit_subexpr_under_binder(
mut self,
- _label: &'a Label,
- subexpr: &'a SE1,
- ) -> SE2 {
+ _label: &'a mut Label,
+ subexpr: &'a mut SE,
+ ) -> Result<(), Self::Error> {
self.visit_subexpr(subexpr)
}
+
+ fn visit(self, input: &'a mut ExprF<SE, E>) -> Result<(), Self::Error> {
+ visit_mut(self, input)
+ }
}
-impl<'a, T, SE1, SE2, E1, E2>
- GenericVisitor<&'a ExprF<SE1, E1>, Result<ExprF<SE2, E2>, T::Error>> for T
+fn visit_ref<'a, V, SE1, SE2, E1, E2>(
+ mut v: V,
+ input: &'a ExprF<SE1, E1>,
+) -> Result<ExprF<SE2, E2>, V::Error>
where
- T: ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>,
+ V: ExprFVisitor<'a, SE1, SE2, E1, E2>,
{
- fn visit(
- self,
- input: &'a ExprF<SE1, E1>,
- ) -> Result<ExprF<SE2, E2>, T::Error> {
- fn vec<'a, T, U, Err, F: FnMut(&'a T) -> Result<U, Err>>(
- x: &'a [T],
- f: F,
- ) -> Result<Vec<U>, Err> {
- x.iter().map(f).collect()
- }
- fn opt<'a, T, U, Err, F: FnOnce(&'a T) -> Result<U, Err>>(
- x: &'a Option<T>,
- f: F,
- ) -> Result<Option<U>, Err> {
- Ok(match x {
- Some(x) => Some(f(x)?),
- None => None,
+ fn vec<'a, T, U, Err, F: FnMut(&'a T) -> Result<U, Err>>(
+ x: &'a [T],
+ f: F,
+ ) -> Result<Vec<U>, Err> {
+ x.iter().map(f).collect()
+ }
+ fn opt<'a, T, U, Err, F: FnOnce(&'a T) -> Result<U, Err>>(
+ x: &'a Option<T>,
+ f: F,
+ ) -> Result<Option<U>, Err> {
+ Ok(match x {
+ Some(x) => Some(f(x)?),
+ None => None,
+ })
+ }
+ fn dupmap<'a, V, SE1, SE2, E1, E2, T>(
+ x: impl IntoIterator<Item = (&'a Label, &'a SE1)>,
+ mut v: V,
+ ) -> Result<T, V::Error>
+ where
+ SE1: 'a,
+ T: FromIterator<(Label, SE2)>,
+ V: ExprFVisitor<'a, SE1, SE2, E1, E2>,
+ {
+ x.into_iter()
+ .map(|(k, x)| Ok((k.clone(), v.visit_subexpr(x)?)))
+ .collect()
+ }
+ fn optdupmap<'a, V, SE1, SE2, E1, E2, T>(
+ x: impl IntoIterator<Item = (&'a Label, &'a Option<SE1>)>,
+ mut v: V,
+ ) -> Result<T, V::Error>
+ where
+ SE1: 'a,
+ T: FromIterator<(Label, Option<SE2>)>,
+ V: ExprFVisitor<'a, SE1, SE2, E1, E2>,
+ {
+ x.into_iter()
+ .map(|(k, x)| {
+ Ok((
+ k.clone(),
+ match x {
+ Some(x) => Some(v.visit_subexpr(x)?),
+ None => None,
+ },
+ ))
})
+ .collect()
+ }
+
+ use crate::ExprF::*;
+ Ok(match input {
+ Var(v) => Var(v.clone()),
+ Lam(l, t, e) => {
+ let t = v.visit_subexpr(t)?;
+ let e = v.visit_subexpr_under_binder(l, e)?;
+ Lam(l.clone(), t, e)
}
- fn dupmap<'a, V, SE1, SE2, E1, E2, T>(
- x: impl IntoIterator<Item = (&'a Label, &'a SE1)>,
- mut v: V,
- ) -> Result<T, V::Error>
- where
- SE1: 'a,
- T: FromIterator<(Label, SE2)>,
- V: ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>,
- {
- x.into_iter()
- .map(|(k, x)| Ok((k.clone(), v.visit_subexpr(x)?)))
- .collect()
+ Pi(l, t, e) => {
+ let t = v.visit_subexpr(t)?;
+ let e = v.visit_subexpr_under_binder(l, e)?;
+ Pi(l.clone(), t, e)
}
- fn optdupmap<'a, V, SE1, SE2, E1, E2, T>(
- x: impl IntoIterator<Item = (&'a Label, &'a Option<SE1>)>,
- mut v: V,
- ) -> Result<T, V::Error>
- where
- SE1: 'a,
- T: FromIterator<(Label, Option<SE2>)>,
- V: ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>,
- {
- x.into_iter()
- .map(|(k, x)| {
- Ok((
- k.clone(),
- match x {
- Some(x) => Some(v.visit_subexpr(x)?),
- None => None,
- },
- ))
- })
- .collect()
+ Let(l, t, a, e) => {
+ let t = opt(t, &mut |e| v.visit_subexpr(e))?;
+ let a = v.visit_subexpr(a)?;
+ let e = v.visit_subexpr_under_binder(l, e)?;
+ Let(l.clone(), t, a, e)
}
-
- let mut v = self;
- use crate::ExprF::*;
- Ok(match input {
- Var(v) => Var(v.clone()),
- Lam(l, t, e) => {
- let t = v.visit_subexpr(t)?;
- let e = v.visit_subexpr_under_binder(l, e)?;
- Lam(l.clone(), t, e)
- }
- Pi(l, t, e) => {
- let t = v.visit_subexpr(t)?;
- let e = v.visit_subexpr_under_binder(l, e)?;
- Pi(l.clone(), t, e)
- }
- Let(l, t, a, e) => {
- let t = opt(t, &mut |e| v.visit_subexpr(e))?;
- let a = v.visit_subexpr(a)?;
- let e = v.visit_subexpr_under_binder(l, e)?;
- Let(l.clone(), t, a, e)
- }
- App(f, a) => App(v.visit_subexpr(f)?, v.visit_subexpr(a)?),
- Annot(x, t) => Annot(v.visit_subexpr(x)?, v.visit_subexpr(t)?),
- Const(k) => Const(*k),
- Builtin(v) => Builtin(*v),
- BoolLit(b) => BoolLit(*b),
- NaturalLit(n) => NaturalLit(*n),
- IntegerLit(n) => IntegerLit(*n),
- DoubleLit(n) => DoubleLit(*n),
- TextLit(t) => TextLit(t.traverse_ref(|e| v.visit_subexpr(e))?),
- BinOp(o, x, y) => {
- BinOp(*o, v.visit_subexpr(x)?, v.visit_subexpr(y)?)
- }
- BoolIf(b, t, f) => BoolIf(
- v.visit_subexpr(b)?,
- v.visit_subexpr(t)?,
- v.visit_subexpr(f)?,
- ),
- EmptyListLit(t) => EmptyListLit(v.visit_subexpr(t)?),
- NEListLit(es) => NEListLit(vec(es, |e| v.visit_subexpr(e))?),
- SomeLit(e) => SomeLit(v.visit_subexpr(e)?),
- RecordType(kts) => RecordType(dupmap(kts, v)?),
- RecordLit(kvs) => RecordLit(dupmap(kvs, v)?),
- UnionType(kts) => UnionType(optdupmap(kts, v)?),
- Merge(x, y, t) => Merge(
- v.visit_subexpr(x)?,
- v.visit_subexpr(y)?,
- opt(t, |e| v.visit_subexpr(e))?,
- ),
- ToMap(x, t) => {
- ToMap(v.visit_subexpr(x)?, opt(t, |e| v.visit_subexpr(e))?)
- }
- Field(e, l) => Field(v.visit_subexpr(e)?, l.clone()),
- Projection(e, ls) => Projection(v.visit_subexpr(e)?, ls.clone()),
- Assert(e) => Assert(v.visit_subexpr(e)?),
- Import(i) => Import(i.visit_subexpr(|e| v.visit_subexpr(e))?),
- Embed(a) => Embed(v.visit_embed(a)?),
- })
- }
+ App(f, a) => App(v.visit_subexpr(f)?, v.visit_subexpr(a)?),
+ Annot(x, t) => Annot(v.visit_subexpr(x)?, v.visit_subexpr(t)?),
+ Const(k) => Const(*k),
+ Builtin(v) => Builtin(*v),
+ BoolLit(b) => BoolLit(*b),
+ NaturalLit(n) => NaturalLit(*n),
+ IntegerLit(n) => IntegerLit(*n),
+ DoubleLit(n) => DoubleLit(*n),
+ TextLit(t) => TextLit(t.traverse_ref(|e| v.visit_subexpr(e))?),
+ BinOp(o, x, y) => BinOp(*o, v.visit_subexpr(x)?, v.visit_subexpr(y)?),
+ BoolIf(b, t, f) => BoolIf(
+ v.visit_subexpr(b)?,
+ v.visit_subexpr(t)?,
+ v.visit_subexpr(f)?,
+ ),
+ EmptyListLit(t) => EmptyListLit(v.visit_subexpr(t)?),
+ NEListLit(es) => NEListLit(vec(es, |e| v.visit_subexpr(e))?),
+ SomeLit(e) => SomeLit(v.visit_subexpr(e)?),
+ RecordType(kts) => RecordType(dupmap(kts, v)?),
+ RecordLit(kvs) => RecordLit(dupmap(kvs, v)?),
+ UnionType(kts) => UnionType(optdupmap(kts, v)?),
+ Merge(x, y, t) => Merge(
+ v.visit_subexpr(x)?,
+ v.visit_subexpr(y)?,
+ opt(t, |e| v.visit_subexpr(e))?,
+ ),
+ ToMap(x, t) => {
+ ToMap(v.visit_subexpr(x)?, opt(t, |e| v.visit_subexpr(e))?)
+ }
+ Field(e, l) => Field(v.visit_subexpr(e)?, l.clone()),
+ Projection(e, ls) => Projection(v.visit_subexpr(e)?, ls.clone()),
+ Assert(e) => Assert(v.visit_subexpr(e)?),
+ Import(i) => Import(i.traverse_ref(|e| v.visit_subexpr(e))?),
+ Embed(a) => Embed(v.visit_embed(a)?),
+ })
}
-impl<'a, T, SE1, SE2, E1, E2> GenericVisitor<&'a ExprF<SE1, E1>, ExprF<SE2, E2>>
- for T
+fn visit_mut<'a, V, SE, E>(
+ mut v: V,
+ input: &'a mut ExprF<SE, E>,
+) -> Result<(), V::Error>
where
- T: ExprFInFallibleVisitor<'a, SE1, SE2, E1, E2>,
+ V: ExprFMutVisitor<'a, SE, E>,
{
- fn visit(self, input: &'a ExprF<SE1, E1>) -> ExprF<SE2, E2> {
- trivial_result(InfallibleWrapper(self).visit(input))
+ fn vec<'a, V, SE, E>(v: &mut V, x: &'a mut Vec<SE>) -> Result<(), V::Error>
+ where
+ V: ExprFMutVisitor<'a, SE, E>,
+ {
+ for x in x {
+ v.visit_subexpr(x)?;
+ }
+ Ok(())
}
-}
-
-struct InfallibleWrapper<T>(T);
-
-impl<'a, T, SE1, SE2, E1, E2> ExprFFallibleVisitor<'a, SE1, SE2, E1, E2>
- for InfallibleWrapper<T>
-where
- T: ExprFInFallibleVisitor<'a, SE1, SE2, E1, E2>,
-{
- type Error = !;
-
- fn visit_subexpr(&mut self, subexpr: &'a SE1) -> Result<SE2, Self::Error> {
- Ok(self.0.visit_subexpr(subexpr))
+ fn opt<'a, V, SE, E>(
+ v: &mut V,
+ x: &'a mut Option<SE>,
+ ) -> Result<(), V::Error>
+ where
+ V: ExprFMutVisitor<'a, SE, E>,
+ {
+ if let Some(x) = x {
+ v.visit_subexpr(x)?;
+ }
+ Ok(())
}
- fn visit_embed(self, embed: &'a E1) -> Result<E2, Self::Error> {
- Ok(self.0.visit_embed(embed))
+ fn dupmap<'a, V, SE, E>(
+ mut v: V,
+ x: impl IntoIterator<Item = (&'a Label, &'a mut SE)>,
+ ) -> Result<(), V::Error>
+ where
+ SE: 'a,
+ V: ExprFMutVisitor<'a, SE, E>,
+ {
+ for (_, x) in x {
+ v.visit_subexpr(x)?;
+ }
+ Ok(())
+ }
+ fn optdupmap<'a, V, SE, E>(
+ mut v: V,
+ x: impl IntoIterator<Item = (&'a Label, &'a mut Option<SE>)>,
+ ) -> Result<(), V::Error>
+ where
+ SE: 'a,
+ V: ExprFMutVisitor<'a, SE, E>,
+ {
+ for (_, x) in x {
+ opt(&mut v, x)?;
+ }
+ Ok(())
}
- fn visit_subexpr_under_binder(
- self,
- label: &'a Label,
- subexpr: &'a SE1,
- ) -> Result<SE2, Self::Error> {
- Ok(self.0.visit_subexpr_under_binder(label, subexpr))
+ use crate::ExprF::*;
+ match input {
+ Var(_) | Const(_) | Builtin(_) | BoolLit(_) | NaturalLit(_)
+ | IntegerLit(_) | DoubleLit(_) => {}
+ Lam(l, t, e) => {
+ v.visit_subexpr(t)?;
+ v.visit_subexpr_under_binder(l, e)?;
+ }
+ Pi(l, t, e) => {
+ v.visit_subexpr(t)?;
+ v.visit_subexpr_under_binder(l, e)?;
+ }
+ Let(l, t, a, e) => {
+ opt(&mut v, t)?;
+ v.visit_subexpr(a)?;
+ v.visit_subexpr_under_binder(l, e)?;
+ }
+ App(f, a) => {
+ v.visit_subexpr(f)?;
+ v.visit_subexpr(a)?;
+ }
+ Annot(x, t) => {
+ v.visit_subexpr(x)?;
+ v.visit_subexpr(t)?;
+ }
+ TextLit(t) => t.traverse_mut(|e| v.visit_subexpr(e))?,
+ BinOp(_, x, y) => {
+ v.visit_subexpr(x)?;
+ v.visit_subexpr(y)?;
+ }
+ BoolIf(b, t, f) => {
+ v.visit_subexpr(b)?;
+ v.visit_subexpr(t)?;
+ v.visit_subexpr(f)?;
+ }
+ EmptyListLit(t) => v.visit_subexpr(t)?,
+ NEListLit(es) => vec(&mut v, es)?,
+ SomeLit(e) => v.visit_subexpr(e)?,
+ RecordType(kts) => dupmap(v, kts)?,
+ RecordLit(kvs) => dupmap(v, kvs)?,
+ UnionType(kts) => optdupmap(v, kts)?,
+ Merge(x, y, t) => {
+ v.visit_subexpr(x)?;
+ v.visit_subexpr(y)?;
+ opt(&mut v, t)?;
+ }
+ ToMap(x, t) => {
+ v.visit_subexpr(x)?;
+ opt(&mut v, t)?;
+ }
+ Field(e, _) => v.visit_subexpr(e)?,
+ Projection(e, _) => v.visit_subexpr(e)?,
+ Assert(e) => v.visit_subexpr(e)?,
+ Import(i) => i.traverse_mut(|e| v.visit_subexpr(e))?,
+ Embed(a) => v.visit_embed(a)?,
}
+ Ok(())
}
pub struct TraverseRefWithBindersVisitor<F1, F2> {
@@ -202,7 +286,7 @@ pub struct TraverseRefWithBindersVisitor<F1, F2> {
pub visit_under_binder: F2,
}
-impl<'a, SE, E, SE2, Err, F1, F2> ExprFFallibleVisitor<'a, SE, SE2, E, E>
+impl<'a, SE, E, SE2, Err, F1, F2> ExprFVisitor<'a, SE, SE2, E, E>
for TraverseRefWithBindersVisitor<F1, F2>
where
SE: 'a,
@@ -231,7 +315,7 @@ pub struct TraverseRefVisitor<F1> {
pub visit_subexpr: F1,
}
-impl<'a, SE, E, SE2, Err, F1> ExprFFallibleVisitor<'a, SE, SE2, E, E>
+impl<'a, SE, E, SE2, Err, F1> ExprFVisitor<'a, SE, SE2, E, E>
for TraverseRefVisitor<F1>
where
SE: 'a,
@@ -248,26 +332,22 @@ where
}
}
-pub struct ResolveVisitor<F1>(pub F1);
+pub struct TraverseMutVisitor<F1> {
+ pub visit_subexpr: F1,
+}
-impl<'a, 'b, E, E2, Err, F1> ExprFFallibleVisitor<'a, Expr<E>, Expr<E2>, E, E2>
- for &'b mut ResolveVisitor<F1>
+impl<'a, SE, E, Err, F1> ExprFMutVisitor<'a, SE, E> for TraverseMutVisitor<F1>
where
- F1: FnMut(&Import<Expr<E2>>) -> Result<E2, Err>,
+ SE: 'a,
+ E: 'a,
+ F1: FnMut(&'a mut SE) -> Result<(), Err>,
{
type Error = Err;
fn visit_subexpr(
&mut self,
- subexpr: &'a Expr<E>,
- ) -> Result<Expr<E2>, Self::Error> {
- Ok(subexpr.rewrap(
- subexpr
- .as_ref()
- .traverse_resolve_with_visitor(&mut **self)?,
- ))
- }
- fn visit_embed(self, _embed: &'a E) -> Result<E2, Self::Error> {
- unimplemented!()
+ subexpr: &'a mut SE,
+ ) -> Result<(), Self::Error> {
+ (self.visit_subexpr)(subexpr)
}
}
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index 1262774..41d6d04 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -60,17 +60,32 @@ impl<'input> ParseInput<'input, Rule> {
original_input_str: self.original_input_str.clone(),
}
}
+ /// If the contained pair has exactly one child, return a new Self containing it.
+ fn single_child(&self) -> Option<Self> {
+ let mut children = self.pair.clone().into_inner();
+ if let Some(child) = children.next() {
+ if children.next().is_none() {
+ return Some(self.with_pair(child));
+ }
+ }
+ None
+ }
fn as_span(&self) -> Span {
Span::make(self.original_input_str.clone(), self.pair.as_span())
}
fn as_str(&self) -> &'input str {
self.pair.as_str()
}
+ fn as_rule(&self) -> Rule {
+ self.pair.as_rule()
+ }
}
-// Used to retrieve the `Rule` enum associated with the `Self` type in `parse_children`.
+// Used by the macros.
trait PestConsumer {
- type RuleEnum: pest::RuleType;
+ type Rule: pest::RuleType;
+ fn rule_alias(rule: Self::Rule) -> String;
+ fn allows_shortcut(rule: Self::Rule) -> bool;
}
fn debug_pair(pair: Pair<Rule>) -> String {
@@ -231,21 +246,17 @@ struct Parsers;
#[make_parser(Rule)]
impl Parsers {
- fn EOI(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn EOI(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
+ #[alias(label)]
fn simple_label(input: ParseInput<Rule>) -> ParseResult<Label> {
- Ok(Label::from(input.as_str().trim().to_owned()))
+ Ok(Label::from(input.as_str()))
}
+ #[alias(label)]
fn quoted_label(input: ParseInput<Rule>) -> ParseResult<Label> {
- Ok(Label::from(input.as_str().trim().to_owned()))
- }
- fn label(input: ParseInput<Rule>) -> ParseResult<Label> {
- Ok(parse_children!(input;
- [simple_label(l)] => l,
- [quoted_label(l)] => l,
- ))
+ Ok(Label::from(input.as_str()))
}
fn double_quote_literal<E: Clone>(
@@ -262,17 +273,15 @@ impl Parsers {
input: ParseInput<Rule>,
) -> ParseResult<ParsedTextContents<E>> {
Ok(parse_children!(input;
- [interpolation(e)] => {
+ [expression(e)] => {
InterpolatedTextContents::Expr(e)
},
- [double_quote_escaped(s)] => {
- InterpolatedTextContents::Text(s)
- },
[double_quote_char(s)] => {
- InterpolatedTextContents::Text(s.to_owned())
+ InterpolatedTextContents::Text(s)
},
))
}
+ #[alias(double_quote_char)]
fn double_quote_escaped(input: ParseInput<Rule>) -> ParseResult<String> {
Ok(match input.as_str() {
"\"" => "\"".to_owned(),
@@ -345,8 +354,8 @@ impl Parsers {
}
fn double_quote_char<'a>(
input: ParseInput<'a, Rule>,
- ) -> ParseResult<&'a str> {
- Ok(input.as_str())
+ ) -> ParseResult<String> {
+ Ok(input.as_str().to_owned())
}
fn single_quote_literal<E: Clone>(
@@ -356,6 +365,7 @@ impl Parsers {
[single_quote_continue(lines)] => {
let newline: ParsedText<E> = "\n".to_string().into();
+ // Reverse lines and chars in each line
let mut lines: Vec<ParsedText<E>> = lines
.into_iter()
.rev()
@@ -377,44 +387,27 @@ impl Parsers {
) -> ParseResult<&'a str> {
Ok(input.as_str())
}
- fn escaped_quote_pair<'a>(_: ParseInput<'a, Rule>) -> ParseResult<&'a str> {
+ #[alias(single_quote_char)]
+ fn escaped_quote_pair<'a>(
+ _input: ParseInput<'a, Rule>,
+ ) -> ParseResult<&'a str> {
Ok("''")
}
+ #[alias(single_quote_char)]
fn escaped_interpolation<'a>(
- _: ParseInput<'a, Rule>,
+ _input: ParseInput<'a, Rule>,
) -> ParseResult<&'a str> {
Ok("${")
}
- fn interpolation<E: Clone>(
- input: ParseInput<Rule>,
- ) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
- [expression(e)] => e
- ))
- }
// Returns a vec of lines in reversed order, where each line is also in reversed order.
fn single_quote_continue<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Vec<Vec<ParsedTextContents<E>>>> {
Ok(parse_children!(input;
- [interpolation(c), single_quote_continue(lines)] => {
- let c = InterpolatedTextContents::Expr(c);
- let mut lines = lines;
- lines.last_mut().unwrap().push(c);
- lines
- },
- [escaped_quote_pair(c), single_quote_continue(lines)] => {
+ [expression(e), single_quote_continue(lines)] => {
+ let c = InterpolatedTextContents::Expr(e);
let mut lines = lines;
- // TODO: don't allocate for every char
- let c = InterpolatedTextContents::Text(c.to_owned());
- lines.last_mut().unwrap().push(c);
- lines
- },
- [escaped_interpolation(c), single_quote_continue(lines)] => {
- let mut lines = lines;
- // TODO: don't allocate for every char
- let c = InterpolatedTextContents::Text(c.to_owned());
lines.last_mut().unwrap().push(c);
lines
},
@@ -435,38 +428,41 @@ impl Parsers {
))
}
+ #[alias(expression)]
fn builtin<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> {
let s = input.as_str();
- let span = input.as_span();
- Ok(spanned(
- span,
- match crate::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),
- _ => Err(input
- .error(format!("Unrecognized builtin: '{}'", s)))?,
- }
- }
+ let e = match crate::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),
+ _ => Err(input.error(format!("Unrecognized builtin: '{}'", s)))?,
},
- ))
+ };
+ Ok(spanned(input.as_span(), e))
}
- fn NaN(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
+ #[alias(double_literal)]
+ fn NaN(_input: ParseInput<Rule>) -> ParseResult<core::Double> {
+ Ok(std::f64::NAN.into())
}
- fn minus_infinity_literal(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
+ #[alias(double_literal)]
+ fn minus_infinity_literal(
+ _input: ParseInput<Rule>,
+ ) -> ParseResult<core::Double> {
+ Ok(std::f64::NEG_INFINITY.into())
}
- fn plus_infinity_literal(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
+ #[alias(double_literal)]
+ fn plus_infinity_literal(
+ _input: ParseInput<Rule>,
+ ) -> ParseResult<core::Double> {
+ Ok(std::f64::INFINITY.into())
}
+ #[alias(double_literal)]
fn numeric_double_literal(
input: ParseInput<Rule>,
) -> ParseResult<core::Double> {
@@ -481,15 +477,6 @@ impl Parsers {
}
}
- fn double_literal(input: ParseInput<Rule>) -> ParseResult<core::Double> {
- Ok(parse_children!(input;
- [numeric_double_literal(n)] => n,
- [minus_infinity_literal(_)] => std::f64::NEG_INFINITY.into(),
- [plus_infinity_literal(_)] => std::f64::INFINITY.into(),
- [NaN(_)] => std::f64::NAN.into(),
- ))
- }
-
fn natural_literal(input: ParseInput<Rule>) -> ParseResult<core::Natural> {
input
.as_str()
@@ -506,13 +493,13 @@ impl Parsers {
.map_err(|e| input.error(format!("{}", e)))
}
+ #[alias(expression, shortcut = true)]
fn identifier<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> {
- let span = input.as_span();
Ok(parse_children!(input;
[variable(v)] => {
- spanned(span, Var(v))
+ spanned(input.as_span(), Var(v))
},
- [builtin(e)] => e,
+ [expression(e)] => e,
))
}
@@ -527,42 +514,40 @@ impl Parsers {
))
}
+ #[alias(path_component)]
fn unquoted_path_component<'a>(
input: ParseInput<'a, Rule>,
- ) -> ParseResult<&'a str> {
- Ok(input.as_str())
+ ) -> ParseResult<String> {
+ Ok(input.as_str().to_string())
}
+ #[alias(path_component)]
fn quoted_path_component<'a>(
input: ParseInput<'a, Rule>,
- ) -> ParseResult<&'a str> {
- Ok(input.as_str())
- }
- fn path_component(input: ParseInput<Rule>) -> ParseResult<String> {
- Ok(parse_children!(input;
- [unquoted_path_component(s)] => s.to_string(),
- [quoted_path_component(s)] => {
- const RESERVED: &percent_encoding::AsciiSet =
- &percent_encoding::CONTROLS
- .add(b'=').add(b':').add(b'/').add(b'?')
- .add(b'#').add(b'[').add(b']').add(b'@')
- .add(b'!').add(b'$').add(b'&').add(b'\'')
- .add(b'(').add(b')').add(b'*').add(b'+')
- .add(b',').add(b';');
- s.chars()
- .map(|c| {
- // Percent-encode ascii chars
- if c.is_ascii() {
- percent_encoding::utf8_percent_encode(
- &c.to_string(),
- RESERVED,
- ).to_string()
- } else {
- c.to_string()
- }
- })
- .collect()
- },
- ))
+ ) -> ParseResult<String> {
+ #[rustfmt::skip]
+ const RESERVED: &percent_encoding::AsciiSet =
+ &percent_encoding::CONTROLS
+ .add(b'=').add(b':').add(b'/').add(b'?')
+ .add(b'#').add(b'[').add(b']').add(b'@')
+ .add(b'!').add(b'$').add(b'&').add(b'\'')
+ .add(b'(').add(b')').add(b'*').add(b'+')
+ .add(b',').add(b';');
+ Ok(input
+ .as_str()
+ .chars()
+ .map(|c| {
+ // Percent-encode ascii chars
+ if c.is_ascii() {
+ percent_encoding::utf8_percent_encode(
+ &c.to_string(),
+ RESERVED,
+ )
+ .to_string()
+ } else {
+ c.to_string()
+ }
+ })
+ .collect())
}
fn path(input: ParseInput<Rule>) -> ParseResult<FilePath> {
Ok(parse_children!(input;
@@ -572,30 +557,40 @@ impl Parsers {
))
}
- fn local(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> {
+ #[alias(import_type)]
+ fn local<E: Clone>(
+ input: ParseInput<Rule>,
+ ) -> ParseResult<ImportLocation<Expr<E>>> {
Ok(parse_children!(input;
- [parent_path(l)] => l,
- [here_path(l)] => l,
- [home_path(l)] => l,
- [absolute_path(l)] => l,
+ [local_path((prefix, p))] => ImportLocation::Local(prefix, p),
))
}
- fn parent_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> {
+ #[alias(local_path)]
+ fn parent_path(
+ input: ParseInput<Rule>,
+ ) -> ParseResult<(FilePrefix, FilePath)> {
Ok(parse_children!(input;
[path(p)] => (FilePrefix::Parent, p)
))
}
- fn here_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> {
+ #[alias(local_path)]
+ fn here_path(
+ input: ParseInput<Rule>,
+ ) -> ParseResult<(FilePrefix, FilePath)> {
Ok(parse_children!(input;
[path(p)] => (FilePrefix::Here, p)
))
}
- fn home_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> {
+ #[alias(local_path)]
+ fn home_path(
+ input: ParseInput<Rule>,
+ ) -> ParseResult<(FilePrefix, FilePath)> {
Ok(parse_children!(input;
[path(p)] => (FilePrefix::Home, p)
))
}
+ #[alias(local_path)]
fn absolute_path(
input: ParseInput<Rule>,
) -> ParseResult<(FilePrefix, FilePath)> {
@@ -641,25 +636,31 @@ impl Parsers {
Ok(input.as_str().to_owned())
}
- fn http<E: Clone>(input: ParseInput<Rule>) -> ParseResult<URL<Expr<E>>> {
- Ok(parse_children!(input;
- [http_raw(url)] => url,
- [http_raw(url), import_expression(e)] =>
- URL { headers: Some(e), ..url },
- ))
+ #[alias(import_type)]
+ fn http<E: Clone>(
+ input: ParseInput<Rule>,
+ ) -> ParseResult<ImportLocation<Expr<E>>> {
+ Ok(ImportLocation::Remote(parse_children!(input;
+ [http_raw(url)] => url,
+ [http_raw(url), expression(e)] => URL { headers: Some(e), ..url },
+ )))
}
- fn env(input: ParseInput<Rule>) -> ParseResult<String> {
+ #[alias(import_type)]
+ fn env<E: Clone>(
+ input: ParseInput<Rule>,
+ ) -> ParseResult<ImportLocation<Expr<E>>> {
Ok(parse_children!(input;
- [bash_environment_variable(s)] => s,
- [posix_environment_variable(s)] => s,
+ [environment_variable(v)] => ImportLocation::Env(v),
))
}
+ #[alias(environment_variable)]
fn bash_environment_variable(
input: ParseInput<Rule>,
) -> ParseResult<String> {
Ok(input.as_str().to_owned())
}
+ #[alias(environment_variable)]
fn posix_environment_variable(
input: ParseInput<Rule>,
) -> ParseResult<String> {
@@ -686,27 +687,11 @@ impl Parsers {
})
}
- fn missing(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
- }
-
- fn import_type<E: Clone>(
- input: ParseInput<Rule>,
+ #[alias(import_type)]
+ fn missing<E: Clone>(
+ _input: ParseInput<Rule>,
) -> ParseResult<ImportLocation<Expr<E>>> {
- Ok(parse_children!(input;
- [missing(_)] => {
- ImportLocation::Missing
- },
- [env(e)] => {
- ImportLocation::Env(e)
- },
- [http(url)] => {
- ImportLocation::Remote(url)
- },
- [local((prefix, p))] => {
- ImportLocation::Local(prefix, p)
- },
- ))
+ Ok(ImportLocation::Missing)
}
fn hash(input: ParseInput<Rule>) -> ParseResult<Hash> {
@@ -722,78 +707,65 @@ impl Parsers {
fn import_hashed<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<crate::Import<Expr<E>>> {
+ use crate::Import;
+ let mode = ImportMode::Code;
Ok(parse_children!(input;
- [import_type(location)] =>
- crate::Import {mode: ImportMode::Code, location, hash: None },
- [import_type(location), hash(h)] =>
- crate::Import {mode: ImportMode::Code, location, hash: Some(h) },
+ [import_type(location)] => Import { mode, location, hash: None },
+ [import_type(location), hash(h)] => Import { mode, location, hash: Some(h) },
))
}
- fn Text(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
+ #[alias(import_mode)]
+ fn Text(_input: ParseInput<Rule>) -> ParseResult<ImportMode> {
+ Ok(ImportMode::RawText)
}
- fn Location(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
+ #[alias(import_mode)]
+ fn Location(_input: ParseInput<Rule>) -> ParseResult<ImportMode> {
+ Ok(ImportMode::Location)
}
+ #[alias(expression)]
fn import<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> {
- let span = input.as_span();
- Ok(parse_children!(input;
+ use crate::Import;
+ let import = parse_children!(input;
[import_hashed(imp)] => {
- spanned(span, Import(crate::Import {
- mode: ImportMode::Code,
- ..imp
- }))
- },
- [import_hashed(imp), Text(_)] => {
- spanned(span, Import(crate::Import {
- mode: ImportMode::RawText,
- ..imp
- }))
+ Import { mode: ImportMode::Code, ..imp }
},
- [import_hashed(imp), Location(_)] => {
- spanned(span, Import(crate::Import {
- mode: ImportMode::Location,
- ..imp
- }))
+ [import_hashed(imp), import_mode(mode)] => {
+ Import { mode, ..imp }
},
- ))
+ );
+ Ok(spanned(input.as_span(), Import(import)))
}
- fn lambda(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
- }
- fn forall(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn lambda(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
- fn arrow(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn forall(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
- fn merge(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn arrow(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
- fn assert(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn merge(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
- fn if_(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn assert(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
- fn in_(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn if_(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
- fn toMap(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn toMap(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
+ #[alias(expression)]
fn empty_list_literal<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
- let span = input.as_span();
Ok(parse_children!(input;
- [application_expression(e)] => {
- spanned(span, EmptyListLit(e))
- },
+ [expression(e)] => spanned(input.as_span(), EmptyListLit(e)),
))
}
@@ -808,7 +780,7 @@ impl Parsers {
expression(right)] => {
spanned(span, BoolIf(cond, left, right))
},
- [let_binding(bindings).., in_(()), expression(final_expr)] => {
+ [let_binding(bindings).., expression(final_expr)] => {
bindings.rev().fold(
final_expr,
|acc, x| unspanned(Let(x.0, x.1, x.2, acc))
@@ -818,24 +790,22 @@ impl Parsers {
arrow(()), expression(body)] => {
spanned(span, Pi(l, typ, body))
},
- [operator_expression(typ), arrow(()), expression(body)] => {
+ [expression(typ), arrow(()), expression(body)] => {
spanned(span, Pi("_".into(), typ, body))
},
- [merge(()), import_expression(x), import_expression(y),
- application_expression(z)] => {
+ [merge(()), expression(x), expression(y), expression(z)] => {
spanned(span, Merge(x, y, Some(z)))
},
- [empty_list_literal(e)] => e,
[assert(()), expression(x)] => {
spanned(span, Assert(x))
},
- [toMap(()), import_expression(x), application_expression(y)] => {
+ [toMap(()), expression(x), expression(y)] => {
spanned(span, ToMap(x, Some(y)))
},
- [operator_expression(e)] => e,
- [operator_expression(e), expression(annot)] => {
+ [expression(e), expression(annot)] => {
spanned(span, Annot(e, annot))
},
+ [expression(e)] => e,
))
}
@@ -850,14 +820,8 @@ impl Parsers {
))
}
- fn List(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
- }
- fn Optional(_: ParseInput<Rule>) -> ParseResult<()> {
- Ok(())
- }
-
- #[prec_climb(application_expression, PRECCLIMBER)]
+ #[alias(expression, shortcut = true)]
+ #[prec_climb(expression, PRECCLIMBER)]
fn operator_expression<E: Clone>(
input: ParseInput<Rule>,
l: Expr<E>,
@@ -886,55 +850,48 @@ impl Parsers {
Ok(unspanned(BinOp(op, l, r)))
}
- fn Some_(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn Some_(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
+ #[alias(expression, shortcut = true)]
fn application_expression<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
Ok(parse_children!(input;
- [first_application_expression(e)] => e,
- [first_application_expression(first),
- import_expression(rest)..] => {
+ [expression(e)] => e,
+ [expression(first), expression(rest)..] => {
rest.fold(first, |acc, e| unspanned(App(acc, e)))
},
))
}
+ #[alias(expression, shortcut = true)]
fn first_application_expression<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
let span = input.as_span();
Ok(parse_children!(input;
- [Some_(()), import_expression(e)] => {
+ [Some_(()), expression(e)] => {
spanned(span, SomeLit(e))
},
- [merge(()), import_expression(x), import_expression(y)] => {
+ [merge(()), expression(x), expression(y)] => {
spanned(span, Merge(x, y, None))
},
- [toMap(()), import_expression(x)] => {
+ [toMap(()), expression(x)] => {
spanned(span, ToMap(x, None))
},
- [import_expression(e)] => e,
- ))
- }
-
- fn import_expression<E: Clone>(
- input: ParseInput<Rule>,
- ) -> ParseResult<Expr<E>> {
- Ok(parse_children!(input;
- [selector_expression(e)] => e,
- [import(e)] => e,
+ [expression(e)] => e,
))
}
+ #[alias(expression, shortcut = true)]
fn selector_expression<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
Ok(parse_children!(input;
- [primitive_expression(e)] => e,
- [primitive_expression(first), selector(rest)..] => {
+ [expression(e)] => e,
+ [expression(first), selector(rest)..] => {
rest.fold(first, |acc, e| unspanned(match e {
Either::Left(l) => Field(acc, l),
Either::Right(ls) => Projection(acc, ls),
@@ -959,6 +916,7 @@ impl Parsers {
))
}
+ #[alias(expression, shortcut = true)]
fn primitive_expression<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
@@ -969,46 +927,41 @@ impl Parsers {
[integer_literal(n)] => spanned(span, IntegerLit(n)),
[double_quote_literal(s)] => spanned(span, TextLit(s)),
[single_quote_literal(s)] => spanned(span, TextLit(s)),
- [empty_record_type(e)] => e,
- [empty_record_literal(e)] => e,
- [non_empty_record_type_or_literal(e)] => e,
- [union_type(e)] => e,
- [non_empty_list_literal(e)] => e,
- [identifier(e)] => e,
[expression(e)] => e,
))
}
+ #[alias(expression)]
fn empty_record_literal<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
- let span = input.as_span();
- Ok(spanned(span, RecordLit(Default::default())))
+ Ok(spanned(input.as_span(), RecordLit(Default::default())))
}
+ #[alias(expression)]
fn empty_record_type<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
- let span = input.as_span();
- Ok(spanned(span, RecordType(Default::default())))
+ Ok(spanned(input.as_span(), RecordType(Default::default())))
}
+ #[alias(expression)]
fn non_empty_record_type_or_literal<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
- let span = input.as_span();
- Ok(parse_children!(input;
+ let e = parse_children!(input;
[label(first_label), non_empty_record_type(rest)] => {
let (first_expr, mut map) = rest;
map.insert(first_label, first_expr);
- spanned(span, RecordType(map))
+ RecordType(map)
},
[label(first_label), non_empty_record_literal(rest)] => {
let (first_expr, mut map) = rest;
map.insert(first_label, first_expr);
- spanned(span, RecordLit(map))
+ RecordLit(map)
},
- ))
+ );
+ Ok(spanned(input.as_span(), e))
}
fn non_empty_record_type<E: Clone>(
@@ -1047,19 +1000,16 @@ impl Parsers {
))
}
+ #[alias(expression)]
fn union_type<E: Clone>(input: ParseInput<Rule>) -> ParseResult<Expr<E>> {
- let span = input.as_span();
- Ok(parse_children!(input;
- [empty_union_type(_)] => {
- spanned(span, UnionType(Default::default()))
- },
- [union_type_entry(entries)..] => {
- spanned(span, UnionType(entries.collect()))
- },
- ))
+ let map = parse_children!(input;
+ [empty_union_type(_)] => Default::default(),
+ [union_type_entry(entries)..] => entries.collect(),
+ );
+ Ok(spanned(input.as_span(), UnionType(map)))
}
- fn empty_union_type(_: ParseInput<Rule>) -> ParseResult<()> {
+ fn empty_union_type(_input: ParseInput<Rule>) -> ParseResult<()> {
Ok(())
}
@@ -1072,13 +1022,13 @@ impl Parsers {
))
}
+ #[alias(expression)]
fn non_empty_list_literal<E: Clone>(
input: ParseInput<Rule>,
) -> ParseResult<Expr<E>> {
- let span = input.as_span();
Ok(parse_children!(input;
[expression(items)..] => spanned(
- span,
+ input.as_span(),
NEListLit(items.collect())
)
))
diff --git a/tests_buffer b/tests_buffer
index 6597d69..1c4cde5 100644
--- a/tests_buffer
+++ b/tests_buffer
@@ -4,6 +4,7 @@ parser:
text interpolation and escapes
projection by expression unit tests
fix fakeurlencode test
+s/QuotedVariable/VariableQuoted/
success/
operators/
PrecedenceAll1 a ? b || c + d ++ e # f && g ∧ h ⫽ i ⩓ j * k == l != m n.o
@@ -13,6 +14,7 @@ success/
EmptyRecordLiteral {=}
ToMap toMap x
ToMapAnnot toMap x : T
+ VariableQuotedSpace ` x `
failure/
AssertNoAnnotation assert