mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
trim function arguments (scope and env)
This commit is contained in:
parent
7c87320cc1
commit
12baa2bd13
4 changed files with 38 additions and 150 deletions
14
src/infer.rs
14
src/infer.rs
|
@ -3,7 +3,6 @@ use crate::collections::ImMap;
|
||||||
use crate::solve::solve;
|
use crate::solve::solve;
|
||||||
use crate::subs::{Content, Subs, Variable};
|
use crate::subs::{Content, Subs, Variable};
|
||||||
use crate::types::Constraint;
|
use crate::types::Constraint;
|
||||||
use crate::uniqueness::Env;
|
|
||||||
|
|
||||||
pub fn infer_expr(subs: &mut Subs, constraint: &Constraint, expr_var: Variable) -> Content {
|
pub fn infer_expr(subs: &mut Subs, constraint: &Constraint, expr_var: Variable) -> Content {
|
||||||
let env: ImMap<Symbol, Variable> = ImMap::default();
|
let env: ImMap<Symbol, Variable> = ImMap::default();
|
||||||
|
@ -12,16 +11,3 @@ pub fn infer_expr(subs: &mut Subs, constraint: &Constraint, expr_var: Variable)
|
||||||
|
|
||||||
subs.get(expr_var).content
|
subs.get(expr_var).content
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn infer_uniq(
|
|
||||||
subs: &mut Subs,
|
|
||||||
environment: &Env,
|
|
||||||
constraint: &Constraint,
|
|
||||||
expr_var: Variable,
|
|
||||||
) -> Content {
|
|
||||||
let env: ImMap<Symbol, Variable> = environment.bound_names.clone();
|
|
||||||
|
|
||||||
solve(&env, subs, constraint);
|
|
||||||
|
|
||||||
subs.get(expr_var).content
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
use crate::can;
|
|
||||||
use crate::can::expr::Expr::{self};
|
use crate::can::expr::Expr::{self};
|
||||||
use crate::can::pattern::Pattern;
|
use crate::can::pattern::Pattern;
|
||||||
use crate::can::procedure::{Procedure, References};
|
use crate::can::procedure::{Procedure, References};
|
||||||
|
@ -29,35 +28,17 @@ pub struct Env {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn canonicalize_declaration(
|
pub fn canonicalize_declaration(
|
||||||
var_store: &VarStore,
|
var_store: &VarStore,
|
||||||
home: Box<str>,
|
|
||||||
name: Box<str>,
|
|
||||||
region: Region,
|
region: Region,
|
||||||
loc_expr: Located<Expr>,
|
loc_expr: Located<Expr>,
|
||||||
declared_idents: &ImMap<Ident, (Symbol, Region)>,
|
_declared_idents: &ImMap<Ident, (Symbol, Region)>,
|
||||||
_declared_variants: &ImMap<Symbol, Located<Box<str>>>,
|
_declared_variants: &ImMap<Symbol, Located<Box<str>>>,
|
||||||
expected: Expected<Type>,
|
expected: Expected<Type>,
|
||||||
) -> (Output, Env) {
|
) -> (Output) {
|
||||||
// If we're canonicalizing the declaration `foo = ...` inside the `Main` module,
|
|
||||||
// scope_prefix will be "Main.foo$" and its first closure will be named "Main.foo$0"
|
|
||||||
let scope_prefix = format!("{}.{}$", home, name).into();
|
|
||||||
let mut scope = can::scope::Scope::new(scope_prefix, declared_idents.clone());
|
|
||||||
let mut env: Env = Env {
|
|
||||||
bound_names: ImMap::default(),
|
|
||||||
procedures: ImMap::default(),
|
|
||||||
};
|
|
||||||
let rigids = ImMap::default();
|
let rigids = ImMap::default();
|
||||||
|
|
||||||
let output = canonicalize_expr(
|
let output = canonicalize_expr(&rigids, var_store, region, &loc_expr.value, expected);
|
||||||
&rigids,
|
|
||||||
&mut env,
|
|
||||||
var_store,
|
|
||||||
&mut scope,
|
|
||||||
region,
|
|
||||||
&loc_expr.value,
|
|
||||||
expected,
|
|
||||||
);
|
|
||||||
|
|
||||||
(output, env)
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PatternState {
|
pub struct PatternState {
|
||||||
|
@ -145,9 +126,8 @@ type Rigids = ImMap<Box<str>, Type>;
|
||||||
|
|
||||||
pub fn canonicalize_expr(
|
pub fn canonicalize_expr(
|
||||||
rigids: &Rigids,
|
rigids: &Rigids,
|
||||||
env: &mut Env,
|
|
||||||
var_store: &VarStore,
|
var_store: &VarStore,
|
||||||
scope: &mut can::scope::Scope,
|
|
||||||
region: Region,
|
region: Region,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
expected: Expected<Type>,
|
expected: Expected<Type>,
|
||||||
|
@ -198,9 +178,7 @@ pub fn canonicalize_expr(
|
||||||
);
|
);
|
||||||
let elem_out = canonicalize_expr(
|
let elem_out = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
loc_elem.region,
|
loc_elem.region,
|
||||||
&loc_elem.value,
|
&loc_elem.value,
|
||||||
elem_expected,
|
elem_expected,
|
||||||
|
@ -227,12 +205,13 @@ pub fn canonicalize_expr(
|
||||||
// constraing expected ~ the type of this symbol in the environment
|
// constraing expected ~ the type of this symbol in the environment
|
||||||
Output::new(Lookup(symbol.clone(), expected, region))
|
Output::new(Lookup(symbol.clone(), expected, region))
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
FunctionPointer(_variable, symbol) => match env.bound_names.get(symbol) {
|
FunctionPointer(_variable, symbol) => match env.bound_names.get(symbol) {
|
||||||
// constraing expected ~ the type of this symbol in the environment
|
// constraing expected ~ the type of this symbol in the environment
|
||||||
None => panic!("FunctionPointer: no variable for {:?}", symbol),
|
None => panic!("FunctionPointer: no variable for {:?}", symbol),
|
||||||
Some(var) => Output::new(Eq(Variable(*var), expected, Region::zero())),
|
Some(var) => Output::new(Eq(Variable(*var), expected, Region::zero())),
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
Closure(_symbol, _recursion, args, body) => {
|
Closure(_symbol, _recursion, args, body) => {
|
||||||
// first, generate constraints for the arguments
|
// first, generate constraints for the arguments
|
||||||
let mut arg_types = Vec::new();
|
let mut arg_types = Vec::new();
|
||||||
|
@ -265,9 +244,7 @@ pub fn canonicalize_expr(
|
||||||
|
|
||||||
let mut output = canonicalize_expr(
|
let mut output = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
&body.value,
|
&body.value,
|
||||||
Expected::NoExpectation(ret_type.clone()),
|
Expected::NoExpectation(ret_type.clone()),
|
||||||
|
@ -305,16 +282,8 @@ pub fn canonicalize_expr(
|
||||||
let mut vars = Vec::with_capacity(2 + loc_args.len());
|
let mut vars = Vec::with_capacity(2 + loc_args.len());
|
||||||
|
|
||||||
// Canonicalize the function expression and its arguments
|
// Canonicalize the function expression and its arguments
|
||||||
let fn_con = canonicalize_expr(
|
let fn_con =
|
||||||
rigids,
|
canonicalize_expr(rigids, var_store, fn_region, &fn_expr, fn_expected).constraint;
|
||||||
env,
|
|
||||||
var_store,
|
|
||||||
scope,
|
|
||||||
fn_region,
|
|
||||||
&fn_expr,
|
|
||||||
fn_expected,
|
|
||||||
)
|
|
||||||
.constraint;
|
|
||||||
|
|
||||||
// TODO look up the name and use NamedFnArg if possible.
|
// TODO look up the name and use NamedFnArg if possible.
|
||||||
let fn_reason = Reason::AnonymousFnCall {
|
let fn_reason = Reason::AnonymousFnCall {
|
||||||
|
@ -336,9 +305,7 @@ pub fn canonicalize_expr(
|
||||||
let expected_arg = Expected::ForReason(reason, arg_type.clone(), region);
|
let expected_arg = Expected::ForReason(reason, arg_type.clone(), region);
|
||||||
let arg_con = canonicalize_expr(
|
let arg_con = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
loc_arg.region,
|
loc_arg.region,
|
||||||
&loc_arg.value,
|
&loc_arg.value,
|
||||||
expected_arg,
|
expected_arg,
|
||||||
|
@ -370,15 +337,7 @@ pub fn canonicalize_expr(
|
||||||
Defs(_, defs, loc_ret) => {
|
Defs(_, defs, loc_ret) => {
|
||||||
// The body expression gets a new scope for canonicalization,
|
// The body expression gets a new scope for canonicalization,
|
||||||
// so clone it.
|
// so clone it.
|
||||||
Output::new(can_defs(
|
Output::new(can_defs(rigids, var_store, defs, expected, loc_ret))
|
||||||
rigids,
|
|
||||||
env,
|
|
||||||
var_store,
|
|
||||||
&mut scope.clone(),
|
|
||||||
defs,
|
|
||||||
expected,
|
|
||||||
loc_ret,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
// Case( Variable, Box<Located<Expr>>, Vec<(Located<Pattern>, Located<Expr>)>,
|
// Case( Variable, Box<Located<Expr>>, Vec<(Located<Pattern>, Located<Expr>)>,
|
||||||
Case(_variable, loc_cond, branches) => {
|
Case(_variable, loc_cond, branches) => {
|
||||||
|
@ -386,9 +345,7 @@ pub fn canonicalize_expr(
|
||||||
let cond_type = Variable(cond_var);
|
let cond_type = Variable(cond_var);
|
||||||
let mut output = canonicalize_expr(
|
let mut output = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
&loc_cond.value,
|
&loc_cond.value,
|
||||||
Expected::NoExpectation(cond_type.clone()),
|
Expected::NoExpectation(cond_type.clone()),
|
||||||
|
@ -401,10 +358,8 @@ pub fn canonicalize_expr(
|
||||||
Expected::FromAnnotation(name, arity, _, typ) => {
|
Expected::FromAnnotation(name, arity, _, typ) => {
|
||||||
for (index, (loc_pattern, loc_expr)) in branches.into_iter().enumerate() {
|
for (index, (loc_pattern, loc_expr)) in branches.into_iter().enumerate() {
|
||||||
let branch_con = canonicalize_case_branch(
|
let branch_con = canonicalize_case_branch(
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
rigids,
|
rigids,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
loc_pattern,
|
loc_pattern,
|
||||||
loc_expr,
|
loc_expr,
|
||||||
|
@ -438,10 +393,8 @@ pub fn canonicalize_expr(
|
||||||
|
|
||||||
for (index, (loc_pattern, loc_expr)) in branches.into_iter().enumerate() {
|
for (index, (loc_pattern, loc_expr)) in branches.into_iter().enumerate() {
|
||||||
let branch_con = canonicalize_case_branch(
|
let branch_con = canonicalize_case_branch(
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
rigids,
|
rigids,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
loc_pattern,
|
loc_pattern,
|
||||||
loc_expr,
|
loc_expr,
|
||||||
|
@ -489,10 +442,8 @@ pub fn canonicalize_expr(
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn canonicalize_case_branch(
|
fn canonicalize_case_branch(
|
||||||
env: &mut Env,
|
|
||||||
var_store: &VarStore,
|
var_store: &VarStore,
|
||||||
rigids: &Rigids,
|
rigids: &Rigids,
|
||||||
scope: &mut can::scope::Scope,
|
|
||||||
region: Region,
|
region: Region,
|
||||||
loc_pattern: &Located<Pattern>,
|
loc_pattern: &Located<Pattern>,
|
||||||
loc_expr: &Located<Expr>,
|
loc_expr: &Located<Expr>,
|
||||||
|
@ -500,20 +451,8 @@ fn canonicalize_case_branch(
|
||||||
expr_expected: Expected<Type>,
|
expr_expected: Expected<Type>,
|
||||||
_output: &mut Output,
|
_output: &mut Output,
|
||||||
) -> (Constraint) {
|
) -> (Constraint) {
|
||||||
// Each case branch gets a new scope for canonicalization.
|
let branch_output =
|
||||||
// Shadow `scope` to make sure we don't accidentally use the original one for the
|
canonicalize_expr(rigids, var_store, region, &loc_expr.value, expr_expected);
|
||||||
// rest of this block.
|
|
||||||
let mut scope = scope.clone();
|
|
||||||
|
|
||||||
let branch_output = canonicalize_expr(
|
|
||||||
rigids,
|
|
||||||
env,
|
|
||||||
var_store,
|
|
||||||
&mut scope,
|
|
||||||
region,
|
|
||||||
&loc_expr.value,
|
|
||||||
expr_expected,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut state = PatternState {
|
let mut state = PatternState {
|
||||||
headers: ImMap::default(),
|
headers: ImMap::default(),
|
||||||
|
@ -572,9 +511,9 @@ fn add_pattern_to_lookup_types(
|
||||||
|
|
||||||
fn can_defs(
|
fn can_defs(
|
||||||
rigids: &Rigids,
|
rigids: &Rigids,
|
||||||
env: &mut Env,
|
|
||||||
var_store: &VarStore,
|
var_store: &VarStore,
|
||||||
scope: &mut can::scope::Scope,
|
|
||||||
defs: &Vec<(Located<Pattern>, Located<Expr>)>,
|
defs: &Vec<(Located<Pattern>, Located<Expr>)>,
|
||||||
expected: Expected<Type>,
|
expected: Expected<Type>,
|
||||||
body: &Located<Expr>,
|
body: &Located<Expr>,
|
||||||
|
@ -601,9 +540,7 @@ fn can_defs(
|
||||||
let expr_type = Type::Variable(expr_var);
|
let expr_type = Type::Variable(expr_var);
|
||||||
let expr_constraint = canonicalize_expr(
|
let expr_constraint = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
expr.region,
|
expr.region,
|
||||||
&expr.value,
|
&expr.value,
|
||||||
Expected::NoExpectation(expr_type.clone()),
|
Expected::NoExpectation(expr_type.clone()),
|
||||||
|
@ -630,16 +567,8 @@ fn can_defs(
|
||||||
|
|
||||||
// The def as a whole is a tail call iff its return expression is a tail call.
|
// The def as a whole is a tail call iff its return expression is a tail call.
|
||||||
// Use its output as a starting point because its tail_call already has the right answer!
|
// Use its output as a starting point because its tail_call already has the right answer!
|
||||||
let ret_con = canonicalize_expr(
|
let ret_con =
|
||||||
rigids,
|
canonicalize_expr(rigids, var_store, body.region, &body.value, expected).constraint;
|
||||||
env,
|
|
||||||
var_store,
|
|
||||||
scope,
|
|
||||||
body.region,
|
|
||||||
&body.value,
|
|
||||||
expected,
|
|
||||||
)
|
|
||||||
.constraint;
|
|
||||||
|
|
||||||
Let(Box::new(LetConstraint {
|
Let(Box::new(LetConstraint {
|
||||||
rigid_vars: rigid_info.vars,
|
rigid_vars: rigid_info.vars,
|
||||||
|
@ -683,9 +612,7 @@ fn can_defs(
|
||||||
// Canonicalize the function expression and its arguments
|
// Canonicalize the function expression and its arguments
|
||||||
let (fn_expr, mut output) = canonicalize_expr(
|
let (fn_expr, mut output) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
loc_fn.region,
|
loc_fn.region,
|
||||||
&loc_fn.value,
|
&loc_fn.value,
|
||||||
fn_expected,
|
fn_expected,
|
||||||
|
@ -718,9 +645,7 @@ fn can_defs(
|
||||||
let expected_arg = ForReason(reason, arg_type.clone(), region);
|
let expected_arg = ForReason(reason, arg_type.clone(), region);
|
||||||
let (arg_expr, arg_out) = canonicalize_expr(
|
let (arg_expr, arg_out) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
loc_arg.region,
|
loc_arg.region,
|
||||||
&loc_arg.value,
|
&loc_arg.value,
|
||||||
expected_arg,
|
expected_arg,
|
||||||
|
@ -790,7 +715,7 @@ fn can_defs(
|
||||||
|
|
||||||
let mut output = Output::new(Lookup(symbol, expected, region));
|
let mut output = Output::new(Lookup(symbol, expected, region));
|
||||||
let ident = Ident::new(module_parts, name);
|
let ident = Ident::new(module_parts, name);
|
||||||
let can_expr = match resolve_ident(&env, &scope, ident, &mut output.references) {
|
let can_expr = match resolve_ident(& & ident, &mut output.references) {
|
||||||
Ok(symbol) => Var(var_store.fresh(), symbol),
|
Ok(symbol) => Var(var_store.fresh(), symbol),
|
||||||
Err(ident) => {
|
Err(ident) => {
|
||||||
let loc_ident = Located {
|
let loc_ident = Located {
|
||||||
|
@ -810,7 +735,7 @@ fn can_defs(
|
||||||
ast::Expr::Defs(defs, loc_ret) => {
|
ast::Expr::Defs(defs, loc_ret) => {
|
||||||
// The body expression gets a new scope for canonicalization,
|
// The body expression gets a new scope for canonicalization,
|
||||||
// so clone it.
|
// so clone it.
|
||||||
can_defs(rigids, env, var_store, scope.clone(), defs, expected, loc_ret)
|
can_defs(rigids, var_store, scope.clone(), defs, expected, loc_ret)
|
||||||
}
|
}
|
||||||
ast::Expr::Closure(loc_arg_patterns, loc_body_expr) => {
|
ast::Expr::Closure(loc_arg_patterns, loc_body_expr) => {
|
||||||
// The globally unique symbol that will refer to this closure once it gets converted
|
// The globally unique symbol that will refer to this closure once it gets converted
|
||||||
|
@ -845,7 +770,7 @@ fn can_defs(
|
||||||
|
|
||||||
for loc_pattern in loc_arg_patterns.into_iter() {
|
for loc_pattern in loc_arg_patterns.into_iter() {
|
||||||
// Exclude the current ident from shadowable_idents; you can't shadow yourself!
|
// Exclude the current ident from shadowable_idents; you can't shadow yourself!
|
||||||
// (However, still include it in scope, because you *can* recursively refer to yourself.)
|
// (However, still include it in because you *can* recursively refer to yourself.)
|
||||||
let mut shadowable_idents = scope.idents.clone();
|
let mut shadowable_idents = scope.idents.clone();
|
||||||
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
||||||
|
|
||||||
|
@ -856,10 +781,8 @@ fn can_defs(
|
||||||
pattern_types.push(pattern_type);
|
pattern_types.push(pattern_type);
|
||||||
|
|
||||||
let can_arg = canonicalize_pattern(
|
let can_arg = canonicalize_pattern(
|
||||||
env,
|
|
||||||
&mut state,
|
&mut state,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
FunctionArg,
|
FunctionArg,
|
||||||
&loc_pattern.value,
|
&loc_pattern.value,
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
|
@ -882,9 +805,7 @@ fn can_defs(
|
||||||
let body_type = NoExpectation(ret_type);
|
let body_type = NoExpectation(ret_type);
|
||||||
let (loc_body_expr, mut output) = canonicalize_expr(
|
let (loc_body_expr, mut output) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
loc_body_expr.region,
|
loc_body_expr.region,
|
||||||
&loc_body_expr.value,
|
&loc_body_expr.value,
|
||||||
body_type,
|
body_type,
|
||||||
|
@ -957,9 +878,7 @@ fn can_defs(
|
||||||
let cond_type = Variable(cond_var);
|
let cond_type = Variable(cond_var);
|
||||||
let (can_cond, mut output) = canonicalize_expr(
|
let (can_cond, mut output) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
&loc_cond.value,
|
&loc_cond.value,
|
||||||
NoExpectation(cond_type.clone()),
|
NoExpectation(cond_type.clone()),
|
||||||
|
@ -977,10 +896,8 @@ fn can_defs(
|
||||||
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
||||||
let (can_pattern, loc_can_expr, branch_con, branch_references) =
|
let (can_pattern, loc_can_expr, branch_con, branch_references) =
|
||||||
canonicalize_case_branch(
|
canonicalize_case_branch(
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
rigids,
|
rigids,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
loc_pattern,
|
loc_pattern,
|
||||||
loc_expr,
|
loc_expr,
|
||||||
|
@ -1024,10 +941,8 @@ fn can_defs(
|
||||||
|
|
||||||
let (can_pattern, loc_can_expr, branch_con, branch_references) =
|
let (can_pattern, loc_can_expr, branch_con, branch_references) =
|
||||||
canonicalize_case_branch(
|
canonicalize_case_branch(
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
rigids,
|
rigids,
|
||||||
scope,
|
|
||||||
region,
|
region,
|
||||||
loc_pattern,
|
loc_pattern,
|
||||||
loc_expr,
|
loc_expr,
|
||||||
|
@ -1102,17 +1017,17 @@ fn can_defs(
|
||||||
}
|
}
|
||||||
ast::Expr::BinaryInt(string) => {
|
ast::Expr::BinaryInt(string) => {
|
||||||
let (constraint, answer) =
|
let (constraint, answer) =
|
||||||
int_expr_from_result(var_store, finish_parsing_bin(string), env, expected, region);
|
int_expr_from_result(var_store, finish_parsing_bin(string), expected, region);
|
||||||
(answer, Output::new(constraint))
|
(answer, Output::new(constraint))
|
||||||
}
|
}
|
||||||
ast::Expr::HexInt(string) => {
|
ast::Expr::HexInt(string) => {
|
||||||
let (constraint, answer) =
|
let (constraint, answer) =
|
||||||
int_expr_from_result(var_store, finish_parsing_hex(string), env, expected, region);
|
int_expr_from_result(var_store, finish_parsing_hex(string), expected, region);
|
||||||
(answer, Output::new(constraint))
|
(answer, Output::new(constraint))
|
||||||
}
|
}
|
||||||
ast::Expr::OctalInt(string) => {
|
ast::Expr::OctalInt(string) => {
|
||||||
let (constraint, answer) =
|
let (constraint, answer) =
|
||||||
int_expr_from_result(var_store, finish_parsing_oct(string), env, expected, region);
|
int_expr_from_result(var_store, finish_parsing_oct(string), expected, region);
|
||||||
(answer, Output::new(constraint))
|
(answer, Output::new(constraint))
|
||||||
}
|
}
|
||||||
// Below this point, we shouln't see any of these nodes anymore because
|
// Below this point, we shouln't see any of these nodes anymore because
|
||||||
|
@ -1163,7 +1078,7 @@ fn can_defs(
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn canonicalize_case_branch<'a>(
|
fn canonicalize_case_branch<'a>(
|
||||||
env: &mut Env,
|
|
||||||
var_store: &VarStore,
|
var_store: &VarStore,
|
||||||
rigids: &Rigids,
|
rigids: &Rigids,
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
|
@ -1181,7 +1096,7 @@ fn canonicalize_case_branch<'a>(
|
||||||
let mut scope = scope.clone();
|
let mut scope = scope.clone();
|
||||||
|
|
||||||
// Exclude the current ident from shadowable_idents; you can't shadow yourself!
|
// Exclude the current ident from shadowable_idents; you can't shadow yourself!
|
||||||
// (However, still include it in scope, because you *can* recursively refer to yourself.)
|
// (However, still include it in because you *can* recursively refer to yourself.)
|
||||||
let mut shadowable_idents = scope.idents.clone();
|
let mut shadowable_idents = scope.idents.clone();
|
||||||
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
||||||
|
|
||||||
|
@ -1195,9 +1110,8 @@ fn canonicalize_case_branch<'a>(
|
||||||
|
|
||||||
let (can_expr, branch_output) = canonicalize_expr(
|
let (can_expr, branch_output) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
region,
|
region,
|
||||||
&loc_expr.value,
|
&loc_expr.value,
|
||||||
expr_expected,
|
expr_expected,
|
||||||
|
@ -1234,10 +1148,9 @@ fn canonicalize_case_branch<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let loc_can_pattern = canonicalize_pattern(
|
let loc_can_pattern = canonicalize_pattern(
|
||||||
env,
|
|
||||||
&mut state,
|
&mut state,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
CaseBranch,
|
CaseBranch,
|
||||||
&loc_pattern.value,
|
&loc_pattern.value,
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
|
@ -1456,7 +1369,7 @@ where
|
||||||
let mut answer = Vec::new();
|
let mut answer = Vec::new();
|
||||||
|
|
||||||
for loc_pattern in loc_patterns {
|
for loc_pattern in loc_patterns {
|
||||||
add_idents_from_pattern(&loc_pattern.region, &loc_pattern.value, scope, &mut answer);
|
add_idents_from_pattern(&loc_pattern.region, &loc_pattern.value, &mut answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
answer
|
answer
|
||||||
|
@ -1486,7 +1399,7 @@ fn add_idents_from_pattern<'a>(
|
||||||
// &None => (),
|
// &None => (),
|
||||||
// &Some(ref loc_args) => {
|
// &Some(ref loc_args) => {
|
||||||
// for loc_arg in loc_args.iter() {
|
// for loc_arg in loc_args.iter() {
|
||||||
// add_idents_from_pattern(loc_arg, scope, answer);
|
// add_idents_from_pattern(loc_arg, answer);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
|
@ -1500,7 +1413,7 @@ fn add_idents_from_pattern<'a>(
|
||||||
}
|
}
|
||||||
SpaceBefore(pattern, _) | SpaceAfter(pattern, _) => {
|
SpaceBefore(pattern, _) | SpaceAfter(pattern, _) => {
|
||||||
// Ignore the newline/comment info; it doesn't matter in canonicalization.
|
// Ignore the newline/comment info; it doesn't matter in canonicalization.
|
||||||
add_idents_from_pattern(region, pattern, scope, answer)
|
add_idents_from_pattern(region, pattern, answer)
|
||||||
}
|
}
|
||||||
Variant(_, _)
|
Variant(_, _)
|
||||||
| IntLiteral(_)
|
| IntLiteral(_)
|
||||||
|
@ -1677,7 +1590,7 @@ fn pattern_from_def<'a>(def: &'a Def<'a>) -> Option<&'a Located<ast::Pattern<'a>
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn can_defs<'a>(
|
fn can_defs<'a>(
|
||||||
rigids: &Rigids,
|
rigids: &Rigids,
|
||||||
env: &mut Env,
|
|
||||||
var_store: &VarStore,
|
var_store: &VarStore,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
defs: &'a bumpalo::collections::Vec<'a, &'a Located<Def<'a>>>,
|
defs: &'a bumpalo::collections::Vec<'a, &'a Located<Def<'a>>>,
|
||||||
|
@ -1692,7 +1605,7 @@ fn can_defs<'a>(
|
||||||
// TODO can we get rid of this clone? It's recursively cloning expressions...
|
// TODO can we get rid of this clone? It's recursively cloning expressions...
|
||||||
defs.iter()
|
defs.iter()
|
||||||
.flat_map(|loc_def| pattern_from_def(&loc_def.value)),
|
.flat_map(|loc_def| pattern_from_def(&loc_def.value)),
|
||||||
&scope,
|
&
|
||||||
);
|
);
|
||||||
|
|
||||||
scope.idents = union_pairs(scope.idents, defined_idents.iter());
|
scope.idents = union_pairs(scope.idents, defined_idents.iter());
|
||||||
|
@ -1747,9 +1660,7 @@ fn can_defs<'a>(
|
||||||
Def::Body(ref loc_pattern, loc_expr) => {
|
Def::Body(ref loc_pattern, loc_expr) => {
|
||||||
let (loc_can_expr, output) = canonicalize_expr(
|
let (loc_can_expr, output) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
&loc_expr.value,
|
&loc_expr.value,
|
||||||
NoExpectation(expr_type.clone()),
|
NoExpectation(expr_type.clone()),
|
||||||
|
@ -1771,7 +1682,7 @@ fn can_defs<'a>(
|
||||||
// standalone annotation), so we need to canonicalize the pattern and expr.
|
// standalone annotation), so we need to canonicalize the pattern and expr.
|
||||||
if let Some(loc_pattern) = opt_loc_pattern {
|
if let Some(loc_pattern) = opt_loc_pattern {
|
||||||
// Exclude the current ident from shadowable_idents; you can't shadow yourself!
|
// Exclude the current ident from shadowable_idents; you can't shadow yourself!
|
||||||
// (However, still include it in scope, because you *can* recursively refer to yourself.)
|
// (However, still include it in because you *can* recursively refer to yourself.)
|
||||||
let mut shadowable_idents = scope.idents.clone();
|
let mut shadowable_idents = scope.idents.clone();
|
||||||
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
remove_idents(&loc_pattern.value, &mut shadowable_idents);
|
||||||
|
|
||||||
|
@ -1786,10 +1697,8 @@ fn can_defs<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let loc_can_pattern = canonicalize_pattern(
|
let loc_can_pattern = canonicalize_pattern(
|
||||||
env,
|
|
||||||
&mut state,
|
&mut state,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
Assignment,
|
Assignment,
|
||||||
&loc_pattern.value,
|
&loc_pattern.value,
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
|
@ -1803,7 +1712,7 @@ fn can_defs<'a>(
|
||||||
// it should result in this expression's type. After all, this
|
// it should result in this expression's type. After all, this
|
||||||
// is the type to which this symbol is defined!
|
// is the type to which this symbol is defined!
|
||||||
add_pattern_to_lookup_types(
|
add_pattern_to_lookup_types(
|
||||||
&scope,
|
&
|
||||||
// TODO can we we avoid this clone?
|
// TODO can we we avoid this clone?
|
||||||
loc_pattern.clone(),
|
loc_pattern.clone(),
|
||||||
&mut flex_info.def_types,
|
&mut flex_info.def_types,
|
||||||
|
@ -1923,9 +1832,8 @@ fn can_defs<'a>(
|
||||||
// Use its output as a starting point because its tail_call already has the right answer!
|
// Use its output as a starting point because its tail_call already has the right answer!
|
||||||
let (ret_expr, mut output) = canonicalize_expr(
|
let (ret_expr, mut output) = canonicalize_expr(
|
||||||
rigids,
|
rigids,
|
||||||
env,
|
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
|
||||||
loc_ret.region,
|
loc_ret.region,
|
||||||
&loc_ret.value,
|
&loc_ret.value,
|
||||||
expected,
|
expected,
|
||||||
|
|
|
@ -54,7 +54,6 @@ pub fn uniq_expr(
|
||||||
Vec<Problem>,
|
Vec<Problem>,
|
||||||
VarStore,
|
VarStore,
|
||||||
Variable,
|
Variable,
|
||||||
roc::uniqueness::Env,
|
|
||||||
VarStore,
|
VarStore,
|
||||||
Variable,
|
Variable,
|
||||||
) {
|
) {
|
||||||
|
@ -80,7 +79,6 @@ pub fn uniq_expr_with(
|
||||||
Vec<Problem>,
|
Vec<Problem>,
|
||||||
VarStore,
|
VarStore,
|
||||||
Variable,
|
Variable,
|
||||||
roc::uniqueness::Env,
|
|
||||||
VarStore,
|
VarStore,
|
||||||
Variable,
|
Variable,
|
||||||
) {
|
) {
|
||||||
|
@ -112,10 +110,8 @@ pub fn uniq_expr_with(
|
||||||
|
|
||||||
let variable2 = var_store2.fresh();
|
let variable2 = var_store2.fresh();
|
||||||
let expected2 = Expected::NoExpectation(Type::Variable(variable2));
|
let expected2 = Expected::NoExpectation(Type::Variable(variable2));
|
||||||
let (output2, env) = roc::uniqueness::canonicalize_declaration(
|
let output2 = roc::uniqueness::canonicalize_declaration(
|
||||||
&var_store2,
|
&var_store2,
|
||||||
home.into(),
|
|
||||||
name.into(),
|
|
||||||
Region::zero(),
|
Region::zero(),
|
||||||
loc_expr,
|
loc_expr,
|
||||||
declared_idents,
|
declared_idents,
|
||||||
|
@ -126,7 +122,7 @@ pub fn uniq_expr_with(
|
||||||
dbg!(output.constraint.clone());
|
dbg!(output.constraint.clone());
|
||||||
dbg!(output2.constraint.clone());
|
dbg!(output2.constraint.clone());
|
||||||
(
|
(
|
||||||
output2, output, problems, var_store1, variable, env, var_store2, variable2,
|
output2, output, problems, var_store1, variable, var_store2, variable2,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,21 +12,19 @@ mod helpers;
|
||||||
mod test_infer {
|
mod test_infer {
|
||||||
use crate::helpers::uniq_expr;
|
use crate::helpers::uniq_expr;
|
||||||
use roc::infer::infer_expr;
|
use roc::infer::infer_expr;
|
||||||
use roc::infer::infer_uniq;
|
|
||||||
use roc::pretty_print_types::{content_to_string, name_all_type_vars};
|
use roc::pretty_print_types::{content_to_string, name_all_type_vars};
|
||||||
use roc::subs::Subs;
|
use roc::subs::Subs;
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
|
|
||||||
fn infer_eq(src: &str, expected: &str) {
|
fn infer_eq(src: &str, expected: &str) {
|
||||||
let (output2, output1, _, var_store1, variable1, env, var_store2, variable2) =
|
let (output2, output1, _, var_store1, variable1, var_store2, variable2) = uniq_expr(src);
|
||||||
uniq_expr(src);
|
|
||||||
|
|
||||||
let mut subs1 = Subs::new(var_store1.into());
|
let mut subs1 = Subs::new(var_store1.into());
|
||||||
let mut subs2 = Subs::new(var_store2.into());
|
let mut subs2 = Subs::new(var_store2.into());
|
||||||
|
|
||||||
let content1 = infer_expr(&mut subs1, &output1.constraint, variable1);
|
let content1 = infer_expr(&mut subs1, &output1.constraint, variable1);
|
||||||
let content2 = infer_uniq(&mut subs2, &env, &output2.constraint, variable2);
|
let content2 = infer_expr(&mut subs2, &output2.constraint, variable2);
|
||||||
|
|
||||||
name_all_type_vars(variable1, &mut subs1);
|
name_all_type_vars(variable1, &mut subs1);
|
||||||
name_all_type_vars(variable2, &mut subs2);
|
name_all_type_vars(variable2, &mut subs2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue