summaryrefslogtreecommitdiff
path: root/dhall/src/syntax
diff options
context:
space:
mode:
authorNadrieril Feneanar2019-12-24 20:41:22 +0000
committerGitHub2019-12-24 20:41:22 +0000
commit057d645a90a6b57f40f72eb7e347ba2c6219777e (patch)
tree151473a0a6cb7222fd6b4eb3abf1cfacca012aad /dhall/src/syntax
parent06e75c919d999c310f8ca1c151c6a5ad6918ca08 (diff)
parent18dd5ba3ae94fd89dd27c0ae3891ac3e43ace350 (diff)
Merge pull request #124 from Nadrieril/catchup-spec
Catchup on standard changes
Diffstat (limited to 'dhall/src/syntax')
-rw-r--r--dhall/src/syntax/ast/expr.rs4
-rw-r--r--dhall/src/syntax/ast/visitor.rs7
-rw-r--r--dhall/src/syntax/binary/decode.rs5
-rw-r--r--dhall/src/syntax/binary/encode.rs1
-rw-r--r--dhall/src/syntax/text/parser.rs81
-rw-r--r--dhall/src/syntax/text/printer.rs31
6 files changed, 96 insertions, 33 deletions
diff --git a/dhall/src/syntax/ast/expr.rs b/dhall/src/syntax/ast/expr.rs
index 48c48d8..68cb524 100644
--- a/dhall/src/syntax/ast/expr.rs
+++ b/dhall/src/syntax/ast/expr.rs
@@ -79,6 +79,8 @@ pub enum Builtin {
NaturalSubtract,
IntegerToDouble,
IntegerShow,
+ IntegerNegate,
+ IntegerClamp,
DoubleShow,
ListBuild,
ListFold,
@@ -163,6 +165,8 @@ pub enum ExprKind<SubExpr, Embed> {
Projection(SubExpr, DupTreeSet<Label>),
/// `e.(t)`
ProjectionByExpr(SubExpr, SubExpr),
+ /// `x::y`
+ Completion(SubExpr, SubExpr),
/// `./some/path`
Import(Import<SubExpr>),
/// Embeds the result of resolving an import
diff --git a/dhall/src/syntax/ast/visitor.rs b/dhall/src/syntax/ast/visitor.rs
index b557995..424048b 100644
--- a/dhall/src/syntax/ast/visitor.rs
+++ b/dhall/src/syntax/ast/visitor.rs
@@ -164,6 +164,9 @@ where
ProjectionByExpr(e, x) => {
ProjectionByExpr(v.visit_subexpr(e)?, v.visit_subexpr(x)?)
}
+ Completion(e, x) => {
+ Completion(v.visit_subexpr(e)?, v.visit_subexpr(x)?)
+ }
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)?),
@@ -281,6 +284,10 @@ where
v.visit_subexpr(e)?;
v.visit_subexpr(x)?;
}
+ Completion(x, y) => {
+ v.visit_subexpr(x)?;
+ v.visit_subexpr(y)?;
+ }
Assert(e) => v.visit_subexpr(e)?,
Import(i) => i.traverse_mut(|e| v.visit_subexpr(e))?,
Embed(a) => v.visit_embed(a)?,
diff --git a/dhall/src/syntax/binary/decode.rs b/dhall/src/syntax/binary/decode.rs
index 254ab07..c18deb5 100644
--- a/dhall/src/syntax/binary/decode.rs
+++ b/dhall/src/syntax/binary/decode.rs
@@ -98,6 +98,11 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> {
let l = Label::from(l.as_str());
Pi(l, x, y)
}
+ [U64(3), U64(13), x, y] => {
+ let x = cbor_value_to_dhall(&x)?;
+ let y = cbor_value_to_dhall(&y)?;
+ Completion(x, y)
+ }
[U64(3), U64(n), x, y] => {
let x = cbor_value_to_dhall(&x)?;
let y = cbor_value_to_dhall(&y)?;
diff --git a/dhall/src/syntax/binary/encode.rs b/dhall/src/syntax/binary/encode.rs
index 25a545c..5e79f2d 100644
--- a/dhall/src/syntax/binary/encode.rs
+++ b/dhall/src/syntax/binary/encode.rs
@@ -164,6 +164,7 @@ where
ProjectionByExpr(x, y) => {
ser_seq!(ser; tag(10), expr(x), vec![expr(y)])
}
+ Completion(x, y) => ser_seq!(ser; tag(3), tag(13), expr(x), expr(y)),
Import(import) => serialize_import(ser, import),
Embed(_) => unimplemented!(
"An expression with resolved imports cannot be binary-encoded"
diff --git a/dhall/src/syntax/text/parser.rs b/dhall/src/syntax/text/parser.rs
index 832472b..feaa2a5 100644
--- a/dhall/src/syntax/text/parser.rs
+++ b/dhall/src/syntax/text/parser.rs
@@ -57,6 +57,8 @@ impl crate::syntax::Builtin {
"Natural/subtract" => Some(NaturalSubtract),
"Integer/toDouble" => Some(IntegerToDouble),
"Integer/show" => Some(IntegerShow),
+ "Integer/negate" => Some(IntegerNegate),
+ "Integer/clamp" => Some(IntegerClamp),
"Double/show" => Some(DoubleShow),
"List/build" => Some(ListBuild),
"List/fold" => Some(ListFold),
@@ -181,6 +183,15 @@ impl DhallParser {
Ok(Label::from(input.as_str()))
}
+ // TODO: waiting for https://github.com/dhall-lang/dhall-lang/pull/871
+ // #[alias(label)]
+ // fn any_label_or_some(input: ParseInput) -> ParseResult<Label> {
+ // Ok(match_nodes!(input.into_children();
+ // [label(l)] => l,
+ // [Some_(_)] => Label::from("Some"),
+ // ))
+ // }
+
fn double_quote_literal(input: ParseInput) -> ParseResult<ParsedText> {
Ok(match_nodes!(input.into_children();
[double_quote_chunk(chunks)..] => {
@@ -215,19 +226,18 @@ impl DhallParser {
"t" => "\t".to_owned(),
// "uXXXX" or "u{XXXXX}"
s => {
- use std::convert::{TryFrom, TryInto};
+ use std::convert::TryInto;
let s = &s[1..];
let s = if &s[0..1] == "{" {
&s[1..s.len() - 1]
} else {
- &s[0..s.len()]
+ s
};
if s.len() > 8 {
Err(input.error(format!(
- "Escape sequences can't have more than 8 chars: \"{}\"",
- s
+ "Escape sequences can't have more than 8 chars"
)))?
}
@@ -240,12 +250,10 @@ impl DhallParser {
// `s` has length 8, so `bytes` has length 4
let bytes: &[u8] = &hex::decode(s).unwrap();
let i = u32::from_be_bytes(bytes.try_into().unwrap());
- let c = char::try_from(i).unwrap();
match i {
- 0xD800..=0xDFFF => {
- let c_ecapsed = c.escape_unicode();
- Err(input.error(format!("Escape sequences can't contain surrogate pairs: \"{}\"", c_ecapsed)))?
- }
+ 0xD800..=0xDFFF => Err(input.error(format!(
+ "Escape sequences can't contain surrogate pairs"
+ )))?,
0x0FFFE..=0x0FFFF
| 0x1FFFE..=0x1FFFF
| 0x2FFFE..=0x2FFFF
@@ -262,12 +270,12 @@ impl DhallParser {
| 0xDFFFE..=0xDFFFF
| 0xEFFFE..=0xEFFFF
| 0xFFFFE..=0xFFFFF
- | 0x10_FFFE..=0x10_FFFF => {
- let c_ecapsed = c.escape_unicode();
- Err(input.error(format!("Escape sequences can't contain non-characters: \"{}\"", c_ecapsed)))?
- }
+ | 0x10_FFFE..=0x10_FFFF => Err(input.error(format!(
+ "Escape sequences can't contain non-characters"
+ )))?,
_ => {}
}
+ let c: char = i.try_into().unwrap();
std::iter::once(c).collect()
}
})
@@ -384,19 +392,27 @@ impl DhallParser {
}
fn natural_literal(input: ParseInput) -> ParseResult<Natural> {
- input
- .as_str()
- .trim()
- .parse()
- .map_err(|e| input.error(format!("{}", e)))
+ let s = input.as_str().trim();
+ if s.starts_with("0x") {
+ let without_prefix = s.trim_start_matches("0x");
+ usize::from_str_radix(without_prefix, 16)
+ .map_err(|e| input.error(format!("{}", e)))
+ } else {
+ s.parse().map_err(|e| input.error(format!("{}", e)))
+ }
}
fn integer_literal(input: ParseInput) -> ParseResult<Integer> {
- input
- .as_str()
- .trim()
- .parse()
- .map_err(|e| input.error(format!("{}", e)))
+ let s = input.as_str().trim();
+ let (sign, rest) = (&s[0..1], &s[1..]);
+ if rest.starts_with("0x") {
+ let without_prefix =
+ sign.to_owned() + rest.trim_start_matches("0x");
+ isize::from_str_radix(&without_prefix, 16)
+ .map_err(|e| input.error(format!("{}", e)))
+ } else {
+ s.parse().map_err(|e| input.error(format!("{}", e)))
+ }
}
#[alias(expression, shortcut = true)]
@@ -766,6 +782,25 @@ impl DhallParser {
}
#[alias(expression, shortcut = true)]
+ fn completion_expression(input: ParseInput) -> ParseResult<Expr> {
+ Ok(match_nodes!(input.children();
+ [expression(e)] => e,
+ [expression(first), expression(rest)..] => {
+ rest.fold(
+ first,
+ |acc, e| {
+ spanned_union(
+ acc.span(),
+ e.span(),
+ Completion(acc, e),
+ )
+ }
+ )
+ },
+ ))
+ }
+
+ #[alias(expression, shortcut = true)]
fn selector_expression(input: ParseInput) -> ParseResult<Expr> {
Ok(match_nodes!(input.children();
[expression(e)] => e,
diff --git a/dhall/src/syntax/text/printer.rs b/dhall/src/syntax/text/printer.rs
index 78942ed..96f4c2a 100644
--- a/dhall/src/syntax/text/printer.rs
+++ b/dhall/src/syntax/text/printer.rs
@@ -64,6 +64,9 @@ impl<E: Display + Clone> UnspannedExpr<E> {
Field(a, b) => Field(a.phase(Primitive), b),
Projection(e, ls) => Projection(e.phase(Primitive), ls),
ProjectionByExpr(a, b) => ProjectionByExpr(a.phase(Primitive), b),
+ Completion(a, b) => {
+ Completion(a.phase(Primitive), b.phase(Primitive))
+ }
e => e,
}
}
@@ -89,9 +92,10 @@ impl<E: Display + Clone> UnspannedExpr<E> {
// Precedence is magically handled by the ordering of BinOps.
ExprKind::BinOp(op, _, _) => phase > PrintPhase::BinOp(*op),
ExprKind::App(_, _) => phase > PrintPhase::App,
- Field(_, _) | Projection(_, _) | ProjectionByExpr(_, _) => {
- phase > PrintPhase::Import
- }
+ Field(_, _)
+ | Projection(_, _)
+ | ProjectionByExpr(_, _)
+ | Completion(_, _) => phase > PrintPhase::Import,
_ => false,
};
@@ -189,13 +193,6 @@ impl<SE: Display + Clone, E: Display> Display for ExprKind<SE, E> {
Field(a, b) => {
write!(f, "{}.{}", a, b)?;
}
- Projection(e, ls) => {
- write!(f, "{}.", e)?;
- fmt_list("{ ", ", ", " }", ls, f, Display::fmt)?;
- }
- ProjectionByExpr(a, b) => {
- write!(f, "{}.({})", a, b)?;
- }
Var(a) => a.fmt(f)?,
Const(k) => k.fmt(f)?,
Builtin(v) => v.fmt(f)?,
@@ -224,6 +221,16 @@ impl<SE: Display + Clone, E: Display> Display for ExprKind<SE, E> {
}
Ok(())
})?,
+ Projection(e, ls) => {
+ write!(f, "{}.", e)?;
+ fmt_list("{ ", ", ", " }", ls, f, Display::fmt)?;
+ }
+ ProjectionByExpr(a, b) => {
+ write!(f, "{}.({})", a, b)?;
+ }
+ Completion(a, b) => {
+ write!(f, "{}::{}", a, b)?;
+ }
Import(a) => a.fmt(f)?,
Embed(a) => a.fmt(f)?,
}
@@ -322,6 +329,8 @@ impl Display for NaiveDouble {
f.write_str("-Infinity")
} else if v.is_nan() {
f.write_str("NaN")
+ } else if v == 0.0 && v.is_sign_negative() {
+ f.write_str("-0.0")
} else {
let s = format!("{}", v);
if s.contains('e') || s.contains('.') {
@@ -459,6 +468,8 @@ impl Display for Builtin {
NaturalShow => "Natural/show",
NaturalSubtract => "Natural/subtract",
IntegerToDouble => "Integer/toDouble",
+ IntegerNegate => "Integer/negate",
+ IntegerClamp => "Integer/clamp",
IntegerShow => "Integer/show",
DoubleShow => "Double/show",
ListBuild => "List/build",