Let constraint compiles

This commit is contained in:
Richard Feldman 2019-08-28 21:08:11 -04:00
parent 49cd2ede8a
commit 7308ef24c0
4 changed files with 40 additions and 54 deletions

View file

@ -1,6 +1,6 @@
use canonicalize::{Pattern, Procedure, Symbol};
use canonicalize::Expr::{self, *};
use collections::{ImMap, MutMap};
use collections::ImMap;
use region::{Located, Region};
use subs::{Variable, Subs};
use types::{Expected, Expected::*, LetConstraint, Reason};
@ -117,10 +117,10 @@ pub fn constrain_def(
loc_expr: Located<Expr>,
bound_vars: BoundTypeVars,
subs: &mut Subs,
body_constraint: Constraint
ret_constraint: Constraint
) -> Constraint {
let mut state = PatternState {
headers: MutMap::default(),
assignment_types: ImMap::default(),
vars: Vec::with_capacity(1),
reversed_constraints: Vec::with_capacity(1)
};
@ -131,16 +131,16 @@ pub fn constrain_def(
Let(Box::new(LetConstraint {
rigid_vars: Vec::new(),
flex_vars: args.vars,
header_constraint:
assignments_constraint:
Let(Box::new(LetConstraint {
rigid_vars: Vec::new(),
flex_vars: state.vars,
header: state.headers,
header_constraint: And(state.reversed_constraints),
body_constraint: constrain(bound_vars, subs, loc_expr, NoExpectation(args.ret_type))
assignment_types: state.assignment_types,
assignments_constraint: And(state.reversed_constraints),
ret_constraint: constrain(bound_vars, subs, loc_expr, NoExpectation(args.ret_type))
})),
body_constraint,
header: panic!("TODO Map.singleton name (A.At region tipe)"),
ret_constraint,
assignment_types: panic!("TODO Map.singleton name (A.At region tipe)"),
}))
}
@ -152,17 +152,17 @@ pub fn constrain_procedure(
expected: Expected<Type>
) -> Constraint {
let mut state = PatternState {
headers: MutMap::default(),
assignment_types: ImMap::default(),
vars: Vec::with_capacity(proc.args.len()),
reversed_constraints: Vec::with_capacity(1)
};
let args = constrain_args(proc.args.into_iter(), subs, &mut state);
let body_type = NoExpectation(args.ret_type);
let body_constraint = constrain(bound_vars, subs, proc.body, body_type);
let ret_constraint = constrain(bound_vars, subs, proc.body, body_type);
state.reversed_constraints.reverse();
let header_constraint = And(state.reversed_constraints);
let assignments_constraint = And(state.reversed_constraints);
// panic!("TODO occurs check");
@ -170,9 +170,9 @@ pub fn constrain_procedure(
Let(Box::new(LetConstraint {
rigid_vars: Vec::new(),
flex_vars: state.vars,
header: state.headers,
header_constraint,
body_constraint
assignment_types: state.assignment_types,
assignments_constraint,
ret_constraint
})),
Eq(args.typ, expected, region)
])
@ -215,13 +215,13 @@ where I: Iterator<Item = Located<Pattern>>
}
struct PatternState {
headers: MutMap<Symbol, Located<Type>>,
assignment_types: ImMap<Symbol, Located<Type>>,
vars: Vec<Variable>,
reversed_constraints: Vec<Constraint>
}
fn add_to_headers(region: Region, symbol: Symbol, expected: Expected<Type>, state: &mut PatternState) {
state.headers.insert(symbol, Located {region, value: expected.unwrap()});
fn add_to_assignment_types(region: Region, symbol: Symbol, expected: Expected<Type>, state: &mut PatternState) {
state.assignment_types.insert(symbol, Located {region, value: expected.unwrap()});
}
fn add_pattern(loc_pattern: Located<Pattern>, expected: Expected<Type>, state: &mut PatternState) {
@ -230,7 +230,7 @@ fn add_pattern(loc_pattern: Located<Pattern>, expected: Expected<Type>, state: &
let region = loc_pattern.region;
match loc_pattern.value {
Identifier(symbol) => add_to_headers(region, symbol, expected, state),
Identifier(symbol) => add_to_assignment_types(region, symbol, expected, state),
Underscore => (),
_ => panic!("TODO other patterns"),
}

View file

@ -9,11 +9,12 @@ use constrain::constrain;
pub fn infer_expr(subs: &mut Subs, loc_expr: Located<Expr>, procedures: MutMap<Symbol, Procedure>) -> Content {
let bound_vars = ImMap::default();
let env = ImMap::default();
let variable = subs.mk_flex_var();
let expected = NoExpectation(Variable(variable));
let constraint = constrain(bound_vars, subs, loc_expr, expected);
solve(subs, constraint);
solve(&env, subs, constraint);
subs.get(variable).content
}

View file

@ -15,10 +15,11 @@
use subs::{Subs, Variable, Descriptor, Content, FlatType};
use collections::ImMap;
use canonicalize::Symbol;
use types::Constraint::{self, *};
use types::Type::{self, *};
type Env = ImMap<String, Variable>;
type Env = ImMap<Symbol, Variable>;
pub fn solve(env: &Env, subs: &mut Subs, constraint: Constraint) {
println!("\nSolving:\n\n\t{:?}\n\n", constraint);
@ -37,22 +38,19 @@ pub fn solve(env: &Env, subs: &mut Subs, constraint: Constraint) {
},
Let(box_let_constraint) => {
let let_con = *box_let_constraint;
let no_rigid_vars = let_con.rigid_vars.is_empty();
match let_con.ret_constraint {
True if no_rigid_vars => {
True => {
// If the return expression is guaranteed to solve,
// and there are no rigid vars to worry about,
// solve the assignments themselves and move on.
solve(env, subs, let_con.assignments_constraint)
},
body_con => {
if no_rigid_vars && let_con.flex_vars.is_empty() {
ret_con => {
// Solve the assignments' constraints first.
solve(env, subs, let_con.assignments_constraint);
// Add a variable for each assignment to the env.
let new_env = env.clone();
let mut new_env = env.clone();
for (name, loc_type) in let_con.assignment_types {
let var = type_to_variable(subs, loc_type.value);
@ -62,23 +60,9 @@ pub fn solve(env: &Env, subs: &mut Subs, constraint: Constraint) {
// Now solve the body, using the new env which includes
// the assignments' name-to-variable mappings.
solve(&new_env, subs, let_con.ret_constraint);
solve(&new_env, subs, ret_con);
// TODO do an occurs check for each of the assignments!
} else {
let vars = let_con.rigid_vars;
vars.extend(let_con.flex_vars);
// Add a variable for each assignment to the env.
let new_env = env.clone();
for (name, loc_type) in let_con.assignment_types {
let var = type_to_variable(subs, loc_type.value);
new_env.insert(name, var);
}
}
}
}
},

View file

@ -2,6 +2,7 @@ use subs::Variable;
use region::Region;
use operator::Operator;
use region::Located;
use canonicalize::Symbol;
use collections::ImMap;
type ModuleName = String;
@ -55,7 +56,7 @@ pub enum Constraint {
pub struct LetConstraint {
pub rigid_vars: Vec<Variable>,
pub flex_vars: Vec<Variable>,
pub assignment_types: ImMap<String, Located<Type>>,
pub assignment_types: ImMap<Symbol, Located<Type>>,
pub assignments_constraint: Constraint,
pub ret_constraint: Constraint,
}