Fix hiding logic; Fix hiding with predecls

* Hiding logic is simplified and fixed so you can hide and unhide the
  same def repeatedly.
* Separates predeclared ids into its own data structure to protect them
  from hiding. Otherwise, you could hide the predeclared variable and
  the actual def would panic.
This commit is contained in:
Jakub Žádník
2021-10-01 22:29:24 +03:00
parent aa06a71e1f
commit 2af8116f50
2 changed files with 89 additions and 81 deletions

View File

@ -42,7 +42,7 @@ pub fn parse_def_predecl(working_set: &mut StateWorkingSet, spans: &[Span]) {
signature.name = name;
let decl = signature.predeclare();
working_set.add_decl(decl);
working_set.add_predecl(decl);
}
}
}
@ -95,15 +95,15 @@ pub fn parse_def(
call.positional.push(block);
if let (Some(name), Some(mut signature), Some(block_id)) =
(name, signature, block_id)
(&name, signature, block_id)
{
let decl_id = working_set
.find_decl(name.as_bytes())
.find_predecl(name.as_bytes())
.expect("internal error: predeclaration failed to add definition");
let declaration = working_set.get_decl_mut(decl_id);
signature.name = name;
signature.name = name.clone();
*declaration = signature.into_block_command(block_id);
}
@ -118,6 +118,19 @@ pub fn parse_def(
}
working_set.exit_scope();
if let Some(name) = name {
// It's OK if it returns None: The decl was already merged in previous parse
// pass.
working_set.merge_predecl(name.as_bytes());
} else {
error = error.or_else(|| {
Some(ParseError::UnknownState(
"Could not get string from string expression".into(),
*name_span,
))
});
}
call
} else {
let err_span = Span {
@ -581,18 +594,10 @@ pub fn parse_hide(
let name_bytes: Vec<u8> = working_set.get_span_contents(spans[1]).into();
// TODO: Do the import pattern stuff for bulk-hiding
// TODO: move this error into error = error.or pattern
let _decl_id = if let Some(id) = working_set.find_decl(&name_bytes) {
id
} else {
return (
garbage_statement(spans),
Some(ParseError::UnknownCommand(spans[1])),
);
};
// Hide the definitions
working_set.hide_decl(name_bytes);
if working_set.hide_decl(&name_bytes).is_none() {
error = error.or_else(|| Some(ParseError::UnknownCommand(spans[1])));
}
// Create the Hide command call
let hide_decl_id = working_set