summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2020-04-10 12:10:53 +0100
committerNadrieril2020-04-10 12:10:53 +0100
commitefe4b340bebaa7ef8bce6e69194959b126c5fade (patch)
tree627fa7b0b2b951efc4102d02e0a8f5a05e4aa03e
parentda80ef06a91e3869cc3c1d4dbd07259c408ff490 (diff)
Deserialize `Prelude.Map` and `toMap` to a map instead of a list
-rw-r--r--README.md4
-rw-r--r--dhall/src/operations/normalization.rs4
-rw-r--r--dhall/src/operations/typecheck.rs6
-rw-r--r--dhall/src/syntax/ast/label.rs6
-rw-r--r--serde_dhall/src/static_type.rs1
-rw-r--r--serde_dhall/src/value.rs58
-rw-r--r--serde_dhall/tests/de.rs4
-rw-r--r--tests_buffer1
8 files changed, 74 insertions, 10 deletions
diff --git a/README.md b/README.md
index 6d9372b..e4411d3 100644
--- a/README.md
+++ b/README.md
@@ -169,8 +169,12 @@ same name as the corresponding test.
#### [Unreleased]
+- Deserialize `Prelude.Map` and `toMap` to a map instead of a list.
+
#### [0.5.1] - 2020-04-09
+- Small fixes
+
#### [0.5.0] - 2020-04-05
- Add `serde_dhall::from_file` to read a Dhall file directly.
diff --git a/dhall/src/operations/normalization.rs b/dhall/src/operations/normalization.rs
index e3a9415..86fed13 100644
--- a/dhall/src/operations/normalization.rs
+++ b/dhall/src/operations/normalization.rs
@@ -226,11 +226,11 @@ pub fn normalize_operation(opkind: &OpKind<Nir>) -> Ret {
Some(h) => ret_kind(h.app_to_kind(v.clone())),
None => nothing_to_do(),
},
- EmptyOptionalLit(_) => match kvs.get(&"None".into()) {
+ EmptyOptionalLit(_) => match kvs.get("None") {
Some(h) => ret_ref(h),
None => nothing_to_do(),
},
- NEOptionalLit(v) => match kvs.get(&"Some".into()) {
+ NEOptionalLit(v) => match kvs.get("Some") {
Some(h) => ret_kind(h.app_to_kind(v.clone())),
None => nothing_to_do(),
},
diff --git a/dhall/src/operations/typecheck.rs b/dhall/src/operations/typecheck.rs
index 91d5059..314c587 100644
--- a/dhall/src/operations/typecheck.rs
+++ b/dhall/src/operations/typecheck.rs
@@ -398,11 +398,11 @@ pub fn typecheck_operation(
if kts.len() != 2 {
return span_err(err_msg);
}
- match kts.get(&"mapKey".into()) {
+ match kts.get("mapKey") {
Some(t) if *t == Nir::from_builtin(Builtin::Text) => {}
_ => return span_err(err_msg),
}
- match kts.get(&"mapValue".into()) {
+ match kts.get("mapValue") {
Some(_) => {}
None => return span_err(err_msg),
}
@@ -434,7 +434,7 @@ pub fn typecheck_operation(
}
Field(scrut, x) => {
match scrut.ty().kind() {
- RecordType(kts) => match kts.get(&x) {
+ RecordType(kts) => match kts.get(x) {
Some(val) => Type::new_infer_universe(env, val.clone())?,
None => return span_err("MissingRecordField"),
},
diff --git a/dhall/src/syntax/ast/label.rs b/dhall/src/syntax/ast/label.rs
index 43c3f53..2abde80 100644
--- a/dhall/src/syntax/ast/label.rs
+++ b/dhall/src/syntax/ast/label.rs
@@ -24,6 +24,12 @@ impl From<&Label> for String {
}
}
+impl std::borrow::Borrow<str> for Label {
+ fn borrow(&self) -> &str {
+ self.0.as_ref()
+ }
+}
+
impl Label {
pub fn from_str(s: &str) -> Label {
Label(s.into())
diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs
index 26c70cd..3c5da18 100644
--- a/serde_dhall/src/static_type.rs
+++ b/serde_dhall/src/static_type.rs
@@ -47,6 +47,7 @@ use crate::SimpleType;
/// `{ _1: T, _2: U }` | `(T, U)`, structs
/// `{ x: T, y: T }` | `HashMap<String, T>`, structs
/// `< x: T \| y: U >` | enums
+/// `Prelude.Map.Type Text T` | `HashMap<String, T>`, structs
/// `T -> U` | unsupported
/// `Prelude.JSON.Type` | unsupported
/// `Prelude.Map.Type T U` | unsupported
diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs
index 03cfdba..0f0b256 100644
--- a/serde_dhall/src/value.rs
+++ b/serde_dhall/src/value.rs
@@ -144,13 +144,61 @@ impl SimpleValue {
NirKind::NEOptionalLit(x) => {
SimpleValue::Optional(Some(Box::new(Self::from_nir(x)?)))
}
- NirKind::EmptyListLit(_) => SimpleValue::List(vec![]),
- NirKind::NEListLit(xs) => SimpleValue::List(
- xs.iter().map(Self::from_nir).collect::<Option<_>>()?,
- ),
+ NirKind::EmptyListLit(t) => {
+ // Detect and handle the special records that make assoc maps
+ if let NirKind::RecordType(kts) = t.kind() {
+ if kts.len() == 2
+ && kts.contains_key("mapKey")
+ && kts.contains_key("mapValue")
+ {
+ return Some(SimpleValue::Record(Default::default()));
+ }
+ }
+ SimpleValue::List(vec![])
+ }
+ NirKind::NEListLit(xs) => {
+ // Detect and handle the special records that make assoc maps
+ if let NirKind::RecordLit(kvs) = xs[0].kind() {
+ if kvs.len() == 2
+ && kvs.contains_key("mapKey")
+ && kvs.contains_key("mapValue")
+ {
+ let convert_entry = |x: &Nir| match x.kind() {
+ NirKind::RecordLit(kvs) => {
+ let k = match kvs.get("mapKey").unwrap().kind()
+ {
+ NirKind::TextLit(t)
+ if t.as_text().is_some() =>
+ {
+ t.as_text().unwrap()
+ }
+ // TODO
+ _ => panic!(
+ "Expected `mapKey` to be a text \
+ literal"
+ ),
+ };
+ let v = Self::from_nir(
+ kvs.get("mapValue").unwrap(),
+ )?;
+ Some((k, v))
+ }
+ _ => unreachable!("Internal type error"),
+ };
+ return Some(SimpleValue::Record(
+ xs.iter()
+ .map(convert_entry)
+ .collect::<Option<_>>()?,
+ ));
+ }
+ }
+ SimpleValue::List(
+ xs.iter().map(Self::from_nir).collect::<Option<_>>()?,
+ )
+ }
NirKind::RecordLit(kvs) => SimpleValue::Record(
kvs.iter()
- .map(|(k, v)| Some((k.into(), Self::from_nir(v)?)))
+ .map(|(k, v)| Some((k.to_string(), Self::from_nir(v)?)))
.collect::<Option<_>>()?,
),
NirKind::UnionLit(field, x, _) => SimpleValue::Union(
diff --git a/serde_dhall/tests/de.rs b/serde_dhall/tests/de.rs
index 41b4080..1932e26 100644
--- a/serde_dhall/tests/de.rs
+++ b/serde_dhall/tests/de.rs
@@ -80,6 +80,10 @@ fn test_de_untyped() {
parse::<HashMap<String, usize>>("{ x = 1, y = 2 }"),
expected_map
);
+ assert_eq!(
+ parse::<HashMap<String, usize>>("toMap { x = 1, y = 2 }"),
+ expected_map
+ );
let mut expected_map = HashMap::new();
expected_map.insert("if".to_string(), 1);
diff --git a/tests_buffer b/tests_buffer
index bd76d36..3240b41 100644
--- a/tests_buffer
+++ b/tests_buffer
@@ -24,6 +24,7 @@ normalization:
move builtins and operators in their own folder ?
RecordSortFields { b = 1, a = 0 }
RecordTypeSortFields { b : Bool, a : Natural }
+\(foo: { x: Bool, y: Bool }) -> \(bar: { x: Bool }) -> (foo.{x, y} // bar).{ x }
type-inference:
something that involves destructuring a recordtype after merge