mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
Count default exprs as having used things
This commit is contained in:
parent
81a1111cae
commit
71f929aba2
3 changed files with 75 additions and 43 deletions
|
@ -148,7 +148,7 @@ pub fn canonicalize_defs<'a>(
|
||||||
// Any time we have an Annotation followed immediately by a Body,
|
// Any time we have an Annotation followed immediately by a Body,
|
||||||
// check to see if their patterns are equivalent. If they are,
|
// check to see if their patterns are equivalent. If they are,
|
||||||
// turn it into a TypedBody. Otherwise, give an error.
|
// turn it into a TypedBody. Otherwise, give an error.
|
||||||
let pending_def = match &loc_def.value {
|
let (new_output, pending_def) = match &loc_def.value {
|
||||||
Annotation(pattern, annotation) | Nested(Annotation(pattern, annotation)) => {
|
Annotation(pattern, annotation) | Nested(Annotation(pattern, annotation)) => {
|
||||||
match iter.peek() {
|
match iter.peek() {
|
||||||
Some(Located {
|
Some(Located {
|
||||||
|
@ -189,6 +189,8 @@ pub fn canonicalize_defs<'a>(
|
||||||
_ => to_pending_def(env, var_store, &loc_def.value, &mut scope, pattern_type),
|
_ => to_pending_def(env, var_store, &loc_def.value, &mut scope, pattern_type),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
output.union(new_output);
|
||||||
|
|
||||||
// Record the ast::Expr for later. We'll do another pass through these
|
// Record the ast::Expr for later. We'll do another pass through these
|
||||||
// once we have the entire scope assembled. If we were to canonicalize
|
// once we have the entire scope assembled. If we were to canonicalize
|
||||||
// the exprs right now, they wouldn't have symbols in scope from defs
|
// the exprs right now, they wouldn't have symbols in scope from defs
|
||||||
|
@ -212,8 +214,8 @@ pub fn canonicalize_defs<'a>(
|
||||||
|
|
||||||
let mut can_vars: Vec<Located<(Lowercase, Variable)>> =
|
let mut can_vars: Vec<Located<(Lowercase, Variable)>> =
|
||||||
Vec::with_capacity(vars.len());
|
Vec::with_capacity(vars.len());
|
||||||
|
|
||||||
let mut is_phantom = false;
|
let mut is_phantom = false;
|
||||||
|
|
||||||
for loc_lowercase in vars {
|
for loc_lowercase in vars {
|
||||||
if let Some(var) = can_ann
|
if let Some(var) = can_ann
|
||||||
.introduced_variables
|
.introduced_variables
|
||||||
|
@ -1288,13 +1290,13 @@ fn to_pending_def<'a>(
|
||||||
def: &'a ast::Def<'a>,
|
def: &'a ast::Def<'a>,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
pattern_type: PatternType,
|
pattern_type: PatternType,
|
||||||
) -> PendingDef<'a> {
|
) -> (Output, PendingDef<'a>) {
|
||||||
use roc_parse::ast::Def::*;
|
use roc_parse::ast::Def::*;
|
||||||
|
|
||||||
match def {
|
match def {
|
||||||
Annotation(loc_pattern, loc_ann) => {
|
Annotation(loc_pattern, loc_ann) => {
|
||||||
// This takes care of checking for shadowing and adding idents to scope.
|
// This takes care of checking for shadowing and adding idents to scope.
|
||||||
let loc_can_pattern = canonicalize_pattern(
|
let (output, loc_can_pattern) = canonicalize_pattern(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
scope,
|
||||||
|
@ -1303,11 +1305,14 @@ fn to_pending_def<'a>(
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
);
|
);
|
||||||
|
|
||||||
PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann)
|
(
|
||||||
|
output,
|
||||||
|
PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Body(loc_pattern, loc_expr) => {
|
Body(loc_pattern, loc_expr) => {
|
||||||
// This takes care of checking for shadowing and adding idents to scope.
|
// This takes care of checking for shadowing and adding idents to scope.
|
||||||
let loc_can_pattern = canonicalize_pattern(
|
let (output, loc_can_pattern) = canonicalize_pattern(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
scope,
|
||||||
|
@ -1316,7 +1321,10 @@ fn to_pending_def<'a>(
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
);
|
);
|
||||||
|
|
||||||
PendingDef::Body(loc_pattern, loc_can_pattern, loc_expr)
|
(
|
||||||
|
output,
|
||||||
|
PendingDef::Body(loc_pattern, loc_can_pattern, loc_expr),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
TypedBody(loc_pattern, loc_ann, loc_expr) => pending_typed_body(
|
TypedBody(loc_pattern, loc_ann, loc_expr) => pending_typed_body(
|
||||||
env,
|
env,
|
||||||
|
@ -1358,19 +1366,22 @@ fn to_pending_def<'a>(
|
||||||
region: loc_var.region,
|
region: loc_var.region,
|
||||||
});
|
});
|
||||||
|
|
||||||
return PendingDef::InvalidAlias;
|
return (Output::default(), PendingDef::InvalidAlias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingDef::Alias {
|
(
|
||||||
name: Located {
|
Output::default(),
|
||||||
region: name.region,
|
PendingDef::Alias {
|
||||||
value: symbol,
|
name: Located {
|
||||||
|
region: name.region,
|
||||||
|
value: symbol,
|
||||||
|
},
|
||||||
|
vars: can_rigids,
|
||||||
|
ann,
|
||||||
},
|
},
|
||||||
vars: can_rigids,
|
)
|
||||||
ann,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Err((original_region, loc_shadowed_symbol)) => {
|
Err((original_region, loc_shadowed_symbol)) => {
|
||||||
|
@ -1379,7 +1390,7 @@ fn to_pending_def<'a>(
|
||||||
shadow: loc_shadowed_symbol,
|
shadow: loc_shadowed_symbol,
|
||||||
});
|
});
|
||||||
|
|
||||||
PendingDef::InvalidAlias
|
(Output::default(), PendingDef::InvalidAlias)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1398,9 +1409,9 @@ fn pending_typed_body<'a>(
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
pattern_type: PatternType,
|
pattern_type: PatternType,
|
||||||
) -> PendingDef<'a> {
|
) -> (Output, PendingDef<'a>) {
|
||||||
// This takes care of checking for shadowing and adding idents to scope.
|
// This takes care of checking for shadowing and adding idents to scope.
|
||||||
let loc_can_pattern = canonicalize_pattern(
|
let (output, loc_can_pattern) = canonicalize_pattern(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
scope,
|
||||||
|
@ -1409,7 +1420,10 @@ fn pending_typed_body<'a>(
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
);
|
);
|
||||||
|
|
||||||
PendingDef::TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr)
|
(
|
||||||
|
output,
|
||||||
|
PendingDef::TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make aliases recursive
|
/// Make aliases recursive
|
||||||
|
|
|
@ -427,9 +427,10 @@ pub fn canonicalize_expr<'a>(
|
||||||
let original_scope = scope;
|
let original_scope = scope;
|
||||||
let mut scope = original_scope.clone();
|
let mut scope = original_scope.clone();
|
||||||
let mut can_args = Vec::with_capacity(loc_arg_patterns.len());
|
let mut can_args = Vec::with_capacity(loc_arg_patterns.len());
|
||||||
|
let mut output = Output::default();
|
||||||
|
|
||||||
for loc_pattern in loc_arg_patterns.into_iter() {
|
for loc_pattern in loc_arg_patterns.into_iter() {
|
||||||
let can_arg = canonicalize_pattern(
|
let (new_output, can_arg) = canonicalize_pattern(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
&mut scope,
|
||||||
|
@ -438,16 +439,21 @@ pub fn canonicalize_expr<'a>(
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
output.union(new_output);
|
||||||
|
|
||||||
can_args.push((var_store.fresh(), can_arg));
|
can_args.push((var_store.fresh(), can_arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (loc_body_expr, mut output) = canonicalize_expr(
|
let (loc_body_expr, new_output) = canonicalize_expr(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
&mut scope,
|
||||||
loc_body_expr.region,
|
loc_body_expr.region,
|
||||||
&loc_body_expr.value,
|
&loc_body_expr.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
output.union(new_output);
|
||||||
|
|
||||||
// Now that we've collected all the references, check to see if any of the args we defined
|
// Now that we've collected all the references, check to see if any of the args we defined
|
||||||
// went unreferenced. If any did, report them as unused arguments.
|
// went unreferenced. If any did, report them as unused arguments.
|
||||||
for (sub_symbol, region) in scope.symbols() {
|
for (sub_symbol, region) in scope.symbols() {
|
||||||
|
@ -713,14 +719,18 @@ fn canonicalize_when_branch<'a>(
|
||||||
|
|
||||||
// TODO report symbols not bound in all patterns
|
// TODO report symbols not bound in all patterns
|
||||||
for loc_pattern in &branch.patterns {
|
for loc_pattern in &branch.patterns {
|
||||||
patterns.push(canonicalize_pattern(
|
let (new_output, can_pattern) = canonicalize_pattern(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
&mut scope,
|
&mut scope,
|
||||||
WhenBranch,
|
WhenBranch,
|
||||||
&loc_pattern.value,
|
&loc_pattern.value,
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
));
|
);
|
||||||
|
|
||||||
|
output.union(new_output);
|
||||||
|
|
||||||
|
patterns.push(can_pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (value, mut branch_output) = canonicalize_expr(
|
let (value, mut branch_output) = canonicalize_expr(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
use crate::expr::{canonicalize_expr, Expr};
|
use crate::expr::{canonicalize_expr, Expr, Output};
|
||||||
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};
|
||||||
|
@ -100,10 +100,11 @@ pub fn canonicalize_pattern<'a>(
|
||||||
pattern_type: PatternType,
|
pattern_type: PatternType,
|
||||||
pattern: &ast::Pattern<'a>,
|
pattern: &ast::Pattern<'a>,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Located<Pattern> {
|
) -> (Output, Located<Pattern>) {
|
||||||
use roc_parse::ast::Pattern::*;
|
use roc_parse::ast::Pattern::*;
|
||||||
use PatternType::*;
|
use PatternType::*;
|
||||||
|
|
||||||
|
let mut output = Output::default();
|
||||||
let can_pattern = match pattern {
|
let can_pattern = match pattern {
|
||||||
Identifier(name) => match scope.introduce(
|
Identifier(name) => match scope.introduce(
|
||||||
(*name).into(),
|
(*name).into(),
|
||||||
|
@ -154,17 +155,18 @@ pub fn canonicalize_pattern<'a>(
|
||||||
|
|
||||||
let mut can_patterns = Vec::with_capacity(patterns.len());
|
let mut can_patterns = Vec::with_capacity(patterns.len());
|
||||||
for loc_pattern in *patterns {
|
for loc_pattern in *patterns {
|
||||||
can_patterns.push((
|
let (new_output, can_pattern) = canonicalize_pattern(
|
||||||
var_store.fresh(),
|
env,
|
||||||
canonicalize_pattern(
|
var_store,
|
||||||
env,
|
scope,
|
||||||
var_store,
|
pattern_type,
|
||||||
scope,
|
&loc_pattern.value,
|
||||||
pattern_type,
|
loc_pattern.region,
|
||||||
&loc_pattern.value,
|
);
|
||||||
loc_pattern.region,
|
|
||||||
),
|
output.union(new_output);
|
||||||
));
|
|
||||||
|
can_patterns.push((var_store.fresh(), can_pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
|
@ -283,7 +285,7 @@ pub fn canonicalize_pattern<'a>(
|
||||||
RequiredField(label, loc_guard) => {
|
RequiredField(label, loc_guard) => {
|
||||||
// a guard does not introduce the label into scope!
|
// a guard does not introduce the label into scope!
|
||||||
let symbol = scope.ignore(label.into(), &mut env.ident_ids);
|
let symbol = scope.ignore(label.into(), &mut env.ident_ids);
|
||||||
let can_guard = canonicalize_pattern(
|
let (new_output, can_guard) = canonicalize_pattern(
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
scope,
|
||||||
|
@ -292,6 +294,8 @@ pub fn canonicalize_pattern<'a>(
|
||||||
loc_guard.region,
|
loc_guard.region,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
output.union(new_output);
|
||||||
|
|
||||||
destructs.push(Located {
|
destructs.push(Located {
|
||||||
region: loc_pattern.region,
|
region: loc_pattern.region,
|
||||||
value: RecordDestruct {
|
value: RecordDestruct {
|
||||||
|
@ -311,8 +315,7 @@ pub fn canonicalize_pattern<'a>(
|
||||||
region,
|
region,
|
||||||
) {
|
) {
|
||||||
Ok(symbol) => {
|
Ok(symbol) => {
|
||||||
// TODO use output?
|
let (can_default, expr_output) = canonicalize_expr(
|
||||||
let (can_default, _output) = canonicalize_expr(
|
|
||||||
env,
|
env,
|
||||||
var_store,
|
var_store,
|
||||||
scope,
|
scope,
|
||||||
|
@ -320,6 +323,8 @@ pub fn canonicalize_pattern<'a>(
|
||||||
&loc_default.value,
|
&loc_default.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
output.union(expr_output);
|
||||||
|
|
||||||
destructs.push(Located {
|
destructs.push(Located {
|
||||||
region: loc_pattern.region,
|
region: loc_pattern.region,
|
||||||
value: RecordDestruct {
|
value: RecordDestruct {
|
||||||
|
@ -375,10 +380,13 @@ pub fn canonicalize_pattern<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Located {
|
(
|
||||||
region,
|
output,
|
||||||
value: can_pattern,
|
Located {
|
||||||
}
|
region,
|
||||||
|
value: can_pattern,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't
|
/// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue