hm-inference #6

Merged
sb10q merged 136 commits from hm-inference into master 2021-08-19 11:46:50 +08:00
4 changed files with 24 additions and 40 deletions
Showing only changes of commit b01d0f6fbb - Show all commits

View File

@ -22,9 +22,7 @@ impl<'a> Inferencer<'a> {
} }
Ok(()) Ok(())
} }
_ => { _ => self.check_expr(pattern, defined_identifiers),
self.check_expr(pattern, defined_identifiers)
}
} }
} }
@ -46,7 +44,10 @@ impl<'a> Inferencer<'a> {
match &expr.node { match &expr.node {
ExprKind::Name { id, .. } => { ExprKind::Name { id, .. } => {
if !defined_identifiers.contains(id) { if !defined_identifiers.contains(id) {
return Err(format!("unknown identifier {} (use before def?) at {}", id, expr.location)); return Err(format!(
"unknown identifier {} (use before def?) at {}",
id, expr.location
));
} }
} }
ExprKind::List { elts, .. } ExprKind::List { elts, .. }
@ -66,9 +67,7 @@ impl<'a> Inferencer<'a> {
ExprKind::UnaryOp { operand, .. } => { ExprKind::UnaryOp { operand, .. } => {
self.check_expr(operand, defined_identifiers)?; self.check_expr(operand, defined_identifiers)?;
} }
ExprKind::Compare { ExprKind::Compare { left, comparators, .. } => {
left, comparators, ..
} => {
for elt in once(left.as_ref()).chain(comparators.iter()) { for elt in once(left.as_ref()).chain(comparators.iter()) {
self.check_expr(elt, defined_identifiers)?; self.check_expr(elt, defined_identifiers)?;
} }
@ -83,10 +82,7 @@ impl<'a> Inferencer<'a> {
self.check_expr(orelse, defined_identifiers)?; self.check_expr(orelse, defined_identifiers)?;
} }
ExprKind::Slice { lower, upper, step } => { ExprKind::Slice { lower, upper, step } => {
for elt in [lower.as_ref(), upper.as_ref(), step.as_ref()] for elt in [lower.as_ref(), upper.as_ref(), step.as_ref()].iter().flatten() {
.iter()
.flatten()
{
self.check_expr(elt, defined_identifiers)?; self.check_expr(elt, defined_identifiers)?;
} }
} }
@ -99,13 +95,9 @@ impl<'a> Inferencer<'a> {
} }
self.check_expr(body, &defined_identifiers)?; self.check_expr(body, &defined_identifiers)?;
} }
ExprKind::ListComp { ExprKind::ListComp { elt, generators, .. } => {
elt, generators, ..
} => {
// in our type inference stage, we already make sure that there is only 1 generator // in our type inference stage, we already make sure that there is only 1 generator
let ast::Comprehension { let ast::Comprehension { target, iter, ifs, .. } = &generators[0];
target, iter, ifs, ..
} = &generators[0];
self.check_expr(iter, defined_identifiers)?; self.check_expr(iter, defined_identifiers)?;
let mut defined_identifiers = defined_identifiers.to_vec(); let mut defined_identifiers = defined_identifiers.to_vec();
self.check_pattern(target, &mut defined_identifiers)?; self.check_pattern(target, &mut defined_identifiers)?;
@ -113,11 +105,7 @@ impl<'a> Inferencer<'a> {
self.check_expr(term, &defined_identifiers)?; self.check_expr(term, &defined_identifiers)?;
} }
} }
ExprKind::Call { ExprKind::Call { func, args, keywords } => {
func,
args,
keywords,
} => {
for expr in once(func.as_ref()) for expr in once(func.as_ref())
.chain(args.iter()) .chain(args.iter())
.chain(keywords.iter().map(|v| v.node.value.as_ref())) .chain(keywords.iter().map(|v| v.node.value.as_ref()))
@ -141,13 +129,7 @@ impl<'a> Inferencer<'a> {
defined_identifiers: &mut Vec<String>, defined_identifiers: &mut Vec<String>,
) -> Result<bool, String> { ) -> Result<bool, String> {
match &stmt.node { match &stmt.node {
StmtKind::For { StmtKind::For { target, iter, body, orelse, .. } => {
target,
iter,
body,
orelse,
..
} => {
self.check_expr(iter, defined_identifiers)?; self.check_expr(iter, defined_identifiers)?;
for stmt in orelse.iter() { for stmt in orelse.iter() {
self.check_stmt(stmt, defined_identifiers)?; self.check_stmt(stmt, defined_identifiers)?;

View File

@ -7,7 +7,7 @@ pub struct FileID(u32);
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum Location { pub enum Location {
CodeRange(FileID, ast::Location), CodeRange(FileID, ast::Location),
Builtin Builtin,
} }
pub struct FileRegistry { pub struct FileRegistry {

View File

@ -1,6 +1,6 @@
use super::location::Location; use super::location::Location;
use super::top_level::DefinitionId;
use super::typedef::Type; use super::typedef::Type;
use crate::top_level::DefinitionId;
use rustpython_parser::ast::Expr; use rustpython_parser::ast::Expr;
pub enum SymbolValue<'a> { pub enum SymbolValue<'a> {

View File

@ -1,7 +1,7 @@
use std::{cell::RefCell, sync::Arc};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::{TryInto, From}; use std::convert::{From, TryInto};
use std::iter::once; use std::iter::once;
use std::{cell::RefCell, sync::Arc};
use super::magic_methods::*; use super::magic_methods::*;
use super::symbol_resolver::SymbolResolver; use super::symbol_resolver::SymbolResolver;
@ -24,10 +24,7 @@ pub struct CodeLocation {
impl From<Location> for CodeLocation { impl From<Location> for CodeLocation {
fn from(loc: Location) -> CodeLocation { fn from(loc: Location) -> CodeLocation {
CodeLocation { CodeLocation { row: loc.row(), col: loc.column() }
row: loc.row(),
col: loc.column()
}
} }
} }
@ -190,8 +187,12 @@ impl<'a> Inferencer<'a> {
params: Vec<Type>, params: Vec<Type>,
ret: Type, ret: Type,
) -> InferenceResult { ) -> InferenceResult {
let call = let call = Arc::new(Call {
Arc::new(Call { posargs: params, kwargs: HashMap::new(), ret, fun: RefCell::new(None) }); posargs: params,
kwargs: HashMap::new(),
ret,
fun: RefCell::new(None),
});
let call = self.unifier.add_ty(TypeEnum::TCall(vec![call].into())); let call = self.unifier.add_ty(TypeEnum::TCall(vec![call].into()));
let fields = once((method, call)).collect(); let fields = once((method, call)).collect();
let record = self.unifier.add_record(fields); let record = self.unifier.add_record(fields);
@ -333,7 +334,8 @@ impl<'a> Inferencer<'a> {
} }
let arg0 = self.fold_expr(args.remove(0))?; let arg0 = self.fold_expr(args.remove(0))?;
let ty = if let Some(arg) = args.pop() { let ty = if let Some(arg) = args.pop() {
self.function_data.resolver self.function_data
.resolver
.parse_type_name(&arg) .parse_type_name(&arg)
.ok_or_else(|| "error parsing type".to_string())? .ok_or_else(|| "error parsing type".to_string())?
} else { } else {