Skip to content

Commit

Permalink
Rely on symbol table for function body analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
Glyphack committed Nov 6, 2023
1 parent 7dab732 commit b6e8b90
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 23 deletions.
4 changes: 3 additions & 1 deletion typechecker/src/symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,11 @@ pub struct Function {
pub function_node: ast::FunctionDef,
pub is_method: bool,
pub is_generator: bool,
/// return statements that are reachable in the top level function body
pub return_statements: Vec<ast::Return>,
/// yield statements that are reachable in the top level function body
pub yeild_statements: Vec<ast::Yield>,
// helpful to later type check exceptions
/// raise statements that are reachable in the top level function body
pub raise_statements: Vec<ast::Raise>,
}

Expand Down
37 changes: 15 additions & 22 deletions typechecker/src/type_check/type_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl TypeEvaluator {
None => symbol.last_declaration(),
};

log::debug!("get_symbol_node_type: {:?}", decl);
log::debug!("fetch symbol declaration: {:?}", decl);
match decl {
Some(decl) => self.get_type_from_declaration(decl),
None => Ok(PythonType::Any),
Expand Down Expand Up @@ -222,27 +222,11 @@ impl TypeEvaluator {
let annotated_return_type = if let Some(type_annotation) = f.function_node.returns.clone() {
type_inference::get_type_from_annotation(&type_annotation)
} else {
// TODO infer from function body
PythonType::Unknown
let inferred_return_type = self.infer_function_return_type(f);
log::debug!("infered_return_type: {:?}", inferred_return_type);
inferred_return_type
};

let is_never = if f.is_abstract() {
false
} else {
// TODO: if all code paths are raising then it's never type
f.function_node.body.iter().any(|stmt| match stmt {
ast::Statement::Raise(_) => true,
_ => false,
})
};


log::debug!("is_never: {}", is_never);
if is_never {
// TODO: if type annotation is not correct error
return Ok(PythonType::Never);
}

let arguments = f.function_node.args.clone();
let name = f.function_node.name.clone();

Expand Down Expand Up @@ -277,10 +261,12 @@ impl TypeEvaluator {
name: name.to_string(),
position,
};
match self.symbol_table.lookup_in_scope(lookup_request) {
let result = match self.symbol_table.lookup_in_scope(lookup_request) {
Some(symbol) => self.get_symbol_node_type(symbol, position),
None => Ok(PythonType::Unknown),
}
};
log::debug!("infer_type_from_symbol_table: {:?} => {:?}", name, result);
result
}

fn get_sequence_type_from_elements(&self, elements: &Vec<ast::Expression>) -> PythonType {
Expand All @@ -296,6 +282,13 @@ impl TypeEvaluator {
}
prev_elm_type
}

fn infer_function_return_type(&self, f: &crate::symbol_table::Function) -> PythonType {
if !f.is_abstract() && !f.raise_statements.is_empty() {
return PythonType::Never;
}
PythonType::Unknown
}
}

impl TraversalVisitorImmutGeneric<PythonType> for TypeEvaluator {
Expand Down

0 comments on commit b6e8b90

Please sign in to comment.