[fine] Report errors with environments, fix match bug
I'm worried that this will turn into something I always have to do instead of something I just do sometimes: always provide the provenance of some error type or another. Link error types to diagnostics, etc.
This commit is contained in:
parent
2ba34701ac
commit
8779aade24
3 changed files with 41 additions and 30 deletions
|
|
@ -431,7 +431,7 @@ pub struct Environment {
|
|||
pub location: Location,
|
||||
pub next_index: usize,
|
||||
pub declarations: HashMap<Box<str>, Declaration>,
|
||||
pub is_error: bool,
|
||||
pub error: Option<&'static str>,
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
|
|
@ -457,18 +457,22 @@ impl Environment {
|
|||
location,
|
||||
next_index,
|
||||
declarations: HashMap::new(),
|
||||
is_error: false,
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error() -> EnvironmentRef {
|
||||
pub fn is_error(&self) -> bool {
|
||||
self.error.is_some()
|
||||
}
|
||||
|
||||
pub fn error(why: &'static str) -> EnvironmentRef {
|
||||
// TODO: Exactly once?
|
||||
EnvironmentRef::new(Environment {
|
||||
parent: None,
|
||||
location: Location::Local,
|
||||
next_index: 0,
|
||||
declarations: HashMap::new(),
|
||||
is_error: true,
|
||||
error: Some(why),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1137,12 +1141,12 @@ impl Semantics {
|
|||
let Some(pattern) = tree.child_tree_of_kind(&self.syntax_tree, TreeKind::Pattern) else {
|
||||
// Should really have a pattern in there; otherwise there was a
|
||||
// parse error, don't make more trouble.
|
||||
return Environment::error();
|
||||
return Environment::error("no rhs (pattern)");
|
||||
};
|
||||
|
||||
// The left hand side of the `is` expression is used for wildcard types.
|
||||
let Some(lhs) = tree.nth_tree(0) else {
|
||||
return Environment::error();
|
||||
return Environment::error("no lhs (value)");
|
||||
};
|
||||
self.environment_of_pattern(parent, pattern, lhs)
|
||||
}
|
||||
|
|
@ -1159,7 +1163,7 @@ impl Semantics {
|
|||
let Some(pattern) = tree.child_tree_of_kind(&self.syntax_tree, TreeKind::Pattern) else {
|
||||
// Should really have a pattern in there; otherwise there was a
|
||||
// parse error, don't make more trouble.
|
||||
return Environment::error();
|
||||
return Environment::error("arm: no lhs (pattern)");
|
||||
};
|
||||
|
||||
// The expression in the match expression is the binding for the wildcard pattern.
|
||||
|
|
@ -1180,8 +1184,8 @@ impl Semantics {
|
|||
}
|
||||
|
||||
// The expression is the first tree child of match expression.
|
||||
let Some(lhs) = tree.nth_tree(1) else {
|
||||
return Environment::error();
|
||||
let Some(lhs) = tree.nth_tree(2) else {
|
||||
return Environment::error("arm: no rhs (expression)");
|
||||
};
|
||||
self.environment_of_pattern(parent, pattern, lhs)
|
||||
}
|
||||
|
|
@ -1201,7 +1205,7 @@ impl Semantics {
|
|||
return parent;
|
||||
};
|
||||
let Some(variable) = binding.nth_token(0) else {
|
||||
return Environment::error();
|
||||
return Environment::error("no variable");
|
||||
};
|
||||
|
||||
let is_wildcard = tree
|
||||
|
|
@ -1218,7 +1222,7 @@ impl Semantics {
|
|||
// match for the variable to have a value.
|
||||
let Some(type_expr) = tree.child_of_kind(&self.syntax_tree, TreeKind::TypeExpression)
|
||||
else {
|
||||
return Environment::error();
|
||||
return Environment::error("no type expression");
|
||||
};
|
||||
type_expr
|
||||
};
|
||||
|
|
@ -1658,7 +1662,7 @@ impl Semantics {
|
|||
let tree = &self.syntax_tree[left_tree];
|
||||
|
||||
#[allow(unused_assignments)]
|
||||
let mut environment = Environment::error();
|
||||
let mut environment = Environment::error("?");
|
||||
|
||||
let declaration = match tree.kind {
|
||||
// TODO: Assign to list access
|
||||
|
|
@ -1668,7 +1672,7 @@ impl Semantics {
|
|||
match environment.bind(id) {
|
||||
Some(decl) => decl,
|
||||
None => {
|
||||
if !environment.is_error {
|
||||
if !environment.is_error() {
|
||||
self.report_error_tree(tree, format!("cannot find value {id} here"));
|
||||
}
|
||||
return Some(Type::Error);
|
||||
|
|
@ -1682,7 +1686,7 @@ impl Semantics {
|
|||
match environment.bind(id) {
|
||||
Some(decl) => decl,
|
||||
None => {
|
||||
if !environment.is_error {
|
||||
if !environment.is_error() {
|
||||
self.report_error_tree(tree, format!("'{typ}' has no member {id}"));
|
||||
}
|
||||
return Some(Type::Error);
|
||||
|
|
@ -1820,7 +1824,7 @@ impl Semantics {
|
|||
.type_of_declaration(*tree, declaration),
|
||||
),
|
||||
None => {
|
||||
if !environment.is_error {
|
||||
if !environment.is_error() {
|
||||
self.report_error_tree(tree, format!("Unrecognized type: '{token}'"));
|
||||
}
|
||||
Some(Type::Error)
|
||||
|
|
@ -2046,7 +2050,7 @@ impl Semantics {
|
|||
|
||||
let id_str = id.as_str(&self.source);
|
||||
let Some(declaration) = env.bind(id_str) else {
|
||||
if !env.is_error {
|
||||
if !env.is_error() {
|
||||
self.report_error_span(
|
||||
id.start(),
|
||||
id.end(),
|
||||
|
|
@ -2100,10 +2104,10 @@ impl Semantics {
|
|||
}
|
||||
EnvironmentRef::new(result)
|
||||
}
|
||||
Type::Error => return Environment::error(),
|
||||
Type::Error => return Environment::error("error type has no members"),
|
||||
_ => {
|
||||
self.report_error_tree_ref(t, format!("cannot access members of '{typ}'"));
|
||||
return Environment::error();
|
||||
return Environment::error("type has no members");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2140,7 +2144,7 @@ impl Semantics {
|
|||
return Some(self.type_of_declaration(Some(t), declaration));
|
||||
}
|
||||
|
||||
if !environment.is_error {
|
||||
if !environment.is_error() {
|
||||
self.report_error_tree(tree, format!("cannot find value {id} here"));
|
||||
}
|
||||
Some(Type::Error)
|
||||
|
|
@ -2202,7 +2206,7 @@ impl Semantics {
|
|||
});
|
||||
}
|
||||
|
||||
if !environment.is_error {
|
||||
if !environment.is_error() {
|
||||
self.report_error_tree(tree, "`self` is only valid in methods");
|
||||
}
|
||||
Some(Type::Error)
|
||||
|
|
@ -2340,7 +2344,7 @@ impl Semantics {
|
|||
let declaration = match environment.bind(id) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
if !environment.is_error {
|
||||
if !environment.is_error() {
|
||||
self.report_error_tree(tree, format!("cannot find value {id} here"));
|
||||
}
|
||||
return Some(Type::Error);
|
||||
|
|
@ -2647,6 +2651,9 @@ impl Semantics {
|
|||
eprintln!("\nThe environment of the tree was:");
|
||||
let mut environment = Some(self.environment_of(tr));
|
||||
while let Some(env) = environment {
|
||||
if let Some(error) = env.error {
|
||||
eprint!(" *** ERROR: {error}");
|
||||
}
|
||||
for (k, v) in env.declarations.iter() {
|
||||
eprint!(" {k}: ");
|
||||
match v {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue