mirror of
				https://github.com/roc-lang/roc.git
				synced 2025-11-03 22:13:35 +00:00 
			
		
		
		
	Add tests for desugaring and formatting
This commit is contained in:
		
							parent
							
								
									a292e070d4
								
							
						
					
					
						commit
						1a9668e83a
					
				
					 2 changed files with 174 additions and 51 deletions
				
			
		| 
						 | 
					@ -972,7 +972,59 @@ mod test_can {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn try_desugar_double_question_binop() {
 | 
					    fn try_desugar_works_elsewhere() {
 | 
				
			||||||
 | 
					        let src = indoc!(
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					                when Foo 123 is
 | 
				
			||||||
 | 
					                    Foo try -> try
 | 
				
			||||||
 | 
					            "#
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let arena = Bump::new();
 | 
				
			||||||
 | 
					        let out = can_expr_with(&arena, test_home(), src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!(out.problems, Vec::new());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Assert that we don't treat `try` as a keyword here
 | 
				
			||||||
 | 
					        // by desugaring to:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // when Foo 123 is
 | 
				
			||||||
 | 
					        //     Foo try -> try
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let (cond_expr, branches) = assert_when_expr(&out.loc_expr.value);
 | 
				
			||||||
 | 
					        match cond_expr {
 | 
				
			||||||
 | 
					            Expr::Tag {
 | 
				
			||||||
 | 
					                name, arguments, ..
 | 
				
			||||||
 | 
					            } => {
 | 
				
			||||||
 | 
					                assert_eq!(name.0.to_string(), "Foo");
 | 
				
			||||||
 | 
					                assert_eq!(arguments.len(), 1);
 | 
				
			||||||
 | 
					                assert_num_value(&arguments[0].1.value, 123);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => panic!("cond_expr was not a Tag: {:?}", cond_expr),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!(branches.len(), 1);
 | 
				
			||||||
 | 
					        assert_eq!(branches[0].patterns.len(), 1);
 | 
				
			||||||
 | 
					        assert!(!branches[0].patterns[0].degenerate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match &branches[0].patterns[0].pattern.value {
 | 
				
			||||||
 | 
					            Pattern::AppliedTag {
 | 
				
			||||||
 | 
					                tag_name,
 | 
				
			||||||
 | 
					                arguments,
 | 
				
			||||||
 | 
					                ..
 | 
				
			||||||
 | 
					            } => {
 | 
				
			||||||
 | 
					                assert_eq!(tag_name.0.to_string(), "Foo");
 | 
				
			||||||
 | 
					                assert_eq!(arguments.len(), 1);
 | 
				
			||||||
 | 
					                assert_pattern_name(&arguments[0].1.value, "try", &out.interns);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            other => panic!("First argument was not an applied tag: {:?}", other),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_var_usage(&branches[0].value.value, "try", &out.interns);
 | 
				
			||||||
 | 
					        assert!(&branches[0].guard.is_none());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn desugar_double_question_binop() {
 | 
				
			||||||
        let src = indoc!(
 | 
					        let src = indoc!(
 | 
				
			||||||
            r#"
 | 
					            r#"
 | 
				
			||||||
                Str.to_u64("123") ?? Num.max_u64
 | 
					                Str.to_u64("123") ?? Num.max_u64
 | 
				
			||||||
| 
						 | 
					@ -989,7 +1041,7 @@ mod test_can {
 | 
				
			||||||
        //   Ok(#double_question_ok_0_17) -> Ok(#double_question_ok_0_17)
 | 
					        //   Ok(#double_question_ok_0_17) -> Ok(#double_question_ok_0_17)
 | 
				
			||||||
        //   Err(_) -> Num.max_u64
 | 
					        //   Err(_) -> Num.max_u64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (cond_expr, branches) = assert_when(&out.loc_expr.value);
 | 
					        let (cond_expr, branches) = assert_when_expr(&out.loc_expr.value);
 | 
				
			||||||
        let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns);
 | 
					        let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(cond_args.len(), 1);
 | 
					        assert_eq!(cond_args.len(), 1);
 | 
				
			||||||
| 
						 | 
					@ -1016,7 +1068,7 @@ mod test_can {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn try_desugar_single_question_binop() {
 | 
					    fn desugar_single_question_binop() {
 | 
				
			||||||
        let src = indoc!(
 | 
					        let src = indoc!(
 | 
				
			||||||
            r#"
 | 
					            r#"
 | 
				
			||||||
                Str.to_u64("123") ? FailedToConvert
 | 
					                Str.to_u64("123") ? FailedToConvert
 | 
				
			||||||
| 
						 | 
					@ -1033,7 +1085,7 @@ mod test_can {
 | 
				
			||||||
        //   Ok(#single_question_ok_0_17) -> #single_question_ok_0_17
 | 
					        //   Ok(#single_question_ok_0_17) -> #single_question_ok_0_17
 | 
				
			||||||
        //   Err(#single_question_err_0_17) -> return Err(FailedToConvert(#single_question_err_0_17))
 | 
					        //   Err(#single_question_err_0_17) -> return Err(FailedToConvert(#single_question_err_0_17))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (cond_expr, branches) = assert_when(&out.loc_expr.value);
 | 
					        let (cond_expr, branches) = assert_when_expr(&out.loc_expr.value);
 | 
				
			||||||
        let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns);
 | 
					        let cond_args = assert_func_call(cond_expr, "to_u64", CalledVia::Space, &out.interns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(cond_args.len(), 1);
 | 
					        assert_eq!(cond_args.len(), 1);
 | 
				
			||||||
| 
						 | 
					@ -1075,11 +1127,13 @@ mod test_can {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn try_desugar_works_elsewhere() {
 | 
					    fn desugar_and_operator() {
 | 
				
			||||||
        let src = indoc!(
 | 
					        let src = indoc!(
 | 
				
			||||||
            r#"
 | 
					            r#"
 | 
				
			||||||
                when Foo 123 is
 | 
					                left = Bool.true
 | 
				
			||||||
                    Foo try -> try
 | 
					                right = Bool.false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                left and right
 | 
				
			||||||
            "#
 | 
					            "#
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        let arena = Bump::new();
 | 
					        let arena = Bump::new();
 | 
				
			||||||
| 
						 | 
					@ -1087,43 +1141,49 @@ mod test_can {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(out.problems, Vec::new());
 | 
					        assert_eq!(out.problems, Vec::new());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Assert that we don't treat `try` as a keyword here
 | 
					        // Assert that we desugar to:
 | 
				
			||||||
        // by desugaring to:
 | 
					 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
        // when Foo 123 is
 | 
					        // if left then right else Bool.false
 | 
				
			||||||
        //     Foo try -> try
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (cond_expr, branches) = assert_when(&out.loc_expr.value);
 | 
					        let continuation1 = assert_let_expr(&out.loc_expr.value);
 | 
				
			||||||
        match cond_expr {
 | 
					        let continuation2 = assert_let_expr(&continuation1.value);
 | 
				
			||||||
            Expr::Tag {
 | 
					        let (branches, final_else) = assert_if_expr(&continuation2.value);
 | 
				
			||||||
                name, arguments, ..
 | 
					 | 
				
			||||||
            } => {
 | 
					 | 
				
			||||||
                assert_eq!(name.0.to_string(), "Foo");
 | 
					 | 
				
			||||||
                assert_eq!(arguments.len(), 1);
 | 
					 | 
				
			||||||
                assert_num_value(&arguments[0].1.value, 123);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            _ => panic!("cond_expr was not a Tag: {:?}", cond_expr),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_eq!(branches.len(), 1);
 | 
					        assert_eq!(branches.len(), 1);
 | 
				
			||||||
        assert_eq!(branches[0].patterns.len(), 1);
 | 
					 | 
				
			||||||
        assert!(!branches[0].patterns[0].degenerate);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match &branches[0].patterns[0].pattern.value {
 | 
					        assert_var_usage(&branches[0].0.value, "left", &out.interns);
 | 
				
			||||||
            Pattern::AppliedTag {
 | 
					        assert_var_usage(&branches[0].1.value, "right", &out.interns);
 | 
				
			||||||
                tag_name,
 | 
					        assert_var_usage(&final_else.value, "false", &out.interns);
 | 
				
			||||||
                arguments,
 | 
					    }
 | 
				
			||||||
                ..
 | 
					 | 
				
			||||||
            } => {
 | 
					 | 
				
			||||||
                assert_eq!(tag_name.0.to_string(), "Foo");
 | 
					 | 
				
			||||||
                assert_eq!(arguments.len(), 1);
 | 
					 | 
				
			||||||
                assert_pattern_name(&arguments[0].1.value, "try", &out.interns);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            other => panic!("First argument was not an applied tag: {:?}", other),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_var_usage(&branches[0].value.value, "try", &out.interns);
 | 
					    #[test]
 | 
				
			||||||
        assert!(&branches[0].guard.is_none());
 | 
					    fn desugar_or_operator() {
 | 
				
			||||||
 | 
					        let src = indoc!(
 | 
				
			||||||
 | 
					            r#"
 | 
				
			||||||
 | 
					                left = Bool.true
 | 
				
			||||||
 | 
					                right = Bool.false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                left or right
 | 
				
			||||||
 | 
					            "#
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let arena = Bump::new();
 | 
				
			||||||
 | 
					        let out = can_expr_with(&arena, test_home(), src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!(out.problems, Vec::new());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Assert that we desugar to:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // if left then Bool.true else right
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let continuation1 = assert_let_expr(&out.loc_expr.value);
 | 
				
			||||||
 | 
					        let continuation2 = assert_let_expr(&continuation1.value);
 | 
				
			||||||
 | 
					        let (branches, final_else) = assert_if_expr(&continuation2.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_eq!(branches.len(), 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert_var_usage(&branches[0].0.value, "left", &out.interns);
 | 
				
			||||||
 | 
					        assert_var_usage(&branches[0].1.value, "true", &out.interns);
 | 
				
			||||||
 | 
					        assert_var_usage(&final_else.value, "right", &out.interns);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn assert_num_value(expr: &Expr, num: usize) {
 | 
					    fn assert_num_value(expr: &Expr, num: usize) {
 | 
				
			||||||
| 
						 | 
					@ -1238,7 +1298,14 @@ mod test_can {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn assert_when(expr: &Expr) -> (&Expr, &Vec<WhenBranch>) {
 | 
					    fn assert_let_expr(expr: &Expr) -> &Loc<Expr> {
 | 
				
			||||||
 | 
					        match expr {
 | 
				
			||||||
 | 
					            Expr::LetNonRec(_, continuation) | Expr::LetRec(_, continuation, _) => continuation,
 | 
				
			||||||
 | 
					            _ => panic!("Expr was not a Let(Non)?Rec: {expr:?}",),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn assert_when_expr(expr: &Expr) -> (&Expr, &Vec<WhenBranch>) {
 | 
				
			||||||
        match expr {
 | 
					        match expr {
 | 
				
			||||||
            Expr::When {
 | 
					            Expr::When {
 | 
				
			||||||
                loc_cond, branches, ..
 | 
					                loc_cond, branches, ..
 | 
				
			||||||
| 
						 | 
					@ -1247,6 +1314,17 @@ mod test_can {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn assert_if_expr(expr: &Expr) -> (&[(Loc<Expr>, Loc<Expr>)], &Loc<Expr>) {
 | 
				
			||||||
 | 
					        match expr {
 | 
				
			||||||
 | 
					            Expr::If {
 | 
				
			||||||
 | 
					                branches,
 | 
				
			||||||
 | 
					                final_else,
 | 
				
			||||||
 | 
					                ..
 | 
				
			||||||
 | 
					            } => (&branches, &**final_else),
 | 
				
			||||||
 | 
					            _ => panic!("Expr was not a When: {:?}", expr),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn assert_try_expr(expr: &Expr) -> &Expr {
 | 
					    fn assert_try_expr(expr: &Expr) -> &Expr {
 | 
				
			||||||
        match expr {
 | 
					        match expr {
 | 
				
			||||||
            Expr::Try { result_expr, .. } => &result_expr.value,
 | 
					            Expr::Try { result_expr, .. } => &result_expr.value,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5022,8 +5022,8 @@ mod test_fmt {
 | 
				
			||||||
                r#"
 | 
					                r#"
 | 
				
			||||||
            if
 | 
					            if
 | 
				
			||||||
                (1 == 1)
 | 
					                (1 == 1)
 | 
				
			||||||
                && (2 == 1)
 | 
					                and (2 == 1)
 | 
				
			||||||
                && (3 == 2)
 | 
					                and (3 == 2)
 | 
				
			||||||
            then
 | 
					            then
 | 
				
			||||||
                "true"
 | 
					                "true"
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
| 
						 | 
					@ -5317,18 +5317,63 @@ mod test_fmt {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn multi_line_binary_op_1() {
 | 
					    fn multi_line_binary_op_and() {
 | 
				
			||||||
 | 
					        expr_formats_to(
 | 
				
			||||||
 | 
					            indoc!(
 | 
				
			||||||
 | 
					                r"
 | 
				
			||||||
 | 
					                is_last
 | 
				
			||||||
 | 
					                && is_empty
 | 
				
			||||||
 | 
					                && is_loaded
 | 
				
			||||||
 | 
					                "
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            indoc!(
 | 
				
			||||||
 | 
					                r"
 | 
				
			||||||
 | 
					                is_last
 | 
				
			||||||
 | 
					                and is_empty
 | 
				
			||||||
 | 
					                and is_loaded
 | 
				
			||||||
 | 
					                "
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expr_formats_same(indoc!(
 | 
					        expr_formats_same(indoc!(
 | 
				
			||||||
            r"
 | 
					            r"
 | 
				
			||||||
            isLast
 | 
					            is_last
 | 
				
			||||||
            && isEmpty
 | 
					            and is_empty
 | 
				
			||||||
            && isLoaded
 | 
					            and is_loaded
 | 
				
			||||||
            "
 | 
					            "
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn multi_line_binary_op_2() {
 | 
					    fn multi_line_binary_op_or() {
 | 
				
			||||||
 | 
					        expr_formats_to(
 | 
				
			||||||
 | 
					            indoc!(
 | 
				
			||||||
 | 
					                r"
 | 
				
			||||||
 | 
					                is_last
 | 
				
			||||||
 | 
					                || is_empty
 | 
				
			||||||
 | 
					                || is_loaded
 | 
				
			||||||
 | 
					                "
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            indoc!(
 | 
				
			||||||
 | 
					                r"
 | 
				
			||||||
 | 
					                is_last
 | 
				
			||||||
 | 
					                or is_empty
 | 
				
			||||||
 | 
					                or is_loaded
 | 
				
			||||||
 | 
					                "
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expr_formats_same(indoc!(
 | 
				
			||||||
 | 
					            r"
 | 
				
			||||||
 | 
					            is_last
 | 
				
			||||||
 | 
					            or is_empty
 | 
				
			||||||
 | 
					            or is_loaded
 | 
				
			||||||
 | 
					            "
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn multi_line_binary_op_symbol() {
 | 
				
			||||||
        expr_formats_to(
 | 
					        expr_formats_to(
 | 
				
			||||||
            indoc!(
 | 
					            indoc!(
 | 
				
			||||||
                r"
 | 
					                r"
 | 
				
			||||||
| 
						 | 
					@ -5398,15 +5443,15 @@ mod test_fmt {
 | 
				
			||||||
        expr_formats_to(
 | 
					        expr_formats_to(
 | 
				
			||||||
            indoc!(
 | 
					            indoc!(
 | 
				
			||||||
                r"
 | 
					                r"
 | 
				
			||||||
                isGreenLight
 | 
					                is_green_light
 | 
				
			||||||
                    && isRedLight && isYellowLight
 | 
					                    && is_red_light && is_yellow_light
 | 
				
			||||||
                "
 | 
					                "
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            indoc!(
 | 
					            indoc!(
 | 
				
			||||||
                r"
 | 
					                r"
 | 
				
			||||||
                isGreenLight
 | 
					                is_green_light
 | 
				
			||||||
                && isRedLight
 | 
					                and is_red_light
 | 
				
			||||||
                && isYellowLight
 | 
					                and is_yellow_light
 | 
				
			||||||
                "
 | 
					                "
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue