Constrain optional fields

This commit is contained in:
Richard Feldman 2020-07-18 14:51:18 -04:00
parent 1bdfe578bd
commit 7330e82f75
5 changed files with 39 additions and 10 deletions

View File

@ -1,4 +1,5 @@
use crate::env::Env;
use crate::expr::Expr;
use crate::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
use crate::scope::Scope;
use roc_module::ident::{Ident, Lowercase, TagName};
@ -50,7 +51,7 @@ pub struct RecordDestruct {
#[derive(Clone, Debug, PartialEq)]
pub enum DestructType {
Required,
Optional(Variable),
Optional(Variable, Located<Expr>),
Guard(Variable, Located<Pattern>),
}

View File

@ -327,6 +327,7 @@ pub fn constrain_expr(
pattern_types.push(pattern_type);
constrain_pattern(
env,
&loc_pattern.value,
loc_pattern.region,
pattern_expected,
@ -843,6 +844,7 @@ fn constrain_when_branch(
// then unify that variable with the expectation?
for loc_pattern in &when_branch.patterns {
constrain_pattern(
env,
&loc_pattern.value,
loc_pattern.region,
pattern_expected.clone(),
@ -947,7 +949,11 @@ pub fn constrain_decls(
constraint
}
fn constrain_def_pattern(loc_pattern: &Located<Pattern>, expr_type: Type) -> PatternState {
fn constrain_def_pattern(
env: &Env,
loc_pattern: &Located<Pattern>,
expr_type: Type,
) -> PatternState {
let pattern_expected = PExpected::NoExpectation(expr_type);
let mut state = PatternState {
@ -957,6 +963,7 @@ fn constrain_def_pattern(loc_pattern: &Located<Pattern>, expr_type: Type) -> Pat
};
constrain_pattern(
env,
&loc_pattern.value,
loc_pattern.region,
pattern_expected,
@ -970,7 +977,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
let expr_var = def.expr_var;
let expr_type = Type::Variable(expr_var);
let mut pattern_state = constrain_def_pattern(&def.loc_pattern, expr_type.clone());
let mut pattern_state = constrain_def_pattern(env, &def.loc_pattern, expr_type.clone());
pattern_state.vars.push(expr_var);
@ -1117,6 +1124,7 @@ pub fn rec_defs_help(
};
constrain_pattern(
env,
&def.loc_pattern.value,
def.loc_pattern.region,
pattern_expected,

View File

@ -1,4 +1,5 @@
use crate::builtins;
use crate::expr::{constrain_expr, Env};
use roc_can::constraint::Constraint;
use roc_can::expected::{Expected, PExpected};
use roc_can::pattern::Pattern::{self, *};
@ -8,7 +9,7 @@ use roc_module::ident::Lowercase;
use roc_module::symbol::Symbol;
use roc_region::all::{Located, Region};
use roc_types::subs::Variable;
use roc_types::types::{Category, PReason, PatternCategory, RecordField, Type};
use roc_types::types::{Category, PReason, PatternCategory, Reason, RecordField, Type};
pub struct PatternState {
pub headers: SendMap<Symbol, Located<Type>>,
@ -120,6 +121,7 @@ fn headers_from_annotation_help(
/// intiialize the Vecs in PatternState using with_capacity
/// based on its knowledge of their lengths.
pub fn constrain_pattern(
env: &Env,
pattern: &Pattern,
region: Region,
expected: PExpected<Type>,
@ -223,14 +225,30 @@ pub fn constrain_pattern(
));
state.vars.push(*guard_var);
constrain_pattern(&loc_guard.value, loc_guard.region, expected, state);
constrain_pattern(env, &loc_guard.value, loc_guard.region, expected, state);
RecordField::Required(pat_type)
}
DestructType::Optional(_var) => {
todo!("Add a constraint for the default value.");
DestructType::Optional(expr_var, loc_expr) => {
// Eq(Type, Expected<Type>, Category, Region),
let expr_expected = Expected::ForReason(
Reason::RecordDefaultField(label.clone()),
pat_type.clone(),
loc_expr.region,
);
// RecordField::Optional(pat_type)
state.constraints.push(Constraint::Eq(
Type::Variable(*expr_var),
expr_expected.clone(),
Category::DefaultValue(label.clone()),
region,
));
state.vars.push(*expr_var);
constrain_expr(env, loc_expr.region, &loc_expr.value, expr_expected);
RecordField::Optional(pat_type)
}
DestructType::Required => {
// No extra constraints necessary.
@ -283,7 +301,7 @@ pub fn constrain_pattern(
pattern_type,
region,
);
constrain_pattern(&loc_pattern.value, loc_pattern.region, expected, state);
constrain_pattern(env, &loc_pattern.value, loc_pattern.region, expected, state);
}
let whole_con = Constraint::Eq(

View File

@ -250,7 +250,7 @@ fn constrain_pattern(
RecordField::Required(pat_type)
}
DestructType::Optional(_var) => {
DestructType::Optional(_expr_var, _loc_expr) => {
todo!("Add a constraint for the default value.");
// RecordField::Optional(pat_type)

View File

@ -864,6 +864,7 @@ pub enum Reason {
},
RecordUpdateValue(Lowercase),
RecordUpdateKeys(Symbol, SendMap<Lowercase, Region>),
RecordDefaultField(Lowercase),
}
#[derive(PartialEq, Debug, Clone)]
@ -893,6 +894,7 @@ pub enum Category {
Record,
Accessor(Lowercase),
Access(Lowercase),
DefaultValue(Lowercase), // for setting optional fields
}
#[derive(Debug, Clone, PartialEq, Eq)]