Skip to content

Commit e366681

Browse files
committed
Generate constr for match expression and arm conds (#397)
* Generate constr for match expression and arm conds * Do not propagate for handle - Add factorial test from README
1 parent 198815d commit e366681

7 files changed

Lines changed: 48 additions & 6 deletions

File tree

src/check/constrain/constraint/iterator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ impl Constraints {
4444
if constraint.is_flag {
4545
// Can only reinsert constraint once
4646
let msg = format!(
47-
"Cannot infer type. Expected a {}, was {}",
48-
&constraint.left.expect, &constraint.right.expect
47+
"Cannot infer type within {}. Expected a {}, was {}",
48+
constraint.msg, &constraint.left.expect, &constraint.right.expect
4949
);
5050
return Err(vec![TypeErr::new(constraint.left.pos, &msg)]);
5151
}

src/check/constrain/generate/control_flow.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub fn gen_flow(
3838
let outer_env = generate(expr_or_stmt, &env.raises_caught(&raises), ctx, constr)?
3939
.raises_caught(&raises_before);
4040

41-
constrain_cases(ast, cases, &outer_env, ctx, constr)?;
41+
constrain_cases(ast, &None, cases, &outer_env, ctx, constr)?;
4242
Ok(outer_env.clone())
4343
}
4444

@@ -83,7 +83,7 @@ pub fn gen_flow(
8383
Node::Case { .. } => Err(vec![TypeErr::new(ast.pos, "Case cannot be top level")]),
8484
Node::Match { cond, cases } => {
8585
let outer_env = generate(cond, env, ctx, constr)?;
86-
constrain_cases(ast, cases, &outer_env, ctx, constr)?;
86+
constrain_cases(ast, &Some(*cond.clone()), cases, &outer_env, ctx, constr)?;
8787
Ok(env.clone())
8888
}
8989

@@ -116,7 +116,7 @@ pub fn gen_flow(
116116
}
117117
}
118118

119-
fn constrain_cases(ast: &AST, cases: &Vec<AST>, env: &Environment, ctx: &Context, constr: &mut ConstrBuilder) -> Constrained<()> {
119+
fn constrain_cases(ast: &AST, expr: &Option<AST>, cases: &Vec<AST>, env: &Environment, ctx: &Context, constr: &mut ConstrBuilder) -> Constrained<()> {
120120
let is_define_mode = env.is_def_mode;
121121
let exp_ast = Expected::try_from((ast, &env.var_mappings))?;
122122

@@ -128,8 +128,17 @@ fn constrain_cases(ast: &AST, cases: &Vec<AST>, env: &Environment, ctx: &Context
128128
let cond_env = generate(cond, &env.is_def_mode(true), ctx, constr)?;
129129
generate(body, &cond_env.is_def_mode(is_define_mode), ctx, constr)?;
130130

131+
if let Node::ExpressionType { expr: ref cond, .. } = cond.node {
132+
if let Some(expr) = expr {
133+
constr.add("match expression and arm condition",
134+
&Expected::try_from((expr, &env.var_mappings))?,
135+
&Expected::try_from((cond, &env.var_mappings))?,
136+
);
137+
}
138+
}
139+
131140
let exp_body = Expected::try_from((body, &cond_env.var_mappings))?;
132-
constr.add("handle arm body", &exp_body, &exp_ast);
141+
constr.add("match arm body", &exp_body, &exp_ast);
133142
constr.exit_set(case.pos)?;
134143
}
135144
_ => return Err(vec![TypeErr::new(case.pos, "Expected case")])

src/check/resource/std/input

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
def input(in: str) -> str: pass
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
def factorial(x: Int) -> Int => match x
2+
0 => 1
3+
n => n * factorial(n - 1)
4+
5+
def num := input("Compute factorial: ")
6+
if num.is_digit() then
7+
def result := factorial(Int(num))
8+
print("Factorial {num} is: {result}.")
9+
else
10+
print("Input was not an integer.")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from typing import Union
2+
def factorial(x: int) -> int:
3+
match x:
4+
case 0:
5+
return 1
6+
case n:
7+
return n * factorial(n - 1)
8+
9+
num: Union[flot, int, str] = input("Compute factorial: ")
10+
11+
if num.is_digit():
12+
result = factorial(int(num))
13+
print(f"Factorial {num} is: {result}.")
14+
else:
15+
print("Input was not an integer.")

tests/system/valid/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod definition;
99
pub mod error;
1010
pub mod function;
1111
pub mod operation;
12+
pub mod readme_examples;
1213

1314
#[test]
1415
fn empty_file() -> OutTestRet {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
use crate::system::{OutTestRet, test_directory};
2+
3+
#[test]
4+
fn factorial() -> OutTestRet {
5+
test_directory(true, &["readme_example"], &["readme_example", "target"], "factorial")
6+
}

0 commit comments

Comments
 (0)