[fine] While loops, nothing

This commit is contained in:
John Doty 2024-02-05 06:11:37 -08:00
parent 1cc5ce6ca9
commit ac3c158a81
7 changed files with 166 additions and 48 deletions

View file

@ -171,7 +171,7 @@ impl fmt::Display for Type {
Error => write!(f, "<< INTERNAL ERROR >>"),
Unreachable => write!(f, "<< UNREACHABLE >>"),
Assignment(_) => write!(f, "assignment"),
Nothing => write!(f, "()"),
Nothing => write!(f, "nothing"),
F64 => write!(f, "f64"),
I64 => write!(f, "i64"),
String => write!(f, "string"),
@ -1139,9 +1139,9 @@ impl<'a> Semantics<'a> {
TreeKind::Block => self.type_of_block(tree),
TreeKind::CallExpression => self.type_of_call(tree),
TreeKind::ClassDecl => self.type_of_class_decl(t, tree),
TreeKind::FieldDecl => self.type_of_field_decl(tree),
TreeKind::ConditionalExpression => self.type_of_conditional(tree),
TreeKind::ExpressionStatement => self.type_of_expression_statement(tree),
TreeKind::FieldDecl => self.type_of_field_decl(tree),
TreeKind::FieldValue => self.type_of_field_value(t, tree),
TreeKind::ForStatement => Some(Type::Nothing),
TreeKind::FunctionDecl => self.type_of_function_decl(tree),
@ -1153,6 +1153,9 @@ impl<'a> Semantics<'a> {
TreeKind::ListConstructor => self.type_of_list_constructor(t, tree),
TreeKind::ListConstructorElement => self.type_of_list_constructor_element(tree),
TreeKind::LiteralExpression => self.type_of_literal(tree),
TreeKind::MatchArm => self.type_of_match_arm(tree),
TreeKind::MatchBody => self.type_of_match_body(tree),
TreeKind::MatchExpression => self.type_of_match_expression(tree),
TreeKind::MemberAccess => self.type_of_member_access(tree),
TreeKind::NewObjectExpression => self.type_of_new_object_expression(tree),
TreeKind::Parameter => self.type_of_parameter(tree),
@ -1164,10 +1167,7 @@ impl<'a> Semantics<'a> {
TreeKind::TypeIdentifier => self.type_of_type_identifier(t, tree),
TreeKind::TypeParameter => self.type_of_type_parameter(tree),
TreeKind::UnaryExpression => self.type_of_unary(tree),
TreeKind::MatchExpression => self.type_of_match_expression(tree),
TreeKind::MatchBody => self.type_of_match_body(tree),
TreeKind::MatchArm => self.type_of_match_arm(tree),
TreeKind::WhileStatement => Some(Type::Nothing),
_ => self.internal_compiler_error(Some(t), "asking for a nonsense type"),
};
@ -1241,6 +1241,16 @@ impl<'a> Semantics<'a> {
(TokenKind::EqualEqual, Type::Bool, Type::Bool) => Some(Type::Bool),
(TokenKind::EqualEqual, Type::Nothing, Type::Nothing) => Some(Type::Bool),
(TokenKind::Less, Type::F64, Type::F64) => Some(Type::Bool),
(TokenKind::LessEqual, Type::F64, Type::F64) => Some(Type::Bool),
(TokenKind::Greater, Type::F64, Type::F64) => Some(Type::Bool),
(TokenKind::GreaterEqual, Type::F64, Type::F64) => Some(Type::Bool),
(TokenKind::Less, Type::String, Type::String) => Some(Type::Bool),
(TokenKind::LessEqual, Type::String, Type::String) => Some(Type::Bool),
(TokenKind::Greater, Type::String, Type::String) => Some(Type::Bool),
(TokenKind::GreaterEqual, Type::String, Type::String) => Some(Type::Bool),
// This is dumb and should be punished, probably.
(_, _, Type::Unreachable) => {
self.report_error(
@ -1353,7 +1363,7 @@ impl<'a> Semantics<'a> {
"f64" => Some(Type::F64),
"string" => Some(Type::String),
"bool" => Some(Type::Bool),
"()" => Some(Type::Nothing),
"nothing" => Some(Type::Nothing),
"list" => {
let args =
tree.child_tree_of_kind(self.syntax_tree, TreeKind::TypeParameterList)?;
@ -2041,6 +2051,8 @@ pub fn check(s: &Semantics) {
TreeKind::MatchArm => {}
TreeKind::MatchBody => check_match_body(s, t, tree),
TreeKind::MatchExpression => {}
TreeKind::WhileStatement => check_while_statement(s, tree),
}
}
}
@ -2240,6 +2252,7 @@ fn check_match_body(s: &Semantics, t: TreeRef, _tree: &Tree) {
let _ = s.type_of(t); // Checks arm count and compatibility.
// TODO: completeness checks
// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_pattern_analysis/usefulness/index.html
// let arms: Vec<_> = tree
// .children_of_kind(s.syntax_tree, TreeKind::MatchArm)
@ -2253,6 +2266,18 @@ fn check_match_body(s: &Semantics, t: TreeRef, _tree: &Tree) {
// }
}
fn check_while_statement(s: &Semantics, tree: &Tree) {
if let Some(expr) = tree.nth_tree(1) {
let expr_type = s.type_of(expr);
if !s.can_convert(&expr_type, &Type::Bool) {
s.report_error_tree_ref(
expr,
"the condition of the while loop must produce a boolean",
);
}
}
}
#[cfg(test)]
mod tests {
use super::*;