diff --git a/Cargo.lock b/Cargo.lock index 61f75bb..1829427 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,9 +152,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "els" -version = "0.1.26" +version = "0.1.27-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad69bdb783d8f54317278b3d32b138b05fe0708c9a22454cd9505f39edf4d044" +checksum = "52d65a32e855c6093747f38e0c2d4049b0f38c4b74dea213bf5031b18ebca141" dependencies = [ "erg_common", "erg_compiler", @@ -177,18 +177,18 @@ dependencies = [ [[package]] name = "erg_common" -version = "0.6.14" +version = "0.6.15-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abef65c68abb0bbf94d43bdedddc44349ff02f8a21b510dedf66f4be24587a0c" +checksum = "0fa2ce07958c54ec955967e0008f0aaa016122c1ec18b30ba2ddeffa9f61b3f2" dependencies = [ "backtrace-on-stack-overflow", ] [[package]] name = "erg_compiler" -version = "0.6.14" +version = "0.6.15-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c82d01efbb07c5da0d5ee35ce6fc053e09512dca0275136e5cf2c07bd7ee43" +checksum = "e136c552b1707b4c9d158a636ab1a3f09e2c4dee6b5d511623998080ed6021f9" dependencies = [ "erg_common", "erg_parser", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "erg_parser" -version = "0.6.14" +version = "0.6.15-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b572d85a2a33d729a8dd03a655ee1c36b9e86f4e85deb22f9043542e4b8fb41f" +checksum = "ad991bc363694adf11d621278109ec82d5328e2191b7f369dcb66b78f85b413a" dependencies = [ "erg_common", "unicode-xid", diff --git a/Cargo.toml b/Cargo.toml index a2392f1..67afc36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ edition = "2021" repository = "https://github.com/mtshiba/pylyzer" [workspace.dependencies] -erg_common = { version = "0.6.14", features = ["py_compat", "els"] } -erg_compiler = { version = "0.6.14", features = ["py_compat", "els"] } -els = { version = "0.1.26", features = ["py_compat"] } +erg_common = { version = "0.6.15-nightly.0", features = ["py_compat", "els"] } +erg_compiler = { version = "0.6.15-nightly.0", features = ["py_compat", "els"] } +els = { version = "0.1.27-nightly.0", features = ["py_compat"] } rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.2.0", features = ["all-nodes-with-ranges", "location"] } rustpython-ast = { git = "https://github.com/RustPython/Parser", version = "0.2.0", features = ["all-nodes-with-ranges", "location"] } # erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] } diff --git a/crates/py2erg/convert.rs b/crates/py2erg/convert.rs index 8cad8a1..3a2a705 100644 --- a/crates/py2erg/convert.rs +++ b/crates/py2erg/convert.rs @@ -26,7 +26,9 @@ use rustpython_parser::ast::located::{ self as py_ast, Alias, Arg, Arguments, Boolop, Cmpop, ExprConstant, Keyword, Located, ModModule, Operator, Stmt, String, Suite, Unaryop, }; -use rustpython_parser::source_code::{SourceLocation as PyLocation, SourceRange as PySourceRange, OneIndexed}; +use rustpython_parser::source_code::{ + OneIndexed, SourceLocation as PyLocation, SourceRange as PySourceRange, +}; use crate::ast_util::accessor_name; use crate::error::*; @@ -383,10 +385,15 @@ impl ASTConverter { } fn convert_params(&mut self, params: Arguments) -> Params { - fn split_kwonlyargs(params: Arguments) -> (Vec, Vec<(Arg, py_ast::Expr)>) { + fn split_args(params: Arguments) -> (Vec, Vec<(Arg, py_ast::Expr)>) { let mut args = Vec::new(); let mut with_defaults = Vec::new(); - for arg in params.kwonlyargs.into_iter() { + for arg in params + .posonlyargs + .into_iter() + .chain(params.args.into_iter()) + .chain(params.kwonlyargs.into_iter()) + { if let Some(default) = arg.default { with_defaults.push((arg.def, *default)); } else { @@ -395,7 +402,7 @@ impl ASTConverter { } (args, with_defaults) } - let (non_defaults, defaults) = split_kwonlyargs(params); + let (non_defaults, defaults) = split_args(params); let non_defaults = non_defaults .into_iter() .map(|p| self.convert_nd_param(p)) @@ -1019,12 +1026,7 @@ impl ASTConverter { loc.row.get(), function.col_end().unwrap_or(0) + 1, ); - let rp = Token::new( - TokenKind::RParen, - ")", - loc.row.get(), - last_col + 1, - ); + let rp = Token::new(TokenKind::RParen, ")", loc.row.get(), last_col + 1); (lp, rp) }; let args = Args::new(pos_args, None, kw_args, Some(paren)); @@ -1143,8 +1145,9 @@ impl ASTConverter { } py_ast::Expr::Subscript(subs) => { let obj = self.convert_expr(*subs.value); - let method = - obj.attr_expr(self.convert_ident("__getitem__".to_string(), subs.slice.location())); + let method = obj.attr_expr( + self.convert_ident("__getitem__".to_string(), subs.slice.location()), + ); method.call1(self.convert_expr(*subs.slice)) } _other => { @@ -1573,7 +1576,13 @@ impl ASTConverter { py_ast::Stmt::AnnAssign(ann_assign) => { let anot = self.convert_expr(*ann_assign.annotation.clone()); let t_spec = self.convert_type_spec(*ann_assign.annotation); - let t_spec = TypeSpecWithOp::new(AS, t_spec, anot); + let as_op = Token::new( + TokenKind::As, + "as", + t_spec.ln_begin().unwrap_or(0), + t_spec.col_begin().unwrap_or(0), + ); + let t_spec = TypeSpecWithOp::new(as_op, t_spec, anot); match *ann_assign.target { py_ast::Expr::Name(name) => { if let Some(value) = ann_assign.value { @@ -1598,10 +1607,9 @@ impl ASTConverter { } py_ast::Expr::Attribute(attr) => { let loc = attr.location(); - let attr = self.convert_expr(*attr.value).attr(self.convert_attr_ident( - attr.attr.to_string(), - loc, - )); + let attr = self + .convert_expr(*attr.value) + .attr(self.convert_attr_ident(attr.attr.to_string(), loc)); if let Some(value) = ann_assign.value { let expr = self.convert_expr(*value); let redef = ReDef::new(attr, expr); @@ -1630,9 +1638,9 @@ impl ASTConverter { } py_ast::Expr::Attribute(attr) => { let attr_name_loc = attr.end_location().unwrap_or(attr.location()); - let attr = self - .convert_expr(*attr.value) - .attr(self.convert_attr_ident(attr.attr.to_string(), attr_name_loc)); + let attr = self.convert_expr(*attr.value).attr( + self.convert_attr_ident(attr.attr.to_string(), attr_name_loc), + ); let expr = self.convert_expr(*assign.value); let adef = ReDef::new(attr, expr); Expr::ReDef(adef) @@ -1670,9 +1678,9 @@ impl ASTConverter { Self::param_pattern_to_var(param.pat), param.t_spec, )); - let method = tmp_expr.clone().attr_expr( - self.convert_ident("__getitem__".to_string(), loc), - ); + let method = tmp_expr + .clone() + .attr_expr(self.convert_ident("__getitem__".to_string(), loc)); let tuple_acc = method.call1(Expr::Literal(index)); let body = DefBody::new(EQUAL, Block::new(vec![tuple_acc]), DefId(0)); @@ -1787,7 +1795,7 @@ impl ASTConverter { class_def.decorator_list, class_loc, ) - }, + } py_ast::Stmt::For(for_) => { let loc = for_.location(); let iter = self.convert_expr(*for_.iter); @@ -1887,9 +1895,7 @@ impl ASTConverter { let def = if let Some(alias) = name.asname { self.register_name_info(&alias, NameKind::Variable); let var = VarSignature::new( - VarPattern::Ident( - self.convert_ident(alias.to_string(), loc), - ), + VarPattern::Ident(self.convert_ident(alias.to_string(), loc)), None, ); Def::new( @@ -1916,15 +1922,12 @@ impl ASTConverter { // from module import foo, bar py_ast::Stmt::ImportFrom(import_from) => { let loc = import_from.location(); - self.convert_from_import( - import_from.module, - import_from.names, - loc, - ) - }, + self.convert_from_import(import_from.module, import_from.names, loc) + } py_ast::Stmt::Try(try_) => { let chunks = self.convert_block(try_.body, BlockKind::Try).into_iter(); - let dummy = chunks.chain(self.convert_block(try_.orelse, BlockKind::Try)) + let dummy = chunks + .chain(self.convert_block(try_.orelse, BlockKind::Try)) .chain(self.convert_block(try_.finalbody, BlockKind::Try)) .collect(); Expr::Dummy(Dummy::new(None, dummy)) diff --git a/crates/py2erg/error.rs b/crates/py2erg/error.rs index fd411b1..a402b9d 100644 --- a/crates/py2erg/error.rs +++ b/crates/py2erg/error.rs @@ -1,5 +1,5 @@ -use erg_common::config::Input; use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage}; +use erg_common::io::Input; use erg_common::switch_lang; use erg_compiler::error::CompileError; diff --git a/crates/py2erg/gen_decl.rs b/crates/py2erg/gen_decl.rs index f006722..0886567 100644 --- a/crates/py2erg/gen_decl.rs +++ b/crates/py2erg/gen_decl.rs @@ -1,7 +1,7 @@ use std::fs::File; use std::io::{BufWriter, Write}; -use erg_common::config::Input; +use erg_common::io::Input; use erg_common::log; use erg_compiler::context::register::{CheckStatus, PylyzerStatus}; use erg_compiler::hir::{Expr, HIR}; diff --git a/src/analyze.rs b/src/analyze.rs index 6f8e700..15125ea 100644 --- a/src/analyze.rs +++ b/src/analyze.rs @@ -8,36 +8,45 @@ use erg_compiler::artifact::{BuildRunnable, Buildable, CompleteArtifact, Incompl use erg_compiler::context::register::CheckStatus; use erg_compiler::context::ModuleContext; use erg_compiler::erg_parser::ast::{Module, AST}; -use erg_compiler::erg_parser::error::ParseErrors; +use erg_compiler::erg_parser::error::{ + CompleteArtifact as ParseArtifact, IncompleteArtifact as IncompleteParseArtifact, ParseErrors, +}; use erg_compiler::erg_parser::parse::Parsable; use erg_compiler::error::{CompileError, CompileErrors}; use erg_compiler::lower::ASTLowerer; use erg_compiler::module::SharedCompilerResource; use py2erg::{dump_decl_er, reserve_decl_er, ShadowingMode}; -use rustpython_ast::source_code::{LinearLocator}; -use rustpython_parser::{Parse, ParseErrorType}; +use rustpython_ast::source_code::RandomLocator; use rustpython_ast::{Fold, ModModule}; +use rustpython_parser::{Parse, ParseErrorType}; use crate::handle_err; pub struct SimplePythonParser {} impl Parsable for SimplePythonParser { - fn parse(code: String) -> Result { + fn parse(code: String) -> Result> { let py_program = ModModule::parse(&code, "").map_err(|_err| ParseErrors::empty())?; - let mut locator = LinearLocator::new(&code); - let py_program = locator.fold(py_program).map_err(|_err| ParseErrors::empty())?; + let mut locator = RandomLocator::new(&code); + // let mut locator = LinearLocator::new(&code); + let py_program = locator + .fold(py_program) + .map_err(|_err| ParseErrors::empty())?; let shadowing = if cfg!(feature = "debug") { ShadowingMode::Visible } else { ShadowingMode::Invisible }; let converter = py2erg::ASTConverter::new(ErgConfig::default(), shadowing); - let IncompleteArtifact{ object: Some(erg_module), errors, .. } = converter.convert_program(py_program) else { unreachable!() }; + let IncompleteArtifact{ object: Some(erg_module), errors, warns } = converter.convert_program(py_program) else { unreachable!() }; if errors.is_empty() { - Ok(erg_module) + Ok(ParseArtifact::new(erg_module, warns.into())) } else { - Err(ParseErrors::empty()) + Err(IncompleteParseArtifact::new( + Some(erg_module), + warns.into(), + errors.into(), + )) } } } @@ -114,7 +123,8 @@ impl PythonAnalyzer { ) -> Result { let filename = self.cfg.input.filename(); let py_program = ModModule::parse(&py_code, &filename).map_err(|err| { - let mut locator = LinearLocator::new(&py_code); + let mut locator = RandomLocator::new(&py_code); + // let mut locator = LinearLocator::new(&py_code); let err = locator.locate_error::<_, ParseErrorType>(err); let msg = err.to_string(); let loc = err.location.unwrap(); @@ -123,12 +133,18 @@ impl PythonAnalyzer { msg, 0, ErrorKind::SyntaxError, - erg_common::error::Location::range(loc.row.get(), loc.column.to_zero_indexed(), loc.row.get(), loc.column.to_zero_indexed()), + erg_common::error::Location::range( + loc.row.get(), + loc.column.to_zero_indexed(), + loc.row.get(), + loc.column.to_zero_indexed(), + ), ); let err = CompileError::new(core, self.cfg.input.clone(), "".into()); IncompleteArtifact::new(None, CompileErrors::from(err), CompileErrors::empty()) })?; - let mut locator = LinearLocator::new(&py_code); + let mut locator = RandomLocator::new(&py_code); + // let mut locator = LinearLocator::new(&py_code); let py_program = locator.fold(py_program).unwrap(); let shadowing = if cfg!(feature = "debug") { ShadowingMode::Visible @@ -165,7 +181,7 @@ impl PythonAnalyzer { } pub fn run(&mut self) { - if self.cfg.output_dir.is_some() { + if self.cfg.dist_dir.is_some() { reserve_decl_er(self.cfg.input.clone()); } let py_code = self.cfg.input.read(); @@ -179,13 +195,13 @@ impl PythonAnalyzer { artifact.warns.len(), self.cfg.input.unescaped_filename() ); - artifact.warns.fmt_all_stderr(); + artifact.warns.write_all_stderr(); } println!( "{GREEN}All checks OK{RESET}: {}", self.cfg.input.unescaped_filename() ); - if self.cfg.output_dir.is_some() { + if self.cfg.dist_dir.is_some() { dump_decl_er( self.cfg.input.clone(), artifact.object, @@ -202,7 +218,7 @@ impl PythonAnalyzer { artifact.warns.len(), self.cfg.input.unescaped_filename() ); - artifact.warns.fmt_all_stderr(); + artifact.warns.write_all_stderr(); } let code = if artifact.errors.is_empty() { println!( @@ -216,11 +232,11 @@ impl PythonAnalyzer { artifact.errors.len(), self.cfg.input.unescaped_filename() ); - artifact.errors.fmt_all_stderr(); + artifact.errors.write_all_stderr(); 1 }; // Even if type checking fails, some APIs are still valid, so generate a file - if self.cfg.output_dir.is_some() { + if self.cfg.dist_dir.is_some() { dump_decl_er( self.cfg.input.clone(), artifact.object.unwrap(), diff --git a/src/config.rs b/src/config.rs index 6451fc4..fd85ba8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,7 +2,8 @@ use std::env; use std::path::PathBuf; use std::str::FromStr; -use erg_common::config::{ErgConfig, ErgMode, Input}; +use erg_common::config::{ErgConfig, ErgMode}; +use erg_common::io::Input; use erg_common::switch_lang; fn command_message() -> &'static str { @@ -94,7 +95,7 @@ pub(crate) fn parse_args() -> ErgConfig { cfg.quiet_repl = true; } "--dump-decl" => { - cfg.output_dir = Some(""); + cfg.dist_dir = Some(""); } "--verbose" => { cfg.verbose = args diff --git a/tests/test.rs b/tests/test.rs index e785d7a..e87058f 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; -use erg_common::config::{ErgConfig, Input}; +use erg_common::config::ErgConfig; +use erg_common::io::Input; use erg_common::spawn::exec_new_thread; use erg_common::traits::Stream; use erg_compiler::artifact::{CompleteArtifact, IncompleteArtifact};