summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
m---------dhall-lang0
-rw-r--r--dhall/src/phase/normalize.rs36
-rw-r--r--dhall/src/phase/typecheck.rs16
-rw-r--r--dhall_syntax/src/core/text.rs12
-rw-r--r--dhall_syntax/src/parser.rs83
6 files changed, 106 insertions, 43 deletions
diff --git a/README.md b/README.md
index 68f157a..3212b2e 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ This is still quite unstable so use at your own risk. Documentation is severely
- Parsing: 100%
- Imports: 10%
-- Normalization: 83%
+- Normalization: 99%
- Typechecking: 83%
You can see what's missing from the commented out tests in `dhall/src/normalize.rs` and `dhall/src/typecheck.rs`.
diff --git a/dhall-lang b/dhall-lang
-Subproject 43490948b89dc8ed1a8d2d4d89edc962f685224
+Subproject f12c7b5c37b9667162255d9562c811896965eff
diff --git a/dhall/src/phase/normalize.rs b/dhall/src/phase/normalize.rs
index 048c25e..5672bc4 100644
--- a/dhall/src/phase/normalize.rs
+++ b/dhall/src/phase/normalize.rs
@@ -838,18 +838,20 @@ mod spec_tests {
norm!(success_prelude_Text_concat_1, "prelude/Text/concat/1");
norm!(success_prelude_Text_concatMap_0, "prelude/Text/concatMap/0");
norm!(success_prelude_Text_concatMap_1, "prelude/Text/concatMap/1");
- // norm!(success_prelude_Text_concatMapSep_0, "prelude/Text/concatMapSep/0");
- // norm!(success_prelude_Text_concatMapSep_1, "prelude/Text/concatMapSep/1");
- // norm!(success_prelude_Text_concatSep_0, "prelude/Text/concatSep/0");
- // norm!(success_prelude_Text_concatSep_1, "prelude/Text/concatSep/1");
- // norm!(success_prelude_Text_show_0, "prelude/Text/show/0");
- // norm!(success_prelude_Text_show_1, "prelude/Text/show/1");
- // norm!(success_remoteSystems, "remoteSystems");
+ norm!(success_prelude_Text_concatMapSep_0, "prelude/Text/concatMapSep/0");
+ norm!(success_prelude_Text_concatMapSep_1, "prelude/Text/concatMapSep/1");
+ norm!(success_prelude_Text_concatSep_0, "prelude/Text/concatSep/0");
+ norm!(success_prelude_Text_concatSep_1, "prelude/Text/concatSep/1");
+ norm!(success_prelude_Text_show_0, "prelude/Text/show/0");
+ norm!(success_prelude_Text_show_1, "prelude/Text/show/1");
+ norm!(success_remoteSystems, "remoteSystems");
norm!(success_simple_doubleShow, "simple/doubleShow");
norm!(success_simple_enum, "simple/enum");
norm!(success_simple_integerShow, "simple/integerShow");
// norm!(success_simple_integerToDouble, "simple/integerToDouble");
+ norm!(success_simple_letAvoidCapture, "simple/letAvoidCapture");
+ norm!(success_simple_letenum, "simple/letenum");
norm!(success_simple_letlet, "simple/letlet");
norm!(success_simple_listBuild, "simple/listBuild");
norm!(success_simple_multiLine, "simple/multiLine");
@@ -860,6 +862,7 @@ mod spec_tests {
norm!(success_simple_optionalBuild, "simple/optionalBuild");
norm!(success_simple_optionalBuildFold, "simple/optionalBuildFold");
norm!(success_simple_optionalFold, "simple/optionalFold");
+ norm!(success_simple_simpleAddition, "simple/simpleAddition");
norm!(success_simple_sortOperator, "simple/sortOperator");
norm!(success_simplifications_and, "simplifications/and");
norm!(success_simplifications_eq, "simplifications/eq");
@@ -867,6 +870,7 @@ mod spec_tests {
norm!(success_simplifications_ne, "simplifications/ne");
norm!(success_simplifications_or, "simplifications/or");
+ norm!(success_unit_BareInterpolation, "unit/BareInterpolation");
norm!(success_unit_Bool, "unit/Bool");
norm!(success_unit_Double, "unit/Double");
norm!(success_unit_DoubleLiteral, "unit/DoubleLiteral");
@@ -978,6 +982,8 @@ mod spec_tests {
norm!(success_unit_OperatorPlusRhsZero, "unit/OperatorPlusRhsZero");
norm!(success_unit_OperatorTextConcatenateLhsEmpty, "unit/OperatorTextConcatenateLhsEmpty");
norm!(success_unit_OperatorTextConcatenateLhsNonEmpty, "unit/OperatorTextConcatenateLhsNonEmpty");
+ norm!(success_unit_OperatorTextConcatenateRhsEmpty, "unit/OperatorTextConcatenateRhsEmpty");
+ norm!(success_unit_OperatorTextConcatenateRhsNonEmpty, "unit/OperatorTextConcatenateRhsNonEmpty");
norm!(success_unit_OperatorTextConcatenateTextText, "unit/OperatorTextConcatenateTextText");
norm!(success_unit_OperatorTimesLhsOne, "unit/OperatorTimesLhsOne");
norm!(success_unit_OperatorTimesLhsZero, "unit/OperatorTimesLhsZero");
@@ -1037,10 +1043,14 @@ mod spec_tests {
norm!(success_unit_UnionTypeNormalizeArguments, "unit/UnionTypeNormalizeArguments");
norm!(success_unit_Variable, "unit/Variable");
- alpha_norm!(alpha_success_unit_FunctionBindingUnderscore, "unit/FunctionBindingUnderscore");
- alpha_norm!(alpha_success_unit_FunctionBindingX, "unit/FunctionBindingX");
- alpha_norm!(alpha_success_unit_FunctionNestedBindingX, "unit/FunctionNestedBindingX");
- alpha_norm!(alpha_success_unit_FunctionTypeBindingUnderscore, "unit/FunctionTypeBindingUnderscore");
- alpha_norm!(alpha_success_unit_FunctionTypeBindingX, "unit/FunctionTypeBindingX");
- alpha_norm!(alpha_success_unit_FunctionTypeNestedBindingX, "unit/FunctionTypeNestedBindingX");
+ alpha_norm!(regression_preludeBoolFold, "regression/preludeBoolFold");
+ alpha_norm!(unit_FunctionBindingUnderscore, "unit/FunctionBindingUnderscore");
+ alpha_norm!(unit_FunctionBindingX, "unit/FunctionBindingX");
+ alpha_norm!(unit_FunctionNestedBindingX, "unit/FunctionNestedBindingX");
+ alpha_norm!(unit_FunctionNestedBindingXX, "unit/FunctionNestedBindingXX");
+ // alpha_norm!(unit_FunctionNestedBindingXXFree, "unit/FunctionNestedBindingXXFree");
+ alpha_norm!(unit_FunctionNestedBindingXY, "unit/FunctionNestedBindingXY");
+ alpha_norm!(unit_FunctionTypeBindingUnderscore, "unit/FunctionTypeBindingUnderscore");
+ alpha_norm!(unit_FunctionTypeBindingX, "unit/FunctionTypeBindingX");
+ alpha_norm!(unit_FunctionTypeNestedBindingX, "unit/FunctionTypeNestedBindingX");
}
diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs
index fa37379..265ce08 100644
--- a/dhall/src/phase/typecheck.rs
+++ b/dhall/src/phase/typecheck.rs
@@ -1007,6 +1007,7 @@ mod spec_tests {
tc_failure!(tc_failure_combineMixedRecords, "combineMixedRecords");
// tc_failure!(tc_failure_duplicateFields, "duplicateFields");
tc_failure!(tc_failure_hurkensParadox, "hurkensParadox");
+ // tc_failure!(tc_failure_importBoundary, "importBoundary");
tc_failure!(tc_failure_mixedUnions, "mixedUnions");
tc_failure!(tc_failure_preferMixedRecords, "preferMixedRecords");
tc_failure!(tc_failure_unit_FunctionApplicationArgumentNotMatch, "unit/FunctionApplicationArgumentNotMatch");
@@ -1039,6 +1040,7 @@ mod spec_tests {
tc_failure!(tc_failure_unit_OperatorEqualNotBool, "unit/OperatorEqualNotBool");
tc_failure!(tc_failure_unit_OperatorListConcatenateLhsNotList, "unit/OperatorListConcatenateLhsNotList");
tc_failure!(tc_failure_unit_OperatorListConcatenateListsNotMatch, "unit/OperatorListConcatenateListsNotMatch");
+ tc_failure!(tc_failure_unit_OperatorListConcatenateNotListsButMatch, "unit/OperatorListConcatenateNotListsButMatch");
tc_failure!(tc_failure_unit_OperatorListConcatenateRhsNotList, "unit/OperatorListConcatenateRhsNotList");
tc_failure!(tc_failure_unit_OperatorNotEqualNotBool, "unit/OperatorNotEqualNotBool");
tc_failure!(tc_failure_unit_OperatorOrNotBool, "unit/OperatorOrNotBool");
@@ -1083,8 +1085,8 @@ mod spec_tests {
tc_failure!(tc_failure_unit_UnionTypeNotType, "unit/UnionTypeNotType");
tc_failure!(tc_failure_unit_VariableFree, "unit/VariableFree");
- // ti_success!(ti_success_simple_alternativesAreTypes, "simple/alternativesAreTypes");
- // ti_success!(ti_success_simple_kindParameter, "simple/kindParameter");
+ ti_success!(ti_success_simple_alternativesAreTypes, "simple/alternativesAreTypes");
+ ti_success!(ti_success_simple_kindParameter, "simple/kindParameter");
ti_success!(ti_success_unit_Bool, "unit/Bool");
ti_success!(ti_success_unit_Double, "unit/Double");
ti_success!(ti_success_unit_DoubleLiteral, "unit/DoubleLiteral");
@@ -1157,6 +1159,10 @@ mod spec_tests {
ti_success!(ti_success_unit_OptionalBuild, "unit/OptionalBuild");
ti_success!(ti_success_unit_OptionalFold, "unit/OptionalFold");
ti_success!(ti_success_unit_RecordEmpty, "unit/RecordEmpty");
+ ti_success!(ti_success_unit_RecordNestedKind, "unit/RecordNestedKind");
+ ti_success!(ti_success_unit_RecordNestedKindLike, "unit/RecordNestedKindLike");
+ ti_success!(ti_success_unit_RecordNestedType, "unit/RecordNestedType");
+ ti_success!(ti_success_unit_RecordNestedTypeLike, "unit/RecordNestedTypeLike");
ti_success!(ti_success_unit_RecordOneKind, "unit/RecordOneKind");
ti_success!(ti_success_unit_RecordOneType, "unit/RecordOneType");
ti_success!(ti_success_unit_RecordOneValue, "unit/RecordOneValue");
@@ -1170,15 +1176,20 @@ mod spec_tests {
ti_success!(ti_success_unit_RecordType, "unit/RecordType");
ti_success!(ti_success_unit_RecordTypeEmpty, "unit/RecordTypeEmpty");
ti_success!(ti_success_unit_RecordTypeKind, "unit/RecordTypeKind");
+ ti_success!(ti_success_unit_RecordTypeKindLike, "unit/RecordTypeKindLike");
+ ti_success!(ti_success_unit_RecordTypeNestedKind, "unit/RecordTypeNestedKind");
+ ti_success!(ti_success_unit_RecordTypeNestedKindLike, "unit/RecordTypeNestedKindLike");
ti_success!(ti_success_unit_RecordTypeType, "unit/RecordTypeType");
// ti_success!(ti_success_unit_RecursiveRecordMergeLhsEmpty, "unit/RecursiveRecordMergeLhsEmpty");
// ti_success!(ti_success_unit_RecursiveRecordMergeRecursively, "unit/RecursiveRecordMergeRecursively");
+ // ti_success!(ti_success_unit_RecursiveRecordMergeRecursivelyKinds, "unit/RecursiveRecordMergeRecursivelyKinds");
// ti_success!(ti_success_unit_RecursiveRecordMergeRecursivelyTypes, "unit/RecursiveRecordMergeRecursivelyTypes");
// ti_success!(ti_success_unit_RecursiveRecordMergeRhsEmpty, "unit/RecursiveRecordMergeRhsEmpty");
// ti_success!(ti_success_unit_RecursiveRecordMergeTwo, "unit/RecursiveRecordMergeTwo");
// ti_success!(ti_success_unit_RecursiveRecordMergeTwoKinds, "unit/RecursiveRecordMergeTwoKinds");
// ti_success!(ti_success_unit_RecursiveRecordMergeTwoTypes, "unit/RecursiveRecordMergeTwoTypes");
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeRecursively, "unit/RecursiveRecordTypeMergeRecursively");
+ // ti_success!(ti_success_unit_RecursiveRecordTypeMergeRecursivelyKinds, "unit/RecursiveRecordTypeMergeRecursivelyKinds");
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeRecursivelyTypes, "unit/RecursiveRecordTypeMergeRecursivelyTypes");
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeRhsEmpty, "unit/RecursiveRecordTypeMergeRhsEmpty");
// ti_success!(ti_success_unit_RecursiveRecordTypeMergeTwo, "unit/RecursiveRecordTypeMergeTwo");
@@ -1199,6 +1210,7 @@ mod spec_tests {
ti_success!(ti_success_unit_Type, "unit/Type");
ti_success!(ti_success_unit_TypeAnnotation, "unit/TypeAnnotation");
ti_success!(ti_success_unit_TypeAnnotationSort, "unit/TypeAnnotationSort");
+ ti_success!(ti_success_unit_UnionConstructorEmptyField, "unit/UnionConstructorEmptyField");
ti_success!(ti_success_unit_UnionConstructorField, "unit/UnionConstructorField");
ti_success!(ti_success_unit_UnionOne, "unit/UnionOne");
ti_success!(ti_success_unit_UnionTypeEmpty, "unit/UnionTypeEmpty");
diff --git a/dhall_syntax/src/core/text.rs b/dhall_syntax/src/core/text.rs
index 83643d9..e79a86b 100644
--- a/dhall_syntax/src/core/text.rs
+++ b/dhall_syntax/src/core/text.rs
@@ -43,6 +43,18 @@ impl<SubExpr> InterpolatedTextContents<SubExpr> {
}
impl<SubExpr> InterpolatedText<SubExpr> {
+ pub fn head(&self) -> &str {
+ &self.head
+ }
+
+ pub fn head_mut(&mut self) -> &mut String {
+ &mut self.head
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.head.is_empty() && self.tail.is_empty()
+ }
+
pub fn traverse_ref<'a, SubExpr2, E, F>(
&'a self,
mut f: F,
diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs
index 51dbfd2..607d19c 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -319,6 +319,47 @@ fn can_be_shortcutted(rule: Rule) -> bool {
}
}
+// Trim the shared indent off of a vec of lines, as defined by the Dhall semantics of multiline
+// literals.
+fn trim_indent(lines: &mut Vec<ParsedText>) {
+ let is_indent = |c: char| c == ' ' || c == '\t';
+
+ // There is at least one line so this is safe
+ let last_line_head = lines.last().unwrap().head();
+ let indent_chars = last_line_head
+ .char_indices()
+ .take_while(|(_, c)| is_indent(*c));
+ let mut min_indent_idx = match indent_chars.last() {
+ Some((i, _)) => i,
+ // If there is no indent char, then no indent needs to be stripped
+ None => return,
+ };
+
+ for line in lines.iter() {
+ // Ignore empty lines
+ if line.is_empty() {
+ continue;
+ }
+ // Take chars from line while they match the current minimum indent.
+ let indent_chars = last_line_head[0..=min_indent_idx]
+ .char_indices()
+ .zip(line.head().chars())
+ .take_while(|((_, c1), c2)| c1 == c2);
+ match indent_chars.last() {
+ Some(((i, _), _)) => min_indent_idx = i,
+ // If there is no indent char, then no indent needs to be stripped
+ None => return,
+ };
+ }
+
+ // Remove the shared indent from non-empty lines
+ for line in lines.iter_mut() {
+ if !line.is_empty() {
+ line.head_mut().replace_range(0..=min_indent_idx, "");
+ }
+ }
+}
+
make_parser! {
token_rule!(EOI<()>);
@@ -378,38 +419,37 @@ make_parser! {
rule!(single_quote_literal<ParsedText>; children!(
[single_quote_continue(lines)] => {
- let space = InterpolatedTextContents::Text(" ".to_owned());
- let newline = InterpolatedTextContents::Text("\n".to_owned());
- let min_indent = lines
- .iter()
- .map(|l| {
- l.iter().rev().take_while(|c| **c == space).count()
- })
- .min()
- .unwrap();
+ let newline: ParsedText = "\n".to_string().into();
- lines
+ let mut lines: Vec<ParsedText> = lines
.into_iter()
.rev()
- .map(|mut l| { l.split_off(l.len() - min_indent); l })
- .intersperse(vec![newline])
- .flat_map(|x| x.into_iter().rev())
+ .map(|l| l.into_iter().rev().collect::<ParsedText>())
+ .collect();
+
+ trim_indent(&mut lines);
+
+ lines
+ .into_iter()
+ .intersperse(newline)
+ .flat_map(|x| x.into_iter())
.collect::<ParsedText>()
}
));
rule!(single_quote_char<&'a str>;
captured_str!(s) => s
);
- rule!(escaped_quote_pair<&'a str>;
+ rule!(escaped_quote_pair<&'a str> as single_quote_char;
captured_str!(_) => "''"
);
- rule!(escaped_interpolation<&'a str>;
+ rule!(escaped_interpolation<&'a str> as single_quote_char;
captured_str!(_) => "${"
);
rule!(interpolation<ParsedSubExpr>; children!(
[expression(e)] => e
));
+ // Returns a vec of lines in reversed order, where each line is also in reversed order.
rule!(single_quote_continue<Vec<Vec<ParsedTextContents>>>; children!(
[interpolation(c), single_quote_continue(lines)] => {
let c = InterpolatedTextContents::Expr(c);
@@ -417,24 +457,13 @@ make_parser! {
lines.last_mut().unwrap().push(c);
lines
},
- [escaped_quote_pair(c), single_quote_continue(lines)] => {
- let c = InterpolatedTextContents::Text(c.to_owned());
- let mut lines = lines;
- lines.last_mut().unwrap().push(c);
- lines
- },
- [escaped_interpolation(c), single_quote_continue(lines)] => {
- let c = InterpolatedTextContents::Text(c.to_owned());
- let mut lines = lines;
- lines.last_mut().unwrap().push(c);
- lines
- },
[single_quote_char("\n"), single_quote_continue(lines)] => {
let mut lines = lines;
lines.push(vec![]);
lines
},
[single_quote_char(c), single_quote_continue(lines)] => {
+ // TODO: don't allocate for every char
let c = InterpolatedTextContents::Text(c.to_owned());
let mut lines = lines;
lines.last_mut().unwrap().push(c);