[fine] Garbage Compile

This commit is contained in:
John Doty 2024-01-08 18:43:47 -08:00
parent 8d09076586
commit 6d2fd446ee
3 changed files with 113 additions and 38 deletions

View file

@ -389,9 +389,7 @@ impl<'a> Semantics<'a> {
};
let declaration_type = match tree.nth_tree(3) {
Some(expr) => self
.type_of(expr)
.expect("the tree in the expression should yield a type"),
Some(expr) => self.type_of(expr),
// The syntax error should already have been reported, so we'll
// stick with error type here. (But bind the name, because we see
@ -432,7 +430,6 @@ impl<'a> Semantics<'a> {
let declaration_type = if let Some(type_expression) = param.nth_tree(2) {
self.type_of(type_expression)
.expect("the type expression should yield *some* type here")
} else {
Type::Error
};
@ -445,17 +442,17 @@ impl<'a> Semantics<'a> {
EnvironmentRef::new(environment)
}
pub fn type_of(&self, t: TreeRef) -> Option<Type> {
pub fn type_of(&self, t: TreeRef) -> Type {
{
let state = &mut self.types.borrow_mut()[t.index()];
match state {
Incremental::None => (),
Incremental::Complete(existing) => return Some(existing.clone()),
Incremental::Complete(existing) => return existing.clone(),
Incremental::InProgress => {
// eprintln!("type_of circular => {t:?}");
self.report_error_tree_ref(t, "The type of this expression depends on itself");
*state = Incremental::Complete(Type::Error);
return Some(Type::Error);
return Type::Error;
}
}
*state = Incremental::InProgress;
@ -488,7 +485,7 @@ impl<'a> Semantics<'a> {
let result = result.unwrap_or(Type::Error);
self.types.borrow_mut()[t.index()] = Incremental::Complete(result.clone());
Some(result)
result
}
fn type_of_unary(&self, tree: &Tree) -> Option<Type> {
@ -497,10 +494,7 @@ impl<'a> Semantics<'a> {
let op = tree.nth_token(0)?;
let expr = tree.nth_tree(1)?;
let argument_type = self
.type_of(expr)
.expect("Our argument should be an expression");
let argument_type = self.type_of(expr);
match (op.kind, argument_type) {
(TokenKind::Plus, Type::F64) => Some(Type::F64),
(TokenKind::Minus, Type::F64) => Some(Type::F64),
@ -534,13 +528,9 @@ impl<'a> Semantics<'a> {
fn type_of_binary(&self, tree: &Tree) -> Option<Type> {
assert_eq!(tree.kind, TreeKind::BinaryExpression);
let lhs = self
.type_of(tree.nth_tree(0)?)
.expect("must be an expression");
let lhs = self.type_of(tree.nth_tree(0)?);
let op = tree.nth_token(1)?;
let rhs = self
.type_of(tree.nth_tree(2)?)
.expect("must be an expression");
let rhs = self.type_of(tree.nth_tree(2)?);
match (op.kind, lhs, rhs) {
(
@ -618,22 +608,17 @@ impl<'a> Semantics<'a> {
let mut is_unreachable = false;
for i in 1..last_index {
// TODO: if `is_unreachable` here then we actually have
// unreachable code here! We should warn about it I guess.
is_unreachable = self
.type_of(tree.nth_tree(i)?)
.map(|t| matches!(t, Type::Unreachable))
.unwrap_or(false)
|| is_unreachable;
// unreachable code here! We should warn about it
// I guess.
is_unreachable =
matches!(self.type_of(tree.nth_tree(i)?), Type::Unreachable) || is_unreachable;
}
// NOTE: If for some reason the last statement is unsuitable for a
// type then we consider the type of the block to be Nothing.
// (And explicitly not Error, which is what returning None
// would yield.)
let last_type = self
.type_of(tree.nth_tree(last_index)?)
.unwrap_or(Type::Nothing);
let last_type = self.type_of(tree.nth_tree(last_index)?);
// If anything in this block generated an "Unreachable" then the
// whole type of the block is "unreachable" no matter what.
@ -660,26 +645,22 @@ impl<'a> Semantics<'a> {
fn type_of_grouping(&self, tree: &Tree) -> Option<Type> {
assert_eq!(tree.kind, TreeKind::GroupingExpression);
let expr = tree.nth_tree(1)?;
Some(
self.type_of(expr)
.expect("the thing in the parenthesis must have some type"),
)
tree.nth_tree(1).map(|t| self.type_of(t))
}
fn type_of_conditional(&self, tree: &Tree) -> Option<Type> {
assert_eq!(tree.kind, TreeKind::ConditionalExpression);
let cond_tree = tree.nth_tree(1)?;
let cond_type = self.type_of(cond_tree).expect("must be expression");
let then_type = self.type_of(tree.nth_tree(2)?).expect("must be expression");
let cond_type = self.type_of(cond_tree);
let then_type = self.type_of(tree.nth_tree(2)?);
let has_else = tree
.nth_token(3)
.map(|t| t.kind == TokenKind::Else)
.unwrap_or(false);
let else_type = if has_else {
Some(self.type_of(tree.nth_tree(4)?).expect("must be expression"))
Some(self.type_of(tree.nth_tree(4)?))
} else {
None
};
@ -731,7 +712,7 @@ impl<'a> Semantics<'a> {
.map(|t| t.kind == TokenKind::Semicolon)
.unwrap_or(false);
let expression_type = self.type_of(tree.nth_tree(0)?).expect("must be expression");
let expression_type = self.type_of(tree.nth_tree(0)?);
Some(match expression_type {
Type::Unreachable => Type::Unreachable,
_ => {
@ -802,7 +783,7 @@ impl<'a> Semantics<'a> {
}
}
fn internal_compiler_error(&self, tr: Option<TreeRef>, message: &str) -> ! {
pub fn internal_compiler_error(&self, tr: Option<TreeRef>, message: &str) -> ! {
eprintln!("Internal compiler error: {message}!");
self.dump_compiler_state(tr);
panic!("INTERNAL COMPILER ERROR: {message}")