Update: generate type definition files even in errors

This commit is contained in:
Shunsuke Shibayama 2022-12-25 18:17:39 +09:00
parent d5485229cc
commit f0cf267da2
3 changed files with 42 additions and 18 deletions

6
Cargo.lock generated
View File

@ -227,7 +227,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_common" name = "erg_common"
version = "0.6.0-beta.4" version = "0.6.0-beta.4"
source = "git+https://github.com/erg-lang/erg?branch=main#46418987c1e6bf24baa774827cb1e4be8fe25b67" source = "git+https://github.com/erg-lang/erg?branch=main#1c607cfe5ba87b0dc37c4a3393629c023d85e317"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
@ -237,7 +237,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_compiler" name = "erg_compiler"
version = "0.6.0-beta.4" version = "0.6.0-beta.4"
source = "git+https://github.com/erg-lang/erg?branch=main#46418987c1e6bf24baa774827cb1e4be8fe25b67" source = "git+https://github.com/erg-lang/erg?branch=main#1c607cfe5ba87b0dc37c4a3393629c023d85e317"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_parser", "erg_parser",
@ -246,7 +246,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_parser" name = "erg_parser"
version = "0.6.0-beta.4" version = "0.6.0-beta.4"
source = "git+https://github.com/erg-lang/erg?branch=main#46418987c1e6bf24baa774827cb1e4be8fe25b67" source = "git+https://github.com/erg-lang/erg?branch=main#1c607cfe5ba87b0dc37c4a3393629c023d85e317"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"unicode-xid 0.2.4", "unicode-xid 0.2.4",

View File

@ -1,10 +1,26 @@
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use erg_common::log;
use erg_common::config::Input; use erg_common::config::Input;
use erg_compiler::hir::{HIR, Expr}; use erg_compiler::hir::{HIR, Expr};
use erg_compiler::ty::HasType; use erg_compiler::ty::HasType;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CheckStatus {
Succeed,
Failed,
}
impl CheckStatus {
pub const fn is_succeed(&self) -> bool {
matches!(self, CheckStatus::Succeed)
}
pub const fn is_failed(&self) -> bool {
matches!(self, CheckStatus::Failed)
}
}
pub struct DeclFile { pub struct DeclFile {
pub filename: String, pub filename: String,
pub code: String, pub code: String,
@ -14,8 +30,8 @@ fn escape_type(typ: String) -> String {
typ.replace('%', "Type_") typ.replace('%', "Type_")
} }
pub fn gen_decl_er(hir: HIR) -> DeclFile { pub fn gen_decl_er(hir: HIR, status: CheckStatus) -> DeclFile {
let mut code = "".to_string(); let mut code = if status.is_failed() { "# failed\n".to_string() } else { "# succeed\n".to_string() };
for chunk in hir.module.into_iter() { for chunk in hir.module.into_iter() {
match chunk { match chunk {
Expr::Def(def) => { Expr::Def(def) => {
@ -32,12 +48,13 @@ pub fn gen_decl_er(hir: HIR) -> DeclFile {
} }
code.push('\n'); code.push('\n');
} }
log!("code:\n{code}");
let filename = hir.name.replace(".py", ".d.er"); let filename = hir.name.replace(".py", ".d.er");
DeclFile { filename, code } DeclFile { filename, code }
} }
pub fn dump_decl_er(input: Input, hir: HIR) { pub fn dump_decl_er(input: Input, hir: HIR, status: CheckStatus) {
let file = gen_decl_er(hir); let file = gen_decl_er(hir, status);
let mut path = if let Input::File(path) = input { path } else { PathBuf::new() }; let mut path = if let Input::File(path) = input { path } else { PathBuf::new() };
path.pop(); path.pop();
path.push("__pycache__"); path.push("__pycache__");

View File

@ -1,4 +1,5 @@
use erg_common::traits::{Runnable, Stream}; use erg_common::traits::{Runnable, Stream};
use erg_common::style::{GREEN, BLUE, RED, YELLOW, RESET};
use erg_common::config::{ErgConfig}; use erg_common::config::{ErgConfig};
use erg_common::error::{MultiErrorDisplay, ErrorCore, ErrorKind}; use erg_common::error::{MultiErrorDisplay, ErrorCore, ErrorKind};
use erg_compiler::artifact::{BuildRunnable, CompleteArtifact, IncompleteArtifact, Buildable}; use erg_compiler::artifact::{BuildRunnable, CompleteArtifact, IncompleteArtifact, Buildable};
@ -6,7 +7,7 @@ use erg_compiler::context::Context;
use erg_compiler::erg_parser::ast::AST; use erg_compiler::erg_parser::ast::AST;
use erg_compiler::error::{CompileErrors, CompileError}; use erg_compiler::error::{CompileErrors, CompileError};
use erg_compiler::lower::ASTLowerer; use erg_compiler::lower::ASTLowerer;
use py2erg::ShadowingMode; use py2erg::{CheckStatus, ShadowingMode};
use py2erg::dump_decl_er; use py2erg::dump_decl_er;
use rustpython_parser::parser; use rustpython_parser::parser;
@ -118,33 +119,39 @@ impl PythonAnalyzer {
pub fn run(&mut self) { pub fn run(&mut self) {
let filename = self.cfg.input.filename(); let filename = self.cfg.input.filename();
let py_code = self.cfg.input.read(); let py_code = self.cfg.input.read();
println!("Start checking: {filename}"); println!("{BLUE}Start checking{RESET}: {filename}");
match self.analyze(py_code, "exec") { match self.analyze(py_code, "exec") {
Ok(artifact) => { Ok(artifact) => {
if !artifact.warns.is_empty() { if !artifact.warns.is_empty() {
println!("Found warnings: {}", artifact.warns.len()); println!("{YELLOW}Found {} warnings{RESET}: {}", artifact.warns.len(), self.cfg.input.filename());
artifact.warns.fmt_all_stderr(); artifact.warns.fmt_all_stderr();
} }
println!("All checks OK."); println!("{GREEN}All checks OK{RESET}: {}", self.cfg.input.filename());
if self.cfg.output_dir.is_some() { if self.cfg.output_dir.is_some() {
dump_decl_er(self.cfg.input.clone(), artifact.object); dump_decl_er(self.cfg.input.clone(), artifact.object, CheckStatus::Succeed);
println!("A declaration file has been generated to __pycache__ directory."); println!("A declaration file has been generated to __pycache__ directory.");
} }
std::process::exit(0); std::process::exit(0);
} }
Err(artifact) => { Err(artifact) => {
if !artifact.warns.is_empty() { if !artifact.warns.is_empty() {
println!("Found warnings: {}", artifact.warns.len()); println!("{YELLOW}Found {} warnings{RESET}: {}", artifact.warns.len(), self.cfg.input.filename());
artifact.warns.fmt_all_stderr(); artifact.warns.fmt_all_stderr();
} }
if artifact.errors.is_empty() { let code = if artifact.errors.is_empty() {
println!("All checks OK."); println!("{GREEN}All checks OK{RESET}: {}", self.cfg.input.filename());
std::process::exit(0); 0
} else { } else {
println!("Found errors: {}", artifact.errors.len()); println!("{RED}Found {} errors{RESET}: {}", artifact.errors.len(), self.cfg.input.filename());
artifact.errors.fmt_all_stderr(); artifact.errors.fmt_all_stderr();
std::process::exit(1); 1
};
// Even if type checking fails, some APIs are still valid, so generate a file
if self.cfg.output_dir.is_some() {
dump_decl_er(self.cfg.input.clone(), artifact.object.unwrap(), CheckStatus::Failed);
println!("A declaration file has been generated to __pycache__ directory.");
} }
std::process::exit(code);
} }
} }
} }