summaryrefslogtreecommitdiff
path: root/dhall/src/phase/binary.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dhall/src/phase/binary.rs158
1 files changed, 114 insertions, 44 deletions
diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs
index 1812131..5e7eb40 100644
--- a/dhall/src/phase/binary.rs
+++ b/dhall/src/phase/binary.rs
@@ -48,10 +48,21 @@ fn cbor_value_to_dhall(
Bool(b) => BoolLit(*b),
Array(vec) => match vec.as_slice() {
[String(l), U64(n)] => {
+ if l.as_str() == "_" {
+ Err(DecodeError::WrongFormatError(
+ "`_` variable was encoded incorrectly".to_owned(),
+ ))?
+ }
let l = Label::from(l.as_str());
Var(V(l, *n as usize))
}
[U64(0), f, args..] => {
+ if args.is_empty() {
+ Err(DecodeError::WrongFormatError(
+ "Function application must have at least one argument"
+ .to_owned(),
+ ))?
+ }
let mut f = cbor_value_to_dhall(&f)?;
for a in args {
let a = cbor_value_to_dhall(&a)?;
@@ -65,6 +76,11 @@ fn cbor_value_to_dhall(
Lam(Label::from("_"), x, y)
}
[U64(1), String(l), x, y] => {
+ if l.as_str() == "_" {
+ Err(DecodeError::WrongFormatError(
+ "`_` variable was encoded incorrectly".to_owned(),
+ ))?
+ }
let x = cbor_value_to_dhall(&x)?;
let y = cbor_value_to_dhall(&y)?;
let l = Label::from(l.as_str());
@@ -76,6 +92,11 @@ fn cbor_value_to_dhall(
Pi(Label::from("_"), x, y)
}
[U64(2), String(l), x, y] => {
+ if l.as_str() == "_" {
+ Err(DecodeError::WrongFormatError(
+ "`_` variable was encoded incorrectly".to_owned(),
+ ))?
+ }
let x = cbor_value_to_dhall(&x)?;
let y = cbor_value_to_dhall(&y)?;
let l = Label::from(l.as_str());
@@ -106,7 +127,7 @@ fn cbor_value_to_dhall(
}
[U64(4), t] => {
let t = cbor_value_to_dhall(&t)?;
- EmptyListLit(t)
+ EmptyListLit(rc(App(rc(ExprF::Builtin(Builtin::List)), t)))
}
[U64(4), Null, rest..] => {
let rest = rest
@@ -115,18 +136,22 @@ fn cbor_value_to_dhall(
.collect::<Result<Vec<_>, _>>()?;
NEListLit(rest)
}
- [U64(5), t] => {
- let t = cbor_value_to_dhall(&t)?;
- OldOptionalLit(None, t)
- }
[U64(5), Null, x] => {
let x = cbor_value_to_dhall(&x)?;
SomeLit(x)
}
+ // Old-style optional literals
+ [U64(5), t] => {
+ let t = cbor_value_to_dhall(&t)?;
+ App(rc(ExprF::Builtin(Builtin::OptionalNone)), t)
+ }
[U64(5), t, x] => {
let x = cbor_value_to_dhall(&x)?;
let t = cbor_value_to_dhall(&t)?;
- OldOptionalLit(Some(x), t)
+ Annot(
+ rc(SomeLit(x)),
+ rc(App(rc(ExprF::Builtin(Builtin::Optional)), t)),
+ )
}
[U64(6), x, y] => {
let x = cbor_value_to_dhall(&x)?;
@@ -156,12 +181,9 @@ fn cbor_value_to_dhall(
let map = cbor_map_to_dhall_opt_map(map)?;
UnionType(map)
}
- [U64(12), String(l), x, Object(map)] => {
- let map = cbor_map_to_dhall_opt_map(map)?;
- let x = cbor_value_to_dhall(&x)?;
- let l = Label::from(l.as_str());
- UnionLit(l, x, map)
- }
+ [U64(12), ..] => Err(DecodeError::WrongFormatError(
+ "Union literals are not supported anymore".to_owned(),
+ ))?,
[U64(14), x, y, z] => {
let x = cbor_value_to_dhall(&x)?;
let y = cbor_value_to_dhall(&y)?;
@@ -191,8 +213,13 @@ fn cbor_value_to_dhall(
}
[U64(24), hash, U64(mode), U64(scheme), rest..] => {
let mode = match mode {
+ 0 => ImportMode::Code,
1 => ImportMode::RawText,
- _ => ImportMode::Code,
+ 2 => ImportMode::Location,
+ _ => Err(DecodeError::WrongFormatError(format!(
+ "import/mode/unknown_mode: {:?}",
+ mode
+ )))?,
};
let hash = match hash {
Null => None,
@@ -216,18 +243,20 @@ fn cbor_value_to_dhall(
};
let headers = match rest.next() {
Some(Null) => None,
- Some(x) => {
- match cbor_value_to_dhall(&x)?.as_ref() {
- Embed(import) => Some(Box::new(
- import.location_hashed.clone(),
- )),
- _ => Err(DecodeError::WrongFormatError(
- "import/remote/headers".to_owned(),
- ))?,
- }
- }
+ // TODO
+ // Some(x) => {
+ // match cbor_value_to_dhall(&x)?.as_ref() {
+ // Embed(import) => Some(Box::new(
+ // import.location_hashed.clone(),
+ // )),
+ // _ => Err(DecodeError::WrongFormatError(
+ // "import/remote/headers".to_owned(),
+ // ))?,
+ // }
+ // }
_ => Err(DecodeError::WrongFormatError(
- "import/remote/headers".to_owned(),
+ "import/remote/headers is unimplemented"
+ .to_owned(),
))?,
};
let authority = match rest.next() {
@@ -330,6 +359,10 @@ fn cbor_value_to_dhall(
let y = cbor_value_to_dhall(&y)?;
Annot(x, y)
}
+ [U64(28), x] => {
+ let x = cbor_value_to_dhall(&x)?;
+ EmptyListLit(x)
+ }
_ => Err(DecodeError::WrongFormatError(format!("{:?}", data)))?,
},
_ => Err(DecodeError::WrongFormatError(format!("{:?}", data)))?,
@@ -378,7 +411,6 @@ enum Serialize<'a> {
CBOR(cbor::Value),
RecordMap(&'a DupTreeMap<Label, ParsedSubExpr>),
UnionMap(&'a DupTreeMap<Label, Option<ParsedSubExpr>>),
- Import(&'a Import),
}
macro_rules! count {
@@ -403,6 +435,7 @@ where
S: serde::ser::Serializer,
{
use cbor::Value::{String, I64, U64};
+ use dhall_syntax::Builtin;
use dhall_syntax::ExprF::*;
use std::iter::once;
@@ -444,12 +477,23 @@ where
ser_seq!(ser; tag(2), expr(x), expr(y))
}
Pi(l, x, y) => ser_seq!(ser; tag(2), label(l), expr(x), expr(y)),
- // TODO: multilet
- Let(l, None, x, y) => {
- ser_seq!(ser; tag(25), label(l), null(), expr(x), expr(y))
- }
- Let(l, Some(t), x, y) => {
- ser_seq!(ser; tag(25), label(l), expr(t), expr(x), expr(y))
+ Let(_, _, _, _) => {
+ let (bound_e, bindings) = collect_nested_lets(e);
+ let count = 1 + 3 * bindings.len() + 1;
+
+ use serde::ser::SerializeSeq;
+ let mut ser_seq = ser.serialize_seq(Some(count))?;
+ ser_seq.serialize_element(&tag(25))?;
+ for (l, t, v) in bindings {
+ ser_seq.serialize_element(&label(l))?;
+ match t {
+ Some(t) => ser_seq.serialize_element(&expr(t))?,
+ None => ser_seq.serialize_element(&null())?,
+ }
+ ser_seq.serialize_element(&expr(v))?;
+ }
+ ser_seq.serialize_element(&expr(bound_e))?;
+ ser_seq.end()
}
App(_, _) => {
let (f, args) = collect_nested_applications(e);
@@ -460,10 +504,14 @@ where
)
}
Annot(x, y) => ser_seq!(ser; tag(26), expr(x), expr(y)),
- OldOptionalLit(None, t) => ser_seq!(ser; tag(5), expr(t)),
- OldOptionalLit(Some(x), t) => ser_seq!(ser; tag(5), expr(t), expr(x)),
SomeLit(x) => ser_seq!(ser; tag(5), null(), expr(x)),
- EmptyListLit(x) => ser_seq!(ser; tag(4), expr(x)),
+ EmptyListLit(x) => match x.as_ref() {
+ App(f, a) => match f.as_ref() {
+ ExprF::Builtin(Builtin::List) => ser_seq!(ser; tag(4), expr(a)),
+ _ => ser_seq!(ser; tag(28), expr(x)),
+ },
+ _ => ser_seq!(ser; tag(28), expr(x)),
+ },
NEListLit(xs) => ser.collect_seq(
once(tag(4)).chain(once(null())).chain(xs.iter().map(expr)),
),
@@ -477,9 +525,6 @@ where
RecordType(map) => ser_seq!(ser; tag(7), RecordMap(map)),
RecordLit(map) => ser_seq!(ser; tag(8), RecordMap(map)),
UnionType(map) => ser_seq!(ser; tag(11), UnionMap(map)),
- UnionLit(l, x, map) => {
- ser_seq!(ser; tag(12), label(l), expr(x), UnionMap(map))
- }
Field(x, l) => ser_seq!(ser; tag(9), expr(x), label(l)),
BinOp(op, x, y) => {
use dhall_syntax::BinOp::*;
@@ -542,6 +587,7 @@ where
let mode = match import.mode {
ImportMode::Code => 0,
ImportMode::RawText => 1,
+ ImportMode::Location => 2,
};
ser_seq.serialize_element(&U64(mode))?;
@@ -565,12 +611,14 @@ where
ImportLocation::Remote(url) => {
match &url.headers {
None => ser_seq.serialize_element(&Null)?,
- Some(location_hashed) => ser_seq.serialize_element(
- &self::Serialize::Import(&Import {
- mode: ImportMode::Code,
- location_hashed: location_hashed.as_ref().clone(),
- }),
- )?,
+ Some(location_hashed) => {
+ ser_seq.serialize_element(&self::Serialize::Expr(
+ &SubExpr::from_expr_no_note(ExprF::Embed(Import {
+ mode: ImportMode::Code,
+ location_hashed: location_hashed.as_ref().clone(),
+ })),
+ ))?
+ }
};
ser_seq.serialize_element(&url.authority)?;
for p in &url.path {
@@ -617,7 +665,6 @@ impl<'a> serde::ser::Serialize for Serialize<'a> {
(cbor::Value::String(k.into()), v)
}))
}
- Serialize::Import(import) => serialize_import(ser, import),
}
}
}
@@ -641,3 +688,26 @@ fn collect_nested_applications<'a, N, E>(
let e = go(e, &mut vec);
(e, vec)
}
+
+type LetBinding<'a, N, E> =
+ (&'a Label, &'a Option<SubExpr<N, E>>, &'a SubExpr<N, E>);
+
+fn collect_nested_lets<'a, N, E>(
+ e: &'a SubExpr<N, E>,
+) -> (&'a SubExpr<N, E>, Vec<LetBinding<'a, N, E>>) {
+ fn go<'a, N, E>(
+ e: &'a SubExpr<N, E>,
+ vec: &mut Vec<LetBinding<'a, N, E>>,
+ ) -> &'a SubExpr<N, E> {
+ match e.as_ref() {
+ ExprF::Let(l, t, v, e) => {
+ vec.push((l, t, v));
+ go(e, vec)
+ }
+ _ => e,
+ }
+ }
+ let mut vec = vec![];
+ let e = go(e, &mut vec);
+ (e, vec)
+}