add some error message, try to write test using test case

This commit is contained in:
ychenfo 2021-07-26 17:30:48 +08:00
parent 123c5cf903
commit e631e4997b
4 changed files with 58 additions and 11 deletions

14
Cargo.lock generated
View File

@ -387,6 +387,7 @@ dependencies = [
"num-bigint 0.3.2", "num-bigint 0.3.2",
"num-traits", "num-traits",
"rustpython-parser", "rustpython-parser",
"test-case",
] ]
[[package]] [[package]]
@ -825,6 +826,19 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "test-case"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b114ece25254e97bf48dd4bfc2a12bad0647adacfe4cae1247a9ca6ad302cec"
dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]] [[package]]
name = "tiny-keccak" name = "tiny-keccak"
version = "2.0.2" version = "2.0.2"

View File

@ -11,3 +11,6 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", feat
rustpython-parser = { git = "https://github.com/RustPython/RustPython", branch = "master" } rustpython-parser = { git = "https://github.com/RustPython/RustPython", branch = "master" }
indoc = "1.0" indoc = "1.0"
[dev-dependencies]
test-case = "1.2.0"
indoc = "1.0"

View File

@ -1,6 +1,9 @@
#![warn(clippy::all)] #![warn(clippy::all)]
#![allow(clippy::clone_double_ref)] #![allow(clippy::clone_double_ref)]
#[cfg(test)]
extern crate test_case;
extern crate num_bigint; extern crate num_bigint;
extern crate inkwell; extern crate inkwell;
extern crate rustpython_parser; extern crate rustpython_parser;

View File

@ -22,14 +22,14 @@ impl<'a> ast::fold::Fold<()> for TypeInferencer<'a> {
fn fold_expr(&mut self, node: ast::Expr<()>) -> Result<ast::Expr<Self::TargetU>, Self::Error> { fn fold_expr(&mut self, node: ast::Expr<()>) -> Result<ast::Expr<Self::TargetU>, Self::Error> {
self.error_stack.push((node.node.name().into(), node.location)); self.error_stack.push(("Checking ".to_string() + node.node.name(), node.location));
let expr = match &node.node { let expr = match &node.node {
ast::ExprKind::ListComp { .. } => return self.fold_listcomp(node), ast::ExprKind::ListComp { .. } => return self.fold_listcomp(node),
_ => rustpython_parser::ast::fold::fold_expr(self, node)? _ => rustpython_parser::ast::fold::fold_expr(self, node)?
}; };
Ok(ast::Expr { let ret = Ok(ast::Expr {
// compute type info and store in the custom field // compute type info and store in the custom field
custom: match &expr.node { custom: match &expr.node {
ast::ExprKind::Constant {value, kind: _} => self.infer_constant(value), ast::ExprKind::Constant {value, kind: _} => self.infer_constant(value),
@ -50,7 +50,9 @@ impl<'a> ast::fold::Fold<()> for TypeInferencer<'a> {
}?, }?,
location: expr.location, location: expr.location,
node: expr.node node: expr.node
}) });
self.error_stack.pop();
ret
} }
} }
@ -320,7 +322,7 @@ impl<'a> TypeInferencer<'a> {
// some pre-folds need special handling // some pre-folds need special handling
fn fold_listcomp(&mut self, expr: ast::Expr<()>) -> Result<ast::Expr<Option<Type>>, String> { fn fold_listcomp(&mut self, expr: ast::Expr<()>) -> Result<ast::Expr<Option<Type>>, String> {
self.error_stack.push(("folding list comprehension at ".into(), expr.location)); self.error_stack.push(("list comprehension at ".into(), expr.location));
if let ast::Expr { if let ast::Expr {
location, location,
@ -343,7 +345,7 @@ impl<'a> TypeInferencer<'a> {
is_async} = gen; is_async} = gen;
let iter_folded = Box::new(self.fold_expr(*iter)?); let iter_folded = Box::new(self.fold_expr(*iter)?);
if let TypeEnum::ParametricType( let ret = if let TypeEnum::ParametricType(
primitives::LIST_TYPE, primitives::LIST_TYPE,
ls) = iter_folded ls) = iter_folded
.custom .custom
@ -390,14 +392,17 @@ impl<'a> TypeInferencer<'a> {
result result
} else { } else {
Err("iteration is supported for list only".into()) Err("iteration is supported for list only".into())
} };
self.error_stack.pop();
ret
} else { } else {
panic!("this function is for list comprehensions only!"); panic!("this function is for list comprehensions only!");
} }
} }
fn infer_simple_binding<T>(&mut self, name: &ast::Expr<T>, ty: Type) -> Result<(), String> { fn infer_simple_binding<T>(&mut self, name: &ast::Expr<T>, ty: Type) -> Result<(), String> {
match &name.node { self.error_stack.push(("resolving list comprehension variables".into(), name.location));
let ret = match &name.node {
ast::ExprKind::Name {id, ctx: _} => { ast::ExprKind::Name {id, ctx: _} => {
if id == "_" { if id == "_" {
Ok(()) Ok(())
@ -424,7 +429,9 @@ impl<'a> TypeInferencer<'a> {
} }
} }
_ => Err("not supported".into()) _ => Err("not supported".into())
} };
self.error_stack.pop();
ret
} }
fn fold_expr(&mut self, node: ast::Expr<()>) -> Result<ast::Expr<Option<Type>>, String> { fn fold_expr(&mut self, node: ast::Expr<()>) -> Result<ast::Expr<Option<Type>>, String> {
@ -437,10 +444,14 @@ impl<'a> TypeInferencer<'a> {
} }
} }
pub mod test { pub mod test {
use std::vec;
use crate::typecheck::{symbol_resolver::SymbolResolver, symbol_resolver::*, location::*}; use crate::typecheck::{symbol_resolver::SymbolResolver, symbol_resolver::*, location::*};
use rustpython_parser::ast::Expr; use rustpython_parser::ast::Expr;
use test_case::test_case; // FIXME
use super::*; use super::*;
pub fn new_ctx<'a>() -> TypeInferencer<'a> { pub fn new_ctx<'a>() -> TypeInferencer<'a> {
@ -626,7 +637,7 @@ pub mod test {
); );
} }
#[test] #[test]
fn test_mix() { fn test_mix() {
let mut inf = new_ctx(); let mut inf = new_ctx();
let ast1 = rustpython_parser::parser::parse_expression("False == [True or True, False][0]").unwrap(); let ast1 = rustpython_parser::parser::parse_expression("False == [True or True, False][0]").unwrap();
@ -642,7 +653,7 @@ pub mod test {
let ast11 = rustpython_parser::parser::parse_expression("(1, 2, 3, 4)[1]").unwrap(); let ast11 = rustpython_parser::parser::parse_expression("(1, 2, 3, 4)[1]").unwrap();
let ast12 = rustpython_parser::parser::parse_expression("(1, True, 3, False)[1]").unwrap(); let ast12 = rustpython_parser::parser::parse_expression("(1, True, 3, False)[1]").unwrap();
let ast13 = rustpython_parser::parser::parse_expression("[1, True, 2]").unwrap(); // let ast13 = rustpython_parser::parser::parse_expression("[1, True, 2]").unwrap();
let folded = inf.fold_expr(ast1).unwrap(); let folded = inf.fold_expr(ast1).unwrap();
let folded_2 = inf.fold_expr(ast2).unwrap(); let folded_2 = inf.fold_expr(ast2).unwrap();
@ -670,6 +681,22 @@ pub mod test {
println!("{:?}", folded_10.custom); println!("{:?}", folded_10.custom);
println!("{:?}", folded_11.custom); println!("{:?}", folded_11.custom);
println!("{:?}", folded_12.custom); println!("{:?}", folded_12.custom);
let folded_13 = inf.fold_expr(ast13); // let folded_13 = inf.fold_expr(ast13);
}
#[test]
fn test_err_msg() {
let mut inf = new_ctx();
for prog in vec![
"[1, True, 2]",
"True if 1 else False",
"1 if True else False",
] {
let ast = rustpython_parser::parser::parse_expression(prog).unwrap();
let _folded = inf.fold_expr(ast);
println!("");
}
// println!("{:?}", folded);
} }
} }