From 6e0d808e0f5683de942d912231fa10211b6d1377 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 22 Dec 2019 18:08:21 +0000 Subject: Put test builders in a vec --- dhall/build.rs | 112 +++++++++++++++++---------------------------------------- 1 file changed, 33 insertions(+), 79 deletions(-) diff --git a/dhall/build.rs b/dhall/build.rs index 3021f03..9d97839 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -51,8 +51,7 @@ fn dhall_files_in_dir<'a>( }) } -#[derive(Debug, Clone)] -struct TestFeature { +struct TestFeature { /// Name of the module, used in the output of `cargo test` module_name: &'static str, /// Directory containing the tests files @@ -60,7 +59,7 @@ struct TestFeature { /// Relevant variant of `dhall::tests::Test` variant: &'static str, /// Given a file name, whether to exclude it - path_filter: F, + path_filter: Box bool>, /// Type of the input file input_type: FileType, /// Type of the output file, if any @@ -69,7 +68,7 @@ struct TestFeature { fn make_test_module( w: &mut impl Write, // Where to output the generated code - mut feature: TestFeature bool>, + mut feature: TestFeature, ) -> std::io::Result<()> { let tests_dir = feature.directory; writeln!(w, "mod {} {{", feature.module_name)?; @@ -113,15 +112,13 @@ fn generate_tests() -> std::io::Result<()> { let parser_tests_path = Path::new(&out_dir).join("spec_tests.rs"); let spec_tests_dir = Path::new("../dhall-lang/tests/"); - let mut file = File::create(parser_tests_path)?; - make_test_module( - &mut file, + let tests = vec![ TestFeature { module_name: "parser_success", directory: spec_tests_dir.join("parser/success/"), variant: "ParserSuccess", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false // Too slow in debug mode || path == "largeExpression" @@ -131,31 +128,23 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" || path == "unit/import/urls/emptyPathSegment" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Binary), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "parser_failure", directory: spec_tests_dir.join("parser/failure/"), variant: "ParserFailure", - path_filter: |_path: &str| false, + path_filter: Box::new(|_path: &str| false), input_type: FileType::Text, output_type: None, }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "printer", directory: spec_tests_dir.join("parser/success/"), variant: "Printer", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false // Too slow in debug mode || path == "largeExpression" @@ -163,19 +152,15 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" || path == "unit/import/urls/emptyPathSegment" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Binary), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "binary_encoding", directory: spec_tests_dir.join("parser/success/"), variant: "BinaryEncoding", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false // Too slow in debug mode || path == "largeExpression" @@ -189,43 +174,31 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/import/urls/emptyPath0" || path == "unit/import/urls/emptyPath1" || path == "unit/import/urls/emptyPathSegment" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Binary), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "binary_decoding_success", directory: spec_tests_dir.join("binary-decode/success/"), variant: "BinaryDecodingSuccess", - path_filter: |_path: &str| false, + path_filter: Box::new(|_path: &str| false), input_type: FileType::Binary, output_type: Some(FileType::Text), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "binary_decoding_failure", directory: spec_tests_dir.join("binary-decode/failure/"), variant: "BinaryDecodingFailure", - path_filter: |_path: &str| false, + path_filter: Box::new(|_path: &str| false), input_type: FileType::Binary, output_type: None, }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "import_success", directory: spec_tests_dir.join("import/success/"), variant: "ImportSuccess", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false || path == "alternativeEnvNatural" || path == "alternativeEnvSimple" @@ -236,38 +209,30 @@ fn generate_tests() -> std::io::Result<()> { || path == "hashFromCache" || path == "headerForwarding" || path == "noHeaderForwarding" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Text), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "import_failure", directory: spec_tests_dir.join("import/failure/"), variant: "ImportFailure", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false || path == "alternativeEnv" || path == "alternativeEnvMissing" || path == "hashMismatch" || path == "missing" || path == "referentiallyInsane" - }, + }), input_type: FileType::Text, output_type: None, }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "beta_normalize", directory: spec_tests_dir.join("normalization/success/"), variant: "Normalization", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { // We don't support bignums path == "simple/integerToDouble" // Too slow @@ -301,34 +266,26 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/RightBiasedMergeEquivalentArguments" || path == "unit/NestedRecordProjection" || path == "unit/NestedRecordProjectionByType" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Text), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "alpha_normalize", directory: spec_tests_dir.join("alpha-normalization/success/"), variant: "AlphaNormalization", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { // This test doesn't typecheck path == "unit/FunctionNestedBindingXXFree" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Text), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "type_inference_success", directory: spec_tests_dir.join("type-inference/success/"), variant: "TypeInferenceSuccess", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false // Too slow || path == "prelude" @@ -340,19 +297,15 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/ToMap" || path == "unit/ToMapAnnotated" || path == "simple/toMapEmptyNormalizeAnnotation" - }, + }), input_type: FileType::Text, output_type: Some(FileType::Text), }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "type_inference_failure", directory: spec_tests_dir.join("type-inference/failure/"), variant: "TypeInferenceFailure", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false // TODO: Enable imports in typecheck tests || path == "importBoundary" @@ -369,19 +322,15 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/MistypedToMap4" || path == "unit/NonRecordToMap" || path == "unit/ToMapWrongKind" - }, + }), input_type: FileType::Text, output_type: None, }, - )?; - - make_test_module( - &mut file, TestFeature { module_name: "type_error", directory: spec_tests_dir.join("type-inference/failure/"), variant: "TypeError", - path_filter: |path: &str| { + path_filter: Box::new(|path: &str| { false // TODO: Enable imports in typecheck tests || path == "importBoundary" @@ -398,11 +347,16 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/MistypedToMap4" || path == "unit/NonRecordToMap" || path == "unit/ToMapWrongKind" - }, + }), input_type: FileType::Text, output_type: None, }, - )?; + ]; + + let mut file = File::create(parser_tests_path)?; + for test in tests { + make_test_module(&mut file, test)?; + } Ok(()) } -- cgit v1.2.3 From fa6de4c077ab4f1c28d2ec64a33a3be8c5a9bb1c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 22 Dec 2019 18:24:21 +0000 Subject: Update dhall-lang submodule --- dhall-lang | 2 +- dhall/build.rs | 3 +++ dhall/src/error/mod.rs | 1 + dhall/src/semantics/phase/typecheck.rs | 10 +++++++++- dhall/tests/type-errors/unit/MergeUnusedHandler.txt | 1 + .../tests/type-errors/unit/RecordProjectionDuplicateFields.txt | 1 + 6 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 dhall/tests/type-errors/unit/MergeUnusedHandler.txt create mode 100644 dhall/tests/type-errors/unit/RecordProjectionDuplicateFields.txt diff --git a/dhall-lang b/dhall-lang index 781961f..1457988 160000 --- a/dhall-lang +++ b/dhall-lang @@ -1 +1 @@ -Subproject commit 781961f4694667667f093d28e7b35569c67678c4 +Subproject commit 145798835f4ea7e4b30f1eccd651e9f25cca1e2c diff --git a/dhall/build.rs b/dhall/build.rs index 9d97839..3e7c023 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -296,6 +296,7 @@ fn generate_tests() -> std::io::Result<()> { // TODO: toMap || path == "unit/ToMap" || path == "unit/ToMapAnnotated" + || path == "unit/ToMapInferTypeFromRecord" || path == "simple/toMapEmptyNormalizeAnnotation" }), input_type: FileType::Text, @@ -321,6 +322,7 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/MistypedToMap3" || path == "unit/MistypedToMap4" || path == "unit/NonRecordToMap" + || path == "unit/ToMapEmptyInvalidAnnotation" || path == "unit/ToMapWrongKind" }), input_type: FileType::Text, @@ -346,6 +348,7 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/MistypedToMap3" || path == "unit/MistypedToMap4" || path == "unit/NonRecordToMap" + || path == "unit/ToMapEmptyInvalidAnnotation" || path == "unit/ToMapWrongKind" }), input_type: FileType::Text, diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs index 1288c12..40cccac 100644 --- a/dhall/src/error/mod.rs +++ b/dhall/src/error/mod.rs @@ -76,6 +76,7 @@ pub(crate) enum TypeMessage { MergeHandlerReturnTypeMustNotBeDependent, ProjectionMustBeRecord, ProjectionMissingEntry, + ProjectionDuplicateField, Sort, RecordTypeDuplicateField, RecordTypeMergeRequiresRecordType(Value), diff --git a/dhall/src/semantics/phase/typecheck.rs b/dhall/src/semantics/phase/typecheck.rs index c439f74..856f5c3 100644 --- a/dhall/src/semantics/phase/typecheck.rs +++ b/dhall/src/semantics/phase/typecheck.rs @@ -774,7 +774,15 @@ fn type_last_layer( for l in labels { match kts.get(l) { None => return mkerr(ProjectionMissingEntry), - Some(t) => new_kts.insert(l.clone(), t.clone()), + Some(t) => { + use std::collections::hash_map::Entry; + match new_kts.entry(l.clone()) { + Entry::Occupied(_) => { + return mkerr(ProjectionDuplicateField) + } + Entry::Vacant(e) => e.insert(t.clone()), + } + } }; } diff --git a/dhall/tests/type-errors/unit/MergeUnusedHandler.txt b/dhall/tests/type-errors/unit/MergeUnusedHandler.txt new file mode 100644 index 0000000..4b68fea --- /dev/null +++ b/dhall/tests/type-errors/unit/MergeUnusedHandler.txt @@ -0,0 +1 @@ +Type error: Unhandled error diff --git a/dhall/tests/type-errors/unit/RecordProjectionDuplicateFields.txt b/dhall/tests/type-errors/unit/RecordProjectionDuplicateFields.txt new file mode 100644 index 0000000..4b68fea --- /dev/null +++ b/dhall/tests/type-errors/unit/RecordProjectionDuplicateFields.txt @@ -0,0 +1 @@ +Type error: Unhandled error -- cgit v1.2.3 From 54d7e61ad40682ee24e36288980ee4164ea87c34 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 22 Dec 2019 18:38:05 +0000 Subject: Update dhall-lang submodule --- dhall-lang | 2 +- dhall/build.rs | 7 +------ dhall/src/syntax/text/printer.rs | 2 ++ dhall/tests/type-errors/unit/AssertDoubleZeros.txt | 1 + 4 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 dhall/tests/type-errors/unit/AssertDoubleZeros.txt diff --git a/dhall-lang b/dhall-lang index 1457988..b760b41 160000 --- a/dhall-lang +++ b/dhall-lang @@ -1 +1 @@ -Subproject commit 145798835f4ea7e4b30f1eccd651e9f25cca1e2c +Subproject commit b760b4183c8c589e3572a7f9e049d60e69ca53dd diff --git a/dhall/build.rs b/dhall/build.rs index 3e7c023..e06f9b3 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -224,6 +224,7 @@ fn generate_tests() -> std::io::Result<()> { || path == "hashMismatch" || path == "missing" || path == "referentiallyInsane" + || path == "customHeadersUsingBoundVariable" }), input_type: FileType::Text, output_type: None, @@ -308,9 +309,6 @@ fn generate_tests() -> std::io::Result<()> { variant: "TypeInferenceFailure", path_filter: Box::new(|path: &str| { false - // TODO: Enable imports in typecheck tests - || path == "importBoundary" - || path == "customHeadersUsingBoundVariable" // TODO: projection by expression || path == "unit/RecordProjectionByTypeFieldTypeMismatch" || path == "unit/RecordProjectionByTypeNotPresent" @@ -334,9 +332,6 @@ fn generate_tests() -> std::io::Result<()> { variant: "TypeError", path_filter: Box::new(|path: &str| { false - // TODO: Enable imports in typecheck tests - || path == "importBoundary" - || path == "customHeadersUsingBoundVariable" // TODO: projection by expression || path == "unit/RecordProjectionByTypeFieldTypeMismatch" || path == "unit/RecordProjectionByTypeNotPresent" diff --git a/dhall/src/syntax/text/printer.rs b/dhall/src/syntax/text/printer.rs index 78942ed..dff3479 100644 --- a/dhall/src/syntax/text/printer.rs +++ b/dhall/src/syntax/text/printer.rs @@ -322,6 +322,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('.') { diff --git a/dhall/tests/type-errors/unit/AssertDoubleZeros.txt b/dhall/tests/type-errors/unit/AssertDoubleZeros.txt new file mode 100644 index 0000000..4b68fea --- /dev/null +++ b/dhall/tests/type-errors/unit/AssertDoubleZeros.txt @@ -0,0 +1 @@ +Type error: Unhandled error -- cgit v1.2.3 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-lang | 2 +- dhall/build.rs | 16 ++++++++++++++++ dhall/src/dhall.pest.visibility | 2 ++ dhall/src/semantics/phase/normalize.rs | 1 + dhall/src/semantics/phase/typecheck.rs | 1 + dhall/src/syntax/ast/expr.rs | 2 ++ dhall/src/syntax/ast/visitor.rs | 7 +++++++ dhall/src/syntax/binary/decode.rs | 5 +++++ dhall/src/syntax/binary/encode.rs | 3 +++ dhall/src/syntax/text/parser.rs | 19 +++++++++++++++++++ dhall/src/syntax/text/printer.rs | 20 ++++++++++++-------- 11 files changed, 69 insertions(+), 9 deletions(-) diff --git a/dhall-lang b/dhall-lang index b760b41..e95d863 160000 --- a/dhall-lang +++ b/dhall-lang @@ -1 +1 @@ -Subproject commit b760b4183c8c589e3572a7f9e049d60e69ca53dd +Subproject commit e95d863766356c3b5a299c1db1c299df7a315294 diff --git a/dhall/build.rs b/dhall/build.rs index e06f9b3..ec06ece 100644 --- a/dhall/build.rs +++ b/dhall/build.rs @@ -267,6 +267,9 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/RightBiasedMergeEquivalentArguments" || path == "unit/NestedRecordProjection" || path == "unit/NestedRecordProjectionByType" + // TODO: record completion + || path == "simple/completion" + || path == "unit/Completion" }), input_type: FileType::Text, output_type: Some(FileType::Text), @@ -299,6 +302,9 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/ToMapAnnotated" || path == "unit/ToMapInferTypeFromRecord" || path == "simple/toMapEmptyNormalizeAnnotation" + // TODO: record completion + || path == "simple/completion" + || path == "unit/Completion" }), input_type: FileType::Text, output_type: Some(FileType::Text), @@ -322,6 +328,11 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/NonRecordToMap" || path == "unit/ToMapEmptyInvalidAnnotation" || path == "unit/ToMapWrongKind" + // TODO: record completion + || path == "unit/CompletionMissingRequiredField" + || path == "unit/CompletionWithWrongDefaultType" + || path == "unit/CompletionWithWrongFieldName" + || path == "unit/CompletionWithWrongOverridenType" }), input_type: FileType::Text, output_type: None, @@ -345,6 +356,11 @@ fn generate_tests() -> std::io::Result<()> { || path == "unit/NonRecordToMap" || path == "unit/ToMapEmptyInvalidAnnotation" || path == "unit/ToMapWrongKind" + // TODO: record completion + || path == "unit/CompletionMissingRequiredField" + || path == "unit/CompletionWithWrongDefaultType" + || path == "unit/CompletionWithWrongFieldName" + || path == "unit/CompletionWithWrongOverridenType" }), input_type: FileType::Text, output_type: None, 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 diff --git a/dhall/src/semantics/phase/normalize.rs b/dhall/src/semantics/phase/normalize.rs index d81a910..65384c2 100644 --- a/dhall/src/semantics/phase/normalize.rs +++ b/dhall/src/semantics/phase/normalize.rs @@ -741,6 +741,7 @@ pub(crate) fn normalize_one_layer( ExprKind::ProjectionByExpr(_, _) => { unimplemented!("selection by expression") } + ExprKind::Completion(_, _) => unimplemented!("record completion"), ExprKind::Merge(ref handlers, ref variant, _) => { let handlers_borrow = handlers.as_whnf(); diff --git a/dhall/src/semantics/phase/typecheck.rs b/dhall/src/semantics/phase/typecheck.rs index 856f5c3..c9834e1 100644 --- a/dhall/src/semantics/phase/typecheck.rs +++ b/dhall/src/semantics/phase/typecheck.rs @@ -792,6 +792,7 @@ fn type_last_layer( )) } ProjectionByExpr(_, _) => unimplemented!("selection by expression"), + Completion(_, _) => unimplemented!("record completion"), }; Ok(match ret { diff --git a/dhall/src/syntax/ast/expr.rs b/dhall/src/syntax/ast/expr.rs index 48c48d8..fe49448 100644 --- a/dhall/src/syntax/ast/expr.rs +++ b/dhall/src/syntax/ast/expr.rs @@ -163,6 +163,8 @@ pub enum ExprKind { Projection(SubExpr, DupTreeSet