Constrain optional fields

This commit is contained in:
Richard Feldman 2020-07-18 14:51:18 -04:00
parent 872f4b3541
commit 28a2f9656e
5 changed files with 39 additions and 10 deletions

View file

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

View file

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

View file

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

View file

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

View file

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