From e294450e1e76491e96019b8a3695463e09d1739b Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 22 Dec 2019 19:02:18 +0000 Subject: Implement parsing for record completion --- dhall/src/dhall.pest.visibility | 2 ++ 1 file changed, 2 insertions(+) (limited to 'dhall/src/dhall.pest.visibility') diff --git a/dhall/src/dhall.pest.visibility b/dhall/src/dhall.pest.visibility index 17c1edc..41aa833 100644 --- a/dhall/src/dhall.pest.visibility +++ b/dhall/src/dhall.pest.visibility @@ -91,6 +91,7 @@ prefer lambda forall arrow +# complete # exponent numeric_double_literal minus_infinity_literal @@ -161,6 +162,7 @@ equivalent_expression application_expression first_application_expression # import_expression +completion_expression selector_expression selector labels -- cgit v1.3.1 From 4c7deccba50cb6d46134362128e3cb25c693c153 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 23 Dec 2019 22:30:27 +0000 Subject: Update dhall-lang submodule --- dhall-lang | 2 +- dhall/build.rs | 8 ++++++++ dhall/src/dhall.pest.visibility | 4 ++++ dhall/src/syntax/text/parser.rs | 23 ++++++++++------------- 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'dhall/src/dhall.pest.visibility') diff --git a/dhall-lang b/dhall-lang index 3b31dea..464b735 160000 --- a/dhall-lang +++ b/dhall-lang @@ -1 +1 @@ -Subproject commit 3b31dea1ba47f9de041a7288826f07a05a167ba7 +Subproject commit 464b7358545a0d5c10d0aa987fed94bedc7f5162 diff --git a/dhall/build.rs b/dhall/build.rs index 70389bf..981e558 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -414,12 +414,20 @@ fn convert_abnf_to_pest() -> std::io::Result<()> { rules.remove("url_path"); writeln!(&mut file, "url_path = _{{ path }}")?; + // Work around some greediness issue in the grammar. rules.remove("missing"); writeln!( &mut file, r#"missing = {{ "missing" ~ !simple_label_next_char }}"# )?; + // Prefer my nice error message to illegible parse errors. + rules.remove("unicode_escape"); + writeln!( + &mut file, + r#"unicode_escape = _{{ HEXDIG{{4}} | "{{" ~ HEXDIG+ ~ "}}" }}"# + )?; + rules.remove("simple_label"); writeln!( &mut file, diff --git a/dhall/src/dhall.pest.visibility b/dhall/src/dhall.pest.visibility index 41aa833..5d3b4c8 100644 --- a/dhall/src/dhall.pest.visibility +++ b/dhall/src/dhall.pest.visibility @@ -24,6 +24,10 @@ quoted_label double_quote_chunk double_quote_escaped # unicode_escape +# unicode_suffix +# unbraced_escape +# braced_codepoint +# braced_escape double_quote_char double_quote_literal single_quote_continue diff --git a/dhall/src/syntax/text/parser.rs b/dhall/src/syntax/text/parser.rs index d9e5c3b..27e0382 100644 --- a/dhall/src/syntax/text/parser.rs +++ b/dhall/src/syntax/text/parser.rs @@ -217,19 +217,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" )))? } @@ -242,12 +241,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 @@ -264,12 +261,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() } }) -- cgit v1.3.1 From 5f52c5bda0277edd87323eb67dcda721cd18a9d3 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 24 Dec 2019 20:23:19 +0000 Subject: Extend merge to work on Optionals --- dhall-lang | 2 +- dhall/build.rs | 16 ++++++++++++--- dhall/src/dhall.pest.visibility | 1 + dhall/src/error/mod.rs | 2 +- dhall/src/semantics/phase/normalize.rs | 24 ++++++++++++++++++++-- dhall/src/semantics/phase/typecheck.rs | 16 +++++++++++++-- dhall/src/syntax/text/parser.rs | 9 ++++++++ .../type-errors/unit/MergeAnnotationNotType.txt | 2 +- .../unit/MergeEmptyWithoutAnnotation.txt | 2 +- .../type-errors/unit/MergeHandlerNotInUnion.txt | 2 +- dhall/tests/type-errors/unit/MergeRhsNotUnion.txt | 2 +- 11 files changed, 65 insertions(+), 13 deletions(-) (limited to 'dhall/src/dhall.pest.visibility') diff --git a/dhall-lang b/dhall-lang index c7dd51e..0c99dc6 160000 --- a/dhall-lang +++ b/dhall-lang @@ -1 +1 @@ -Subproject commit c7dd51ec433e07433243cf1a1134655dbab6cc95 +Subproject commit 0c99dc6f53919fc2df6b965877c355b62cf6ba02 diff --git a/dhall/build.rs b/dhall/build.rs index 981e558..3d4a2eb 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -128,7 +128,7 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" || path == "unit/import/urls/emptyPathSegment" - // TODO: https://github.com/dhall-lang/dhall-lang/pull/788#issuecomment-568298973 + // TODO: waiting for https://github.com/dhall-lang/dhall-lang/pull/871 || path == "preferMissingNoSpaces" }), input_type: FileType::Text, @@ -154,7 +154,7 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" || path == "unit/import/urls/emptyPathSegment" - // TODO: https://github.com/dhall-lang/dhall-lang/pull/788#issuecomment-568298973 + // TODO: waiting for https://github.com/dhall-lang/dhall-lang/pull/871 || path == "preferMissingNoSpaces" }), input_type: FileType::Text, @@ -178,7 +178,7 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" || path == "unit/import/urls/emptyPathSegment" - // TODO: https://github.com/dhall-lang/dhall-lang/pull/788#issuecomment-568298973 + // TODO: waiting for https://github.com/dhall-lang/dhall-lang/pull/871 || path == "preferMissingNoSpaces" }), input_type: FileType::Text, @@ -282,6 +282,9 @@ fn generate_tests() -> std::io::Result<()> { // TODO: record completion || path == "simple/completion" || path == "unit/Completion" + // TODO: waiting for https://github.com/dhall-lang/dhall-lang/pull/871 + || path == "unit/MergeNone" + || path == "unit/MergeSome" }), input_type: FileType::Text, output_type: Some(FileType::Text), @@ -317,6 +320,9 @@ fn generate_tests() -> std::io::Result<()> { // TODO: record completion || path == "simple/completion" || path == "unit/Completion" + // TODO: waiting for https://github.com/dhall-lang/dhall-lang/pull/871 + || path == "unit/MergeNone" + || path == "unit/MergeSome" }), input_type: FileType::Text, output_type: Some(FileType::Text), @@ -423,6 +429,10 @@ fn convert_abnf_to_pest() -> std::io::Result<()> { // Prefer my nice error message to illegible parse errors. rules.remove("unicode_escape"); + rules.remove("unbraced_escape"); + rules.remove("braced_escape"); + rules.remove("braced_codepoint"); + rules.remove("unicode_suffix"); writeln!( &mut file, r#"unicode_escape = _{{ HEXDIG{{4}} | "{{" ~ HEXDIG+ ~ "}}" }}"# diff --git a/dhall/src/dhall.pest.visibility b/dhall/src/dhall.pest.visibility index 5d3b4c8..03a000b 100644 --- a/dhall/src/dhall.pest.visibility +++ b/dhall/src/dhall.pest.visibility @@ -21,6 +21,7 @@ quoted_label # label # nonreserved_label # any_label +any_label_or_some double_quote_chunk double_quote_escaped # unicode_escape diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs index 8976478..6e7be64 100644 --- a/dhall/src/error/mod.rs +++ b/dhall/src/error/mod.rs @@ -67,7 +67,7 @@ pub(crate) enum TypeMessage { BinOpTypeMismatch(BinOp, Value), InvalidTextInterpolation(Value), Merge1ArgMustBeRecord(Value), - Merge2ArgMustBeUnion(Value), + Merge2ArgMustBeUnionOrOptional(Value), MergeEmptyNeedsAnnotation, MergeHandlerMissingVariant(Label), MergeVariantMissingHandler(Label), diff --git a/dhall/src/semantics/phase/normalize.rs b/dhall/src/semantics/phase/normalize.rs index 5a0f566..459eaf1 100644 --- a/dhall/src/semantics/phase/normalize.rs +++ b/dhall/src/semantics/phase/normalize.rs @@ -590,8 +590,8 @@ pub(crate) fn normalize_one_layer( ty: &Value, ) -> ValueKind { use ValueKind::{ - AppliedBuiltin, BoolLit, DoubleLit, EmptyListLit, IntegerLit, - NEListLit, NEOptionalLit, NaturalLit, RecordLit, TextLit, + AppliedBuiltin, BoolLit, DoubleLit, EmptyListLit, EmptyOptionalLit, + IntegerLit, NEListLit, NEOptionalLit, NaturalLit, RecordLit, TextLit, UnionConstructor, UnionLit, UnionType, }; @@ -739,6 +739,26 @@ pub(crate) fn normalize_one_layer( Ret::Expr(expr) } }, + (RecordLit(kvs), EmptyOptionalLit(_)) => { + match kvs.get(&"None".into()) { + Some(h) => Ret::Value(h.clone()), + None => { + drop(handlers_borrow); + drop(variant_borrow); + Ret::Expr(expr) + } + } + } + (RecordLit(kvs), NEOptionalLit(v)) => { + match kvs.get(&"Some".into()) { + Some(h) => Ret::Value(h.app(v.clone())), + None => { + drop(handlers_borrow); + drop(variant_borrow); + Ret::Expr(expr) + } + } + } _ => { drop(handlers_borrow); drop(variant_borrow); diff --git a/dhall/src/semantics/phase/typecheck.rs b/dhall/src/semantics/phase/typecheck.rs index 7ea4951..97502d4 100644 --- a/dhall/src/semantics/phase/typecheck.rs +++ b/dhall/src/semantics/phase/typecheck.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::cmp::max; use std::collections::HashMap; @@ -695,8 +696,19 @@ fn type_last_layer( let union_type = union.get_type()?; let union_borrow = union_type.as_whnf(); let variants = match &*union_borrow { - ValueKind::UnionType(kts) => kts, - _ => return mkerr(Merge2ArgMustBeUnion(union.clone())), + ValueKind::UnionType(kts) => Cow::Borrowed(kts), + ValueKind::AppliedBuiltin(syntax::Builtin::Optional, args) + if args.len() == 1 => + { + let ty = &args[0]; + let mut kts = HashMap::new(); + kts.insert("None".into(), None); + kts.insert("Some".into(), Some(ty.clone())); + Cow::Owned(kts) + } + _ => { + return mkerr(Merge2ArgMustBeUnionOrOptional(union.clone())) + } }; let mut inferred_type = None; diff --git a/dhall/src/syntax/text/parser.rs b/dhall/src/syntax/text/parser.rs index 0e3e97a..feaa2a5 100644 --- a/dhall/src/syntax/text/parser.rs +++ b/dhall/src/syntax/text/parser.rs @@ -183,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