Skip to content

Commit

Permalink
feat: support slice
Browse files Browse the repository at this point in the history
  • Loading branch information
mtshiba committed Jun 16, 2024
1 parent 91427c6 commit a088185
Show file tree
Hide file tree
Showing 11 changed files with 539 additions and 209 deletions.
532 changes: 385 additions & 147 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ edition = "2021"
repository = "https://github.com/mtshiba/pylyzer"

[workspace.dependencies]
erg_common = { version = "0.6.36-nightly.2", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.36-nightly.2", features = ["py_compat", "els"] }
els = { version = "0.1.48-nightly.2", features = ["py_compat"] }
erg_common = { version = "0.6.39-nightly.0", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.39-nightly.0", features = ["py_compat", "els"] }
els = { version = "0.1.51-nightly.0", features = ["py_compat"] }
# rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
# rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] }
rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.3.1", features = ["all-nodes-with-ranges", "location"] }
Expand Down
80 changes: 65 additions & 15 deletions crates/py2erg/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ use erg_common::traits::{Locational, Stream};
use erg_common::{log, set};
use erg_compiler::artifact::IncompleteArtifact;
use erg_compiler::erg_parser::ast::{
Accessor, Args, List, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstAccessor, ConstArgs,
Accessor, Args, BinOp, Block, ClassAttr, ClassAttrs, ClassDef, ConstAccessor, ConstArgs,
ConstAttribute, ConstDict, ConstExpr, ConstKeyValue, ConstPosArg, Decorator, Def, DefBody,
DefId, DefaultParamSignature, Dict, Dummy, Expr, Identifier, KeyValue, KwArg, Lambda,
LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature, NormalList, NormalDict,
NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamTySpec, Params, PosArg,
PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, Signature, SubrSignature, SubrTypeSpec,
Tuple, TupleTypeSpec, TypeAscription, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp,
VarName, VarPattern, VarRecordAttr, VarRecordAttrs, VarRecordPattern, VarSignature,
VisModifierSpec, ListComprehension, SetComprehension,
LambdaSignature, List, ListComprehension, Literal, Methods, Module, NonDefaultParamSignature,
NormalDict, NormalList, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamTySpec,
Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, SetComprehension, Signature,
SubrSignature, SubrTypeSpec, Tuple, TupleTypeSpec, TypeAscription, TypeBoundSpecs, TypeSpec,
TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarRecordAttrs, VarRecordPattern,
VarSignature, VisModifierSpec,
};
use erg_compiler::erg_parser::desugar::Desugarer;
use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL};
Expand Down Expand Up @@ -102,6 +102,7 @@ fn escape_name(name: String) -> String {
"bool" => "Bool".into(),
"list" => "GenericList".into(),
"bytes" => "Bytes".into(),
"bytearray" => "ByteArray!".into(),
// "range" => "GenericRange".into(),
"dict" => "GenericDict".into(),
"set" => "GenericSet".into(),
Expand Down Expand Up @@ -453,7 +454,9 @@ impl ASTConverter {

fn convert_params(&mut self, params: Arguments) -> Params {
#[allow(clippy::type_complexity)]
fn split_args(params: Arguments) -> (Vec<Arg>, Option<Arg>, Vec<(Arg, py_ast::Expr)>, Option<Arg>) {
fn split_args(
params: Arguments,
) -> (Vec<Arg>, Option<Arg>, Vec<(Arg, py_ast::Expr)>, Option<Arg>) {
let mut args = Vec::new();
let mut with_defaults = Vec::new();
let var_args = params.vararg.map(|x| *x);
Expand Down Expand Up @@ -796,7 +799,10 @@ impl ASTConverter {
global,
Identifier::private("List!".into()),
));
TypeSpec::poly(acc, ConstArgs::new(vec![elem_t, len], None, vec![], None, None))
TypeSpec::poly(
acc,
ConstArgs::new(vec![elem_t, len], None, vec![], None, None),
)
}
"dict" => {
let py_ast::Expr::Tuple(mut tuple) = args else {
Expand Down Expand Up @@ -924,7 +930,11 @@ impl ASTConverter {
};
let (line_end, c_end) = (
expr_range.end.unwrap_or(expr_range.start).row.get(),
expr_range.end.unwrap_or(expr_range.start).column.to_zero_indexed(),
expr_range
.end
.unwrap_or(expr_range.start)
.column
.to_zero_indexed(),
);
let l_brace = Token::new(
l_kind,
Expand Down Expand Up @@ -1168,7 +1178,13 @@ impl ASTConverter {
.next()
.map(|ex| self.convert_expr(ex));
let generators = vec![(ident, iter)];
let arr = Expr::List(List::Comprehension(ListComprehension::new(l_sqbr, r_sqbr, Some(layout), generators, guard)));
let arr = Expr::List(List::Comprehension(ListComprehension::new(
l_sqbr,
r_sqbr,
Some(layout),
generators,
guard,
)));
Self::mutate_expr(arr)
}
py_ast::Expr::Set(set) => {
Expand Down Expand Up @@ -1199,7 +1215,13 @@ impl ASTConverter {
.next()
.map(|ex| self.convert_expr(ex));
let generators = vec![(ident, iter)];
Expr::Set(Set::Comprehension(SetComprehension::new(l_brace, r_brace, Some(layout), generators, guard)))
Expr::Set(Set::Comprehension(SetComprehension::new(
l_brace,
r_brace,
Some(layout),
generators,
guard,
)))
// Self::mutate_expr(set)
}
py_ast::Expr::Dict(dict) => {
Expand Down Expand Up @@ -1235,6 +1257,24 @@ impl ASTConverter {
);
method.call1(self.convert_expr(*subs.slice))
}
py_ast::Expr::Slice(slice) => {
let loc = slice.location();
let start = slice.lower.map(|ex| self.convert_expr(*ex));
let stop = slice.upper.map(|ex| self.convert_expr(*ex));
let step = slice.step.map(|ex| self.convert_expr(*ex));
let mut args = Args::empty();
if let Some(start) = start {
args.push_pos(PosArg::new(start));
}
if let Some(stop) = stop {
args.push_pos(PosArg::new(stop));
}
if let Some(step) = step {
args.push_pos(PosArg::new(step));
}
let slice = self.convert_ident("slice".to_string(), loc);
slice.call(args).into()
}
_other => {
log!(err "unimplemented: {:?}", _other);
Expr::Dummy(Dummy::new(None, vec![]))
Expand Down Expand Up @@ -1302,14 +1342,18 @@ impl ASTConverter {
init_def.ln_end().unwrap_or(0),
init_def.col_end().unwrap_or(0),
);
let Signature::Subr(sig) = init_def.sig else { unreachable!() };
let Signature::Subr(sig) = init_def.sig else {
unreachable!()
};
let mut fields = vec![];
let mut params = vec![];
for chunk in init_def.body.block {
#[allow(clippy::single_match)]
match chunk {
Expr::ReDef(redef) => {
let Accessor::Attr(attr) = redef.attr else { continue; };
let Accessor::Attr(attr) = redef.attr else {
continue;
};
// if `self.foo == ...`
if attr.obj.get_name().map(|s| &s[..]) == Some("self") {
let (param_typ_name, arg_typ_name) = if let Some(t_spec_op) = sig
Expand Down Expand Up @@ -1517,7 +1561,13 @@ impl ASTConverter {
let class_as_expr = Expr::Accessor(Accessor::Ident(ident));
let (base_type, attrs) = self.extract_method(body, inherit);
self.block_id_counter += 1;
let methods = Methods::new(DefId(self.block_id_counter), class, class_as_expr, VisModifierSpec::Public(DOT), attrs);
let methods = Methods::new(
DefId(self.block_id_counter),
class,
class_as_expr,
VisModifierSpec::Public(DOT),
attrs,
);
(base_type, vec![methods])
}

Expand Down
24 changes: 18 additions & 6 deletions crates/py2erg/gen_decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use std::io::{BufWriter, Write};
use std::path::Path;

use erg_common::io::Input;
use erg_common::log;
use erg_common::pathutil::mod_name;
use erg_common::set::Set;
use erg_common::traits::LimitedDisplay;
use erg_common::{log, Str};
use erg_compiler::build_package::{CheckStatus, PylyzerStatus};
use erg_compiler::hir::{Expr, HIR, ClassDef};
use erg_compiler::hir::{ClassDef, Expr, HIR};
use erg_compiler::ty::value::{GenTypeObj, TypeObj};
use erg_compiler::ty::{HasType, Type};

Expand All @@ -23,6 +24,7 @@ fn escape_type(typ: String) -> String {
pub struct DeclFileGenerator {
filename: String,
namespace: String,
imported: Set<Str>,
code: String,
}

Expand All @@ -44,6 +46,7 @@ impl DeclFileGenerator {
Self {
filename: input.filename().replace(".py", ".d.er"),
namespace: "".to_string(),
imported: Set::new(),
code,
}
}
Expand Down Expand Up @@ -77,10 +80,19 @@ impl DeclFileGenerator {
name = name.split('.').next().unwrap().to_string();
let full_path_str = ref_t.typarams()[0].to_string_unabbreviated();
let mod_name = mod_name(Path::new(full_path_str.trim_matches('"')));
format!(
"{}.{name} = pyimport \"{mod_name}\"",
self.namespace,
)
let imported = if self.imported.insert(mod_name.clone()) {
format!("{}.{mod_name} = pyimport \"{mod_name}\"", self.namespace)
} else {
"".to_string()
};
if self.imported.insert(name.clone().into()) {
format!(
"{}.{name} = pyimport \"{mod_name}\"\n{imported}",
self.namespace,
)
} else {
imported
}
} else {
format!("{}.{name}: {typ}", self.namespace)
};
Expand Down
70 changes: 48 additions & 22 deletions src/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ use erg_common::config::ErgConfig;
use erg_common::error::{ErrorCore, ErrorKind, MultiErrorDisplay};
use erg_common::style::colors::{BLUE, GREEN, RED, YELLOW};
use erg_common::style::RESET;
use erg_common::traits::{New, ExitStatus, Runnable, Stream};
use erg_common::traits::{ExitStatus, New, Runnable, Stream};
use erg_common::Str;
use erg_compiler::GenericHIRBuilder;
use erg_compiler::artifact::{BuildRunnable, Buildable, CompleteArtifact, IncompleteArtifact};
use erg_compiler::build_package::{CheckStatus, GenericPackageBuilder};
use erg_compiler::context::ModuleContext;
use erg_compiler::erg_parser::ast::{Module, AST};
use erg_compiler::erg_parser::build_ast::ASTBuildable;
use erg_compiler::erg_parser::error::{
CompleteArtifact as ParseArtifact, IncompleteArtifact as IncompleteParseArtifact, ParseErrors, ParserRunnerErrors,
CompleteArtifact as ParseArtifact, IncompleteArtifact as IncompleteParseArtifact, ParseErrors,
ParserRunnerErrors,
};
use erg_compiler::erg_parser::parse::Parsable;
use erg_compiler::error::{CompileError, CompileErrors};
use erg_compiler::module::SharedCompilerResource;
use erg_compiler::GenericHIRBuilder;
use py2erg::{dump_decl_er, reserve_decl_er, ShadowingMode};
use rustpython_ast::source_code::{RandomLocator, SourceRange};
use rustpython_ast::{Fold, ModModule};
Expand All @@ -32,9 +33,7 @@ impl Parsable for SimplePythonParser {
fn parse(code: String) -> Result<ParseArtifact, IncompleteParseArtifact<Module, ParseErrors>> {
let mut slf = Self::new(ErgConfig::string(code.clone()));
slf.build_ast(code)
.map(|art| {
ParseArtifact::new(art.ast.module, art.warns.into())
})
.map(|art| ParseArtifact::new(art.ast.module, art.warns.into()))
.map_err(|iart| {
IncompleteParseArtifact::new(
iart.ast.map(|art| art.module),
Expand All @@ -55,7 +54,10 @@ impl ASTBuildable for SimplePythonParser {
fn build_ast(
&mut self,
code: String,
) -> Result<ParseArtifact<AST, ParserRunnerErrors>, IncompleteParseArtifact<AST, ParserRunnerErrors>> {
) -> Result<
ParseArtifact<AST, ParserRunnerErrors>,
IncompleteParseArtifact<AST, ParserRunnerErrors>,
> {
let filename = self.cfg.input.filename();
let py_program = self.parse_py_code(code)?;
let shadowing = if cfg!(feature = "debug") {
Expand All @@ -64,7 +66,14 @@ impl ASTBuildable for SimplePythonParser {
ShadowingMode::Invisible
};
let converter = py2erg::ASTConverter::new(ErgConfig::default(), shadowing);
let IncompleteArtifact{ object: Some(erg_module), errors, warns } = converter.convert_program(py_program) else { unreachable!() };
let IncompleteArtifact {
object: Some(erg_module),
errors,
warns,
} = converter.convert_program(py_program)
else {
unreachable!()
};
let erg_ast = AST::new(erg_common::Str::rc(&filename), erg_module);
if errors.is_empty() {
Ok(ParseArtifact::new(erg_ast, warns.into()))
Expand All @@ -79,7 +88,10 @@ impl ASTBuildable for SimplePythonParser {
}

impl SimplePythonParser {
pub fn parse_py_code(&self, code: String) -> Result<ModModule<SourceRange>, IncompleteParseArtifact<AST, ParserRunnerErrors>>{
pub fn parse_py_code(
&self,
code: String,
) -> Result<ModModule<SourceRange>, IncompleteParseArtifact<AST, ParserRunnerErrors>> {
let py_program = ModModule::parse(&code, "<stdin>").map_err(|err| {
let mut locator = RandomLocator::new(&code);
// let mut locator = LinearLocator::new(&py_code);
Expand All @@ -99,7 +111,11 @@ impl SimplePythonParser {
),
);
let err = CompileError::new(core, self.cfg.input.clone(), "".into());
IncompleteParseArtifact::new(None, ParserRunnerErrors::from(err), ParserRunnerErrors::empty())
IncompleteParseArtifact::new(
None,
ParserRunnerErrors::from(err),
ParserRunnerErrors::empty(),
)
})?;
let mut locator = RandomLocator::new(&code);
// let mut locator = LinearLocator::new(&code);
Expand All @@ -118,7 +134,8 @@ pub struct PythonAnalyzer {

impl New for PythonAnalyzer {
fn new(cfg: ErgConfig) -> Self {
let checker = GenericPackageBuilder::new(cfg.clone(), SharedCompilerResource::new(cfg.clone()));
let checker =
GenericPackageBuilder::new(cfg.clone(), SharedCompilerResource::new(cfg.clone()));
Self { checker, cfg }
}
}
Expand Down Expand Up @@ -173,7 +190,8 @@ impl Buildable for PythonAnalyzer {
&mut self,
ast: AST,
mode: &str,
) -> Result<CompleteArtifact<erg_compiler::hir::HIR>, IncompleteArtifact<erg_compiler::hir::HIR>> {
) -> Result<CompleteArtifact<erg_compiler::hir::HIR>, IncompleteArtifact<erg_compiler::hir::HIR>>
{
self.check(ast, CompileErrors::empty(), CompileErrors::empty(), mode)
}
fn pop_context(&mut self) -> Option<ModuleContext> {
Expand All @@ -191,7 +209,13 @@ impl PythonAnalyzer {
New::new(cfg)
}

fn check(&mut self, erg_ast: AST, mut errors: CompileErrors, mut warns: CompileErrors, mode: &str) -> Result<CompleteArtifact, IncompleteArtifact> {
fn check(
&mut self,
erg_ast: AST,
mut errors: CompileErrors,
mut warns: CompileErrors,
mode: &str,
) -> Result<CompleteArtifact, IncompleteArtifact> {
match self.checker.build_from_ast(erg_ast, mode) {
Ok(mut artifact) => {
artifact.warns.extend(warns);
Expand Down Expand Up @@ -224,21 +248,23 @@ impl PythonAnalyzer {
) -> Result<CompleteArtifact, IncompleteArtifact> {
let filename = self.cfg.input.filename();
let parser = SimplePythonParser::new(self.cfg.copy());
let py_program = parser.parse_py_code(py_code)
.map_err(|iart| {
IncompleteArtifact::new(
None,
iart.errors.into(),
iart.warns.into(),
)
})?;
let py_program = parser
.parse_py_code(py_code)
.map_err(|iart| IncompleteArtifact::new(None, iart.errors.into(), iart.warns.into()))?;
let shadowing = if cfg!(feature = "debug") {
ShadowingMode::Visible
} else {
ShadowingMode::Invisible
};
let converter = py2erg::ASTConverter::new(self.cfg.copy(), shadowing);
let IncompleteArtifact{ object: Some(erg_module), errors, warns } = converter.convert_program(py_program) else { unreachable!() };
let IncompleteArtifact {
object: Some(erg_module),
errors,
warns,
} = converter.convert_program(py_program)
else {
unreachable!()
};
let erg_ast = AST::new(erg_common::Str::rc(&filename), erg_module);
erg_common::log!("AST:\n{erg_ast}");
self.check(erg_ast, errors, warns, mode)
Expand Down
5 changes: 2 additions & 3 deletions src/copy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::fs::{copy, create_dir_all, read_dir};
use std::path::Path;
use std::fs::{copy, read_dir, create_dir_all};

use erg_common::env::{erg_path, python_site_packages};

Expand Down Expand Up @@ -31,8 +31,7 @@ pub(crate) fn copy_dot_erg() {
for site_packages in python_site_packages() {
if site_packages.join(".erg").exists() {
println!("Copying site-package/.erg to {}", erg_path().display());
copy_dir(site_packages.join(".erg"), erg_path())
.expect("Failed to copy .erg");
copy_dir(site_packages.join(".erg"), erg_path()).expect("Failed to copy .erg");
}
}
}
Loading

0 comments on commit a088185

Please sign in to comment.