Compare commits

..

1 Commits

Author SHA1 Message Date
be218fc0d4 a mess.. 2021-01-19 13:55:13 +08:00
2 changed files with 77 additions and 168 deletions

View File

@ -160,50 +160,50 @@ fn resolve_function<'a>(
} }
} }
fn get_expr_unknowns<'a>( fn get_expression_unknowns<'a>(
defined: &mut Vec<&'a str>, defined: &[&'a str],
unknowns: &mut Vec<&'a str>, unknowns: &mut Vec<&'a str>,
expr: &'a ExpressionType, expr: &'a ExpressionType,
) { ) {
match expr { match expr {
ExpressionType::BoolOp { values, .. } => { ExpressionType::BoolOp { values, .. } => {
for v in values.iter() { for v in values.iter() {
get_expr_unknowns(defined, unknowns, &v.node) get_expression_unknowns(defined, unknowns, &v.node)
} }
} }
ExpressionType::Binop { a, b, .. } => { ExpressionType::Binop { a, b, .. } => {
get_expr_unknowns(defined, unknowns, &a.node); get_expression_unknowns(defined, unknowns, &a.node);
get_expr_unknowns(defined, unknowns, &b.node); get_expression_unknowns(defined, unknowns, &b.node);
} }
ExpressionType::Subscript { a, b } => { ExpressionType::Subscript { a, b } => {
get_expr_unknowns(defined, unknowns, &a.node); get_expression_unknowns(defined, unknowns, &a.node);
get_expr_unknowns(defined, unknowns, &b.node); get_expression_unknowns(defined, unknowns, &b.node);
} }
ExpressionType::Unop { a, .. } => { ExpressionType::Unop { a, .. } => {
get_expr_unknowns(defined, unknowns, &a.node); get_expression_unknowns(defined, unknowns, &a.node);
} }
ExpressionType::Compare { vals, .. } => { ExpressionType::Compare { vals, .. } => {
for v in vals.iter() { for v in vals.iter() {
get_expr_unknowns(defined, unknowns, &v.node) get_expression_unknowns(defined, unknowns, &v.node)
} }
} }
ExpressionType::Attribute { value, .. } => { ExpressionType::Attribute { value, .. } => {
get_expr_unknowns(defined, unknowns, &value.node); get_expression_unknowns(defined, unknowns, &value.node);
} }
ExpressionType::Call { function, args, .. } => { ExpressionType::Call { function, args, .. } => {
get_expr_unknowns(defined, unknowns, &function.node); get_expression_unknowns(defined, unknowns, &function.node);
for v in args.iter() { for v in args.iter() {
get_expr_unknowns(defined, unknowns, &v.node) get_expression_unknowns(defined, unknowns, &v.node)
} }
} }
ExpressionType::List { elements } => { ExpressionType::List { elements } => {
for v in elements.iter() { for v in elements.iter() {
get_expr_unknowns(defined, unknowns, &v.node) get_expression_unknowns(defined, unknowns, &v.node)
} }
} }
ExpressionType::Tuple { elements } => { ExpressionType::Tuple { elements } => {
for v in elements.iter() { for v in elements.iter() {
get_expr_unknowns(defined, unknowns, &v.node) get_expression_unknowns(defined, unknowns, &v.node)
} }
} }
ExpressionType::Comprehension { kind, generators } => { ExpressionType::Comprehension { kind, generators } => {
@ -211,22 +211,22 @@ fn get_expr_unknowns<'a>(
unimplemented!() unimplemented!()
} }
let g = &generators[0]; let g = &generators[0];
get_expr_unknowns(defined, unknowns, &g.iter.node); get_expression_unknowns(defined, unknowns, &g.iter.node);
let mut scoped = defined.clone(); let mut scoped = defined.to_owned();
get_expr_unknowns(defined, &mut scoped, &g.target.node); get_expression_unknowns(defined, &mut scoped, &g.target.node);
for if_expr in g.ifs.iter() { for if_expr in g.ifs.iter() {
get_expr_unknowns(&mut scoped, unknowns, &if_expr.node); get_expression_unknowns(&scoped, unknowns, &if_expr.node);
} }
match kind.as_ref() { match kind.as_ref() {
ComprehensionKind::List { element } => { ComprehensionKind::List { element } => {
get_expr_unknowns(&mut scoped, unknowns, &element.node); get_expression_unknowns(&scoped, unknowns, &element.node);
} }
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
ExpressionType::Slice { elements } => { ExpressionType::Slice { elements } => {
for v in elements.iter() { for v in elements.iter() {
get_expr_unknowns(defined, unknowns, &v.node); get_expression_unknowns(defined, unknowns, &v.node);
} }
} }
ExpressionType::Identifier { name } => { ExpressionType::Identifier { name } => {
@ -235,81 +235,35 @@ fn get_expr_unknowns<'a>(
} }
} }
ExpressionType::IfExpression { test, body, orelse } => { ExpressionType::IfExpression { test, body, orelse } => {
get_expr_unknowns(defined, unknowns, &test.node); get_expression_unknowns(defined, unknowns, &test.node);
get_expr_unknowns(defined, unknowns, &body.node); get_expression_unknowns(defined, unknowns, &body.node);
get_expr_unknowns(defined, unknowns, &orelse.node); get_expression_unknowns(defined, unknowns, &orelse.node);
} }
_ => (), _ => (),
}; };
} }
struct ExprPattern<'a>(&'a ExpressionType, Vec<usize>, bool); pub fn get_pattern_match_unknowns<'a>(
defined: &mut Vec<&'a str>,
impl<'a> ExprPattern<'a> { unknowns: &mut Vec<&'a str>,
fn new(expr: &'a ExpressionType) -> ExprPattern { expr: &'a ExpressionType,
let mut pattern = ExprPattern(expr, Vec::new(), true); ) {
pattern.find_leaf(); match expr {
pattern ExpressionType::Identifier { name } => {
defined.push(&name.as_str());
} }
ExpressionType::Tuple { elements } => {
fn pointed(&mut self) -> &'a ExpressionType { for v in elements.iter() {
let mut current = self.0; get_pattern_match_unknowns(defined, unknowns, &v.node);
for v in self.1.iter() {
if let ExpressionType::Tuple { elements } = current {
current = &elements[*v].node
} else {
unreachable!()
} }
} }
current _ => {
} get_expression_unknowns(defined, unknowns, expr);
fn find_leaf(&mut self) {
let mut current = self.pointed();
while let ExpressionType::Tuple { elements } = current {
if elements.is_empty() {
break;
}
current = &elements[0].node;
self.1.push(0);
}
}
fn inc(&mut self) -> bool {
loop {
if self.1.is_empty() {
return false;
}
let ind = self.1.pop().unwrap() + 1;
let parent = self.pointed();
if let ExpressionType::Tuple { elements } = parent {
if ind < elements.len() {
self.1.push(ind);
self.find_leaf();
return true;
}
} else {
unreachable!()
}
}
}
}
impl<'a> Iterator for ExprPattern<'a> {
type Item = &'a ExpressionType;
fn next(&mut self) -> Option<Self::Item> {
if self.2 {
self.2 = false;
Some(self.pointed())
} else if self.inc() {
Some(self.pointed())
} else {
None
} }
} }
} }
fn get_stmt_unknowns<'a>( pub fn get_statement_unknowns<'a>(
defined: &mut Vec<&'a str>, defined: &mut Vec<&'a str>,
unknowns: &mut Vec<&'a str>, unknowns: &mut Vec<&'a str>,
stmts: &'a [Statement], stmts: &'a [Statement],
@ -317,78 +271,59 @@ fn get_stmt_unknowns<'a>(
for stmt in stmts.iter() { for stmt in stmts.iter() {
match &stmt.node { match &stmt.node {
StatementType::Return { value } => { StatementType::Return { value } => {
if let Some(value) = value { if let Some(v) = value {
get_expr_unknowns(defined, unknowns, &value.node); get_expression_unknowns(defined, unknowns, &v.node);
} }
} }
StatementType::Assign { targets, value } => { StatementType::Assign { targets, value } => {
get_expr_unknowns(defined, unknowns, &value.node); get_expression_unknowns(defined, unknowns, &value.node);
for target in targets.iter() { for t in targets.iter() {
for node in ExprPattern::new(&target.node).into_iter() { get_pattern_match_unknowns(defined, unknowns, &t.node);
if let ExpressionType::Identifier { name } = node {
let name = name.as_str();
if !defined.contains(&name) {
defined.push(name);
}
} else {
get_expr_unknowns(defined, unknowns, node);
}
}
} }
} }
StatementType::AugAssign { target, value, .. } => { StatementType::AugAssign { target, value, .. } => {
get_expr_unknowns(defined, unknowns, &target.node); get_expression_unknowns(defined, unknowns, &target.node);
get_expr_unknowns(defined, unknowns, &value.node); get_expression_unknowns(defined, unknowns, &value.node);
} }
StatementType::AnnAssign { target, value, .. } => { StatementType::AnnAssign { target, value, .. } => {
get_expr_unknowns(defined, unknowns, &target.node); if let Some(v) = value {
if let Some(value) = value { get_expression_unknowns(defined, unknowns, &v.node);
get_expr_unknowns(defined, unknowns, &value.node);
} }
get_pattern_match_unknowns(defined, unknowns, &target.node);
} }
StatementType::Expression { expression } => { StatementType::Expression { expression } => {
get_expr_unknowns(defined, unknowns, &expression.node); get_expression_unknowns(defined, unknowns, &expression.node);
}
StatementType::Global { names } => {
for name in names.iter() {
let name = name.as_str();
if !unknowns.contains(&name) {
unknowns.push(name);
}
}
} }
StatementType::If { test, body, orelse } StatementType::If { test, body, orelse }
| StatementType::While { test, body, orelse } => { | StatementType::While { test, body, orelse } => {
get_expr_unknowns(defined, unknowns, &test.node); get_expression_unknowns(defined, unknowns, &test.node);
// we are not very strict at this point... get_statement_unknowns(defined, unknowns, body.as_slice());
// some identifiers not treated as unknowns may not be resolved
// but should be checked during type inference
get_stmt_unknowns(defined, unknowns, body.as_slice());
if let Some(orelse) = orelse { if let Some(orelse) = orelse {
get_stmt_unknowns(defined, unknowns, orelse.as_slice()); get_statement_unknowns(defined, unknowns, orelse.as_slice());
} }
} }
StatementType::For { is_async, target, iter, body, orelse } => { StatementType::For { is_async, target, body, orelse, iter } => {
if *is_async { if *is_async {
unimplemented!() unimplemented!();
} }
get_expr_unknowns(defined, unknowns, &iter.node); let mut scoped = defined.to_owned();
for node in ExprPattern::new(&target.node).into_iter() { get_expression_unknowns(defined, unknowns, &iter.node);
if let ExpressionType::Identifier { name } = node { get_expression_unknowns(defined, &mut scoped, &target.node);
let name = name.as_str(); get_statement_unknowns(&mut scoped, unknowns, body.as_slice());
if !defined.contains(&name) {
defined.push(name);
}
} else {
get_expr_unknowns(defined, unknowns, node);
}
}
get_stmt_unknowns(defined, unknowns, body.as_slice());
if let Some(orelse) = orelse { if let Some(orelse) = orelse {
get_stmt_unknowns(defined, unknowns, orelse.as_slice()); get_statement_unknowns(&mut scoped, unknowns, orelse.as_slice());
} }
} }
_ => (), StatementType::With { is_async, items, body } => {
if *is_async {
unimplemented!();
}
let mut scoped = defined.to_owned();
for item in items.iter() {
}
}
_ => {}
} }
} }
} }
@ -455,7 +390,7 @@ pub fn resolve_signatures<'a>(ctx: &mut TopLevelContext<'a>, stmts: &'a [Stateme
mod tests { mod tests {
use super::*; use super::*;
use indoc::indoc; use indoc::indoc;
use rustpython_parser::parser::{parse_program, parse_statement}; use rustpython_parser::parser::parse_program;
#[test] #[test]
fn test_get_classes() { fn test_get_classes() {
@ -465,14 +400,14 @@ mod tests {
b: Test b: Test
def test(self, a: int32) -> Test2: def test(self, a: int32) -> Test2:
return self.b return b
class Bar(Foo, 'FooBar'): class Bar(Foo, 'FooBar'):
def test2(self, a: list[Foo]) -> Test2: def test2(self, a: list[Foo]) -> Test2:
return self.b return b
def test3(self, a: list[FooBar2]) -> Test2: def test3(self, a: list[FooBar2]) -> Test2:
return self.b return b
" }) " })
.unwrap(); .unwrap();
let (mut classes, mut unknowns) = get_typenames(&ast.statements); let (mut classes, mut unknowns) = get_typenames(&ast.statements);
@ -485,19 +420,4 @@ mod tests {
assert_eq!(&classes, &["Bar", "Foo"]); assert_eq!(&classes, &["Bar", "Foo"]);
assert_eq!(&unknowns, &["FooBar", "FooBar2", "Test", "Test2"]); assert_eq!(&unknowns, &["FooBar", "FooBar2", "Test", "Test2"]);
} }
#[test]
fn test_assignment() {
let ast = parse_statement(indoc! {"
((a, b), c[i]) = core.foo(x, get_y())
" })
.unwrap();
let mut defined = Vec::new();
let mut unknowns = Vec::new();
get_stmt_unknowns(&mut defined, &mut unknowns, ast.as_slice());
defined.sort();
unknowns.sort();
assert_eq!(defined.as_slice(), &["a", "b"]);
assert_eq!(unknowns.as_slice(), &["c", "core", "get_y", "i", "x"]);
}
} }

View File

@ -12,23 +12,12 @@ Errors:
- Incorrect number of parameters - Incorrect number of parameters
Symbol Resolution: Symbol Resolution:
- Add all files with annotated class/functions.
- Find class references, load them all in TopLevelContext. - Find class references, load them all in TopLevelContext.
- Find unbounded identifiers in the functions. - Find unbounded identifiers/functions in functions.
- If it is a function/class name, record its object ID. - `inspect.getmodule(x)` every unknown `x` if not primitive/list of primitives,
- Otherwise, load its value. (check to see if specified with `global`) check their files recursively by getting their file path, cache with
(Function implemented in python, with rust binding to add value to global (normalized) path as key.
variable dictionary)
Global variable dictionary:
- Primitives, including integers, floats, bools, etc.
- Primitive lists.
- Numpy multi-dimensional array, with value + dimension vectors.
- Reference array, with integer index referring to other things.
- Symbol table: python id -> reference id.
TopLevelContext/InferenceContext: TopLevelContext/InferenceContext:
- Restrict visibility by user defined function. - Restrict visibility by user defined function.