mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 04:09:05 +00:00
Merge branch 'main' into pr/320
This commit is contained in:
commit
924b22a171
91 changed files with 1836 additions and 1027 deletions
|
@ -10,7 +10,7 @@ use erg_parser::build_ast::ASTBuilder;
|
|||
use crate::artifact::{BuildRunnable, Buildable, CompleteArtifact, IncompleteArtifact};
|
||||
use crate::context::{Context, ContextProvider, ModuleContext};
|
||||
use crate::effectcheck::SideEffectChecker;
|
||||
use crate::error::{CompileError, CompileErrors};
|
||||
use crate::error::{CompileError, CompileErrors, LowerWarnings};
|
||||
use crate::lower::ASTLowerer;
|
||||
use crate::module::SharedCompilerResource;
|
||||
use crate::ownercheck::OwnershipChecker;
|
||||
|
@ -66,18 +66,26 @@ impl Runnable for HIRBuilder {
|
|||
|
||||
fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
|
||||
let mut builder = ASTBuilder::new(self.cfg().copy());
|
||||
let ast = builder.build(self.cfg_mut().input.read())?;
|
||||
let artifact = self.check(ast, "exec").map_err(|arti| arti.errors)?;
|
||||
artifact.warns.fmt_all_stderr();
|
||||
let artifact = builder
|
||||
.build(self.cfg_mut().input.read())
|
||||
.map_err(|arti| arti.errors)?;
|
||||
artifact.warns.write_all_stderr();
|
||||
let artifact = self
|
||||
.check(artifact.ast, "exec")
|
||||
.map_err(|arti| arti.errors)?;
|
||||
artifact.warns.write_all_stderr();
|
||||
println!("{}", artifact.object);
|
||||
Ok(ExitStatus::compile_passed(artifact.warns.len()))
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, Self::Errs> {
|
||||
let mut builder = ASTBuilder::new(self.cfg().copy());
|
||||
let ast = builder.build(src)?;
|
||||
let artifact = self.check(ast, "eval").map_err(|arti| arti.errors)?;
|
||||
artifact.warns.fmt_all_stderr();
|
||||
let artifact = builder.build(src).map_err(|arti| arti.errors)?;
|
||||
artifact.warns.write_all_stderr();
|
||||
let artifact = self
|
||||
.check(artifact.ast, "eval")
|
||||
.map_err(|arti| arti.errors)?;
|
||||
artifact.warns.write_all_stderr();
|
||||
Ok(artifact.object.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -148,10 +156,13 @@ impl HIRBuilder {
|
|||
mode: &str,
|
||||
) -> Result<CompleteArtifact, IncompleteArtifact> {
|
||||
let mut ast_builder = ASTBuilder::new(self.cfg().copy());
|
||||
let ast = ast_builder.build(src).map_err(|errs| {
|
||||
IncompleteArtifact::new(None, CompileErrors::from(errs), CompileErrors::empty())
|
||||
})?;
|
||||
self.check(ast, mode)
|
||||
let artifact = ast_builder
|
||||
.build(src)
|
||||
.map_err(|iart| IncompleteArtifact::new(None, iart.errors.into(), iart.warns.into()))?;
|
||||
self.lowerer
|
||||
.warns
|
||||
.extend(LowerWarnings::from(artifact.warns));
|
||||
self.check(artifact.ast, mode)
|
||||
}
|
||||
|
||||
pub fn pop_mod_ctx(&mut self) -> Option<ModuleContext> {
|
||||
|
|
|
@ -7,9 +7,10 @@ use std::process;
|
|||
use crate::ty::codeobj::{CodeObj, CodeObjFlags, MakeFunctionFlags};
|
||||
use crate::ty::value::GenTypeObj;
|
||||
use erg_common::cache::CacheSet;
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::config::ErgConfig;
|
||||
use erg_common::env::erg_std_path;
|
||||
use erg_common::error::{ErrorDisplay, Location};
|
||||
use erg_common::io::Input;
|
||||
use erg_common::opcode::{CommonOpcode, CompareOp};
|
||||
use erg_common::opcode308::Opcode308;
|
||||
use erg_common::opcode310::Opcode310;
|
||||
|
@ -646,8 +647,8 @@ impl PyCodeGenerator {
|
|||
}
|
||||
StoreLoadKind::Local | StoreLoadKind::LocalConst => match acc_kind {
|
||||
Name => LOAD_NAME as u8,
|
||||
Attr => LOAD_ATTR as u8,
|
||||
Method => LOAD_METHOD as u8,
|
||||
UnboundAttr => LOAD_ATTR as u8,
|
||||
BoundAttr => LOAD_METHOD as u8,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -669,9 +670,9 @@ impl PyCodeGenerator {
|
|||
StoreLoadKind::Local | StoreLoadKind::LocalConst => {
|
||||
match acc_kind {
|
||||
Name => STORE_NAME as u8,
|
||||
Attr => STORE_ATTR as u8,
|
||||
UnboundAttr => STORE_ATTR as u8,
|
||||
// cannot overwrite methods directly
|
||||
Method => STORE_ATTR as u8,
|
||||
BoundAttr => STORE_ATTR as u8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -792,9 +793,9 @@ impl PyCodeGenerator {
|
|||
log!(info "entered {} ({ident})", fn_name!());
|
||||
let escaped = escape_ident(ident);
|
||||
let name = self
|
||||
.local_search(&escaped, Attr)
|
||||
.local_search(&escaped, UnboundAttr)
|
||||
.unwrap_or_else(|| self.register_attr(escaped));
|
||||
let instr = self.select_load_instr(name.kind, Attr);
|
||||
let instr = self.select_load_instr(name.kind, UnboundAttr);
|
||||
self.write_instr(instr);
|
||||
self.write_arg(name.idx);
|
||||
if self.py_version.minor >= Some(11) {
|
||||
|
@ -809,9 +810,9 @@ impl PyCodeGenerator {
|
|||
}
|
||||
let escaped = escape_ident(ident);
|
||||
let name = self
|
||||
.local_search(&escaped, Method)
|
||||
.local_search(&escaped, BoundAttr)
|
||||
.unwrap_or_else(|| self.register_method(escaped));
|
||||
let instr = self.select_load_instr(name.kind, Method);
|
||||
let instr = self.select_load_instr(name.kind, BoundAttr);
|
||||
self.write_instr(instr);
|
||||
self.write_arg(name.idx);
|
||||
if self.py_version.minor >= Some(11) {
|
||||
|
@ -866,7 +867,7 @@ impl PyCodeGenerator {
|
|||
}
|
||||
Accessor::Attr(attr) => {
|
||||
self.emit_expr(*attr.obj);
|
||||
self.emit_store_instr(attr.ident, Attr);
|
||||
self.emit_store_instr(attr.ident, UnboundAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1010,7 +1011,7 @@ impl PyCodeGenerator {
|
|||
self.emit_precall_and_call(argc);
|
||||
} else {
|
||||
match kind {
|
||||
AccessKind::Method => self.write_instr(Opcode310::CALL_METHOD),
|
||||
AccessKind::BoundAttr => self.write_instr(Opcode310::CALL_METHOD),
|
||||
_ => self.write_instr(Opcode310::CALL_FUNCTION),
|
||||
}
|
||||
self.write_arg(argc);
|
||||
|
@ -2188,7 +2189,7 @@ impl PyCodeGenerator {
|
|||
let is_py_api = method_name.is_py_api();
|
||||
self.emit_expr(obj);
|
||||
self.emit_load_method_instr(method_name);
|
||||
self.emit_args_311(args, Method, is_py_api);
|
||||
self.emit_args_311(args, BoundAttr, is_py_api);
|
||||
}
|
||||
|
||||
fn emit_var_args_311(&mut self, pos_len: usize, var_args: &PosArg) {
|
||||
|
@ -3121,7 +3122,7 @@ impl PyCodeGenerator {
|
|||
self.emit_load_name_instr(Identifier::private("#path"));
|
||||
self.emit_load_method_instr(Identifier::public("append"));
|
||||
self.emit_load_const(erg_std_path().to_str().unwrap());
|
||||
self.emit_call_instr(1, Method);
|
||||
self.emit_call_instr(1, BoundAttr);
|
||||
self.stack_dec();
|
||||
self.emit_pop_top();
|
||||
let erg_std_mod = Identifier::public("_erg_std_prelude");
|
||||
|
|
|
@ -80,19 +80,31 @@ impl Name {
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum AccessKind {
|
||||
Name,
|
||||
Attr,
|
||||
Method,
|
||||
/// class/module attr
|
||||
/// e.g. `Str.center`
|
||||
UnboundAttr,
|
||||
/// method/instance attr
|
||||
/// e.g. `"aaa".center`
|
||||
///
|
||||
/// can also access class/module attrs
|
||||
BoundAttr,
|
||||
}
|
||||
|
||||
impl AccessKind {
|
||||
pub const fn is_local(&self) -> bool {
|
||||
matches!(self, Self::Name)
|
||||
}
|
||||
pub const fn is_attr(&self) -> bool {
|
||||
matches!(self, Self::Attr)
|
||||
pub const fn is_unbound_attr(&self) -> bool {
|
||||
matches!(self, Self::UnboundAttr)
|
||||
}
|
||||
pub const fn is_method(&self) -> bool {
|
||||
matches!(self, Self::Method)
|
||||
pub const fn is_bound_attr(&self) -> bool {
|
||||
matches!(self, Self::BoundAttr)
|
||||
}
|
||||
pub fn matches(&self, vi: &VarInfo) -> bool {
|
||||
match self {
|
||||
Self::Name | Self::BoundAttr => true,
|
||||
Self::UnboundAttr => !vi.kind.is_instance_attr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,19 +167,19 @@ impl Runnable for Compiler {
|
|||
let warns = self
|
||||
.compile_and_dump_as_pyc(path, src, "exec")
|
||||
.map_err(|eart| {
|
||||
eart.warns.fmt_all_stderr();
|
||||
eart.warns.write_all_stderr();
|
||||
eart.errors
|
||||
})?;
|
||||
warns.fmt_all_stderr();
|
||||
warns.write_all_stderr();
|
||||
Ok(ExitStatus::compile_passed(warns.len()))
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
|
||||
let arti = self.compile(src, "eval").map_err(|eart| {
|
||||
eart.warns.fmt_all_stderr();
|
||||
eart.warns.write_all_stderr();
|
||||
eart.errors
|
||||
})?;
|
||||
arti.warns.fmt_all_stderr();
|
||||
arti.warns.write_all_stderr();
|
||||
Ok(arti.object.code_info(Some(self.code_generator.py_version)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -301,6 +301,13 @@ impl Context {
|
|||
panic!("err: {err}");
|
||||
}
|
||||
}
|
||||
} else if typ.has_undoable_linked_var() {
|
||||
if let Err(err) = self.overwrite_typarams(typ, rhs) {
|
||||
Self::undo_substitute_typarams(typ);
|
||||
if DEBUG_MODE {
|
||||
panic!("err: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
for rhs_sup in rhs_ctx.super_traits.iter() {
|
||||
// Not `supertype_of` (only structures are compared)
|
||||
|
@ -459,8 +466,8 @@ impl Context {
|
|||
// => ?P.undoable_link(Int)
|
||||
// => Mul Int :> Int
|
||||
(FreeVar(lfv), rhs) => {
|
||||
if let FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } = &*lfv.borrow() {
|
||||
return self.supertype_of(t, rhs);
|
||||
if let Some(t) = lfv.get_linked() {
|
||||
return self.supertype_of(&t, rhs);
|
||||
}
|
||||
if let Some((_sub, sup)) = lfv.get_subsup() {
|
||||
lfv.undoable_link(rhs);
|
||||
|
@ -482,8 +489,8 @@ impl Context {
|
|||
}
|
||||
}
|
||||
(lhs, FreeVar(rfv)) => {
|
||||
if let FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } = &*rfv.borrow() {
|
||||
return self.supertype_of(lhs, t);
|
||||
if let Some(t) = rfv.get_linked() {
|
||||
return self.supertype_of(lhs, &t);
|
||||
}
|
||||
if let Some((sub, _sup)) = rfv.get_subsup() {
|
||||
rfv.undoable_link(lhs);
|
||||
|
@ -908,15 +915,23 @@ impl Context {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
if let (Ok(sup), Ok(sub)) = (
|
||||
match (
|
||||
self.convert_tp_into_type(sup_p.clone()),
|
||||
self.convert_tp_into_type(sub_p.clone()),
|
||||
) {
|
||||
return match variance {
|
||||
Variance::Contravariant => self.subtype_of(&sup, &sub),
|
||||
Variance::Covariant => self.supertype_of(&sup, &sub),
|
||||
Variance::Invariant => self.same_type_of(&sup, &sub),
|
||||
};
|
||||
(Ok(sup), Ok(sub)) => {
|
||||
return match variance {
|
||||
Variance::Contravariant => self.subtype_of(&sup, &sub),
|
||||
Variance::Covariant => self.supertype_of(&sup, &sub),
|
||||
Variance::Invariant => self.same_type_of(&sup, &sub),
|
||||
};
|
||||
}
|
||||
(Err(le), Err(re)) => {
|
||||
log!(err "cannot convert {le}, {re} to types")
|
||||
}
|
||||
(Err(err), _) | (_, Err(err)) => {
|
||||
log!(err "cannot convert {err} to a type");
|
||||
}
|
||||
}
|
||||
self.eq_tp(sup_p, sub_p)
|
||||
}
|
||||
|
|
|
@ -1338,6 +1338,11 @@ impl Context {
|
|||
TyParam::FreeVar(fv) if fv.is_linked() => self.convert_tp_into_type(fv.crack().clone()),
|
||||
TyParam::Type(t) => Ok(t.as_ref().clone()),
|
||||
TyParam::Mono(name) => Ok(Type::Mono(name)),
|
||||
TyParam::App { name, args } => Ok(Type::Poly { name, params: args }),
|
||||
TyParam::Proj { obj, attr } => {
|
||||
let lhs = self.convert_tp_into_type(*obj)?;
|
||||
Ok(lhs.proj(attr))
|
||||
}
|
||||
// TyParam::Erased(_t) => Ok(Type::Obj),
|
||||
TyParam::Value(v) => self.convert_value_into_type(v).map_err(TyParam::Value),
|
||||
// TODO: Dict, Set
|
||||
|
@ -1650,6 +1655,20 @@ impl Context {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn overwrite_typarams(&self, qt: &Type, st: &Type) -> EvalResult<()> {
|
||||
let qtps = qt.typarams();
|
||||
let stps = st.typarams();
|
||||
if qt.qual_name() != st.qual_name() || qtps.len() != stps.len() {
|
||||
log!(err "{qt} / {st}");
|
||||
log!(err "[{}] [{}]", erg_common::fmt_vec(&qtps), erg_common::fmt_vec(&stps));
|
||||
return Ok(()); // TODO: e.g. Sub(Int) / Eq and Sub(?T)
|
||||
}
|
||||
for (qtp, stp) in qtps.into_iter().zip(stps.into_iter()) {
|
||||
self.overwrite_typaram(qtp, stp)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn substitute_typaram(&self, qtp: TyParam, stp: TyParam) -> EvalResult<()> {
|
||||
match qtp {
|
||||
TyParam::FreeVar(ref fv) if fv.is_generalized() => {
|
||||
|
@ -1693,6 +1712,49 @@ impl Context {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn overwrite_typaram(&self, qtp: TyParam, stp: TyParam) -> EvalResult<()> {
|
||||
match qtp {
|
||||
TyParam::FreeVar(ref fv) if fv.is_undoable_linked() => {
|
||||
if !stp.is_unbound_var() || !stp.is_generalized() {
|
||||
fv.undoable_link(&stp);
|
||||
}
|
||||
if let Err(errs) = self.sub_unify_tp(&stp, &qtp, None, &(), false) {
|
||||
log!(err "{errs}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
TyParam::Type(qt) => self.overwrite_type(stp, *qt),
|
||||
TyParam::Value(ValueObj::Type(qt)) => self.overwrite_type(stp, qt.into_typ()),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn overwrite_type(&self, stp: TyParam, qt: Type) -> EvalResult<()> {
|
||||
let st = self.convert_tp_into_type(stp).map_err(|tp| {
|
||||
EvalError::not_a_type_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
().loc(),
|
||||
self.caused_by(),
|
||||
&tp.to_string(),
|
||||
)
|
||||
})?;
|
||||
if qt.has_undoable_linked_var() {
|
||||
if let Ok(qt) = <&FreeTyVar>::try_from(&qt) {
|
||||
if !st.is_unbound_var() || !st.is_generalized() {
|
||||
qt.undoable_link(&st);
|
||||
}
|
||||
}
|
||||
}
|
||||
if !st.is_unbound_var() || !st.is_generalized() {
|
||||
self.overwrite_typarams(&qt, &st)?;
|
||||
}
|
||||
if let Err(errs) = self.sub_unify(&st, &qt, &(), None) {
|
||||
log!(err "{errs}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn undo_substitute_typarams(substituted_q: &Type) {
|
||||
for tp in substituted_q.typarams().into_iter() {
|
||||
match tp {
|
||||
|
|
|
@ -303,7 +303,9 @@ pub(crate) fn sub_tpdict_get<'d>(
|
|||
let mut matches = vec![];
|
||||
for (k, v) in dict.iter() {
|
||||
match (<&Type>::try_from(key), <&Type>::try_from(k)) {
|
||||
(Ok(idx), Ok(kt)) if ctx.subtype_of(&idx.lower_bounded(), &kt.lower_bounded()) => {
|
||||
(Ok(idx), Ok(kt))
|
||||
if ctx.subtype_of(&idx.lower_bounded(), &kt.lower_bounded()) || dict.len() == 1 =>
|
||||
{
|
||||
matches.push((idx, kt, v));
|
||||
}
|
||||
(_, _) if key == k => {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
use std::option::Option; // conflicting to Type::Option
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use erg_common::config::Input;
|
||||
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
||||
use erg_common::error::{ErrorCore, Location, SubMessage};
|
||||
use erg_common::io::Input;
|
||||
use erg_common::levenshtein;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::traits::{Locational, NoTypeDisplay, Stream};
|
||||
|
@ -420,7 +420,7 @@ impl Context {
|
|||
) -> Triple<VarInfo, TyCheckError> {
|
||||
if let Some(vi) = self.get_current_scope_var(&ident.name) {
|
||||
match self.validate_visibility(ident, vi, input, namespace) {
|
||||
Ok(()) => {
|
||||
Ok(()) if acc_kind.matches(vi) => {
|
||||
return Triple::Ok(vi.clone());
|
||||
}
|
||||
Err(err) => {
|
||||
|
@ -428,6 +428,7 @@ impl Context {
|
|||
return Triple::Err(err);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if let Some((name, _vi)) = self
|
||||
.future_defined_locals
|
||||
|
@ -453,6 +454,17 @@ impl Context {
|
|||
self.get_similar_name(ident.inspect()),
|
||||
));
|
||||
}
|
||||
for (_, method_ctx) in self.methods_list.iter() {
|
||||
match method_ctx.rec_get_var_info(ident, acc_kind, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
return Triple::Ok(vi);
|
||||
}
|
||||
Triple::Err(e) => {
|
||||
return Triple::Err(e);
|
||||
}
|
||||
Triple::None => {}
|
||||
}
|
||||
}
|
||||
if acc_kind.is_local() {
|
||||
if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||
return parent.rec_get_var_info(ident, acc_kind, input, namespace);
|
||||
|
@ -468,7 +480,7 @@ impl Context {
|
|||
) -> Option<&mut VarInfo> {
|
||||
if let Some(vi) = self.get_current_scope_var(&ident.name) {
|
||||
match self.validate_visibility(ident, vi, &self.cfg.input, self) {
|
||||
Ok(()) => {
|
||||
Ok(()) if acc_kind.matches(vi) => {
|
||||
let vi = self.get_mut_current_scope_var(&ident.name).unwrap();
|
||||
return Some(vi);
|
||||
}
|
||||
|
@ -477,6 +489,7 @@ impl Context {
|
|||
return None;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if acc_kind.is_local() {
|
||||
|
@ -500,7 +513,7 @@ impl Context {
|
|||
.or_else(|| self.future_defined_locals.get(&ident.inspect()[..]))
|
||||
{
|
||||
match self.validate_visibility(ident, vi, input, namespace) {
|
||||
Ok(()) => {
|
||||
Ok(()) if acc_kind.matches(vi) => {
|
||||
return Triple::Ok(vi.clone());
|
||||
}
|
||||
Err(err) => {
|
||||
|
@ -508,6 +521,7 @@ impl Context {
|
|||
return Triple::Err(err);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if acc_kind.is_local() {
|
||||
|
@ -562,9 +576,10 @@ impl Context {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
// class/module attr
|
||||
if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
|
||||
for ctx in singular_ctxs {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::UnboundAttr, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
return Triple::Ok(vi);
|
||||
}
|
||||
|
@ -575,7 +590,8 @@ impl Context {
|
|||
}
|
||||
}
|
||||
}
|
||||
match self.get_attr_from_nominal_t(obj, ident, input, namespace) {
|
||||
// bound method/instance attr
|
||||
match self.get_bound_attr_from_nominal_t(obj, ident, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
if let Some(self_t) = vi.t.self_t() {
|
||||
match self
|
||||
|
@ -636,7 +652,7 @@ impl Context {
|
|||
Triple::None
|
||||
}
|
||||
|
||||
fn get_attr_from_nominal_t(
|
||||
fn get_bound_attr_from_nominal_t(
|
||||
&self,
|
||||
obj: &hir::Expr,
|
||||
ident: &Identifier,
|
||||
|
@ -646,7 +662,7 @@ impl Context {
|
|||
let self_t = obj.t();
|
||||
if let Some(sups) = self.get_nominal_super_type_ctxs(&self_t) {
|
||||
for ctx in sups {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
return Triple::Ok(vi);
|
||||
}
|
||||
|
@ -657,7 +673,7 @@ impl Context {
|
|||
}
|
||||
// if self is a methods context
|
||||
if let Some(ctx) = self.get_same_name_context(&ctx.name) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::Method, input, namespace) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
return Triple::Ok(vi);
|
||||
}
|
||||
|
@ -691,7 +707,7 @@ impl Context {
|
|||
}
|
||||
};
|
||||
for ctx in ctxs {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::Attr, input, namespace) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
obj.ref_t().coerce();
|
||||
return Triple::Ok(vi);
|
||||
|
@ -702,7 +718,7 @@ impl Context {
|
|||
_ => {}
|
||||
}
|
||||
if let Some(ctx) = self.get_same_name_context(&ctx.name) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::Method, input, namespace) {
|
||||
match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
|
||||
Triple::Ok(vi) => {
|
||||
return Triple::Ok(vi);
|
||||
}
|
||||
|
@ -946,7 +962,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
if let Some(ctx) = self.get_same_name_context(&ctx.name) {
|
||||
match ctx.rec_get_var_info(attr_name, AccessKind::Method, input, namespace) {
|
||||
match ctx.rec_get_var_info(attr_name, AccessKind::BoundAttr, input, namespace) {
|
||||
Triple::Ok(t) => {
|
||||
return Ok(t);
|
||||
}
|
||||
|
@ -3072,4 +3088,58 @@ impl Context {
|
|||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_instance_attr(&self, name: &str) -> Option<&VarInfo> {
|
||||
if let Some(vi) = self.locals.get(name) {
|
||||
if vi.kind.is_instance_attr() {
|
||||
return Some(vi);
|
||||
}
|
||||
}
|
||||
if let Some(vi) = self.decls.get(name) {
|
||||
if vi.kind.is_instance_attr() {
|
||||
return Some(vi);
|
||||
}
|
||||
}
|
||||
if self.kind.is_method_def() {
|
||||
self.get_nominal_type_ctx(&mono(&self.name))
|
||||
.and_then(|(_, ctx)| ctx.get_instance_attr(name))
|
||||
} else {
|
||||
self.methods_list.iter().find_map(|(_, ctx)| {
|
||||
if ctx.kind.is_trait_impl() {
|
||||
None
|
||||
} else {
|
||||
ctx.get_instance_attr(name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// does not remove instance attribute declarations
|
||||
pub(crate) fn remove_class_attr(&mut self, name: &str) -> Option<(VarName, VarInfo)> {
|
||||
if let Some((k, v)) = self.locals.remove_entry(name) {
|
||||
if v.kind.is_instance_attr() {
|
||||
self.locals.insert(k, v);
|
||||
} else {
|
||||
return Some((k, v));
|
||||
}
|
||||
} else if let Some((k, v)) = self.decls.remove_entry(name) {
|
||||
if v.kind.is_instance_attr() {
|
||||
self.decls.insert(k, v);
|
||||
} else {
|
||||
return Some((k, v));
|
||||
}
|
||||
}
|
||||
if self.kind.is_method_def() {
|
||||
self.get_mut_nominal_type_ctx(&mono(&self.name))
|
||||
.and_then(|(_, ctx)| ctx.remove_class_attr(name))
|
||||
} else {
|
||||
self.methods_list.iter_mut().find_map(|(_, ctx)| {
|
||||
if ctx.kind.is_trait_impl() {
|
||||
None
|
||||
} else {
|
||||
ctx.remove_class_attr(name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -574,19 +574,23 @@ impl Context {
|
|||
) -> TyCheckResult<Type> {
|
||||
match poly_spec.acc.to_string().trim_start_matches([':', '.']) {
|
||||
"Array" => {
|
||||
let ctx = self
|
||||
.get_nominal_type_ctx(&array_t(Type::Obj, TyParam::Failure))
|
||||
.unwrap()
|
||||
.1;
|
||||
// TODO: kw
|
||||
let mut args = poly_spec.args.pos_args();
|
||||
if let Some(first) = args.next() {
|
||||
let t = self.instantiate_const_expr_as_type(
|
||||
&first.expr,
|
||||
None,
|
||||
Some((ctx, 0)),
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
let len = if let Some(len) = args.next() {
|
||||
self.instantiate_const_expr(
|
||||
&len.expr,
|
||||
None,
|
||||
Some((ctx, 1)),
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?
|
||||
|
@ -824,21 +828,24 @@ impl Context {
|
|||
self.instantiate_acc(acc, erased_idx, tmp_tv_cache, not_found_is_qvar)
|
||||
}
|
||||
ast::ConstExpr::App(app) => {
|
||||
let name = match &app.acc {
|
||||
ast::ConstAccessor::Local(local) => local.inspect(),
|
||||
_ => return type_feature_error!(self, app.loc(), "instantiating const callee"),
|
||||
let ast::ConstAccessor::Local(ident) = &app.acc else {
|
||||
return type_feature_error!(self, app.loc(), "instantiating const callee");
|
||||
};
|
||||
let &ctx = self
|
||||
.get_singular_ctxs_by_ident(ident, self)?
|
||||
.first()
|
||||
.unwrap_or(&self);
|
||||
let mut args = vec![];
|
||||
for (i, arg) in app.args.pos_args().enumerate() {
|
||||
let arg_t = self.instantiate_const_expr(
|
||||
&arg.expr,
|
||||
Some((self, i)),
|
||||
Some((ctx, i)),
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
args.push(arg_t);
|
||||
}
|
||||
Ok(TyParam::app(name.clone(), args))
|
||||
Ok(TyParam::app(ident.inspect().clone(), args))
|
||||
}
|
||||
ast::ConstExpr::Array(ConstArray::Normal(array)) => {
|
||||
let mut tp_arr = vec![];
|
||||
|
|
|
@ -319,6 +319,10 @@ impl ContextKind {
|
|||
matches!(self, Self::MethodDefs(_))
|
||||
}
|
||||
|
||||
pub const fn is_trait_impl(&self) -> bool {
|
||||
matches!(self, Self::MethodDefs(Some(_)))
|
||||
}
|
||||
|
||||
pub const fn is_type(&self) -> bool {
|
||||
matches!(self, Self::Class | Self::Trait | Self::StructuralTrait)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::time::{Duration, SystemTime};
|
|||
|
||||
use erg_common::config::ErgMode;
|
||||
use erg_common::consts::{ERG_MODE, PYTHON_MODE};
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::env::{is_pystd_main_module, is_std_decl_path};
|
||||
use erg_common::erg_util::BUILTIN_ERG_MODS;
|
||||
use erg_common::levenshtein::get_similar_name;
|
||||
|
@ -32,7 +33,7 @@ use crate::ty::free::{Constraint, HasLevel};
|
|||
use crate::ty::typaram::TyParam;
|
||||
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
|
||||
use crate::ty::{
|
||||
GuardType, HasType, ParamTy, SubrType, Type, Variable, Visibility, VisibilityModifier,
|
||||
Field, GuardType, HasType, ParamTy, SubrType, Type, Variable, Visibility, VisibilityModifier,
|
||||
};
|
||||
|
||||
use crate::build_hir::HIRBuilder;
|
||||
|
@ -200,7 +201,10 @@ impl Context {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(_decl) = self.decls.remove(&ident.name) {
|
||||
if self
|
||||
.remove_class_attr(ident.name.inspect())
|
||||
.is_some_and(|(_, decl)| !decl.kind.is_auto())
|
||||
{
|
||||
Err(TyCheckErrors::from(TyCheckError::duplicate_decl_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
|
@ -266,7 +270,10 @@ impl Context {
|
|||
self.absolutize(sig.ident.name.loc()),
|
||||
);
|
||||
self.index().register(&vi);
|
||||
if let Some(_decl) = self.decls.remove(name) {
|
||||
if self
|
||||
.remove_class_attr(name)
|
||||
.is_some_and(|(_, decl)| !decl.kind.is_auto())
|
||||
{
|
||||
Err(TyCheckErrors::from(TyCheckError::duplicate_decl_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
|
@ -452,6 +459,7 @@ impl Context {
|
|||
if self
|
||||
.registered_info(name.inspect(), name.is_const())
|
||||
.is_some()
|
||||
&& &name.inspect()[..] != "_"
|
||||
{
|
||||
Err(TyCheckErrors::from(TyCheckError::reassign_error(
|
||||
self.cfg.input.clone(),
|
||||
|
@ -1287,9 +1295,7 @@ impl Context {
|
|||
2,
|
||||
self.level,
|
||||
);
|
||||
if ERG_MODE {
|
||||
self.gen_class_new_method(&gen, &mut ctx)?;
|
||||
}
|
||||
self.gen_class_new_method(&gen, &mut ctx)?;
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const)
|
||||
} else {
|
||||
let params = gen
|
||||
|
@ -1306,9 +1312,7 @@ impl Context {
|
|||
2,
|
||||
self.level,
|
||||
);
|
||||
if ERG_MODE {
|
||||
self.gen_class_new_method(&gen, &mut ctx)?;
|
||||
}
|
||||
self.gen_class_new_method(&gen, &mut ctx)?;
|
||||
self.register_gen_poly_type(ident, gen, ctx, Const)
|
||||
}
|
||||
}
|
||||
|
@ -1350,16 +1354,7 @@ impl Context {
|
|||
..
|
||||
} = additional
|
||||
{
|
||||
for (field, t) in rec.iter() {
|
||||
let varname = VarName::from_str(field.symbol.clone());
|
||||
let vi = VarInfo::instance_attr(
|
||||
field.clone(),
|
||||
t.clone(),
|
||||
self.impl_of(),
|
||||
ctx.name.clone(),
|
||||
);
|
||||
ctx.decls.insert(varname, vi);
|
||||
}
|
||||
self.register_instance_attrs(&mut ctx, rec)?;
|
||||
}
|
||||
param_t
|
||||
.map(|t| self.intersection(t, additional.typ()))
|
||||
|
@ -1421,16 +1416,7 @@ impl Context {
|
|||
self.level,
|
||||
);
|
||||
let Some(TypeObj::Builtin{ t: Type::Record(req), .. }) = gen.base_or_sup() else { todo!("{gen}") };
|
||||
for (field, t) in req.iter() {
|
||||
let vi = VarInfo::instance_attr(
|
||||
field.clone(),
|
||||
t.clone(),
|
||||
self.impl_of(),
|
||||
ctx.name.clone(),
|
||||
);
|
||||
ctx.decls
|
||||
.insert(VarName::from_str(field.symbol.clone()), vi);
|
||||
}
|
||||
self.register_instance_attrs(&mut ctx, req)?;
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const)
|
||||
} else {
|
||||
feature_error!(
|
||||
|
@ -1463,16 +1449,7 @@ impl Context {
|
|||
None
|
||||
};
|
||||
if let Some(additional) = additional {
|
||||
for (field, t) in additional.iter() {
|
||||
let vi = VarInfo::instance_attr(
|
||||
field.clone(),
|
||||
t.clone(),
|
||||
self.impl_of(),
|
||||
ctx.name.clone(),
|
||||
);
|
||||
ctx.decls
|
||||
.insert(VarName::from_str(field.symbol.clone()), vi);
|
||||
}
|
||||
self.register_instance_attrs(&mut ctx, additional)?;
|
||||
}
|
||||
for sup in super_classes.into_iter() {
|
||||
if let Some((_, sup_ctx)) = self.get_nominal_type_ctx(&sup) {
|
||||
|
@ -1524,6 +1501,29 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_instance_attrs(
|
||||
&self,
|
||||
ctx: &mut Context,
|
||||
rec: &Dict<Field, Type>,
|
||||
) -> CompileResult<()> {
|
||||
for (field, t) in rec.iter() {
|
||||
let varname = VarName::from_str(field.symbol.clone());
|
||||
let vi =
|
||||
VarInfo::instance_attr(field.clone(), t.clone(), self.impl_of(), ctx.name.clone());
|
||||
// self.index().register(&vi);
|
||||
if let Some(_ent) = ctx.decls.insert(varname.clone(), vi) {
|
||||
return Err(CompileErrors::from(CompileError::duplicate_decl_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
varname.loc(),
|
||||
self.caused_by(),
|
||||
varname.inspect(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gen_class_new_method(&self, gen: &GenTypeObj, ctx: &mut Context) -> CompileResult<()> {
|
||||
let mut methods = Self::methods(None, self.cfg.clone(), self.shared.clone(), 2, self.level);
|
||||
let new_t = if let Some(base) = gen.base_or_sup() {
|
||||
|
@ -1532,16 +1532,7 @@ impl Context {
|
|||
t: Type::Record(rec),
|
||||
..
|
||||
} => {
|
||||
for (field, t) in rec.iter() {
|
||||
let varname = VarName::from_str(field.symbol.clone());
|
||||
let vi = VarInfo::instance_attr(
|
||||
field.clone(),
|
||||
t.clone(),
|
||||
self.impl_of(),
|
||||
ctx.name.clone(),
|
||||
);
|
||||
ctx.decls.insert(varname, vi);
|
||||
}
|
||||
self.register_instance_attrs(ctx, rec)?;
|
||||
}
|
||||
other => {
|
||||
methods.register_fixed_auto_impl(
|
||||
|
@ -1557,16 +1548,31 @@ impl Context {
|
|||
} else {
|
||||
func0(gen.typ().clone())
|
||||
};
|
||||
methods.register_fixed_auto_impl(
|
||||
"__new__",
|
||||
new_t.clone(),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PRIVATE,
|
||||
Some("__call__".into()),
|
||||
)?;
|
||||
// 必要なら、ユーザーが独自に上書きする
|
||||
// users can override this if necessary
|
||||
methods.register_auto_impl("new", new_t, Immutable, Visibility::BUILTIN_PUBLIC, None)?;
|
||||
if ERG_MODE {
|
||||
methods.register_fixed_auto_impl(
|
||||
"__new__",
|
||||
new_t.clone(),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PRIVATE,
|
||||
Some("__call__".into()),
|
||||
)?;
|
||||
// users can override this if necessary
|
||||
methods.register_auto_impl(
|
||||
"new",
|
||||
new_t,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
None,
|
||||
)?;
|
||||
} else {
|
||||
methods.register_auto_impl(
|
||||
"__call__",
|
||||
new_t,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some("__call__".into()),
|
||||
)?;
|
||||
}
|
||||
ctx.methods_list
|
||||
.push((ClassDefType::Simple(gen.typ().clone()), methods));
|
||||
Ok(())
|
||||
|
|
|
@ -446,11 +446,13 @@ impl Context {
|
|||
Ok(())
|
||||
}
|
||||
(TyParam::Dict(sub), TyParam::Dict(sup)) => {
|
||||
for (lk, lv) in sub.iter() {
|
||||
if let Some(rv) = sup.get(lk).or_else(|| sub_tpdict_get(sup, lk, self)) {
|
||||
self.sub_unify_tp(lv, rv, _variance, loc, allow_divergence)?;
|
||||
for (sub_k, sub_v) in sub.iter() {
|
||||
if let Some(sup_v) = sup.get(sub_k).or_else(|| sub_tpdict_get(sup, sub_k, self))
|
||||
{
|
||||
// self.sub_unify_tp(sub_k, sup_k, _variance, loc, allow_divergence)?;
|
||||
self.sub_unify_tp(sub_v, sup_v, _variance, loc, allow_divergence)?;
|
||||
} else {
|
||||
log!(err "{sup} does not have key {lk}");
|
||||
log!(err "{sup} does not have key {sub_k}");
|
||||
// TODO:
|
||||
return Err(TyCheckErrors::from(TyCheckError::unreachable(
|
||||
self.cfg.input.clone(),
|
||||
|
|
|
@ -177,7 +177,7 @@ impl ASTLowerer {
|
|||
for ctx in ctxs {
|
||||
if let Triple::Ok(vi) = ctx.rec_get_var_info(
|
||||
&ident.raw,
|
||||
AccessKind::Attr,
|
||||
AccessKind::UnboundAttr,
|
||||
self.input(),
|
||||
&self.module.context,
|
||||
) {
|
||||
|
|
|
@ -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 crate::error::*;
|
||||
|
|
|
@ -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::style::{StyledStr, StyledString, StyledStrings, Stylize};
|
||||
use erg_common::traits::Locational;
|
||||
use erg_common::{switch_lang, Str};
|
||||
|
@ -485,11 +485,12 @@ impl LowerError {
|
|||
) -> Self {
|
||||
let hint = similar_name.map(|n| {
|
||||
let vis = similar_info.map_or("".into(), |vi| vi.vis.modifier.display());
|
||||
let kind = similar_info.map_or("", |vi| vi.kind.display());
|
||||
switch_lang!(
|
||||
"japanese" => format!("似た名前の{vis}属性があります: {n}"),
|
||||
"simplified_chinese" => format!("具有相同名称的{vis}属性: {n}"),
|
||||
"traditional_chinese" => format!("具有相同名稱的{vis}屬性: {n}"),
|
||||
"english" => format!("has a similar name {vis} attribute: {n}"),
|
||||
"japanese" => format!("似た名前の{vis}{kind}属性があります: {n}"),
|
||||
"simplified_chinese" => format!("具有相同名称的{vis}{kind}属性: {n}"),
|
||||
"traditional_chinese" => format!("具有相同名稱的{vis}{kind}屬性: {n}"),
|
||||
"english" => format!("has a similar name {vis} {kind} attribute: {n}"),
|
||||
)
|
||||
});
|
||||
let found = StyledString::new(name, Some(ERR), Some(ATTR));
|
||||
|
@ -1157,4 +1158,30 @@ impl LowerWarning {
|
|||
caused_by,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn same_name_instance_attr_warning(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
caused_by: String,
|
||||
name: &str,
|
||||
) -> Self {
|
||||
let name = StyledStr::new(readable_name(name), Some(WARN), Some(ATTR));
|
||||
Self::new(
|
||||
ErrorCore::new(
|
||||
vec![SubMessage::only_loc(loc)],
|
||||
switch_lang!(
|
||||
"japanese" => format!("同名のインスタンス属性{name}が存在します"),
|
||||
"simplified_chinese" => format!("同名的实例属性{name}已存在"),
|
||||
"traditional_chinese" => format!("同名的實例屬性{name}已存在"),
|
||||
"english" => format!("an instance attribute named {name} already exists"),
|
||||
),
|
||||
errno,
|
||||
NameWarning,
|
||||
loc,
|
||||
),
|
||||
input,
|
||||
caused_by,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@ pub mod tycheck;
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use erg_common::config::Input;
|
||||
use erg_common::error::{
|
||||
ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay, SubMessage,
|
||||
};
|
||||
use erg_common::io::Input;
|
||||
use erg_common::style::{Attribute, Color, StyledStr, StyledString, StyledStrings, Theme, THEME};
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::{impl_display_and_error, impl_stream, switch_lang};
|
||||
|
||||
use erg_parser::error::{ParserRunnerError, ParserRunnerErrors};
|
||||
use erg_parser::error::{ParseError, ParseErrors, ParserRunnerError, ParserRunnerErrors};
|
||||
|
||||
pub use crate::error::eval::*;
|
||||
pub use crate::error::lower::*;
|
||||
|
@ -497,6 +497,18 @@ impl From<CompileError> for CompileErrors {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<CompileError> for ParseError {
|
||||
fn from(err: CompileError) -> Self {
|
||||
Self::new(*err.core)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompileErrors> for ParseErrors {
|
||||
fn from(err: CompileErrors) -> Self {
|
||||
Self::new(err.into_iter().map(ParseError::from).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiErrorDisplay<CompileError> for CompileErrors {}
|
||||
|
||||
impl fmt::Display for CompileErrors {
|
||||
|
@ -524,7 +536,7 @@ mod test {
|
|||
ty::{Predicate, Type},
|
||||
varinfo::{AbsLocation, VarInfo},
|
||||
};
|
||||
use erg_common::{config::Input, error::Location};
|
||||
use erg_common::{error::Location, io::Input};
|
||||
use erg_parser::ast::{VarName, VisModifierSpec};
|
||||
|
||||
// These Erg codes are not correct grammar.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use erg_common::config::Input;
|
||||
use erg_common::error::{ErrorCore, ErrorKind::*, Location, SubMessage};
|
||||
use erg_common::io::Input;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::style::{StyledStr, StyledString, StyledStrings, Stylize};
|
||||
use erg_common::traits::{Locational, NoTypeDisplay};
|
||||
|
|
0
crates/erg_compiler/lib/external/matplotlib.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/matplotlib.d/package.er
vendored
Normal file
|
@ -8,6 +8,9 @@
|
|||
dtype: Type
|
||||
size: Nat
|
||||
|
||||
.nan: Float
|
||||
.Nan: Float
|
||||
|
||||
.abs: |T|(object: .NDArray(T),) -> .NDArray(T)
|
||||
.add: |T|(object: .NDArray(T), other: .NDArray(T)) -> .NDArray(T)
|
||||
.all: |T <: Num|(object: .NDArray(T),) -> Bool
|
||||
|
|
0
crates/erg_compiler/lib/external/numpy.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/numpy.d/package.er
vendored
Normal file
5
crates/erg_compiler/lib/external/pandas.d/__init__.d.er
vendored
Normal file
5
crates/erg_compiler/lib/external/pandas.d/__init__.d.er
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
.DataFrame!;
|
||||
.Series!;
|
||||
.Index;
|
||||
} = pyimport "core/api"
|
0
crates/erg_compiler/lib/external/pandas.d/core.d/__init__.d.er
vendored
Normal file
0
crates/erg_compiler/lib/external/pandas.d/core.d/__init__.d.er
vendored
Normal file
3
crates/erg_compiler/lib/external/pandas.d/core.d/api.d.er
vendored
Normal file
3
crates/erg_compiler/lib/external/pandas.d/core.d/api.d.er
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{.DataFrame!;} = pyimport "./frame"
|
||||
{.Series!;} = pyimport "./series"
|
||||
{.Index;} = pyimport "./indexes/api"
|
14
crates/erg_compiler/lib/external/pandas.d/core.d/frame.d.er
vendored
Normal file
14
crates/erg_compiler/lib/external/pandas.d/core.d/frame.d.er
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
{.Index;} = pyimport "./indexes/api"
|
||||
|
||||
# I := Nat, V := Obj
|
||||
.DataFrame!: (C: Type, I: Type, V: Type) -> ClassType
|
||||
.DataFrame!(C, I, V) <: Input(C)
|
||||
.DataFrame!(C, I, V) <: Input(I)
|
||||
.DataFrame!(C, I, V) <: Output(V)
|
||||
.DataFrame!.
|
||||
__call__: |K, V, I|(dic: {K: [V; _]} or Iterable(Iterable(V)), index: [I; _] := [Nat; _]) -> .DataFrame!(K, I, V)
|
||||
shape: (Nat, Nat)
|
||||
index: .Index(_) # TODO
|
||||
head: |C, I, V|(self: .DataFrame!(C, I, V), tail: Nat := {5}) -> .DataFrame!(C, I, V)
|
||||
tail: |C, I, V|(self: .DataFrame!(C, I, V), tail: Nat := {5}) -> .DataFrame!(C, I, V)
|
||||
info!: (self: .DataFrame!(_, _, _)) => NoneType
|
0
crates/erg_compiler/lib/external/pandas.d/core.d/indexes.d/__init__.d.er
vendored
Normal file
0
crates/erg_compiler/lib/external/pandas.d/core.d/indexes.d/__init__.d.er
vendored
Normal file
1
crates/erg_compiler/lib/external/pandas.d/core.d/indexes.d/api.d.er
vendored
Normal file
1
crates/erg_compiler/lib/external/pandas.d/core.d/indexes.d/api.d.er
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{.Index;} = pyimport "./base"
|
2
crates/erg_compiler/lib/external/pandas.d/core.d/indexes.d/base.d.er
vendored
Normal file
2
crates/erg_compiler/lib/external/pandas.d/core.d/indexes.d/base.d.er
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.Index: (T: Type) -> ClassType
|
||||
.Index(T) <: Output(T)
|
8
crates/erg_compiler/lib/external/pandas.d/core.d/series.d.er
vendored
Normal file
8
crates/erg_compiler/lib/external/pandas.d/core.d/series.d.er
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
{.Index;} = pyimport "./indexes/api"
|
||||
|
||||
# K := Nat, V := Obj
|
||||
.Series!: (K: Type, V: Type) -> ClassType
|
||||
.Series!(K, V) <: Input(K)
|
||||
.Series!(K, V) <: Output(V)
|
||||
.Series!.
|
||||
__call__: |K, V|(iterable: Iterable(V), index: [K; _] or .Index(K) := [Nat; _]) -> .Series! K, V
|
0
crates/erg_compiler/lib/external/pandas.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/pandas.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/requests.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/requests.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/setuptools.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/setuptools.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/tqdm.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/tqdm.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/urllib3.d/package.er
vendored
Normal file
0
crates/erg_compiler/lib/external/urllib3.d/package.er
vendored
Normal file
|
@ -215,12 +215,12 @@ impl ASTLowerer {
|
|||
format!("{}{code}", "\n".repeat(first_line as usize))
|
||||
};
|
||||
match ASTBuilder::new(self.cfg().clone()).build(code) {
|
||||
Ok(ast) => {
|
||||
self.check_doc_ast(ast);
|
||||
Ok(artifact) => {
|
||||
self.check_doc_ast(artifact.ast);
|
||||
}
|
||||
Err(errs) => {
|
||||
let errs = CompileErrors::from(errs);
|
||||
self.errs.extend(errs);
|
||||
Err(iart) => {
|
||||
self.errs.extend(CompileErrors::from(iart.errors));
|
||||
self.warns.extend(CompileErrors::from(iart.warns));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ use crate::context::{
|
|||
RegistrationMode, TraitImpl,
|
||||
};
|
||||
use crate::error::{
|
||||
CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarning, LowerWarnings,
|
||||
SingleLowerResult,
|
||||
CompileError, CompileErrors, CompileWarning, LowerError, LowerErrors, LowerResult,
|
||||
LowerWarning, LowerWarnings, SingleLowerResult,
|
||||
};
|
||||
use crate::hir;
|
||||
use crate::hir::HIR;
|
||||
|
@ -125,22 +125,27 @@ impl Runnable for ASTLowerer {
|
|||
|
||||
fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
|
||||
let mut ast_builder = ASTBuilder::new(self.cfg.copy());
|
||||
let ast = ast_builder.build(self.cfg.input.read())?;
|
||||
let artifact = self
|
||||
.lower(ast, "exec")
|
||||
let artifact = ast_builder
|
||||
.build(self.cfg.input.read())
|
||||
.map_err(|artifact| artifact.errors)?;
|
||||
artifact.warns.fmt_all_stderr();
|
||||
println!("{}", artifact.object);
|
||||
artifact.warns.write_all_to(&mut self.cfg.output);
|
||||
let artifact = self
|
||||
.lower(artifact.ast, "exec")
|
||||
.map_err(|artifact| artifact.errors)?;
|
||||
artifact.warns.write_all_to(&mut self.cfg.output);
|
||||
use std::io::Write;
|
||||
write!(self.cfg.output, "{}", artifact.object).unwrap();
|
||||
Ok(ExitStatus::compile_passed(artifact.warns.len()))
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, Self::Errs> {
|
||||
let mut ast_builder = ASTBuilder::new(self.cfg.copy());
|
||||
let ast = ast_builder.build(src)?;
|
||||
let artifact = ast_builder.build(src).map_err(|artifact| artifact.errors)?;
|
||||
artifact.warns.write_all_stderr();
|
||||
let artifact = self
|
||||
.lower(ast, "eval")
|
||||
.lower(artifact.ast, "eval")
|
||||
.map_err(|artifact| artifact.errors)?;
|
||||
artifact.warns.fmt_all_stderr();
|
||||
artifact.warns.write_all_stderr();
|
||||
Ok(format!("{}", artifact.object))
|
||||
}
|
||||
}
|
||||
|
@ -1663,6 +1668,23 @@ impl ASTLowerer {
|
|||
self.pop_append_errs();
|
||||
errs
|
||||
})?;
|
||||
if let Some(ident) = def.sig.ident() {
|
||||
if self
|
||||
.module
|
||||
.context
|
||||
.get_instance_attr(ident.inspect())
|
||||
.is_some()
|
||||
{
|
||||
self.warns
|
||||
.push(CompileWarning::same_name_instance_attr_warning(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
ident.loc(),
|
||||
self.module.context.caused_by(),
|
||||
ident.inspect(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ClassAttr::Decl(_) | ast::ClassAttr::Doc(_) => {}
|
||||
}
|
||||
|
@ -1730,21 +1752,19 @@ impl ASTLowerer {
|
|||
if let Some(sup_type) = call.args.get_left_or_key("Super") {
|
||||
Self::check_inheritable(&self.cfg, &mut self.errs, type_obj, sup_type, &hir_def.sig);
|
||||
}
|
||||
let (__new__, need_to_gen_new) = if let (Some(dunder_new_vi), Some(new_vi)) = (
|
||||
class_ctx.get_current_scope_var(&VarName::from_static("__new__")),
|
||||
class_ctx.get_current_scope_var(&VarName::from_static("new")),
|
||||
) {
|
||||
(dunder_new_vi.t.clone(), new_vi.kind == VarKind::Auto)
|
||||
} else {
|
||||
let Some(__new__) = class_ctx.get_current_scope_var(&VarName::from_static("__new__")).or(class_ctx.get_current_scope_var(&VarName::from_static("__call__"))) else {
|
||||
return unreachable_error!(LowerErrors, LowerError, self);
|
||||
};
|
||||
let need_to_gen_new = class_ctx
|
||||
.get_current_scope_var(&VarName::from_static("new"))
|
||||
.map_or(false, |vi| vi.kind == VarKind::Auto);
|
||||
let require_or_sup = Self::get_require_or_sup_or_base(hir_def.body.block.remove(0));
|
||||
Ok(hir::ClassDef::new(
|
||||
type_obj.clone(),
|
||||
hir_def.sig,
|
||||
require_or_sup,
|
||||
need_to_gen_new,
|
||||
__new__,
|
||||
__new__.t.clone(),
|
||||
hir_methods,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use erg_common::config::ErgConfig;
|
||||
use erg_common::error::MultiErrorDisplay;
|
||||
use erg_common::io::Output;
|
||||
use erg_common::spawn::exec_new_thread;
|
||||
use erg_common::traits::Runnable;
|
||||
|
||||
|
@ -13,7 +14,8 @@ use erg_compiler::ty::constructors::{
|
|||
use erg_compiler::ty::Type::*;
|
||||
|
||||
fn load_file(path: &'static str) -> Result<ModuleContext, CompileErrors> {
|
||||
let cfg = ErgConfig::with_main_path(path.into());
|
||||
let mut cfg = ErgConfig::with_main_path(path.into());
|
||||
cfg.output = Output::Null;
|
||||
let mut lowerer = ASTLowerer::new(cfg);
|
||||
lowerer.exec()?;
|
||||
Ok(lowerer.pop_mod_ctx().unwrap())
|
||||
|
@ -26,7 +28,7 @@ fn test_infer_types() -> Result<(), ()> {
|
|||
|
||||
fn _test_infer_types() -> Result<(), ()> {
|
||||
let module = load_file("tests/infer.er").map_err(|errs| {
|
||||
errs.fmt_all_stderr();
|
||||
errs.write_all_stderr();
|
||||
})?;
|
||||
let t = type_q("T");
|
||||
let u = type_q("U");
|
||||
|
|
|
@ -148,10 +148,10 @@ impl Runnable for Transpiler {
|
|||
path.set_extension("py");
|
||||
let src = self.cfg.input.read();
|
||||
let artifact = self.transpile(src, "exec").map_err(|eart| {
|
||||
eart.warns.fmt_all_stderr();
|
||||
eart.warns.write_all_stderr();
|
||||
eart.errors
|
||||
})?;
|
||||
artifact.warns.fmt_all_stderr();
|
||||
artifact.warns.write_all_stderr();
|
||||
let mut f = File::create(path).unwrap();
|
||||
f.write_all(artifact.object.code.as_bytes()).unwrap();
|
||||
Ok(ExitStatus::compile_passed(artifact.warns.len()))
|
||||
|
@ -159,10 +159,10 @@ impl Runnable for Transpiler {
|
|||
|
||||
fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
|
||||
let artifact = self.transpile(src, "eval").map_err(|eart| {
|
||||
eart.warns.fmt_all_stderr();
|
||||
eart.warns.write_all_stderr();
|
||||
eart.errors
|
||||
})?;
|
||||
artifact.warns.fmt_all_stderr();
|
||||
artifact.warns.write_all_stderr();
|
||||
Ok(artifact.object.code)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -444,6 +444,22 @@ impl SubrType {
|
|||
|| self.return_t.has_qvar()
|
||||
}
|
||||
|
||||
pub fn has_undoable_linked_var(&self) -> bool {
|
||||
self.non_default_params
|
||||
.iter()
|
||||
.any(|pt| pt.typ().has_undoable_linked_var())
|
||||
|| self
|
||||
.var_params
|
||||
.as_ref()
|
||||
.map(|pt| pt.typ().has_undoable_linked_var())
|
||||
.unwrap_or(false)
|
||||
|| self
|
||||
.default_params
|
||||
.iter()
|
||||
.any(|pt| pt.typ().has_undoable_linked_var())
|
||||
|| self.return_t.has_undoable_linked_var()
|
||||
}
|
||||
|
||||
pub fn typarams(&self) -> Vec<TyParam> {
|
||||
[
|
||||
self.non_default_params
|
||||
|
@ -2450,6 +2466,58 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_undoable_linked_var(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_undoable_linked() => true,
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().has_undoable_linked_var(),
|
||||
Self::FreeVar(fv) => {
|
||||
if let Some((sub, sup)) = fv.get_subsup() {
|
||||
fv.dummy_link();
|
||||
let res_sub = sub.has_undoable_linked_var();
|
||||
let res_sup = sup.has_undoable_linked_var();
|
||||
fv.undo();
|
||||
res_sub || res_sup
|
||||
} else {
|
||||
let opt_t = fv.get_type();
|
||||
opt_t.map_or(false, |t| t.has_undoable_linked_var())
|
||||
}
|
||||
}
|
||||
Self::Ref(ty) => ty.has_undoable_linked_var(),
|
||||
Self::RefMut { before, after } => {
|
||||
before.has_undoable_linked_var()
|
||||
|| after
|
||||
.as_ref()
|
||||
.map(|t| t.has_undoable_linked_var())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
Self::And(lhs, rhs) | Self::Or(lhs, rhs) => {
|
||||
lhs.has_undoable_linked_var() || rhs.has_undoable_linked_var()
|
||||
}
|
||||
Self::Not(ty) => ty.has_undoable_linked_var(),
|
||||
Self::Callable { param_ts, return_t } => {
|
||||
param_ts.iter().any(|t| t.has_undoable_linked_var())
|
||||
|| return_t.has_undoable_linked_var()
|
||||
}
|
||||
Self::Subr(subr) => subr.has_undoable_linked_var(),
|
||||
Self::Quantified(quant) => quant.has_undoable_linked_var(),
|
||||
Self::Record(r) => r.values().any(|t| t.has_undoable_linked_var()),
|
||||
Self::Refinement(refine) => {
|
||||
refine.t.has_undoable_linked_var() || refine.pred.has_undoable_linked_var()
|
||||
}
|
||||
Self::Poly { params, .. } => params.iter().any(|tp| tp.has_undoable_linked_var()),
|
||||
Self::Proj { lhs, .. } => lhs.has_undoable_linked_var(),
|
||||
Self::ProjCall { lhs, args, .. } => {
|
||||
lhs.has_undoable_linked_var() || args.iter().any(|tp| tp.has_undoable_linked_var())
|
||||
}
|
||||
Self::Structural(ty) => ty.has_undoable_linked_var(),
|
||||
Self::Guard(guard) => guard.to.has_undoable_linked_var(),
|
||||
Self::Bounded { sub, sup } => {
|
||||
sub.has_undoable_linked_var() || sup.has_undoable_linked_var()
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_no_qvar(&self) -> bool {
|
||||
!self.has_qvar()
|
||||
}
|
||||
|
|
|
@ -341,6 +341,21 @@ impl Predicate {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_undoable_linked_var(&self) -> bool {
|
||||
match self {
|
||||
Self::Value(_) => false,
|
||||
Self::Const(_) => false,
|
||||
Self::Equal { rhs, .. }
|
||||
| Self::GreaterEqual { rhs, .. }
|
||||
| Self::LessEqual { rhs, .. }
|
||||
| Self::NotEqual { rhs, .. } => rhs.has_undoable_linked_var(),
|
||||
Self::Or(lhs, rhs) | Self::And(lhs, rhs) => {
|
||||
lhs.has_undoable_linked_var() || rhs.has_undoable_linked_var()
|
||||
}
|
||||
Self::Not(pred) => pred.has_undoable_linked_var(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min_max<'a>(
|
||||
&'a self,
|
||||
min: Option<&'a TyParam>,
|
||||
|
|
|
@ -1062,6 +1062,29 @@ impl TyParam {
|
|||
!self.has_unbound_var()
|
||||
}
|
||||
|
||||
pub fn has_undoable_linked_var(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) => fv.is_undoable_linked(),
|
||||
Self::Type(t) => t.has_undoable_linked_var(),
|
||||
Self::Proj { obj, .. } => obj.has_undoable_linked_var(),
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_undoable_linked_var()),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.has_undoable_linked_var()),
|
||||
Self::Dict(kv) => kv
|
||||
.iter()
|
||||
.any(|(k, v)| k.has_undoable_linked_var() || v.has_undoable_linked_var()),
|
||||
Self::Record(rec) => rec.iter().any(|(_, v)| v.has_undoable_linked_var()),
|
||||
Self::Lambda(lambda) => lambda.body.iter().any(|t| t.has_undoable_linked_var()),
|
||||
Self::UnaryOp { val, .. } => val.has_undoable_linked_var(),
|
||||
Self::BinOp { lhs, rhs, .. } => {
|
||||
lhs.has_undoable_linked_var() || rhs.has_undoable_linked_var()
|
||||
}
|
||||
Self::App { args, .. } => args.iter().any(|p| p.has_undoable_linked_var()),
|
||||
Self::Erased(t) => t.has_undoable_linked_var(),
|
||||
Self::Value(ValueObj::Type(t)) => t.typ().has_undoable_linked_var(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn union_size(&self) -> usize {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().union_size(),
|
||||
|
|
|
@ -7,10 +7,10 @@ use std::hash::{Hash, Hasher};
|
|||
use std::ops::Neg;
|
||||
use std::sync::Arc;
|
||||
|
||||
use erg_common::config::Input;
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
||||
use erg_common::fresh::fresh_varname;
|
||||
use erg_common::io::Input;
|
||||
use erg_common::python_util::PythonVersion;
|
||||
use erg_common::serialize::*;
|
||||
use erg_common::set::Set;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
|||
|
||||
use erg_common::error::Location;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::Str;
|
||||
use erg_common::{switch_lang, Str};
|
||||
|
||||
use erg_parser::ast::DefId;
|
||||
|
||||
|
@ -39,6 +39,7 @@ use Mutability::*;
|
|||
pub enum VarKind {
|
||||
Defined(DefId),
|
||||
Declared,
|
||||
InstanceAttr,
|
||||
Parameter {
|
||||
def_id: DefId,
|
||||
var: bool,
|
||||
|
@ -88,6 +89,38 @@ impl VarKind {
|
|||
pub const fn is_builtin(&self) -> bool {
|
||||
matches!(self, Self::Builtin)
|
||||
}
|
||||
|
||||
pub const fn is_auto(&self) -> bool {
|
||||
matches!(self, Self::Auto)
|
||||
}
|
||||
|
||||
pub const fn is_instance_attr(&self) -> bool {
|
||||
matches!(self, Self::InstanceAttr)
|
||||
}
|
||||
|
||||
pub const fn display(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Auto | Self::FixedAuto => switch_lang!(
|
||||
"japanese" => "自動",
|
||||
"simplified_chinese" => "自动",
|
||||
"traditional_chinese" => "自動",
|
||||
"english" => "auto",
|
||||
),
|
||||
Self::Builtin => switch_lang!(
|
||||
"japanese" => "組み込み",
|
||||
"simplified_chinese" => "内置",
|
||||
"traditional_chinese" => "內置",
|
||||
"english" => "builtin",
|
||||
),
|
||||
Self::InstanceAttr => switch_lang!(
|
||||
"japanese" => "インスタンス",
|
||||
"simplified_chinese" => "实例",
|
||||
"traditional_chinese" => "實例",
|
||||
"english" => "instance",
|
||||
),
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -285,12 +318,11 @@ impl VarInfo {
|
|||
} else {
|
||||
Mutability::Immutable
|
||||
};
|
||||
let kind = VarKind::Declared;
|
||||
Self::new(
|
||||
t,
|
||||
muty,
|
||||
Visibility::new(field.vis, namespace),
|
||||
kind,
|
||||
VarKind::InstanceAttr,
|
||||
None,
|
||||
impl_of,
|
||||
None,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue