don't add guarded record fields into scope

This commit is contained in:
Folkert 2020-04-09 01:06:26 +02:00
parent 85e2cf4465
commit fd7ca5bcc9
8 changed files with 196 additions and 79 deletions

View file

@ -267,45 +267,26 @@ pub fn canonicalize_pattern<'a>(
};
}
RecordField(label, loc_guard) => {
match scope.introduce(
label.into(),
&env.exposed_ident_ids,
&mut env.ident_ids,
region,
) {
Ok(symbol) => {
let can_guard = canonicalize_pattern(
env,
var_store,
scope,
pattern_type,
&loc_guard.value,
loc_guard.region,
);
// a guard does not introduce the label into scope!
let symbol = scope.ignore(label.into(), &mut env.ident_ids);
let can_guard = canonicalize_pattern(
env,
var_store,
scope,
pattern_type,
&loc_guard.value,
loc_guard.region,
);
destructs.push(Located {
region: loc_pattern.region,
value: RecordDestruct {
var: var_store.fresh(),
label: Lowercase::from(label),
symbol,
guard: Some((var_store.fresh(), can_guard)),
},
});
}
Err((original_region, shadow)) => {
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
original_region,
shadow: shadow.clone(),
}));
// No matter what the other patterns
// are, we're definitely shadowed and will
// get a runtime exception as soon as we
// encounter the first bad pattern.
opt_erroneous = Some(Pattern::Shadowed(original_region, shadow));
}
};
destructs.push(Located {
region: loc_pattern.region,
value: RecordDestruct {
var: var_store.fresh(),
label: Lowercase::from(label),
symbol,
guard: Some((var_store.fresh(), can_guard)),
},
});
}
_ => panic!("invalid pattern in record"),
}

View file

@ -57,10 +57,13 @@ impl Scope {
pub fn lookup(&mut self, ident: &Ident, region: Region) -> Result<Symbol, RuntimeError> {
match self.idents.get(ident) {
Some((symbol, _)) => Ok(*symbol),
None => Err(RuntimeError::LookupNotInScope(Located {
region,
value: ident.clone().into(),
})),
None => Err(RuntimeError::LookupNotInScope(
Located {
region,
value: ident.clone().into(),
},
self.idents.keys().map(|v| v.as_ref().into()).collect(),
)),
}
}
@ -107,6 +110,14 @@ impl Scope {
}
}
/// Ignore an identifier.
///
/// Used for record guards like { x: Just _ }
pub fn ignore(&mut self, ident: Ident, all_ident_ids: &mut IdentIds) -> Symbol {
let ident_id = all_ident_ids.add(ident.into());
Symbol::new(self.home, ident_id)
}
/// Import a Symbol from another module into this module's top-level scope.
///
/// Returns Err if this would shadow an existing ident, including the