From 345df2051ca28b4ed1937823e9fd23d0e1f0e285 Mon Sep 17 00:00:00 2001 From: FintanH Date: Wed, 24 Jul 2019 14:35:15 +0100 Subject: Add section to README for contributing. It describes how to set up the git repo, rustup, and cargo --- README.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/README.md b/README.md index 66748dc..1fe59da 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,62 @@ This is still quite unstable so use at your own risk. Documentation is severely You can see what's missing from the commented out tests in `dhall/src/normalize.rs` and `dhall/src/typecheck.rs`. +# Contributing + +This section will cover how we can get started on contributing this project. + +## Setting up the repository + +To get a copy of this repository we can run: + +```bash +$ git clone https://github.com/Nadrieril/dhall-rust.git +``` + +But we also might note that it's better practice to fork the repository to your own workspace. +There you can make changes and submit pull requests against this repository. + +After the repositry has been cloned we need to update the [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) +in the project, i.e. `dhall-lang`. We can do this by running: + +```bash +$ git submodule update --init --recursive +``` + +## Building and Testing + +A preferred method among the Rust community for developing is to use [`rustup`](https://rustup.rs/). + +It can be installed by running: + +```bash +$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +or if [nix](https://nixos.org/) is your tool of choice: + +```bash +$ nix-shell -p rustup +``` + +Once `rustup` is installed we can get it to manage our toolchain by running: + +```bash +$ rustup toolchain install nightly +``` + +Then we can manage our building and testing with the [`cargo`](https://crates.io/) dependency manager: + +```bash +$ cargo build +``` + +```bash +$ cargo test +``` + +Now we can have fun and happy contributing! + ## License Licensed under the terms of the 2-Clause BSD License ([LICENSE](LICENSE) or -- cgit v1.2.3 From e51b89d717a1f1aaba7e59c79c9fb4b8e7031bab Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Sat, 27 Jul 2019 15:09:31 +0100 Subject: Add case for RightBasedRecordMerge in the typechecking phase. The implementation checks the types and kinds of the LHS and RHS. In the happy path it unions the HashMap prefering keys on the RHS over the LHS, and the result is the type of the resulting HashMap. The error cases are: - If the kinds of the records differ it results in a RecordMismatch error. - If either the LHS or RHS are not records it results in a MustCombineRecord error. --- dhall/src/error/mod.rs | 2 ++ dhall/src/phase/typecheck.rs | 51 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/dhall/src/error/mod.rs b/dhall/src/error/mod.rs index 125d013..20b8636 100644 --- a/dhall/src/error/mod.rs +++ b/dhall/src/error/mod.rs @@ -76,9 +76,11 @@ pub(crate) enum TypeMessage { MergeAnnotMismatch, MergeHandlerTypeMismatch, MergeHandlerReturnTypeMustNotBeDependent, + MustCombineRecord(Typed), ProjectionMustBeRecord, ProjectionMissingEntry, Sort, + RecordMismatch(Typed, Typed), RecordTypeDuplicateField, UnionTypeDuplicateField, Unimplemented, diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index 419b2e2..2315edb 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -598,6 +598,47 @@ fn type_last_layer( } Ok(RetTypeOnly(text_type)) } + BinOp(RightBiasedRecordMerge, l, r) => { + let l_type = l.get_type()?; + let l_kind = l_type.get_type()?; + let r_type = r.get_type()?; + let r_kind = r_type.get_type()?; + + // Check the equality of kinds. + // This is to disallow expression such as: + // "{ x = Text } // { y = 1 }" + ensure_equal!( + l_kind, + r_kind, + mkerr(RecordMismatch(l.clone(), r.clone())), + ); + + // Extract the LHS record type + let mut kts_x = match l_type.to_value() { + Value::RecordType(kts) => kts, + _ => return Err(mkerr(MustCombineRecord(l.clone()))), + }; + + // Extract the RHS record type + let kts_y = match r_type.to_value() { + Value::RecordType(kts) => kts, + _ => return Err(mkerr(MustCombineRecord(r.clone()))), + }; + + // Union the two records, prefering + // the values found in the RHS. + for (label, value) in kts_y { + kts_x.insert(label, value); + } + + // Construct the final record type from the union + Ok(RetTypeOnly(tck_record_type( + ctx, + kts_x.iter() + .map(|(x, v)| Ok((x.clone(), v.to_type()))), + )? + .into_type())) + } BinOp(o @ ListAppend, l, r) => { match l.get_type()?.to_value() { Value::AppliedBuiltin(List, _) => {} @@ -1135,11 +1176,11 @@ mod spec_tests { // ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwo, "unit/RecursiveRecordTypeMergeTwo"); // ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwoKinds, "unit/RecursiveRecordTypeMergeTwoKinds"); // ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwoTypes, "unit/RecursiveRecordTypeMergeTwoTypes"); - // ti_success!(ti_success_unit_RightBiasedRecordMergeRhsEmpty, "unit/RightBiasedRecordMergeRhsEmpty"); - // ti_success!(ti_success_unit_RightBiasedRecordMergeTwo, "unit/RightBiasedRecordMergeTwo"); - // ti_success!(ti_success_unit_RightBiasedRecordMergeTwoDifferent, "unit/RightBiasedRecordMergeTwoDifferent"); - // ti_success!(ti_success_unit_RightBiasedRecordMergeTwoKinds, "unit/RightBiasedRecordMergeTwoKinds"); - // ti_success!(ti_success_unit_RightBiasedRecordMergeTwoTypes, "unit/RightBiasedRecordMergeTwoTypes"); + ti_success!(ti_success_unit_RightBiasedRecordMergeRhsEmpty, "unit/RightBiasedRecordMergeRhsEmpty"); + ti_success!(ti_success_unit_RightBiasedRecordMergeTwo, "unit/RightBiasedRecordMergeTwo"); + ti_success!(ti_success_unit_RightBiasedRecordMergeTwoDifferent, "unit/RightBiasedRecordMergeTwoDifferent"); + ti_success!(ti_success_unit_RightBiasedRecordMergeTwoKinds, "unit/RightBiasedRecordMergeTwoKinds"); + ti_success!(ti_success_unit_RightBiasedRecordMergeTwoTypes, "unit/RightBiasedRecordMergeTwoTypes"); ti_success!(ti_success_unit_SomeTrue, "unit/SomeTrue"); ti_success!(ti_success_unit_Text, "unit/Text"); ti_success!(ti_success_unit_TextLiteral, "unit/TextLiteral"); -- cgit v1.2.3 From f806ad6bf0fad5a720c9b87310d86838612f3b7a Mon Sep 17 00:00:00 2001 From: FintanH Date: Wed, 31 Jul 2019 12:15:12 +0100 Subject: Reuse the merge_maps function to implement the right-biased union --- dhall/src/phase/normalize.rs | 2 +- dhall/src/phase/typecheck.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dhall/src/phase/normalize.rs b/dhall/src/phase/normalize.rs index be2ba51..da19dc1 100644 --- a/dhall/src/phase/normalize.rs +++ b/dhall/src/phase/normalize.rs @@ -372,7 +372,7 @@ enum Ret<'a> { Expr(ExprF), } -fn merge_maps( +pub(crate) fn merge_maps( map1: &HashMap, map2: &HashMap, mut f: impl FnMut(&V, &V) -> V, diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index 2315edb..9107e36 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -599,6 +599,8 @@ fn type_last_layer( Ok(RetTypeOnly(text_type)) } BinOp(RightBiasedRecordMerge, l, r) => { + use crate::phase::normalize::merge_maps; + let l_type = l.get_type()?; let l_kind = l_type.get_type()?; let r_type = r.get_type()?; @@ -614,7 +616,7 @@ fn type_last_layer( ); // Extract the LHS record type - let mut kts_x = match l_type.to_value() { + let kts_x = match l_type.to_value() { Value::RecordType(kts) => kts, _ => return Err(mkerr(MustCombineRecord(l.clone()))), }; @@ -627,15 +629,13 @@ fn type_last_layer( // Union the two records, prefering // the values found in the RHS. - for (label, value) in kts_y { - kts_x.insert(label, value); - } + let kts = merge_maps(&kts_x, &kts_y, |_, r_t| r_t.clone()); // Construct the final record type from the union Ok(RetTypeOnly(tck_record_type( ctx, - kts_x.iter() - .map(|(x, v)| Ok((x.clone(), v.to_type()))), + kts.iter() + .map(|(x, v)| Ok((x.clone(), v.to_type()))), )? .into_type())) } -- cgit v1.2.3 From dceabb85e407b8e0e52105a725f3bb782fa474de Mon Sep 17 00:00:00 2001 From: FintanH Date: Wed, 31 Jul 2019 14:06:11 +0100 Subject: Add unreachable call for RightBasedRecordMerge case --- dhall/src/phase/typecheck.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index 9107e36..ecd0a69 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -663,6 +663,7 @@ fn type_last_layer( NaturalTimes => Natural, TextAppend => Text, ListAppend => unreachable!(), + RightBiasedRecordMerge => unreachable!(), _ => return Err(mkerr(Unimplemented)), })?; -- cgit v1.2.3