[fine] Starting on pattern matching, make patterns explicit
This commit is contained in:
parent
f00b9e22e7
commit
deed9d9a45
4 changed files with 178 additions and 50 deletions
|
|
@ -850,14 +850,29 @@ impl<'a> Semantics<'a> {
|
|||
|
||||
fn environment_of_is_expression(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||
assert_eq!(tree.kind, TreeKind::IsExpression);
|
||||
|
||||
// The environment of an `is` expression is the environment produced by the pattern.
|
||||
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();
|
||||
};
|
||||
self.environment_of_pattern(parent, pattern)
|
||||
}
|
||||
|
||||
// NOTE: THIS IS CALLED DIRECTLY, NOT VIA `environment_of` TO AVOID CYCLES.
|
||||
fn environment_of_pattern(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||
assert_eq!(tree.kind, TreeKind::Pattern);
|
||||
|
||||
let Some(binding) = tree.child_tree_of_kind(self.syntax_tree, TreeKind::VariableBinding)
|
||||
else {
|
||||
// No binding, no new environment.
|
||||
return parent;
|
||||
};
|
||||
let Some(variable) = binding.nth_token(0) else {
|
||||
return Environment::error();
|
||||
};
|
||||
let Some(type_expr) = binding.nth_tree(2) else {
|
||||
let Some(type_expr) = tree.child_of_kind(self.syntax_tree, TreeKind::TypeExpression) else {
|
||||
return Environment::error();
|
||||
};
|
||||
|
||||
|
|
@ -866,7 +881,7 @@ impl<'a> Semantics<'a> {
|
|||
|
||||
let mut env = Environment::new(Some(parent), Location::Local);
|
||||
env.insert(variable, type_expr);
|
||||
return EnvironmentRef::new(env);
|
||||
EnvironmentRef::new(env)
|
||||
}
|
||||
|
||||
pub fn class_of(&self, t: TreeRef) -> ClassRef {
|
||||
|
|
@ -1911,6 +1926,11 @@ pub fn check(s: &Semantics) {
|
|||
|
||||
TreeKind::IsExpression => check_is_expression(s, tree),
|
||||
TreeKind::VariableBinding => check_variable_binding(s, tree),
|
||||
TreeKind::Pattern => check_pattern(s, tree),
|
||||
|
||||
TreeKind::MatchArm => {}
|
||||
TreeKind::MatchBody => {}
|
||||
TreeKind::MatchExpression => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2090,6 +2110,26 @@ fn check_is_expression(_s: &Semantics, _tree: &Tree) {
|
|||
// TODO
|
||||
}
|
||||
|
||||
fn check_pattern(s: &Semantics, tree: &Tree) {
|
||||
// If there's an AND then it must produce a boolean.
|
||||
let and_index = tree.children.iter().position(|c| match c {
|
||||
Child::Token(t) => t.kind == TokenKind::And,
|
||||
_ => false,
|
||||
});
|
||||
if let Some(and_index) = and_index {
|
||||
if let Some(pred) = tree.nth_tree(and_index + 1) {
|
||||
let predicate_type = s.type_of(pred);
|
||||
if !s.can_convert(&predicate_type, &Type::Bool) {
|
||||
// TODO: TEST
|
||||
s.report_error_tree_ref(
|
||||
pred,
|
||||
format!("this predicate produces {predicate_type}, but must produce a boolean"),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_variable_binding(_s: &Semantics, _tree: &Tree) {
|
||||
// TODO
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue